static SLVAL enumerable_empty(sl_vm_t* vm, SLVAL self) { SLVAL enumerator = sl_send(vm, self, "enumerate", 0); if(!sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { return vm->lib._true; } else { return vm->lib._false; } }
static SLVAL enumerable_length(sl_vm_t* vm, SLVAL self) { SLVAL enumerator = sl_send(vm, self, "enumerate", 0); int i = 0; while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { i++; } return sl_make_int(vm, i); }
static SLVAL enumerable_to_a(sl_vm_t* vm, SLVAL self) { SLVAL array = sl_make_array(vm, 0, NULL); SLVAL enumerator = sl_send(vm, self, "enumerate", 0); SLVAL val; while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { val = sl_send(vm, enumerator, "current", 0); sl_array_push(vm, array, 1, &val); } return array; }
static SLVAL enumerable_reject(sl_vm_t* vm, SLVAL self, SLVAL f) { SLVAL val, truthy, ary = sl_make_array(vm, 0, NULL); SLVAL enumerator = sl_send(vm, self, "enumerate", 0); while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { val = sl_send(vm, enumerator, "current", 0); truthy = sl_send(vm, f, "call", 1, val); if(!sl_is_truthy(truthy)) { sl_array_push(vm, ary, 1, &val); } } return ary; }
static SLVAL enumerable_find(sl_vm_t* vm, SLVAL self, SLVAL f) { SLVAL val, truthy; SLVAL enumerator = sl_send(vm, self, "enumerate", 0); while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { val = sl_send(vm, enumerator, "current", 0); truthy = sl_send(vm, f, "call", 1, val); if(sl_is_truthy(truthy)) { return val; } } return vm->lib.nil; }
static SLVAL enumerable_any(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { SLVAL enumerator = sl_send(vm, self, "enumerate", 0); SLVAL val; while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { val = sl_send(vm, enumerator, "current", 0); if(argc > 0) { val = sl_send(vm, argv[0], "call", 1, val); } if(sl_is_truthy(val)) { return vm->lib._true; } } return vm->lib._false; }
static SLVAL enumerable_take(sl_vm_t* vm, SLVAL self, SLVAL countv) { SLVAL ary = sl_make_array(vm, 0, NULL); SLVAL enumerator = sl_send(vm, self, "enumerate", 0); for(int count = sl_get_int(countv); count > 0; count--) { if(!sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { return ary; } SLVAL elem = sl_send(vm, enumerator, "current", 0); sl_array_push(vm, ary, 1, &elem); } return ary; }
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; }
static SLVAL enumerable_reduce(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { SLVAL enumerator = sl_send(vm, self, "enumerate", 0); SLVAL acc, val, f; if(argc == 1) { if(!sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { sl_throw_message2(vm, vm->lib.ArgumentError, "Can't reduce empty array without initializer"); } else { acc = sl_send(vm, enumerator, "current", 0); } f = argv[0]; } else { acc = argv[0]; f = argv[1]; } while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) { val = sl_send(vm, enumerator, "current", 0); acc = sl_send(vm, f, "call", 2, acc, val); } return acc; }
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; } }