From 00f068fb903ca968c37912f749fddc688614a454 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Thu, 25 Sep 2025 21:47:39 +0800 Subject: [PATCH] js: support variable args of js function() with 'arguments[]' array --- examples/js.html | 9 +- examples/js2.html | 22 ++ html/Makefile | 4 + html/abc_html.c | 65 +++-- js/abc_libjs.c | 16 ++ js/abc_libjs.so | Bin 14440 -> 55000 bytes js/core/scf_3ac.c | 2 +- js/core/scf_basic_block.c | 8 +- js/core/scf_function.c | 5 + js/core/scf_function.h | 1 + js/core/scf_node.h | 4 + js/core/scf_operator_handler_3ac.c | 6 +- js/core/scf_optimizer.c | 11 +- js/core/scf_optimizer_auto_gc_find.c | 10 +- js/core/scf_optimizer_js_array.c | 126 ++++++++++ js/core/scf_optimizer_js_call.c | 146 ++++++++++++ js/core/scf_variable.h | 1 + js/doc.c | 156 ++++++++++-- js/parse/scf_dfa_call.c | 175 +++++++++++++- js/parse/scf_dfa_class.c | 4 +- js/parse/scf_dfa_enum.c | 4 +- js/parse/scf_dfa_expr.c | 104 +++++--- js/parse/scf_dfa_function.c | 11 +- js/parse/scf_dfa_function_js.c | 110 +++++++-- js/parse/scf_dfa_init_data.c | 26 +- js/parse/scf_dfa_switch.c | 20 +- js/parse/scf_operator_handler_semantic.c | 291 +++++++++++++++++------ js/parse/scf_parse.h | 3 +- ui/Makefile | 2 + 29 files changed, 1116 insertions(+), 226 deletions(-) create mode 100644 examples/js2.html create mode 100644 js/core/scf_optimizer_js_array.c create mode 100644 js/core/scf_optimizer_js_call.c diff --git a/examples/js.html b/examples/js.html index 146d3e4..e6b57d1 100644 --- a/examples/js.html +++ b/examples/js.html @@ -7,12 +7,13 @@

含有js的页面

diff --git a/examples/js2.html b/examples/js2.html new file mode 100644 index 0000000..871481e --- /dev/null +++ b/examples/js2.html @@ -0,0 +1,22 @@ + + + + +

含有javascript的页面

+ +

含有js的页面

