static WsAsmIns *asm_alloc(WsCompiler *compiler, WsUInt16 type, WsUInt32 line) { WsAsmIns *ins = ws_f_calloc(compiler->pool_asm, 1, sizeof(*ins)); if (ins == NULL) ws_error_memory(compiler); else { ins->type = type; ins->line = line; } return ins; }
static WsExpression *expr_alloc(WsCompiler *compiler, WsExpressionType type, WsUInt32 line) { WsExpression *expr = ws_f_calloc(compiler->pool_stree, 1, sizeof(*expr)); if (expr == NULL) ws_error_memory(compiler); else { expr->type = type; expr->line = line; } return expr; }
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; }
void ws_list_append(WsCompiler *compiler, WsList *list, void *value) { WsListItem *item; if (list == NULL) /* A recovery code for previous memory allocation problems. */ return; item = ws_f_calloc(compiler->pool_stree, 1, sizeof(*item)); if (item == NULL) { ws_error_memory(compiler); return; } item->data = value; if (list->tail) { list->tail->next = item; list->tail = item; } else list->head = list->tail = item; list->num_items++; }
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; } }