static int own_instance_methods_iter(sl_vm_t* vm, SLID name, SLVAL method, SLVAL ary) { SLVAL namev = sl_id_to_string(vm, name); sl_array_push(vm, ary, 1, &namev); return SL_ST_CONTINUE; (void)method; }
static SLVAL sl_method_name(sl_vm_t* vm, SLVAL method) { sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); if(!methp->initialized) { return vm->lib.nil; } return sl_id_to_string(vm, methp->name); }
static SLVAL sl_method_name(sl_vm_t* vm, SLVAL method) { sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); if(!(methp->base.user_flags & SL_FLAG_METHOD_INITIALIZED)) { return vm->lib.nil; } return sl_id_to_string(vm, methp->extra->name); }
static int own_instance_methods_iter(sl_vm_t* vm, SLID name, SLVAL method, SLVAL ary) { if(sl_get_primitive_type(method) != SL_T_CACHED_METHOD_ENTRY) { SLVAL namev = sl_id_to_string(vm, name); sl_array_push(vm, ary, 1, &namev); } return SL_ST_CONTINUE; }
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->extra->in) == (sl_object_t*)object) { return sl_id_to_string(vm, klass->extra->name); } else { return sl_make_formatted_string(vm, "%V::%I", sl_class_to_s(vm, klass->extra->in), klass->extra->name); } }
static SLVAL sl_send_missing(sl_vm_t* vm, SLVAL recv, SLID id, int argc, SLVAL* argv) { /* look for method_missing method */ SLVAL argv2[argc + 1]; memcpy(&argv2[1], argv, sizeof(SLVAL) * argc); argv2[0] = sl_id_to_string(vm, id); sl_method_t* method = sl_lookup_method(vm, recv, vm->id.method_missing); if(method) { return sl_apply_method(vm, recv, method, argc + 1, argv2); } /* nope */ sl_error(vm, vm->lib.NoMethodError, "Undefined method %QI on %X", id, recv); return vm->lib.nil; /* shutup gcc */ }
static SLVAL sl_class_name(sl_vm_t* vm, SLVAL self) { return sl_id_to_string(vm, get_class(vm, self)->extra->name); }
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); }
// somewhat similar to sprintf // // Valid formats: // // %V - Slash value, converted to string first with #to_s // %I - Slash ID // %s - C string // %d - integer // %% - literal '%' sign // // You may add the 'Q' modifier to a format specifier to quote it in double // quotes. For example "%QV" would quote the value when interpolating it into // the string SLVAL sl_make_formatted_string_va(struct sl_vm* vm, const char* format, va_list va) { SLVAL strings = sl_make_array(vm, 0, NULL); const char *current_ptr = format, *next_ptr; SLVAL quote = vm->lib.nil; while((next_ptr = strchr(current_ptr, '%'))) { if(next_ptr != current_ptr) { SLVAL literal = sl_make_string(vm, (uint8_t*)current_ptr, (size_t)(next_ptr - current_ptr)); sl_array_push(vm, strings, 1, &literal); } SLVAL element = vm->lib.nil; bool quoted = false; again: switch(next_ptr[1]) { case 'Q': { if(sl_get_primitive_type(quote) == SL_T_NIL) { quote = sl_make_cstring(vm, "\""); } sl_array_push(vm, strings, 1, "e); next_ptr++; quoted = true; goto again; } case 'V': { element = va_arg(va, SLVAL); break; } case 'X': { element = va_arg(va, SLVAL); element = sl_inspect(vm, element); break; } case 'I': { SLID id = va_arg(va, SLID); element = sl_id_to_string(vm, id); break; } case 's': { char* cstr = va_arg(va, char*); element = sl_make_cstring(vm, cstr); break; } case 'd': { char buff[32]; int num = va_arg(va, int); sprintf(buff, "%d", num); element = sl_make_cstring(vm, buff); break; } case 'p': { char buff[32]; void* ptr = va_arg(va, void*); sprintf(buff, "%p", ptr); element = sl_make_cstring(vm, buff); break; } case 0: { return vm->lib.nil; } default: { element = sl_make_string(vm, (uint8_t*)(next_ptr + 1), 1); break; } } sl_array_push(vm, strings, 1, &element); if(quoted) { sl_array_push(vm, strings, 1, "e); quoted = false; } current_ptr = next_ptr + 2; } if(current_ptr[0]) { SLVAL element = sl_make_cstring(vm, current_ptr); sl_array_push(vm, strings, 1, &element); } return sl_array_join(vm, strings, 0, NULL); }