7857 - shell: first function call

This commit is contained in:
Kartik K. Agaram 2021-03-05 15:18:46 -08:00
parent e4fc67ee44
commit bcde6be528
4 changed files with 338 additions and 20 deletions

View File

@ -29,9 +29,108 @@ fn evaluate _in: (addr handle cell), out: (addr handle cell), env: (addr cell),
trace-higher trace
return
}
# TODO: pairs
copy-object _in, out
trace-higher trace
# in-addr is a pair
# TODO: special forms
trace-text trace, "eval", "function call"
trace-text trace, "eval", "evaluating list elements"
var evaluated-list-storage: (handle cell)
var evaluated-list-ah/esi: (addr handle cell) <- address evaluated-list-storage
var curr-out-ah/edx: (addr handle cell) <- copy evaluated-list-ah
var curr/ecx: (addr cell) <- copy in-addr
$evaluate-list:loop: {
allocate-pair curr-out-ah
var is-nil?/eax: boolean <- is-nil? curr
compare is-nil?, 0/false
break-if-!=
# eval left
var curr-out/eax: (addr cell) <- lookup *curr-out-ah
var left-out-ah/edi: (addr handle cell) <- get curr-out, left
var left-ah/esi: (addr handle cell) <- get curr, left
evaluate left-ah, left-out-ah, env, trace
#
curr-out-ah <- get curr-out, right
var right-ah/eax: (addr handle cell) <- get curr, right
var right/eax: (addr cell) <- lookup *right-ah
curr <- copy right
loop
}
trace-text trace, "eval", "apply"
var evaluated-list/eax: (addr cell) <- lookup *evaluated-list-ah
var function-ah/ecx: (addr handle cell) <- get evaluated-list, left
var args-ah/edx: (addr handle cell) <- get evaluated-list, right
#? dump-cell args-ah
#? abort "aaa"
apply function-ah, args-ah, out, env, trace
}
fn apply _f-ah: (addr handle cell), args-ah: (addr handle cell), out: (addr handle cell), env: (addr cell), trace: (addr trace) {
var f-ah/eax: (addr handle cell) <- copy _f-ah
var f/eax: (addr cell) <- lookup *f-ah
{
var f-type/ecx: (addr int) <- get f, type
compare *f-type, 4/primitive-function
break-if-!=
apply-primitive f, args-ah, out, env, trace
return
}
abort "unknown function"
}
fn apply-primitive _f: (addr cell), args-ah: (addr handle cell), out: (addr handle cell), env: (addr cell), trace: (addr trace) {
var f/esi: (addr cell) <- copy _f
var f-index/eax: (addr int) <- get f, index-data
{
compare *f-index, 1/add
break-if-!=
apply-add args-ah, out, env, trace
return
}
abort "unknown primitive function"
}
fn apply-add _args-ah: (addr handle cell), out: (addr handle cell), env: (addr cell), trace: (addr trace) {
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 <- is-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
#? dump-cell right-ah
#? abort "aaa"
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
# add
var result/xmm0: float <- copy *first-value
result <- add *second-value
new-float out, result
}
fn lookup-symbol sym: (addr cell), out: (addr handle cell), _env: (addr cell), trace: (addr trace) {
@ -120,10 +219,10 @@ fn lookup-symbol-in-hardcoded-globals _sym: (addr cell), out: (addr handle cell)
var _sym-data/eax: (addr stream byte) <- lookup *sym-data-ah
var sym-data/esi: (addr stream byte) <- copy _sym-data
{
var is-plus?/eax: boolean <- stream-data-equal? sym-data, "+"
compare is-plus?, 0/false
var is-add?/eax: boolean <- stream-data-equal? sym-data, "+"
compare is-add?, 0/false
break-if-=
new-primitive-function out, 1/plus
new-primitive-function out, 1/add
trace-text trace, "eval", "global +"
return
}
@ -183,7 +282,7 @@ fn test-lookup-symbol-in-hardcoded-globals {
var result-type/edx: (addr int) <- get result, type
check-ints-equal *result-type, 4/primitive-function, "F - test-lookup-symbol-in-hardcoded-globals/0"
var result-value/eax: (addr int) <- get result, index-data
check-ints-equal *result-value, 1/plus, "F - test-lookup-symbol-in-hardcoded-globals/1"
check-ints-equal *result-value, 1/add, "F - test-lookup-symbol-in-hardcoded-globals/1"
}
fn car _in: (addr cell), out: (addr handle cell), trace: (addr trace) {
@ -419,18 +518,51 @@ fn test-evaluate-primitive-function {
var nil-storage: (handle cell)
var nil-ah/ecx: (addr handle cell) <- address nil-storage
allocate-pair nil-ah
var plus-storage: (handle cell)
var plus-ah/ebx: (addr handle cell) <- address plus-storage
new-symbol plus-ah, "+"
var add-storage: (handle cell)
var add-ah/ebx: (addr handle cell) <- address add-storage
new-symbol add-ah, "+"
# eval +, nil env
var tmp-storage: (handle cell)
var tmp-ah/esi: (addr handle cell) <- address tmp-storage
var env/eax: (addr cell) <- lookup *nil-ah
evaluate plus-ah, tmp-ah, env, 0/no-trace
evaluate add-ah, tmp-ah, env, 0/no-trace
#
var result/eax: (addr cell) <- lookup *tmp-ah
var result-type/edx: (addr int) <- get result, type
check-ints-equal *result-type, 4/primitive-function, "F - test-evaluate-primitive-function/0"
var result-value/eax: (addr int) <- get result, index-data
check-ints-equal *result-value, 1/plus, "F - test-evaluate-primitive-function/1"
check-ints-equal *result-value, 1/add, "F - test-evaluate-primitive-function/1"
}
fn test-evaluate-primitive-function-call {
var t-storage: trace
var t/edi: (addr trace) <- address t-storage
initialize-trace t, 0x100, 0/visible # we don't use trace UI
#
var nil-storage: (handle cell)
var nil-ah/ecx: (addr handle cell) <- address nil-storage
allocate-pair nil-ah
var one-storage: (handle cell)
var one-ah/edx: (addr handle cell) <- address one-storage
new-integer one-ah, 1
var add-storage: (handle cell)
var add-ah/ebx: (addr handle cell) <- address add-storage
new-symbol add-ah, "+"
# eval (+ 1 1), nil env
var tmp-storage: (handle cell)
var tmp-ah/esi: (addr handle cell) <- address tmp-storage
new-pair tmp-ah, *one-ah, *nil-ah
new-pair tmp-ah, *one-ah, *tmp-ah
new-pair tmp-ah, *add-ah, *tmp-ah
#? dump-cell tmp-ah
var env/eax: (addr cell) <- lookup *nil-ah
evaluate tmp-ah, tmp-ah, env, t
#? dump-trace t
#
var result/eax: (addr cell) <- lookup *tmp-ah
var result-type/edx: (addr int) <- get result, type
check-ints-equal *result-type, 1/number, "F - test-evaluate-primitive-function-call/0"
var result-value-addr/eax: (addr float) <- get result, number-data
var result-value/eax: int <- convert *result-value-addr
check-ints-equal result-value, 2, "F - test-evaluate-primitive-function-call/1"
}

View File

@ -35,6 +35,16 @@ fn print-cell _in: (addr handle cell), out: (addr stream byte), trace: (addr tra
}
}
# debug helper
fn dump-cell in-ah: (addr handle cell) {
var stream-storage: (stream byte 0x40)
var stream/edx: (addr stream byte) <- address stream-storage
print-cell in-ah, stream, 0/no-trace
var d1/eax: int <- copy 0
var d2/ecx: int <- copy 0
d1, d2 <- draw-stream-wrapping-right-then-down 0/screen, stream, 0/xmin, 0/ymin, 0x80/xmax, 0x30/ymax, 0/x, 0/y, 7/fg, 0/bg
}
fn print-symbol _in: (addr cell), out: (addr stream byte), trace: (addr trace) {
trace-text trace, "print", "symbol"
var in/esi: (addr cell) <- copy _in

View File

@ -73,6 +73,14 @@ fn next-token in: (addr gap-buffer), _out-cell: (addr cell), trace: (addr trace)
next-bracket-token g, out, trace
break $next-token:body
}
# non-symbol operators
{
var operator?/eax: boolean <- is-operator-grapheme? g
compare operator?, 0/false
break-if-=
next-operator-token in, out, trace
break $next-token:body
}
}
trace-higher trace
var stream-storage: (stream byte 0x40)
@ -120,6 +128,43 @@ fn next-symbol-token in: (addr gap-buffer), out: (addr stream byte), trace: (add
trace trace, "read", stream
}
fn next-operator-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) {
trace-text trace, "read", "looking for a operator"
trace-lower trace
$next-operator-token:loop: {
var done?/eax: boolean <- gap-buffer-scan-done? in
compare done?, 0/false
break-if-!=
var g/eax: grapheme <- peek-from-gap-buffer in
{
var stream-storage: (stream byte 0x40)
var stream/esi: (addr stream byte) <- address stream-storage
write stream, "next: "
var gval/eax: int <- copy g
write-int32-hex stream, gval
trace trace, "read", stream
}
# if non-operator, return
{
var operator-grapheme?/eax: boolean <- is-operator-grapheme? g
compare operator-grapheme?, 0/false
break-if-!=
trace-text trace, "read", "stop"
break $next-operator-token:loop
}
var g/eax: grapheme <- read-from-gap-buffer in
write-grapheme out, g
loop
}
trace-higher trace
var stream-storage: (stream byte 0x40)
var stream/esi: (addr stream byte) <- address stream-storage
write stream, "=> "
rewind-stream out
write-stream stream, out
trace trace, "read", stream
}
fn next-number-token in: (addr gap-buffer), out: (addr stream byte), trace: (addr trace) {
trace-text trace, "read", "looking for a number"
trace-lower trace
@ -194,11 +239,6 @@ fn is-symbol-grapheme? g: grapheme -> _/eax: boolean {
break-if-!=
return 0/false
}
compare g, 0x27/single-quote
{
break-if-!=
return 0/false
}
compare g, 0x60/backquote
{
break-if-!=
@ -253,6 +293,11 @@ fn is-symbol-grapheme? g: grapheme -> _/eax: boolean {
break-if-!=
return 0/false
}
compare g, 0x27/single-quote
{
break-if-!=
return 0/false
}
compare g, 0x2a/asterisk
{
break-if-!=
@ -268,13 +313,12 @@ fn is-symbol-grapheme? g: grapheme -> _/eax: boolean {
break-if-!=
return 0/false
}
# '-' is a symbol char
compare g, 0x2e/period
compare g, 0x2d/dash # '-' not allowed in symbols
{
break-if-!=
return 0/false
}
compare g, 0x2f/slash
compare g, 0x2e/period
{
break-if-!=
return 0/false
@ -373,6 +417,108 @@ fn is-bracket-grapheme? g: grapheme -> _/eax: boolean {
return 0/false
}
fn is-operator-grapheme? g: grapheme -> _/eax: boolean {
# '$' is a symbol char
compare g, 0x25/percent
{
break-if-!=
return 1/false
}
compare g, 0x26/ampersand
{
break-if-!=
return 1/true
}
compare g, 0x27/single-quote
{
break-if-!=
return 1/true
}
compare g, 0x2a/asterisk
{
break-if-!=
return 1/true
}
compare g, 0x2b/plus
{
break-if-!=
return 1/true
}
compare g, 0x2c/comma
{
break-if-!=
return 1/true
}
compare g, 0x2d/dash # '-' not allowed in symbols
{
break-if-!=
return 1/true
}
compare g, 0x2e/period
{
break-if-!=
return 1/true
}
compare g, 0x2f/slash
{
break-if-!=
return 1/true
}
compare g, 0x3a/colon
{
break-if-!=
return 1/true
}
compare g, 0x3b/semi-colon
{
break-if-!=
return 1/true
}
compare g, 0x3c/less-than
{
break-if-!=
return 1/true
}
compare g, 0x3d/equal
{
break-if-!=
return 1/true
}
compare g, 0x3e/greater-than
{
break-if-!=
return 1/true
}
# '?' is a symbol char
compare g, 0x40/at-sign
{
break-if-!=
return 1/true
}
compare g, 0x5c/backslash
{
break-if-!=
return 1/true
}
compare g, 0x5e/caret
{
break-if-!=
return 1/true
}
# '_' is a symbol char
compare g, 0x7c/vertical-line
{
break-if-!=
return 1/true
}
compare g, 0x7e/tilde
{
break-if-!=
return 1/true
}
return 0/false
}
fn is-number-token? _in: (addr cell) -> _/eax: boolean {
var in/eax: (addr cell) <- copy _in
var in-data-ah/eax: (addr handle stream byte) <- get in, text-data

View File

@ -255,6 +255,36 @@ fn trace-lines-equal? _a: (addr trace-line), _b: (addr trace-line) -> _/eax: boo
return data-match?
}
fn dump-trace _self: (addr trace) {
var already-hiding-lines?: boolean
var y/ecx: int <- copy 0
var self/esi: (addr trace) <- copy _self
compare self, 0
{
break-if-!=
return
}
var trace-ah/eax: (addr handle array trace-line) <- get self, data
var _trace/eax: (addr array trace-line) <- lookup *trace-ah
var trace/edi: (addr array trace-line) <- copy _trace
var i/edx: int <- copy 0
var max-addr/ebx: (addr int) <- get self, first-free
var max/ebx: int <- copy *max-addr
$dump-trace:loop: {
compare i, max
break-if->=
$dump-trace:iter: {
var offset/ebx: (offset trace-line) <- compute-offset trace, i
var curr/ebx: (addr trace-line) <- index trace, offset
var curr-label-ah/eax: (addr handle array byte) <- get curr, label
var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
y <- render-trace-line 0/screen, curr, 0, y, 0x80/width, 0x30/height, 7/fg, 0/bg
}
i <- increment
loop
}
}
## UI stuff
fn mark-lines-dirty _self: (addr trace) {