+ + + + + diff --git a/html/Makefile b/html/Makefile index 1d21c36..37acf10 100644 --- a/html/Makefile +++ b/html/Makefile @@ -105,6 +105,10 @@ CFILES += ../js/core/scf_pointer_alias.c CFILES += ../js/core/scf_optimizer.c CFILES += ../js/core/scf_optimizer_dag.c CFILES += ../js/core/scf_optimizer_inline.c + +CFILES += ../js/core/scf_optimizer_js_array.c +CFILES += ../js/core/scf_optimizer_js_call.c + CFILES += ../js/core/scf_optimizer_split_call.c CFILES += ../js/core/scf_optimizer_call.c CFILES += ../js/core/scf_optimizer_common_expr.c diff --git a/html/abc_html.c b/html/abc_html.c index 5e48e3b..f47710a 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -593,6 +593,7 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) abc_char_t* c = NULL; + int flag = 0; while (1) { c = __html_pop_char(html); if (!c) { @@ -601,8 +602,13 @@ static int __html_parse_text(abc_html_t* html, abc_obj_t* obj) return -1; } - if ('<' == c->c) - break; + if ('\'' == c->c || '\"' == c->c) + flag = !flag; + + if (!flag) { + if ('<' == c->c) + break; + } if ('\n' == c->c) { html->n_lines++; @@ -869,44 +875,45 @@ static int __html_parse_attr(abc_html_t* html, abc_obj_t* obj, const html_attr_t static int __html_js_path(scf_string_t** ppath, abc_obj_t* obj, const char* prefix, const char* ext, int dir_flag) { - if (*ppath) - scf_string_free(*ppath); - - *ppath = scf_string_alloc(); - if (!*ppath) + scf_string_t* path = scf_string_alloc(); + if (!path) return -ENOMEM; + int ret = 0; + if (dir_flag) { char* cwd = get_current_dir_name(); - if (!cwd) + if (!cwd) { + scf_string_free(path); return -ENOMEM; + } - int ret = scf_string_cat_cstr(*ppath, cwd); + ret = scf_string_cat_cstr(path, cwd); free(cwd); cwd = NULL; if (ret < 0) - return ret; + goto error; - ret = scf_string_cat_cstr(*ppath, "/"); + ret = scf_string_cat_cstr(path, "/"); if (ret < 0) - return ret; + goto error; } if (prefix) { - int ret = scf_string_cat_cstr(*ppath, prefix); + ret = scf_string_cat_cstr(path, prefix); if (ret < 0) - return ret; + goto error; } - int len = (*ppath)->len; + int len = path->len; int i; - int ret = scf_string_cat(*ppath, obj->file); + ret = scf_string_cat(path, obj->file); if (ret < 0) - return ret; + goto error; - for (i = len; i < (*ppath)->len; i++) { - char c = (*ppath)->data[i]; + for (i = len; i < path->len; i++) { + char c = path->data[i]; if ('_' == c || ('0' <= c && c <= '9') @@ -914,23 +921,31 @@ static int __html_js_path(scf_string_t** ppath, abc_obj_t* obj, const char* pref || ('A' <= c && c <= 'Z')) continue; - (*ppath)->data[i] = '_'; + path->data[i] = '_'; } char buf[256]; len = snprintf(buf, sizeof(buf) - 1, "_%d_%d", obj->line, obj->pos); - ret = scf_string_cat_cstr_len(*ppath, buf, len); + ret = scf_string_cat_cstr_len(path, buf, len); if (ret < 0) - return ret; + goto error; if (ext) { - ret = scf_string_cat_cstr(*ppath, ext); + ret = scf_string_cat_cstr(path, ext); if (ret < 0) - return ret; + goto error; } + if (*ppath) + scf_string_free(*ppath); + + *ppath = path; return 0; + +error: + scf_string_free(path); + return ret; } static int __html_run_js(abc_html_t* html, abc_obj_t* obj) @@ -962,6 +977,8 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) } if (obj->text) { + scf_logd("obj->text: %s\n", obj->text->data); + ret = scf_parse_file(html->js, obj->js_path->data, obj->text); if (ret < 0) return ret; diff --git a/js/abc_libjs.c b/js/abc_libjs.c index c43216d..a606910 100644 --- a/js/abc_libjs.c +++ b/js/abc_libjs.c @@ -96,3 +96,19 @@ error: } return -1; } + +int abc_html_write_i(abc_html_t* html, int64_t i) +{ + char buf[128]; + snprintf(buf, sizeof(buf) - 1, "%ld", i); + + return abc_html_write(html, buf); +} + +int abc_html_write_d(abc_html_t* html, double d) +{ + char buf[128]; + snprintf(buf, sizeof(buf) - 1, "%lg", d); + + return abc_html_write(html, buf); +} diff --git a/js/abc_libjs.so b/js/abc_libjs.so index cb2894b91f8825c8ff490375a86190317ca0631c..60fb561ab41edae56d980c62122a562bf3a17cdd 100755 GIT binary patch literal 55000 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�yursMfXFK^72``~&$ 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 diff --git a/js/core/scf_3ac.c b/js/core/scf_3ac.c index 37989c2..45a2691 100644 --- a/js/core/scf_3ac.c +++ b/js/core/scf_3ac.c @@ -502,7 +502,7 @@ void scf_3ac_code_print(scf_3ac_code_t* c, scf_list_t* sentinel) } if (c->srcs) { - + for (i = 0; i < c->srcs->size; i++) { src = c->srcs->data[i]; diff --git a/js/core/scf_basic_block.c b/js/core/scf_basic_block.c index b38a2dd..55a6426 100644 --- a/js/core/scf_basic_block.c +++ b/js/core/scf_basic_block.c @@ -1132,8 +1132,9 @@ int scf_basic_block_active_vars(scf_basic_block_t* bb) } #endif - scf_vector_clear(bb->entry_dn_actives, NULL); - scf_vector_clear(bb->dn_updateds, NULL); + scf_vector_clear(bb->entry_dn_actives, NULL); + scf_vector_clear(bb->entry_dn_inactives, NULL); + scf_vector_clear(bb->dn_updateds, NULL); if (!scf_list_empty(&bb->code_list_head)) { @@ -1319,6 +1320,9 @@ int scf_basic_block_loads_saves(scf_basic_block_t* bb, scf_list_t* bb_list_head) int ret; int i; + scf_vector_clear(bb->dn_loads, NULL); + scf_vector_clear(bb->dn_saves, NULL); + for (i = 0; i < bb->entry_dn_actives->size; i++) { dn = bb->entry_dn_actives->data[i]; diff --git a/js/core/scf_function.c b/js/core/scf_function.c index 4fe5bef..a8d5e31 100644 --- a/js/core/scf_function.c +++ b/js/core/scf_function.c @@ -99,6 +99,11 @@ void scf_function_free(scf_function_t* f) f->signature = NULL; } + if (f->src_code) { + scf_string_free(f->src_code); + f->src_code = NULL; + } + if (f->rets) { scf_vector_clear(f->rets, ( void (*)(void*) ) scf_variable_free); scf_vector_free (f->rets); diff --git a/js/core/scf_function.h b/js/core/scf_function.h index 26e074a..c69b4a3 100644 --- a/js/core/scf_function.h +++ b/js/core/scf_function.h @@ -9,6 +9,7 @@ struct scf_function_s { scf_scope_t* scope; scf_string_t* signature; + scf_string_t* src_code; scf_list_t list; // for scope diff --git a/js/core/scf_node.h b/js/core/scf_node.h index 1ad8432..375badd 100644 --- a/js/core/scf_node.h +++ b/js/core/scf_node.h @@ -19,6 +19,8 @@ struct scf_node_s { int nb_nodes; // children nodes count scf_node_t** nodes; // children nodes + scf_expr_t* js_create; // the expr which created this node, only for js! + union { scf_variable_t* var; scf_lex_word_t* w; @@ -44,6 +46,8 @@ struct scf_node_s { uint32_t split_flag :1; // set when node is a split node of its parent uint32_t _3ac_done :1; // set when node's 3ac code is made + uint32_t this_done :1; // set when node is a function call() & its 'this' pointer is set + uint32_t semi_flag :1; // set when followed by a ';' }; diff --git a/js/core/scf_operator_handler_3ac.c b/js/core/scf_operator_handler_3ac.c index c033049..840b46a 100644 --- a/js/core/scf_operator_handler_3ac.c +++ b/js/core/scf_operator_handler_3ac.c @@ -1677,7 +1677,11 @@ static int _scf_op_expr(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* #if 1 assert(1 == nb_nodes); - scf_handler_data_t* d = data; + scf_handler_data_t* d = data; + scf_node_t* parent = nodes[0]->parent; + + if (parent->_3ac_done) + return 0; int ret = _scf_expr_calculate_internal(ast, nodes[0], d); if (ret < 0) diff --git a/js/core/scf_optimizer.c b/js/core/scf_optimizer.c index 79fd61c..38214e9 100644 --- a/js/core/scf_optimizer.c +++ b/js/core/scf_optimizer.c @@ -1,6 +1,9 @@ #include"scf_optimizer.h" extern scf_optimizer_t scf_optimizer_inline; +extern scf_optimizer_t scf_optimizer_js_array; +extern scf_optimizer_t scf_optimizer_js_call; + extern scf_optimizer_t scf_optimizer_split_call; extern scf_optimizer_t scf_optimizer_dag; @@ -32,6 +35,9 @@ extern scf_optimizer_t scf_optimizer_generate_loads_saves; static scf_optimizer_t* scf_optimizers[] = { &scf_optimizer_inline, // global optimizer + &scf_optimizer_js_array, + &scf_optimizer_js_call, + &scf_optimizer_split_call, &scf_optimizer_dag, @@ -46,14 +52,15 @@ static scf_optimizer_t* scf_optimizers[] = &scf_optimizer_loads_saves, &scf_optimizer_auto_gc_find, // global optimizer - &scf_optimizer_dominators, - &scf_optimizer_auto_gc, &scf_optimizer_basic_block, &scf_optimizer_const_teq, + &scf_optimizer_active_vars, + &scf_optimizer_loads_saves, + &scf_optimizer_dominators, &scf_optimizer_loop, &scf_optimizer_vla, diff --git a/js/core/scf_optimizer_auto_gc_find.c b/js/core/scf_optimizer_auto_gc_find.c index ae9b6f3..9cf8a6c 100644 --- a/js/core/scf_optimizer_auto_gc_find.c +++ b/js/core/scf_optimizer_auto_gc_find.c @@ -344,6 +344,8 @@ static int _auto_gc_find_argv_out(scf_basic_block_t* cur_bb, scf_3ac_code_t* c) static int _auto_gc_find_ret(scf_basic_block_t* cur_bb, scf_3ac_code_t* c) { + if (!c->dsts) + return 0; assert(c->srcs->size > 0); scf_3ac_operand_t* dst; @@ -501,17 +503,16 @@ static int _auto_gc_find_ref(scf_dn_status_t* ds_obj, scf_dag_node_t* dn, scf_3a } if (fret->auto_gc_flag) { - _bb_add_ds (cur_bb, ds_obj); - _bb_add_ds_for_ret(cur_bb, ds_obj, f2); - ds = scf_dn_status_alloc(dn); if (!ds) return -ENOMEM; - _bb_del_ds(cur_bb, ds); scf_dn_status_free(ds); ds = NULL; + + _bb_add_ds (cur_bb, ds_obj); + _bb_add_ds_for_ret(cur_bb, ds_obj, f2); return 2; } } else { @@ -849,7 +850,6 @@ static int _auto_gc_function_find(scf_ast_t* ast, scf_function_t* f, scf_list_t* 0xffff & (uintptr_t)ds, ds->ret_flag, ds->ret_index, ds->dag_node->var->arg_flag); scf_dn_status_print(ds); #endif - if (ds->dag_node->var->arg_flag) ds->dag_node->var->auto_gc_flag = 1; else { diff --git a/js/core/scf_optimizer_js_array.c b/js/core/scf_optimizer_js_array.c new file mode 100644 index 0000000..e5899cf --- /dev/null +++ b/js/core/scf_optimizer_js_array.c @@ -0,0 +1,126 @@ +#include"scf_optimizer.h" +#include"scf_pointer_alias.h" + +static int __js_array_realloc(scf_ast_t* ast, scf_3ac_code_t** pc, scf_node_t* array, scf_node_t* index) +{ + scf_3ac_code_t* c; + scf_variable_t* v; + scf_function_t* f = NULL; + scf_type_t* t = NULL; + scf_node_t* pf; + + int ret = scf_ast_find_global_function(&f, ast, "Object_array_realloc"); + if (ret < 0) + return ret; + + 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_t* srcs[3] = {pf, array, index}; + + c = scf_3ac_code_NN(SCF_OP_CALL, NULL, 0, srcs, 3); + if (!c) { + scf_node_free(pf); + return -ENOMEM; + } + + *pc = c; + return 0; +} + +static int _optimize_js_array_bb(scf_ast_t* ast, scf_basic_block_t* bb, scf_list_t* bb_list_head) +{ + scf_3ac_operand_t* base; + scf_3ac_operand_t* index; + scf_3ac_code_t* c; + scf_3ac_code_t* c2; + scf_variable_t* v; + scf_node_t* array; + scf_type_t* Object = NULL; + scf_list_t* l; + + int ret = scf_ast_find_global_type(&Object, ast, "Object"); + if (ret < 0) + return ret; + + for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) { + + c = scf_list_data(l, scf_3ac_code_t, list); + l = scf_list_next(l); + + if (SCF_OP_ARRAY_INDEX == c->op->type || scf_type_is_assign_array_index(c->op->type)) { + base = c->srcs->data[0]; + index = c->srcs->data[1]; + array = base->node; + + while (SCF_OP_EXPR == array->type || SCF_OP_POINTER == array->type) + array = array->nodes[0]; + + v = _scf_operand_get(array); + + if (v->type == Object->type) { + c2 = NULL; + ret = __js_array_realloc(ast, &c2, array, index->node); + if (ret < 0) + return ret; + + c2->basic_block = c->basic_block; + + assert(scf_list_prev(&c->list) != scf_list_sentinel(&bb->code_list_head)); + + scf_list_add_tail(scf_list_prev(&c->list), &c2->list); + } + } + } + + return 0; +} + +static int _optimize_js_array(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions) +{ + if (!f) + return -EINVAL; + + scf_list_t* bb_list_head = &f->basic_block_list_head; + scf_list_t* l; + scf_basic_block_t* bb; + + if (scf_list_empty(bb_list_head)) + return 0; + + for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) { + + bb = scf_list_data(l, scf_basic_block_t, list); + l = scf_list_next(l); + + if (bb->jmp_flag || bb->end_flag || bb->cmp_flag) + continue; + + int ret = _optimize_js_array_bb(ast, bb, bb_list_head); + if (ret < 0) + return ret; + } + + return 0; +} + +scf_optimizer_t scf_optimizer_js_array = +{ + .name = "js_array", + + .optimize = _optimize_js_array, + + .flags = SCF_OPTIMIZER_LOCAL, +}; diff --git a/js/core/scf_optimizer_js_call.c b/js/core/scf_optimizer_js_call.c new file mode 100644 index 0000000..2f5eca3 --- /dev/null +++ b/js/core/scf_optimizer_js_call.c @@ -0,0 +1,146 @@ +#include"scf_optimizer.h" +#include"scf_pointer_alias.h" + +static int __js_call_arguments(scf_ast_t* ast, scf_3ac_code_t** pc, scf_node_t* arguments, int i, scf_node_t* arg) +{ + scf_3ac_code_t* c; + scf_variable_t* v; + scf_function_t* f = NULL; + scf_type_t* t = NULL; + scf_node_t* pf; + scf_node_t* index; + + int ret = scf_ast_find_global_function(&f, ast, "Object_func_arguments"); + if (ret < 0) + return ret; + + 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; + + // index + ret = scf_ast_find_type_type(&t, ast, SCF_VAR_INT); + if (ret < 0) + return ret; + + v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 1, 0, NULL); + if (!v) + return -ENOMEM; + v->data.u64 = i; + v->const_literal_flag = 1; + + index = scf_node_alloc(NULL, v->type, v); + scf_variable_free(v); + v = NULL; + if (!index) + return -ENOMEM; + + scf_node_t* srcs[] = {pf, arguments, index, arg}; + + c = scf_3ac_code_NN(SCF_OP_CALL, NULL, 0, srcs, 4); + if (!c) { + scf_node_free(index); + scf_node_free(pf); + return -ENOMEM; + } + + *pc = c; + return 0; +} + +static int _optimize_js_call_bb(scf_ast_t* ast, scf_basic_block_t* bb, scf_list_t* bb_list_head) +{ + scf_3ac_operand_t* src; + scf_3ac_operand_t* args; + scf_3ac_code_t* c; + scf_3ac_code_t* c2; + scf_variable_t* v; + scf_function_t* f; + scf_node_t* array; + scf_type_t* Object = NULL; + scf_list_t* l; + + int ret = scf_ast_find_global_type(&Object, ast, "Object"); + if (ret < 0) + return ret; + + for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) { + + c = scf_list_data(l, scf_3ac_code_t, list); + l = scf_list_next(l); + + if (SCF_OP_CALL != c->op->type) + continue; + + src = c->srcs->data[0]; + f = _scf_operand_get(src->node)->func_ptr; + + if (!f->js_flag || !f->vargs_flag) + continue; + args = c->srcs->data[2]; + + int i; + for (i = 3; i < c->srcs->size; i++) { + src = c->srcs->data[i]; + + c2 = NULL; + ret = __js_call_arguments(ast, &c2, args->node, i - 3, src->node); + if (ret < 0) + return ret; + + c2->basic_block = c->basic_block; + + scf_list_add_tail(&c->list, &c2->list); + } + } + + return 0; +} + +static int _optimize_js_call(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions) +{ + if (!f) + return -EINVAL; + + scf_list_t* bb_list_head = &f->basic_block_list_head; + scf_list_t* l; + scf_basic_block_t* bb; + + if (scf_list_empty(bb_list_head)) + return 0; + + for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) { + + bb = scf_list_data(l, scf_basic_block_t, list); + l = scf_list_next(l); + + if (bb->jmp_flag || bb->end_flag || bb->cmp_flag) + continue; + + int ret = _optimize_js_call_bb(ast, bb, bb_list_head); + if (ret < 0) + return ret; + } + + return 0; +} + +scf_optimizer_t scf_optimizer_js_call = +{ + .name = "js_call", + + .optimize = _optimize_js_call, + + .flags = SCF_OPTIMIZER_LOCAL, +}; diff --git a/js/core/scf_variable.h b/js/core/scf_variable.h index 1d560a1..96e695d 100644 --- a/js/core/scf_variable.h +++ b/js/core/scf_variable.h @@ -18,6 +18,7 @@ struct scf_variable_s { int js_type; int js_index; + scf_variable_t* js_var; int nb_lbs; // number of '{}' when parse js object int nb_rbs; diff --git a/js/doc.c b/js/doc.c index 1711088..c1aa9c2 100644 --- a/js/doc.c +++ b/js/doc.c @@ -2,12 +2,21 @@ struct Object; -int abc_html_write(Object* html, const char* s); +int abc_html_write (Object* html, const char* s); +int abc_html_write_i(Object* html, int64_t i); +int abc_html_write_d(Object* html, double d); + +enum { + JS_Undef, + JS_Number, + JS_String, + JS_Object, +}; struct Object { int type; - int n_members; + int length; Object** members; char* name; // p.x --> p.members[x] @@ -16,22 +25,35 @@ struct Object int __init(Object* this, double d) { - this->d = d; + this->d = d; + this->type = JS_Number; + printf("this: %p, this->d: %lg, d: %lg\n\n", this, this->d, d); return 0; } int __init(Object* this, int64_t d) { - this->d = d; + this->d = d; + this->type = JS_Number; + printf("this: %p, this->d: %lg, d: %ld\n\n", this, this->d, d); return 0; } - int __init(Object* this, void* p) + int __init(Object* this, const char* s) { + int len = strlen(s); + + this->str = scf__auto_malloc(len + 1); + if (!this->str) + return -1; + + memcpy(this->str, s, len + 1); + + this->type = JS_String; return 0; } - int __init(Object* this, const char* name, int n_members) + int __init(Object* this, const char* name, int length) { printf("this: %p, name: %s\n", this, name); int len = strlen(name); @@ -41,19 +63,21 @@ struct Object return -1; memcpy(this->name, name, len + 1); - this->n_members = n_members; + this->length = length; - if (n_members > 0) { - this->members = scf__auto_malloc(sizeof(Object*) * n_members); + if (length > 0) { + this->members = scf__auto_malloc(sizeof(Object*) * length); if (!this->members) return -1; } printf("\n"); + + this->type = JS_Object; return 0; } - int __init(Object* this, const char* name, int n_members, double d) + int __init(Object* this, const char* name, int length, double d) { printf("this: %p, name: %s\n", this, name); int len = strlen(name); @@ -63,27 +87,75 @@ struct Object return -1; memcpy(this->name, name, len + 1); - this->n_members = n_members; + this->length = length; - if (n_members > 0) { - this->members = scf__auto_malloc(sizeof(Object*) * n_members); + if (length > 0) { + this->members = scf__auto_malloc(sizeof(Object*) * length); if (!this->members) return -1; - } + + this->type = JS_Object; + } else + this->type = JS_Number; this->d = d; - printf("this: %p, this->d: %lg, d: %lg\n", this, this->d, d); + printf("this: %p, this->d: %lg, d: %lg\n\n", this, this->d, d); return 0; } const char* toString(Object* this) { - char* s = scf__auto_malloc(128); - if (!s) - return NULL; + char* p; + char* s; + int len; + int type = JS_Undef; + + if (this) + type = this->type; + + switch (type) { + case JS_Number: + s = scf__auto_malloc(128); + if (!s) + return NULL; + + snprintf(s, 127, "%lg", this->d); + break; + + case JS_String: + len = strlen(this->str); + + s = scf__auto_malloc(len + 1); + if (!s) + return NULL; + + memcpy(s, this->str, len + 1); + break; + + case JS_Object: + p = "[object Object]"; + len = strlen(p); + + s = scf__auto_malloc(len + 1); + if (!s) + return NULL; + + memcpy(s, p, len + 1); + break; + + default: + p = "undefined"; + len = strlen(p); + + s = scf__auto_malloc(len + 1); + if (!s) + return NULL; + + memcpy(s, p, len + 1); + break; + }; - snprintf(s, 127, "%lg", this->d); return s; } @@ -93,6 +165,21 @@ struct Object abc_html_write(this, s); } + void write(Object* this, const char* s) + { + abc_html_write(this, s); + } + + void write(Object* this, int64_t i) + { + abc_html_write_i(this, i); + } + + void write(Object* this, double d) + { + abc_html_write_i(this, d); + } + Object* operator+(Object* this, Object* that) { Object* res = create Object(this->d + that->d); @@ -103,7 +190,7 @@ struct Object { if (this->members) { int i; - for (i = 0; i < this->n_members; i++) { + for (i = 0; i < this->length; i++) { if (this->members[i]) { this->members[i].__release(); @@ -124,6 +211,35 @@ struct Object } }; +void Object_func_arguments(Object* this, int i, Object* arg) +{ + if (i < this->length) { + scf__auto_ref(arg); + this->members[i] = arg; + } +} + +int Object_array_realloc(Object* this, int i) +{ + if (i < this->length) + return 0; + + int n = i + 1; + void* p = scf__auto_malloc(sizeof(Object*) * n); + if (!p) + return -1; + + if (this->length > 0) { + memcpy(p, this->members, sizeof(Object*) * this->length); + + scf__auto_freep(&this->members, NULL); + } + + this->members = p; + this->length = n; + return 0; +} + Object* document = NULL; void __js_main(Object* doc) diff --git a/js/parse/scf_dfa_call.c b/js/parse/scf_dfa_call.c index 18a26ad..d90ac76 100644 --- a/js/parse/scf_dfa_call.c +++ b/js/parse/scf_dfa_call.c @@ -147,6 +147,11 @@ static int _call_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->expr = NULL; d->expr_local_flag++; + if (d->parent_block) { + ast->current_block = d->parent_block; + d->parent_block = NULL; + } + scf_stack_push(s, cd); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "call_rp"), SCF_DFA_HOOK_POST); @@ -156,6 +161,139 @@ static int _call_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_NEXT_WORD; } +static int _call_add_arguments(scf_ast_t* ast, scf_lex_word_t* w, int n_members, scf_expr_t* e, scf_type_t* Object) +{ + scf_variable_t* v; + scf_block_t* b; + scf_type_t* pt = scf_block_find_type_type(ast->current_block, SCF_FUNCTION_PTR); + scf_node_t* create; + scf_node_t* assign; + scf_node_t* node; + scf_node_t* arguments; + scf_expr_t* e2; + + // add 'arguments' + v = SCF_VAR_ALLOC_BY_TYPE(w, Object, 0, 1, NULL); + if (!v) + return -ENOMEM; + + arguments = scf_node_alloc(NULL, v->type, v); + scf_variable_free(v); + v = NULL; + if (!arguments) + return -ENOMEM; + + b = scf_block_alloc_cstr("multi_rets"); + if (!b) { + scf_node_free(arguments); + return -ENOMEM; + } + + int ret = scf_node_add_child((scf_node_t*)b, arguments); + if (ret < 0) { + scf_node_free(arguments); + scf_block_free(b); + return ret; + } + + assign = scf_node_alloc(w, SCF_OP_ASSIGN, NULL); + if (!assign) { + scf_block_free(b); + return -ENOMEM; + } + + ret = scf_node_add_child(assign, (scf_node_t*)b); + if (ret < 0) { + scf_node_free(assign); + scf_block_free(b); + return ret; + } + b = NULL; + + // add create() + create = scf_node_alloc(w, SCF_OP_CREATE, NULL); + if (!create) { + scf_node_free(assign); + return -ENOMEM; + } + + ret = scf_node_add_child(assign, create); + if (ret < 0) { + scf_node_free(create); + scf_node_free(assign); + return ret; + } + + // add construct() for obj + v = SCF_VAR_ALLOC_BY_TYPE(Object->w, pt, 1, 1, NULL); + if (!v) { + scf_node_free(assign); + return -ENOMEM; + } + v->const_literal_flag = 1; + + node = scf_node_alloc(NULL, v->type, v); + scf_variable_free(v); + v = NULL; + if (!node) { + scf_node_free(assign); + return -ENOMEM; + } + + ret = scf_node_add_child(create, node); + if (ret < 0) { + scf_node_free(node); + scf_node_free(assign); + return ret; + } + + // add obj name + ret = scf_ast_add_const_str(ast, create, Object->w); + if (ret < 0) { + scf_node_free(assign); + return ret; + } + + // add obj members + ret = scf_ast_add_const_var(ast, create, SCF_VAR_INT, n_members); + if (ret < 0) { + scf_node_free(assign); + return ret; + } + + e2 = scf_expr_alloc(); + if (!e2) { + scf_node_free(assign); + return -ENOMEM; + } + + ret = scf_node_add_child(e2, assign); + if (ret < 0) { + scf_expr_free(e2); + scf_node_free(assign); + return ret; + } + + ret = scf_node_add_child((scf_node_t*)ast->current_block, e2); + if (ret < 0) { + scf_expr_free(e2); + return ret; + } + + node = scf_node_clone(arguments); + if (!node) + return -ENOMEM; + + ret = scf_node_add_child(e, node); + if (ret < 0) { + scf_node_free(node); + return ret; + } + + e->js_create = e2; + return 0; +} + static int _call_add_obj(scf_ast_t* ast, scf_lex_word_t* w, scf_node_t* call, scf_expr_t* e, scf_type_t* Object) { scf_variable_t* v = NULL; @@ -250,6 +388,7 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) } scf_parse_t* parse = dfa->priv; + scf_ast_t* ast = parse->ast; dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; scf_stack_t* s = d->module_datas[dfa_module_call.index]; @@ -287,10 +426,10 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) } scf_variable_t* r; - scf_function_t* f; - scf_expr_t* e; + scf_function_t* f = NULL; scf_type_t* Object = NULL; scf_node_t* pf = cd->call->nodes[0]; + scf_expr_t* e; while (SCF_OP_EXPR == pf->type) pf = pf->nodes[0]; @@ -298,13 +437,16 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) if (SCF_OP_POINTER == pf->type) pf = pf->nodes[1]; - int ret = scf_ast_find_type(&Object, parse->ast, "Object"); + int ret = scf_ast_find_type(&Object, ast, "Object"); if (ret < 0) return ret; + int js_flag = 1; if (SCF_FUNCTION_PTR == pf->type) { f = pf->var->func_ptr; + js_flag = f->js_flag; + scf_logw("f: %s, f->js_flag: %d\n", f->node.w->text->data, f->js_flag); } else assert(Object->type == pf->type); @@ -314,8 +456,8 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) for (i = 0; i < cd->argv->size; i++) { e = cd->argv->data[i]; - if (pf->type == Object->type) { - ret = _call_add_obj(parse->ast, w, cd->call, e, Object); + if (js_flag) { + ret = _call_add_obj(ast, w, cd->call, e, Object); if (ret < 0) return ret; } @@ -329,8 +471,8 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) // the last arg if (d->expr) { - if (pf->type == Object->type) { - ret = _call_add_obj(parse->ast, w, cd->call, d->expr, Object); + if (js_flag) { + ret = _call_add_obj(ast, w, cd->call, d->expr, Object); if (ret < 0) return ret; } @@ -339,6 +481,25 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->expr = NULL; } + if (js_flag) { + e = scf_expr_alloc(); + if (!e) + return -ENOMEM; + + ret = _call_add_arguments(ast, w, cd->call->nb_nodes - 1, e, Object); + if (ret < 0) + return ret; + + scf_node_add_child(cd->call, e); + + int i; + for (i = cd->call->nb_nodes - 2; i >= 1; i--) + cd->call->nodes[i + 1] = cd->call->nodes[i]; + + cd->call->nodes[1] = e; + e = NULL; + } + if (cd->parent_expr) d->expr = cd->parent_expr; else diff --git a/js/parse/scf_dfa_class.c b/js/parse/scf_dfa_class.c index 17a4a10..5429e61 100644 --- a/js/parse/scf_dfa_class.c +++ b/js/parse/scf_dfa_class.c @@ -89,7 +89,7 @@ static int _class_action_lb(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_NEXT_WORD; } -int _class_calculate_size(scf_dfa_t* dfa, scf_type_t* s) +int _class_calculate_size(scf_type_t* s) { scf_variable_t* v; @@ -192,7 +192,7 @@ static int _class_action_rb(scf_dfa_t* dfa, scf_vector_t* words, void* data) dfa_data_t* d = data; class_module_data_t* md = d->module_datas[dfa_module_class.index]; - if (_class_calculate_size(dfa, md->current_class) < 0) { + if (_class_calculate_size(md->current_class) < 0) { scf_loge("\n"); return SCF_DFA_ERROR; } diff --git a/js/parse/scf_dfa_enum.c b/js/parse/scf_dfa_enum.c index aab35a0..d0bdafd 100644 --- a/js/parse/scf_dfa_enum.c +++ b/js/parse/scf_dfa_enum.c @@ -136,8 +136,6 @@ static int _enum_action_var(scf_dfa_t* dfa, scf_vector_t* words, void* data) md->current_v = v; - scf_logi("enum var: '%s', type: %d, size: %d\n", w->text->data, v->type, v->size); - return SCF_DFA_NEXT_WORD; } @@ -198,6 +196,8 @@ static int _enum_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->expr_local_flag--; } + scf_logi("enum var: '%s', value: %ld\n", md->current_v->w->text->data, md->current_v->data.i64); + md->current_v = NULL; return SCF_DFA_SWITCH_TO; diff --git a/js/parse/scf_dfa_expr.c b/js/parse/scf_dfa_expr.c index 7f8c3b4..42bb81e 100644 --- a/js/parse/scf_dfa_expr.c +++ b/js/parse/scf_dfa_expr.c @@ -8,7 +8,7 @@ extern scf_dfa_module_t dfa_module_expr; typedef struct { scf_stack_t* ls_exprs; scf_stack_t* lp_exprs; - scf_block_t* parent_block; + scf_variable_t* current_var; scf_type_t* current_struct; @@ -16,6 +16,8 @@ typedef struct { int _type_find_type(scf_dfa_t* dfa, dfa_identity_t* id); +int _class_calculate_size(scf_type_t* s); + static int _expr_is_expr(scf_dfa_t* dfa, void* word) { scf_lex_word_t* w = word; @@ -85,6 +87,7 @@ int _expr_add_var(scf_parse_t* parse, dfa_data_t* d) scf_node_t* node = NULL; scf_type_t* pt = NULL; scf_type_t* t = NULL; + scf_type_t* t2 = NULL; scf_function_t* f = NULL; dfa_identity_t* id = scf_stack_pop(d->current_identities); scf_lex_word_t* w; @@ -111,24 +114,50 @@ int _expr_add_var(scf_parse_t* parse, dfa_data_t* d) if (scf_ast_find_function(&f, parse->ast, w->text->data) < 0) return SCF_DFA_ERROR; - if (!f) { + if (f) { + var = SCF_VAR_ALLOC_BY_TYPE(id->identity, pt, 1, 1, f); + if (!var) + return -ENOMEM; + + var->const_literal_flag = 1; + + } else if (md->current_var && md->current_var->js_type >= 0) { + t = NULL; + if (scf_ast_find_type_type(&t, parse->ast, md->current_var->js_type) < 0) + return SCF_DFA_ERROR; + + t2 = NULL; + if (scf_ast_find_type_type(&t2, parse->ast, SCF_VAR_VAR) < 0) + return SCF_DFA_ERROR; + + var = SCF_VAR_ALLOC_BY_TYPE(w, t2, 0, 0, NULL); + if (!var) + return -ENOMEM; + var->member_flag = 1; + + scf_scope_push_var(t->scope, var); + + if (_class_calculate_size(t) < 0) + return SCF_DFA_ERROR; + + } else { scf_loge("function '%s' not found\n", w->text->data); return SCF_DFA_ERROR; } - - var = SCF_VAR_ALLOC_BY_TYPE(id->identity, pt, 1, 1, f); - if (!var) - return -ENOMEM; - - var->const_literal_flag = 1; + } else { + if (d->current_function + && d->current_function->js_flag + && !strcmp(w->text->data, "arguments")) + 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); if (md->current_var && md->current_var->js_type >= 0 - && SCF_FUNCTION_PTR != var->type - && var->member_flag) { + && var->member_flag + && strcmp(var->w->text->data, "length")) { + scf_logi("md->current_var: %s, var: %s, member_flag: %d, line: %d, pos: %d\n", md->current_var->w->text->data, var->w->text->data, var->member_flag, var->w->line, var->w->pos); @@ -166,6 +195,7 @@ int _expr_add_var(scf_parse_t* parse, dfa_data_t* d) return -ENOMEM; v->const_literal_flag = 1; v->data.i64 = var->js_index; + v->js_var = var; node = scf_node_alloc(w, v->type, v); scf_variable_free(v); @@ -354,7 +384,7 @@ static int _expr_action_op(scf_dfa_t* dfa, scf_vector_t* words, void* data, int if (scf_ast_find_type_type(&t, parse->ast, md->current_var->js_type) < 0) return SCF_DFA_ERROR; - scf_loge("t: %p, js_type: %d\n", t, t->type); + scf_logd("t: %p, js_type: %d\n", t, t->type); parse->ast->current_block = (scf_block_t*)t; } } @@ -373,6 +403,7 @@ static int _expr_action_binary_op(scf_dfa_t* dfa, scf_vector_t* words, void* dat scf_logd("\n"); scf_parse_t* parse = dfa->priv; + scf_ast_t* ast = parse->ast; dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; expr_module_data_t* md = d->module_datas[dfa_module_expr.index]; @@ -383,7 +414,7 @@ static int _expr_action_binary_op(scf_dfa_t* dfa, scf_vector_t* words, void* dat if (id && id->identity) { - v = scf_block_find_variable(parse->ast->current_block, id->identity->text->data); + v = scf_block_find_variable(ast->current_block, id->identity->text->data); if (!v) { scf_logw("'%s' not var\n", id->identity->text->data); @@ -404,14 +435,16 @@ static int _expr_action_binary_op(scf_dfa_t* dfa, scf_vector_t* words, void* dat if (SCF_LEX_WORD_ARROW == w->type || SCF_LEX_WORD_DOT == w->type) { assert(md->current_struct); - if (!md->parent_block) - md->parent_block = parse->ast->current_block; + if (!d->parent_block) + d->parent_block = ast->current_block; - parse->ast->current_block = (scf_block_t*)md->current_struct; + ast->current_block = (scf_block_t*)md->current_struct; - } else if (md->parent_block) { - parse->ast->current_block = md->parent_block; - md->parent_block = NULL; + scf_logi("ast->current_block: %p, js_type: %d\n", ast->current_block, ast->current_block->node.type); + + } else if (d->parent_block) { + ast->current_block = d->parent_block; + d->parent_block = NULL; } return _expr_action_op(dfa, words, data, 2); @@ -434,9 +467,9 @@ static int _expr_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_stack_push(md->lp_exprs, d->expr); d->expr = e; - if (md->parent_block) { - parse->ast->current_block = md->parent_block; - md->parent_block = NULL; + if (d->parent_block) { + parse->ast->current_block = d->parent_block; + d->parent_block = NULL; } return SCF_DFA_NEXT_WORD; @@ -553,9 +586,9 @@ static int _expr_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) } } - if (md->parent_block) { - parse->ast->current_block = md->parent_block; - md->parent_block = NULL; + if (d->parent_block) { + parse->ast->current_block = d->parent_block; + d->parent_block = NULL; } scf_expr_t* parent = scf_stack_pop(md->lp_exprs); @@ -626,9 +659,9 @@ static int _expr_action_ls(scf_dfa_t* dfa, scf_vector_t* words, void* data) } } - if (md->parent_block) { - parse->ast->current_block = md->parent_block; - md->parent_block = NULL; + if (d->parent_block) { + parse->ast->current_block = d->parent_block; + d->parent_block = NULL; } if (md->current_var->js_type >= 0) { @@ -698,9 +731,9 @@ static int _expr_action_rs(scf_dfa_t* dfa, scf_vector_t* words, void* data) } } - if (md->parent_block) { - parse->ast->current_block = md->parent_block; - md->parent_block = NULL; + if (d->parent_block) { + parse->ast->current_block = d->parent_block; + d->parent_block = NULL; } scf_expr_t* ls_parent = scf_stack_pop(md->ls_exprs); @@ -820,9 +853,12 @@ static int _expr_fini_expr(scf_parse_t* parse, dfa_data_t* d, int semi_flag) return SCF_DFA_ERROR; } - if (md->parent_block) { - parse->ast->current_block = md->parent_block; - md->parent_block = NULL; + if (md->current_var) + md->current_var = NULL; + + if (d->parent_block) { + parse->ast->current_block = d->parent_block; + d->parent_block = NULL; } scf_logd("d->expr: %p\n", d->expr); @@ -858,7 +894,7 @@ static int _expr_fini_expr(scf_parse_t* parse, dfa_data_t* d, int semi_flag) d->expr = NULL; } - scf_logd("d->expr: %p, d->expr_local_flag: %d\n", d->expr, d->expr_local_flag); + scf_logi("d->expr: %p, d->expr_local_flag: %d\n", d->expr, d->expr_local_flag); } return SCF_DFA_OK; diff --git a/js/parse/scf_dfa_function.c b/js/parse/scf_dfa_function.c index b5cf920..fe0748e 100644 --- a/js/parse/scf_dfa_function.c +++ b/js/parse/scf_dfa_function.c @@ -279,18 +279,16 @@ static int _function_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) assert(t->scope); - if (!strcmp(f->node.w->text->data, "__init")) { + if (!strcmp(f->node.w->text->data, "__release")) { - fprev = scf_scope_find_same_function(t->scope, f); - - } else { fprev = scf_scope_find_function(t->scope, f->node.w->text->data); - - if (fprev && !scf_function_same(fprev, f)) { + if (fprev) { scf_loge("function '%s' can't be overloaded, repeated declare first in line: %d, second in line: %d\n", f->node.w->text->data, fprev->node.w->line, f->node.w->line); return SCF_DFA_ERROR; } + } else { + fprev = scf_scope_find_same_function(t->scope, f); } } else { scf_block_t* b = fd->parent_block; @@ -311,7 +309,6 @@ static int _function_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) } if (fprev && !scf_function_same(fprev, f)) { - scf_loge("repeated declare function '%s', first in line: %d, second in line: %d, function overloading only can do in class\n", f->node.w->text->data, fprev->node.w->line, f->node.w->line); return SCF_DFA_ERROR; diff --git a/js/parse/scf_dfa_function_js.c b/js/parse/scf_dfa_function_js.c index 62590a3..97ff26b 100644 --- a/js/parse/scf_dfa_function_js.c +++ b/js/parse/scf_dfa_function_js.c @@ -8,6 +8,7 @@ typedef struct { scf_block_t* parent_block; scf_expr_t* parent_expr; + int start_word; } dfa_fun_data_t; int _function_js_add_function(scf_dfa_t* dfa, scf_lex_word_t* w, dfa_data_t* d) @@ -83,11 +84,12 @@ int _function_js_add_arg(scf_ast_t* ast, scf_lex_word_t* w, dfa_data_t* d) arg = SCF_VAR_ALLOC_BY_TYPE(w, t, 0, 1, NULL); if (!arg) return SCF_DFA_ERROR; + arg->js_type = t->type; scf_scope_push_var(d->current_function->scope, arg); - scf_logi("d->argc: %d, arg->nb_pointers: %d, arg->nb_dimentions: %d\n", - d->argc, arg->nb_pointers, arg->nb_dimentions); + scf_logi("d->argc: %d, arg->nb_pointers: %d, arg->nb_dimentions: %d, %s\n", + d->argc, arg->nb_pointers, arg->nb_dimentions, w->text->data); scf_vector_add(d->current_function->argv, arg); @@ -100,15 +102,6 @@ int _function_js_add_arg(scf_ast_t* ast, scf_lex_word_t* w, dfa_data_t* d) return SCF_DFA_NEXT_WORD; } -static int _function_js_action_vargs(scf_dfa_t* dfa, scf_vector_t* words, void* data) -{ - dfa_data_t* d = data; - - d->current_function->vargs_flag = 1; - - return SCF_DFA_NEXT_WORD; -} - static int _function_js_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; @@ -132,6 +125,16 @@ static int _function_js_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* return SCF_DFA_NEXT_WORD; } +static int _function_js_action_func(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_js.index]; + + fd->start_word = words->size - 1; + + return SCF_DFA_NEXT_WORD; +} + static int _function_js_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; @@ -139,6 +142,7 @@ static int _function_js_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* dat dfa_fun_data_t* fd = d->module_datas[dfa_module_function_js.index]; scf_lex_word_t* w; scf_lex_word_t* this; + scf_lex_word_t* arguments; if (words->size < 2) return SCF_DFA_ERROR; @@ -176,6 +180,24 @@ static int _function_js_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* dat if (ret < 0) return SCF_DFA_ERROR; + // add 'arguments' + arguments = scf_lex_word_alloc(w->file, 0, 0, SCF_LEX_WORD_ID); + if (!arguments) + return SCF_DFA_ERROR; + + arguments->text = scf_string_cstr("arguments"); + if (!arguments->text) { + scf_lex_word_free(arguments); + return SCF_DFA_ERROR; + } + + ret = _function_js_add_arg(parse->ast, arguments, d); + + scf_lex_word_free(arguments); + arguments = NULL; + if (ret < 0) + return SCF_DFA_ERROR; + return SCF_DFA_NEXT_WORD; } @@ -248,19 +270,70 @@ static int _function_js_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* da scf_lex_word_t* h = NULL; dfa_fun_data_t* fd = d->module_datas[dfa_module_function_js.index]; scf_function_t* f = d->current_function; + scf_variable_t* arg; scf_type_t* t; + int i; + parse->ast->current_block = (scf_block_t*)(fd->parent_block); if (f->node.nb_nodes > 0) f->node.define_flag = 1; - w = scf_lex_word_clone(f->node.w); - if (!w) - return -ENOMEM; - w->type = SCF_LEX_WORD_ID; + if (!f->vargs_flag) { + for (i = 0; i < f->argv->size; i++) { + arg = f->argv->data[i]; + + if (!strcmp(arg->w->text->data, "arguments")) + break; + } + + assert(0 == scf_vector_del(f->argv, arg)); + assert(0 == scf_vector_del(f->scope->vars, arg)); + + assert(2 == arg->refs); + arg->refs = 1; + + scf_variable_free(arg); + arg = NULL; + } + + for (i = fd->start_word; i < words->size; i++) { + w = words->data[i]; + + if (!f->src_code) { + f->src_code = scf_string_clone(w->text); + if (!f->src_code) + return -ENOMEM; + } else { + int ret = scf_string_cat_cstr_len(f->src_code, " ", 1); + if (ret < 0) + return ret; + + ret = scf_string_cat(f->src_code, w->text); + if (ret < 0) + return ret; + } + } + + w = dfa->ops->pop_word(dfa); dfa->ops->push_word(dfa, w); + switch (w->type) { + case SCF_LEX_WORD_SEMICOLON: + case SCF_LEX_WORD_COMMA: + case SCF_LEX_WORD_LP: + w = scf_lex_word_clone(f->node.w); + if (!w) + return -ENOMEM; + w->type = SCF_LEX_WORD_ID; + + dfa->ops->push_word(dfa, w); + break; + default: + break; + }; + d->expr = fd->parent_expr; fd->parent_expr = NULL; fd->parent_block = NULL; @@ -281,12 +354,11 @@ static int _function_js_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* da static int _dfa_init_module_function_js(scf_dfa_t* dfa) { SCF_DFA_MODULE_NODE(dfa, function_js, comma, scf_dfa_is_comma, _function_js_action_comma); - SCF_DFA_MODULE_NODE(dfa, function_js, vargs, scf_dfa_is_vargs, _function_js_action_vargs); SCF_DFA_MODULE_NODE(dfa, function_js, end, scf_dfa_is_entry, _function_js_action_end); SCF_DFA_MODULE_NODE(dfa, function_js, lp, scf_dfa_is_lp, _function_js_action_lp); SCF_DFA_MODULE_NODE(dfa, function_js, rp, scf_dfa_is_rp, _function_js_action_rp); - SCF_DFA_MODULE_NODE(dfa, function_js, func, scf_dfa_is_func, scf_dfa_action_next); + SCF_DFA_MODULE_NODE(dfa, function_js, func, scf_dfa_is_func, _function_js_action_func); SCF_DFA_MODULE_NODE(dfa, function_js, fname, scf_dfa_is_identity, scf_dfa_action_next); SCF_DFA_MODULE_NODE(dfa, function_js, arg, scf_dfa_is_identity, scf_dfa_action_next); @@ -325,7 +397,6 @@ static int _dfa_fini_module_function_js(scf_dfa_t* dfa) static int _dfa_init_syntax_function_js(scf_dfa_t* dfa) { SCF_DFA_GET_MODULE_NODE(dfa, function_js, comma, comma); - SCF_DFA_GET_MODULE_NODE(dfa, function_js, vargs, vargs); SCF_DFA_GET_MODULE_NODE(dfa, function_js, lp, lp); SCF_DFA_GET_MODULE_NODE(dfa, function_js, rp, rp); @@ -350,9 +421,6 @@ static int _dfa_init_syntax_function_js(scf_dfa_t* dfa) scf_dfa_node_add_child(comma, arg); scf_dfa_node_add_child(arg, rp); - scf_dfa_node_add_child(comma, vargs); - scf_dfa_node_add_child(vargs, rp); - // function_js body scf_dfa_node_add_child(rp, block); diff --git a/js/parse/scf_dfa_init_data.c b/js/parse/scf_dfa_init_data.c index 67b9d8f..2eb7808 100644 --- a/js/parse/scf_dfa_init_data.c +++ b/js/parse/scf_dfa_init_data.c @@ -6,7 +6,7 @@ extern scf_dfa_module_t dfa_module_init_data; int scf_object_init(scf_ast_t* ast, scf_lex_word_t* w, scf_variable_t* var, scf_variable_t* obj, scf_vector_t* init_exprs); -int _class_calculate_size(scf_dfa_t* dfa, scf_type_t* s); +int _class_calculate_size(scf_type_t* s); int _expr_add_var(scf_parse_t* parse, dfa_data_t* d); @@ -532,7 +532,7 @@ static int _data_action_rb(scf_dfa_t* dfa, scf_vector_t* words, void* data) if (ret < 0) goto error; - ret = _class_calculate_size(dfa, t); + ret = _class_calculate_size(t); if (ret < 0) goto error; @@ -652,7 +652,7 @@ static int _data_action_rs(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_variable_free(obj); obj = NULL; - return SCF_DFA_NEXT_WORD; + return SCF_DFA_SWITCH_TO; } static int _dfa_init_module_init_data(scf_dfa_t* dfa) @@ -662,8 +662,8 @@ static int _dfa_init_module_init_data(scf_dfa_t* dfa) SCF_DFA_MODULE_NODE(dfa, init_data, colon, scf_dfa_is_colon, scf_dfa_action_next); SCF_DFA_MODULE_NODE(dfa, init_data, comma, scf_dfa_is_comma, _data_action_comma); - SCF_DFA_MODULE_NODE(dfa, init_data, func, scf_dfa_is_func, _data_action_func); - SCF_DFA_MODULE_NODE(dfa, init_data, func_end, scf_dfa_is_entry, _data_action_func_end); +// SCF_DFA_MODULE_NODE(dfa, init_data, func, scf_dfa_is_func, _data_action_func); +// SCF_DFA_MODULE_NODE(dfa, init_data, func_end, scf_dfa_is_entry, _data_action_func_end); SCF_DFA_MODULE_NODE(dfa, init_data, lb, scf_dfa_is_lb, _data_action_lb); SCF_DFA_MODULE_NODE(dfa, init_data, rb, scf_dfa_is_rb, _data_action_rb); @@ -692,8 +692,8 @@ static int _dfa_init_syntax_init_data(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, init_data, comma, comma); SCF_DFA_GET_MODULE_NODE(dfa, init_data, colon, colon); SCF_DFA_GET_MODULE_NODE(dfa, init_data, member, member); - SCF_DFA_GET_MODULE_NODE(dfa, init_data, func, func); - SCF_DFA_GET_MODULE_NODE(dfa, init_data, func_end, func_end); +// SCF_DFA_GET_MODULE_NODE(dfa, init_data, func, func); +// SCF_DFA_GET_MODULE_NODE(dfa, init_data, func_end, func_end); SCF_DFA_GET_MODULE_NODE(dfa, init_data, lb, lb); SCF_DFA_GET_MODULE_NODE(dfa, init_data, rb, rb); @@ -727,12 +727,12 @@ static int _dfa_init_syntax_init_data(scf_dfa_t* dfa) scf_dfa_node_add_child(lb, member); scf_dfa_node_add_child(member, colon); - // init member function() - scf_dfa_node_add_child(colon, func); - scf_dfa_node_add_child(func, func_js); - scf_dfa_node_add_child(func_end, comma); - scf_dfa_node_add_child(func_end, member); - scf_dfa_node_add_child(func_end, rb); +// // init member function() +// scf_dfa_node_add_child(colon, func); +// scf_dfa_node_add_child(func, func_js); +// scf_dfa_node_add_child(func_end, comma); +// scf_dfa_node_add_child(func_end, member); +// scf_dfa_node_add_child(func_end, rb); scf_dfa_node_add_child(colon, expr); scf_dfa_node_add_child(expr, comma); diff --git a/js/parse/scf_dfa_switch.c b/js/parse/scf_dfa_switch.c index fa22c3a..331236a 100644 --- a/js/parse/scf_dfa_switch.c +++ b/js/parse/scf_dfa_switch.c @@ -17,6 +17,9 @@ typedef struct { } dfa_switch_data_t; +int _expr_add_var(scf_parse_t* parse, dfa_data_t* d); + + static int _switch_is_end(scf_dfa_t* dfa, void* word) { return 1; @@ -58,7 +61,7 @@ static int _switch_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) dfa_data_t* d = data; assert(!d->expr); - d->expr_local_flag = 1; + d->expr_local_flag++; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "switch_rp"), SCF_DFA_HOOK_POST); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "switch_lp_stat"), SCF_DFA_HOOK_POST); @@ -99,7 +102,7 @@ static int _switch_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_node_add_child(sd->_switch, d->expr); d->expr = NULL; - d->expr_local_flag = 0; + assert(--d->expr_local_flag >= 0); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "switch_end"), SCF_DFA_HOOK_END); @@ -121,7 +124,7 @@ static int _switch_action_case(scf_dfa_t* dfa, scf_vector_t* words, void* data) dfa_switch_data_t* sd = scf_stack_top(s); assert(!d->expr); - d->expr_local_flag = 1; + d->expr_local_flag++; sd->child = scf_node_alloc(w, SCF_OP_CASE, NULL); if (!sd->child) @@ -129,6 +132,8 @@ static int _switch_action_case(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_node_add_child((scf_node_t*)parse->ast->current_block, sd->child); + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "switch_colon"), SCF_DFA_HOOK_PRE); + return SCF_DFA_NEXT_WORD; } @@ -165,9 +170,16 @@ static int _switch_action_colon(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } + dfa_identity_t* id = scf_stack_top(d->current_identities); + + if (id && id->identity) { + if (_expr_add_var(parse, d) < 0) + return SCF_DFA_ERROR; + } + scf_node_add_child(sd->child, d->expr); d->expr = NULL; - d->expr_local_flag = 0; + assert(--d->expr_local_flag >= 0); } else { assert(SCF_OP_DEFAULT == sd->child->type); diff --git a/js/parse/scf_operator_handler_semantic.c b/js/parse/scf_operator_handler_semantic.c index c4ce9ad..91aecdf 100644 --- a/js/parse/scf_operator_handler_semantic.c +++ b/js/parse/scf_operator_handler_semantic.c @@ -1563,6 +1563,75 @@ static int __scf_op_semantic_call(scf_ast_t* ast, scf_function_t* f, void* data) return 0; } +static int _semantic_add_this(scf_ast_t* ast, scf_function_t* f, scf_node_t* parent) +{ + scf_variable_t* v; + scf_type_t* t; + scf_node_t* this; + scf_node_t* p = parent->nodes[0]; + + while (p && SCF_OP_EXPR == p->type) + p = p->nodes[0]; + + if (SCF_OP_POINTER == p->type) { + assert(2 == p->nb_nodes); + + this = p->nodes[0]; + } else { + int ret = scf_ast_find_variable(&v, ast, "document"); + if (ret < 0) + return ret; + + this = scf_node_alloc(NULL, v->type, v); + } + + if (!this) + return -ENOMEM; + scf_node_add_child(parent, this); + + scf_logi("f: %s(), this: %p, p->type: %d\n", f->node.w->text->data, this, p->type); + + int i; + for (i = parent->nb_nodes - 2; i >= 1; i--) + parent->nodes[i + 1] = parent->nodes[i]; + parent->nodes[1] = this; + + if (SCF_OP_POINTER == p->type) { + for (i = 0; i < p->parent->nb_nodes; i++) { + if (p->parent->nodes[i] == p) { + p->parent->nodes[i] = p->nodes[1]; + p->nodes[1]->parent = p->parent; + break; + } + } + + p->nodes[0] = NULL; + p->nodes[1] = NULL; + + scf_node_free(p); + p = NULL; + } + + if (f->js_flag) { + p = parent->nodes[0]; + while (p && SCF_OP_EXPR == p->type) + p = p->nodes[0]; + + t = scf_block_find_type_type(ast->current_block, SCF_FUNCTION_PTR); + v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f); + if (!v) + return -ENOMEM; + v->const_literal_flag = 1; + + scf_node_free_data(p); + + p->type = SCF_FUNCTION_PTR; + p->var = v; + } + + return 0; +} + static int _scf_op_semantic_call(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { assert(nb_nodes > 0); @@ -1571,13 +1640,11 @@ static int _scf_op_semantic_call(scf_ast_t* ast, scf_node_t** nodes, int nb_node scf_variable_t** pret = d->pret; scf_variable_t* v0; scf_variable_t* v1; - scf_variable_t* v; scf_function_t* f; scf_type_t* t; scf_type_t* Object = NULL; scf_node_t* parent = nodes[0]->parent; - scf_node_t* p; - scf_node_t* this; + int i; d->pret = &nodes[0]->result; int ret = _scf_expr_calculate_internal(ast, nodes[0], d); @@ -1607,74 +1674,48 @@ static int _scf_op_semantic_call(scf_ast_t* ast, scf_node_t** nodes, int nb_node f = v0->func_ptr; - if (f->member_flag) { // add 'this' pointer for member function - p = nodes[0]; - - while (p && SCF_OP_EXPR == p->type) - p = p->nodes[0]; - - if (SCF_OP_POINTER == p->type) { - assert(2 == p->nb_nodes); - - this = p->nodes[0]; - - scf_node_add_child(parent, this); - - int i; - for (i = parent->nb_nodes - 2; i >= 1; i--) - parent->nodes[i + 1] = parent->nodes[i]; - parent->nodes[1] = this; - - for (i = 0; i < p->parent->nb_nodes; i++) { - if (p->parent->nodes[i] == p) { - p->parent->nodes[i] = p->nodes[1]; - p->nodes[1]->parent = p->parent; - break; - } - } - - p->nodes[0] = NULL; - p->nodes[1] = NULL; - - scf_node_free(p); - p = NULL; - } else { - ret = scf_ast_find_variable(&v, ast, "document"); + if (f->member_flag) { + if (!parent->this_done) { // add 'this' pointer for member function + ret = _semantic_add_this(ast, f, parent); if (ret < 0) return ret; + parent->this_done = 1; + } - if (nb_nodes < 2 || _scf_operand_get(nodes[1]) != v) { - - this = scf_node_alloc(NULL, v->type, v); - if (!this) - return -ENOMEM; + if (!f->js_flag) { + t = NULL; + v1 = _scf_operand_get(parent->nodes[1]); - scf_node_add_child(parent, this); + ret = scf_ast_find_type_type(&t, ast, v1->type); + if (ret < 0) + return ret; - int i; - for (i = parent->nb_nodes - 2; i >= 1; i--) - parent->nodes[i + 1] = parent->nodes[i]; - parent->nodes[1] = this; + scf_vector_t* argv = scf_vector_alloc(); + if (!argv) + return -ENOMEM; - scf_logi("f: %s(), this: %p, p->type: %d\n", f->node.w->text->data, this, p->type); + for (i = 1; i < parent->nb_nodes; i++) { + ret = scf_vector_add(argv, _scf_operand_get(parent->nodes[i])); + if (ret < 0) { + scf_vector_free(argv); + return ret; + } } - } - if (f->js_flag) { - p = parent->nodes[0]; - while (p && SCF_OP_EXPR == p->type) - p = p->nodes[0]; + scf_function_t* f2 = NULL; - t = scf_block_find_type_type(ast->current_block, SCF_FUNCTION_PTR); - v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f); - if (!v) - return -ENOMEM; - v->const_literal_flag = 1; + ret = _semantic_find_proper_function(ast, t, f->node.w->text->data, argv, &f2); - scf_node_free_data(p); + scf_vector_free(argv); + argv = NULL; + if (ret < 0) { + scf_loge("function '%s()' of class '%s' not found\n", f->node.w->text->data, t->name->data); + return ret; + } - p->type = SCF_FUNCTION_PTR; - p->var = v; + v0 = _scf_operand_get(parent->nodes[0]); + f = f2; + v0->func_ptr = f2; } } @@ -1684,16 +1725,29 @@ static int _scf_op_semantic_call(scf_ast_t* ast, scf_node_t** nodes, int nb_node f->node.w->text->data, f->argv->size, parent->nb_nodes - 1, parent->w->file->data, parent->w->line); return -1; } + + } else if (f->argv->size == parent->nb_nodes - 2 && f->js_flag && !f->vargs_flag) { + scf_node_t* arguments = parent->nodes[2]; + + for (i = 3; i < parent->nb_nodes; i++) + parent->nodes[i - 1] = parent->nodes[i]; + parent->nodes[i - 1] = NULL; + parent->nb_nodes--; + + assert(arguments->js_create); + arguments->js_create->_3ac_done = 1; + + scf_node_free(arguments); + arguments = NULL; + } else if (f->argv->size != parent->nb_nodes - 1) { scf_loge("number of args pass to '%s()' needs %d, real: %d, file: %s, line: %d\n", f->node.w->text->data, f->argv->size, parent->nb_nodes - 1, parent->w->file->data, parent->w->line); - assert(0); return -1; } scf_logi("f: %s, f->argv->size: %d, nb_nodes: %d\n", f->node.w->text->data, f->argv->size, parent->nb_nodes); - int i; for (i = 0; i < f->argv->size; i++) { v0 = f->argv->data[i]; @@ -2785,6 +2839,63 @@ static int _semantic_multi_rets_assign(scf_ast_t* ast, scf_node_t** nodes, int n return 0; } +static scf_variable_t* __object_func_ptr(scf_node_t* p) +{ + while (SCF_OP_EXPR == p->type) + p = p->nodes[0]; + + if (SCF_OP_ARRAY_INDEX == p->type || SCF_OP_POINTER == p->type) { + assert(2 == p->nb_nodes); + + p = p->nodes[1]; + + while (SCF_OP_EXPR == p->type) + p = p->nodes[0]; + } + + if (!scf_type_is_var(p->type)) + return NULL; + + if (p->var->js_var) + return p->var->js_var; + return p->var; +} + +static scf_node_t* __object_func_src(scf_ast_t* ast, scf_function_t* f) +{ + scf_node_t* node; + scf_type_t* t = scf_block_find_type_type(ast->current_block, SCF_VAR_CHAR); + scf_variable_t* v; + scf_lex_word_t* w = scf_lex_word_clone(f->node.w); + + if (!w) + return NULL; + + int ret = scf_string_cat_cstr(w->text, "__cstr"); + if (ret < 0) { + scf_lex_word_free(w); + return NULL; + } + + v = SCF_VAR_ALLOC_BY_TYPE(w, t, 1, 1, NULL); + scf_lex_word_free(w); + w = NULL; + if (!v) + return NULL; + + v->data.s = scf_string_clone(f->src_code); + if (!v->data.s) { + scf_variable_free(v); + return NULL; + } + v->const_literal_flag = 1; + + node = scf_node_alloc(NULL, v->type, v); + scf_variable_free(v); + v = NULL; + return node; +} + static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { assert(2 == nb_nodes); @@ -2825,8 +2936,8 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no return _semantic_multi_rets_assign(ast, nodes, nb_nodes, data); } - scf_variable_t* v0 = _scf_operand_get(nodes[0]); - scf_variable_t* v1 = _scf_operand_get(nodes[1]); + scf_variable_t* v0 = _scf_operand_get(nodes[0]); + scf_variable_t* v1 = _scf_operand_get(nodes[1]); assert(v0); assert(v1); @@ -2898,22 +3009,52 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no return -1; } + scf_type_t* t = NULL; + scf_type_t* t1 = NULL; + + int ret = scf_ast_find_type_type(&t, ast, v0->type); + if (ret < 0) + return ret; + + if (!strcmp(t->name->data, "Object")) { + ret = scf_ast_find_type_type(&t1, ast, v1->type); + if (ret < 0) + return ret; + + scf_variable_t* pf0 = __object_func_ptr(nodes[0]); + scf_variable_t* pf1; + + if (!strcmp(t1->name->data, "Object")) + pf1 = __object_func_ptr(nodes[1]); + else + pf1 = v1; + + if (pf0 && pf1 && SCF_FUNCTION_PTR == pf1->type) { + pf0->func_ptr = pf1->func_ptr; + + scf_logd("---- pf1: %s()\n", pf1->w->text->data); + } + } + if (!scf_variable_same_type(v0, v1)) { if (scf_variable_is_struct_pointer(v0) && v1->w && strcmp(v1->w->text->data, "NULL")) { - scf_type_t* t = NULL; - int ret = scf_ast_find_type_type(&t, ast, v0->type); - if (ret < 0) - return ret; - assert(t); + if (!strcmp(t->name->data, "Object") && SCF_FUNCTION_PTR == v1->type) { + scf_node_t* node = __object_func_src(ast, v1->func_ptr); + if (!node) + return -ENOMEM; + + scf_node_free(nodes[1]); + nodes[1] = node; + node->parent = parent; - if (!strcmp(t->name->data, "Object") && SCF_FUNCTION_PTR == v1->type) - v0->func_ptr = v1->func_ptr; + v1 = _scf_operand_get(nodes[1]); + } if (scf_scope_find_function(t->scope, "__init")) { - int ret = _semantic_do_create(ast, nodes, nb_nodes, d); + ret = _semantic_do_create(ast, nodes, nb_nodes, d); if (0 == ret) return 0; @@ -2931,15 +3072,15 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no return -1; } - int ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); + ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); if (ret < 0) { scf_loge("add type cast failed\n"); return ret; } } - scf_type_t* t = NULL; - int ret = scf_ast_find_type_type(&t, ast, v0->type); + t = NULL; + ret = scf_ast_find_type_type(&t, ast, v0->type); if (ret < 0) return ret; diff --git a/js/parse/scf_parse.h b/js/parse/scf_parse.h index aa89b4c..e7c0cb7 100644 --- a/js/parse/scf_parse.h +++ b/js/parse/scf_parse.h @@ -83,8 +83,7 @@ struct dfa_data_s { scf_lex_word_t* current_assign_w; scf_lex_word_t* current_async_w; - scf_type_t* root_struct; - scf_type_t* current_struct; + scf_block_t* parent_block; scf_node_t* current_node; diff --git a/ui/Makefile b/ui/Makefile index fade274..04d6fc5 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -156,6 +156,8 @@ CFILES += ../js/core/scf_pointer_alias.c CFILES += ../js/core/scf_optimizer.c CFILES += ../js/core/scf_optimizer_dag.c CFILES += ../js/core/scf_optimizer_inline.c +CFILES += ../js/core/scf_optimizer_js_array.c +CFILES += ../js/core/scf_optimizer_js_call.c CFILES += ../js/core/scf_optimizer_split_call.c CFILES += ../js/core/scf_optimizer_call.c CFILES += ../js/core/scf_optimizer_common_expr.c -- 2.25.1