Пример #1
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;
        }
    }
}
Пример #2
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));
}
Пример #3
0
static SLID
def_expression_method_name(sl_parse_state_t* ps)
{
    switch(peek_token(ps)->type) {
        case SL_TOK_IDENTIFIER:
            return sl_intern2(ps->vm, next_token(ps)->str);
        /* operators: */
        case SL_TOK_SHIFT_LEFT:
        case SL_TOK_SHIFT_RIGHT:
        case SL_TOK_DBL_EQUALS:
        case SL_TOK_NOT_EQUALS:
        case SL_TOK_SPACESHIP:
        case SL_TOK_LTE:
        case SL_TOK_LT:
        case SL_TOK_GTE:
        case SL_TOK_GT:
        case SL_TOK_PLUS:
        case SL_TOK_POW:
        case SL_TOK_TIMES:
        case SL_TOK_DIVIDE:
        case SL_TOK_MOD:
        case SL_TOK_CARET:
        case SL_TOK_AMP:
        case SL_TOK_PIPE:
            return sl_intern2(ps->vm, next_token(ps)->str);
        /* operators that can also be unary: */
        case SL_TOK_MINUS:
        case SL_TOK_TILDE:
        {
            sl_token_t* tok = next_token(ps);
            if(peek_token(ps)->type == SL_TOK_SELF) {
                return sl_intern2(ps->vm, sl_string_concat(ps->vm, tok->str, next_token(ps)->str));
            } else {
                return sl_intern2(ps->vm, tok->str);
            }
            break;
        }
        /* keywords: */
        case SL_TOK_LAST:
        case SL_TOK_NEXT:
            return sl_intern2(ps->vm, next_token(ps)->str);
        case SL_TOK_OPEN_BRACKET:
            next_token(ps);
            expect_token(ps, SL_TOK_CLOSE_BRACKET);
            return sl_intern(ps->vm, "[]");
        default:
            unexpected(ps, next_token(ps));
            SLID dummy;
            return dummy; /* never reached */
    }
}
Пример #4
0
static SLID
def_expression_method_name(sl_parse_state_t* ps)
{
    switch(peek_token(ps)->type) {
        case SL_TOK_IDENTIFIER:
            return sl_intern2(ps->vm, next_token(ps)->str);
        /* operators: */
        case SL_TOK_SHIFT_LEFT:
        case SL_TOK_SHIFT_RIGHT:
        case SL_TOK_DBL_EQUALS:
        case SL_TOK_NOT_EQUALS:
        case SL_TOK_SPACESHIP:
        case SL_TOK_LTE:
        case SL_TOK_LT:
        case SL_TOK_GTE:
        case SL_TOK_GT:
        case SL_TOK_PLUS:
        case SL_TOK_MINUS:
        case SL_TOK_POW:
        case SL_TOK_TIMES:
        case SL_TOK_DIVIDE:
        case SL_TOK_MOD:
        case SL_TOK_CARET:
        case SL_TOK_TILDE:
        case SL_TOK_AMP:
        case SL_TOK_PIPE:
            return sl_intern2(ps->vm, next_token(ps)->str);
        /* keywords: */
        case SL_TOK_LAST:
        case SL_TOK_NEXT:
            return sl_intern2(ps->vm, next_token(ps)->str);
        case SL_TOK_OPEN_BRACKET:
            if(peek_token_n(ps, 2)->type == SL_TOK_CLOSE_BRACKET) {
                next_token(ps);
                next_token(ps);
                return sl_intern(ps->vm, "[]");
            }
        default:
            unexpected(ps, next_token(ps));
            SLID dummy;
            return dummy; /* never reached */
    }
}
Пример #5
0
static SLVAL
sl_class_own_instance_method(sl_vm_t* vm, SLVAL self, SLVAL method_name)
{
    sl_class_t* klass = get_class(vm, self);
    SLVAL method;
    SLID mid = sl_intern2(vm, method_name);
    if(sl_st_lookup(klass->instance_methods, (sl_st_data_t)mid.id, (sl_st_data_t*)&method)) {
        return method;
    }
    return vm->lib.nil;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
0
static SLVAL
sl_class_own_instance_method(sl_vm_t* vm, SLVAL self, SLVAL method_name)
{
    sl_class_t* klass = get_class(vm, self);
    SLVAL method;
    SLID mid = sl_intern2(vm, method_name);
    method_name = sl_to_s(vm, method_name);
    if(sl_st_lookup(klass->instance_methods, (sl_st_data_t)mid.id, (sl_st_data_t*)&method)) {
        if(sl_get_primitive_type(method) != SL_T_CACHED_METHOD_ENTRY) {
            return method;
        }
    }
    return vm->lib.nil;
}
Пример #11
0
static SLVAL
sl_class_instance_method(sl_vm_t* vm, SLVAL self, SLVAL method_name)
{
    sl_class_t* klass = get_class(vm, self);
    SLVAL method;
    SLID mid = sl_intern2(vm, method_name);
    method_name = sl_to_s(vm, method_name);
    if(sl_st_lookup(klass->instance_methods, (sl_st_data_t)mid.id, (sl_st_data_t*)&method)) {
        return method;
    }
    if(sl_get_primitive_type(klass->super) == SL_T_CLASS) {
        return sl_class_instance_method(vm, klass->super, method_name);
    }
    return vm->lib.nil;
}
Пример #12
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);
}
Пример #13
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);
    }
}
Пример #14
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;
        }
    }
}
Пример #15
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;
    }
}
Пример #16
0
static SLVAL
sl_class_instance_method(sl_vm_t* vm, SLVAL self, SLVAL method_name)
{
    sl_class_t* klass = get_class(vm, self);
    SLVAL method;
    SLID mid = sl_intern2(vm, method_name);
    method_name = sl_to_s(vm, method_name);
    if(sl_st_lookup(klass->instance_methods, (sl_st_data_t)mid.id, (sl_st_data_t*)&method)) {
        if(sl_get_primitive_type(method) == SL_T_CACHED_METHOD_ENTRY) {
            sl_cached_method_entry_t* cme = (void*)sl_get_ptr(method);
            // TODO - improve cache invalidation. this is too coarse
            if(cme->state == vm->state_method) {
                return sl_make_ptr((sl_object_t*)cme->method);
            }
        } else {
            return method;
        }
    }
    if(sl_get_primitive_type(klass->super) == SL_T_CLASS) {
        return sl_class_instance_method(vm, klass->super, method_name);
    }
    return vm->lib.nil;
}
Пример #17
0
NODE(sl_node_var_t, cvar)
{
    SLID id = sl_intern2(cs->vm, sl_make_ptr((sl_object_t*)node->name));
    op_get_cvar(cs, id, dest);
}
Пример #18
0
SLID
sl_intern(sl_vm_t* vm, char* cstr)
{
    return sl_intern2(vm, sl_make_cstring(vm, cstr));
}
Пример #19
0
SLID
sl_id_make_setter(sl_vm_t* vm, SLID id)
{
    SLVAL str = sl_make_formatted_string(vm, "%I=", id);
    return sl_intern2(vm, str);
}
Пример #20
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);
}
Пример #21
0
static sl_node_base_t*
primary_expression(sl_parse_state_t* ps)
{
    sl_token_t* tok;
    sl_node_base_t* node;
    switch(peek_token(ps)->type) {
        case SL_TOK_INTEGER:
            tok = next_token(ps);
            return sl_make_immediate_node(ps, sl_integer_parse(ps->vm, tok->as.str.buff, tok->as.str.len));
        case SL_TOK_FLOAT:
            return sl_make_immediate_node(ps, sl_make_float(ps->vm, next_token(ps)->as.dbl));
        case SL_TOK_STRING:
            tok = next_token(ps);
            return sl_make_immediate_node(ps, sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
        case SL_TOK_REGEXP:
            return regexp_expression(ps);
        case SL_TOK_CONSTANT:
            tok = next_token(ps);
            return sl_make_const_node(ps, NULL, sl_intern2(ps->vm, sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len)));
        case SL_TOK_IDENTIFIER:
            tok = next_token(ps);
            return sl_make_var_node(ps, SL_NODE_VAR,
                sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
        case SL_TOK_TRUE:
            next_token(ps);
            return sl_make_immediate_node(ps, ps->vm->lib._true);
        case SL_TOK_FALSE:
            next_token(ps);
            return sl_make_immediate_node(ps, ps->vm->lib._false);
        case SL_TOK_NIL:
            next_token(ps);
            return sl_make_immediate_node(ps, ps->vm->lib.nil);
        case SL_TOK_SELF:
            next_token(ps);
            return sl_make_self_node(ps);
        case SL_TOK_IVAR:
            tok = next_token(ps);
            node = sl_make_var_node(ps, SL_NODE_IVAR,
                sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
            return node;
        case SL_TOK_CVAR:
            tok = next_token(ps);
            node = sl_make_var_node(ps, SL_NODE_CVAR,
                sl_make_string(ps->vm, tok->as.str.buff, tok->as.str.len));
            return node;
        case SL_TOK_IF:
        case SL_TOK_UNLESS:
            return if_expression(ps);
        case SL_TOK_WHILE:
        case SL_TOK_UNTIL:
            return while_expression(ps);
        case SL_TOK_FOR:
            return for_expression(ps);
        case SL_TOK_CLASS:
            return class_expression(ps);
        case SL_TOK_DEF:
            return def_expression(ps);
        case SL_TOK_LAMBDA:
            return lambda_expression(ps);
        case SL_TOK_TRY:
            return try_expression(ps);
        case SL_TOK_OPEN_BRACKET:
            return array_expression(ps);
        case SL_TOK_OPEN_PAREN:
            return bracketed_expression(ps);
        case SL_TOK_OPEN_BRACE:
            return dict_expression(ps);
        case SL_TOK_NEXT:
            tok = next_token(ps);
            if(!(ps->scope->flags & SL_PF_CAN_NEXT_LAST)) {
                error(ps, sl_make_cstring(ps->vm, "next invalid outside loop"), tok);
            }
            return sl_make_singleton_node(ps, SL_NODE_NEXT);
        case SL_TOK_LAST:
            tok = next_token(ps);
            if(!(ps->scope->flags & SL_PF_CAN_NEXT_LAST)) {
                error(ps, sl_make_cstring(ps->vm, "last invalid outside loop"), tok);
            }
            return sl_make_singleton_node(ps, SL_NODE_LAST);
        case SL_TOK_RANGE_EX:
            next_token(ps);
            return sl_make_singleton_node(ps, SL_NODE_YADA_YADA);
        default:
            unexpected(ps, peek_token(ps));
            return NULL;
    }
}