7106 - tile: arrays of ints

This commit is contained in:
Kartik Agaram 2020-10-25 21:15:43 -07:00
parent 1787560a6d
commit 2d7960d493
8 changed files with 194 additions and 43 deletions

View File

@ -171,7 +171,7 @@ test-compare-inequal-arrays-equal-sizes:
5d/pop-to-ebp
c3/return
parse-array-of-ints: # ad: (addr allocation-descriptor), s: (addr string), out: (addr handle array int)
_parse-array-of-ints: # ad: (addr allocation-descriptor), s: (addr array byte), out: (addr handle array int)
# pseudocode
# end = &s->data[s->size]
# curr = s->data
@ -216,25 +216,25 @@ parse-array-of-ints: # ad: (addr allocation-descriptor), s: (addr string), out:
01/add-to %edx 1/r32/ecx
# var size/ebx: int = 0
31/xor-with %ebx 3/r32/ebx
$parse-array-of-ints:loop1:
$_parse-array-of-ints:loop1:
# if (curr >= end) break
39/compare %ecx 2/r32/edx
73/jump-if-addr>= $parse-array-of-ints:break1/disp8
73/jump-if-addr>= $_parse-array-of-ints:break1/disp8
# curr = skip-chars-matching-in-slice(curr, end, ' ')
(skip-chars-matching-in-slice %ecx %edx 0x20) # => eax
89/<- %ecx 0/r32/eax
# if (curr >= end) break
39/compare %ecx 2/r32/edx
73/jump-if-addr>= $parse-array-of-ints:break1/disp8
73/jump-if-addr>= $_parse-array-of-ints:break1/disp8
# curr = skip-chars-not-matching-in-slice(curr, end, ' ')
(skip-chars-not-matching-in-slice %ecx %edx 0x20) # => eax
89/<- %ecx 0/r32/eax
# size += 4
81 0/subop/add %ebx 4/imm32
eb/jump $parse-array-of-ints:loop1/disp8
$parse-array-of-ints:break1:
eb/jump $_parse-array-of-ints:loop1/disp8
$_parse-array-of-ints:break1:
(allocate-array *(ebp+8) %ebx *(ebp+0x10))
$parse-array-of-ints:pass2:
$_parse-array-of-ints:pass2:
# var slice/edi: slice = {s->data, 0}
68/push 0/imm32/end
8d/copy-address *(esi+4) 7/r32/edi
@ -244,16 +244,16 @@ $parse-array-of-ints:pass2:
8b/-> *(ebp+0x10) 0/r32/eax
(lookup *eax *(eax+4)) # => eax
8d/copy-address *(eax+4) 1/r32/ecx
$parse-array-of-ints:loop2:
$_parse-array-of-ints:loop2:
# if (slice->start >= end) break
39/compare *edi 2/r32/edx
73/jump-if-addr>= $parse-array-of-ints:end/disp8
73/jump-if-addr>= $_parse-array-of-ints:end/disp8
# slice->start = skip-chars-matching-in-slice(slice->start, end, ' ')
(skip-chars-matching-in-slice *edi %edx 0x20) # => eax
89/<- *edi 0/r32/eax
# if (slice->start >= end) break
39/compare *edi 2/r32/edx
73/jump-if-addr>= $parse-array-of-ints:end/disp8
73/jump-if-addr>= $_parse-array-of-ints:end/disp8
# slice->end = skip-chars-not-matching-in-slice(slice->start, end, ' ')
(skip-chars-not-matching-in-slice *edi %edx 0x20) # => eax
89/<- *(edi+4) 0/r32/eax
@ -265,8 +265,8 @@ $parse-array-of-ints:loop2:
# slice->start = slice->end
8b/-> *(edi+4) 0/r32/eax
89/<- *edi 0/r32/eax
eb/jump $parse-array-of-ints:loop2/disp8
$parse-array-of-ints:end:
eb/jump $_parse-array-of-ints:loop2/disp8
$_parse-array-of-ints:end:
# . reclaim locals
81 0/subop/add %esp 8/imm32
# . restore registers
@ -296,7 +296,7 @@ test-parse-array-of-ints:
68/push 0xc/imm32/size
89/<- %ecx 4/r32/esp
#
(parse-array-of-ints Heap "1 2 3" %esi)
(_parse-array-of-ints Heap "1 2 3" %esi)
(lookup *esi *(esi+4)) # => eax
(array-equal? %ecx %eax) # => eax
(check-ints-equal %eax 1 "F - test-parse-array-of-ints")
@ -315,7 +315,7 @@ test-parse-array-of-ints-empty:
68/push 0/imm32
89/<- %esi 4/r32/esp
#
(parse-array-of-ints Heap "" %esi)
(_parse-array-of-ints Heap "" %esi)
(lookup *esi *(esi+4)) # => eax
(check-ints-equal *eax 0 "F - test-parse-array-of-ints-empty")
# . epilogue
@ -333,7 +333,7 @@ test-parse-array-of-ints-just-whitespace:
68/push 0/imm32
89/<- %esi 4/r32/esp
#
(parse-array-of-ints Heap Space %esi)
(_parse-array-of-ints Heap Space %esi)
(lookup *esi *(esi+4)) # => eax
(check-ints-equal *eax 0 "F - test-parse-array-of-ints-just-whitespace")
# . epilogue
@ -356,7 +356,7 @@ test-parse-array-of-ints-extra-whitespace:
68/push 0xc/imm32/size
89/<- %ecx 4/r32/esp
#
(parse-array-of-ints Heap " 1 2 3 " %esi)
(_parse-array-of-ints Heap " 1 2 3 " %esi)
(lookup *esi *(esi+4)) # => eax
(array-equal? %ecx %eax) # => eax
(check-ints-equal %eax 1 "F - test-parse-array-of-ints-extra-whitespace")
@ -365,6 +365,18 @@ test-parse-array-of-ints-extra-whitespace:
5d/pop-to-ebp
c3/return
parse-array-of-ints: # s: (addr array byte), out: (addr handle array int)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
#
(_parse-array-of-ints Heap *(ebp+8) *(ebp+0xc))
$parse-array-of-ints:end:
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
# helper for later tests
# compare an array with a string representation of an array literal
check-array-equal: # a: (addr array int), expected: (addr string), msg: (addr string)
@ -379,7 +391,7 @@ check-array-equal: # a: (addr array int), expected: (addr string), msg: (addr s
68/push 0/imm32
89/<- %esi 4/r32/esp
# var b/eax: (addr array int) = parse-array-of-ints(Heap, expected)
(parse-array-of-ints Heap *(ebp+0xc) %esi)
(parse-array-of-ints *(ebp+0xc) %esi)
(lookup *esi *(esi+4)) # => eax
#
(array-equal? *(ebp+8) %eax)

