From: yu.dongliang <18588496441@163.com> Date: Thu, 25 Sep 2025 13:47:39 +0000 (+0800) Subject: js: support variable args of js function() with 'arguments[]' array X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=00f068fb903ca968c37912f749fddc688614a454;p=abc.git js: support variable args of js function() with 'arguments[]' array --- 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 cb2894b..60fb561 100755 Binary files a/js/abc_libjs.so and b/js/abc_libjs.so differ 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