From: yu.dongliang <18588496441@163.com> Date: Sat, 18 Jul 2026 15:21:54 +0000 (+0800) Subject: support C style function ptr as args of function. X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=290ca8a892690aa0388952e8269d438ece7b79a4;p=scf.git support C style function ptr as args of function. --- diff --git a/examples/c_func_ptr_arg.c b/examples/c_func_ptr_arg.c new file mode 100644 index 0000000..0b1ef6f --- /dev/null +++ b/examples/c_func_ptr_arg.c @@ -0,0 +1,25 @@ +int add(int a, int b) +{ + return a + b; +} + +int add_array(int* array, int n, int (*add_pt)(int a, int b)) +{ + return add_pt(array[0], array[1]); +} + +typedef int (*add_array_pt)(int* array, int n, int (*add_pt)(int a, int b)); + +int printf(const char* fmt, ...); + +int main() +{ + int a[2] = {1, 2}; + + add_array_pt f = add_array; + + int ret = f(a, 2, add); + + printf("ret: %d\n", ret); + return 0; +} diff --git a/parse/scf_dfa_function.c b/parse/scf_dfa_function.c index e6b472e..9c4f0de 100644 --- a/parse/scf_dfa_function.c +++ b/parse/scf_dfa_function.c @@ -7,10 +7,13 @@ extern scf_dfa_module_t dfa_module_function; typedef struct { scf_block_t* parent_block; + scf_function_t* f; scf_variable_t* v_pf; - int pf_lps; - int pf_rps; + int argc; + int nb_lps; + int nb_rps; + } dfa_fun_data_t; int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d) @@ -18,7 +21,8 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d) scf_parse_t* parse = dfa->priv; scf_ast_t* ast = parse->ast; dfa_identity_t* id = NULL; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; + dfa_fun_data_t* fd = scf_stack_top(s); scf_lex_word_t* name = NULL; dfa_identity_t* id0; @@ -130,7 +134,7 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d) id = NULL; } - scf_logi("function: %s(), line: %d, member_flag: %d\n", f->node.w->text->data, f->node.w->line, f->member_flag); + scf_logi("s->size: %d, function: %s(), line: %d, member_flag: %d\n", s->size, f->node.w->text->data, f->node.w->line, f->member_flag); int void_flag = 0; @@ -193,54 +197,63 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d) SCF_XCHG(f->rets->data[i], f->rets->data[j]); } - if (!f->member_flag || v_pf) { - - b = ast->current_block; - while (b) { - if (b->node.file_flag) - break; - b = (scf_block_t*)b->node.parent; - } + if (v_pf) { + v_pf->static_flag = f->static_flag; + v_pf->func_ptr = f; + } - scf_scope_push_function(b->scope, f); + scf_scope_push_function(ast->current_block->scope, f); - scf_node_add_child((scf_node_t*)b, (scf_node_t*)f); - - if (v_pf) { - v_pf->static_flag = f->static_flag; - v_pf->func_ptr = f; - } - } else { - scf_scope_push_function(ast->current_block->scope, f); - - scf_node_add_child((scf_node_t*)ast->current_block, (scf_node_t*)f); - } + scf_node_add_child((scf_node_t*)ast->current_block, (scf_node_t*)f); fd ->parent_block = ast->current_block; ast->current_block = (scf_block_t*)f; - d->current_function = f; + fd->f = f; return SCF_DFA_NEXT_WORD; } int _function_add_arg(scf_dfa_t* dfa, dfa_data_t* d) { - dfa_identity_t* t = NULL; - dfa_identity_t* v = NULL; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; + dfa_fun_data_t* fd = scf_stack_top(s); + dfa_identity_t* t = NULL; + dfa_identity_t* v = NULL; switch (d->current_identities->size) { case 0: break; + case 1: t = scf_stack_pop(d->current_identities); - assert(t && t->type); + assert(t); + + if (!t->type) { + scf_loge("NO type found for '%s', file: %s, line: %d\n", + t->identity->text->data, + t->identity->file->data, t->identity->line); + + free(t); + return SCF_DFA_ERROR; + } break; + case 2: v = scf_stack_pop(d->current_identities); t = scf_stack_pop(d->current_identities); - assert(t && t->type); + assert(t); assert(v && v->identity); + + if (!t->type) { + scf_loge("NO type found for '%s', file: %s, line: %d\n", + t->identity->text->data, + t->identity->file->data, t->identity->line); + + free(t); + free(v); + return SCF_DFA_ERROR; + } break; default: scf_loge("\n"); @@ -248,10 +261,10 @@ int _function_add_arg(scf_dfa_t* dfa, dfa_data_t* d) break; }; - if (t && t->type) { - scf_variable_t* arg = NULL; - scf_lex_word_t* w = NULL; + scf_variable_t* arg = NULL; + scf_lex_word_t* w = NULL; + if (t && t->type) { if (v && v->identity) w = v->identity; @@ -265,49 +278,62 @@ int _function_add_arg(scf_dfa_t* dfa, dfa_data_t* d) if (!arg) return SCF_DFA_ERROR; - scf_scope_push_var(d->current_function->scope, arg); - } else { + scf_scope_push_var(fd->f->scope, arg); + } else arg = d->current_var; - if (arg->nb_dimentions > 0) { - arg->nb_pointers += arg->nb_dimentions; - arg->nb_dimentions = 0; - } + if (v) { + free(v); + v = NULL; + } - if (arg->dimentions) { - free(arg->dimentions); - arg->dimentions = NULL; - } + free(t); + t = NULL; - arg->const_literal_flag = 0; + } else { + if (!d->current_var) + return SCF_DFA_NEXT_WORD; - d->current_var = NULL; - } + arg = d->current_var; + } - scf_logi("d->argc: %d, arg->nb_pointers: %d, arg->nb_dimentions: %d\n", - d->argc, arg->nb_pointers, arg->nb_dimentions); + d->current_var = NULL; - scf_vector_add(d->current_function->argv, arg); + if (arg->nb_dimentions > 0) { + arg->nb_pointers += arg->nb_dimentions; + arg->nb_dimentions = 0; + } - arg->refs++; - arg->arg_flag = 1; - arg->local_flag = 1; + if (arg->dimentions) { + free(arg->dimentions); + arg->dimentions = NULL; + } - if (v) - free(v); - free(t); + arg->const_literal_flag = 0; - d->argc++; - } + scf_logi("s->size: %d, fd->f: %s(), fd->argc: %d, arg->nb_pointers: %d, arg->nb_dimentions: %d\n", + s->size, fd->f->node.w->text->data, fd->argc, arg->nb_pointers, arg->nb_dimentions); + + assert(scf_vector_find(fd->f->scope->vars, arg)); + + scf_vector_add(fd->f->argv, arg); + + arg->refs++; + arg->arg_flag = 1; + arg->local_flag = 1; + + fd->argc++; return SCF_DFA_NEXT_WORD; } static int _function_action_vargs(scf_dfa_t* dfa, scf_vector_t* words, void* data) { - dfa_data_t* d = data; + dfa_data_t* d = data; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; + dfa_fun_data_t* fd = scf_stack_top(s); - d->current_function->vargs_flag = 1; + fd->f->vargs_flag = 1; return SCF_DFA_NEXT_WORD; } @@ -328,8 +354,7 @@ static int _function_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* dat static int _function_action_pf_star(scf_dfa_t* dfa, scf_vector_t* words, void* data) { - dfa_data_t* d = data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + dfa_data_t* d = data; d->pf_pointers++; @@ -338,10 +363,9 @@ static int _function_action_pf_star(scf_dfa_t* dfa, scf_vector_t* words, void* d static int _function_action_pf_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) { - dfa_data_t* d = data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + dfa_data_t* d = data; - fd->pf_lps++; + d->pf_lps++; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_pf_rp"), SCF_DFA_HOOK_PRE); @@ -350,15 +374,14 @@ static int _function_action_pf_lp(scf_dfa_t* dfa, scf_vector_t* words, void* dat static int _function_action_pf_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) { - dfa_data_t* d = data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; - dfa_identity_t* id = scf_stack_top(d->current_identities); + dfa_data_t* d = data; + dfa_identity_t* id = scf_stack_top(d->current_identities); - fd->pf_rps++; + d->pf_rps++; - if (fd->pf_rps == fd->pf_lps) { - fd->pf_rps = 0; - fd->pf_lps = 0; + if (d->pf_rps == d->pf_lps) { + d->pf_rps = 0; + d->pf_lps = 0; if (id && id->identity) scf_logw("pf: %s(), nb_pointers: %d\n", id->identity->text->data, d->pf_pointers); @@ -373,23 +396,31 @@ static int _function_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; dfa_data_t* d = data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; + dfa_fun_data_t* fd = calloc(1, sizeof(dfa_fun_data_t)); + + if (!fd) + return -ENOMEM; + + int ret = scf_stack_push(s, fd); + if (ret < 0) + return ret; assert(!d->current_node); if (d->pf_pointers <= 0) d->current_var = NULL; - if (_function_add_function(dfa, d) < 0) - return SCF_DFA_ERROR; + ret = _function_add_function(dfa, d); + if (ret < 0) + return ret; d->current_var = NULL; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_rp"), SCF_DFA_HOOK_PRE); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_comma"), SCF_DFA_HOOK_PRE); - d->argc = 0; - d->nb_lps++; + fd->nb_lps++; return SCF_DFA_NEXT_WORD; } @@ -397,44 +428,52 @@ static int _function_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) static int _function_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; + scf_lex_word_t* w = words->data[words->size - 1]; dfa_data_t* d = data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; - scf_function_t* f = d->current_function; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; + + dfa_fun_data_t* fd = scf_stack_top(s); + scf_function_t* f = fd->f; scf_function_t* fprev = NULL; + scf_block_t* b = fd->parent_block; - d->nb_rps++; + if (fd->nb_rps < fd->nb_lps) { + fd->nb_rps++; - if (d->nb_rps < d->nb_lps) { - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_rp"), SCF_DFA_HOOK_PRE); - return SCF_DFA_NEXT_WORD; - } + if (fd->nb_rps < fd->nb_lps) { + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_rp"), SCF_DFA_HOOK_PRE); + return SCF_DFA_NEXT_WORD; + } - if (_function_add_arg(dfa, d) < 0) { - scf_loge("function add arg failed\n"); + } else { + scf_loge("too many ')' for function: %s(), file: %s, line: %d\n", f->node.w->text->data, w->file->data, w->line); return SCF_DFA_ERROR; } - scf_list_del(&f->list); - scf_node_del_child((scf_node_t*)fd->parent_block, (scf_node_t*)f); + scf_logi("f: %s(), fd->nb_lps: %d, fd->nb_rps: %d\n", f->node.w->text->data, fd->nb_lps, fd->nb_rps); - if (fd->parent_block->node.type >= SCF_STRUCT) { + if (_function_add_arg(dfa, d) < 0) + return SCF_DFA_ERROR; - scf_type_t* t = (scf_type_t*)fd->parent_block; + scf_list_del(&f->list); + scf_node_del_child((scf_node_t*)b, (scf_node_t*)f); - if (!t->node.class_flag) { + if (b->node.type >= SCF_STRUCT) { + + if (!b->node.class_flag) { scf_loge("only class has member function\n"); return SCF_DFA_ERROR; } - assert(t->scope); + assert(b->scope); if (!strcmp(f->node.w->text->data, "__init")) { - fprev = scf_scope_find_same_function(t->scope, f); + fprev = scf_scope_find_same_function(b->scope, f); } else if (!strcmp(f->node.w->text->data, "__release")) { - fprev = scf_scope_find_function(t->scope, f->node.w->text->data); + fprev = scf_scope_find_function(b->scope, f->node.w->text->data); if (fprev && !scf_function_same(fprev, f)) { scf_loge("function '%s' can't be overloaded, repeated declare first in line: %d, second in line: %d\n", @@ -446,14 +485,14 @@ static int _function_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } } else { - scf_block_t* b = fd->parent_block; + while (b) { + if (b->node.root_flag || b->node.file_flag) + break; - if (!b->node.root_flag && !b->node.file_flag) { - scf_loge("function should be defined in file, global, or class\n"); - return SCF_DFA_ERROR; + b = (scf_block_t*)b->node.parent; } - assert(b->scope); + assert(b && b->scope); if (f->static_flag) fprev = scf_scope_find_function(b->scope, f->node.w->text->data); @@ -485,8 +524,14 @@ static int _function_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) SCF_XCHG(v0->w, v1->w); } + if (fd->v_pf) { + assert(fd->v_pf->func_ptr == fd->f); + + fd->v_pf->func_ptr = fprev; + } + scf_function_free(f); - d->current_function = fprev; + fd->f = fprev; } else { scf_lex_word_t* w = dfa->ops->pop_word(dfa); @@ -503,14 +548,28 @@ static int _function_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) dfa->ops->push_word(dfa, w); } } else { - scf_scope_push_function(fd->parent_block->scope, f); + scf_scope_push_function(b->scope, f); - scf_node_add_child((scf_node_t*)fd->parent_block, (scf_node_t*)f); + scf_node_add_child((scf_node_t*)b, (scf_node_t*)f); } - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_end"), SCF_DFA_HOOK_END); + if (s->size <= 1) + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_end"), SCF_DFA_HOOK_END); + else { + assert(!d->current_var); - parse->ast->current_block = (scf_block_t*)d->current_function; + d->current_var = fd->v_pf; + fd->v_pf = NULL; + + scf_logd("fd->f: %s(), d->current_var: %p\n", fd->f->node.w->text->data, d->current_var); + + scf_stack_pop(s); + free(fd); + + fd = scf_stack_top(s); + } + + parse->ast->current_block = (scf_block_t*)fd->f; return SCF_DFA_NEXT_WORD; } @@ -520,20 +579,22 @@ static int _function_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_parse_t* parse = dfa->priv; dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; + dfa_fun_data_t* fd = scf_stack_pop(s); parse->ast->current_block = (scf_block_t*)(fd->parent_block); - if (d->current_function->node.nb_nodes > 0) - d->current_function->node.define_flag = 1; + if (fd->f->node.nb_nodes > 0) + fd->f->node.define_flag = 1; fd->parent_block = NULL; - d->current_function = NULL; - d->argc = 0; - d->nb_lps = 0; - d->nb_rps = 0; + fd->nb_lps = 0; + fd->nb_rps = 0; + scf_logi("s->size: %d\n", s->size); + + free(fd); return SCF_DFA_OK; } @@ -550,32 +611,29 @@ static int _dfa_init_module_function(scf_dfa_t* dfa) SCF_DFA_MODULE_NODE(dfa, function, pf_lp, scf_dfa_is_lp, _function_action_pf_lp); SCF_DFA_MODULE_NODE(dfa, function, pf_rp, scf_dfa_is_rp, _function_action_pf_rp); - scf_parse_t* parse = dfa->priv; - dfa_data_t* d = parse->dfa_data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + scf_parse_t* parse = dfa->priv; + dfa_data_t* d = parse->dfa_data; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; - assert(!fd); + assert(!s); - fd = calloc(1, sizeof(dfa_fun_data_t)); - if (!fd) { - scf_loge("\n"); + s = scf_stack_alloc(); + if (!s) return SCF_DFA_ERROR; - } - d->module_datas[dfa_module_function.index] = fd; + d->module_datas[dfa_module_function.index] = s; return SCF_DFA_OK; } static int _dfa_fini_module_function(scf_dfa_t* dfa) { - scf_parse_t* parse = dfa->priv; - dfa_data_t* d = parse->dfa_data; - dfa_fun_data_t* fd = d->module_datas[dfa_module_function.index]; + scf_parse_t* parse = dfa->priv; + dfa_data_t* d = parse->dfa_data; + scf_stack_t* s = d->module_datas[dfa_module_function.index]; - if (fd) { - free(fd); - fd = NULL; + if (s) { + scf_stack_free(s); d->module_datas[dfa_module_function.index] = NULL; } diff --git a/parse/scf_dfa_operator.c b/parse/scf_dfa_operator.c index 2d1abae..c460f51 100644 --- a/parse/scf_dfa_operator.c +++ b/parse/scf_dfa_operator.c @@ -130,8 +130,6 @@ int _operator_add_arg(scf_dfa_t* dfa, dfa_data_t* d) free(id0); free(id1); - - d->argc++; } return SCF_DFA_NEXT_WORD; @@ -175,10 +173,9 @@ static int _operator_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "operator_rp"), SCF_DFA_HOOK_PRE); + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "operator_rp"), SCF_DFA_HOOK_PRE); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "operator_comma"), SCF_DFA_HOOK_PRE); - d->argc = 0; d->nb_lps++; return SCF_DFA_NEXT_WORD; @@ -290,7 +287,6 @@ static int _operator_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) opd->parent_block = NULL; d->current_function = NULL; - d->argc = 0; d->nb_lps = 0; d->nb_rps = 0; diff --git a/parse/scf_parse.h b/parse/scf_parse.h index 719e89c..d56ba39 100644 --- a/parse/scf_parse.h +++ b/parse/scf_parse.h @@ -79,7 +79,10 @@ struct dfa_data_s { scf_function_t* current_function; int argc; + int pf_pointers; + int pf_lps; + int pf_rps; scf_lex_word_t* current_async_w;