Exemplo n.º 1
0
static sl_node_base_t*
send_with_args_expression(sl_parse_state_t* ps, sl_node_base_t* recv, SLID id)
{
    size_t argc = 0, cap = 2;
    sl_node_base_t** argv = sl_alloc(ps->vm->arena, sizeof(sl_node_base_t*) * cap);
    bool splat_last = false;
    expect_token(ps, SL_TOK_OPEN_PAREN);
    while(peek_token(ps)->type != SL_TOK_CLOSE_PAREN) {
        if(argc >= cap) {
            cap *= 2;
            argv = sl_realloc(ps->vm->arena, argv, sizeof(sl_node_base_t*) * cap);
        }
        if(peek_token(ps)->type == SL_TOK_TIMES) {
            next_token(ps);
            splat_last = true;
            argv[argc++] = expression(ps);
            break;
        }
        argv[argc++] = expression(ps);
        if(peek_token(ps)->type != SL_TOK_CLOSE_PAREN) {
            expect_token(ps, SL_TOK_COMMA);
        }
    }
    expect_token(ps, SL_TOK_CLOSE_PAREN);
    return sl_make_send_node(ps, recv, id, argc, argv, splat_last);
}
Exemplo n.º 2
0
static sl_node_base_t*
unary_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* expr;
    sl_token_t* tok;
    switch(peek_token(ps)->type) {
        case SL_TOK_MINUS:
            tok = next_token(ps);
            expr = unary_expression(ps);
            return sl_make_send_node(ps, expr, sl_intern(ps->vm, "negate"), 0, NULL);
        case SL_TOK_TILDE:
            tok = next_token(ps);
            expr = unary_expression(ps);
            return sl_make_send_node(ps, expr, sl_intern2(ps->vm, tok->str), 0, NULL);
        case SL_TOK_NOT:
            next_token(ps);
            expr = unary_expression(ps);
            return sl_make_unary_node(ps, expr, SL_NODE_NOT);
        case SL_TOK_RETURN:
            tok = next_token(ps);
            if(!(ps->scope->flags & SL_PF_CAN_RETURN)) {
                error(ps, sl_make_cstring(ps->vm, "Can't return outside of a method or lambda"), tok);
            }
            switch(peek_token(ps)->type) {
                case SL_TOK_SEMICOLON:
                case SL_TOK_CLOSE_BRACE:
                case SL_TOK_CLOSE_TAG:
                /* in these case we want to allow for postfix control structures: */
                case SL_TOK_IF:
                case SL_TOK_UNLESS:
                    return sl_make_unary_node(ps, sl_make_immediate_node(ps, ps->vm->lib.nil), SL_NODE_RETURN);
                default:
                    return sl_make_unary_node(ps, low_precedence_logical_expression(ps), SL_NODE_RETURN);
            }
            break;
        case SL_TOK_THROW:
            next_token(ps);
            return sl_make_unary_node(ps, low_precedence_logical_expression(ps), SL_NODE_THROW);
        case SL_TOK_USE:
            return use_expression(ps);
        default:
            return power_expression(ps);
    }
}
Exemplo n.º 3
0
static sl_node_base_t*
call_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = primary_expression(ps);
    sl_node_base_t** nodes;
    size_t node_len;
    size_t node_cap;
    sl_token_t* tok;
    if(left->type == SL_NODE_VAR && peek_token(ps)->type == SL_TOK_OPEN_PAREN) {
        left = send_with_args_expression(ps, sl_make_self_node(ps),
            sl_intern2(ps->vm, sl_make_ptr((sl_object_t*)((sl_node_var_t*)left)->name)));
    }
    while(1) {
        tok = peek_token(ps);
        switch(tok->type) {
            case SL_TOK_DOT:
                next_token(ps);
                left = send_expression(ps, left);
                break;
            case SL_TOK_COLON:
                next_token(ps);
                left = sl_make_bind_method_node(ps, left, def_expression_method_name(ps));
                break;
            case SL_TOK_PAAMAYIM_NEKUDOTAYIM:
                next_token(ps);
                tok = expect_token(ps, SL_TOK_CONSTANT);
                left = sl_make_const_node(ps, left,
                    sl_intern2(ps->vm,
                        sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len)));
                break;
            case SL_TOK_OPEN_BRACKET:
                next_token(ps);
                node_cap = 1;
                node_len = 0;
                nodes = sl_alloc(ps->vm->arena, sizeof(SLVAL) * node_cap);
                while(peek_token(ps)->type != SL_TOK_CLOSE_BRACKET) {
                    if(node_len >= node_cap) {
                        node_cap *= 2;
                        nodes = sl_realloc(ps->vm->arena, nodes, sizeof(SLVAL) * node_cap);
                    }
                    nodes[node_len++] = expression(ps);
                    if(peek_token(ps)->type != SL_TOK_CLOSE_BRACKET) {
                        expect_token(ps, SL_TOK_COMMA);
                    }
                }
                expect_token(ps, SL_TOK_CLOSE_BRACKET);
                left = sl_make_send_node(ps, left, sl_intern(ps->vm, "[]"), node_len, nodes);
                break;
            default:
                return left;
        }
    }
}
Exemplo n.º 4
0
static sl_node_base_t*
send_expression(sl_parse_state_t* ps, sl_node_base_t* recv)
{
    SLVAL id;
    sl_token_t* tok;
    tok = expect_token(ps, SL_TOK_IDENTIFIER);
    id = sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len);
    if(peek_token(ps)->type != SL_TOK_OPEN_PAREN) {
        return sl_make_send_node(ps, recv, sl_intern2(ps->vm, id), 0, NULL);
    }
    return send_with_args_expression(ps, recv, sl_intern2(ps->vm, id));
}
Exemplo n.º 5
0
static sl_node_base_t*
shift_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = add_expression(ps);
    sl_node_base_t* right;
    sl_token_t* tok;
    while(peek_token(ps)->type == SL_TOK_SHIFT_LEFT || peek_token(ps)->type == SL_TOK_SHIFT_RIGHT) {
        tok = next_token(ps);
        right = add_expression(ps);
        left = sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right);
    }
    return left;
}
Exemplo n.º 6
0
static sl_node_base_t*
add_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = mul_expression(ps);
    sl_node_base_t* right;
    sl_token_t* tok;
    while(peek_token(ps)->type == SL_TOK_PLUS || peek_token(ps)->type == SL_TOK_MINUS) {
        tok = next_token(ps);
        right = mul_expression(ps);
        left = sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right);
    }
    return left;
}
Exemplo n.º 7
0
static sl_node_base_t*
power_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = inc_dec_expression(ps);
    sl_node_base_t* right;
    sl_token_t* tok;
    if(peek_token(ps)->type == SL_TOK_POW) {
        tok = next_token(ps);
        right = power_expression(ps);
        left = sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right);
    }
    return left;
}
Exemplo n.º 8
0
static sl_node_base_t*
mul_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = unary_expression(ps);
    sl_node_base_t* right;
    sl_token_t* tok;
    while(peek_token(ps)->type == SL_TOK_TIMES || peek_token(ps)->type == SL_TOK_DIVIDE ||
            peek_token(ps)->type == SL_TOK_MOD) {
        tok = next_token(ps);
        right = unary_expression(ps);
        left = sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right, false);
    }
    return left;
}
Exemplo n.º 9
0
static sl_node_base_t*
bitwise_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = shift_expression(ps);
    sl_node_base_t* right;
    sl_token_t* tok;
    while(1) {
        switch(peek_token(ps)->type) {
            case SL_TOK_PIPE:
            case SL_TOK_AMP:
            case SL_TOK_CARET:
                tok = next_token(ps);
                right = shift_expression(ps);
                left = sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right);
                break;
            default:
                return left;
        }
    }
}
Exemplo n.º 10
0
static sl_node_base_t*
relational_expression(sl_parse_state_t* ps)
{
    sl_node_base_t* left = bitwise_expression(ps);
    sl_token_t* tok;
    sl_node_base_t* right;
    switch(peek_token(ps)->type) {
        case SL_TOK_DBL_EQUALS:
        case SL_TOK_NOT_EQUALS:
        case SL_TOK_LT:
        case SL_TOK_GT:
        case SL_TOK_LTE:
        case SL_TOK_GTE:
        case SL_TOK_SPACESHIP:
            tok = next_token(ps);
            right = bitwise_expression(ps);
            return sl_make_send_node(ps, left, sl_intern2(ps->vm, tok->str), 1, &right);
        default:
            return left;
    }
}