Esempio n. 1
0
File: string.c Progetto: richo/slash
static SLVAL
sl_string_replace(sl_vm_t* vm, SLVAL self, SLVAL search, SLVAL replace)
{
    if(sl_is_a(vm, search, vm->lib.String)) {
        return sl_enumerable_join(vm, sl_string_split(vm, self, 1, &search), 1, &replace);
    }

    sl_expect(vm, search, vm->lib.Regexp);

    SLVAL retn = sl_make_cstring(vm, "");

    while(1) {
        SLVAL match = sl_regexp_match(vm, search, 1, &self);

        if(!sl_is_truthy(match)) {
            return sl_string_concat(vm, retn, self);
        } else {
            SLVAL part = sl_regexp_match_before(vm, match);
            if(sl_is_a(vm, replace, vm->lib.String)) {
                part = sl_string_concat(vm, part, replace);
            } else {
                part = sl_string_concat(vm, part, sl_send_id(vm, replace, vm->id.call, 1, match));
            }
            retn = sl_string_concat(vm, retn, part);
        }

        self = sl_regexp_match_after(vm, match);
    }
}
Esempio n. 2
0
static SLVAL
sl_gcrypt_algorithm_inspect(sl_vm_t* vm, SLVAL self)
{
    gcrypt_algorithm_t* algo = get_algo(vm, self);
    SLVAL str = sl_make_cstring(vm, "#<GCrypt::Algorithm: ");
    str = sl_string_concat(vm, str, algo->name);
    str = sl_string_concat(vm, str, sl_make_cstring(vm, ">"));
    return str;
}
Esempio n. 3
0
static void
unexpected(sl_parse_state_t* ps, sl_token_t* tok)
{
    SLVAL err;
    if(tok->type != SL_TOK_END) {
        err = sl_make_cstring(ps->vm, "Unexpected '");
        err = sl_string_concat(ps->vm, err, tok->str);
        err = sl_string_concat(ps->vm, err, sl_make_cstring(ps->vm, "'"));
    } else {
        err = sl_make_cstring(ps->vm, "Unexpected end of file");
    }
    error(ps, err, tok);
}
Esempio n. 4
0
static SLVAL
response_set_cookie(sl_vm_t* vm, SLVAL self, SLVAL name, SLVAL value)
{
    SLVAL header;
    sl_expect(vm, name, vm->lib.String);
    sl_expect(vm, value, vm->lib.String);
    name = sl_string_url_encode(vm, name);
    value = sl_string_url_encode(vm, value);

    header = name;
    header = sl_string_concat(vm, header, sl_make_cstring(vm, "="));
    header = sl_string_concat(vm, header, value);

    return response_set_header(vm, self, sl_make_cstring(vm, "Set-Cookie"), header);
}
Esempio n. 5
0
static SLVAL
sl_class_to_s(sl_vm_t* vm, SLVAL self)
{
    sl_class_t* klass = get_class(vm, self);
    sl_class_t* object = (sl_class_t*)sl_get_ptr(vm->lib.Object);
    if(klass == object || sl_get_ptr(klass->in) == (sl_object_t*)object) {
        return get_class(vm, self)->name;
    } else {
        return sl_string_concat(vm,
            sl_class_to_s(vm, klass->in),
            sl_string_concat(vm,
                sl_make_cstring(vm, "::"),
                klass->name));
    }
}
Esempio n. 6
0
SLVAL
sl_do_file(sl_vm_t* vm, char* filename)
{
    filename = sl_realpath(vm, filename);
    FILE* f = fopen(filename, "rb");
    uint8_t* src;
    size_t file_size;
    SLVAL err;
    
    if(!f) {
        err = sl_make_cstring(vm, "Could not load file: ");
        err = sl_string_concat(vm, err, sl_make_cstring(vm, filename));
        err = sl_string_concat(vm, err, sl_make_cstring(vm, " - "));
        err = sl_string_concat(vm, err, sl_make_cstring(vm, strerror(errno)));
        sl_throw(vm, sl_make_error2(vm, vm->lib.Error, err));
    }
    fseek(f, 0, SEEK_END);
    file_size = ftell(f);
    fseek(f, 0, SEEK_SET);
    src = sl_alloc(vm->arena, file_size);
    if(file_size && !fread(src, file_size, 1, f)) {
        fclose(f);
        err = sl_make_cstring(vm, "Could not load file: ");
        err = sl_string_concat(vm, err, sl_make_cstring(vm, filename));
        err = sl_string_concat(vm, err, sl_make_cstring(vm, " - "));
        err = sl_string_concat(vm, err, sl_make_cstring(vm, strerror(errno)));
        sl_throw(vm, sl_make_error2(vm, vm->lib.Error, err));
    }
    fclose(f);
    
    return sl_do_string(vm, src, file_size, filename, 0);
}
Esempio n. 7
0
SLVAL
sl_string_concat(sl_vm_t* vm, SLVAL self, SLVAL other)
{
    sl_string_t* a = sl_get_string(vm, self);
    sl_string_t* b = sl_get_string(vm, other);
    if(strcmp(a->encoding, b->encoding) != 0) {
        return sl_string_concat(vm, self, sl_string_encode(vm, other, a->encoding));
    }
    uint8_t* buff = (uint8_t*)sl_alloc_buffer(vm->arena, a->buff_len + b->buff_len);
    memcpy(buff, a->buff, a->buff_len);
    memcpy(buff + a->buff_len, b->buff, b->buff_len);
    return sl_make_string(vm, buff, a->buff_len + b->buff_len);
}
Esempio n. 8
0
SLVAL
sl_enumerable_join(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv)
{
    SLVAL enumerator = sl_send(vm, self, "enumerate", 0);
    SLVAL joiner, val, str;
    if(argc) {
        joiner = sl_to_s(vm, argv[0]);
    } else {
        joiner = sl_make_cstring(vm, "");
    }
    if(!sl_is_truthy(sl_send(vm, enumerator, "next", 0))) {
        return sl_make_cstring(vm, "");
    }
    str = sl_to_s(vm, sl_send(vm, enumerator, "current", 0));
    while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) {
        val = sl_send(vm, enumerator, "current", 0);
        val = sl_to_s(vm, val);
        str = sl_string_concat(vm, str, joiner);
        str = sl_string_concat(vm, str, val);
    }
    return str;
}
Esempio n. 9
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 */
    }
}
Esempio n. 10
0
NODE(sl_node_var_t, var)
{
    sl_vm_insn_t insn;
    size_t frame;
    sl_compile_state_t* xcs = cs;
    size_t index = 0xCAFE;
    SLVAL err;
    frame = 0;
    while(xcs) {
        if(st_lookup(xcs->vars, (st_data_t)node->name, (st_data_t*)&index)) {
            if(frame == 0) {
                insn.opcode = SL_OP_MOV;
                emit(cs, insn);
            } else {
                insn.opcode = SL_OP_GET_OUTER;
                emit(cs, insn);
                insn.uint = frame;
                emit(cs, insn);
                mark_upper_scopes_as_closure_unsafe(cs, frame);
            }
            insn.uint = index;
            emit(cs, insn);
            insn.uint = dest;
            emit(cs, insn);
            return;
        }
        xcs = xcs->parent;
        frame++;
    }
    err = sl_make_cstring(cs->vm, "Undefined variable '");
    err = sl_string_concat(cs->vm, err, sl_make_ptr((sl_object_t*)node->name));
    err = sl_string_concat(cs->vm, err, sl_make_cstring(cs->vm, "' "));
    err = sl_make_error2(cs->vm, cs->vm->lib.NameError, err);
    sl_error_add_frame(cs->vm, err, sl_make_cstring(cs->vm, "<compiler>"), sl_make_cstring(cs->vm, (char*)cs->section->filename), sl_make_int(cs->vm, node->base.line));
    sl_throw(cs->vm, err);
}
Esempio n. 11
0
static void
emit_assignment(sl_compile_state_t* cs, sl_node_base_t* lval, size_t reg)
{
    sl_node_assign_var_t a_var;
    sl_node_send_t send;
    
    size_t dest_reg = reg_alloc(cs);
    
    sl_node__register_t node;
    sl_node__register_t* node_p = &node;
    node.base.type = SL_NODE__REGISTER;
    node.base.line = 0;
    node.reg = reg;
    
    switch(lval->type) {
        case SL_NODE_VAR:    a_var.base.type = SL_NODE_ASSIGN_VAR;    break;
        case SL_NODE_IVAR:   a_var.base.type = SL_NODE_ASSIGN_IVAR;   break;
        case SL_NODE_CVAR:   a_var.base.type = SL_NODE_ASSIGN_CVAR;   break;
        case SL_NODE_CONST:  a_var.base.type = SL_NODE_ASSIGN_CONST;  break;
        case SL_NODE_ARRAY:  a_var.base.type = SL_NODE_ASSIGN_ARRAY;  break;
        case SL_NODE_SEND:
            /* special case that turns a.b = 1 into a.send("b=", 1) */
            /* this is separate to the other method of handling send assignments
               which also handles compound assignments. */
            memcpy(&send, lval, sizeof(sl_node_send_t));
            send.id = sl_string_concat(cs->vm, send.id, sl_make_cstring(cs->vm, "="));
            send.arg_count = 1;
            send.args = (sl_node_base_t**)&node_p;
            compile_node(cs, (sl_node_base_t*)&send, dest_reg);
            reg_free(cs, dest_reg);
            return;
        default: {
            SLVAL err = sl_make_cstring(cs->vm, "Invalid lval in assignment");
            err = sl_make_error2(cs->vm, cs->vm->lib.SyntaxError, err);
            sl_error_add_frame(cs->vm, err, sl_make_cstring(cs->vm, "<compiler>"), sl_make_cstring(cs->vm, (char*)cs->section->filename), sl_make_int(cs->vm, lval->line));
            sl_throw(cs->vm, err);
        }
    }
    
    a_var.base.line = 0;
    a_var.lval = (void*)lval;
    a_var.rval = (sl_node_base_t*)&node;
    compile_node(cs, (sl_node_base_t*)&a_var, dest_reg);
    
    reg_free(cs, dest_reg);
}
Esempio n. 12
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);
}
Esempio n. 13
0
void
sl_render_error_page(sl_vm_t* vm, SLVAL err)
{
    sl_vm_frame_t frame;
    sl_response_internal_opts_t* resp = response(vm);
    resp->status = 500;
    SLVAL caught_error;
    if(resp->descriptive_error_pages) {
        SL_TRY(frame, SL_UNWIND_EXCEPTION, {
            SLVAL error_lambda = sl_do_string(vm, (uint8_t*)sl__src_lib_error_page_sl, strlen(sl__src_lib_error_page_sl), "(error-page)", 0);
            sl_lambda_call(vm, error_lambda, 1, &err);
        }, caught_error, {
            sl_response_write(vm,
                sl_string_concat(vm,
                    sl_make_cstring(vm, "<h1>Internal Server Error</h1><pre>"),
                    sl_string_concat(vm,
                        sl_string_html_escape(vm, sl_to_s_no_throw(vm, caught_error)),
                        sl_make_cstring(vm, "</pre>"))));
        });
    } else {
        sl_response_write(vm, sl_make_cstring(vm, "<h1>Internal Server Error</h1>"));
    }
}

void
sl_init_response(sl_vm_t* vm)
{
    SLVAL Response = sl_new(vm, vm->lib.Object, 0, NULL);
    sl_vm_store_put(vm, &Response_, Response);

    sl_define_singleton_method(vm, Response, "write", -2, sl_response_write);
Esempio n. 14
0
static SLVAL
bignum_ordinalize(sl_vm_t* vm, SLVAL self)
{
    long rem = sl_bignum_get_long(vm, sl_bignum_mod(vm, self, sl_make_int(vm, 10)));
    return sl_string_concat(vm, sl_to_s(vm, self), ordinalize(vm, rem % 10));
}
Esempio n. 15
0
static SLVAL
int_ordinalize(sl_vm_t* vm, SLVAL self)
{
    int i = sl_get_int(self);
    return sl_string_concat(vm, sl_to_s(vm, self), ordinalize(vm, i % 10));
}