about summary refs log tree commit diff stats
path: root/apps/tile/word.mu
blob: 70c2eafb60e578606ab1f648a012134988076105 (plain) (blame)
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
}