wsstree.c
来自「The Kannel Open Source WAP and SMS gatew」· C语言 代码 · 共 1,501 行 · 第 1/4 页
C
1,501 行
/********************* Statements ***************************************//* Linearize the variable declaration list `list'. */static void linearize_variable_init(WsCompiler *compiler, WsList *list, WsUInt32 line){ WsNamespace *ns; WsListItem *li; /* For each variable, declared with this list. */ for (li = list->head; li; li = li->next) { WsVarDec *vardec = li->data; ns = ws_variable_define(compiler, line, WS_TRUE, vardec->name); if (ns && vardec->expr) { ws_expr_linearize(compiler, vardec->expr); /* Emit an instruction to store the initialization value to the variable. */ ws_asm_link(compiler, ws_asm_variable(compiler, line, WS_ASM_P_STORE_VAR, ns->vindex)); } }}void ws_stmt_linearize(WsCompiler *compiler, WsStatement *stmt){ WsListItem *li; WsAsmIns *ins; switch (stmt->type) { case WS_STMT_BLOCK: for (li = stmt->u.block->head; li; li = li->next) ws_stmt_linearize(compiler, li->data); break; case WS_STMT_VARIABLE: linearize_variable_init(compiler, stmt->u.var, stmt->first_line); break; case WS_STMT_EMPTY: /* Nothing here. */ break; case WS_STMT_EXPR: ws_expr_linearize(compiler, stmt->u.expr); /* Pop the expressions result from the stack. Otherwise loops could eventually cause stack overflows. */ ws_asm_link(compiler, ws_asm_ins(compiler, stmt->last_line, WS_ASM_POP)); break; case WS_STMT_IF: { WsAsmIns *l_else = ws_asm_label(compiler, (stmt->u.s_if.s_else ? stmt->u.s_if.s_else->first_line : stmt->last_line)); WsAsmIns *l_end = ws_asm_label(compiler, stmt->last_line); /* Linearize the expression. */ ws_expr_linearize(compiler, stmt->u.s_if.expr); /* If the result is false, jump to the else-branch. */ ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line, WS_ASM_P_TJUMP, l_else)); /* Else, execute the then-branch and jump to the end. */ ws_stmt_linearize(compiler, stmt->u.s_if.s_then); ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line, WS_ASM_P_JUMP, l_end)); /* Then else-branch. */ ws_asm_link(compiler, l_else); /* Linearize the else-branch if it is present. */ if (stmt->u.s_if.s_else) ws_stmt_linearize(compiler, stmt->u.s_if.s_else); /* Insert the end label. */ ws_asm_link(compiler, l_end); } break; case WS_STMT_FOR: { WsAsmIns *l_loop = ws_asm_label(compiler, stmt->first_line); WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line); WsAsmIns *l_break = ws_asm_label(compiler, stmt->first_line); WsContBreak *cb; /* Store the labels to the compiler. */ cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb)); if (cb == NULL) { ws_error_memory(compiler); return; } cb->next = compiler->cont_break; compiler->cont_break = cb; cb->l_cont = l_cont; cb->l_break = l_break; /* Linearize the possible init code. */ if (stmt->u.s_for.init) linearize_variable_init(compiler, stmt->u.s_for.init, stmt->first_line); else if (stmt->u.s_for.e1) { /* Linearize the init. */ ws_expr_linearize(compiler, stmt->u.s_for.e1); /* Pop the result. */ ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line, WS_ASM_POP)); } /* Insert the loop label. */ ws_asm_link(compiler, l_loop); /* Linearize the condition. */ if (stmt->u.s_for.e2) { ws_expr_linearize(compiler, stmt->u.s_for.e2); /* If false, jump out. */ ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line, WS_ASM_P_TJUMP, l_break)); } /* Linearize the body statement. */ ws_stmt_linearize(compiler, stmt->u.s_for.stmt); /* Link the continue label. */ ws_asm_link(compiler, l_cont); /* Linearize the update expression. */ if (stmt->u.s_for.e3) { ws_expr_linearize(compiler, stmt->u.s_for.e3); /* Pop the result. */ ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line, WS_ASM_POP)); } /* Jump to the loop label to check the condition. */ ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line, WS_ASM_P_JUMP, l_loop)); /* Insert the break label. */ ws_asm_link(compiler, l_break); /* Pop the cont-break block. */ compiler->cont_break = compiler->cont_break->next; } break; case WS_STMT_WHILE: { WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line); WsAsmIns *l_break = ws_asm_label(compiler, stmt->u.s_while.stmt->last_line); WsContBreak *cb; /* Store the labels to the compiler. */ cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb)); if (cb == NULL) { ws_error_memory(compiler); return; } cb->next = compiler->cont_break; compiler->cont_break = cb; cb->l_cont = l_cont; cb->l_break = l_break; /* Insert the continue label. */ ws_asm_link(compiler, l_cont); /* Linearize the expression. */ ws_expr_linearize(compiler, stmt->u.s_while.expr); /* If false, jump out. */ ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line, WS_ASM_P_TJUMP, l_break)); /* Linearize the body statement. */ ws_stmt_linearize(compiler, stmt->u.s_while.stmt); /* And jump to the continue label to check the expression. */ ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line, WS_ASM_P_JUMP, l_cont)); /* Insert the break label. */ ws_asm_link(compiler, l_break); /* Pop the cont-break block. */ compiler->cont_break = compiler->cont_break->next; } break; case WS_STMT_CONTINUE: if (compiler->cont_break == NULL) ws_src_error(compiler, stmt->first_line, "continue statement not within a loop"); ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line, WS_ASM_P_JUMP, compiler->cont_break->l_cont)); break; case WS_STMT_BREAK: if (compiler->cont_break == NULL) ws_src_error(compiler, stmt->first_line, "break statement not within a loop"); ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line, WS_ASM_P_JUMP, compiler->cont_break->l_break)); break; case WS_STMT_RETURN: if (stmt->u.expr) { /* Linearize the return value and return it. */ ws_expr_linearize(compiler, stmt->u.expr); ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN); } else /* Return an empty string. */ ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN_ES); ws_asm_link(compiler, ins); break; }}/* Constructors. */static WsStatement *stmt_alloc(WsCompiler *compiler, WsStatementType type, WsUInt32 first_line, WsUInt32 last_line){ WsStatement *stmt = ws_f_calloc(compiler->pool_stree, 1, sizeof(*stmt)); if (stmt == NULL) ws_error_memory(compiler); else { stmt->type = type; stmt->first_line = first_line; stmt->last_line = last_line; } return stmt;}WsStatement *ws_stmt_block(WsCompiler *compiler, WsUInt32 fline, WsUInt32 lline, WsList *block){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_BLOCK, fline, lline); if (stmt) stmt->u.block = block; return stmt;}WsStatement *ws_stmt_variable(WsCompilerPtr compiler, WsUInt32 line, WsList *variables){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_VARIABLE, line, line); if (stmt) stmt->u.var = variables; return stmt;}WsStatement *ws_stmt_empty(WsCompiler *compiler, WsUInt32 line){ return stmt_alloc(compiler, WS_STMT_EMPTY, line, line);}WsStatement *ws_stmt_expr(WsCompiler *compiler, WsUInt32 line, WsExpression *expr){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_EXPR, line, line); if (stmt) stmt->u.expr = expr; return stmt;}WsStatement *ws_stmt_if(WsCompiler *compiler, WsUInt32 line, WsExpression *expr, WsStatement *s_then, WsStatement *s_else){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_IF, line, line); if (stmt) { stmt->u.s_if.expr = expr; stmt->u.s_if.s_then = s_then; stmt->u.s_if.s_else = s_else; } return stmt;}WsStatement *ws_stmt_for(WsCompilerPtr compiler, WsUInt32 line, WsList *init, WsExpression *e1, WsExpression *e2, WsExpression *e3, WsStatement *stmt_body){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_FOR, line, line); if (stmt) { stmt->u.s_for.init = init; stmt->u.s_for.e1 = e1; stmt->u.s_for.e2 = e2; stmt->u.s_for.e3 = e3; stmt->u.s_for.stmt = stmt_body; } return stmt;}WsStatement *ws_stmt_while(WsCompiler *compiler, WsUInt32 line, WsExpression *expr, WsStatement *stmt_arg){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_WHILE, line, line); if (stmt) { stmt->u.s_while.expr = expr; stmt->u.s_while.stmt = stmt_arg; } return stmt;}WsStatement *ws_stmt_continue(WsCompiler *compiler, WsUInt32 line){ return stmt_alloc(compiler, WS_STMT_CONTINUE, line, line);}WsStatement *ws_stmt_break(WsCompiler *compiler, WsUInt32 line){ return stmt_alloc(compiler, WS_STMT_BREAK, line, line);}WsStatement *ws_stmt_return(WsCompilerPtr compiler, WsUInt32 line, WsExpression *expr){ WsStatement *stmt = stmt_alloc(compiler, WS_STMT_RETURN, line, line); if (stmt) stmt->u.expr = expr; return stmt;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?