NODE(sl_node_var_t, var) { size_t frame; sl_compile_state_t* xcs = cs; size_t index = 0xCAFE; SLVAL err; frame = 0; while(xcs) { if(sl_st_lookup(xcs->vars, (sl_st_data_t)node->name, (sl_st_data_t*)&index)) { if(frame == 0) { op_mov(cs, index, dest); } else { op_get_outer(cs, frame, index, dest); mark_upper_scopes_as_closure_unsafe(cs, frame); } return; } xcs = xcs->parent; frame++; } err = sl_make_formatted_string(cs->vm, "Undefined variable %QV", node->name); 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); }
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; }
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; }
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; }
static sl_method_t* lookup_method_rec(sl_vm_t* vm, SLVAL klass, SLID id) { sl_class_t* klassp = (sl_class_t*)sl_get_ptr(klass); if(klassp->base.primitive_type == SL_T_NIL) { return NULL; } sl_method_t* method; if(sl_st_lookup(klassp->instance_methods, (sl_st_data_t)id.id, (sl_st_data_t*)&method)) { return method; } return lookup_method_rec(vm, klassp->super, id); }
static SLID sl_intern2_no_check(sl_vm_t* vm, SLVAL str) { SLID id; if(sl_st_lookup(vm->intern.name_to_id, (sl_st_data_t)sl_get_ptr(str), (sl_st_data_t*)&id)) { return id; } id.id = vm->intern.id_to_name_size++; sl_st_insert(vm->intern.name_to_id, (sl_st_data_t)sl_get_ptr(str), (sl_st_data_t)id.id); if(vm->intern.id_to_name_size >= vm->intern.id_to_name_cap) { vm->intern.id_to_name_cap *= 2; vm->intern.id_to_name = sl_realloc(vm->arena, vm->intern.id_to_name, sizeof(SLVAL) * vm->intern.id_to_name_cap); } vm->intern.id_to_name[id.id] = str; return id; }
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; }