7106 - tile: arrays of ints
This commit is contained in:
parent
1787560a6d
commit
2d7960d493
|
@ -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
2
400.mu
|
@ -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)
|
||||
|
|
19
405screen.mu
19
405screen.mu
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue