From 9b850772fcfcb823a4af30b6e7a66f60b5e8fb75 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Wed, 10 Dec 2025 12:22:12 +0800 Subject: [PATCH] js: support 'for..in..' --- examples/js.html | 12 +- js/core/scf_block.c | 65 +- js/core/scf_lex_word.h | 1 + js/core/scf_node.h | 4 + js/core/scf_operator_handler_3ac.c | 26 +- js/core/scf_optimizer_auto_gc.c | 4 + js/core/scf_pointer_alias.c | 12 +- js/doc.c | 1 + js/lex/scf_lex.c | 1 + js/native/risc/scf_risc.c | 21 +- js/native/x64/scf_x64.c | 21 +- js/parse/scf_dfa_block.c | 6 +- js/parse/scf_dfa_expr.c | 5 +- js/parse/scf_dfa_for.c | 904 +++++++++++++++++++---- js/parse/scf_dfa_util.h | 7 + js/parse/scf_dfa_var.c | 3 + js/parse/scf_operator_handler_const.c | 21 +- js/parse/scf_operator_handler_semantic.c | 47 +- js/parse/scf_parse.c | 6 +- js/parse/scf_parse_util.c | 38 - 20 files changed, 923 insertions(+), 282 deletions(-) diff --git a/examples/js.html b/examples/js.html index c6906ac..234458c 100644 --- a/examples/js.html +++ b/examples/js.html @@ -8,10 +8,14 @@ diff --git a/js/core/scf_block.c b/js/core/scf_block.c index cf39598..5461b0d 100644 --- a/js/core/scf_block.c +++ b/js/core/scf_block.c @@ -104,7 +104,10 @@ scf_variable_t* scf_block_find_variable(scf_block_t* b, const char* name) { assert(b); while (b) { - if (SCF_OP_BLOCK == b->node.type || SCF_FUNCTION == b->node.type || b->node.type >= SCF_STRUCT) { + if (SCF_OP_BLOCK == b->node.type + || SCF_OP_FOR == b->node.type + || SCF_FUNCTION == b->node.type + || b->node.type >= SCF_STRUCT) { if (b->scope) { scf_variable_t* v = scf_scope_find_variable(b->scope, name); @@ -151,3 +154,63 @@ scf_label_t* scf_block_find_label(scf_block_t* b, const char* name) } return NULL; } + +int __find_local_vars(scf_node_t* node, void* arg, scf_vector_t* results) +{ + if (SCF_OP_BLOCK == node->type || SCF_OP_FOR == node->type || SCF_FUNCTION == node->type) { + + scf_variable_t* v; + scf_block_t* b = (scf_block_t*)node; + int i; + + if (b->scope) { + for (i = 0; i < b->scope->vars->size; i++) { + v = b->scope->vars->data[i]; + + int ret = scf_vector_add(results, v); + if (ret < 0) + return ret; + } + } + } + return 0; +} + +int __find_function(scf_node_t* node, void* arg, scf_vector_t* results) +{ + if (SCF_FUNCTION == node->type) { + + scf_function_t* f = (scf_function_t*)node; + + return scf_vector_add(results, f); + } + + return 0; +} + +int __find_global_var(scf_node_t* node, void* arg, scf_vector_t* results) +{ + if (SCF_OP_BLOCK == node->type + || (node->type >= SCF_STRUCT && node->class_flag)) { + + scf_variable_t* v; + scf_block_t* b = (scf_block_t*)node; + int i; + + if (!b->scope || !b->scope->vars) + return 0; + + for (i = 0; i < b->scope->vars->size; i++) { + v = b->scope->vars->data[i]; + + if (v->global_flag || v->static_flag) { + + int ret = scf_vector_add(results, v); + if (ret < 0) + return ret; + } + } + } + + return 0; +} diff --git a/js/core/scf_lex_word.h b/js/core/scf_lex_word.h index 1d05618..17ac40d 100644 --- a/js/core/scf_lex_word.h +++ b/js/core/scf_lex_word.h @@ -90,6 +90,7 @@ enum scf_lex_words SCF_LEX_WORD_KEY_ELSE, // else SCF_LEX_WORD_KEY_FOR, // for + SCF_LEX_WORD_KEY_IN, // in SCF_LEX_WORD_KEY_DO, // do SCF_LEX_WORD_KEY_WHILE, // while diff --git a/js/core/scf_node.h b/js/core/scf_node.h index 92ec397..946298c 100644 --- a/js/core/scf_node.h +++ b/js/core/scf_node.h @@ -84,6 +84,10 @@ scf_function_t* _scf_function_get(scf_node_t* node); typedef int (*scf_node_find_pt)(scf_node_t* node, void* arg, scf_vector_t* results); int scf_node_search_bfs(scf_node_t* root, void* arg, scf_vector_t* results, int max, scf_node_find_pt find); +int __find_local_vars(scf_node_t* node, void* arg, scf_vector_t* results); +int __find_global_var(scf_node_t* node, void* arg, scf_vector_t* results); +int __find_function (scf_node_t* node, void* arg, scf_vector_t* results); + scf_label_t* scf_label_alloc(scf_lex_word_t* w); void scf_label_free(scf_label_t* l); diff --git a/js/core/scf_operator_handler_3ac.c b/js/core/scf_operator_handler_3ac.c index 0b04e66..3d31a07 100644 --- a/js/core/scf_operator_handler_3ac.c +++ b/js/core/scf_operator_handler_3ac.c @@ -1289,17 +1289,23 @@ static int _scf_op_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* d scf_list_t* start_prev = scf_list_tail(d->_3ac_list_head); scf_3ac_code_t* jmp_end = NULL; - if (nodes[1]) { - assert(SCF_OP_EXPR == nodes[1]->type); - - int jmp_op = _scf_op_cond(ast, nodes[1], d); - if (jmp_op < 0) { + scf_node_t* cond = nodes[1]; + if (cond) { + if (_scf_op_node(ast, cond, d) < 0) { scf_loge("\n"); return -1; } - jmp_end = scf_3ac_jmp_code(jmp_op, NULL, NULL); - scf_list_add_tail(d->_3ac_list_head, &jmp_end->list); + if (cond->nb_nodes > 0) { + int jmp_op = _scf_op_cond(ast, cond->nodes[cond->nb_nodes - 1], d); + if (jmp_op < 0) { + scf_loge("\n"); + return -1; + } + + jmp_end = scf_3ac_jmp_code(jmp_op, NULL, NULL); + scf_list_add_tail(d->_3ac_list_head, &jmp_end->list); + } } scf_branch_ops_t* local_branch_ops = scf_branch_ops_alloc(); @@ -1677,11 +1683,7 @@ 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_node_t* parent = nodes[0]->parent; - - if (parent->_3ac_done) - return 0; + scf_handler_data_t* d = data; int ret = _scf_expr_calculate_internal(ast, nodes[0], d); if (ret < 0) diff --git a/js/core/scf_optimizer_auto_gc.c b/js/core/scf_optimizer_auto_gc.c index afd61f2..aa0aa91 100644 --- a/js/core/scf_optimizer_auto_gc.c +++ b/js/core/scf_optimizer_auto_gc.c @@ -873,6 +873,8 @@ ref: if (cur_bb != bb) { scf_list_del(&c->list); scf_list_add_tail(&cur_bb->code_list_head, &c->list); + + c->basic_block = cur_bb; } ret = _auto_gc_bb_ref(ds_obj, ds_malloced, ast, f, &cur_bb); @@ -894,6 +896,8 @@ end: if (cur_bb != bb) { scf_list_del(&c->list); scf_list_add_tail(&cur_bb->code_list_head, &c->list); + + c->basic_block = cur_bb; } } diff --git a/js/core/scf_pointer_alias.c b/js/core/scf_pointer_alias.c index 02af3c6..710d764 100644 --- a/js/core/scf_pointer_alias.c +++ b/js/core/scf_pointer_alias.c @@ -124,12 +124,18 @@ static int _bb_pointer_initeds(scf_vector_t* initeds, scf_list_t* bb_list_head, dn = ds->dag_node; v = dn->var; + if (ds->dn_indexes) + return 0; + if (scf_variable_const(v) || scf_variable_const_string(v)) return 0; if (v->arg_flag) return 0; + if (v->tmp_flag) + return 0; + if (v->global_flag) { if (v->nb_pointers > 0) scf_logw("global pointer '%s' is not inited, file: %s, line: %d\n", v->w->text->data, v->w->file->data, v->w->line); @@ -147,12 +153,6 @@ static int _bb_pointer_initeds(scf_vector_t* initeds, scf_list_t* bb_list_head, return 0; } - if (ds->dn_indexes) - return 0; - - if (v->tmp_flag) - return 0; - if (SCF_OP_ADDRESS_OF != dn->type) { scf_loge("pointer '%s_%d_%d' is not inited, tmp_flag: %d, local_flag: %d, file: %s, line: %d\n", v->w->text->data, v->w->line, v->w->pos, v->tmp_flag, v->local_flag, v->w->file->data, v->w->line); diff --git a/js/doc.c b/js/doc.c index 2d320eb..6de9ccf 100644 --- a/js/doc.c +++ b/js/doc.c @@ -73,6 +73,7 @@ struct Object memcpy(this->str, s, len + 1); this->type = JS_String; + printf("this: %p, this->str: %s, s: %s\n\n", this, this->str, s); return 0; } diff --git a/js/lex/scf_lex.c b/js/lex/scf_lex.c index 2537116..a090615 100644 --- a/js/lex/scf_lex.c +++ b/js/lex/scf_lex.c @@ -7,6 +7,7 @@ static scf_key_word_t key_words[] = {"endif", SCF_LEX_WORD_KEY_ENDIF}, {"for", SCF_LEX_WORD_KEY_FOR}, + {"in", SCF_LEX_WORD_KEY_IN}, {"while", SCF_LEX_WORD_KEY_WHILE}, {"do", SCF_LEX_WORD_KEY_DO}, diff --git a/js/native/risc/scf_risc.c b/js/native/risc/scf_risc.c index 2915c98..d0b71d8 100644 --- a/js/native/risc/scf_risc.c +++ b/js/native/risc/scf_risc.c @@ -1079,25 +1079,6 @@ int _scf_risc_select_inst(scf_native_t* ctx) return 0; } -static int _find_local_vars(scf_node_t* node, void* arg, scf_vector_t* results) -{ - scf_block_t* b = (scf_block_t*)node; - - if ((SCF_OP_BLOCK == b->node.type || SCF_FUNCTION == b->node.type) && b->scope) { - - int i; - for (i = 0; i < b->scope->vars->size; i++) { - - scf_variable_t* var = b->scope->vars->data[i]; - - int ret = scf_vector_add(results, var); - if (ret < 0) - return ret; - } - } - return 0; -} - int scf_risc_select_inst(scf_native_t* ctx, scf_function_t* f) { scf_risc_context_t* risc = ctx->priv; @@ -1110,7 +1091,7 @@ int scf_risc_select_inst(scf_native_t* ctx, scf_function_t* f) if (!local_vars) return -ENOMEM; - int ret = scf_node_search_bfs((scf_node_t*)f, NULL, local_vars, -1, _find_local_vars); + int ret = scf_node_search_bfs((scf_node_t*)f, NULL, local_vars, -1, __find_local_vars); if (ret < 0) return ret; diff --git a/js/native/x64/scf_x64.c b/js/native/x64/scf_x64.c index 9d7da3b..ced05ba 100644 --- a/js/native/x64/scf_x64.c +++ b/js/native/x64/scf_x64.c @@ -1100,25 +1100,6 @@ int _scf_x64_select_inst(scf_native_t* ctx) return 0; } -static int _find_local_vars(scf_node_t* node, void* arg, scf_vector_t* results) -{ - scf_block_t* b = (scf_block_t*)node; - - if ((SCF_OP_BLOCK == b->node.type || SCF_FUNCTION == b->node.type) && b->scope) { - - int i; - for (i = 0; i < b->scope->vars->size; i++) { - - scf_variable_t* var = b->scope->vars->data[i]; - - int ret = scf_vector_add(results, var); - if (ret < 0) - return ret; - } - } - return 0; -} - int scf_x64_select_inst(scf_native_t* ctx, scf_function_t* f) { scf_x64_context_t* x64 = ctx->priv; @@ -1129,7 +1110,7 @@ int scf_x64_select_inst(scf_native_t* ctx, scf_function_t* f) if (!local_vars) return -ENOMEM; - int ret = scf_node_search_bfs((scf_node_t*)f, NULL, local_vars, -1, _find_local_vars); + int ret = scf_node_search_bfs((scf_node_t*)f, NULL, local_vars, -1, __find_local_vars); if (ret < 0) return ret; diff --git a/js/parse/scf_dfa_block.c b/js/parse/scf_dfa_block.c index 2afd08a..bf42d29 100644 --- a/js/parse/scf_dfa_block.c +++ b/js/parse/scf_dfa_block.c @@ -19,7 +19,7 @@ typedef struct { static int _block_action_entry(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; - dfa_data_t* d = data; + dfa_data_t* d = data; scf_stack_t* s = d->module_datas[dfa_module_block.index]; dfa_block_data_t* bd = scf_stack_top(s); @@ -75,7 +75,7 @@ static int _block_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) static int _block_action_lb(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; - dfa_data_t* d = data; + dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; scf_stack_t* s = d->module_datas[dfa_module_block.index]; @@ -109,7 +109,7 @@ static int _block_action_lb(scf_dfa_t* dfa, scf_vector_t* words, void* data) static int _block_action_rb(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; - dfa_data_t* d = data; + dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; scf_stack_t* s = d->module_datas[dfa_module_block.index]; dfa_block_data_t* bd = scf_stack_top(s); diff --git a/js/parse/scf_dfa_expr.c b/js/parse/scf_dfa_expr.c index ffde7f1..75337c1 100644 --- a/js/parse/scf_dfa_expr.c +++ b/js/parse/scf_dfa_expr.c @@ -909,7 +909,7 @@ int _expr_multi_rets(scf_expr_t* e) return 0; } -static int _expr_fini_expr(scf_parse_t* parse, dfa_data_t* d, int semi_flag) +int _expr_fini_expr(scf_parse_t* parse, dfa_data_t* d, int semi_flag) { expr_module_data_t* md = d->module_datas[dfa_module_expr.index]; dfa_identity_t* id = scf_stack_top(d->current_identities); @@ -1006,6 +1006,7 @@ static int _dfa_init_module_expr(scf_dfa_t* dfa) SCF_DFA_MODULE_NODE(dfa, expr, comma, scf_dfa_is_comma, _expr_action_comma); SCF_DFA_MODULE_NODE(dfa, expr, semicolon, scf_dfa_is_semicolon, _expr_action_semicolon); + SCF_DFA_MODULE_NODE(dfa, expr, in, scf_dfa_is_in, _expr_action_semicolon); scf_parse_t* parse = dfa->priv; dfa_data_t* d = parse->dfa_data; @@ -1079,6 +1080,7 @@ static int _dfa_init_syntax_expr(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, expr, comma, comma); SCF_DFA_GET_MODULE_NODE(dfa, expr, semicolon, semicolon); + SCF_DFA_GET_MODULE_NODE(dfa, expr, in, in); SCF_DFA_GET_MODULE_NODE(dfa, identity, identity, identity); SCF_DFA_GET_MODULE_NODE(dfa, call, lp, call_lp); @@ -1225,6 +1227,7 @@ static int _dfa_init_syntax_expr(scf_dfa_t* dfa) scf_dfa_node_add_child(identity, semicolon); scf_dfa_node_add_child(rs, semicolon); + scf_dfa_node_add_child(identity, in); return 0; } diff --git a/js/parse/scf_dfa_for.c b/js/parse/scf_dfa_for.c index 543c116..5e671fb 100644 --- a/js/parse/scf_dfa_for.c +++ b/js/parse/scf_dfa_for.c @@ -12,15 +12,22 @@ typedef struct { scf_block_t* parent_block; scf_node_t* parent_node; - scf_node_t* _for; + scf_block_t* _for; - int nb_semicolons; - scf_vector_t* init_exprs; - scf_expr_t* cond_expr; - scf_vector_t* update_exprs; + scf_block_t* init_exprs; + scf_block_t* cond_exprs; + scf_block_t* update_exprs; + + // for..in.. + scf_lex_word_t* in; + scf_variable_t* i; // loop index + scf_variable_t* member; + scf_expr_t* obj; + int nb_semicolons; } dfa_for_data_t; +int _expr_fini_expr(scf_parse_t* parse, dfa_data_t* d, int semi_flag); static int _for_is_end(scf_dfa_t* dfa, void* word) { @@ -30,28 +37,37 @@ static int _for_is_end(scf_dfa_t* dfa, void* word) static int _for_action_for(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]; dfa_for_data_t* fd = NULL; scf_stack_t* s = d->module_datas[dfa_module_for.index]; - scf_node_t* _for = scf_node_alloc(w, SCF_OP_FOR, NULL); + scf_block_t* _for = scf_block_alloc(w); if (!_for) return -ENOMEM; + _for->node.type = SCF_OP_FOR; + + int ret; + if (d->current_node) + ret = scf_node_add_child(d->current_node, (scf_node_t*) _for); + else + ret = scf_node_add_child((scf_node_t*)ast->current_block, (scf_node_t*) _for); + if (ret < 0) { + scf_block_free(_for); + return ret; + } fd = calloc(1, sizeof(dfa_for_data_t)); if (!fd) return -ENOMEM; - if (d->current_node) - scf_node_add_child(d->current_node, _for); - else - scf_node_add_child((scf_node_t*)parse->ast->current_block, _for); + fd->parent_block = ast->current_block; + fd->parent_node = d->current_node; + fd->_for = _for; + d->current_node = (scf_node_t*) _for; - fd->parent_block = parse->ast->current_block; - fd->parent_node = d->current_node; - fd->_for = _for; - d->current_node = _for; + ast->current_block = _for; scf_stack_push(s, fd); @@ -67,11 +83,10 @@ static int _for_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) dfa_for_data_t* fd = scf_stack_top(s); assert(!d->expr); - d->expr_local_flag = 1; +// d->expr_local_flag = 1; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_rp"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_semicolon"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_comma"), SCF_DFA_HOOK_POST); + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_semicolon"), SCF_DFA_HOOK_END); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_lp_stat"), SCF_DFA_HOOK_POST); return SCF_DFA_NEXT_WORD; @@ -90,142 +105,679 @@ static int _for_action_lp_stat(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_NEXT_WORD; } -static int _for_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* data) +static int _for_action_semicolon(scf_dfa_t* dfa, scf_vector_t* words, void* data) { + if (!data) + return SCF_DFA_ERROR; + scf_parse_t* parse = dfa->priv; dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; scf_stack_t* s = d->module_datas[dfa_module_for.index]; dfa_for_data_t* fd = scf_stack_top(s); + scf_block_t* b; + scf_node_t* node; + + int max = 1; + int i; + + if (SCF_LEX_WORD_KEY_IN == w->type) + fd->in = w; + + if (fd->in) + max = 0; - if (!d->expr) { - scf_loge("need expr before ',' in file: %s, line: %d\n", w->file->data, w->line); + if (fd->nb_semicolons > max) { + scf_loge("too many '%s' in for, file: %s, line: %d\n", w->text->data, w->file->data, w->line); return SCF_DFA_ERROR; } - switch (fd->nb_semicolons) { - case 0: - if (d->expr) { - if (!fd->init_exprs) - fd->init_exprs = scf_vector_alloc(); + b = scf_block_alloc(w); + if (!b) + return -ENOMEM; - scf_vector_add(fd->init_exprs, d->expr); - d->expr = NULL; - } - break; + SCF_XCHG(fd->_for->node.nb_nodes, b->node.nb_nodes); + SCF_XCHG(fd->_for->node.nodes, b->node.nodes); - case 1: - fd->cond_expr = d->expr; - d->expr = NULL; - break; + for (i = 0; i < b->node.nb_nodes; i++) { + node = b->node.nodes[i]; + node->parent = (scf_node_t*)b; + } - case 2: - if (d->expr) { - if (!fd->update_exprs) - fd->update_exprs = scf_vector_alloc(); + if (0 == fd->nb_semicolons) + fd->init_exprs = b; + else + fd->cond_exprs = b; - scf_vector_add(fd->update_exprs, d->expr); - d->expr = NULL; - } - break; - default: - scf_loge("too many ';' in for, file: %s, line: %d\n", w->file->data, w->line); - return SCF_DFA_ERROR; - break; - }; + fd->nb_semicolons++; - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_comma"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_lp_stat"), SCF_DFA_HOOK_POST); + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_semicolon"), SCF_DFA_HOOK_END); + SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_lp_stat"), SCF_DFA_HOOK_POST); - return SCF_DFA_NEXT_WORD; + return SCF_DFA_SWITCH_TO; } -static int _for_action_semicolon(scf_dfa_t* dfa, scf_vector_t* words, void* data) +static int __in_init_member(scf_expr_t** pe, scf_variable_t* member) { - if (!data) - return SCF_DFA_ERROR; + scf_variable_t* null; + scf_expr_t* e; + scf_node_t* node; - scf_parse_t* parse = dfa->priv; - dfa_data_t* d = data; - scf_lex_word_t* w = words->data[words->size - 1]; - scf_stack_t* s = d->module_datas[dfa_module_for.index]; - dfa_for_data_t* fd = scf_stack_top(s); + e = scf_expr_alloc(); + if (!e) + return -ENOMEM; - switch (fd->nb_semicolons) { - case 0: - if (d->expr) { - if (!fd->init_exprs) - fd->init_exprs = scf_vector_alloc(); + node = scf_node_alloc(NULL, member->type, member); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + int ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + node = scf_node_alloc(member->w, SCF_OP_ASSIGN, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '='; + node->w->text->data[1] = '\0'; + node->w->text->len = 1; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + null = scf_variable_clone(member); + if (!null) { + scf_expr_free(e); + return -ENOMEM; + } + + scf_string_free(null->w->text); + null->w->text = scf_string_cstr("NULL"); + if (!null->w->text) { + scf_variable_free(null); + scf_expr_free(e); + return -ENOMEM; + } + + assert(0 == null->nb_dimentions); + + null->type = SCF_VAR_U64; + null->nb_pointers = 0; + null->data.u64 = 0; + null->const_flag = 1; + null->const_literal_flag = 1; + + node = scf_node_alloc(NULL, null->type, null); + scf_variable_free(null); + null = NULL; + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + *pe = e; + return 0; +} + +static int __in_init_expr(scf_expr_t** pe, scf_variable_t* i) +{ + scf_variable_t* v0; + scf_expr_t* e; + scf_node_t* node; + + e = scf_expr_alloc(); + if (!e) + return -ENOMEM; + + node = scf_node_alloc(NULL, i->type, i); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + int ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + node = scf_node_alloc(i->w, SCF_OP_ASSIGN, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '='; + node->w->text->data[1] = '\0'; + node->w->text->len = 1; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + v0 = scf_variable_clone(i); + if (!v0) { + scf_expr_free(e); + return -ENOMEM; + } + v0->w->text->data[0] = '0'; + v0->w->text->data[1] = '\0'; + v0->w->text->len = 1; + + v0->data.u64 = 0; + v0->const_flag = 1; + v0->const_literal_flag = 1; + + node = scf_node_alloc(NULL, v0->type, v0); + scf_variable_free(v0); + v0 = NULL; + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + *pe = e; + return 0; +} + +static int __in_update_expr(scf_expr_t** pe, scf_variable_t* i) +{ + scf_expr_t* e; + scf_node_t* node; + + e = scf_expr_alloc(); + if (!e) + return -ENOMEM; + + node = scf_node_alloc(NULL, i->type, i); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + int ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + node = scf_node_alloc(i->w, SCF_OP_INC, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '+'; + node->w->text->data[1] = '+'; + node->w->text->data[2] = '\0'; + node->w->text->len = 2; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + *pe = e; + return 0; +} + +static int __in_cond_expr(scf_expr_t** pe, scf_variable_t* i, scf_type_t* t, scf_ast_t* ast, scf_block_t* update_exprs) +{ + scf_variable_t* vlen; + scf_expr_t* e; + scf_expr_t* e2; + scf_node_t* node; + scf_node_t* lt; + scf_node_t* dot; + scf_node_t* len; + scf_type_t* Object = NULL; + + int ret = scf_ast_find_type(&Object, ast, "Object"); + if (ret < 0) + return ret; + + vlen = scf_scope_find_variable(Object->scope, "length"); + assert(vlen); + + e = scf_expr_alloc(); + if (!e) + return -ENOMEM; + + node = scf_node_alloc(NULL, i->type, i); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + lt = scf_node_alloc(i->w, SCF_OP_LT, NULL); + if (!lt) { + scf_expr_free(e); + return -ENOMEM; + } + lt->w->text->data[0] = '<'; + lt->w->text->data[1] = '\0'; + lt->w->text->len = 1; + + ret = scf_expr_add_node(e, lt); + if (ret < 0) { + scf_node_free(lt); + scf_expr_free(e); + return ret; + } + + dot = scf_node_alloc(i->w, SCF_OP_POINTER, NULL); + if (!dot) { + scf_expr_free(e); + return -ENOMEM; + } + dot->w->text->data[0] = '.'; + dot->w->text->data[1] = '\0'; + dot->w->text->len = 1; + + e2 = update_exprs->node.nodes[0]; + + ret = scf_node_add_child(dot, e2); + if (ret < 0) { + scf_node_free(dot); + scf_expr_free(e); + return ret; + } + update_exprs->node.nodes[0] = NULL; + update_exprs->node.nb_nodes = 0; + e2 = NULL; + + len = scf_node_alloc(NULL, vlen->type, vlen); + if (!len) { + scf_node_free(dot); + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_node_add_child(dot, len); + if (ret < 0) { + scf_node_free(len); + scf_node_free(dot); + scf_expr_free(e); + return ret; + } - scf_vector_add(fd->init_exprs, d->expr); - d->expr = NULL; + ret = scf_expr_add_node(e, dot); + if (ret < 0) { + scf_node_free(dot); + scf_expr_free(e); + return ret; + } + + *pe = e; + return 0; +} + +static int __in_member_expr(scf_expr_t** pe, dfa_for_data_t* fd, scf_ast_t* ast) +{ + scf_variable_t* members; + scf_variable_t* name; + scf_expr_t* e; + scf_expr_t* e2; + scf_node_t* node; + scf_type_t* Object = NULL; + + int ret = scf_ast_find_type(&Object, ast, "Object"); + if (ret < 0) + return ret; + + members = scf_scope_find_variable(Object->scope, "members"); + name = scf_scope_find_variable(Object->scope, "name"); + + assert(members); + assert(name); + + // member = obj.members[i].name + e = scf_expr_alloc(); + if (!e) + return -ENOMEM; + + // add member + node = scf_node_alloc(NULL, fd->member->type, fd->member); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add = + node = scf_node_alloc(fd->in, SCF_OP_ASSIGN, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '='; + node->w->text->data[1] = '\0'; + node->w->text->len = 1; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add obj + e2 = scf_expr_clone(fd->obj); + if (!e2) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, e2); + if (ret < 0) { + scf_expr_free(e2); + scf_expr_free(e); + return ret; + } + + // add . + node = scf_node_alloc(fd->in, SCF_OP_POINTER, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '.'; + node->w->text->data[1] = '\0'; + node->w->text->len = 1; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add members + node = scf_node_alloc(NULL, members->type, members); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add [] + node = scf_node_alloc(fd->in, SCF_OP_ARRAY_INDEX, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '['; + node->w->text->data[1] = ']'; + node->w->text->data[2] = '\0'; + node->w->text->len = 2; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add i + node = scf_node_alloc(NULL, fd->i->type, fd->i); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add . + node = scf_node_alloc(fd->in, SCF_OP_POINTER, NULL); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + node->w->text->data[0] = '.'; + node->w->text->data[1] = '\0'; + node->w->text->len = 1; + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + // add name + node = scf_node_alloc(NULL, name->type, name); + if (!node) { + scf_expr_free(e); + return -ENOMEM; + } + + ret = scf_expr_add_node(e, node); + if (ret < 0) { + scf_node_free(node); + scf_expr_free(e); + return ret; + } + + *pe = e; + return 0; +} + +static int _for_in_exprs(dfa_for_data_t* fd, scf_ast_t* ast) +{ + scf_variable_t* i; + scf_expr_t* e; + scf_type_t* t; + scf_type_t* Object = NULL; + scf_node_t* node; + int ret; + + assert(0 == fd->_for->node.nb_nodes); + + switch (fd->init_exprs->node.nb_nodes) { + case 0: + if (fd->_for->scope->vars->size <= 0) { + scf_loge("one 'member' var can be used of 'for..in..', but real %d, file: %s, line: %d\n", + fd->init_exprs->node.nb_nodes, fd->in->file->data, fd->in->line); + goto error; } + + fd->member = fd->_for->scope->vars->data[0]; break; case 1: - fd->cond_expr = d->expr; - d->expr = NULL; + e = fd->init_exprs->node.nodes[0]; + + while (e && SCF_OP_EXPR == e->type) + e = e->nodes[0]; + + if (!scf_type_is_var(e->type)) { + scf_loge("'member' var MUST be an var of 'for..in..', but real is an expr, file: %s, line: %d\n", + fd->in->file->data, fd->in->line); + goto error; + } + + fd->member = e->var; break; default: - scf_loge("too many ';' in for, file: %s, line: %d\n", w->file->data, w->line); - return SCF_DFA_ERROR; + scf_loge("one 'member' var can be used of 'for..in..', but real %d, file: %s, line: %d\n", + fd->init_exprs->node.nb_nodes, fd->in->file->data, fd->in->line); + goto error; break; - } + }; - fd->nb_semicolons++; + if (1 == fd->update_exprs->node.nb_nodes) { + e = fd->update_exprs->node.nodes[0]; - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_semicolon"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_comma"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_lp_stat"), SCF_DFA_HOOK_POST); - - return SCF_DFA_SWITCH_TO; -} + fd->obj = e; + } else { + scf_loge("one 'object' var can be used of 'for..in..', but real %d, file: %s, line: %d\n", + fd->init_exprs->node.nb_nodes, fd->in->file->data, fd->in->line); + goto error; + } -static int _for_add_expr_vector(dfa_for_data_t* fd, scf_vector_t* vec) -{ - if (!vec) { - scf_node_add_child(fd->_for, NULL); - return SCF_DFA_OK; + t = scf_block_find_type_type(ast->current_block, SCF_VAR_INT); + i = SCF_VAR_ALLOC_BY_TYPE(fd->in, t, 0, 0, NULL); + if (!i) + goto error; + i->data.u64 = 0; + i->local_flag = 1; + scf_scope_push_var(fd->_for->scope, i); + + // init member + e = NULL; + ret = __in_init_member(&e, fd->member); + if (ret < 0) + goto error; + + ret = scf_node_add_child((scf_node_t*)fd->init_exprs, e); + if (ret < 0) { + scf_expr_free(e); + goto error; } + e = NULL; - if (0 == vec->size) { - scf_node_add_child(fd->_for, NULL); + // init expr + ret = __in_init_expr(&e, i); + if (ret < 0) + goto error; - scf_vector_free(vec); - vec = NULL; - return SCF_DFA_OK; + ret = scf_node_add_child((scf_node_t*)fd->init_exprs, e); + if (ret < 0) { + scf_expr_free(e); + goto error; } + e = NULL; - scf_block_t* b = scf_block_alloc_cstr("for"); - if (!b) - return -ENOMEM; - scf_node_add_child(fd->_for, (scf_node_t*)b); + // cond expr + ret = __in_cond_expr(&e, i, t, ast, fd->update_exprs); + if (ret < 0) + goto error; - int i; - for (i = 0; i < vec->size; i++) { + fd->cond_exprs = scf_block_alloc(fd->in); + if (!fd->cond_exprs) { + scf_expr_free(e); + goto error; + } + + ret = scf_node_add_child((scf_node_t*)fd->cond_exprs, e); + if (ret < 0) { + scf_expr_free(e); + goto error; + } + e = NULL; - scf_expr_t* e = vec->data[i]; + // update expr + ret = __in_update_expr(&e, i); + if (ret < 0) + goto error; - scf_node_add_child((scf_node_t*)b, e); + ret = scf_node_add_child((scf_node_t*)fd->update_exprs, e); + if (ret < 0) { + scf_expr_free(e); + goto error; } + e = NULL; - scf_vector_free(vec); - vec = NULL; - return SCF_DFA_OK; + fd->i = i; + return 0; +error: + scf_block_free(fd->init_exprs); + if (fd->cond_exprs) + scf_block_free(fd->cond_exprs); + scf_block_free(fd->update_exprs); + + fd->init_exprs = NULL; + fd->cond_exprs = NULL; + fd->update_exprs = NULL; + return -1; } static int _for_add_exprs(dfa_for_data_t* fd) { - _for_add_expr_vector(fd, fd->init_exprs); - fd->init_exprs = NULL; + assert(0 == fd->_for->node.nb_nodes); + + int ret = scf_node_add_child((scf_node_t*)fd->_for, (scf_node_t*)fd->init_exprs); + if (ret < 0) + goto _init_error; - scf_node_add_child(fd->_for, fd->cond_expr); - fd->cond_expr = NULL; + ret = scf_node_add_child((scf_node_t*)fd->_for, (scf_node_t*)fd->cond_exprs); + if (ret < 0) + goto _cond_error; - _for_add_expr_vector(fd, fd->update_exprs); + ret = scf_node_add_child((scf_node_t*)fd->_for, (scf_node_t*)fd->update_exprs); + if (ret < 0) + goto _update_error; + + fd->init_exprs = NULL; + fd->cond_exprs = NULL; fd->update_exprs = NULL; + return 0; - return SCF_DFA_OK; +_init_error: + scf_block_free(fd->init_exprs); +_cond_error: + scf_block_free(fd->cond_exprs); +_update_error: + scf_block_free(fd->update_exprs); + + fd->init_exprs = NULL; + fd->cond_exprs = NULL; + fd->update_exprs = NULL; + return ret; } static int _for_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) @@ -235,55 +787,143 @@ static int _for_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_lex_word_t* w = words->data[words->size - 1]; scf_stack_t* s = d->module_datas[dfa_module_for.index]; dfa_for_data_t* fd = scf_stack_top(s); + scf_block_t* b; + scf_node_t* node; + + int ret; + int i; fd->nb_rps++; if (fd->nb_rps < fd->nb_lps) { SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_rp"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_semicolon"), SCF_DFA_HOOK_POST); - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_comma"), SCF_DFA_HOOK_POST); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_lp_stat"), SCF_DFA_HOOK_POST); return SCF_DFA_NEXT_WORD; } - if (2 == fd->nb_semicolons) { - if (d->expr) { - if (!fd->update_exprs) - fd->update_exprs = scf_vector_alloc(); + if (fd->in) + assert (1 == fd->nb_semicolons); + else + assert (2 == fd->nb_semicolons); + + scf_dfa_del_hook_by_name(&dfa->hooks[SCF_DFA_HOOK_END], "for_semicolon"); - scf_vector_add(fd->update_exprs, d->expr); - d->expr = NULL; - } - } else { - scf_loge("too many ';' in for, file: %s, line: %d\n", w->file->data, w->line); - return SCF_DFA_ERROR; + if (d->expr) { + if (_expr_fini_expr(parse, d, 0) < 0) + return SCF_DFA_ERROR; + } + + b = scf_block_alloc(w); + if (!b) + return -ENOMEM; + + SCF_XCHG(fd->_for->node.nb_nodes, b->node.nb_nodes); + SCF_XCHG(fd->_for->node.nodes, b->node.nodes); + + for (i = 0; i < b->node.nb_nodes; i++) { + node = b->node.nodes[i]; + node->parent = (scf_node_t*)b; + } + + fd->update_exprs = b; + + if (fd->in) { + ret = _for_in_exprs(fd, parse->ast); + if (ret < 0) + return ret; } - _for_add_exprs(fd); - d->expr_local_flag = 0; + ret = _for_add_exprs(fd); + if (ret < 0) + return ret; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "for_end"), SCF_DFA_HOOK_END); return SCF_DFA_SWITCH_TO; } +static void __in_member_replace(scf_node_t* b, scf_variable_t* member, scf_variable_t* i) +{ + scf_expr_t* e; + scf_node_t* node; + int k; + + for (k = 0; k < b->nb_nodes; k++) { + node = b->nodes[k]; + + if (SCF_OP_ARRAY_INDEX == node->type) { + assert(2 == node->nb_nodes); + + e = node->nodes[1]; + while (e && SCF_OP_EXPR == e->type) + e = e->nodes[0]; + + if (scf_type_is_var(e->type) && e->var == member) { + scf_variable_free(e->var); + assert(e->var->refs > 0); + + e->var = i; + continue; + } + } + + __in_member_replace(node, member, i); + } +} + static int _for_action_end(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_stack_t* s = d->module_datas[dfa_module_for.index]; dfa_for_data_t* fd = scf_stack_pop(s); - if (3 == fd->_for->nb_nodes) - scf_node_add_child(fd->_for, NULL); + if (3 == fd->_for->node.nb_nodes) { + scf_node_add_child((scf_node_t*)fd->_for, NULL); + + } else if (fd->in) { + scf_node_t* node = fd->_for->node.nodes[3]; + scf_expr_t* e; + scf_block_t* b; + + __in_member_replace(node, fd->member, fd->i); - assert(parse->ast->current_block == fd->parent_block); + b = scf_block_alloc(fd->in); + if (!b) + return -ENOMEM; - d->current_node = fd->parent_node; + int ret = scf_node_add_child((scf_node_t*)b, node); + if (ret < 0) { + scf_block_free(b); + return ret; + } + fd->_for->node.nodes[3] = (scf_node_t*)b; + b->node.parent = (scf_node_t*)fd->_for; + + e = NULL; + ret = __in_member_expr(&e, fd, ast); + if (ret < 0) + return ret; + + ret = scf_node_add_child((scf_node_t*)b, e); + if (ret < 0) { + scf_expr_free(e); + return ret; + } + + int i; + for (i = b->node.nb_nodes - 2; i >= 0; i--) + b->node.nodes[i + 1] = b->node.nodes[i]; + b->node.nodes[0] = e; + } - scf_logi("for: %d, fd: %p, s->size: %d\n", fd->_for->w->line, fd, s->size); + ast->current_block = fd->parent_block; + d->current_node = fd->parent_node; + + scf_logi("for: %d, fd: %p, s->size: %d\n", fd->_for->node.w->line, fd, s->size); free(fd); fd = NULL; @@ -296,7 +936,7 @@ static int _for_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) static int _dfa_init_module_for(scf_dfa_t* dfa) { SCF_DFA_MODULE_NODE(dfa, for, semicolon, scf_dfa_is_semicolon, _for_action_semicolon); - SCF_DFA_MODULE_NODE(dfa, for, comma, scf_dfa_is_comma, _for_action_comma); + SCF_DFA_MODULE_NODE(dfa, for, in, scf_dfa_is_in, _for_action_semicolon); SCF_DFA_MODULE_NODE(dfa, for, end, _for_is_end, _for_action_end); SCF_DFA_MODULE_NODE(dfa, for, lp, scf_dfa_is_lp, _for_action_lp); @@ -340,7 +980,7 @@ static int _dfa_fini_module_for(scf_dfa_t* dfa) static int _dfa_init_syntax_for(scf_dfa_t* dfa) { SCF_DFA_GET_MODULE_NODE(dfa, for, semicolon, semicolon); - SCF_DFA_GET_MODULE_NODE(dfa, for, comma, comma); + SCF_DFA_GET_MODULE_NODE(dfa, for, in, in); SCF_DFA_GET_MODULE_NODE(dfa, for, lp, lp); SCF_DFA_GET_MODULE_NODE(dfa, for, lp_stat, lp_stat); SCF_DFA_GET_MODULE_NODE(dfa, for, rp, rp); @@ -350,20 +990,34 @@ static int _dfa_init_syntax_for(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, expr, entry, expr); SCF_DFA_GET_MODULE_NODE(dfa, block, entry, block); + SCF_DFA_GET_MODULE_NODE(dfa, type, _const, _const); + SCF_DFA_GET_MODULE_NODE(dfa, type, base_type, base_type); + SCF_DFA_GET_MODULE_NODE(dfa, identity, identity, type_name); + // for start scf_vector_add(dfa->syntaxes, _for); - // condition expr + // dead loop scf_dfa_node_add_child(_for, lp); scf_dfa_node_add_child(lp, semicolon); scf_dfa_node_add_child(semicolon, semicolon); scf_dfa_node_add_child(semicolon, rp); + // declare loop var in for + scf_dfa_node_add_child(lp, _const); + scf_dfa_node_add_child(lp, base_type); + scf_dfa_node_add_child(lp, type_name); + + // init, cond, update expr scf_dfa_node_add_child(lp, expr); scf_dfa_node_add_child(expr, semicolon); scf_dfa_node_add_child(semicolon, expr); scf_dfa_node_add_child(expr, rp); + // for (... in ...) + // 'in' will be called from 'expr' or 'var' module, and followed by an expr + scf_dfa_node_add_child(in, expr); + // for body block scf_dfa_node_add_child(rp, block); diff --git a/js/parse/scf_dfa_util.h b/js/parse/scf_dfa_util.h index 84e0733..44b3b16 100644 --- a/js/parse/scf_dfa_util.h +++ b/js/parse/scf_dfa_util.h @@ -298,6 +298,13 @@ static inline int scf_dfa_is_for(scf_dfa_t* dfa, void* word) return SCF_LEX_WORD_KEY_FOR == w->type; } +static inline int scf_dfa_is_in(scf_dfa_t* dfa, void* word) +{ + scf_lex_word_t* w = word; + + return SCF_LEX_WORD_KEY_IN == w->type; +} + static inline int scf_dfa_is_switch(scf_dfa_t* dfa, void* word) { scf_lex_word_t* w = word; diff --git a/js/parse/scf_dfa_var.c b/js/parse/scf_dfa_var.c index ae9e017..33506f7 100644 --- a/js/parse/scf_dfa_var.c +++ b/js/parse/scf_dfa_var.c @@ -354,6 +354,7 @@ static int _dfa_init_module_var(scf_dfa_t* dfa) { SCF_DFA_MODULE_NODE(dfa, var, comma, scf_dfa_is_comma, _var_action_comma); SCF_DFA_MODULE_NODE(dfa, var, semicolon, scf_dfa_is_semicolon, _var_action_semicolon); + SCF_DFA_MODULE_NODE(dfa, var, in, scf_dfa_is_in, _var_action_semicolon); SCF_DFA_MODULE_NODE(dfa, var, assign, scf_dfa_is_assign, _var_action_assign); return SCF_DFA_OK; @@ -364,6 +365,7 @@ static int _dfa_init_syntax_var(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, var, comma, comma); SCF_DFA_GET_MODULE_NODE(dfa, var, semicolon, semicolon); SCF_DFA_GET_MODULE_NODE(dfa, var, assign, assign); + SCF_DFA_GET_MODULE_NODE(dfa, var, in, in); SCF_DFA_GET_MODULE_NODE(dfa, type, identity, identity); @@ -393,6 +395,7 @@ static int _dfa_init_syntax_var(scf_dfa_t* dfa) scf_dfa_node_add_child(init_rs, semicolon); scf_dfa_node_add_child(identity, semicolon); + scf_dfa_node_add_child(identity, in); return 0; } diff --git a/js/parse/scf_operator_handler_const.c b/js/parse/scf_operator_handler_const.c index f1dfa57..35ebbae 100644 --- a/js/parse/scf_operator_handler_const.c +++ b/js/parse/scf_operator_handler_const.c @@ -380,27 +380,8 @@ static int _scf_op_const_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, v scf_handler_data_t* d = data; - if (nodes[0]) { - if (_scf_op_const_node(ast, nodes[0], d) < 0) { - scf_loge("\n"); - return -1; - } - } - - scf_expr_t* e = nodes[1]; - if (e) { - assert(SCF_OP_EXPR == e->type); - - scf_variable_t* r = NULL; - - if (_scf_expr_calculate_internal(ast, e, &r) < 0) { - scf_loge("\n"); - return -1; - } - } - int i; - for (i = 2; i < nb_nodes; i++) { + for (i = 0; i < nb_nodes; i++) { if (!nodes[i]) continue; diff --git a/js/parse/scf_operator_handler_semantic.c b/js/parse/scf_operator_handler_semantic.c index 8ec3f1b..22bb5fe 100644 --- a/js/parse/scf_operator_handler_semantic.c +++ b/js/parse/scf_operator_handler_semantic.c @@ -1522,44 +1522,33 @@ static int _scf_op_semantic_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes assert(4 == nb_nodes); scf_handler_data_t* d = data; - int ret = 0; + scf_variable_t* r; + scf_node_t* cond; + int i; + + for (i = 0; i < nb_nodes; i++) { + if (!nodes[i]) + continue; - if (nodes[0]) { - ret = _scf_op_semantic_node(ast, nodes[0], d); + int ret = _scf_op_semantic_node(ast, nodes[i], d); if (ret < 0) { scf_loge("\n"); return ret; } - } - - scf_expr_t* e = nodes[1]; - if (e) { - assert(SCF_OP_EXPR == e->type); - scf_variable_t* r = NULL; + if (1 == i) { + cond = nodes[i]; - if (_scf_expr_calculate(ast, e, &r) < 0) { - scf_loge("\n"); - return -1; - } - - if (!r || !scf_variable_integer(r)) { - scf_loge("\n"); - return -1; - } - scf_variable_free(r); - r = NULL; - } + if (cond->nb_nodes <= 0) + continue; - int i; - for (i = 2; i < nb_nodes; i++) { - if (!nodes[i]) - continue; + // the final expr is real cond expr + r = _scf_operand_get(cond->nodes[cond->nb_nodes - 1]); - ret = _scf_op_semantic_node(ast, nodes[i], d); - if (ret < 0) { - scf_loge("\n"); - return ret; + if (!r || !scf_variable_integer(r)) { + scf_loge("\n"); + return -1; + } } } diff --git a/js/parse/scf_parse.c b/js/parse/scf_parse.c index c976598..5d180b8 100644 --- a/js/parse/scf_parse.c +++ b/js/parse/scf_parse.c @@ -2353,7 +2353,7 @@ int scf_parse_compile(scf_parse_t* parse, const char* arch) if (!functions) return -ENOMEM; - ret = scf_node_search_bfs(root, NULL, functions, -1, _find_function); + ret = scf_node_search_bfs(root, NULL, functions, -1, __find_function); if (ret < 0) goto error; @@ -2382,7 +2382,7 @@ int scf_parse_to_obj(scf_parse_t* parse, const char* out, const char* arch) if (!functions) return -ENOMEM; - int ret = scf_node_search_bfs((scf_node_t*)b, NULL, functions, -1, _find_function); + int ret = scf_node_search_bfs((scf_node_t*)b, NULL, functions, -1, __find_function); if (ret < 0) { scf_vector_free(functions); return ret; @@ -2396,7 +2396,7 @@ int scf_parse_to_obj(scf_parse_t* parse, const char* out, const char* arch) goto global_vars_error; } - ret = scf_node_search_bfs((scf_node_t*)b, NULL, global_vars, -1, _find_global_var); + ret = scf_node_search_bfs((scf_node_t*)b, NULL, global_vars, -1, __find_global_var); if (ret < 0) { scf_loge("\n"); goto code_error; diff --git a/js/parse/scf_parse_util.c b/js/parse/scf_parse_util.c index afb059c..377c822 100644 --- a/js/parse/scf_parse_util.c +++ b/js/parse/scf_parse_util.c @@ -1,41 +1,3 @@ #include"scf_parse.h" -int _find_function(scf_node_t* node, void* arg, scf_vector_t* vec) -{ - if (SCF_FUNCTION == node->type) { - - scf_function_t* f = (scf_function_t*)node; - - return scf_vector_add(vec, f); - } - - return 0; -} - -int _find_global_var(scf_node_t* node, void* arg, scf_vector_t* vec) -{ - if (SCF_OP_BLOCK == node->type - || (node->type >= SCF_STRUCT && node->class_flag)) { - - scf_block_t* b = (scf_block_t*)node; - - if (!b->scope || !b->scope->vars) - return 0; - - int i; - for (i = 0; i < b->scope->vars->size; i++) { - - scf_variable_t* v = b->scope->vars->data[i]; - - if (v->global_flag || v->static_flag) { - - int ret = scf_vector_add(vec, v); - if (ret < 0) - return ret; - } - } - } - - return 0; -} -- 2.25.1