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
|
type word {
data: gap-buffer
next: (handle word)
prev: (handle word)
}
fn initialize-word _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
initialize-gap-buffer data
}
## some helpers for creating words. mostly for tests
fn initialize-word-with _self: (addr word), s: (addr array byte) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
initialize-gap-buffer-with data, s
}
fn allocate-word-with _out: (addr handle word), s: (addr array byte) {
var out/eax: (addr handle word) <- copy _out
allocate out
var out-addr/eax: (addr word) <- lookup *out
initialize-word-with out-addr, s
}
# just for tests for now
# TODO: handle existing next
# one implication of handles: append must take a handle
fn append-word-with self-h: (handle word), s: (addr array byte) {
var self/eax: (addr word) <- lookup self-h
var next-ah/eax: (addr handle word) <- get self, next
allocate-word-with next-ah, s
var next/eax: (addr word) <- lookup *next-ah
var prev-ah/eax: (addr handle word) <- get next, prev
copy-handle self-h, prev-ah
}
# just for tests for now
# TODO: handle existing prev
fn prepend-word-with self-h: (handle word), s: (addr array byte) {
var self/eax: (addr word) <- lookup self-h
var prev-ah/eax: (addr handle word) <- get self, prev
allocate-word-with prev-ah, s
var prev/eax: (addr word) <- lookup *prev-ah
var next-ah/eax: (addr handle word) <- get prev, next
copy-handle self-h, next-ah
}
## real primitives
fn word-equal? _self: (addr word), s: (addr array byte) -> result/eax: boolean {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
result <- gap-buffer-equal? data, s
}
fn word-length _self: (addr word) -> result/eax: int {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
result <- gap-buffer-length data
}
fn first-word _self: (addr word) -> result/eax: (addr word) {
var self/esi: (addr word) <- copy _self
var out/edi: (addr word) <- copy self
var prev/esi: (addr handle word) <- get self, prev
{
var curr/eax: (addr word) <- lookup *prev
compare curr, 0
break-if-=
out <- copy curr
prev <- get curr, prev
loop
}
result <- copy out
}
fn final-word _self: (addr word) -> result/eax: (addr word) {
var self/esi: (addr word) <- copy _self
var out/edi: (addr word) <- copy self
var next/esi: (addr handle word) <- get self, next
{
var curr/eax: (addr word) <- lookup *next
compare curr, 0
break-if-=
out <- copy curr
next <- get curr, next
loop
}
result <- copy out
}
fn first-grapheme _self: (addr word) -> result/eax: grapheme {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
result <- first-grapheme-in-gap-buffer data
}
fn add-grapheme-to-word _self: (addr word), c: grapheme {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
add-grapheme-at-gap data, c
}
fn cursor-at-start? _self: (addr word) -> result/eax: boolean {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
result <- gap-at-start? data
}
fn cursor-at-end? _self: (addr word) -> result/eax: boolean {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
result <- gap-at-end? data
}
fn cursor-left _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
var dummy/eax: grapheme <- gap-left data
}
fn cursor-right _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
var dummy/eax: grapheme <- gap-right data
}
fn cursor-to-start _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
gap-to-start data
}
fn cursor-to-end _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
gap-to-end data
}
fn cursor-index _self: (addr word) -> result/eax: int {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
result <- gap-index data
}
fn delete-before-cursor _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
delete-before-gap data
}
fn delete-next _self: (addr word) {
$delete-next:body: {
var self/esi: (addr word) <- copy _self
var next-ah/edi: (addr handle word) <- get self, next
var next/eax: (addr word) <- lookup *next-ah
compare next, 0
break-if-= $delete-next:body
var next-next-ah/ecx: (addr handle word) <- get next, next
var self-ah/esi: (addr handle word) <- get next, prev
copy-object next-next-ah, next-ah
var new-next/eax: (addr word) <- lookup *next-next-ah
compare new-next, 0
break-if-= $delete-next:body
var dest/eax: (addr handle word) <- get new-next, prev
copy-object self-ah, dest
}
}
fn print-word screen: (addr screen), _self: (addr word) {
var self/esi: (addr word) <- copy _self
var data/eax: (addr gap-buffer) <- get self, data
render-gap-buffer screen, data
}
# one implication of handles: append must take a handle
fn append-word _self-ah: (addr handle word) {
var self-ah/esi: (addr handle word) <- copy _self-ah
var _self/eax: (addr word) <- lookup *self-ah
var self/ebx: (addr word) <- copy _self
# allocate new handle
var new: (handle word)
var new-ah/ecx: (addr handle word) <- address new
allocate new-ah
var new-addr/eax: (addr word) <- lookup new
initialize-word new-addr
# new->next = self->next
var src/esi: (addr handle word) <- get self, next
var dest/edi: (addr handle word) <- get new-addr, next
copy-object src, dest
# new->next->prev = new
{
var next-addr/eax: (addr word) <- lookup *src
compare next-addr, 0
break-if-=
dest <- get next-addr, prev
copy-object new-ah, dest
}
# new->prev = self
dest <- get new-addr, prev
copy-object _self-ah, dest
# self->next = new
dest <- get self, next
copy-object new-ah, dest
}
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
}
|