#include "mem/mem.h"
#include "data/data.h"
#include "vm/vm.h"
+#include "lib/lib.h"
#include <string.h> // for memcpy/memset
#endif
#include "data/reference.h"
#include "data/closure.h"
-#include "lib/libtable.h"
+#include "lib/methodtable.h"
extern sbPool g_closure_pool;
};
}
-hV sbV_function(u64 id) {
- return (hV) {
- .type = IT_FUNCTION,
- .data = id,
- };
-}
-
hV sbV_empty_list(usize capacity) {
return (hV) {
.type = IT_LIST,
#ifndef __SARABANDE_HANDLE_H__
#define __SARABANDE_HANDLE_H__
-#include "common.h"
+#include "global.h"
#define FLAG_SQUIGGLY (1ULL << 62)
IT_REF = -8, // pointer \abc
IT_LIST = -9, // list [1, 3, 5, 7]
IT_HASH = -10, // hash {a: 1, b: 2}
- IT_FUNCTION = -11, // function => a, b { a + b }
- ITX_TOMBSTONE = -12, // <hashtable_tombstone>
+ IT_BUILTIN = -12, // c function
+ ITX_TOMBSTONE = -13, // <hashtable_tombstone>
};
typedef struct hV {
hV sbV_hash(hHash hash);
hV sbV_int(hInteger i);
hV sbV_boolean(flag b);
-hV sbV_function(u64 id);
hV sbV_empty_list(usize capacity);
hV sbV_empty_hash(usize capacity);
--- /dev/null
+#include "common.h"
+#include "lib/lib.h"
+#include "lib/methodtable.h"
+#include "vm/exec.h"
+
+extern void sbList_create_methods();
+extern void sbString_create_methods();
+extern void sbInteger_create_methods();
+
+void sbLib_sys_init() {
+ sbMethodTable_initialize(&g_list_methods, 16);
+ sbMethodTable_initialize(&g_string_methods, 16);
+ sbMethodTable_initialize(&g_integer_methods, 16);
+
+ sbList_create_methods();
+ sbString_create_methods();
+ sbInteger_create_methods();
+}
+
+void sbLib_sys_deinit() {
+ sbMethodTable_deinitialize(&g_list_methods);
+ sbMethodTable_deinitialize(&g_string_methods);
+ sbMethodTable_deinitialize(&g_integer_methods);
+}
+
+void sbLib_resolve_method(hVm vm) {
+ hV *target = sbVm_pop(vm);
+ hV *argc = sbVm_pop(vm);
+ if (argc->type != IT_INTEGER) {
+ CHECK("argc of send should be integer!");
+ }
+ /* subtract 1 because the method name is itself a param */
+ usize num_params = argc->integer - 1;
+ hV *method_name_val = sbVm_peek(vm, num_params);
+ if (method_name_val->type != IT_SYMBOL) {
+ /* TODO this may become not true */
+ PANIC("method name must be symbol!");
+ }
+
+ hMethodTable table_to_use = NULL;
+ switch(target->type) {
+ case IT_LIST:
+ table_to_use = &g_list_methods;
+ break;
+ case IT_STRING:
+ table_to_use = &g_string_methods;
+ break;
+ case IT_INTEGER:
+ table_to_use = &g_integer_methods;
+ break;
+ default:
+ PANIC("Have not implemented this method table yet!");
+ }
+
+ sbLibMethod f = sbMethodTable_find(table_to_use, method_name_val->symbol);
+ if (f) {
+ f(vm, target, num_params);
+ } else {
+ PANIC("invalid method name for type %lld: %s", (long long)target->type, sbSymbol_name(method_name_val->symbol));
+ }
+}
--- /dev/null
+#ifndef __SARABANDE_LIB_H__
+#define __SARABANDE_LIB_H__
+
+typedef void (*sbLibMethod)(hVm, hV*, usize);
+
+void sbLib_resolve_method(hVm vm);
+
+void sbLib_sys_init();
+
+void sbLib_sys_deinit();
+
+#endif
+++ /dev/null
-#include "lib/libtable.h"
-
-#include "data/hashtable.h"
-#include "vm/exec.h"
-#include "mem/debug.h"
-
-/*
-typedef sbLibTable {
- usize used;
- usize capacity;
- hSymbol *keys;
- sbLibFunc *funcs;
-} sbLibTable;
-*/
-
-extern void sbList_create_methods();
-extern void sbString_create_methods();
-extern void sbInteger_create_methods();
-
-static void insert_func(hSymbol *keys, sbLibFunc *funcs, usize capacity, hSymbol key, sbLibFunc func);
-
-void sbLibTable_initialize(hLibTable t, usize capacity) {
- *t = (sbLibTable) {0};
- if (capacity < 16) {
- capacity = 16;
- }
- t->keys = calloc(capacity, sizeof(hSymbol));
- t->funcs = calloc(capacity, sizeof(sbLibFunc));
- t->capacity = capacity;
-}
-
-void sbLibTable_deinitialize(hLibTable t) {
- free(t->keys);
- free(t->funcs);
- *t = (sbLibTable) {0};
-}
-
-void sbLib_sys_init() {
- sbLibTable_initialize(&g_list_methods, 16);
- sbLibTable_initialize(&g_string_methods, 16);
- sbLibTable_initialize(&g_integer_methods, 16);
-
- sbList_create_methods();
- sbString_create_methods();
- sbInteger_create_methods();
-}
-
-void sbLib_sys_deinit() {
- sbLibTable_deinitialize(&g_list_methods);
- sbLibTable_deinitialize(&g_string_methods);
- sbLibTable_deinitialize(&g_integer_methods);
-}
-
-void sbLib_resolve_method(hVm vm) {
- hV *target = sbVm_pop(vm);
- hV *argc = sbVm_pop(vm);
- if (argc->type != IT_INTEGER) {
- CHECK("argc of send should be integer!");
- }
- /* subtract 1 because the method name is itself a param */
- usize num_params = argc->integer - 1;
- hV *method_name_val = sbVm_peek(vm, num_params);
- if (method_name_val->type != IT_SYMBOL) {
- /* TODO this may become not true */
- PANIC("method name must be symbol!");
- }
-
- hLibTable table_to_use = NULL;
- switch(target->type) {
- case IT_LIST:
- table_to_use = &g_list_methods;
- break;
- case IT_STRING:
- table_to_use = &g_string_methods;
- break;
- case IT_INTEGER:
- table_to_use = &g_integer_methods;
- break;
- default:
- PANIC("Have not implemented this method table yet!");
- }
-
- sbLibFunc f = sbLibTable_find(table_to_use, method_name_val->symbol);
- if (f) {
- f(vm, target, num_params);
- } else {
- PANIC("invalid method name for type %lld: %s", (long long)target->type, sbSymbol_name(method_name_val->symbol));
- }
-}
-
-sbLibFunc sbLibTable_find(hLibTable t, hSymbol key) {
- sbHashValue hash = sbHash_hash_bytes((const char*)&key, sizeof(hSymbol));
- usize index = hash % t->capacity;
- while (t->keys[index] && t->keys[index] != key) {
- index ++;
- index %= t->capacity;
- }
-
- if (t->keys[index]) {
- return t->funcs[index];
- } else {
- return NULL;
- }
-}
-
-void sbLibTable_register(hLibTable t, const char *method_name, usize method_name_length, sbLibFunc behavior) {
- if (t->used > t->capacity / 4 * 3) {
- /* grow table and rehash */
- usize new_capacity = t->capacity * 2;
- hSymbol *new_keys = calloc(new_capacity, sizeof(hSymbol));
- sbLibFunc *new_funcs = calloc(new_capacity, sizeof(sbLibFunc));
-
- for (usize i = 0; i < t->capacity; i++) {
- if (t->keys[i] != 0) {
- insert_func(new_keys, new_funcs, new_capacity, t->keys[i], t->funcs[i]);
- }
- }
-
- free(t->keys);
- free(t->funcs);
- t->keys = new_keys;
- t->funcs = new_funcs;
- t->capacity = new_capacity;
- }
-
- hSymbol sym = sbSymbol_from_bytes(method_name, method_name_length);
- insert_func(t->keys, t->funcs, t->capacity, sym, behavior);
- t->used ++;
-}
-
-/* --- */
-
-static void insert_func(hSymbol *keys, sbLibFunc *funcs, usize capacity, hSymbol key, sbLibFunc func) {
- sbHashValue hash = sbHash_hash_bytes((const char*)&key, sizeof(hSymbol));
- usize index = hash % capacity;
-
- while (keys[index] != 0) {
- index ++;
- index %= capacity;
- }
-
- keys[index] = key;
- funcs[index] = func;
-}
+++ /dev/null
-#include "common.h"
-
-#include "data/symbol.h"
-
-#define LIB_REGISTER(t, n, b) (sbLibTable_register(t, n, sizeof(n) - 1, b))
-
-typedef void (*sbLibFunc)(hVm, hV*, usize);
-
-typedef struct sbLibTable {
- usize used;
- usize capacity;
- hSymbol *keys;
- sbLibFunc *funcs;
-} sbLibTable;
-
-extern sbLibTable g_list_methods;
-extern sbLibTable g_string_methods;
-extern sbLibTable g_integer_methods;
-
-typedef sbLibTable *hLibTable;
-
-void sbLibTable_initialize(hLibTable t, usize capacity);
-
-void sbLibTable_deinitialize(hLibTable t);
-
-sbLibFunc sbLibTable_find(hLibTable t, hSymbol key);
-
-void sbLibTable_register(hLibTable t, const char *method_name, usize method_name_length, sbLibFunc behavior);
-
-void sbLib_resolve_method(hVm vm);
-
-void sbLib_sys_init();
-
-void sbLib_sys_deinit();
-
-void sbList_method(hVm vm);
-#include "lib/libtable.h"
+#include "lib/methodtable.h"
#include "data/list.h"
#include "data/string.h"
void list_any_cfunc(hVm vm, flag init);
void list_all_cfunc(hVm vm, flag init);
-sbLibTable g_integer_methods;
+sbMethodTable g_integer_methods;
static void to_string(hVm vm, hV *target, usize num_params) {
sbVm_pop(vm); /* remove method name */
-#include "lib/libtable.h"
+#include "lib/methodtable.h"
#include "data/list.h"
#include "data/string.h"
void list_any_cfunc(hVm vm, flag init);
void list_all_cfunc(hVm vm, flag init);
-sbLibTable g_list_methods;
+sbMethodTable g_list_methods;
static void length(hVm vm, hV *list, usize num_params) {
if (num_params != 0) {
-#include "lib/libtable.h"
+#include "lib/methodtable.h"
#include "data/list.h"
#include "data/string.h"
void list_any_cfunc(hVm vm, flag init);
void list_all_cfunc(hVm vm, flag init);
-sbLibTable g_string_methods;
+sbMethodTable g_string_methods;
static void split(hVm vm, hV *target, usize num_params) {
sbVm_pop(vm); /* remove method name */
--- /dev/null
+#include "lib/methodtable.h"
+
+#include "data/hashtable.h"
+#include "vm/exec.h"
+#include "mem/debug.h"
+
+/*
+typedef sbMethodTable {
+ usize used;
+ usize capacity;
+ hSymbol *keys;
+ sbLibMethod *funcs;
+} sbMethodTable;
+*/
+
+static void insert_func(hSymbol *keys, sbLibMethod *funcs, usize capacity, hSymbol key, sbLibMethod func);
+
+void sbMethodTable_initialize(hMethodTable t, usize capacity) {
+ *t = (sbMethodTable) {0};
+ if (capacity < 16) {
+ capacity = 16;
+ }
+ t->keys = calloc(capacity, sizeof(hSymbol));
+ t->funcs = calloc(capacity, sizeof(sbLibMethod));
+ t->capacity = capacity;
+}
+
+void sbMethodTable_deinitialize(hMethodTable t) {
+ free(t->keys);
+ free(t->funcs);
+ *t = (sbMethodTable) {0};
+}
+
+sbLibMethod sbMethodTable_find(hMethodTable t, hSymbol key) {
+ sbHashValue hash = sbHash_hash_bytes((const char*)&key, sizeof(hSymbol));
+ usize index = hash % t->capacity;
+ while (t->keys[index] && t->keys[index] != key) {
+ index ++;
+ index %= t->capacity;
+ }
+
+ if (t->keys[index]) {
+ return t->funcs[index];
+ } else {
+ return NULL;
+ }
+}
+
+void sbMethodTable_register(hMethodTable t, const char *method_name, usize method_name_length, sbLibMethod behavior) {
+ if (t->used > t->capacity / 4 * 3) {
+ /* grow table and rehash */
+ usize new_capacity = t->capacity * 2;
+ hSymbol *new_keys = calloc(new_capacity, sizeof(hSymbol));
+ sbLibMethod *new_funcs = calloc(new_capacity, sizeof(sbLibMethod));
+
+ for (usize i = 0; i < t->capacity; i++) {
+ if (t->keys[i] != 0) {
+ insert_func(new_keys, new_funcs, new_capacity, t->keys[i], t->funcs[i]);
+ }
+ }
+
+ free(t->keys);
+ free(t->funcs);
+ t->keys = new_keys;
+ t->funcs = new_funcs;
+ t->capacity = new_capacity;
+ }
+
+ hSymbol sym = sbSymbol_from_bytes(method_name, method_name_length);
+ insert_func(t->keys, t->funcs, t->capacity, sym, behavior);
+ t->used ++;
+}
+
+/* --- */
+
+static void insert_func(hSymbol *keys, sbLibMethod *funcs, usize capacity, hSymbol key, sbLibMethod func) {
+ sbHashValue hash = sbHash_hash_bytes((const char*)&key, sizeof(hSymbol));
+ usize index = hash % capacity;
+
+ while (keys[index] != 0) {
+ index ++;
+ index %= capacity;
+ }
+
+ keys[index] = key;
+ funcs[index] = func;
+}
--- /dev/null
+#include "common.h"
+
+#include "data/symbol.h"
+
+#define LIB_REGISTER(t, n, b) (sbMethodTable_register(t, n, sizeof(n) - 1, b))
+
+typedef struct sbMethodTable {
+ usize used;
+ usize capacity;
+ hSymbol *keys;
+ sbLibMethod *funcs;
+} sbMethodTable;
+
+extern sbMethodTable g_list_methods;
+extern sbMethodTable g_string_methods;
+extern sbMethodTable g_integer_methods;
+
+typedef sbMethodTable *hMethodTable;
+
+void sbMethodTable_initialize(hMethodTable t, usize capacity);
+
+void sbMethodTable_deinitialize(hMethodTable t);
+
+sbLibMethod sbMethodTable_find(hMethodTable t, hSymbol key);
+
+void sbMethodTable_register(hMethodTable t, const char *method_name, usize method_name_length, sbLibMethod behavior);
#include "cstrutil.h"
-usize sbstrncpy(char *dst, const char *src, usize limit) {
- usize count = 0;
- char ch = 0;
-
- do {
- ch = dst[count] = src[count];
- count ++;
- } while (ch && count < limit);
-
- count --;
- if (dst[count] != 0) dst[count] = 0;
-
- return count;
-}
-
int sbstrncmp(const char *a, const char *b, usize limit) {
usize count = 0;
#include "global.h"
-usize sbstrncpy(char *dst, const char *src, usize limit);
-
int sbstrncmp(const char *a, const char *b, usize limit);
#include "data/list.h"
#include "data/reference.h"
#include "data/closure.h"
-#include "lib/libtable.h"
+#include "lib/methodtable.h"
void call_block(hVm vm, usize block_id, hClosure closure);
void return_from_block(hVm vm);
break;
case BC_CALL:
v = pop_stack(vm);
- if (v->type <= 0) {
+ if (v->type == IT_BUILTIN) {
+ } else if (v->type <= 0) {
/* We need to figure out exception support or some such.
* User error should not panic. */
PANIC("attempt to call a non-function value");
+ } else {
+ call_block(vm, v->type, v->closure);
}
- call_block(vm, v->type, v->closure);
break;
case BC_SEND:
sbLib_resolve_method(vm);