# HG changeset patch # User Tassilo Philipp # Date 1642976402 -3600 # Node ID 3d2c5d156d78884076e12ec1fbf942f9867f013c # Parent 45662241d9cd903903c20bf259605df610fabf6c - test/suite_aggrs: support for nested structs, now diff -r 45662241d9cd -r 3d2c5d156d78 test/suite_aggrs/config.lua --- a/test/suite_aggrs/config.lua Sat Jan 22 16:07:57 2022 +0100 +++ b/test/suite_aggrs/config.lua Sun Jan 23 23:20:02 2022 +0100 @@ -1,10 +1,10 @@ -- user config for rand-sig.lua: minargs = 0 -maxargs = 32 +maxargs = 16 maxaggrdepth = 3 -- max nesting depth of aggregates, 1 = no nesting -ncases = 400 +ncases = 800 types = "csijlpfd{}" -seed = 2108 +seed = 2112 -- specify types more than once to increase relative occurance, e.g.: diff -r 45662241d9cd -r 3d2c5d156d78 test/suite_aggrs/design.txt --- a/test/suite_aggrs/design.txt Sat Jan 22 16:07:57 2022 +0100 +++ b/test/suite_aggrs/design.txt Sun Jan 23 23:20:02 2022 +0100 @@ -1,3 +1,4 @@ +ljdcjsl{}i{c}{}s v{ddd} vd{ddd} vdd{ddd} diff -r 45662241d9cd -r 3d2c5d156d78 test/suite_aggrs/main.c --- a/test/suite_aggrs/main.c Sat Jan 22 16:07:57 2022 +0100 +++ b/test/suite_aggrs/main.c Sun Jan 23 23:20:02 2022 +0100 @@ -44,7 +44,7 @@ return -1; } -int invoke(char const* signature, void* t) +static int invoke(char const* signature, void* t) { DCCallVM * p = (DCCallVM*) G_callvm; char const * sig = signature; @@ -71,7 +71,7 @@ sig += len; rtype_st_cmp = G_agg_cmpfuncs[i]; - rtype_st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(); + rtype_st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(NULL); dcBeginCallStruct(p, rtype_st, DC_FALSE); } else @@ -98,7 +98,7 @@ printf("unknown sig at '%s' ;", sig); return 0; } - DCstruct *st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(); + DCstruct *st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(NULL); dcArgStruct(p, st, K_a[pos]); sig += len-1; /* advance to next arg char */ break; diff -r 45662241d9cd -r 3d2c5d156d78 test/suite_aggrs/mk-cases.lua --- a/test/suite_aggrs/mk-cases.lua Sat Jan 22 16:07:57 2022 +0100 +++ b/test/suite_aggrs/mk-cases.lua Sun Jan 23 23:20:02 2022 +0100 @@ -2,10 +2,18 @@ local max = math.max local maxargs = 0 -local n_aggrs = 0 +local aggrs = { } local seen_aggrs = { } +function canon_type(t) + -- struct types have more than one char + if #t > 1 then + return 'struct '..t + end + return t +end + function trim(l) return l:gsub("^%s+",""):gsub("%s+$","") end function mkcase(id,sig) local sig = trim(sig) @@ -13,47 +21,48 @@ local t = { "" } local pos = 0 local n_nest = 0 - local aggr - local aggr_sig = '' + local aggr = { } + local aggr_sig = { } + aggr[0] = { } -- non-sequential [0] collects all non-aggr types + aggr_sig[0] = '' for i = 1, #sig do local name = "a"..pos local ch = sig:sub(i,i) - aggr_sig = aggr_sig..ch - -- aggregate nest level change? if ch == '{' then n_nest = n_nest + 1 - aggr = { } - aggr_sig = ch -- @@@ handle nesting - else - if ch == '}' then -- @@@ handle nesting, here, by reusing structs - n_nest = n_nest - 1 - -- aggr sig complete? - if n_nest == 0 then - -- register yet unseen aggregates, key is sig, val is body and name - if seen_aggrs[aggr_sig] == nil then - n_aggrs = n_aggrs + 1 - ch = 'A'..n_aggrs - seen_aggrs[aggr_sig] = { aggr, ch } - end - ch = seen_aggrs[aggr_sig][2] - end - else - if n_nest > 0 then - aggr[#aggr+1] = ch - aggr[#aggr+1] = 'm'..(#aggr >> 1) - end - end + aggr[n_nest] = { } + aggr_sig[n_nest] = '' end + aggr_sig[n_nest] = aggr_sig[n_nest]..ch + + if ch == '}' then + -- register yet unseen aggregates, key is sig, val is body and name + if seen_aggrs[aggr_sig[n_nest]] == nil then + aggrs[#aggrs+1] = aggr_sig[n_nest] + ch = 'A'..#aggrs + seen_aggrs[aggr_sig[n_nest]] = { aggr[n_nest], ch } + end + ch = seen_aggrs[aggr_sig[n_nest]][2] + + n_nest = n_nest - 1 + aggr_sig[n_nest] = aggr_sig[n_nest]..aggr_sig[n_nest+1] + end + + if ch ~= '{' and ch ~= '}' then + aggr[n_nest][#aggr[n_nest]+1] = canon_type(ch) + aggr[n_nest][#aggr[n_nest]+1] = 'm'..(#aggr[n_nest] >> 1) + end + + if n_nest == 0 then + h[#h+1] = canon_type(ch) -- struct types (more than one char) need copying via a func if #ch > 1 then - h[#h+1] = 'struct '..ch t[#t+1] = 'f_cp'..ch..'(V_a['..pos.."],&"..name..");" else - h[#h+1] = ch t[#t+1] = "V_"..ch.."["..pos.."]="..name..";" end @@ -112,7 +121,9 @@ agg_sizes = {} agg_sigs = {} agg_names = {} - for k, v in pairs(seen_aggrs) do + for a = 1, #aggrs do + k = aggrs[a] + v = seen_aggrs[k] st = 'struct '..v[2] agg_sizes[#agg_sizes + 1] = 'sizeof('..st..')' @@ -121,7 +132,7 @@ -- struct def io.write('/* '..k..' */\n') - io.write(st..'{ ') + io.write(st..' { ') for i = 1, #v[1], 2 do io.write(v[1][i]..' '..v[1][i+1]..'; ') end @@ -132,25 +143,35 @@ 'void f_cp'..v[2]..'('..st..' *x, const '..st..' *y) { ', 'int f_cmp'..v[2]..'(const '..st..' *x, const '..st..' *y) { return ' } - o = { '=', '==', '; ', ' && ' } + o = { '=', '==', 'f_cp', 'f_cmp', '; ', ' && ' } for t = 1, 2 do io.write(s[t]) b = {} for i = 1, #v[1], 2 do - b[#b+1] = 'x->'..v[1][i+1]..' '..o[t]..' y->'..v[1][i+1]; + if string.match(v[1][i], '^struct') then + b[#b+1] = o[t+2]..v[1][i]:sub(8)..'(&x->'..v[1][i+1]..', &y->'..v[1][i+1]..')'; + else + b[#b+1] = 'x->'..v[1][i+1]..' '..o[t]..' y->'..v[1][i+1]; + end end if #b == 0 then b[1] = '1' -- to handle empty structs end - io.write(table.concat(b,o[t+2]).."; };\n") + io.write(table.concat(b,o[t+4]).."; };\n") end -- convenient dcnewstruct helper funcs - io.write('DCstruct* f_newdcst'..v[2]..'() { DCstruct* st = dcNewStruct('..(#v[1]>>1)..', sizeof('..st..'), 0, 1); ') + io.write('static int nfields'..v[2]..' = '..(#v[1]>>1)..';\n') + io.write('DCstruct* f_newdcst'..v[2]..'(DCstruct* parent) {\n\tDCstruct* st = parent;\n\tif(!st) st = dcNewStruct(nfields'..v[2]..', sizeof('..st..'), 0, 1);\n\t') for i = 1, #v[1], 2 do - io.write("dcStructField(st, '"..v[1][i].."', offsetof("..st..', '..v[1][i+1]..'), 1); ') + if string.match(v[1][i], '^struct') then + io.write('dcSubStruct(st, nfields'..v[1][i]:sub(8)..', offsetof('..st..', '..v[1][i+1]..'), sizeof('..v[1][i]..'), 0, DC_TRUE, 1);\n\t') + io.write("f_newdcst"..v[1][i]:sub(8)..'(st);\n\t') + else + io.write("dcStructField(st, '"..v[1][i].."', offsetof("..st..', '..v[1][i+1]..'), 1);\n\t') + end end - io.write(" dcCloseStruct(st); return st; };\n") + io.write("dcCloseStruct(st);\n\treturn st;\n};\n") end -- make table.concat work diff -r 45662241d9cd -r 3d2c5d156d78 test/suite_aggrs/rand-sig.lua --- a/test/suite_aggrs/rand-sig.lua Sat Jan 22 16:07:57 2022 +0100 +++ b/test/suite_aggrs/rand-sig.lua Sun Jan 23 23:20:02 2022 +0100 @@ -3,27 +3,28 @@ -- assure aggr chars are present in pairs (can be weighted, though), to avoid -- inf loops if string.match(types,'{') and not string.match(types,'}') then types = types..'}' end +-- @@@ unions, arrays rtypes = "v"..types -function mkstruct(n_nest) +function mkstruct(n_nest, maxdepth) local s = "{" repeat local id = math.random(#types) local t = types:sub(id,id) - s = s..mktype(t, n_nest) + s = s..mktype(t, n_nest, maxdepth) until t == '}' return s end -function mktype(t, n_nest) +function mktype(t, n_nest, maxdepth) -- ignore new structs if above depth limit if t == '{' then - if n_nest < maxaggrdepth then - return mkstruct(n_nest + 1) + if n_nest < maxdepth then + return mkstruct(n_nest + 1, maxdepth) else return '' end @@ -41,14 +42,18 @@ math.randomseed(seed) local id for i = 1, ncases do - id = math.random(#rtypes) local nargs = math.random(minargs,maxargs) - local sig = { mktype(rtypes:sub(id,id), 0) } - for j = 1, nargs do - id = math.random(#types) - sig[#sig+1] = mktype(types:sub(id,id), 0) - end - io.write(table.concat(sig)) - io.write("\n") + local l = '' + repeat + id = math.random(#rtypes) + local sig = { mktype(rtypes:sub(id,id), 0, math.random(maxaggrdepth)) } -- random depth avoids excessive nesting + for j = 1, nargs do + id = math.random(#types) + sig[#sig+1] = mktype(types:sub(id,id), 0, math.random(maxaggrdepth)) -- random depth avoids excessive nesting + end + l = table.concat(sig) + -- reject sigs without any aggregate, as this is about aggrs after all + until string.match(l, '{') ~= nil + io.write(l.."\n") end