Skip to content

Commit 7be1a1a

Browse files
committed
fix(codegen): index-read, index-call, and assign on [func] arrays (#1439)
Follow-up to 9fee3f9. The creation-time element type was widened to void *, but three downstream codegen paths still assumed int64_t: - NODE_INDEX_EXPR on a TK_ARRAY with func elements fell through to int64_t, so EZ_ARRAY_GET read the fn pointer as an integer. - emit_call_expression had no branch for an indexed callee — it emitted a raw C subscript on an EzArray struct. - Array index assignment (arr[i] = ()f) also fell through to int64_t, producing an int-from-pointer conversion. Detect func elements at each site and emit void *. For the indexed-call case, wrap the callee in a function-pointer cast derived from the call site's arg/return types, mirroring how variable fn-pointer calls are already handled.
1 parent 9fee3f9 commit 7be1a1a

1 file changed

Lines changed: 34 additions & 5 deletions

File tree

ezc/src/codegen/codegen.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,7 +1333,9 @@ static void emit_expression(CodeGen *cg, AstNode *node) {
13331333
if (left_t && left_t->kind == TK_ARRAY) {
13341334
/* Determine element C type */
13351335
const char *c_elem = "int64_t";
1336-
if (left_t->element_type) {
1336+
if (left_t->element_type && strcmp(left_t->element_type, "func") == 0) {
1337+
c_elem = "void *";
1338+
} else if (left_t->element_type) {
13371339
EzType *et = type_from_name(left_t->element_type);
13381340
if (et->kind == TK_FLOAT) c_elem = "double";
13391341
else if (et->kind == TK_BOOL) c_elem = "bool";
@@ -3830,6 +3832,29 @@ static void emit_call_expression(CodeGen *cg, AstNode *node) {
38303832
} else {
38313833
emit_expression(cg, node->data.call.function);
38323834
}
3835+
} else if (node->data.call.function->kind == NODE_INDEX_EXPR) {
3836+
/* Indexed callee (e.g. ops[0](x, y)). The index expression yields a
3837+
* void * for [func] arrays (see NODE_INDEX_EXPR emitter), which isn't
3838+
* directly callable — wrap with a function-pointer cast derived from
3839+
* the call site's arg types and return type. */
3840+
int nargs = node->data.call.arg_count;
3841+
EzType *ret_t = cg->type_table ? typetable_get(cg->type_table, node) : NULL;
3842+
const char *c_ret = (ret_t && ret_t->kind != TK_UNKNOWN) ? ez_type_to_c_cg(cg, type_name(ret_t)) : "int64_t";
3843+
if (ret_t && ret_t->kind == TK_VOID) c_ret = "void";
3844+
emitf(cg, "((%s (*)(", c_ret);
3845+
for (int i = 0; i < nargs; i++) {
3846+
if (i > 0) emit(cg, ", ");
3847+
EzType *arg_t = cg->type_table ? typetable_get(cg->type_table, node->data.call.args[i]) : NULL;
3848+
if (arg_t && arg_t->kind != TK_UNKNOWN) {
3849+
emit(cg, ez_type_to_c_cg(cg, type_name(arg_t)));
3850+
} else {
3851+
emit(cg, "int64_t");
3852+
}
3853+
}
3854+
if (nargs == 0) emit(cg, "void");
3855+
emit(cg, "))");
3856+
emit_expression(cg, node->data.call.function);
3857+
emit(cg, ")");
38333858
} else {
38343859
emit_expression(cg, node->data.call.function);
38353860
}
@@ -4251,10 +4276,14 @@ static void emit_assign_statement(CodeGen *cg, AstNode *node) {
42514276
if (left_t && left_t->kind == TK_ARRAY) {
42524277
const char *c_elem = "int64_t";
42534278
if (left_t->element_type) {
4254-
EzType *et = type_from_name(left_t->element_type);
4255-
if (et->kind == TK_FLOAT) c_elem = "double";
4256-
else if (et->kind == TK_BOOL) c_elem = "bool";
4257-
else if (et->kind == TK_STRING) c_elem = "EzString";
4279+
if (strcmp(left_t->element_type, "func") == 0) {
4280+
c_elem = "void *";
4281+
} else {
4282+
EzType *et = type_from_name(left_t->element_type);
4283+
if (et->kind == TK_FLOAT) c_elem = "double";
4284+
else if (et->kind == TK_BOOL) c_elem = "bool";
4285+
else if (et->kind == TK_STRING) c_elem = "EzString";
4286+
}
42584287
}
42594288
emitf(cg, "EZ_ARRAY_SET(");
42604289
emit_expression(cg, left);

0 commit comments

Comments
 (0)