substring, int parsing, project euler #8
authorcassowarii <2374677+cassowarii@users.noreply.github.com>
Mon, 13 Jul 2026 05:13:20 +0000 (22:13 -0700)
committercassowarii <2374677+cassowarii@users.noreply.github.com>
Mon, 13 Jul 2026 05:13:20 +0000 (22:13 -0700)
sample/project_euler/pe08.sa [new file with mode: 0644]
src/data/integer.c
src/data/integer.h
src/lib/method/string.c
src/lib/module.h
src/lib/module/global.c
src/lib/module/integer.c [new file with mode: 0644]
src/lib/module/string.c

diff --git a/sample/project_euler/pe08.sa b/sample/project_euler/pe08.sa
new file mode 100644 (file)
index 0000000..0485fe6
--- /dev/null
@@ -0,0 +1,6 @@
+let digits = `7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450`
+
+let span = 13
+println list::iota(0, digits.length - span + 1).map(=> index {
+  digits[index..index + span].split().map(integer::from).reduce(1, => a, b { a * b })
+}).reduce(0, math::max)
index bd12d06..533ee3b 100644 (file)
@@ -95,6 +95,24 @@ i64 sbInteger_get_value(hInteger a) {
   }
 }
 
+hInteger sbInteger_parse_string(const char *string, usize length) {
+  hInteger intval = 0;
+
+  /* TODO: I'd like to be able to parse in other bases, too. */
+  const int base = 10;
+
+  for (usize i = 0; i < length; i++) {
+    char ch = string[i];
+    if (!(ch >= '0' && ch <= '9')) {
+      PANIC("Invalid character, cannot parse number: '%c'", ch);
+    }
+    intval = sbInteger_mul(intval, base);
+    intval = sbInteger_sum(intval, ch - '0');
+  }
+
+  return intval;
+}
+
 hInteger sbInteger_sum(hInteger a, hInteger b) {
   if (!is_bigint(a) && !is_bigint(b)) {
     return sbInteger_new(a + b);
index ce092ef..87830c2 100644 (file)
@@ -17,6 +17,8 @@ void sbInteger_retain(hInteger a);
 
 void sbInteger_release(hInteger a);
 
+hInteger sbInteger_parse_string(const char *string, usize length);
+
 hInteger sbInteger_sum(hInteger a, hInteger b);
 
 hInteger sbInteger_diff(hInteger a, hInteger b);
index 2ae655d..24c1f76 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib/table.h"
 #include "lib/sentinel.h"
 #include "data/list.h"
+#include "data/integer.h"
 #include "data/string.h"
 #include "vm/exec.h"
 
@@ -26,16 +27,28 @@ static void split(hVm vm, hV *target, usize num_params) {
 }
 
 static void to_string(hVm vm, hV *target, usize num_params) {
-  if (num_params != 0) {
-    PANIC("to_string takes no parameters");
-  }
-
   /* to_string for a string just returns itself */
   sbVm_push_immediate(vm, target);
 }
 
+static void to_integer(hVm vm, hV *target, usize num_params) {
+  char scratch[8];
+  usize length;
+  const char *data = sbString_get_value(target->string, scratch, &length);
+  hInteger parsed = sbInteger_parse_string(data, length);
+  sbVm_push_immediate(vm, &HVINT(parsed));
+}
+
+static void length(hVm vm, hV *target, usize num_params) {
+  usize length;
+  sbString_get_value(target->string, NULL, &length);
+  sbVm_push_immediate(vm, &HVINT(length));
+}
+
 void sbString_create_methods(void) {
   sbLibTable_initialize(&g_string_methods, 16, TRUE);
   REGISTER_METHOD(&g_string_methods, "split", &METHOD(split, 0, 1));
+  REGISTER_METHOD(&g_string_methods, "length", &PROPERTY(length));
   REGISTER_METHOD_SYM(&g_string_methods, S_OP_TO_STRING, &PROPERTY(to_string));
+  REGISTER_METHOD_SYM(&g_string_methods, S_OP_TO_INT, &PROPERTY(to_integer));
 }
index 1b824cf..b0797dc 100644 (file)
@@ -2,8 +2,10 @@ extern sbLibTable g_global_module;
 extern sbLibTable g_math_module;
 extern sbLibTable g_list_module;
 extern sbLibTable g_string_module;
+extern sbLibTable g_integer_module;
 
 void sbLib_loadmodule_global();
 void sbLib_loadmodule_math();
 void sbLib_loadmodule_list();
 void sbLib_loadmodule_string();
+void sbLib_loadmodule_integer();
index 9600aee..f47a87b 100644 (file)
@@ -31,6 +31,9 @@ void sbLib_loadmodule_global() {
   sbLib_loadmodule_string();
   REGISTER_VALUE(&g_global_module, "string", &HVMODULE(&g_string_module));
 
+  sbLib_loadmodule_integer();
+  REGISTER_VALUE(&g_global_module, "integer", &HVMODULE(&g_integer_module));
+
   sbLib_loadmodule_list();
   REGISTER_VALUE(&g_global_module, "list", &HVMODULE(&g_list_module));
 
diff --git a/src/lib/module/integer.c b/src/lib/module/integer.c
new file mode 100644 (file)
index 0000000..861538a
--- /dev/null
@@ -0,0 +1,47 @@
+#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"
+
+static sbCFuncStatus from_cfunc(hVm vm, flag init);
+
+sbLibTable g_integer_module;
+
+static void from(hVm vm, usize argc) {
+  if (argc != 1) {
+    PANIC("integer::from takes 1 argument");
+  }
+
+  sbVm_call_c_func(vm, from_cfunc);
+}
+
+void sbLib_loadmodule_integer() {
+  sbLibTable_initialize(&g_integer_module, 16, FALSE);
+  REGISTER_VALUE(&g_integer_module, "from", &HVBUILTIN(from));
+  REGISTER_VALUE(&g_integer_module, "convert", &HVSYM(S_OP_TO_INT));
+}
+
+/* --- */
+
+static sbCFuncStatus from_cfunc(hVm vm, flag init) {
+  if (!init) {
+    /* get value of previous integer::convert */
+    hV *value = sbVm_peek(vm, 0);
+    if (value->type != IT_INTEGER) {
+      PANIC("integer::convert needs to return an integer");
+    }
+    return CFUNC_END;
+  } else {
+    sbVm_push_immediate(vm, &HVSYM(S_OP_TO_INT));     /* ... target integer::convert */
+    sbVm_swap(vm);                                    /* ... integer::convert target */
+    sbVm_push_immediate(vm, &HVINT(1));               /* ... integer::convert target 1 */
+    sbVm_swap(vm);                                    /* ... integer::convert 1 target */
+    sbLib_resolve_method(vm);
+    return CFUNC_NEXT;
+  }
+}
index 7a7750d..5073a80 100644 (file)
@@ -8,7 +8,7 @@
 #include "data/integer.h"
 #include "vm/exec.h"
 
-sbCFuncStatus from_cfunc(hVm vm, flag init);
+static sbCFuncStatus from_cfunc(hVm vm, flag init);
 
 sbLibTable g_string_module;
 
@@ -28,7 +28,7 @@ void sbLib_loadmodule_string() {
 
 /* --- */
 
-sbCFuncStatus from_cfunc(hVm vm, flag init) {
+static sbCFuncStatus from_cfunc(hVm vm, flag init) {
   if (!init) {
     /* get value of previous to_string */
     hV *value = sbVm_peek(vm, 0);