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_instance_method(sl_vm_t* vm, SLVAL self, SLVAL method_name) { sl_class_t* klass = get_class(vm, self); SLVAL method; method_name = sl_to_s(vm, method_name); if(st_lookup(klass->instance_methods, (st_data_t)sl_get_ptr(method_name), (st_data_t*)&method)) { return method; } else 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 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; }
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 void json_dump(json_dump_t* state, SLVAL object) { sl_string_t* str; size_t i, len; SLVAL* keys; switch(sl_get_primitive_type(object)) { case SL_T_NIL: JSON_DUMP_NEED_BYTES(4); memcpy(state->buffer + state->buffer_len, "null", 4); state->buffer_len += 4; break; case SL_T_TRUE: JSON_DUMP_NEED_BYTES(4); memcpy(state->buffer + state->buffer_len, "true", 4); state->buffer_len += 4; break; case SL_T_FALSE: JSON_DUMP_NEED_BYTES(5); memcpy(state->buffer + state->buffer_len, "false", 5); state->buffer_len += 5; break; case SL_T_INT: str = (sl_string_t*)sl_get_ptr(sl_int_to_s(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_FLOAT: str = (sl_string_t*)sl_get_ptr(sl_float_to_s(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_BIGNUM: str = (sl_string_t*)sl_get_ptr(sl_bignum_to_s(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_STRING: str = (sl_string_t*)sl_get_ptr(sl_string_inspect(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_ARRAY: JSON_CHECK_RECURSION(object); JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = '['; len = sl_get_int(sl_array_length(state->vm, object)); for(i = 0; i < len; i++) { if(i) { JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ','; } json_dump(state, sl_array_get(state->vm, object, i)); } JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ']'; JSON_END_CHECK_RECURSION(); break; case SL_T_DICT: JSON_CHECK_RECURSION(object); JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = '{'; keys = sl_dict_keys(state->vm, object, &len); for(i = 0; i < len; i++) { if(i) { JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ','; } json_dump(state, sl_to_s(state->vm, keys[i])); JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ':'; json_dump(state, sl_dict_get(state->vm, object, keys[i])); } JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = '}'; JSON_END_CHECK_RECURSION(); break; default: if(!sl_responds_to(state->vm, object, "to_json")) { SLVAL DumpError = state->vm->store[cJSON_DumpError]; sl_error(state->vm, DumpError, "Can't convert type %V to JSON. You can implement #to_json to fix this.", sl_class_of(state->vm, object)); } str = (sl_string_t*)sl_get_ptr(sl_to_s(state->vm, sl_send(state->vm, object, "to_json", 0, NULL))); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; } }
// 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); }