support C style function ptr as args of function.
authoryu.dongliang <18588496441@163.com>
Sat, 18 Jul 2026 15:21:54 +0000 (23:21 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 18 Jul 2026 15:21:54 +0000 (23:21 +0800)
examples/c_func_ptr_arg.c [new file with mode: 0644]
parse/scf_dfa_function.c
parse/scf_dfa_operator.c
parse/scf_parse.h

diff --git a/examples/c_func_ptr_arg.c b/examples/c_func_ptr_arg.c
new file mode 100644 (file)
index 0000000..0b1ef6f
--- /dev/null
@@ -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;
+}
index e6b472e34db81d508a20cfd5095c8d628ff388ab..9c4f0dee5b4f3b6a2ae6f5091bb22ff8bda228fe 100644 (file)
@@ -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;
        }
 
index 2d1abae85ccff7dddc591c4dd3cb554ea1c6ef4b..c460f51c3b7b4ff8ec64fe69b35a63d86e50563c 100644 (file)
@@ -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;
 
index 719e89c10e20c93e8fdbba12e464fbfb0d389d63..d56ba39225a2466a6cb940587db8a1eec51a3fce 100644 (file)
@@ -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;