diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-06-06 12:11:14 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-06-06 12:11:14 -0700 |
commit | 3bdf3b1a7f146998078975e2f7c1d5e887f84e9f (patch) | |
tree | 19ff09df06e4f6bcf26adf58a2a79e674cdb5234 | |
parent | d555a71cb327a7fd52f3d16d03d02f212346c0a7 (diff) | |
download | mu-3bdf3b1a7f146998078975e2f7c1d5e887f84e9f.tar.gz |
shell: remainder operation
-rw-r--r-- | shell/primitives.mu | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/shell/primitives.mu b/shell/primitives.mu index 73c58ce0..a8f22141 100644 --- a/shell/primitives.mu +++ b/shell/primitives.mu @@ -5,6 +5,7 @@ fn initialize-primitives _self: (addr global-table) { append-primitive self, "-" append-primitive self, "*" append-primitive self, "/" + append-primitive self, "%" append-primitive self, "sqrt" append-primitive self, "abs" append-primitive self, "sgn" @@ -105,7 +106,7 @@ fn render-primitives screen: (addr screen), xmin: int, xmax: int, ymax: int { var tmpx/eax: int <- copy xmin tmpx <- draw-text-rightward screen, "fn set if while cons car cdr no not and or = ", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg # numbers - tmpx <- draw-text-rightward screen, "< > <= >= + - * / sqrt abs sgn", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg + tmpx <- draw-text-rightward screen, "< > <= >= + - * / % sqrt abs sgn", tmpx, xmax, y, 0x2a/fg=orange, 0xdc/bg=green-bg } fn primitive-global? _x: (addr global) -> _/eax: boolean { @@ -193,6 +194,19 @@ fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr hand apply-divide args-ah, out, trace return } + # '%' is the remainder operator, because modulo isn't really meaningful for + # non-integers + # + # I considered calling this operator 'rem', but I want to follow Arc in + # using 'rem' for filtering out elements from lists. + # https://arclanguage.github.io/ref/list.html#rem + { + var remainder?/eax: boolean <- string-equal? f-name, "%" + compare remainder?, 0/false + break-if-= + apply-remainder args-ah, out, trace + return + } { var square-root?/eax: boolean <- string-equal? f-name, "sqrt" compare square-root?, 0/false @@ -584,6 +598,56 @@ fn apply-divide _args-ah: (addr handle cell), out: (addr handle cell), trace: (a new-float out, result } +fn apply-remainder _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { + trace-text trace, "eval", "apply %" + var args-ah/eax: (addr handle cell) <- copy _args-ah + var _args/eax: (addr cell) <- lookup *args-ah + var args/esi: (addr cell) <- copy _args + # TODO: check that args is a pair + var empty-args?/eax: boolean <- nil? args + compare empty-args?, 0/false + { + break-if-= + error trace, "% needs 2 args but got 0" + return + } + # args->left->value + var first-ah/eax: (addr handle cell) <- get args, left + var first/eax: (addr cell) <- lookup *first-ah + var first-type/ecx: (addr int) <- get first, type + compare *first-type, 1/number + { + break-if-= + error trace, "first arg for % is not a number" + return + } + var first-value/ecx: (addr float) <- get first, number-data + # args->right->left->value + var right-ah/eax: (addr handle cell) <- get args, right + var right/eax: (addr cell) <- lookup *right-ah + # TODO: check that right is a pair + var second-ah/eax: (addr handle cell) <- get right, left + var second/eax: (addr cell) <- lookup *second-ah + var second-type/edx: (addr int) <- get second, type + compare *second-type, 1/number + { + break-if-= + error trace, "second arg for % is not a number" + return + } + var second-value/edx: (addr float) <- get second, number-data + # divide + var quotient/xmm0: float <- copy *first-value + quotient <- divide *second-value + var quotient-int/eax: int <- truncate quotient + quotient <- convert quotient-int + var sub-result/xmm1: float <- copy quotient + sub-result <- multiply *second-value + var result/xmm0: float <- copy *first-value + result <- subtract sub-result + new-float out, result +} + fn apply-square-root _args-ah: (addr handle cell), out: (addr handle cell), trace: (addr trace) { trace-text trace, "eval", "apply sqrt" var args-ah/eax: (addr handle cell) <- copy _args-ah |