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)
{
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);
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;
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)
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;
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);
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);
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);