js: support 'for..in..'
authoryu.dongliang <18588496441@163.com>
Wed, 10 Dec 2025 04:22:12 +0000 (12:22 +0800)
committeryu.dongliang <18588496441@163.com>
Wed, 10 Dec 2025 04:22:12 +0000 (12:22 +0800)
20 files changed:
examples/js.html
js/core/scf_block.c
js/core/scf_lex_word.h
js/core/scf_node.h
js/core/scf_operator_handler_3ac.c
js/core/scf_optimizer_auto_gc.c
js/core/scf_pointer_alias.c
js/doc.c
js/lex/scf_lex.c
js/native/risc/scf_risc.c
js/native/x64/scf_x64.c
js/parse/scf_dfa_block.c
js/parse/scf_dfa_expr.c
js/parse/scf_dfa_for.c
js/parse/scf_dfa_util.h
js/parse/scf_dfa_var.c
js/parse/scf_operator_handler_const.c
js/parse/scf_operator_handler_semantic.c
js/parse/scf_parse.c
js/parse/scf_parse_util.c

index c6906acda9af96f6b5c39a032b79812f6037db5e..234458c1bf9ea6ed342140eecba865da66845972 100644 (file)
@@ -8,10 +8,14 @@
 
 <script>
 
-var a = [1, 2];
-var i;
-for (i = 0; i < 2; )
-       document.write(a[i++]);
+var obj = {
+       a: 1,
+};
+
+for (var x in obj) {
+       document.write(x);
+       document.write(obj[x]);
+}
 
 </script>
 
index cf3959861dd5cc75d5d5906d94fa065df523b5af..5461b0d364e55a0e22d8f4846d77c0442414d6f9 100644 (file)
@@ -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;
+}
index 1d056183c7ddc13b2979584863a7dff8b69053b9..17ac40d6ea8e99f452dbeda15e488b2dbd6a8cf6 100644 (file)
@@ -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
 
index 92ec39796434a740f253e7d9f406fea741f90ee4..946298cec875d51b08f35bcfc7df8416c4cdfb69 100644 (file)
@@ -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);
 
index 0b04e661654a973b56b5c23a480cc384b48a8266..3d31a07f70c08584a4b29dfe689a14f7b0292752 100644 (file)
@@ -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)
index afd61f2aa0e59a144264200f00091fbf784405b7..aa0aa91eed4a27512d945980687fc9ed7f34be0a 100644 (file)
@@ -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;
                }
        }
 
index 02af3c6fdaabfee0ab1db5538ec923317955c12d..710d764813d26df0011767628f545db50b7acbe1 100644 (file)
@@ -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);
index 2d320eba0f0c234883df6fd27cd8c3db8f0f906b..6de9ccf719aff2dd0d60a8f3bd8f1f5b04b4fc22 100644 (file)
--- 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;
        }
 
index 2537116113b8bd2078221b2742d366d0dfea60ac..a0906158f648d56e9796d6d275869c88d14ca661 100644 (file)
@@ -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},
 
index 2915c9868ade872d31bd4ac1fd08d35d2d94b6b6..d0b71d8b21bb0bbfb70f3b28c6b5a0b48b72c18f 100644 (file)
@@ -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;
 
index 9d7da3bb3ae38c93e6530d7fa8a3427eb1cdebe3..ced05bad09c9daaa2167086f750156292f67e32b 100644 (file)
@@ -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;
 
index 2afd08a2a670bf37a4c0890e6daa3bbfdf4f9457..bf42d29d1eaa825f2bc821bb8b845db16eb1e400 100644 (file)
@@ -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);
index ffde7f1f61a9469e41b80bc1a06052a11fcb3b0a..75337c17c407af9bf6e0835f340f38f02b5c9a1c 100644 (file)
@@ -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;
 }
 
index 543c1169499454feb1467c2a656d438a2754baae..5e671fb8d7230afaa00f9af5fafd2ad00c9a2908 100644 (file)
@@ -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);
 
index 84e07337cf4d791032c1e43a8c78c4fce2d5ec7d..44b3b1647adc3c348527cf0c1d5fe55ec3c14d93 100644 (file)
@@ -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;
index ae9e01706bf65f48db8033fd32f8ed7cd56f8170..33506f79cc1724c4682f479cd105f75050e7915c 100644 (file)
@@ -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;
 }
 
index f1dfa570506595637df83a5ab7d3b09c42d98d63..35ebbaeacb52ef7acd1deeacefe7980af6dd0507 100644 (file)
@@ -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;
 
index 8ec3f1b2d213c40d620011c6fb4312ba8772c933..22bb5fe2ac838ef80cdd79c710931d0f45913410 100644 (file)
@@ -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;
+                       }
                }
        }
 
index c9765985e69f51630905d55fdd998660daa102f8..5d180b8d2d3500e8458b9cc020f713de920cb2af 100644 (file)
@@ -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;
index afb059c82b3043dcf36af15dd36679ba877a0058..377c8228c98a7574ef34a63e5f22913376b89a2a 100644 (file)
@@ -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;
-}