sbCFuncStatus list_each_cfunc(hVm vm, flag init);
sbCFuncStatus list_map_cfunc(hVm vm, flag init);
sbCFuncStatus list_filter_cfunc(hVm vm, flag init);
+sbCFuncStatus list_reduce_cfunc(hVm vm, flag init);
sbCFuncStatus list_any_cfunc(hVm vm, flag init);
sbCFuncStatus list_all_cfunc(hVm vm, flag init);
sbVm_call_c_func(vm, list_filter_cfunc);
}
+static void reduce(hVm vm, hV *list, usize num_params) {
+ if (num_params != 2) {
+ PANIC("wrong number of arguments passed to list#reduce");
+ }
+ sbVm_push_immediate(vm, list);
+ sbVm_call_c_func(vm, list_reduce_cfunc);
+}
+
static void any_p(hVm vm, hV *list, usize num_params) {
if (num_params != 1) {
PANIC("wrong number of arguments passed to list#any?");
REGISTER_METHOD(&g_list_methods, "each", each);
REGISTER_METHOD(&g_list_methods, "map", map);
REGISTER_METHOD(&g_list_methods, "filter", filter);
+ REGISTER_METHOD(&g_list_methods, "reduce", reduce);
REGISTER_METHOD(&g_list_methods, "any?", any_p);
REGISTER_METHOD(&g_list_methods, "all?", all_p);
}
}
}
+sbCFuncStatus list_reduce_cfunc(hVm vm, flag init) {
+ if (init) {
+ /* state: list being reduced, index, callback, result */
+ sbVm_request_var_space(vm, 4);
+ hV *iterating_list = sbVm_pop(vm);
+ hV *result = sbVm_pop(vm);
+ hV *reduce_func = sbVm_pop(vm);
+ usize length;
+ sbList_get_value(iterating_list->list, &length);
+ hV index = HVINT(0);
+
+ vm->fp->locals[0] = *iterating_list;
+ vm->fp->locals[1] = index;
+ vm->fp->locals[2] = *reduce_func;
+ vm->fp->locals[3] = *result;
+ } else {
+ /* get result of reduce function */
+ hV *result = sbVm_pop(vm);
+ vm->fp->locals[3] = *result;
+ }
+
+ usize current_index = vm->fp->locals[1].integer++;
+ usize length;
+ hV *iter_values = sbList_get_value(vm->fp->locals[0].list, &length);
+ if (current_index < length) {
+ /* put current result and new value on stack, then call callback function */
+ sbVm_push(vm, &vm->fp->locals[3]);
+ sbVm_push(vm, &iter_values[current_index]);
+ sbVm_push_immediate(vm, &HVINT(2));
+ sbVm_call_func(vm, &vm->fp->locals[2]);
+ return CFUNC_NEXT;
+ } else {
+ /* return result */
+ sbVm_push_immediate(vm, &vm->fp->locals[3]);
+ return CFUNC_END;
+ }
+}
+
sbCFuncStatus list_any_cfunc(hVm vm, flag init) {
if (init) {
/* state: list being filtered, index, callback */
#include "data/string.h"
#include "data/symbol.h"
#include "data/integer.h"
+#include "vm/operations.h"
#include "vm/exec.h"
#include <math.h>
sbVm_push_immediate(vm, &HVFLOAT(sqrt(original_value)));
}
+static void sbmax(hVm vm, usize argc) {
+ hV *result = &HVNIL;
+ while (argc > 0) {
+ argc --;
+ hV *val = sbVm_pop(vm);
+ if (result->type == IT_NIL || sbV_le(result, val).boolean) {
+ result = val;
+ }
+ }
+
+ sbVm_push_immediate(vm, result);
+}
+
void sbLib_loadmodule_math() {
sbLibTable_initialize(&g_math_module, 16, FALSE);
REGISTER_VALUE(&g_math_module, "sqrt", &HVBUILTIN(sbsqrt));
+ REGISTER_VALUE(&g_math_module, "max", &HVBUILTIN(sbmax));
}
#include "lib/lib.h"
void call_block(hVm vm, usize block_id, hClosure closure);
+void call_builtin(hVm vm, hV *to_call);
void return_from_block(hVm vm);
void execute_instruction(hVm vm);
void push_stack(hVm vm, hV *value);
}
void sbVm_call_func(hVm vm, hV *func) {
- call_block(vm, func->type, func->closure);
+ if (func->type == IT_BUILTIN) {
+ call_builtin(vm, func);
+ } else {
+ call_block(vm, func->type, func->closure);
+ }
}
void sbVm_transfer_to_func(hVm vm, hV *func) {