2
400.mu
View File

@ -139,7 +139,7 @@ sig write-int out: (addr stream byte), n: int
#sig pop s: (addr stack) -> n/eax: int
#sig top s: (addr stack) -> n/eax: int
sig array-equal? a: (addr array int), b: (addr array int) -> result/eax: boolean
sig parse-array-of-ints ad: (addr allocation-descriptor), s: (addr string), out: (addr handle array int)
sig parse-array-of-ints s: (addr array byte), out: (addr handle array int)
sig check-array-equal a: (addr array int), expected: (addr string), msg: (addr string)
#sig push-n-zero-bytes n: int
sig kernel-string-to-string ad: (addr allocation-descriptor), in: (addr kernel-string), out: (addr handle array byte)

View File

@ -203,6 +203,25 @@ $print-string:body: {
}
}
fn print-array-of-ints-in-decimal screen: (addr screen), _a: (addr array int) {
var a/esi: (addr array int) <- copy _a
var max/ecx: int <- length a
var i/eax: int <- copy 0
{
compare i, max
break-if->=
{
compare i, 0
break-if-=
print-string screen, " "
}
var x/ecx: (addr int) <- index a, i
print-int32-decimal screen, *x
i <- increment
loop
}
}
fn print-grapheme screen: (addr screen), c: grapheme {
$print-grapheme:body: {
compare screen, 0

BIN
apps/mu

Binary file not shown.

View File

@ -37,6 +37,7 @@ type value {
type: int
int-data: int # if type = 0
text-data: (handle array byte) # if type = 1
array-data: (handle array int) # if type = 2
}
type table {

View File

@ -424,6 +424,7 @@ $process-sandbox:body: {
break $process-sandbox:body
}
# if start of word is quote and grapheme before cursor is not, just insert it as usual
# TODO: support string escaping
{
var first-grapheme/eax: grapheme <- first-grapheme cursor-word
compare first-grapheme, 0x22 # double quote
@ -433,6 +434,17 @@ $process-sandbox:body: {
break-if-=
break $process-sandbox:space
}
# if start of word is '[' and grapheme before cursor is not ']', just insert it as usual
# TODO: support nested arrays
{
var first-grapheme/eax: grapheme <- first-grapheme cursor-word
compare first-grapheme, 0x5b # '['
break-if-!=
var final-grapheme/eax: grapheme <- grapheme-before-cursor cursor-word
compare final-grapheme, 0x5d # ']'
break-if-=
break $process-sandbox:space
}
# otherwise insert word after and move cursor to it for the next key
# (but we'll continue to track the current cursor-word for the rest of this function)
append-word cursor-word-ah
@ -1352,6 +1364,14 @@ fn render-column screen: (addr screen), functions: (addr handle function), bindi
print-string screen, val
break $render-column:render-value
}
{
compare *val-type, 2 # array
break-if-!=
var val-ah/eax: (addr handle array int) <- get val-addr, array-data
var val/eax: (addr array int) <- lookup *val-ah
render-array screen, val
break $render-column:render-value
}
# render ints by default for now
var val-addr2/eax: (addr int) <- get val-addr, int-data
render-integer screen, *val-addr2, max-width
@ -1410,6 +1430,14 @@ fn render-integer screen: (addr screen), val: int, max-width: int {
print-grapheme screen, 0x20 # space
}
fn render-array screen: (addr screen), val: (addr array int) {
start-color screen, 0, 7
# don't surround in spaces
print-grapheme screen, 0x5b # '['
print-array-of-ints-in-decimal screen, val
print-grapheme screen, 0x5d # ']'
}
fn hash-color val: int -> result/eax: int {
result <- try-modulo val, 7 # assumes that 7 is always the background color
}

View File

@ -65,30 +65,42 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch:
top <- decrement
var dest-offset/edx: (offset value) <- compute-offset data, top
var target-val/edx: (addr value) <- index data, dest-offset
# check target-val is a string
# check target-val is a string or array
var target-type-addr/eax: (addr int) <- get target-val, type
#? print-string 0, "checking type: "
#? {
#? var foo/eax: int <- copy target-type-addr
#? print-int32-hex 0, foo
#? }
#? print-string 0, "\n"
compare *target-type-addr, 1 # string
break-if-!=
#? print-string 0, "is string\n"
# compute length
var src-ah/eax: (addr handle array byte) <- get target-val, text-data
var src/eax: (addr array byte) <- lookup *src-ah
var result/ebx: int <- length src
# save result into target-val
var type-addr/eax: (addr int) <- get target-val, type
copy-to *type-addr, 0 # int
var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
var empty: (handle array byte)
copy-handle empty, target-string-ah
var target/eax: (addr int) <- get target-val, int-data
copy-to *target, result
break $evaluate:process-word
{
break-if-!=
# compute length
var src-ah/eax: (addr handle array byte) <- get target-val, text-data
var src/eax: (addr array byte) <- lookup *src-ah
var result/ebx: int <- length src
# save result into target-val
var type-addr/eax: (addr int) <- get target-val, type
copy-to *type-addr, 0 # int
var target-string-ah/eax: (addr handle array byte) <- get target-val, text-data
var empty: (handle array byte)
copy-handle empty, target-string-ah
var target/eax: (addr int) <- get target-val, int-data
copy-to *target, result
break $evaluate:process-word
}
compare *target-type-addr, 2 # array of ints
{
break-if-!=
# compute length
var src-ah/eax: (addr handle array int) <- get target-val, array-data
var src/eax: (addr array int) <- lookup *src-ah
var result/ebx: int <- length src
# save result into target-val
var type-addr/eax: (addr int) <- get target-val, type
copy-to *type-addr, 0 # int
var target-array-ah/eax: (addr handle array int) <- get target-val, array-data
var empty: (handle array int)
copy-handle empty, target-array-ah
var target/eax: (addr int) <- get target-val, int-data
copy-to *target, result
break $evaluate:process-word
}
}
# if curr-stream defines a binding, save top of stack to bindings
{
@ -152,7 +164,7 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch:
push-value-stack out, val
break $evaluate:process-word
}
# if the word starts with a quote and ends with a quote, return it directly
# if the word starts with a quote and ends with a quote, turn it into a string
{
var start/eax: byte <- stream-first curr-stream
compare start, 0x22 # double-quote
@ -166,6 +178,25 @@ fn evaluate functions: (addr handle function), bindings: (addr table), scratch:
push-string-to-value-stack out, *s
break $evaluate:process-word
}
# if the word starts with a '[' and ends with a ']', turn it into an array
{
var start/eax: byte <- stream-first curr-stream
compare start, 0x5b # '['
break-if-!=
var end/eax: byte <- stream-final curr-stream
compare end, 0x5d # ']'
break-if-!=
# wastefully create a new string to strip quotes
var h: (handle array int)
var tmp-ah/eax: (addr handle array byte) <- address h
unquote-stream-to-string curr-stream, tmp-ah # leak
var tmp/eax: (addr array byte) <- lookup *tmp-ah
var h2: (handle array int)
var array-ah/ecx: (addr handle array int) <- address h2
parse-array-of-ints tmp, array-ah # leak
push-array-to-value-stack out, *array-ah
break $evaluate:process-word
}
# otherwise assume it's a literal int and push it
{
var n/eax: int <- parse-decimal-int-from-stream curr-stream

View File

@ -55,6 +55,27 @@ fn push-string-to-value-stack _self: (addr value-stack), val: (handle array byte
increment *top-addr
}
fn push-array-to-value-stack _self: (addr value-stack), val: (handle array int) {
var self/esi: (addr value-stack) <- copy _self
var top-addr/ecx: (addr int) <- get self, top
var data-ah/edx: (addr handle array value) <- get self, data
var data/eax: (addr array value) <- lookup *data-ah
var top/edx: int <- copy *top-addr
var dest-offset/edx: (offset value) <- compute-offset data, top
var dest-addr/edx: (addr value) <- index data, dest-offset
var dest-addr2/eax: (addr handle array int) <- get dest-addr, array-data
copy-handle val, dest-addr2
var dest-addr3/eax: (addr int) <- get dest-addr, type
#? print-string 0, "setting type to 1: "
#? {
#? var foo/eax: int <- copy dest-addr3
#? print-int32-hex 0, foo
#? }
#? print-string 0, "\n"
copy-to *dest-addr3, 2 # type array
increment *top-addr
}
fn push-value-stack _self: (addr value-stack), val: (addr value) {
var self/esi: (addr value-stack) <- copy _self
var top-addr/ecx: (addr int) <- get self, top
@ -123,7 +144,7 @@ fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
var g/edx: (addr value) <- index data, o
var type/eax: (addr int) <- get g, type
{
compare *type, 0
compare *type, 0 # int
break-if-!=
var g2/edx: (addr int) <- get g, int-data
var w/eax: int <- decimal-size *g2
@ -132,7 +153,7 @@ fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
copy-to out, w
}
{
compare *type, 1
compare *type, 1 # string
break-if-!=
var s-ah/eax: (addr handle array byte) <- get g, text-data
var s/eax: (addr array byte) <- lookup *s-ah
@ -143,8 +164,47 @@ fn value-stack-max-width _self: (addr value-stack) -> result/eax: int {
break-if-<=
copy-to out, w
}
{
compare *type, 2 # array
break-if-!=
var a-ah/eax: (addr handle array int) <- get g, array-data
var a/eax: (addr array int) <- lookup *a-ah
compare a, 0
break-if-=
var w/eax: int <- array-decimal-size a
compare w, out
break-if-<=
copy-to out, w
}
i <- increment
loop
}
result <- copy out
}
# keep sync'd with print-array-of-ints
fn array-decimal-size _a: (addr array int) -> result/eax: int {
var a/esi: (addr array int) <- copy _a
var max/ecx: int <- length a
var i/eax: int <- copy 0
var out/edi: int <- copy 0
{
compare i, max
break-if->=
{
compare i, 0
break-if-=
out <- increment # for space
}
var x/ecx: (addr int) <- index a, i
{
var w/eax: int <- decimal-size *x
out <- add w
}
i <- increment
loop
}
result <- copy out
# we won't add 2 for surrounding brackets since we don't surround arrays in
# spaces like other value types
}