Mercurial > pub > dyncall > dyncall
view test/common/rand-sig.lua @ 663:127b569978cc default tip
- another tweak handling clang trying to be too smart (see last commit)
author | Tassilo Philipp |
---|---|
date | Sun, 24 Mar 2024 13:52:44 +0100 |
parents | 667fe7b2be62 |
children |
line wrap: on
line source
-- following knobs control generation: -- required to be defined by who is using this: -- minargs -- maxargs -- ncases -- types -- seed -- optional: -- rtypes (if not set, it'll be 'v'..types) -- ellipsis -- optional (when including aggregate generation): -- minaggrfields -- maxaggrfields -- maxarraylen -- arraydice -- maxaggrdepth -- reqaggrinsig -------------------------------- if maxaggrdepth == nil then maxaggrdepth = 3 end -- assure aggr chars are present in pairs (can be weighted, though), to avoid -- inf loops; closing chars are allowed to appear alone, as they are ignored -- without any opening char (does not make a lot of sense, though) pairs_op = { '{', '<' } --, '[' } pairs_cl = { '}', '>' } --, ']' } for i = 1, #pairs_op do if string.find(types, '%'..pairs_op[i]) and not string.find(types, '%'..pairs_cl[i]) then types = types..pairs_cl[i] end end if rtypes == nil then rtypes = "v"..types end function mkaggr(n_nest, maxdepth, o, c) local s = o local nfields = 0 repeat local t = c if nfields < maxaggrfields then repeat local id = math.random(#types) t = types:sub(id,id) until t ~= c or nfields >= minaggrfields end s_ = mktype(t, n_nest, maxdepth, o) or '' if(#s_ > 0) then nfields = nfields + 1 end s = s..s_ -- member (which cannot be first char) as array? Disallow multidimensional arrays if #s > 1 and t ~= c and s:sub(-1) ~= ']' and math.random(arraydice) == 1 then s = s..'['..math.random(maxarraylen)..']' end until t == c return s end function mktype(t, n_nest, maxdepth, aggr_open) -- aggregate opener? local aggr_i = 0 for i = 1, #pairs_op do if pairs_op[i] == t then aggr_i = i break end end -- ignore new aggregates if above depth limit if aggr_i ~= 0 and t == pairs_op[aggr_i] then if n_nest < maxdepth then return mkaggr(n_nest + 1, maxdepth, pairs_op[aggr_i], pairs_cl[aggr_i]) else return nil end end -- aggregate closer? for i = 1, #pairs_cl do if pairs_cl[i] == t then aggr_i = i break end end -- if closing char, without any open, ignore if aggr_i ~= 0 and (aggr_open == nil or pairs_op[aggr_i] ~= aggr_open) then return nil end return t end -- pattern matching aggregate start chars local aggr_op_pattern = '[%'..table.concat(pairs_op,'%')..']' math.randomseed(seed) local id local uniq_sigs = { } for i = 1, ncases do local l = '' repeat local nargs = math.random(minargs,maxargs) local varargstart = (ellipsis and nargs > 0 and math.random(0,ellipsis) == 0) and math.random(0,nargs-1) or nargs -- generate vararg sigs? local sig = { } for j = 1, nargs do id = math.random(#types) sig[#sig+1] = mktype(types:sub(id,id), 0, math.random(maxaggrdepth), nil) -- random depth avoids excessive nesting -- start vararg part? if j > varargstart and #sig > 0 then sig[#sig+1] = "." varargstart = nargs end end repeat id = math.random(#rtypes) r = mktype(rtypes:sub(id,id), 0, math.random(maxaggrdepth), nil) -- random depth avoids excessive nesting until r sig[#sig+1] = ')'..r l = table.concat(sig) -- reject dupes, sigs without any aggregate (as this is about aggrs after all), and empty ones (if not wanted) until (reqaggrinsig ~= true or string.match(l, aggr_op_pattern) ~= nil) and uniq_sigs[l] == nil uniq_sigs[l] = 1 io.write(l.."\n") end