parsav  Diff

Differences From Artifact [d98a573fe7]:

To Artifact [89921fa130]:


   107    107   end
   108    108   
   109    109   struct m.acc {
   110    110   	buf: rawstring
   111    111   	sz: intptr
   112    112   	run: intptr
   113    113   	space: intptr
          114  +	pool: &lib.mem.pool
   114    115   }
   115    116   
   116    117   terra m.cdowncase(c: int8)
   117    118   	if c >= @'A' and c <= @'Z' then
   118    119   		return c + (@'a' - @'A')
   119    120   	else return c end
   120    121   end
................................................................................
   127    128   
   128    129   local terra biggest(a: intptr, b: intptr)
   129    130   	if a > b then return a else return b end
   130    131   end
   131    132   
   132    133   terra m.acc:init(run: intptr)
   133    134   	--lib.dbg('initializing string accumulator')
          135  +	self.pool = nil
   134    136   	if run == 0 then
   135    137   		lib.warn('attempted to allocate zero-length string accumulator')
   136    138   		self.buf = nil
   137    139   	else
   138    140   		self.buf = [rawstring](lib.mem.heapa_raw(run))
   139    141   		if self.buf == nil then
   140    142   			lib.warn('string buffer allocation failed, very little memory availble')
................................................................................
   141    143   		end
   142    144   	end
   143    145   	self.run = lib.trn(self.buf == nil, 0, run)
   144    146   	self.space = self.run
   145    147   	self.sz = 0
   146    148   	return self
   147    149   end;
          150  +
          151  +terra m.acc:pool(pool: &lib.mem.pool, run: intptr)
          152  +	self.buf = [&int8](pool:alloc_bytes(run))
          153  +	self.pool = pool
          154  +	self.run = run
          155  +	self.space = self.run
          156  +	self.sz = 0
          157  +	return self
          158  +end
   148    159   
   149    160   terra m.acc:free()
   150    161   	--lib.dbg('freeing string accumulator')
          162  +	if self.pool ~= nil then
          163  +		lib.dbg('attempted to free pooled string accumulator; use frame-reset instead')
          164  +		return
          165  +	end
   151    166   	if self.buf ~= nil and self.space > 0 then
   152    167   		lib.mem.heapf(self.buf)
   153    168   	end
   154    169   end;
   155    170   
   156    171   terra m.acc:crush()
   157    172   	--lib.dbg('crushing string accumulator')
          173  +	if self.pool ~= nil then return self end -- no point unless at end of buffer
   158    174   	self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.sz))
   159    175   	self.space = self.sz
   160    176   	return self
   161    177   end;
   162    178   
   163    179   terra m.acc:finalize()
   164    180   	--lib.dbg('finalizing string accumulator')
................................................................................
   169    185   	self.buf = nil
   170    186   	self.sz = 0
   171    187   	return pt
   172    188   end;
   173    189   
   174    190   terra m.acc:cue(sz: intptr)
   175    191   	if sz <= self.run then return end
          192  +	var curspace = self.space
   176    193   	self.run = sz
   177    194   	if self.space - self.sz < self.run then
   178    195   		self.space = self.sz + self.run
   179         -		self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
          196  +		if self.pool ~= nil then
          197  +			self.buf = [&int8](self.pool:realloc_bytes(self.buf, curspace, self.space))
          198  +		else
          199  +			self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
          200  +		end
   180    201   	end
   181    202   end
   182    203   
   183    204   terra m.acc:reset() -- semantic convenience function
   184    205   	self.sz = 0
   185    206   end
   186    207   
................................................................................
   189    210   	if str == nil then return self end
   190    211   	--if str[len - 1] == 0xA then llen = llen - 1 end -- don't display newlines in debug output
   191    212   	-- lib.dbg('pushing "',{str,llen},'" onto accumulator')
   192    213   	if self.buf == nil then self:init(self.run) end
   193    214   	if self.buf == nil then lib.warn('attempted to push string onto unallocated accumulator') return self end
   194    215   	if len == 0 then len = m.sz(str) end
   195    216   	if len >= self.space - self.sz then
   196         -		self.space = self.space + biggest(self.run,len + 1)
   197         -		self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
          217  +		self:cue(self.space + biggest(self.run,len + 1))
          218  +		--self.space = self.space + biggest(self.run,len + 1)
          219  +		--self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space))
   198    220   	end
   199    221   	lib.mem.cpy(self.buf + self.sz, str, len)
   200    222   	self.sz = self.sz + len
   201    223   	self.buf[self.sz] = 0
   202    224   	return self
   203    225   end;
   204    226   
................................................................................
   242    264   	return `self:push([str:asvalue()], [#(str:asvalue())]) end)
   243    265   m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8))
   244    266   	self:push(str.ptr, str.ct)            return self end;
   245    267   m.acc.methods.rpush = terra(self: &m.acc, str: lib.mem.ref(int8))
   246    268   	self:push(str.ptr, str.ct)            return self end;
   247    269   m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8))
   248    270   	self:push(str.ptr, str.ct) str:free() return self end;
   249         -m.acc.methods.compose = macro(function(self, ...)
          271  +local composefn = function(call, ...)
   250    272   	local minlen = 0
   251    273   	local pstrs = {}
   252    274   	for i,v in ipairs{...} do
   253    275   		if type(v) == 'table' then
   254    276   			local gl = 16 -- guess wildly
   255    277   			if v.tree and v.tree.type.convertible == 'tuple' then
   256    278   				pstrs[#pstrs+1] = {str = `v._0, len = `v._1}
................................................................................
   263    285   			else pstrs[#pstrs+1] = {str = v, len = 0} end
   264    286   			minlen = minlen + gl
   265    287   		elseif type(v) == 'string' then 
   266    288   			pstrs[#pstrs+1] = {str = v, len = #v}
   267    289   			minlen = minlen + #v + 1
   268    290   		else error('invalid type in compose expression') end
   269    291   	end
   270         -	local call = `self:init(minlen)
          292  +	call = call(minlen) --`self:init(minlen)
   271    293   	for i,v in ipairs(pstrs) do
   272    294   		call = `[call]:push([v.str],[v.len])
   273    295   	end
   274    296   	return call
          297  +end
          298  +m.acc.methods.compose = macro(function(self, ...)
          299  +	return composefn(function(minlen) return `self:init(minlen) end, ...)
          300  +end)
          301  +m.acc.methods.pcompose = macro(function(self, pool, ...)
          302  +	return composefn(function(minlen) return `self:pool(pool,minlen) end, ...)
   275    303   end)
          304  +
   276    305   m.acc.metamethods.__lshift = terralib.overloadedfunction('(<<)', {
   277    306   	terra(self: &m.acc, str: rawstring)         return self: push(str,0) end;
   278    307   	terra(self: &m.acc, str: lib.mem.ptr(int8)) return self:ppush(str  ) end;
   279    308   })
   280    309   
   281    310   m.box = terralib.memoize(function(ty)
   282    311   	local b = struct {