1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
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
...
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
|
-- vim: ft=terra
-- string.t: string classes
local m = {
sz = terralib.externfunction('strlen', rawstring -> intptr);
cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
ncmp = terralib.externfunction('strncmp', {rawstring, rawstring, intptr} -> int);
cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
dup = terralib.externfunction('strdup',rawstring -> rawstring);
ndup = terralib.externfunction('strndup',{rawstring, intptr} -> rawstring);
fmt = terralib.externfunction('asprintf',
terralib.types.funcpointer({&rawstring,rawstring},{int},true));
bfmt = terralib.externfunction('sprintf',
terralib.types.funcpointer({rawstring,rawstring},{int},true));
}
(lib.mem.ptr(int8)).metamethods.__cast = function(from,to,e)
if from == &int8 then
return `[lib.mem.ptr(int8)]{ptr = e, ct = m.sz(e)}
elseif to == &int8 then
return e.ptr
................................................................................
}
local terra biggest(a: intptr, b: intptr)
if a > b then return a else return b end
end
terra m.acc:init(run: intptr)
lib.dbg('initializing string accumulator')
self.buf = [rawstring](lib.mem.heapa_raw(run))
self.run = run
self.space = run
self.sz = 0
return self
end;
terra m.acc:free()
lib.dbg('freeing string accumulator')
if self.buf ~= nil and self.space > 0 then
lib.mem.heapf(self.buf)
end
end;
terra m.acc:crush()
lib.dbg('crushing string accumulator')
................................................................................
pt.ct = self.sz
self.buf = nil
self.sz = 0
return pt
end;
terra m.acc:push(str: rawstring, len: intptr)
var llen = len
if str == nil then return self end
if str[len - 1] == 0xA then llen = llen - 1 end -- don't display newlines in debug output
lib.dbg('pushing "',{str,llen},'" onto accumulator')
if self.buf == nil then self:init(self.run) end
if len == 0 then len = m.sz(str) end
if len >= self.space - self.sz then
self.space = self.space + biggest(self.run,len + 1)
self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
end
lib.mem.cpy(self.buf + self.sz, str, len)
self.sz = self.sz + len
self.buf[self.sz] = 0
return self
end;
m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8))
self:push(str.ptr, str.ct) return self end;
m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8))
self:push(str.ptr, str.ct) str:free() return self end;
m.acc.methods.compose = macro(function(self, ...)
local minlen = 0
local pstrs = {}
................................................................................
local ptr = symbol(&int8)
local box = symbol(&m.box(ty))
local memreq_exp = `0
local copiers = {}
for k,v in pairs(vals) do
local ty = (`box.obj.[k]).tree.type
local kp
if ty.ptr_basetype then
kp = quote [box].obj.[k] = [ty] { [ptr] = [&ty.ptr_basetype]([ptr]) } ; end
else
kp = quote [box].obj.[k] = [ty]([ptr]) ; end
end
local cpy
if type(v) ~= 'table' or #v ~= 2 then
cpy = quote [kp] ; [ptr] = m.cpy(ptr, v) end
end
if type(v) == 'string' then
memreq_const = memreq_const + #v + 1
elseif type(v) == 'table' and v.tree and (v.tree.type.ptr_basetype == int8 or v.tree.type.ptr_basetype == uint8) then
cpy = quote [kp]; [ptr] = [&int8](lib.mem.cpy([ptr], [v].ptr, [v].ct)) end
if ty.ptr_basetype then
cpy = quote [cpy]; [box].obj.[k].ct = [v].ct end
end
elseif type(v) == 'table' and v.asvalue and type(v:asvalue()) == 'string' then
local str = tostring(v:asvalue())
memreq_const = memreq_const + #str + 1
elseif type(v) == 'table' and #v == 2 then
local str,sz = v[1],v[2]
if type(sz) == 'number' then
memreq_const = memreq_const + sz
elseif type(sz:asvalue()) == 'number' then
memreq_const = memreq_const + sz:asvalue()
else memreq_exp = `[sz] + [memreq_exp] end
cpy = quote [kp] ; [ptr] = [&int8](lib.mem.cpy([ptr], str, sz)) end
if ty.ptr_basetype then
cpy = quote [cpy]; [box].obj.[k].ct = sz end
end
else
memreq_exp = `(m.sz(v) + 1) + [memreq_exp] -- make room for NUL
if ty.ptr_basetype then
cpy = quote [cpy]; [box].obj.[k].ct = m.sz(v) end
end
end
copiers[#copiers + 1] = cpy
end
return quote
var sz: intptr = memreq_const + [memreq_exp]
var [box] = [&m.box(ty)](lib.mem.heapa_raw(sz))
var [ptr] = [box].storage
[copiers]
in [lib.mem.ptr(ty)] { ct = 1, ptr = &([box].obj) } end
end
return m
|
>
>
|
|
|
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
..
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
...
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
235
236
237
238
239
240
241
|
-- vim: ft=terra
-- string.t: string classes
local util = dofile('common.lua')
local m = {
sz = terralib.externfunction('strlen', rawstring -> intptr);
cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
ncmp = terralib.externfunction('strncmp', {rawstring, rawstring, intptr} -> int);
cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
dup = terralib.externfunction('strdup',rawstring -> rawstring);
ndup = terralib.externfunction('strndup',{rawstring, intptr} -> rawstring);
fmt = terralib.externfunction('asprintf',
terralib.types.funcpointer({&rawstring,rawstring},{int},true));
bfmt = terralib.externfunction('sprintf',
terralib.types.funcpointer({rawstring,rawstring},{int},true));
span = terralib.externfunction('strspn',{rawstring, rawstring} -> rawstring);
}
(lib.mem.ptr(int8)).metamethods.__cast = function(from,to,e)
if from == &int8 then
return `[lib.mem.ptr(int8)]{ptr = e, ct = m.sz(e)}
elseif to == &int8 then
return e.ptr
................................................................................
}
local terra biggest(a: intptr, b: intptr)
if a > b then return a else return b end
end
terra m.acc:init(run: intptr)
--lib.dbg('initializing string accumulator')
self.buf = [rawstring](lib.mem.heapa_raw(run))
self.run = run
self.space = run
self.sz = 0
return self
end;
terra m.acc:free()
--lib.dbg('freeing string accumulator')
if self.buf ~= nil and self.space > 0 then
lib.mem.heapf(self.buf)
end
end;
terra m.acc:crush()
lib.dbg('crushing string accumulator')
................................................................................
pt.ct = self.sz
self.buf = nil
self.sz = 0
return pt
end;
terra m.acc:push(str: rawstring, len: intptr)
--var llen = len
if str == nil then return self end
--if str[len - 1] == 0xA then llen = llen - 1 end -- don't display newlines in debug output
-- lib.dbg('pushing "',{str,llen},'" onto accumulator')
if self.buf == nil then self:init(self.run) end
if len == 0 then len = m.sz(str) end
if len >= self.space - self.sz then
self.space = self.space + biggest(self.run,len + 1)
self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
end
lib.mem.cpy(self.buf + self.sz, str, len)
self.sz = self.sz + len
self.buf[self.sz] = 0
return self
end;
m.lit = macro(function(str)
return `[lib.mem.ref(int8)] {ptr = [str:asvalue()], ct = [#(str:asvalue())]}
end)
m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8))
self:push(str.ptr, str.ct) return self end;
m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8))
self:push(str.ptr, str.ct) str:free() return self end;
m.acc.methods.compose = macro(function(self, ...)
local minlen = 0
local pstrs = {}
................................................................................
local ptr = symbol(&int8)
local box = symbol(&m.box(ty))
local memreq_exp = `0
local copiers = {}
for k,v in pairs(vals) do
local ty = (`box.obj.[k]).tree.type
local kp
local isnull, nullify
if ty.ptr_basetype then
kp = quote [box].obj.[k] = [ty] { ptr = [&ty.ptr_basetype]([ptr]) } ; end
nullify = quote [box].obj.[k] = [ty] { ptr = nil, ct = 0 } end
else
kp = quote [box].obj.[k] = [ty]([ptr]) ; end
nullify = quote [box].obj.[k] = nil end
end
local cpy
if type(v) ~= 'table' or #v ~= 2 then
cpy = quote [kp] ; [ptr] = m.cpy(ptr, v) end
isnull = `v == nil
end
if type(v) == 'string' then
memreq_const = memreq_const + #v + 1
isnull = `false
elseif type(v) == 'table' and v.tree and (v.tree.type.ptr_basetype == int8 or v.tree.type.ptr_basetype == uint8) then
cpy = quote [kp]; [ptr] = [&int8](lib.mem.cpy([ptr], [v].ptr, [v].ct)) end
if ty.ptr_basetype then
cpy = quote [cpy]; [box].obj.[k].ct = [v].ct end
end
isnull = `[v].ptr == nil
elseif type(v) == 'table' and v.asvalue and type(v:asvalue()) == 'string' then
local str = tostring(v:asvalue())
memreq_const = memreq_const + #str + 1
isnull = `false
elseif type(v) == 'table' and #v == 2 then
local str,sz = v[1],v[2]
if type(sz) == 'number' then
memreq_const = memreq_const + sz
elseif type(sz:asvalue()) == 'number' then
memreq_const = memreq_const + sz:asvalue()
else memreq_exp = `[sz] + [memreq_exp] end
cpy = quote [kp] ; [ptr] = [&int8](lib.mem.cpy([ptr], str, sz)) end
if ty.ptr_basetype then
cpy = quote [cpy]; [box].obj.[k].ct = sz end
end
isnull = `[str] == nil
else
memreq_exp = `(m.sz(v) + 1) + [memreq_exp] -- make room for NUL
isnull = `v == nil
if ty.ptr_basetype then
cpy = quote [cpy]; [box].obj.[k].ct = m.sz(v) end
end
end
copiers[#copiers + 1] = quote
if [isnull] then [nullify]
else [cpy] end
end
end
return quote
var sz: intptr = memreq_const + [memreq_exp]
var [box] = [&m.box(ty)](lib.mem.heapa_raw(sz))
var [ptr] = [box].storage
[copiers]
in [lib.mem.ptr(ty)] { ct = 1, ptr = &([box].obj) } end
end
terra m.cspan(str: lib.mem.ptr(int8), reject: lib.mem.ref(int8), maxlen: intptr)
for i=0, lib.math.smallest(maxlen,str.ct) do
if str.ptr[i] == 0 then return 0 end
for j=0, reject.ct do
if str.ptr[i] == reject.ptr[j] then return i end
end
end
return maxlen
end
terra m.ffw(str: &int8, maxlen: intptr)
while maxlen > 0 and @str ~= 0 and
(@str == @' ' or @str == @'\t' or @str == @'\n') do
str = str + 1
maxlen = maxlen - 1
end
return str
end
terra m.ffw_unsafe(str: &int8)
while @str ~= 0 and
(@str == @' ' or @str == @'\t' or @str == @'\n') do
str = str + 1
end
return str
end
return m
|