c argument names in bindings

This commit is contained in:
2026-06-25 08:28:30 +02:00
parent 9d1130b359
commit c08bc6d0cc
9 changed files with 84 additions and 19 deletions
+20 -5
View File
@@ -12,6 +12,7 @@ package translatec
// the output is an honest record of the whole header.
import "../cimport"
import "../lexer"
import "core:fmt"
import "core:mem"
import "core:strings"
@@ -102,7 +103,8 @@ render_type :: proc(b: ^strings.Builder, result: ^cimport.Result, id: cimport.Ty
fmt.sbprintf(b, "[%d]", item.count)
render_type(b, result, item.child, record_names)
case .Function:
render_c_func(b, result, item.params, item.child, item.variadic, record_names)
// Function-pointer types carry no parameter names, so every slot renders `_`.
render_c_func(b, result, item.params, nil, item.child, item.variadic, record_names)
case .Record:
if int(item.record) >= 0 && int(item.record) < len(record_names) {
strings.write_string(b, record_names[item.record])
@@ -112,12 +114,14 @@ render_type :: proc(b: ^strings.Builder, result: ^cimport.Result, id: cimport.Ty
}
}
// render_c_func writes `c_func(arg0 T0, ...) R`. Params are named arg0.. because
// the parser requires parameter names; names do not affect type identity.
// render_c_func writes `c_func(name T0, ...) R`, using the real C parameter name
// when `names` provides one and `_` (the sink) otherwise. Names do not affect type
// identity; the parser requires a name slot, so unnamed params use `_`.
render_c_func :: proc(
b: ^strings.Builder,
result: ^cimport.Result,
params: []cimport.Type_Id,
names: []string,
ret: cimport.Type_Id,
variadic: bool,
record_names: []string,
@@ -127,7 +131,8 @@ render_c_func :: proc(
if index > 0 {
strings.write_string(b, ", ")
}
fmt.sbprintf(b, "arg%d ", index)
name := names[index] if index < len(names) else ""
fmt.sbprintf(b, "%s ", safe_param_name(name))
render_type(b, result, param, record_names)
}
if variadic {
@@ -267,7 +272,7 @@ emit_functions :: proc(b: ^strings.Builder, result: ^cimport.Result, record_name
continue
}
fmt.sbprintf(b, "%s :: ", function.name)
render_c_func(b, result, function.params, function.result, function.variadic, record_names)
render_c_func(b, result, function.params, function.param_names, function.result, function.variadic, record_names)
strings.write_byte(b, '\n')
wrote = true
}
@@ -311,6 +316,16 @@ render_macro_value :: proc(b: ^strings.Builder, value: cimport.Macro_Value) {
}
}
// safe_param_name returns the C parameter name when it is a usable brolang
// identifier, else `_` (the sink): empty names (unnamed C params) and names that
// collide with a brolang keyword (e.g. legal C `int f(int and)`) both become `_`.
safe_param_name :: proc(name: string) -> string {
if len(name) > 0 && lexer.keyword_kind(name) == .Identifier {
return name
}
return "_"
}
macro_scalar_kind :: proc(result: ^cimport.Result, id: cimport.Type_Id) -> bool {
if int(id) < 0 || int(id) >= len(result.types) {
return false