Example #1
0
static sl_node_base_t*
if_expression(sl_parse_state_t* ps)
{
    sl_node_base_t *condition, *if_true, *if_false = NULL;
    int negate_condition = 0;
    if(peek_token(ps)->type == SL_TOK_ELSIF) {
        expect_token(ps, SL_TOK_ELSIF);
    } else if(peek_token(ps)->type == SL_TOK_UNLESS) {
        expect_token(ps, SL_TOK_UNLESS);
        negate_condition = 1;
    } else {
        expect_token(ps, SL_TOK_IF);
    }
    condition = expression(ps);
    if(negate_condition) {
        condition = sl_make_unary_node(ps, condition, SL_NODE_NOT);
    }
    if_true = body_expression(ps);
    if(peek_token(ps)->type == SL_TOK_ELSIF) {
        if_false = if_expression(ps);
    }
    if(peek_token(ps)->type == SL_TOK_ELSE) {
        next_token(ps);
        if_false = body_expression(ps);
    }
    return sl_make_if_node(ps, condition, if_true, if_false);
}
Example #2
0
static sl_node_base_t*
switch_expression(sl_parse_state_t* ps)
{
    expect_token(ps, SL_TOK_SWITCH);
    sl_node_base_t* value = expression(ps);
    expect_token(ps, SL_TOK_OPEN_BRACE);
    size_t case_count = 0, case_cap = 2;
    sl_node_switch_case_t* cases = sl_alloc(ps->vm->arena, sizeof(sl_node_switch_case_t) * case_cap);
    sl_node_base_t* else_body = NULL;
    while(peek_token(ps)->type != SL_TOK_CLOSE_BRACE) {
        if(peek_token(ps)->type == SL_TOK_ELSE) {
            next_token(ps);
            else_body = body_expression(ps);
            break;
        }
        if(case_count + 1 >= case_cap) {
            case_cap *= 2;
            cases = sl_realloc(ps->vm->arena, cases, sizeof(sl_node_switch_case_t) * case_cap);
        }
        cases[case_count].value = expression(ps);
        cases[case_count].body = body_expression(ps);
        case_count++;
    }
    expect_token(ps, SL_TOK_CLOSE_BRACE);
    return sl_make_switch_node(ps, value, case_count, cases, else_body);
}
Example #3
0
static sl_node_base_t*
for_expression(sl_parse_state_t* ps)
{
    sl_node_base_t *lval, *expr, *body, *else_body = NULL;
    sl_node_seq_t* seq_lval;
    sl_token_t* tok;
    sl_parse_scope_t scope;
    expect_token(ps, SL_TOK_FOR);
    /* save current token to allow rewinding and erroring */
    tok = peek_token(ps);
    lval = call_expression(ps);
    if(!sl_node_is_lval(lval)) {
        unexpected(ps, tok);
    }
    if(peek_token(ps)->type == SL_TOK_COMMA || peek_token(ps)->type == SL_TOK_FAT_COMMA) {
        seq_lval = sl_make_seq_node(ps);
        seq_lval->nodes[seq_lval->node_count++] = lval;
        while(peek_token(ps)->type == SL_TOK_COMMA || peek_token(ps)->type == SL_TOK_FAT_COMMA) {
            next_token(ps);
            if(seq_lval->node_count == seq_lval->node_capacity) {
                seq_lval->node_capacity *= 2;
                seq_lval->nodes = sl_realloc(ps->vm->arena, seq_lval->nodes, sizeof(sl_node_base_t*) * seq_lval->node_capacity);
            }
            tok = peek_token(ps);
            lval = call_expression(ps);
            if(!sl_node_is_lval(lval)) {
                unexpected(ps, tok);
            }
            seq_lval->nodes[seq_lval->node_count++] = lval;
        }
        lval = sl_make_array_node(ps, seq_lval->node_count, seq_lval->nodes);
    }
    expect_token(ps, SL_TOK_IN);
    expr = expression(ps);
    
    scope.prev = ps->scope;
    scope.flags = scope.prev->flags | SL_PF_CAN_NEXT_LAST;
    ps->scope = &scope;
    body = body_expression(ps);
    ps->scope = scope.prev;
    if(scope.flags & SL_PF_SCOPE_CLOSURE) {
        ps->scope->flags |= SL_PF_SCOPE_CLOSURE;
    }
    
    if(peek_token(ps)->type == SL_TOK_ELSE) {
        next_token(ps);
        else_body = body_expression(ps);
    }
    return sl_make_for_node(ps, lval, expr, body, else_body);
}
Example #4
0
static sl_node_base_t*
while_expression(sl_parse_state_t* ps)
{
    sl_node_base_t *condition, *body;
    sl_parse_scope_t scope;
    int until = 0;
    if(peek_token(ps)->type == SL_TOK_UNTIL) {
        next_token(ps);
        until = 1;
    } else {
        expect_token(ps, SL_TOK_WHILE);
    }
    condition = expression(ps);
    if(until) {
        condition = sl_make_unary_node(ps, condition, SL_NODE_NOT);
    }
    scope.prev = ps->scope;
    scope.flags = scope.prev->flags | SL_PF_CAN_NEXT_LAST;
    ps->scope = &scope;
    body = body_expression(ps);
    ps->scope = scope.prev;
    if(scope.flags & SL_PF_SCOPE_CLOSURE) {
        ps->scope->flags |= SL_PF_SCOPE_CLOSURE;
    }
    return sl_make_while_node(ps, condition, body);
}
Example #5
0
static sl_node_base_t*
try_expression(sl_parse_state_t* ps)
{
    sl_node_base_t *body, *lval = NULL, *catch_body = NULL;
    sl_token_t* tok;
    expect_token(ps, SL_TOK_TRY);
    body = body_expression(ps);
    expect_token(ps, SL_TOK_CATCH);
    tok = peek_token(ps);
    if(tok->type != SL_TOK_OPEN_BRACE) {
        lval = primary_expression(ps);
        if(!sl_node_is_lval(lval)) {
            unexpected(ps, tok);
        }
    }
    catch_body = body_expression(ps);
    return sl_make_try_node(ps, body, lval, catch_body);
}
Example #6
0
static sl_node_base_t*
class_expression(sl_parse_state_t* ps)
{
    expect_token(ps, SL_TOK_CLASS);
    sl_token_t* tok = expect_token(ps, SL_TOK_CONSTANT);
    SLID name = sl_intern2(ps->vm, sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
    sl_node_base_t *extends, *body;
    if(peek_token(ps)->type == SL_TOK_EXTENDS) {
        next_token(ps);
        extends = expression(ps);
    } else {
        extends = NULL;
    }
    body = body_expression(ps);
    return sl_make_class_node(ps, name, extends, body);
}
Example #7
0
static sl_node_base_t*
lambda_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* body;
    sl_token_t* tok;
    size_t arg_count = 0, arg_cap = 2;
    sl_string_t** args = sl_alloc(ps->vm->arena, sizeof(sl_string_t*) * arg_cap);
    sl_parse_scope_t scope;
    expect_token(ps, SL_TOK_LAMBDA);
    if(peek_token(ps)->type == SL_TOK_IDENTIFIER) {
        tok = next_token(ps);
        args[arg_count++] = (sl_string_t*)sl_get_ptr(
            sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
    } else if(peek_token(ps)->type != SL_TOK_OPEN_BRACE && peek_token(ps)->type != SL_TOK_DOT) {
        expect_token(ps, SL_TOK_OPEN_PAREN);
        while(peek_token(ps)->type != SL_TOK_CLOSE_PAREN) {
            if(arg_count >= arg_cap) {
                arg_cap *= 2;
                args = sl_realloc(ps->vm->arena, args, sizeof(sl_string_t*) * arg_cap);
            }
            tok = expect_token(ps, SL_TOK_IDENTIFIER);
            args[arg_count++] = (sl_string_t*)sl_get_ptr(
                sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
            if(peek_token(ps)->type != SL_TOK_CLOSE_PAREN) {
                expect_token(ps, SL_TOK_COMMA);
            }
        }
        expect_token(ps, SL_TOK_CLOSE_PAREN);
    }
    scope.prev = ps->scope;
    scope.flags = SL_PF_CAN_RETURN;
    ps->scope = &scope;
    if(peek_token(ps)->type == SL_TOK_DOT) {
        next_token(ps);
        body = expression(ps);
    } else {
        body = body_expression(ps);
    }
    ps->scope = scope.prev;
    ps->scope->flags |= SL_PF_SCOPE_CLOSURE;
    return sl_make_lambda_node(ps, arg_count, args, body);
}
Example #8
0
static sl_node_base_t*
def_expression(sl_parse_state_t* ps)
{
    SLID name;
    sl_node_base_t* on = NULL;
    sl_node_base_t* body;
    sl_token_t* tok;
    size_t req_arg_count = 0, req_arg_cap = 2;
    sl_string_t** req_args = sl_alloc(ps->vm->arena, sizeof(sl_string_t*) * req_arg_cap);
    size_t opt_arg_count = 0, opt_arg_cap = 2;
    sl_node_opt_arg_t* opt_args = sl_alloc(ps->vm->arena, sizeof(sl_node_opt_arg_t) * opt_arg_cap);
    sl_parse_scope_t scope;
    expect_token(ps, SL_TOK_DEF);
    switch(peek_token(ps)->type) {
        case SL_TOK_IDENTIFIER:
            if(peek_token_n(ps, 2)->type == SL_TOK_DOT) {
                on = sl_make_var_node(ps, SL_NODE_VAR, next_token(ps)->str);
                next_token(ps);
                name = def_expression_method_name(ps);
            } else {
                on = NULL;
                name = def_expression_method_name(ps);
            }
            break;
        case SL_TOK_SELF:
        case SL_TOK_IVAR:
        case SL_TOK_CVAR:
        case SL_TOK_CONSTANT:
            on = primary_expression(ps);
            expect_token(ps, SL_TOK_DOT);
            name = def_expression_method_name(ps);
            break;
        default:
            name = def_expression_method_name(ps);
    }
    if(peek_token(ps)->type == SL_TOK_EQUALS) {
        next_token(ps);
        name = sl_intern2(ps->vm,
            sl_string_concat(ps->vm, sl_id_to_string(ps->vm, name), sl_make_cstring(ps->vm, "=")));
    }
    int at_opt_args = 0;
    if(peek_token(ps)->type != SL_TOK_OPEN_BRACE) {
        expect_token(ps, SL_TOK_OPEN_PAREN);
        if(peek_token(ps)->type == SL_TOK_SELF) {
            error(ps, sl_make_cstring(ps->vm, "not a chance"), peek_token(ps));
        }
        while(peek_token(ps)->type != SL_TOK_CLOSE_PAREN) {
            tok = expect_token(ps, SL_TOK_IDENTIFIER);
            if(peek_token(ps)->type == SL_TOK_EQUALS) {
                at_opt_args = 1;
            }
            if(at_opt_args) {
                expect_token(ps, SL_TOK_EQUALS);
                if(opt_arg_count >= opt_arg_cap) {
                    opt_arg_cap *= 2;
                    opt_args = sl_realloc(ps->vm->arena, opt_args, sizeof(sl_node_opt_arg_t) * opt_arg_cap);
                }
                opt_args[opt_arg_count].name = (sl_string_t*)sl_get_ptr(
                    sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
                opt_args[opt_arg_count++].default_value = expression(ps);
            } else {
                if(req_arg_count >= req_arg_cap) {
                    req_arg_cap *= 2;
                    req_args = sl_realloc(ps->vm->arena, req_args, sizeof(sl_string_t*) * req_arg_cap);
                }
                req_args[req_arg_count++] = (sl_string_t*)sl_get_ptr(
                    sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
            }
            if(peek_token(ps)->type != SL_TOK_CLOSE_PAREN) {
                expect_token(ps, SL_TOK_COMMA);
            }
        }
        expect_token(ps, SL_TOK_CLOSE_PAREN);
    }
    scope.prev = ps->scope;
    scope.flags = SL_PF_CAN_RETURN;
    ps->scope = &scope;
    body = body_expression(ps);
    ps->scope = scope.prev;
    ps->scope->flags |= SL_PF_SCOPE_CLOSURE;
    return sl_make_def_node(ps, name, on, req_arg_count, req_args, opt_arg_count, opt_args, body);
}