js: support const function array with const index master
authoryu.dongliang <18588496441@163.com>
Sat, 27 Jun 2026 02:42:01 +0000 (10:42 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 27 Jun 2026 02:42:01 +0000 (10:42 +0800)
examples/js_array_func.html [new file with mode: 0644]
js/abc_libjs.so
js/core/scf_variable.c
js/core/scf_variable.h
js/doc.c
js/parse/scf_dfa_call.c
js/parse/scf_dfa_expr.c
js/parse/scf_dfa_init_data.c
js/parse/scf_operator_handler_expr.c
js/parse/scf_operator_handler_semantic.c
js/parse/scf_operator_handler_semantic.h

diff --git a/examples/js_array_func.html b/examples/js_array_func.html
new file mode 100644 (file)
index 0000000..a255ccf
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<h1>含有javascript的页面</h1>
+
+<p>含有js的页面</p>
+
+<script>
+var obj = [
+       function (a, b) {return a + b; },
+];
+
+var c = obj[0](1, 2);
+
+document.write(c);
+
+</script>
+
+</body>
+</html>
index 41cb04229299873b80d908997fabfdbde5a3b993..b48ed9ea0730dbe663f35e6eb65884fe72a2e158 100755 (executable)
Binary files a/js/abc_libjs.so and b/js/abc_libjs.so differ
index cc8935f3b7619adbd35c90919547c83559a6e8a2..39ba592c1ebcddce600d98ae34ca09e5e9a30fa7 100644 (file)
@@ -379,10 +379,13 @@ int scf_variable_same_type(scf_variable_t* v0, scf_variable_t* v1)
                }
 
                if (SCF_FUNCTION_PTR == v0->type) {
-                       assert(v0->func_ptr);
-                       assert(v1->func_ptr);
+                       if (!v0->func_ptr)
+                               assert(v0->arg_flag);
 
-                       if (!scf_function_same_type(v0->func_ptr, v1->func_ptr))
+                       else if (!v1->func_ptr)
+                               assert(v1->arg_flag);
+
+                       else if (!scf_function_same_type(v0->func_ptr, v1->func_ptr))
                                return 0;
                }
        } else {
index b6a57eb3331291ccde6fe9d6685e789ab0e38187..1197f94918f21c12d55ee36072e302ca5197d97f 100644 (file)
@@ -7,6 +7,8 @@
 typedef struct {
        scf_expr_t*         vla; // variable length array
        int                 num; // const    length array
+
+       scf_vector_t*       vars;
 } scf_dimention_t;
 
 struct scf_variable_s {
@@ -67,6 +69,9 @@ struct scf_variable_s {
 
        scf_string_t*       signature;
 
+       scf_dimention_t*    js_dimentions; // this var point to a js array
+       int                                     js_nb_dimentions;
+
        uint32_t            const_literal_flag:1;
        uint32_t            const_flag  :1;
        uint32_t            static_flag :1;
index f8ea1455ea79b6edac9cc24e3071cfe2bfaaa8d1..2f46d82952b142ef800981b965b8afc19c730358 100644 (file)
--- a/js/doc.c
+++ b/js/doc.c
@@ -132,6 +132,12 @@ struct Object
                return 0;
        }
 
+       int __init(Object* this, const char* name, int length, const funcptr* f)
+       {
+               printf("this: %p, f: %p\n", this, f);
+               return 0;
+       }
+
        int __init(Object* this, const char* name, int length, const char* s)
        {
                printf("this: %p, name: %s\n", this, name);
index 47b0754358d072ab2278f7384e907f457c29d33c..4779ac06255980b5a780e2a2b127bb32bf7e5d7f 100644 (file)
@@ -125,10 +125,6 @@ static int _call_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                scf_stack_pop(d->current_identities);
                free(id);
                id = NULL;
-       } else {
-               // f()(), function f should return a function pointer
-               scf_logw("\n");
-//             return SCF_DFA_ERROR;
        }
 
        node_call = scf_node_alloc(w1, SCF_OP_CALL, NULL);
@@ -383,6 +379,74 @@ int _call_add_obj(scf_ast_t* ast, scf_lex_word_t* w, scf_node_t* call, scf_expr_
        return 0;
 }
 
+static int _call_get_func(scf_function_t** pf, scf_node_t* array, scf_vector_t* indexes)
+{
+       scf_variable_t*  base = _scf_operand_get(array);
+       scf_variable_t*  v;
+       int i;
+       int j;
+
+       if (indexes) {
+               for (i = indexes->size - 1; i >= 0; i--) {
+                       v  = indexes->data[i];
+                       j  = v->data.i64;
+
+                       if (!base->js_dimentions
+                                       || base->js_nb_dimentions <= 0
+                                       || base->js_dimentions[0].num <= j)
+                               return -EINVAL;
+
+                       if (!base->js_dimentions[0].vars || j >= base->js_dimentions[0].vars->size)
+                               return -EINVAL;
+
+                       base = base->js_dimentions[0].vars->data[j];
+                       if (!base)
+                               return -EINVAL;
+               }
+       }
+
+       if (SCF_FUNCTION_PTR == base->type) {
+
+               if (!base->const_literal_flag || !base->func_ptr) {
+                       scf_loge("function obj '%s' is not const\n", base->w->text->data);
+                       return -EINVAL;
+               }
+
+               *pf = base->func_ptr;
+       }
+
+       return 0;
+}
+
+static int _call_use_func(scf_ast_t* ast, scf_node_t* call, scf_function_t* f)
+{
+       scf_variable_t*  v;
+       scf_node_t*      pf;
+       scf_expr_t*      e;
+       scf_type_t*      t = NULL;
+
+       int ret = scf_ast_find_type_type(&t, ast, SCF_FUNCTION_PTR);
+       if (ret < 0)
+               return ret;
+
+       v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f);
+       if (!v)
+               return -ENOMEM;
+       v->const_literal_flag = 1;
+
+       pf = scf_node_alloc(NULL, v->type, v);
+       scf_variable_free(v);
+       v = NULL;
+       if (!pf)
+               return -ENOMEM;
+
+       scf_node_free(call->nodes[0]);
+       call->nodes[0] = pf;
+
+       pf->parent = call;
+       return 0;
+}
+
 static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 {
        if (words->size < 2) {
@@ -425,37 +489,84 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
                scf_expr_add_node(cd->parent_expr, cd->call);
        } else {
-               scf_node_add_child(cd->call, cd->func);
+               if (cd->func)
+                       scf_node_add_child(cd->call, cd->func);
        }
 
-       scf_variable_t*  r;
-       scf_function_t*  f      = NULL;
-       scf_type_t*      Object = NULL;
-       scf_node_t*      pf     = cd->call->nodes[0];
+       scf_variable_t*  base;
+       scf_variable_t*  index;
+       scf_function_t*  f;
+       scf_vector_t*    indexes = NULL;
+       scf_type_t*      Object  = NULL;
+       scf_node_t*      pf      = cd->call->nodes[0];
        scf_expr_t*      e;
+       scf_type_t*      t;
 
-       while (SCF_OP_EXPR == pf->type)
-               pf = pf->nodes[0];
+       int ret;
 
-       if (SCF_OP_POINTER == pf->type)
-               pf = pf->nodes[1];
+       while (1) {
+               if (SCF_OP_EXPR == pf->type)
+                       pf = pf->nodes[0];
 
-       int ret = scf_ast_find_type(&Object, ast, "Object");
+               else if (SCF_OP_POINTER == pf->type) {
+                       pf = pf->nodes[1];
+                       break;
+
+               } else if (SCF_OP_ARRAY_INDEX == pf->type) {
+                       index = NULL;
+
+                       ret = scf_expr_calculate(ast, pf->nodes[1], &index);
+                       if (ret < 0)
+                               goto error;
+
+                       if (!scf_variable_const_integer(index)) {
+                               scf_loge("\n");
+
+                               scf_variable_free(index);
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       if (!indexes) {
+                               indexes = scf_vector_alloc();
+
+                               if (!indexes) {
+                                       scf_variable_free(index);
+                                       ret = -ENOMEM;
+                                       goto error;
+                               }
+                       }
+
+                       ret = scf_vector_add(indexes, index);
+                       if (ret < 0) {
+                               scf_variable_free(index);
+                               goto error;
+                       }
+
+                       pf = pf->nodes[0];
+               } else
+                       break;
+       }
+
+       f   = NULL;
+       ret = _call_get_func(&f, pf, indexes);
        if (ret < 0)
-               return ret;
+               goto error;
+
+       ret = scf_ast_find_type(&Object, ast, "Object");
+       if (ret < 0)
+               goto error;
 
        int js_flag    = 1;
        int timer_flag = 0;
 
-       if (SCF_FUNCTION_PTR == pf->type) {
-               f = pf->var->func_ptr;
-
+       if (f) {
                js_flag = f->js_flag;
 
                if (!strcmp(f->node.w->text->data, "setTimeout"))
                        timer_flag = 1;
 
-               scf_logd("f: %s, f->js_flag: %d, timer_flag: %d\n", f->node.w->text->data, f->js_flag, timer_flag);
+               scf_logi("f: %s, f->js_flag: %d, timer_flag: %d\n", f->node.w->text->data, f->js_flag, timer_flag);
        } else
                assert(Object->node.type == pf->type);
 
@@ -468,7 +579,7 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                        {
                                ret = _call_add_obj(ast, w, cd->call, e, Object);
                                if (ret < 0)
-                                       return ret;
+                                       goto error;
                        }
 
                        scf_node_add_child(cd->call, e);
@@ -484,7 +595,7 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                {
                        ret = _call_add_obj(ast, w, cd->call, d->expr, Object);
                        if (ret < 0)
-                               return ret;
+                               goto error;
                }
 
                scf_node_add_child(cd->call, d->expr);
@@ -493,8 +604,10 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
        if (js_flag || timer_flag) {
                e = scf_expr_alloc();
-               if (!e)
-                       return -ENOMEM;
+               if (!e) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
 
                if (js_flag)
                        ret = _call_add_arguments(ast, w, cd->call->nb_nodes - 1, e, Object);
@@ -502,13 +615,13 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                        ret = scf_ast_add_const_var(ast, e, SCF_VAR_INT, cd->call->nb_nodes - 3);
                if (ret < 0) {
                        scf_expr_free(e);
-                       return ret;
+                       goto error;
                }
 
                ret = scf_node_add_child(cd->call, e);
                if (ret < 0) {
                        scf_expr_free(e);
-                       return ret;
+                       goto error;
                }
 
                int i;
@@ -519,6 +632,12 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                e = NULL;
        }
 
+       if (indexes) {
+               ret = _call_use_func(ast, cd->call, f);
+               if (ret < 0)
+                       goto error;
+       }
+
        if (cd->parent_expr)
                d->expr = cd->parent_expr;
        else
@@ -526,10 +645,16 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
        assert(--d->expr_local_flag >= 0);
 
-       free(cd);
-       cd = NULL;
+       ret = SCF_DFA_NEXT_WORD;
 
-       return SCF_DFA_NEXT_WORD;
+error:
+       if (indexes) {
+               scf_vector_clear(indexes, ( void (*)(void*) ) scf_variable_free);
+               scf_vector_free (indexes);
+       }
+
+       free(cd);
+       return ret;
 }
 
 static int _call_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* data)
index 5b4d20634c462ea3775e93bcbe483e799b14bb39..083c16052fea5d79d2c282f7d89b652dbcac7721 100644 (file)
@@ -182,7 +182,8 @@ int _expr_add_var(scf_parse_t* parse, dfa_data_t* d)
                        d->current_function->vargs_flag = 1;
        }
 
-       scf_logi("var: %s, member_flag: %d, js_type: %d, line: %d, pos: %d\n", var->w->text->data, var->member_flag, var->js_type, var->w->line, var->w->pos);
+       scf_logi("var: %s: %p, var->dimentions: %p, nb_dimentions: %d, member_flag: %d, js_type: %d, line: %d, pos: %d\n",
+                       var->w->text->data, var, var->dimentions, var->nb_dimentions, var->member_flag, var->js_type, var->w->line, var->w->pos);
 
        if (md->current_var
                        && md->current_var->js_type >= 0
@@ -736,6 +737,8 @@ static int _expr_action_ls(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                if (scf_ast_find_type(&t, parse->ast, "Object") < 0)
                        return SCF_DFA_ERROR;
 
+               scf_logi("-------- md->current_var: %s\n", md->current_var->w->text->data);
+
                v = scf_scope_find_variable(t->scope, "members");
                if (!v) {
                        scf_logw("var 'members' not found in struct '%s'\n", t->name->data);
@@ -1191,8 +1194,9 @@ static int _dfa_init_syntax_expr(scf_dfa_t* dfa)
        scf_dfa_node_add_child(expr,       rs);
        scf_dfa_node_add_child(ls,         rs);
        scf_dfa_node_add_child(rs,         ls);
-       scf_dfa_node_add_child(rs,         binary_op);
+       scf_dfa_node_add_child(rs,         call_lp);
 
+       scf_dfa_node_add_child(rs,         binary_op);
        scf_dfa_node_add_child(rs,         unary_post);
        scf_dfa_node_add_child(rs,         rp);
        scf_dfa_node_add_child(identity,   unary_post);
index 8d61fbe2f6617dda48310d56fe04316847574ac6..50219491196be3fab0935db6e9a36500659144a6 100644 (file)
@@ -39,8 +39,12 @@ static int _do_data_init(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* obj)
        init_module_data_t* md = d->module_datas[dfa_module_init_data.index];
        dfa_init_expr_t*    ie;
        int i;
+       int ret = 0;
 
-       int ret = scf_object_init(ast, md->assign, d->current_var, obj, md->init_exprs);
+       if (SCF_FUNCTION_PTR != obj->type) {
+
+               ret = scf_object_init(ast, md->assign, d->current_var, obj, md->init_exprs);
+       }
 
        for (i = 0; i < md->init_exprs->size; i++) {
                ie =        md->init_exprs->data[i];
@@ -50,6 +54,12 @@ static int _do_data_init(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* obj)
                ie = NULL;
        }
 
+       d->current_var->js_dimentions    = obj->dimentions;
+       d->current_var->js_nb_dimentions = obj->nb_dimentions;
+
+       obj->dimentions    = NULL;
+       obj->nb_dimentions = 0;
+
        md->assign = NULL;
 
        scf_vector_free(md->init_exprs);
@@ -125,7 +135,10 @@ static int _add_struct_member(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* r)
                scf_variable_free(r);
                return -ENOMEM;
        }
-       v->member_flag = 1;
+
+       v->member_flag        = 1;
+       v->const_flag         = r->const_flag;
+       v->const_literal_flag = r->const_literal_flag;
 
        if (r->nb_dimentions > 0) {
                v->nb_dimentions = r->nb_dimentions;
@@ -159,6 +172,7 @@ static int _add_array_member(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* r)
        init_module_data_t*  md = d->module_datas[dfa_module_init_data.index];
        scf_lex_word_t*      w;
        scf_variable_t*      obj = scf_stack_top(md->init_objs);
+       scf_variable_t*      v;
 
        if (!r) {
                int ret = scf_expr_calculate(ast, d->expr, &r);
@@ -180,6 +194,12 @@ static int _add_array_member(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* r)
                        return -ENOMEM;
                }
 
+               obj->dimentions[0].vars = scf_vector_alloc();
+               if (!obj->dimentions[0].vars) {
+                       scf_variable_free(r);
+                       return -ENOMEM;
+               }
+
                obj->dimentions[0].num = 1;
        } else
                obj->dimentions[0].num++;
@@ -191,11 +211,30 @@ static int _add_array_member(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* r)
                if (obj->dimentions[i + 1].num < r->dimentions[i].num)
                        obj->dimentions[i + 1].num = r->dimentions[i].num;
 
-               scf_logi("obj: %p, obj->dimentions[%d].num: %d\n", obj, i + 1, obj->dimentions[i + 1].num);
+               scf_logi("obj: %p, obj->dimentions[%d].num: %d, r->dimentions[%d].num: %d\n",
+                               obj, i + 1, obj->dimentions[i + 1].num,
+                               i, r->dimentions[i].num);
        }
 
+       v = scf_variable_clone(r);
+
        scf_variable_free(r);
        r = NULL;
+       if (!v)
+               return -ENOMEM;
+
+       int ret = scf_vector_add(obj->dimentions[0].vars, v);
+       if (ret < 0) {
+               scf_variable_free(v);
+               return ret;
+       }
+
+       if (v && SCF_FUNCTION_PTR == v->type && v->func_ptr) {
+               scf_function_t* f = v->func_ptr;
+
+               scf_loge("%s()\n", f->node.w->text->data);
+       }
+
 #if 0
        if (d->current_var->nb_dimentions < md->current_n) {
 
@@ -626,9 +665,11 @@ static int _data_action_rs(scf_dfa_t* dfa, scf_vector_t* words, void* data)
        if (md->init_objs->size <= 0) {
                d->expr_local_flag = 0;
 
-               scf_logi("----------- type: %d, nb_pointers: %d\n\n", d->current_var->type, d->current_var->nb_pointers);
+               if (obj->type >= SCF_STRUCT)
+                       d->current_var->js_type = obj->type;
 
-               d->current_var->js_type = obj->type;
+               scf_logi("----------- type: %d, js_type: %d, SCF_FUNCTION_PTR: %d, nb_pointers: %d\n\n",
+                               d->current_var->type, d->current_var->js_type, SCF_FUNCTION_PTR, d->current_var->nb_pointers);
 
                ret = _do_data_init(parse->ast, d, obj);
                if (ret < 0)
index d5f643709623facdd2177551aa842ef547d538d5..db0ef5afc9013e5f2a5b258f9503c8b6cf0be6f5 100644 (file)
@@ -706,24 +706,33 @@ scf_operator_handler_pt  scf_find_expr_operator_handler(const int type)
 
 int scf_expr_calculate(scf_ast_t* ast, scf_expr_t* e, scf_variable_t** pret)
 {
-       if (!e || !e->nodes || e->nb_nodes <= 0)
-               return -1;
+       if (!e)
+               return -EINVAL;
 
-       if (scf_expr_semantic_analysis(ast, e) < 0)
-               return -1;
+       scf_handler_data_t  d = {0};
+       scf_variable_t*     v;
+
+       int ret = scf_expr_semantic_analysis(ast, e);
+       if (ret < 0)
+               return ret;
 
-       scf_handler_data_t d = {0};
-       scf_variable_t*    v;
+       scf_node_t*  node = e;
 
-       if (!scf_type_is_var(e->nodes[0]->type)) {
+       if (SCF_OP_EXPR == e->type) {
 
-               if (_scf_expr_calculate_internal(ast, e->nodes[0], &d) < 0) {
+               if (!e->nodes || e->nb_nodes != 1) {
                        scf_loge("\n");
-                       return -1;
+                       return -EINVAL;
                }
+
+               node = e->nodes[0];
        }
 
-       v = _scf_operand_get(e->nodes[0]);
+       ret = _scf_expr_calculate_internal(ast, node, &d);
+       if (ret < 0)
+               return ret;
+
+       v = _scf_operand_get(node);
 
        if (pret)
                *pret = scf_variable_ref(v);
index 5742ecef4a13647bbabd5349b864e5b736a838d5..a9d32a2cd13fbf23ecd5db889e5bb324bf9f126d 100644 (file)
@@ -2873,7 +2873,7 @@ static int _semantic_multi_rets_assign(scf_ast_t* ast, scf_node_t** nodes, int n
                scf_variable_t* v1 = _scf_operand_get(call->result_nodes->data[i]);
 
                if (!scf_variable_same_type(v0, v1)) {
-                       scf_loge("\n");
+                       scf_loge("i: %d\n", i);
                        return -1;
                }
 
@@ -3565,17 +3565,22 @@ int scf_expr_semantic_analysis(scf_ast_t* ast, scf_expr_t* e)
 {
        scf_handler_data_t d = {0};
 
-       if (!e->nodes || e->nb_nodes != 1) {
-               scf_loge("\n");
-               return -1;
-       }
+       scf_node_t* node = e;
 
-       int ret = _scf_expr_calculate_internal(ast, e->nodes[0], &d);
-       if (ret < 0) {
-               scf_loge("\n");
-               return -1;
+       if (SCF_OP_EXPR == e->type) {
+
+               if (!e->nodes || e->nb_nodes != 1) {
+                       scf_loge("\n");
+                       return -EINVAL;
+               }
+
+               node = e->nodes[0];
        }
 
+       int ret = _scf_expr_calculate_internal(ast, node, &d);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 92ab2e8c12f7db51f3b1a1d6f2bdae4031704540..25f17102dd6c8a2afe8c0bb3e0f123c793101621 100644 (file)
@@ -12,4 +12,3 @@ int scf_expr_semantic_analysis(scf_ast_t* ast, scf_expr_t* e);
 int scf_semantic_analysis(scf_ast_t* ast);
 
 #endif
-