Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://angg.twu.net/LUA/Pis1.lua.html -- http://angg.twu.net/LUA/Pis1.lua -- (find-angg "LUA/Pis1.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- Supersed by: (find-angg "LUA/Prad1.lua") -- -- Pict2e stack language: a language for generating pict2e code that -- can push and pop contexts and indentations, and that can also -- generate code for sgv.el. -- -- Here is a program in Pis, in pseudocode: -- -- { print("begin picture with bounds (0,0) and (12,8)") -- print("set thickness to 2pt") -- { print("{") -- local indent = outer indent + 2 -- print("set color to red") -- print("line from A to B") -- print("}") -- } -- { print "line from B to C" -- print "line from C to D" -- } -- print("end picture") -- } -- -- All "print"s append lines to the array "out", and some "{}" blocks -- create a copy of the current context and discard it when the block -- ends. -- (defun l () (interactive) (find-angg "LUA/Pis1.lua")) -- «.PisOutput» (to "PisOutput") -- «.PisOutput-tests» (to "PisOutput-tests") -- «.PisContext» (to "PisContext") -- «.PisContext-tests» (to "PisContext-tests") -- «.PisClass» (to "PisClass") -- «.PisClass-tests» (to "PisClass-tests") spaces = function (n) return string.rep(" ", n) end dellastnewline = function (str) return (str:gsub("\n$", "")) end -- «PisOutput» (to ".PisOutput") -- PisOutput = Class { new = function () return PisOutput({}) end, type = "PisOutput", __tostring = function (po) return dellastnewline(table.concat(po)) end, __index = { add0 = function (po, line) table.insert(po, line) return po end, endswithopenbrace = function (po, i) return po[i]:match("^(.*{)%%?\n$") end, startswithnspaces = function (po, j, n) if po[j]:sub(1, n) == spaces(n) then return po[j]:sub(n+1) end end, optimize = function (po) return copy(po):optimize0() end, optimize0 = function (po) for i=#po-1,1,-1 do local a = po:endswithopenbrace(i) local b = a and po:startswithnspaces(i+1, #a) if b then po[i] = a po[i+1] = b end end return po end, }, } -- «PisOutput-tests» (to ".PisOutput-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pis1.lua" po = PisOutput({ "abcd{%\n", " foo\n" }) = po = po:optimize() PP(po) --]] -- «PisContext» (to ".PisContext") -- PisContext = Class { type = "PisContext", new = function (indent, suffix) return PisContext {indent=(indent or ""), suffix=(suffix or "%")} end, __tostring = mytostring, __index = { copy = function (pc) return copy(pc) end, set = function (pc, key, val) pc[key] = val; return pc end, copyset = function (pc, key, val) return pc:copy():set(key, val) end, copyindent = function (pc, extraindent) return pc:copyset("indent", pc.indent .. (extraindent or " ")) end, }, } -- «PisContext-tests» (to ".PisContext-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pis1.lua" = PisContext.new() = PisContext.new():copyindent() = PisContext.new():copyindent(" ") = PisContext.new():copy() = PisContext.new():copy():set("foo", "bar") = PisContext.new():copyset("foo", "bar") --]] -- «PisClass» (to ".PisClass") -- PisClass = Class { type = "PisClass", from = function (classtable) Class(classtable) setmetatable(classtable.__index, { __index = PisClass.__index }) return classtable end, __index = { add0 = function (pis, out, ctx, line) return out:add0(line) end, add1 = function (pis, out, ctx, line) return out:add0(ctx.indent .. line .. ctx.suffix .. "\n") end, additem = function (pis, out, ctx, item) if type(item) == "string" then pis:add1(out, ctx, item) else item:texprint(out, ctx) end end, adds = function (pis, out, ctx, items) for i,item in ipairs(items) do pis:additem(out, ctx, item) end end, tolatex = function (pis, out, ctx) if type(ctx) == "string" then ctx = PisContext.new(ctx) end out = out or PisOutput.new() ctx = ctx or PisContext.new() pis:texprint(out, ctx) return out end, -- tostructsortedkvs = function (pis) return Tos({}):getsortedkvs(pis) end, tostructbe = function (pis, key) local class = getmetatable(pis) and getmetatable(pis).type local k = key and (mytostring(key).."=") or "" if class then return k..class.."({", "})" end return k.."{", "}" end, tostructprint = function (pis, out, ctx, key) local newctx = ctx:copyindent() local b,e = pis:tostructbe(key) local kvs = pis:tostructsortedkvs() pis:add1(out, ctx, b) for _,kvs in ipairs(kvs) do local k,v = kvs.key, kvs.val if type(v) == "string" then local line = format("%s=%s", mytostring(k), mytostring(v)) pis:add1(out, newctx, line) else v:tostructprint(out, newctx, k) end end pis:add1(out, ctx, e) end, tostruct = function (pis, out, ctx, key) if type(ctx) == "string" then ctx = PisContext.new(ctx, "") end out = out or PisOutput.new() ctx = ctx or PisContext.new("", "") pis:tostructprint(out, ctx, key) return out end, }, } PisList = PisClass.from { type = "PisList", __tostring = function (pis) return tostring(pis:tolatex()) end, __index = { texprint = function (pis, out, ctx) pis:adds(out, ctx, pis) end, }, } PisSub = PisClass.from { type = "PisSub", __tostring = function (pis) return tostring(pis:tolatex()) end, __index = { texprint = function (pis, out, ctx) local newctx = ctx:copyindent() pis:add1(out, ctx, (pis.b or "{")) pis:adds(out, newctx, pis) pis:add1(out, ctx, (pis.e or "}")) end, }, } -- «PisClass-tests» (to ".PisClass-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pis1.lua" -- High-level tests: a = PisList({"aa", "aaa"}) b = PisSub ({"bb", "bbb"}) = a:tolatex() = b:tolatex() c = PisList({"cc", a, b, "ccc"}) = c:tolatex() = c:tolatex():optimize() = c:tolatex(nil, ":: ") = PisList({"% Blah: ", c}):tolatex() = PisSub ({"% Blah: ", c}):tolatex() = PisSub ({"% Blah: ", c}):tolatex():optimize() = PisSub ({b="BEGIN", e="END", c}):tolatex() = PisSub ({b="BEGIN", e="END", c}) = PisSub ({b="BEGIN", e="END", c}):tostruct() -- Tests for tostruct: a = PisSub ({b="BEGIN", e="END", "aa", "bb"}) PP(a:tostructsortedkvs()) PP(a:tostructbe()) = a:tostruct() = a:tostruct(nil, nil, "foo") = a:tostruct(nil, nil, 123) b = PisSub ({b="BOGIN", e="OND", a, "cc", "dd"}) = b:tostruct() = b -- Low-level tests: pl = PisLiteral({}) = pl pl:bar() PP(PisClass.__index) PP(PisLiteral) PP(PisLiteral.__index) PP(getmetatable(PisLiteral.__index)) o = PisOutput.new() c = PisContext.new() s = PisSub({"foo", "bar"}) = o = o:optimize() = o = s:tolatex() = s:tolatex():optimize() = s:tolatex(nil, PisContext.new("::")):optimize() --]] PisClass.__index.def = function (pis, name) local b = "\\def\\"..name.."{{" local e = "}}" return PisSub({b=b, pis, e=e}) end PisClass.__index.precolor = function (pis, color) local c = "\\color{"..color.."}" return PisList({c, pis}) end PisClass.__index.prethickness = function (pis, thickness) local c = "\\linethickness{"..thickness.."}" return PisList({c, pis}) end PisClass.__index.preunitlength = function (pis, unitlength) local c = "\\unitlength="..unitlength return PisList({c, pis}) end PisClass.__index.bhbox = function (pis) local b = "\\bhbox{$" local e = "$}" return PisSub({b=b, pis, e=e}) end PisClass.__index.myvcenter = function (pis) local b = "\\myvcenter{" local e = "}" return PisSub({b=b, pis, e=e}) end --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Pis1.lua" a = PisList({"foo", "bar"}) = a = a:preunitlength("2pt"):prethickness("3pt") = a:preunitlength("2pt"):prethickness("3pt"):def("NAME") = a:preunitlength("2pt"):prethickness("3pt"):def("NAME") = a:preunitlength("2pt"):prethickness("3pt"):myvcenter():bhbox() = a --]] -- Local Variables: -- coding: utf-8-unix -- End: