From 12ce78a59dd801bcafed2637d2551e6cfcf6edf4 Mon Sep 17 00:00:00 2001 From: cassowarii <2374677+cassowarii@users.noreply.github.com> Date: Sun, 12 Jul 2026 22:13:20 -0700 Subject: [PATCH] substring, int parsing, project euler #8 --- sample/project_euler/pe08.sa | 6 ++++++ src/data/integer.c | 18 +++++++++++++++++ src/data/integer.h | 2 ++ src/lib/method/string.c | 21 ++++++++++++++++---- src/lib/module.h | 2 ++ src/lib/module/global.c | 3 +++ src/lib/module/integer.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ src/lib/module/string.c | 4 ++-- 8 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 sample/project_euler/pe08.sa create mode 100644 src/lib/module/integer.c diff --git a/sample/project_euler/pe08.sa b/sample/project_euler/pe08.sa new file mode 100644 index 0000000..0485fe6 --- /dev/null +++ b/sample/project_euler/pe08.sa @@ -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) diff --git a/src/data/integer.c b/src/data/integer.c index bd12d06..533ee3b 100644 --- a/src/data/integer.c +++ b/src/data/integer.c @@ -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); diff --git a/src/data/integer.h b/src/data/integer.h index ce092ef..87830c2 100644 --- a/src/data/integer.h +++ b/src/data/integer.h @@ -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); diff --git a/src/lib/method/string.c b/src/lib/method/string.c index 2ae655d..24c1f76 100644 --- a/src/lib/method/string.c +++ b/src/lib/method/string.c @@ -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)); } diff --git a/src/lib/module.h b/src/lib/module.h index 1b824cf..b0797dc 100644 --- a/src/lib/module.h +++ b/src/lib/module.h @@ -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(); diff --git a/src/lib/module/global.c b/src/lib/module/global.c index 9600aee..f47a87b 100644 --- a/src/lib/module/global.c +++ b/src/lib/module/global.c @@ -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 index 0000000..861538a --- /dev/null +++ b/src/lib/module/integer.c @@ -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; + } +} diff --git a/src/lib/module/string.c b/src/lib/module/string.c index 7a7750d..5073a80 100644 --- a/src/lib/module/string.c +++ b/src/lib/module/string.c @@ -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); -- 1.8.3.1