s
}
-def iota N {
- let L = []
- let x = 1
- while x < N {
- L.push x
- x = x + 1
- }
- L
-}
-
-println sum iota(1000).filter => num {
+println sum list::iota(1000).filter => num {
[3, 5].any? => factor { num %% factor }
}
--- /dev/null
+def gcd a, b {
+ # Euclid's algorithm
+ if b == 0 {
+ a
+ } else {
+ gcd b, a % b
+ }
+}
+
+def lcm nums {
+ let result = 1
+ nums.each => num {
+ result = result * num // gcd(result, num)
+ }
+ result
+}
+
+println lcm list::iota 1, 21
case AST_OP_INDEX: EMIT(BC_OP_INDEX); break;
case AST_OP_DIVBY: EMIT(BC_OP_MOD, BC_LD_IMM); EARG(0); EMIT(BC_OP_EQ); break;
default:
- PANIC("unknown operation!\n");
+ PANIC("unknown operation! (%lld / %c)", (long long)op, op);
}
}
PANIC("I haven't implemented this yet!");
}
+flag sbInteger_lt(hInteger a, hInteger b) {
+ if (!is_bigint(a) && !is_bigint(b)) {
+ return a < b;
+ }
+ PANIC("I haven't implemented this yet!");
+}
+
+flag sbInteger_le(hInteger a, hInteger b) {
+ if (!is_bigint(a) && !is_bigint(b)) {
+ return a <= b;
+ }
+ PANIC("I haven't implemented this yet!");
+}
+
+flag sbInteger_eq(hInteger a, hInteger b) {
+ if (!is_bigint(a) && !is_bigint(b)) {
+ return a == b;
+ }
+ PANIC("I haven't implemented this yet!");
+}
+
double sbInteger_as_double(hInteger a) {
if (!is_bigint(a)) {
return (double)a;
hInteger sbInteger_floordiv(hInteger a, hInteger b);
+flag sbInteger_lt(hInteger a, hInteger b);
+
+flag sbInteger_le(hInteger a, hInteger b);
+
+flag sbInteger_eq(hInteger a, hInteger b);
+
void sbInteger_fprint(FILE *out, hInteger a);
usize sbInteger_snprint(char *buf, usize size, hInteger a);
table_to_use = &g_float_methods;
break;
default:
- PANIC("Have not implemented this method table yet!");
+ PANIC("Have not implemented this method table yet! (%lld)", (long long)target->type);
}
sbLibMethod f = sbLibTable_find_method(table_to_use, method_name_val->symbol);
extern sbLibTable g_global_module;
+extern sbLibTable g_list_module;
void sbLib_loadmodule_global();
void sbLib_loadmodule_math();
+void sbLib_loadmodule_list();
REGISTER_VALUE(&g_string_namespace, "convert", &HVSYM(S_OP_TO_STRING));
REGISTER_VALUE(&g_global_module, "string", &HVMODULE(&g_string_namespace));
+ sbLib_loadmodule_list();
+ REGISTER_VALUE(&g_global_module, "list", &HVMODULE(&g_list_module));
+
sbLib_loadmodule_math();
REGISTER_VALUE(&g_global_module, "math", &HVMODULE(&g_math_module));
}
--- /dev/null
+#include "common.h"
+
+#include "lib/table.h"
+#include "lib/sentinel.h"
+#include "data/list.h"
+#include "data/string.h"
+#include "data/symbol.h"
+#include "data/integer.h"
+#include "vm/exec.h"
+
+sbLibTable g_list_module;
+
+static void iota(hVm vm, usize argc) {
+ if (argc != 1 && argc != 2) {
+ PANIC("list::iota takes 1 or 2 arguments");
+ }
+
+ hV *first = sbVm_pop(vm);
+
+ hInteger min, max;
+ if (argc == 1) {
+ if (first->type != IT_INTEGER) {
+ PANIC("list::iota's argument must be an integer!");
+ }
+ min = 0;
+ max = first->integer;
+ } else {
+ hV *second = sbVm_pop(vm);
+ if (first->type != IT_INTEGER || second->type != IT_INTEGER) {
+ PANIC("list::iota's arguments must be integers!");
+ }
+ min = first->integer;
+ max = second->integer;
+ }
+
+ hList result = sbList_new((usize)sbInteger_diff(max, min));
+ hInteger count = min;
+ while (sbInteger_lt(count, max)) {
+ sbList_append(result, &HVINT(count));
+ count = sbInteger_sum(count, 1);
+ }
+
+ sbVm_push_immediate(vm, &HVLIST(result));
+}
+
+void sbLib_loadmodule_list() {
+ sbLibTable_initialize(&g_list_module, 16, FALSE);
+ REGISTER_VALUE(&g_list_module, "iota", &HVBUILTIN(iota));
+ REGISTER_VALUE(&g_list_module, "convert", &HVSYM(S_OP_TO_LIST));
+}
sbV_release(&vm->fp->locals[i]);
}
+ /* move thing that is being returned to the xstack: if we were
+ * originally returning a local variable, we don't want it to get
+ * overwritten by a subsequent function call (and if we were
+ * already returning an immediate value, it does nothing) */
+ ((hV*)(vm->xsp))[-1] = *((hV**)(vm->vsp))[-1];
+ ((hV**)(vm->vsp))[-1] = &((hV*)(vm->xsp))[-1];
+
sbVmStackFrame *frame = (sbVmStackFrame*)vm->fp;
if (frame->return_addr == NULL) {
return ((hV**)(vm->vsp))[-offset - 1];
}
+hV *peek_xstack(hVm vm, isize offset) {
+ return &((hV*)(vm->xsp))[-offset - 1];
+}
+
sbOpcode get_opcode(hVm vm) {
if (vm->ip >= vm->fp->block_func.block->bytecode_end) PANIC("execution outside defined code area");
return *(vm->ip++);
const u8 *ip; /* instruction pointer */
sbVmStackFrame *fp; /* frame pointer */
- u8 *vsp; /* stack pointer */
- u8 *xsp; /* rstack pointer */
+ u8 *vsp; /* vstack pointer */
+ u8 *xsp; /* xstack pointer */
u8 *rsp; /* rstack pointer */
usize stacksize; /* to detect overflow, save these */