-- vim: ft=terra
local m = {
zero = macro(function(r)
return quote
for i = 0, [r.tree.type.N] do r[i] = 0 end
end
end);
heapa_raw = terralib.externfunction('malloc', intptr -> &opaque);
heapr_raw = terralib.externfunction('realloc', {&opaque, intptr} -> &opaque);
heapf = terralib.externfunction('free', &opaque -> {});
cpy = terralib.externfunction('mempcpy',{&opaque, &opaque, intptr} -> &opaque);
}
m.heapa = macro(function(ty, sz)
local p = m.ptr(ty:astype())
return `p {
ptr = [&ty:astype()](m.heapa_raw(sizeof(ty) * sz));
ct = sz;
}
end)
m.ptr = terralib.memoize(function(ty)
local t = terralib.types.newstruct(string.format('ptr<%s>', ty))
t.entries = {
{'ptr', &ty};
{'ct', intptr};
}
t.ptr_basetype = ty
local recurse = false
if ty:isstruct() then
if ty.methods.free then recurse = true end
end
t.metamethods.__not = macro(function(self)
return `self.ptr
end)
t.methods = {
free = terra(self: &t): bool
[recurse and quote
self.ptr:free()
end or {}]
if self.ct > 0 then
m.heapf(self.ptr)
self.ct = 0
return true
end
return false
end;
init = terra(self: &t, newct: intptr): bool
var nv = [&ty](m.heapa_raw(sizeof(ty) * newct))
if nv ~= nil then
self.ptr = nv
self.ct = newct
return true
else return false end
end;
resize = terra(self: &t, newct: intptr): bool
var nv: &ty
if self.ct > 0
then nv = [&ty](m.heapr_raw(self.ptr, sizeof(ty) * newct))
else nv = [&ty](m.heapa_raw(sizeof(ty) * newct))
end
if nv ~= nil then
self.ptr = nv
self.ct = newct
return true
else return false end
end;
}
return t
end)
m.vec = terralib.memoize(function(ty)
local v = terralib.types.newstruct(string.format('vec<%s>', ty.name))
v.entries = {
{field = 'storage', type = m.ptr(ty)};
{field = 'sz', type = intptr};
{field = 'run', type = intptr};
}
local terra biggest(a: intptr, b: intptr)
if a > b then return a else return b end
end
terra v:assure(n: intptr)
if self.storage.ct < n then
self.storage:resize(biggest(n, self.storage.ct + self.run))
end
end
v.methods = {
init = terra(self: &v, run: intptr): bool
if not self.storage:init(run) then return false end
self.run = run
self.sz = 0
return true
end;
new = terra(self: &v): &ty
self:assure(self.sz + 1)
self.sz = self.sz + 1
return self.storage.ptr + (self.sz - 1)
end;
push = terra(self: &v, val: ty)
self:assure(self.sz + 1)
self.storage.ptr[self.sz] = val
self.sz = self.sz + 1
end;
free = terra(self: &v) self.storage:free() end;
last = terra(self: &v, idx: intptr): &ty
if self.sz > idx then
return self.storage.ptr + (self.sz - (idx+1))
else lib.bail('vector underrun!') end
end;
crush = terra(self: &v)
self.storage:resize(self.sz)
return self.storage
end;
}
v.metamethods.__apply = terra(self: &v, idx: intptr): &ty -- no index??
if self.sz > idx then
return self.storage.ptr + idx
else lib.bail('vector overrun!') end
end
return v
end)
return m