I wrote this library to cut down on the number of tokens taken up by large tables with string data, e.g. for dialogue text/translations/etc. Most helpful if those tokens are using a lot of your tokens (i.e. more than 150), since the library itself takes up 139 tokens. But all your table declarations can be reduced to 5 tokens each!
Here's an example of what your code can look like.
Before:
my_table = { hello='world', nested={ some='data\'s nested', inside_of='here' }, 'and', 'indexed', 'data', { as='well' } } |
After:
function table_from_string(str) local tab, is_key = {}, true local key,val,is_on_key local function reset() key,val,is_on_key = '','',true end reset() local i, len = 1, #str while i <= len do local char = sub(str, i, i) -- token separator if char == '\31' then if is_on_key then is_on_key = false else tab[tonum(key) or key] = val reset() end -- subtable start elseif char == '\29' then local j,c = i,'' -- checking for subtable end character while (c ~= '\30') do j = j + 1 c = sub(str, j, j) end tab[tonum(key) or key] = table_from_string(sub(str,i+1,j-1)) reset() i = j else if is_on_key then key = key..char else val = val..char end end i = i + 1 end return tab end my_table= table_from_string( '1�and�2�indexed�3�data�4�as�well��hello�world�nested�inside_of�here�some�data\'s nested��' ) |
Clearly it's more helpful if your data table is much larger than this. In my case, my data tables took up almost 200 tokens, and I saved about 50 using this technique. If I go to add more translations in the future, it will save even more.
And no I wouldn't suggest keeping this compressed version as your only record of your data table, of course! For my own workflow, I am setting up an automated script to take my data table from a separate Lua file and periodically update the contents of the p8 file with the stringified version.
-- print out a table - for debug function tableout(t,deep) deep=deep or 0 local str=sub(" ",1,deep) print(str.."table size: "..#t) for k,v in pairs(t) do if type(v)=="table" then print(str..tostr(k).."[]") tableout(v,deep+1) else print(str..tostr(k).." = "..tostr(v)) end end end -- convert a string to a table function str2table(str) local out,s={} add(out,{}) for l in all(split(str,"\n")) do while ord(l)==9 or ord(l)==32 do l=sub(l,2) end if l~="" then s=split(l,"=") if (#s==1) s[1]=#out[#out]+1 s[2]=l if (s[2]=="{") s[2]={} if s[2]=="}" then deli(out) else out[#out][s[1]]=s[2] if (type(s[2])=="table") add(out,s[2]) end end end return out[1] end table2=str2table([[ hello=world something { a=10 b=20 c=30 doda { doublenest } } and indexed nestedkey={ something } ]]) cls() tableout(table2) print("---") |
My Variant :)
It use a multi-line-String and a more lua-like syntax. So it is easier change- and readable. Disadvantage is, that it don't allow escape-sequenzes like \n \r.
Can the functionality of these things be expanded to cover cases:
var=true function add_enemy(x,y) obj={r=rnd(100),x=x or 100, y=var and 11 or 63, apples={}} end |
So we have extraneous local var (upvalue) x, global variable var, and/or, function call rnd().
apples is covered it 'has to' be formatted like this is my understanding? can I make it just like apples={} ?
apples={ } |
@GPI you can save another token by swapping from for-loop to foreach().
function str2table(str) local out,s={} add(out,{}) foreach(split(str,"\n"), function(l) -- for l in all(split(str,"\n")) do while ord(l)==9 or ord(l)==32 do l=sub(l,2) end if l~="" then s=split(l,"=") if (#s==1) s[1]=#out[#out]+1 s[2]=l if (s[2]=="{") s[2]={} if s[2]=="}" then deli(out) else out[#out][s[1]]=s[2] if (type(s[2])=="table") add(out,s[2]) end end -- end end) return out[1] end --127 |
@Cerb043_4 yup, you can absolutely do stuff like that, but it'll take a lot more than 139 tokens to set up. I've got a project that has some stuff that looks like this:
eval[[ (set rep (fn (n x) (let a (pack)) (for 1 $n (fn () (add $a $x))) $a )) (set pat_param_idx (' {b0=11,b1=27,dr=43})) (set syn_pat_template (' { nt=`(rep 16 19) dt=`(rep 16 64) st=`(rep 16 64) l=16 })) ]] |
You can take a look at the implementation in https://github.com/luchak/rp8/blob/main/src/utils.lua . There's some weirdness / edge cases, particularly with nil
and multivalues, but it mostly works as you'd expect.
There's also https://www.lexaloffle.com/bbs/?tid=47403 which implements something similar (with two different interpreters for different speed/token tradeoffs!), but it hasn't had as many bugfixes as the actually-in-use code I linked above, and also mishandles nested scopes in some unfortunate ways. I'll probably want to reconcile all of these implementations at some point.
[Please log in to post a comment]