about summary refs log tree commit diff stats
path: root/apps/tile
diff options
context:
space:
mode:
Diffstat (limited to 'apps/tile')
-rw-r--r--apps/tile/environment.mu50
-rw-r--r--apps/tile/gap-buffer.mu54
-rw-r--r--apps/tile/int-stack.mu20
-rw-r--r--apps/tile/rpn.mu122
-rw-r--r--apps/tile/word.mu6
5 files changed, 191 insertions, 61 deletions
diff --git a/apps/tile/environment.mu b/apps/tile/environment.mu
index 8c5f1b2a..929e4d6f 100644
--- a/apps/tile/environment.mu
+++ b/apps/tile/environment.mu
@@ -94,6 +94,8 @@ fn render _env: (addr environment), max-depth: int {
   var screen/edi: (addr screen) <- copy _screen
   # prepare screen
   clear-screen screen
+  move-cursor screen, 5, 1  # input-row+stack-margin-top
+  print-string screen, "stack:"
   move-cursor screen, 3, 3  # input-row, input-col
   # cursor-word
   var cursor-word-ah/esi: (addr handle word) <- get env, cursor-word
@@ -115,7 +117,7 @@ fn render _env: (addr environment), max-depth: int {
     compare curr-word, 0
     break-if-=
     move-cursor screen, 3, curr-col  # input-row
-    curr-col <- render-stack screen, first-word, curr-word, max-depth, curr-col, cursor-word, cursor-col-a
+    curr-col <- render-column screen, first-word, curr-word, max-depth, curr-col, cursor-word, cursor-col-a
     var next-word-ah/edx: (addr handle word) <- get curr-word, next
     curr-word <- lookup *next-word-ah
     loop
@@ -123,27 +125,49 @@ fn render _env: (addr environment), max-depth: int {
   move-cursor screen, 3, *cursor-col-a  # input-row
 }
 
-# Render the stack result from interpreting first-world to final-word (inclusive)
-# with the bottom-left corner at botleft-row, botleft-col.
+# Render:
+#   - final-word
+#   - the stack result from interpreting first-world to final-word (inclusive)
+#     with the bottom-left corner at botleft-row, botleft-col.
 #
 # Outputs:
 # - Return the farthest column written.
 # - If final-word is same as cursor-word, do some additional computation to set
 #   cursor-col-a.
-fn render-stack screen: (addr screen), first-word: (addr word), final-word: (addr word), botleft-depth: int, botleft-col: int, cursor-word: (addr word), cursor-col-a: (addr int) -> right-col/ecx: int {
+fn render-column screen: (addr screen), first-word: (addr word), final-word: (addr word), botleft-depth: int, botleft-col: int, cursor-word: (addr word), cursor-col-a: (addr int) -> right-col/ecx: int {
+  # compute stack
+  var stack: int-stack
+  var stack-addr/edi: (addr int-stack) <- address stack
+  initialize-int-stack stack-addr, 0x10  # max-words
+  evaluate first-word, final-word, stack-addr
+  # render stack
+  var curr-row/ecx: int <- copy botleft-depth
+  curr-row <- add 6  # input-row 3 + stack-margin-top 3
+  var i/eax: int <- int-stack-length stack-addr
+  curr-row <- subtract i
+  {
+    compare i, 0
+    break-if-<=
+    move-cursor screen, curr-row, botleft-col
+    {
+      var val/eax: int <- pop-int-stack stack-addr
+      print-int32-decimal screen, val
+    }
+    curr-row <- increment
+    i <- decrement
+    loop
+  }
+  right-col <- copy 8  # TODO: adaptive
+
   # render word, initialize result
   move-cursor screen, 3, botleft-col  # input-row
   print-word screen, final-word
-  right-col <- copy botleft-col
-  var len/eax: int <- word-length final-word
-  right-col <- add len
-  right-col <- add 3  # margin-right
+#?   var len/eax: int <- word-length final-word
+#?   right-col <- copy len
 
-  # render stack
-  var botleft-row/eax: int <- copy botleft-depth
-  botleft-row <- add 4  # input-row 3 + 1 stack-margin-top
-  move-cursor screen, botleft-row, botleft-col
-  print-string screen "-"
+  # post-process right-col
+  right-col <- add botleft-col
+  right-col <- add 3  # margin-right
 }
 
 # We could be a little faster by not using 'first-word' (since max is commutative),
diff --git a/apps/tile/gap-buffer.mu b/apps/tile/gap-buffer.mu
index 1503690b..75f88122 100644
--- a/apps/tile/gap-buffer.mu
+++ b/apps/tile/gap-buffer.mu
@@ -6,15 +6,15 @@ type gap-buffer {
 fn initialize-gap-buffer _self: (addr gap-buffer) {
   var self/esi: (addr gap-buffer) <- copy _self
   var left/eax: (addr grapheme-stack) <- get self, left
-  initialize-grapheme-stack left, 0x10
+  initialize-grapheme-stack left, 0x10  # max-word-size
   var right/eax: (addr grapheme-stack) <- get self, right
-  initialize-grapheme-stack right, 0x10
+  initialize-grapheme-stack right, 0x10  # max-word-size
 }
 
 # just for tests
 fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) {
   initialize-gap-buffer self
-  var stream-storage: (stream byte 0x10)
+  var stream-storage: (stream byte 0x10)  # max-word-size
   var stream/ecx: (addr stream byte) <- address stream-storage
   write stream, s
   {
@@ -27,6 +27,52 @@ fn initialize-gap-buffer-with self: (addr gap-buffer), s: (addr array byte) {
   }
 }
 
+fn emit-gap-buffer _self: (addr gap-buffer), out: (addr stream byte) {
+  var self/esi: (addr gap-buffer) <- copy _self
+  clear-stream out
+  var left/eax: (addr grapheme-stack) <- get self, left
+  emit-stack-from-bottom left, out
+  var right/eax: (addr grapheme-stack) <- get self, right
+  emit-stack-from-top right, out
+}
+
+# dump stack from bottom to top
+fn emit-stack-from-bottom _self: (addr grapheme-stack), out: (addr stream byte) {
+  var self/esi: (addr grapheme-stack) <- copy _self
+  var data-ah/edi: (addr handle array grapheme) <- get self, data
+  var _data/eax: (addr array grapheme) <- lookup *data-ah
+  var data/edi: (addr array grapheme) <- copy _data
+  var top-addr/ecx: (addr int) <- get self, top
+  var i/eax: int <- copy 0
+  {
+    compare i, *top-addr
+    break-if->=
+    var g/edx: (addr grapheme) <- index data, i
+    write-grapheme out, *g
+    i <- increment
+    loop
+  }
+}
+
+# dump stack from top to bottom
+fn emit-stack-from-top _self: (addr grapheme-stack), out: (addr stream byte) {
+  var self/esi: (addr grapheme-stack) <- copy _self
+  var data-ah/edi: (addr handle array grapheme) <- get self, data
+  var _data/eax: (addr array grapheme) <- lookup *data-ah
+  var data/edi: (addr array grapheme) <- copy _data
+  var top-addr/ecx: (addr int) <- get self, top
+  var i/eax: int <- copy *top-addr
+  i <- decrement
+  {
+    compare i, 0
+    break-if-<
+    var g/edx: (addr grapheme) <- index data, i
+    write-grapheme out, *g
+    i <- decrement
+    loop
+  }
+}
+
 fn render-gap-buffer screen: (addr screen), _gap: (addr gap-buffer) {
   var gap/esi: (addr gap-buffer) <- copy _gap
   var left/eax: (addr grapheme-stack) <- get gap, left
@@ -111,7 +157,7 @@ $gap-buffer-equal?:body: {
   # complication: graphemes may be multiple bytes
   # so don't rely on length
   # instead turn the expected result into a stream and arrange to read from it in order
-  var stream-storage: (stream byte 0x10)
+  var stream-storage: (stream byte 0x10)  # max-word-size
   var expected-stream/ecx: (addr stream byte) <- address stream-storage
   write expected-stream, s
   # compare left
diff --git a/apps/tile/int-stack.mu b/apps/tile/int-stack.mu
index 5e7a2223..3bb9336f 100644
--- a/apps/tile/int-stack.mu
+++ b/apps/tile/int-stack.mu
@@ -47,3 +47,23 @@ $pop-int-stack:body: {
   val <- copy *result-addr
 }
 }
+
+fn int-stack-empty? _self: (addr int-stack) -> result/eax: boolean {
+$int-stack-empty?:body: {
+  var self/esi: (addr int-stack) <- copy _self
+  var top-addr/eax: (addr int) <- get self, top
+  compare *top-addr, 0
+  {
+    break-if-!=
+    result <- copy 1  # true
+    break $int-stack-empty?:body
+  }
+  result <- copy 0  # false
+}
+}
+
+fn int-stack-length _self: (addr int-stack) -> result/eax: int {
+  var self/esi: (addr int-stack) <- copy _self
+  var top-addr/eax: (addr int) <- get self, top
+  result <- copy *top-addr
+}
diff --git a/apps/tile/rpn.mu b/apps/tile/rpn.mu
index 696912fd..3ca8a38f 100644
--- a/apps/tile/rpn.mu
+++ b/apps/tile/rpn.mu
@@ -1,53 +1,87 @@
-fn simplify in: (addr stream byte), out: (addr int-stack) {
-  var word-storage: slice
-  var word/ecx: (addr slice) <- address word-storage
+fn evaluate start: (addr word), end: (addr word), out: (addr int-stack) {
+  var curr/eax: (addr word) <- copy start
+  var curr-text-storage: (stream byte 0x10)
+  var curr-text/edi: (addr stream byte) <- address curr-text-storage
   clear-int-stack out
-  $simplify:word-loop: {
-    next-word in, word
-    var done?/eax: boolean <- slice-empty? word
-    compare done?, 0
-    break-if-!=
-    # if word is an operator, perform it
-    {
-      var is-add?/eax: boolean <- slice-equal? word, "+"
-      compare is-add?, 0
-      break-if-=
-      var _b/eax: int <- pop-int-stack out
-      var b/edx: int <- copy _b
-      var a/eax: int <- pop-int-stack out
-      a <- add b
-      push-int-stack out, a
-      loop $simplify:word-loop
-    }
-    {
-      var is-sub?/eax: boolean <- slice-equal? word, "-"
-      compare is-sub?, 0
-      break-if-=
-      var _b/eax: int <- pop-int-stack out
-      var b/edx: int <- copy _b
-      var a/eax: int <- pop-int-stack out
-      a <- subtract b
-      push-int-stack out, a
-      loop $simplify:word-loop
-    }
-    {
-      var is-mul?/eax: boolean <- slice-equal? word, "*"
-      compare is-mul?, 0
-      break-if-=
-      var _b/eax: int <- pop-int-stack out
-      var b/edx: int <- copy _b
-      var a/eax: int <- pop-int-stack out
-      a <- multiply b
-      push-int-stack out, a
-      loop $simplify:word-loop
+  $evaluate:loop: {
+    # precondition (should never hit)
+    compare curr, 0
+    break-if-=
+    # update curr-text
+    emit-word curr, curr-text
+    $evaluate:process-word: {
+      # if curr-text is an operator, perform it
+      {
+        var is-add?/eax: boolean <- stream-data-equal? curr-text, "+"
+        compare is-add?, 0
+        break-if-=
+        var _b/eax: int <- pop-int-stack out
+        var b/edx: int <- copy _b
+        var a/eax: int <- pop-int-stack out
+        a <- add b
+        push-int-stack out, a
+        break $evaluate:process-word
+      }
+      {
+        var is-sub?/eax: boolean <- stream-data-equal? curr-text, "-"
+        compare is-sub?, 0
+        break-if-=
+        var _b/eax: int <- pop-int-stack out
+        var b/edx: int <- copy _b
+        var a/eax: int <- pop-int-stack out
+        a <- subtract b
+        push-int-stack out, a
+        break $evaluate:process-word
+      }
+      {
+        var is-mul?/eax: boolean <- stream-data-equal? curr-text, "*"
+        compare is-mul?, 0
+        break-if-=
+        var _b/eax: int <- pop-int-stack out
+        var b/edx: int <- copy _b
+        var a/eax: int <- pop-int-stack out
+        a <- multiply b
+        push-int-stack out, a
+        break $evaluate:process-word
+      }
+      # otherwise it's an int
+      {
+        var n/eax: int <- parse-decimal-int-from-stream curr-text
+        push-int-stack out, n
+      }
     }
-    # otherwise it's an int
-    var n/eax: int <- parse-decimal-int-from-slice word
-    push-int-stack out, n
+    # termination check
+    compare curr, end
+    break-if-=
+    # update
+    var next-word-ah/edx: (addr handle word) <- get curr, next
+    curr <- lookup *next-word-ah
+    #
     loop
   }
 }
 
+fn test-evaluate {
+  # input = [1, 2, +]
+  var w: (handle word)
+  var wah/eax: (addr handle word) <- address w
+  allocate wah
+  var wa/eax: (addr word) <- lookup w
+  initialize-word-with wa, "1"
+  append-word-with w, "2"
+  var next/ecx: (addr handle word) <- get wa, next
+  append-word-with *next, "+"
+  # initialize output
+  var stack-storage: int-stack
+  var stack/edx: (addr int-stack) <- address stack-storage
+  initialize-int-stack stack, 0x10
+  #
+  evaluate wa, 0, stack
+  # check output
+  var x/eax: int <- pop-int-stack stack
+  check-ints-equal x, 3, "F - test-evaluate"
+}
+
 # Copy of 'simplify' that just tracks the maximum stack depth needed
 # Doesn't actually need to simulate the stack, since every word has a predictable effect.
 fn max-stack-depth first-word: (addr word), final-word: (addr word) -> result/edi: int {
diff --git a/apps/tile/word.mu b/apps/tile/word.mu
index e1c5e22d..9e683985 100644
--- a/apps/tile/word.mu
+++ b/apps/tile/word.mu
@@ -116,3 +116,9 @@ fn append-word _self-ah: (addr handle word) {
   var prev-ah/eax: (addr handle word) <- get next, prev
   copy-handle *self-ah, prev-ah
 }
+
+fn emit-word _self: (addr word), out: (addr stream byte) {
+  var self/esi: (addr word) <- copy _self
+  var data/eax: (addr gap-buffer) <- get self, data
+  emit-gap-buffer data, out
+}
. Agaram <vc@akkartik.com> 2017-10-12 23:55:19 -0700 4054' href='/akkartik/mu/commit/linkify/linkify.cc?h=hlt&id=7a219c68bae6dbe214aec69a051015e851e32400'>7a219c68 ^
201458e3 ^
201458e3 ^

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234