Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- crim.lua: a library for miniforth. -- Written by edrx@inx.com.br. Version: 2001dec04. GPL. -- There's an htmlized version of this file at: -- <http://angg.twu.net/miniforth/crim.lua>. -- "Crim" is an idea that I've been cooking since 1995 for a -- Forth-like language with very compact bytecodes. Crim has a -- definite inner engine but no decent high-level syntax yet; any -- "Crim compiler", like this one, is a tool for exploring possible -- syntaxes. -- «.heir» (to "heir") -- «.newxprimclass» (to "newxprimclass") -- «.hprimclass» (to "hprimclass") -- «.fprimclass» (to "fprimclass") -- «.fipprimclass» (to "fipprimclass") -- «.fwordclass» (to "fwordclass") -- «.sfprimclass» (to "sfprimclass") -- «.declarehprims» (to "declarehprims") -- «.declarefprims» (to "declarefprims") -- «.standard_primitives» (to "standard_primitives") -- «.defineLASTs» (to "defineLASTs") -- «.unskeletize» (to "unskeletize") asmcode = "" nasm = function( nbytes, text ) asmcode = asmcode .. text end dict = dict or {} nasmify = function( str ) return gsub(str, "([^0-9A-Za-z_])", function (c) return format("x%02x", strbyte(c)) end) end --%%%% --% --% «heir» (to ".heir") --% --%%%% heirtag = newtag() heir = function( table ) settag(table, heirtag); return table end settagmethod(heirtag, "gettable", function( table, index ) local a = rawget(table, index); if a then return a end local up = rawget(table, "UP"); if up then return up[index] end end) settagmethod(heirtag, "function", function( ... ) call(arg[1].FUN, arg) end) --%%%% --% --% «newxprimclass» (to ".newxprimclass") --% --%%%% newxprimclass = function( params ) local xprimclass = { prefix = params.prefix, def_format = params.def_format, case_format = "case %s: %s\n", case_formatter = function( xprim ) return format("case %s: PRIMp(\"%s\"); %s\n", xprim.aname, xprim.aname, xprim.Ccode) end, compile_format = params.compile_format, nbytes = params.nbytes, cdefs_str = "", adefs_str = "", case_str = "", all = {}, used = {}, firstopcode = params.firstopcode, nextopcode = params.firstopcode, step = params.step, declare = nil, -- class method define_opcode = nil, -- class method assert_used = nil, -- instance method compile = nil -- instance method } xprimclass.declare = function( xprimclass, aname, Ccode ) local xprim = heir { aname = aname, compile_str = format(xprimclass.compile_format, aname), opcode = nil, Ccode = Ccode, depends = nil, UP = xprimclass, FUN = xprimclass.compile, } tinsert(xprimclass.all, xprim) return xprim end xprimclass.define_opcode = function( xprimclass, aname ) local c, opcode = xprimclass, xprimclass.nextopcode c.adefs_str = c.adefs_str .. format(c.def_format, "%", aname, opcode) c.cdefs_str = c.cdefs_str .. format(c.def_format, "#", aname, opcode) end xprimclass.assert_used = function( xprim ) if xprim.opcode then return end local c = xprim.UP c.define_opcode(c, xprim.aname) xprim.opcode = c.nextopcode c.nextopcode = c.nextopcode + c.step c.case_str = c.case_str .. c.case_formatter(xprim) -- c.case_str .. format(c.case_format, xprim.aname, xprim.Ccode) tinsert(c.used, xprim) if xprim.depends then foreachi(xprim.depends, function( i, depend ) if type(depend)=="string" then dict[depend]:assert_used() else depend:assert_used() end end) end end xprimclass.compile = function( xprim ) xprim:assert_used() nasm(xprim.nbytes, xprim.compile_str) end return xprimclass end --%%%% --% --% «hprimclass» (to ".hprimclass") --% «fprimclass» (to ".fprimclass") --% «fipprimclass» (to ".fipprimclass") --% --%%%% hprimclass = newxprimclass { prefix = "H_", def_format = "%sdefine %-16s 0x%02X\n", compile_format = "\tdb %s\n", nbytes = 1, firstopcode = 0, step = 1, } fprimclass = newxprimclass { prefix = "F_", def_format = "%sdefine %-16s 0x%04X\n", compile_format = "\tdhl %s\n", nbytes = 2, firstopcode = ((255-10)*256)+255, -- space for 10 sfprims step = -1, } fipprimclass = newxprimclass { prefix = "FIP_", def_format = "%sdefine %-16s 0x%04X\n", compile_format = "\tdhl %s\n", nbytes = 1, firstopcode = 65535, step = -1, } --%%%% --% --% «fwordclass» (to ".fwordclass") --% --%%%% fwordclass = { compile = function( fword ) nasm(2, fword.compile_str) end, declare = nil } fwordclass.declare = function( thisclass, wordname ) local aname = "ADR_" .. nasmify(wordname) nasm(0, format("%s:\n", aname)) local fword = heir { compile_str = format("\tdhl %s -_f0\n", aname), UP = thisclass, FUN = thisclass.compile } dict[wordname] = fword end fwordclass.gdeclare = function( thisclass, wordname ) local aname = "ADR_" .. nasmify(wordname) nasm(0, format("global %s\n", aname)) thisclass:declare(wordname) end --%%%% --% --% «sfprimclass» (to ".sfprimclass") --% Experimental! Ugly! --% This supports both adding an sfprim to an existing fprim and --% creating both at the same time with sfprimclass:declare. --% --%%%% sfprimclass = newxprimclass { prefix = "SF_", def_format = "%sdefine %-16s 0x%02X\n", compile_format = "\tdb %s\n", nbytes = 1, firstopcode = 255, step = -1, } sfprimclass.transltable_str = "" sfprimclass.assert_used_sfonly = sfprimclass.assert_used sfprimclass.assert_used = function( sfprim ) local fprim = sfprim.fprim fprim:assert_used() if sfprim.opcode == nil then sfprim.UP.transltable_str = sfprim.UP.transltable_str .. fprim.aname .. ", " end sfprim:assert_used_sfonly() end sfprimclass.declare_sfonly = sfprimclass.declare sfprimclass.declare = function( sfprimclass, sfaname, Ccode ) local faname = strsub(2, sfaname) -- hack; drop the "S" from "SF_" local fprim = fprimclass:declare(faname, Ccode) local sfprim = sfprimclass:declare_sfonly(sfaname, "??") -- no case for sfs sfprim.fprim = fprim fprim.sfprim = sfprim return sfprim, fprim end fprimclass.assert_sfprim_exists = function( fprim ) if fprim.sfprim then return fprim.sfprim end local faname = fprim.aname local sfaname = "S"..faname local sfprim = sfprimclass:declare_sfonly(sfaname, faname..", ") -- ugh sfprim.fprim = fprim fprim.sfprim = sfprim return sfprim, fprim end --%%%% --% --% «declarehprims» (to ".declarehprims") --% «declarefprims» (to ".declarefprims") --% --%%%% declarexprims_helper = function( pairs, fun ) local i, words, aname_stem, Ccode for i=1,getn(pairs),2 do words = split(pairs[i]) aname_stem = nasmify(words[1]) Ccode = pairs[i+1] fun(words, aname_stem, Ccode) end end declarehprims = function( ... ) -- ... = words, Ccode, words, Ccode... declarexprims_helper(arg, function( words, aname_stem, Ccode ) local c = hprimclass local hprim, j = c:declare(c.prefix..aname_stem, Ccode) for j=1,getn(words) do dict[c.prefix..words[j]] = hprim end end) end declarefprims = function( ... ) -- ... = words, Ccode, words, Ccode... declarexprims_helper(arg, function( words, aname_stem, Ccode ) local c = fprimclass local fprim, j = c:declare(c.prefix .. aname_stem, Ccode) for j=1,getn(words) do dict[c.prefix..words[j]] = fprim dict[words[j]] = fprim end end) end declarefipprims = function( ... ) -- ... = words, Ccode, words, Ccode... declarexprims_helper(arg, function( words, aname_stem, Ccode ) local c = fipprimclass local fipprim, j = c:declare(c.prefix .. aname_stem, Ccode) for j=1,getn(words) do dict[c.prefix..words[j]] = fipprim -- won't be used end end) end prefer_sf_form = function( wordsasstring ) foreachi(split(wordsasstring), function( i, word ) local sfprim, fprim = fprimclass.assert_sfprim_exists(dict["F_"..word]) dict["SF_"..word] = sfprim dict[word] = sfprim end) end --%%%% --% --% «standard_primitives» (to ".standard_primitives") --% --%%%% declarehprims( "COL "," goto forth;", "CON "," DS[1]=*(int *)(_f0+RS[0]); DS++; RS--; goto forth;", "TO "," *(int *)(_f0+RS[0]+1)=DS[0]; DS--; RS--; goto forth;", "AT "," DS[1]=((int)_f0)+RS[0]+2; DS++; RS--; goto forth;", "RSR "," SS[1]=((int)_f0)+RS[-1]; SS++; RS[-1]=FIP_RSREXIT; goto head;", "C0 "," fun=*(funptr *)(_f0+RS[0]); DS[1]=(*fun)(); DS++;RS--; goto forth;", "C1 "," fun=*(funptr *)(_f0+RS[0]); DS[0]=(*fun)(DS[0]); RS--; goto forth;", "C2 "," fun=*(funptr *)(_f0+RS[0]); DS[-1]=(*fun)(DS[-1], DS[0]);" .." DS--; RS--; goto forth;", "C3 "," fun=*(funptr *)(_f0+RS[0]); DS[-2]=(*fun)(DS[-2], DS[-1], DS[0]);" .." DS-=2; RS--; goto forth;", "DROPPING"," RS[1]=RS[0]; RS[0]=FIP_FIPDROP; RS++; goto head;" ) declarefprims( "EXIT ; "," RS--; goto forth;", "PLUS + "," DS[-1]+=DS[0]; DS--; goto forth;", "DUP "," DS[1]=DS[0]; DS++; goto forth;", "2DUP "," DS[1]=DS[-1]; DS[2]=DS[0]; DS+=2; goto forth;", "SWAP "," itmp=DS[-1]; DS[-1]=DS[0]; DS[0]=itmp; goto forth;", "DROP "," DS--; goto forth;", "SBRANCH "," SS[0]=(int)_f0+*((ushort *)(SS[0])); goto forth;", "S0BRANCH "," tmp=*((ushort *)(SS[0]))++; if(DS[0]==0) SS[0]=(int)_f0+tmp;" .." DS--; goto forth;", "0 "," DS[1]=0; DS++; goto forth;", "1 "," DS[1]=1; DS++; goto forth;", "TIMES * "," DS[-1]*=DS[0]; DS--; goto forth;", "COUNT "," DS[1]=*((uchar *)(DS[0]))++; DS++; goto forth;", "TYPE "," fwrite((void *)(DS[-1]), 1, DS[0], stdout); DS-=2; goto forth;", "CR "," printf(\"\\n\"); goto forth;", "STO S> "," DS[1]=SS[0]; DS++; SS--; goto forth;", "TOS >S "," SS[1]=DS[0]; SS++; DS--; goto forth;", "SGOBBLE1 "," DS[1]=*((uchar *)(SS[0]))++; DS++; goto forth;", "SGOBBLE2 "," DS[1]=*((ushort *)(SS[0]))++; DS++; goto forth;", "WSTORE W! "," *((ushort *)(DS[0]))=DS[1]; DS-=2; goto forth;", "WFETCH W@ "," DS[0]=*((ushort *)(DS[0])); goto forth;" ) declarefipprims( "RETURN "," RS--; return;", "RSREXIT "," RS[0]=SS[0]-((int)_f0); SS--; goto forth;", "FIPDROP "," RS--; DS--; goto forth;" ) dict["FIP_RETURN"]:assert_used() dict["H_RSR"].depends = {"FIP_RSREXIT"} prefer_sf_form("EXIT ; DUP") dict["EXIT"]:assert_used() --%%%% --% --% «defineLASTs» (to ".defineLASTs") --% «unskeletize» (to ".unskeletize") --% --%%%% -- (find-node "(lua)Patterns" "shortest") defineLASTs = function() hprimclass:define_opcode(hprimclass.prefix .. "LAST") fprimclass:define_opcode(fprimclass.prefix .. "LAST") sfprimclass:define_opcode(sfprimclass.prefix .. "LAST") fipprimclass:define_opcode(fipprimclass.prefix .. "LAST") end unskeletize = function(fnamein, fnameout) local bigstr = readfile(fnamein) bigstr = gsub(bigstr, "<<LUA(.-)LUA>>", dostring) writefile(fnameout, bigstr) printf("Wrote %s\n", fnameout) end -- (find-angg "miniforth/") -- (find-angg "miniforth/crim/") -- (find-angg "miniforth/crim/crim.lua") -- (find-angg "miniforth/crim/demo1.mflua") comment = [[ # (find-fline "~/flua/") # (find-fline "~/flua/demo1.bytecode.asm") # (find-fline "~/flua/demo1.flua") # (find-fline "~/flua/flua-comp.lua") # (find-fline "~/flua/flua-demos.lua") # (find-fline "~/flua/flua-lua.lua") # (find-fline "~/flua/flua-prims.lua") # (find-fline "~/flua/flua.lua") #* a2ps -=p2iso ~/miniforth/crim.lua make -f ~/LATEX/Makefile /tmp/o.p01 #* # (find-fline "~/o") cd ~/miniforth/ mylua crim.lua |& tee ~/o #* # (find-fline "~/o") cd ~/miniforth/ mylua -f miniforth1.lua crim/demo1.mflua |& tee ~/o #* ]]