|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- https://anggtwu.net/LUA/Comprehensions2.lua.html
-- https://anggtwu.net/LUA/Comprehensions2.lua
-- (find-angg "LUA/Comprehensions2.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun e () (interactive) (find-angg "LUA/Comprehensions2.lua"))
-- (defun o () (interactive) (find-angg "LUA/Comprehensions1.lua"))
-- (defun oe () (interactive) (find-2a '(o) '(e)))
-- «.MTree» (to "MTree")
-- «.colnames» (to "colnames")
-- «.syntree» (to "syntree")
-- «.tex» (to "tex")
-- «.add» (to "add")
-- «.collect» (to "collect")
-- «.Comprehension» (to "Comprehension")
-- «.Gen-Filt-Expr» (to "Gen-Filt-Expr")
-- «.Function» (to "Function")
-- «.runcmds» (to "runcmds")
-- «.Comprehension-tests» (to "Comprehension-tests")
-- «.Comprehension-runcmds-tests» (to "Comprehension-runcmds-tests")
-- __ __ _____
-- | \/ |_ _| __ ___ ___
-- | |\/| | | || '__/ _ \/ _ \
-- | | | | | || | | __/ __/
-- |_| |_| |_||_| \___|\___|
--
-- «MTree» (to ".MTree")
MTree = Class {
type = "MTree",
new = function (o) return MTree {[0]=o} end,
from = function (o,...) -- very dwimmy, for building MTrees by hand for tests
if #{...}>0 then o = {[0]=o,...} end
if type(o) == "number" then o = tostring(o) end
if type(o) == "string" then return MTree {[0]=o} end
if otype(o) == "MTree" then return o end -- Mtrees are returned unchanged
local T = MTree {[0]=o[0]} -- other tables are converted recursively
for _,leaf in ipairs(o) do table.insert(T, MTree.from(leaf)) end
return T
end,
__tostring = function (T) return T:tostring() end, -- colnames + syntree
__index = {
--
-- «colnames» (to ".colnames")
setcolnames = function (T,cols) T.colnames = cols; return T end,
colnames_syntree = function (T) return T:colnames_rect(" | ", "") end,
colnames_tex = function (T) return T:colnames_rect(" & ", " \\\\\\HLine") end,
colnames_rect = function (T,sep,post)
if not T.colnames then return Rect {} end
local line = table.concat(T.colnames, sep)..post
return Rect {line}
end,
--
-- «syntree» (to ".syntree")
torect = function (T) return T:colnames_syntree() / SynTree.from(T):torect() end,
tostring = function (T) return T:torect():tostring() end,
--
-- «tex» (to ".tex")
totexrect1 = function (T)
if #T==0 then return Rect {T[0].." \\\\"} end -- if we're on a leaf
local rect = Rect {}
for _,leaf in ipairs(T) do rect = rect / leaf:totexrect1() end
if T[0] then rect = tostring(T[0])..(" & "*rect) end
return rect
end,
totexrect2 = function (T) return T:colnames_tex() / T:totexrect1() end,
totexrect3 = function (T)
return Rect {"\\comprehensionbox{"}
/ (" "..T:totexrect2())
/ " }"
end,
totexrect = function (T) return T:totexrect3() end,
totex = function (T) return T:totexrect():tostring() end,
--
-- «add» (to ".add")
-- Methods that add elements and subtrees to an MTree.
-- These methods are very tricky! See MTree_test{1,2,3} below.
add = function (T,o)
local subTree = MTree.new(o)
table.insert(T,subTree)
return subTree
end,
addstop = function (T) T:add("\\Stop") end,
addfalse = function (T) T:add("\\False"):addstop() end,
addtrue = function (T) return T:add("\\True") end,
addstopifempty = function (T) if #T == 0 then T:addstop() end end,
--
-- «collect» (to ".collect")
collect = function (T) return T:collectintoset() end,
collectintoset = function (T) return Set.from(T:collectintolist()) end,
collectintolist = function (T) return T:collectinto(VTable{}) end,
collectinto = function (T,L)
if #T==0
then if T[0] and T[0] ~= "\\Stop" then table.insert(L,T[0]) end
else for _,subTree in ipairs(T) do subTree:collectinto(L) end
end
return L
end,
},
}
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Comprehensions2.lua"
tr = MTree.from
T = MTree.from {MTree.from(3,34,35), 4}
T = MTree.from(2, MTree.from(3, 34,
35),
4)
= T
PPP(T)
T.colnames = {"foo", "bar"}
= T
= T:totexrect1()
= T:totexrect2()
= T:totexrect3()
--]]
-- ____ _ _
-- / ___|___ _ __ ___ _ __ _ __ ___| |__ ___ _ __ ___(_) ___ _ __
-- | | / _ \| '_ ` _ \| '_ \| '__/ _ \ '_ \ / _ \ '_ \/ __| |/ _ \| '_ \
-- | |__| (_) | | | | | | |_) | | | __/ | | | __/ | | \__ \ | (_) | | | |
-- \____\___/|_| |_| |_| .__/|_| \___|_| |_|\___|_| |_|___/_|\___/|_| |_|
-- |_|
--
-- «Comprehension» (to ".Comprehension")
Comprehension = Class {
type = "Comprehension",
new = function () return Comprehension {prog = Rect{}} end,
from = function (names,cmds,verbose)
local co = Comprehension {prog=Rect{}, names=names, cmds=cmds}
if names then co.colnames = split(names) end
co:runcmds(cmds,verbose)
co:Function()
return co
end,
__tostring = function (co) return co:tostring() end,
__index = {
tostring = function (co) return co.prog:tostring() end,
program = function (co) return co.prog:tostring() end,
pre_ = function (co,r1) co.prog = torect(r1) / co.prog; return co end,
post_ = function (co,r2) co.prog = co.prog / torect(r2); return co end,
pre = function (co,fmt,...) return co:pre_ (format(fmt,...)) end,
post = function (co,fmt,...) return co:post_(format(fmt,...)) end,
--
-- «Gen-Filt-Expr» (to ".Gen-Filt-Expr")
var = function (co,str) -- co:var("_,x in seq(2,5)") returns "x"
str = bitrim(str)
str = str:gsub("^_,", "")
str = str:gsub("^([0-9A-Za-z_]+).*", "%1")
return str
end,
For = function (co,gen)
co.prog = Rect {format("for %s do", gen)}
/ (" " .. co.prog)
/ Rect {"end"}
/ Rect {"T:addstopifempty()"}
return co
end,
Filt = function (co,expr)
local indentedbody = " " .. (Rect {"local T = T:addtrue()"} / co.prog)
co.prog = Rect {format("if %s then", expr)}
/ indentedbody
/ Rect {"else T = T:addfalse()"}
/ Rect {"end"}
return co
end,
Expr = function (co,expr) return co:pre("local T = T:add(%s)", expr) end,
Gen = function (co,gen) return co:Expr(co:var(gen)):For(gen) end,
--
-- «Function» (to ".Function")
Setcolnames = function (co)
if not co.colnames then return co end
local body = mapconcat(mytostring, co.colnames, ", ")
co.prog = Rect {format("T:setcolnames({%s})", body)} / co.prog
return co
end,
Functionbody = function (co)
co.prog = Rect {"local T = MTree.new()"}
/ co.prog
/ Rect {"return T"}
return co
end,
Function0 = function (co)
co.prog = Rect {"function ()"}
/ (" "..co.prog)
/ Rect {" end"}
return co
end,
Function = function (co)
return co:Setcolnames():Functionbody():Function0()
end,
run = function (co) return expr(c:program())() end,
--
-- «runcmds» (to ".runcmds")
runcmd = function (co,cmd,verbose)
local funname,arg = cmd:match("^(.-):(.*)$")
if verbose then PP("runcmd:", funname, arg) end
return co[funname](co, arg)
end,
runcmds = function (co,cmds,verbose)
if verbose then PP("runcmds:", cmds) end
for _,cmd in ipairs(table.reverse(split(cmds))) do
co:runcmd(cmd,verbose)
end
return co
end,
},
}
-- «Comprehension-tests» (to ".Comprehension-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Comprehensions2.lua"
c = Comprehension.new()
= c:Expr("x+y")
= c:Filt("x+y<5")
= c:Gen("y=2,3")
= c:Gen("x=1,2")
c.colnames = {"x", "y", "x+y<5", "x+y"}
= c:Function()
= c:program()
= c:run()
= c:run():totex()
= c:run():collect()
= c:run():collect():ksc(" ")
= c:run():collectintolist()
= table.concat(c:run():collectintolist(), " ")
--]]
-- «Comprehension-runcmds-tests» (to ".Comprehension-runcmds-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Comprehensions2.lua"
c = Comprehension.new()
c:runcmd("Expr:x+y", "verbose")
c:runcmd("Filt:x+y<5", "verbose")
c:runcmd("Gen:y=2,3", "verbose")
c:runcmd("Gen:x=1,2", "verbose")
c:Function()
= c:run()
c = Comprehension.new()
c:runcmds("Gen:x=1,2 Gen:y=2,3 Filt:x+y<5 Expr:x+y", "verbose")
c:Function()
= c:program()
= c:run()
c = Comprehension.from(
" x y x+y<5 x+y",
"Gen:x=1,2 Gen:y=2,3 Filt:x+y<5 Expr:x+y",
"verbose")
= c
= c:run()
= c:run():collect():ksc(" ")
= c:run():totex()
--]]