diff options
| author | Mel <mel@rnrd.eu> | 2026-05-24 20:30:11 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2026-05-24 20:30:11 +0200 |
| commit | 7af54064b23efe1f18fab9e7ee20b0fc811c36b5 (patch) | |
| tree | d8482ce29cdee1892c843f57be881e6fecb98d2d /boot | |
| parent | 2a893246711442dd8407264c05991b44d1d1f66f (diff) | |
| download | catskill-7af54064b23efe1f18fab9e7ee20b0fc811c36b5.tar.zst catskill-7af54064b23efe1f18fab9e7ee20b0fc811c36b5.zip | |
Power operator via runtime library implementation
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/runtime/core.c | 20 | ||||
| -rw-r--r-- | boot/tests/transpile/expressions.cskt | 9 | ||||
| -rw-r--r-- | boot/transpile.c | 13 |
3 files changed, 42 insertions, 0 deletions
diff --git a/boot/runtime/core.c b/boot/runtime/core.c index e377e0a..cc9210e 100644 --- a/boot/runtime/core.c +++ b/boot/runtime/core.c @@ -87,6 +87,26 @@ println(const ascii* s) // `printf` is already linked in via <stdio.h>. +// integer exponentiation by squaring. +// see: https://en.wikipedia.org/wiki/Exponentiation_by_squaring +// negative exponent rounds to 0 for any base except 1 / -1. +integer +pow_integer(integer base, integer exponent) +{ + if (exponent < 0) { + if (base == 1) return 1; + if (base == -1) return (exponent & 1) ? -1 : 1; + return 0; + } + integer result = 1; + while (exponent > 0) { + if (exponent & 1) result *= base; + base *= base; + exponent >>= 1; + } + return result; +} + void* allocate(size_t size) { diff --git a/boot/tests/transpile/expressions.cskt b/boot/tests/transpile/expressions.cskt index c127b9a..0ca3c01 100644 --- a/boot/tests/transpile/expressions.cskt +++ b/boot/tests/transpile/expressions.cskt @@ -1,5 +1,8 @@ precedence-aware expression emission only inserts parentheses when the child binds more loosely than the parent expects. +`**` has no c equivalent and is routed through the integer-power +runtime helper, with right-associative chaining preserved by the +recursive expansion of the call arguments. <<< @@ -10,6 +13,9 @@ main = fun () { var d int = 10 - (4 - 1) var e int = -1 + 2 var f bool = a == b && c != 0 || d > 0 + var g int = 2 ** 10 + var h int = 2 ** 2 ** 3 + var i int = 1 + 2 ** 3 } >>> @@ -23,5 +29,8 @@ void catskill_main(void) { integer d = 10 - (4 - 1); integer e = -1 + 2; bool f = a == b && c != 0 || d > 0; + integer g = pow_integer(2, 10); + integer h = pow_integer(2, pow_integer(2, 3)); + integer i = 1 + pow_integer(2, 3); } #include "runtime.c" diff --git a/boot/transpile.c b/boot/transpile.c index 0627bcb..9c94706 100644 --- a/boot/transpile.c +++ b/boot/transpile.c @@ -406,6 +406,19 @@ transpile_visit_expression_binary_operation(struct Visit* visit, struct Expressi TRANSPILE_PREAMBLE enum Binary_Operation op = expression->value.binary_operator.operation; + + // c has no built-in power operator. + // we route the operation via our own runtime library `pow_integer` function, + // which performs fast exponentiation by squaring. + if (op == BINARY_POWER) { + TRANSPILE_WRITE("pow_integer("); + transpile_emit_expression(visit, expression->value.binary_operator.left_operand, 0); + TRANSPILE_WRITE(", "); + transpile_emit_expression(visit, expression->value.binary_operator.right_operand, 0); + TRANSPILE_WRITE(")"); + return; + } + uint my_precedence = binary_operation_precedence(op); uint parent = transpiler->expression_parent_precedence; bool needs_parens = my_precedence < parent; |
