diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-04-06 09:07:25 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-04-06 09:07:25 -0700 |
commit | 6ef0eabdcff3d02b3f0610311f61aa7d0bf79f7e (patch) | |
tree | 46762c3300502c3fc5d4e1eba4a0979782691967 /shell | |
parent | b9656ea881a8c845b009de90538188656be71b17 (diff) | |
download | mu-6ef0eabdcff3d02b3f0610311f61aa7d0bf79f7e.tar.gz |
shell: now we can start adding primitives
Diffstat (limited to 'shell')
-rw-r--r-- | shell/global.mu | 307 | ||||
-rw-r--r-- | shell/print.mu | 7 |
2 files changed, 314 insertions, 0 deletions
diff --git a/shell/global.mu b/shell/global.mu index f0e00ae0..5204ffc6 100644 --- a/shell/global.mu +++ b/shell/global.mu @@ -16,6 +16,10 @@ fn initialize-globals _self: (addr global-table) { append-primitive self, "-" append-primitive self, "*" append-primitive self, "/" + append-primitive self, "sqrt" + append-primitive self, "car" + append-primitive self, "cdr" + append-primitive self, "cons" } fn append-primitive _self: (addr global-table), name: (addr array byte) { @@ -93,6 +97,55 @@ fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr hand apply-add args-ah, out, env-h, trace return } + { + var is-subtract?/eax: boolean <- string-equal? f-name, "-" + compare is-subtract?, 0/false + break-if-= + apply-subtract args-ah, out, env-h, trace + return + } + { + var is-multiply?/eax: boolean <- string-equal? f-name, "*" + compare is-multiply?, 0/false + break-if-= + apply-multiply args-ah, out, env-h, trace + return + } + { + var is-divide?/eax: boolean <- string-equal? f-name, "/" + compare is-divide?, 0/false + break-if-= + apply-divide args-ah, out, env-h, trace + return + } + { + var is-square-root?/eax: boolean <- string-equal? f-name, "sqrt" + compare is-square-root?, 0/false + break-if-= + apply-square-root args-ah, out, env-h, trace + return + } + { + var is-car?/eax: boolean <- string-equal? f-name, "car" + compare is-car?, 0/false + break-if-= + apply-car args-ah, out, env-h, trace + return + } + { + var is-cdr?/eax: boolean <- string-equal? f-name, "cdr" + compare is-cdr?, 0/false + break-if-= + apply-cdr args-ah, out, env-h, trace + return + } + { + var is-cons?/eax: boolean <- string-equal? f-name, "cons" + compare is-cons?, 0/false + break-if-= + apply-cons args-ah, out, env-h, trace + return + } abort "unknown primitive function" } @@ -144,3 +197,257 @@ fn apply-add _args-ah: (addr handle cell), out: (addr handle cell), env-h: (hand new-float out, result } +fn apply-subtract _args-ah: (addr handle cell), out: (addr handle cell), env-h: (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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # 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 + # subtract + var result/xmm0: float <- copy *first-value + result <- subtract *second-value + new-float out, result +} + +fn apply-multiply _args-ah: (addr handle cell), out: (addr handle cell), env-h: (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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # 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 + # multiply + var result/xmm0: float <- copy *first-value + result <- multiply *second-value + new-float out, result +} + +fn apply-divide _args-ah: (addr handle cell), out: (addr handle cell), env-h: (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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # 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 result/xmm0: float <- copy *first-value + result <- divide *second-value + new-float out, result +} + +fn apply-square-root _args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) { + trace-text trace, "eval", "apply sqrt" + 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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # TODO: check that args is a pair + var empty-args?/eax: boolean <- nil? args + compare empty-args?, 0/false + { + break-if-= + error trace, "sqrt needs 1 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, "arg for sqrt is not a number" + return + } + var first-value/ecx: (addr float) <- get first, number-data + # square-root + var result/xmm0: float <- square-root *first-value + new-float out, result +} + +fn apply-car _args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) { + trace-text trace, "eval", "apply car" + 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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # TODO: check that args is a pair + var empty-args?/eax: boolean <- nil? args + compare empty-args?, 0/false + { + break-if-= + error trace, "car needs 1 args but got 0" + return + } + # args->left + 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, 0/pair + { + break-if-= + error trace, "arg for car is not a pair" + return + } + # car + var result/eax: (addr handle cell) <- get first, left + copy-object result, out +} + +fn apply-cdr _args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) { + trace-text trace, "eval", "apply cdr" + 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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # TODO: check that args is a pair + var empty-args?/eax: boolean <- nil? args + compare empty-args?, 0/false + { + break-if-= + error trace, "cdr needs 1 args but got 0" + return + } + # args->left + 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, 0/pair + { + break-if-= + error trace, "arg for cdr is not a pair" + return + } + # cdr + var result/eax: (addr handle cell) <- get first, right + copy-object result, out +} + +fn apply-cons _args-ah: (addr handle cell), out: (addr handle cell), env-h: (handle cell), trace: (addr trace) { + trace-text trace, "eval", "apply cons" + 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 + var _env/eax: (addr cell) <- lookup env-h + var env/edi: (addr cell) <- copy _env + # TODO: check that args is a pair + var empty-args?/eax: boolean <- nil? args + compare empty-args?, 0/false + { + break-if-= + error trace, "cons needs 2 args but got 0" + return + } + # args->left + var first-ah/ecx: (addr handle cell) <- get args, left + # args->right->left + 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 + # cons + new-pair out, *first-ah, *second-ah +} diff --git a/shell/print.mu b/shell/print.mu index 53677c22..aab6cbfe 100644 --- a/shell/print.mu +++ b/shell/print.mu @@ -4,6 +4,13 @@ fn print-cell _in: (addr handle cell), out: (addr stream byte), trace: (addr tra var in/eax: (addr handle cell) <- copy _in var in-addr/eax: (addr cell) <- lookup *in { + compare in-addr, 0 + break-if-!= + write out, "NULL" + trace-higher trace + return + } + { var nil?/eax: boolean <- nil? in-addr compare nil?, 0/false break-if-= |