add concept of sentinel values for unique message names
authorcassowarii <cassowary@cassowary.me>
Fri, 10 Jul 2026 18:41:10 +0000 (11:41 -0700)
committercassowarii <cassowary@cassowary.me>
Fri, 10 Jul 2026 18:41:10 +0000 (11:41 -0700)
12 files changed:
src/data/symbol.c
src/data/symbol.h
src/lib/lib.c
src/lib/method/float.c
src/lib/method/integer.c
src/lib/method/list.c
src/lib/method/string.c
src/lib/module/global.c
src/lib/sentinel.c [new file with mode: 0644]
src/lib/sentinel.h [new file with mode: 0644]
src/lib/table.c
src/lib/table.h

index 7c8c452..567cd17 100644 (file)
@@ -44,6 +44,10 @@ hSymbol sbSymbol_from_string(hString str) {
   return sbSymbol_from_bytes(data, length);
 }
 
+hSymbol sbSymbol_sentinel(const char *text, usize length) {
+  return new_symbol(text, length);
+}
+
 void sbSymbol_sys_init() {
   symbol_table = sbHash_create(256);
   sbArena_initialize(&symbol_text_arena, NAME_BLOCK_SIZE);
index c341687..fa37149 100644 (file)
@@ -2,6 +2,8 @@
 
 #include "data/value.h"
 
+#define SENTINEL(str) (sbSymbol_sentinel(str, sizeof(str)-1))
+
 void sbSymbol_sys_init();
 void sbSymbol_sys_deinit();
 
@@ -9,4 +11,6 @@ hSymbol sbSymbol_from_string(hString str);
 
 hSymbol sbSymbol_from_bytes(const char *text, usize length);
 
+hSymbol sbSymbol_sentinel(const char *text, usize length);
+
 char *sbSymbol_name(hSymbol sym);
index 9c919ec..b79a25e 100644 (file)
@@ -3,10 +3,13 @@
 #include "vm/exec.h"
 
 #include "lib/table.h"
+#include "lib/sentinel.h"
 #include "lib/method.h"
 #include "lib/module.h"
 
 void sbLib_sys_init() {
+  sbLib_create_sentinels();
+
   sbLib_loadmodule_global();
 
   sbList_create_methods();
index 9accacb..a7304cb 100644 (file)
@@ -1,6 +1,7 @@
 #include "common.h"
 
 #include "lib/table.h"
+#include "lib/sentinel.h"
 #include "data/list.h"
 #include "data/string.h"
 #include "vm/exec.h"
@@ -23,5 +24,5 @@ static void to_string(hVm vm, hV *target, usize num_params) {
 
 void sbFloat_create_methods(void) {
   sbLibTable_initialize(&g_float_methods, 16, TRUE);
-  REGISTER_METHOD(&g_float_methods, "to_string", to_string);
+  REGISTER_METHOD_SYM(&g_float_methods, S_OP_TO_STRING, to_string);
 }
index bb9d9e1..6b94af7 100644 (file)
@@ -1,6 +1,7 @@
 #include "common.h"
 
 #include "lib/table.h"
+#include "lib/sentinel.h"
 #include "data/list.h"
 #include "data/string.h"
 #include "data/integer.h"
@@ -24,5 +25,5 @@ static void to_string(hVm vm, hV *target, usize num_params) {
 
 void sbInteger_create_methods(void) {
   sbLibTable_initialize(&g_integer_methods, 16, TRUE);
-  REGISTER_METHOD(&g_integer_methods, "to_string", to_string);
+  REGISTER_METHOD_SYM(&g_integer_methods, S_OP_TO_STRING, to_string);
 }
index 839a87a..b9197a6 100644 (file)
@@ -1,6 +1,7 @@
 #include "common.h"
 
 #include "lib/table.h"
+#include "lib/sentinel.h"
 #include "data/list.h"
 #include "data/string.h"
 #include "vm/exec.h"
index 1e9e966..614156d 100644 (file)
@@ -1,6 +1,7 @@
 #include "common.h"
 
 #include "lib/table.h"
+#include "lib/sentinel.h"
 #include "data/list.h"
 #include "data/string.h"
 #include "vm/exec.h"
@@ -36,5 +37,5 @@ static void to_string(hVm vm, hV *target, usize num_params) {
 void sbString_create_methods(void) {
   sbLibTable_initialize(&g_string_methods, 16, TRUE);
   REGISTER_METHOD(&g_string_methods, "split", split);
-  REGISTER_METHOD(&g_string_methods, "to_string", to_string);
+  REGISTER_METHOD_SYM(&g_string_methods, S_OP_TO_STRING, to_string);
 }
index a99645a..2b4f986 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib/table.h"
 #include "lib/module.h"
+#include "lib/sentinel.h"
 #include "data/list.h"
 #include "data/string.h"
 #include "data/symbol.h"
@@ -12,6 +13,8 @@ sbCFuncStatus println_cfunc(hVm vm, flag init);
 
 sbLibTable g_global_module;
 
+sbLibTable g_string_namespace;
+
 extern sbLibTable g_math_module;
 
 static void print(hVm vm, usize argc) {
@@ -29,6 +32,10 @@ void sbLib_loadmodule_global() {
   REGISTER_VALUE(&g_global_module, "print", &HVBUILTIN(print));
   REGISTER_VALUE(&g_global_module, "println", &HVBUILTIN(println));
 
+  sbLibTable_initialize(&g_string_namespace, 16, FALSE);
+  REGISTER_VALUE(&g_string_namespace, "convert", &HVSYM(S_OP_TO_STRING));
+  REGISTER_VALUE(&g_global_module, "string", &HVMODULE(&g_string_namespace));
+
   sbLib_loadmodule_math();
   REGISTER_VALUE(&g_global_module, "math", &HVMODULE(&g_math_module));
 }
@@ -45,7 +52,7 @@ sbCFuncStatus print_cfunc(hVm vm, flag init) {
      * thing that checks that it's really a string and throws if not, that we
      * can call from multiple places  */
     if (value->type != IT_STRING) {
-      PANIC("to_string needs to return a string");
+      PANIC("string::convert needs to return a string");
     }
 
     char scratch[8];
@@ -59,17 +66,15 @@ sbCFuncStatus print_cfunc(hVm vm, flag init) {
     }
   }
 
-  /* TODO: Built-in symbols like 'to_string' should be saved globally, so we don't have to do this
-   * hashing at runtime. */
   if (args_left->integer > 0) {
     args_left->integer --;
-    sbVm_push_immediate(vm, args_left); /* ... param args_left */
-    sbVm_swap(vm);                      /* ... args_left param */
-    sbVm_push_immediate(vm, &HVSYM(sbSymbol_from_bytes("to_string", 9))); /* ... args_left param :to_string */
-    sbVm_swap(vm);                      /* ... args_left :to_string param */
-    sbVm_push_immediate(vm, &HVINT(1)); /* ... args_left :to_string param 1 */
-    sbVm_swap(vm);                      /* ... args_left :to_string 1 param */
-    sbLib_resolve_method(vm);           /* call method */
+    sbVm_push_immediate(vm, args_left);               /* ... param args_left */
+    sbVm_swap(vm);                                    /* ... args_left param */
+    sbVm_push_immediate(vm, &HVSYM(S_OP_TO_STRING));  /* ... args_left param string::convert*/
+    sbVm_swap(vm);                                    /* ... args_left string::convert param */
+    sbVm_push_immediate(vm, &HVINT(1));               /* ... args_left string::convert param 1 */
+    sbVm_swap(vm);                                    /* ... args_left string::convert 1 param */
+    sbLib_resolve_method(vm);                         /* call method */
     return CFUNC_NEXT;
   } else {
     sbVm_push_immediate(vm, &HVNIL);
diff --git a/src/lib/sentinel.c b/src/lib/sentinel.c
new file mode 100644 (file)
index 0000000..dab8ba5
--- /dev/null
@@ -0,0 +1,29 @@
+#include "lib/sentinel.h"
+
+#include "data/symbol.h"
+
+hSymbol S_OP_ADD, S_OP_SUB, S_OP_MUL, S_OP_DIV, S_OP_FLDIV, S_OP_MOD;
+hSymbol S_OP_EQ, S_OP_LT, S_OP_LE;
+hSymbol S_OP_CALL, S_OP_SET, S_OP_INDEX, S_OP_INDEX_SET;
+hSymbol S_OP_TO_STRING, S_OP_TO_INT, S_OP_TO_FLOAT, S_OP_TO_LIST, S_OP_TO_HASH;
+
+void sbLib_create_sentinels() {
+  S_OP_ADD = SENTINEL("<op::add>");
+  S_OP_SUB = SENTINEL("<op::sub>");
+  S_OP_MUL = SENTINEL("<op::mul>");
+  S_OP_DIV = SENTINEL("<op::div>");
+  S_OP_FLDIV = SENTINEL("<op::intdiv>");
+  S_OP_MOD = SENTINEL("<op::mod>");
+  S_OP_EQ = SENTINEL("<op::eq>");
+  S_OP_LT = SENTINEL("<op::lt>");
+  S_OP_LE = SENTINEL("<op::le>");
+  S_OP_CALL = SENTINEL("<op::call>");
+  S_OP_SET = SENTINEL("<op::set>");
+  S_OP_INDEX = SENTINEL("<op::index>");
+  S_OP_INDEX_SET = SENTINEL("<op::set_index>");
+  S_OP_TO_STRING = SENTINEL("<string::convert>");
+  S_OP_TO_INT = SENTINEL("<integer::convert>");
+  S_OP_TO_FLOAT = SENTINEL("<float::convert>");
+  S_OP_TO_LIST = SENTINEL("<list::convert>");
+  S_OP_TO_HASH = SENTINEL("<hash::convert>");
+}
diff --git a/src/lib/sentinel.h b/src/lib/sentinel.h
new file mode 100644 (file)
index 0000000..fca6174
--- /dev/null
@@ -0,0 +1,8 @@
+#include "common.h"
+
+extern hSymbol S_OP_ADD, S_OP_SUB, S_OP_MUL, S_OP_DIV, S_OP_FLDIV, S_OP_MOD;
+extern hSymbol S_OP_EQ, S_OP_LT, S_OP_LE;
+extern hSymbol S_OP_CALL, S_OP_SET, S_OP_INDEX, S_OP_INDEX_SET;
+extern hSymbol S_OP_TO_STRING, S_OP_TO_INT, S_OP_TO_FLOAT, S_OP_TO_LIST, S_OP_TO_HASH;
+
+void sbLib_create_sentinels();
index dcca74e..f266116 100644 (file)
@@ -80,26 +80,34 @@ hV *sbLibTable_find_value(hLibTable t, hSymbol key) {
   }
 }
 
-void sbLibTable_register_method(hLibTable t, const char *method_name, usize method_name_length, sbLibMethod method) {
+void sbLibTable_register_method_sym(hLibTable t, hSymbol key, sbLibMethod method) {
   if (!t->method_table) CHECK("cannot put method in non-method table");
 
   check_grow_table(t);
 
-  hSymbol sym = sbSymbol_from_bytes(method_name, method_name_length);
-  insert_method(t->keys, t->methods, t->capacity, sym, method);
+  insert_method(t->keys, t->methods, t->capacity, key, method);
   t->used ++;
 }
 
-void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hV *value) {
+void sbLibTable_register_method(hLibTable t, const char *method_name, usize method_name_length, sbLibMethod method) {
+  hSymbol sym = sbSymbol_from_bytes(method_name, method_name_length);
+  sbLibTable_register_method_sym(t, sym, method);
+}
+
+void sbLibTable_register_value_sym(hLibTable t, hSymbol key, hV *value) {
   if (t->method_table) CHECK("cannot put value in method table");
 
   check_grow_table(t);
 
-  hSymbol sym = sbSymbol_from_bytes(value_name, value_name_length);
-  insert_value(t->keys, t->values, t->capacity, sym, value);
+  insert_value(t->keys, t->values, t->capacity, key, value);
   t->used ++;
 }
 
+void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hV *value) {
+  hSymbol sym = sbSymbol_from_bytes(value_name, value_name_length);
+  sbLibTable_register_value_sym(t, sym, value);
+}
+
 /* --- */
 
 static void insert_method(hSymbol *keys, sbLibMethod *methods, usize capacity, hSymbol key, sbLibMethod method) {
index bde35ae..46cb685 100644 (file)
@@ -1,7 +1,10 @@
 #include "common.h"
 
 #define REGISTER_METHOD(t, n, m) (sbLibTable_register_method(t, n, sizeof(n) - 1, m))
+#define REGISTER_METHOD_SYM(t, s, m) (sbLibTable_register_method_sym(t, s, m))
+
 #define REGISTER_VALUE(t, n, v) (sbLibTable_register_value(t, n, sizeof(n) - 1, v))
+#define REGISTER_VALUE_SYM(t, s, v) (sbLibTable_register_value_sym(t, s, v))
 
 typedef struct sbLibTable {
   usize used;
@@ -26,4 +29,8 @@ hV *sbLibTable_find_value(hLibTable t, hSymbol key);
 
 void sbLibTable_register_method(hLibTable t, const char *method_name, usize method_name_length, sbLibMethod method);
 
+void sbLibTable_register_method_sym(hLibTable t, hSymbol key, sbLibMethod method);
+
 void sbLibTable_register_value(hLibTable t, const char *value_name, usize value_name_length, hV *value);
+
+void sbLibTable_register_value_sym(hLibTable t, hSymbol key, hV *value);