void sl_init_ext_mysql(sl_vm_t* vm) { SLVAL MySQL, MySQL_Error, MySQL_Statement; MySQL = sl_define_class(vm, "MySQL", vm->lib.Object); sl_class_set_allocator(vm, MySQL, allocate_mysql); sl_define_method(vm, MySQL, "init", 3, sl_mysql_init); sl_define_method(vm, MySQL, "use", 1, sl_mysql_use); sl_define_method(vm, MySQL, "query", -2, sl_mysql_query); sl_define_method(vm, MySQL, "prepare", 1, sl_mysql_prepare); sl_define_method(vm, MySQL, "escape", 1, sl_mysql_escape); sl_define_method(vm, MySQL, "insert_id", 0, sl_mysql_insert_id); MySQL_Error = sl_define_class3(vm, sl_intern(vm, "Error"), vm->lib.Error, MySQL); MySQL_Statement = sl_define_class3(vm, sl_intern(vm, "Statement"), vm->lib.Object, MySQL); sl_class_set_allocator(vm, MySQL_Statement, allocate_mysql_stmt); sl_define_method(vm, MySQL_Statement, "param_count", 0, sl_mysql_stmt_param_count); sl_define_method(vm, MySQL_Statement, "execute", -1, sl_mysql_stmt_execute); sl_define_method(vm, MySQL_Statement, "insert_id", 0, sl_mysql_stmt_insert_id); vm->store[cMySQL] = MySQL; vm->store[cMySQL_Error] = MySQL_Error; vm->store[cMySQL_Statement] = MySQL_Statement; sl_do_string(vm, (uint8_t*)sl__ext_mysql_extensions_sl, strlen(sl__ext_mysql_extensions_sl), "ext/mysql/extensions.sl", 0); }
void sl_init_ext_json(sl_vm_t* vm) { SLVAL JSON = sl_define_class(vm, "JSON", vm->lib.Object); SLVAL JSON_ParseError = sl_define_class3(vm, sl_intern(vm, "ParseError"), vm->lib.SyntaxError, JSON); SLVAL JSON_DumpError = sl_define_class3(vm, sl_intern(vm, "DumpError"), vm->lib.SyntaxError, JSON); sl_define_singleton_method(vm, JSON, "parse", -2, sl_json_parse); sl_define_singleton_method(vm, JSON, "dump", 1, sl_json_dump); sl_define_singleton_method(vm, JSON, "decode", -2, sl_json_parse); sl_define_singleton_method(vm, JSON, "encode", 1, sl_json_dump); vm->store[cJSON] = JSON; vm->store[cJSON_ParseError] = JSON_ParseError; vm->store[cJSON_DumpError] = JSON_DumpError; }
void sl_init_regexp(sl_vm_t* vm) { vm->lib.Regexp = sl_define_class(vm, "Regexp", vm->lib.Object); sl_class_set_allocator(vm, vm->lib.Regexp, allocate_regexp); vm->lib.Regexp_Match = sl_define_class3(vm, sl_intern(vm, "Match"), vm->lib.Object, vm->lib.Regexp); sl_class_set_allocator(vm, vm->lib.Regexp_Match, allocate_regexp_match); sl_define_method(vm, vm->lib.Regexp, "init", -2, sl_regexp_init); /* sl_define_method(vm, vm->lib.Regexp, "compile", 0, sl_regexp_compile); */ sl_define_method(vm, vm->lib.Regexp, "match", -2, sl_regexp_match); sl_define_method(vm, vm->lib.Regexp, "source", 0, sl_regexp_source); sl_define_method(vm, vm->lib.Regexp, "options", 0, sl_regexp_options); sl_define_method(vm, vm->lib.Regexp, "==", 1, sl_regexp_eq); sl_class_set_const(vm, vm->lib.Regexp, "CASELESS", sl_make_int(vm, PCRE_CASELESS)); sl_class_set_const(vm, vm->lib.Regexp, "EXTENDED", sl_make_int(vm, PCRE_EXTENDED)); sl_class_set_const(vm, vm->lib.Regexp, "PCRE_VERSION", sl_make_cstring(vm, pcre_version())); sl_define_method(vm, vm->lib.Regexp_Match, "regexp", 0, sl_regexp_match_regexp); sl_define_method(vm, vm->lib.Regexp_Match, "[]", 1, sl_regexp_match_index); sl_define_method(vm, vm->lib.Regexp_Match, "byte_offset", 1, sl_regexp_match_byte_offset); sl_define_method(vm, vm->lib.Regexp_Match, "offset", 1, sl_regexp_match_offset); sl_define_method(vm, vm->lib.Regexp_Match, "capture", 1, sl_regexp_match_capture); sl_define_method(vm, vm->lib.Regexp_Match, "length", 0, sl_regexp_match_length); sl_define_method(vm, vm->lib.Regexp_Match, "before", 0, sl_regexp_match_before); sl_define_method(vm, vm->lib.Regexp_Match, "after", 0, sl_regexp_match_after); }
void sl_init_string(sl_vm_t* vm) { sl_st_insert(((sl_class_t*)sl_get_ptr(vm->lib.Object))->constants, (sl_st_data_t)sl_intern(vm, "String").id, (sl_st_data_t)vm->lib.String.i); sl_define_method(vm, vm->lib.String, "length", 0, sl_string_length); sl_define_method(vm, vm->lib.String, "byte_length", 0, sl_string_byte_length); sl_define_method(vm, vm->lib.String, "concat", 1, sl_string_concat); sl_define_method(vm, vm->lib.String, "+", 1, sl_string_concat); sl_define_method(vm, vm->lib.String, "*", 1, sl_string_times); sl_define_method(vm, vm->lib.String, "to_s", 0, sl_string_to_s); sl_define_method(vm, vm->lib.String, "to_i", 0, sl_string_to_i); sl_define_method(vm, vm->lib.String, "to_f", 0, sl_string_to_f); sl_define_method(vm, vm->lib.String, "inspect", 0, sl_string_inspect); sl_define_method(vm, vm->lib.String, "html_escape", 0, sl_string_html_escape); sl_define_method(vm, vm->lib.String, "url_decode", 0, sl_string_url_decode); sl_define_method(vm, vm->lib.String, "url_encode", 0, sl_string_url_encode); sl_define_method(vm, vm->lib.String, "index", 1, sl_string_index); sl_define_method(vm, vm->lib.String, "[]", 1, sl_string_char_at_index); sl_define_method(vm, vm->lib.String, "split", -2, sl_string_split); sl_define_method(vm, vm->lib.String, "==", 1, sl_string_eq); sl_define_method(vm, vm->lib.String, "~", 1, sl_string_is_match); sl_define_method(vm, vm->lib.String, "<=>", 1, sl_string_spaceship); sl_define_method(vm, vm->lib.String, "hash", 0, sl_string_hash); sl_define_method(vm, vm->lib.String, "encode", 1, sl_string_encode2); sl_define_method(vm, vm->lib.String, "replace", 2, sl_string_replace); sl_define_method(vm, vm->lib.String, "upper", 0, sl_string_upper); sl_define_method(vm, vm->lib.String, "lower", 0, sl_string_lower); }
static SLVAL sl_new_oserror(sl_vm_t* vm, int errno) { char* description = strerror(errno); SLVAL Posix_OSError = vm->store[cPosix_OSError]; SLVAL error = sl_make_error2(vm, Posix_OSError, sl_make_cstring(vm, description)); sl_set_ivar(vm, error, sl_intern(vm, "errno"), sl_make_int(vm, errno)); return error; }
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: next_token(ps); expr = unary_expression(ps); return sl_make_send_node(ps, expr, sl_intern(ps->vm, "-self"), 0, NULL, false); case SL_TOK_TILDE: next_token(ps); expr = unary_expression(ps); return sl_make_send_node(ps, expr, sl_intern(ps->vm, "~self"), 0, NULL, false); 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); } }
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; } } }
SLVAL sl_send(sl_vm_t* vm, SLVAL recv, char* id, int argc, ...) { SLVAL* argv = alloca(argc * sizeof(SLVAL)); va_list va; va_start(va, argc); for(int i = 0; i < argc; i++) { argv[i] = va_arg(va, SLVAL); } va_end(va); return sl_send2(vm, recv, sl_intern(vm, id), argc, argv); }
void sl_init_range(sl_vm_t* vm) { vm->lib.Range = sl_define_class(vm, "Range", vm->lib.Enumerable); sl_class_set_allocator(vm, vm->lib.Range, allocate_range); sl_define_method(vm, vm->lib.Range, "init", -3, range_init); sl_define_method(vm, vm->lib.Range, "enumerate", 0, range_enumerate); vm->lib.Range_Enumerator = sl_define_class3(vm, sl_intern(vm, "Enumerator"), vm->lib.Object, vm->lib.Range); sl_class_set_allocator(vm, vm->lib.Range_Enumerator, allocate_range_enumerator); sl_define_method(vm, vm->lib.Range_Enumerator, "current", 0, range_enumerator_current); sl_define_method(vm, vm->lib.Range_Enumerator, "next", 0, range_enumerator_next); }
void sl_init_ext_posix(sl_vm_t* vm) { SLVAL Posix = sl_define_class(vm, "Posix", vm->lib.Object); SLVAL Posix_OSError = sl_define_class3(vm, sl_intern(vm, "OSError"), vm->lib.Error, Posix); sl_define_method(vm, Posix_OSError, "errno", 0, sl_posix_oserror_get_errno); vm->store[cPosix_OSError] = Posix_OSError; sl_init_ext_posix_errno(vm, Posix); sl_init_ext_posix_fork(vm, Posix); sl_init_ext_posix_getpid(vm, Posix); }
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 */ } }
NODE(sl_node_lambda_t, lambda) { sl_compile_state_t sub_cs; size_t i; init_compile_state(&sub_cs, cs->vm, cs, node->arg_count + 1); for(i = 0; i < node->arg_count; i++) { sl_st_insert(sub_cs.vars, (sl_st_data_t)node->args[i], (sl_st_data_t)(i + 1)); } sub_cs.section->req_registers = node->arg_count; sub_cs.section->arg_registers = node->arg_count; sub_cs.section->name = sl_intern(cs->vm, "<lambda>"); compile_node(&sub_cs, node->body, 0); op_return(&sub_cs, 0); op_lambda(cs, sub_cs.section, dest); }
static void sl_ruby_protect(sl_vm_t* vm, void(*func)(sl_vm_t*,void*), void* data) { struct sl_ruby_protect_args args = { vm, data, func, 0, { 0 } }; sl_vm_frame_t frame; pthread_mutex_lock(&sl_ruby_lock); SL_ENSURE(frame, { rb_rescue2(sl_ruby_protect_try, (VALUE)&args, sl_ruby_protect_catch, (VALUE)&args, rb_eException, 0); pthread_mutex_unlock(&sl_ruby_lock); if(args.exception) { SLVAL Ruby_Exception = sl_vm_store_get(vm, &cRuby_Exception); SLVAL err = sl_allocate(vm, Ruby_Exception); sl_error_set_message(vm, err, sl_ruby_to_slash(vm, rb_obj_as_string(args.exception))); sl_set_ivar(vm, err, sl_intern(vm, "object"), make_ruby_object(vm, args.exception)); args.sl_exception = err; } }, {
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 */ } }
static SLVAL sl_posix_oserror_get_errno(sl_vm_t* vm, SLVAL self) { return sl_get_ivar(vm, self, sl_intern(vm, "errno")); }
int sl_responds_to(sl_vm_t* vm, SLVAL object, char* id) { return sl_responds_to2(vm, object, sl_intern(vm, id)); }