Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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++;
}
Beispiel #5
0
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;
    }
}