Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- diagforth.lua: interpreting the words in "%D" lines in dednat6 files.
-- This file:
--   http://angg.twu.net/dednat6/dednat6/diagforth.lua.html
--   http://angg.twu.net/dednat6/dednat6/diagforth.lua
--           (find-angg "dednat6/dednat6/diagforth.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2021feb26
-- License: GPL3
--


-- (find-blogme4 "eval.lua" "parse_pattern")
-- (find-angg "LUA/lua50init.lua" "untabify")
-- (find-blogme4 "eval.lua" "readvword")



-- «.metastack»		(to "metastack")
-- «.diag-head»		(to "diag-head")
-- «.diagram»		(to "diagram")
-- «.enddiagram»	(to "enddiagram")
-- «.BOX»		(to "BOX")
-- «.nodes»		(to "nodes")
-- «.arrow-modifiers»	(to "arrow-modifiers")
-- «.dxyren»		(to "dxyren")
-- «.arrows»		(to "arrows")
-- «.2D-and-2Dx»	(to "2D-and-2Dx")

-- «.run»		(to "run")
-- «.dxyrun»		(to "dxyrun")
-- «.forths»		(to "forths")

-- «.relplace»		(to "relplace")
-- «.newnode:at:»	(to "newnode:at:")

-- «.high-level-tests»	(to "high-level-tests")
-- «.low-level-tests»	(to "low-level-tests")

require "diagtex"    -- (find-dn6 "diagtex.lua")
require "parse"      -- (find-dn6 "parse.lua")
-- require "process" -- (find-dn6 "process.lua")
require "errors"     -- (find-dn6 "errors.lua")


forths = {}


-- «metastack»  (to ".metastack")
-- (find-dn6 "diagstacks.lua" "MetaStack")
forths["(("] = function () depths:ppush() end
forths["))"] = function () depths:ppop() end
forths["@"] = function () ds:push(depths:metapick(1 + getwordasluaexpr())) end



-- «run»     (to ".run")
-- «dxyrun»  (to ".dxyrun")
-- Used mainly by: (find-dn6 "heads6.lua" "diag-head")
--
dxyrun = function (str, pos)
    setsubj(str, pos or 1)
    while getword() do
      -- PP(word)
      if    forths[word] then forths[word]()
      elseif nodes[word] then ds:push(nodes[word])
      else Error("Unknown word: "..word)
      end
    end
  end




-- «diagram»  (to ".diagram")
-- «enddiagram»  (to ".enddiagram")
forths["diagram"] = function ()
    diagramname = getword() or derror("No diagram name")
    xys = {}
    nodes  = VerticalTable {}
    arrows = VerticalTable {}
    lasty = nil
  end
forths["enddiagram"] = function ()
    output(arrows_to_defdiag(diagramname, tf:hyperlink()))
  end




-- «BOX»  (to ".BOX")
-- (find-es "dednat" "BOX-dednat6")
-- Note: THIS IS A HACK!!! We even redefine "enddiagram"!
--
mybox_bodies = {}
forths["enddiagram"] = function ()
    if #mybox_bodies == 0 then
      output(arrows_to_defdiag(diagramname, tf:hyperlink()))
    else
      output(arrows_to_defdiagprep(diagramname, mybox_preps(), tf:hyperlink()))
      mybox_bodies = {}
    end
  end
mybox_names = {
  "\\myboxa", "\\myboxb", "\\myboxc", "\\myboxd",
  "\\myboxe", "\\myboxf", "\\myboxg", "\\myboxh"
}
mybox_prep1 = function (boxname, body)
    return format("  \\savebox{%s}{$%s$}\n", boxname, body)
  end
mybox_preps = function ()
    prep = ""
    for i,body in ipairs(mybox_bodies) do
      prep = prep .. mybox_prep1(mybox_names[i], body)
    end
    return prep
  end
forths["BOX"] = function ()
    tinsert(mybox_bodies, node_to_TeX(ds:pick(0)))
    ds:pick(0).tex = format("\\usebox{%s}", mybox_names[#mybox_bodies])
  end





-- «2D-and-2Dx»  (to ".2D-and-2Dx")
-- (find-dn4file "dednat4.lua" "dxy2Dx =")
torelativenumber = function (prevn, str)
    local sign, strn = str:match("^([-+]?)([0-9.]+)$")
    if not sign then return end           -- fail
    local n = tonumber(strn)
    if sign == "" then return n end
    if sign == "+" then return prevn + n else return prevn - n end
  end

dxy2Dx = function ()
    xs = {}
    local lastx = nil
    while getword() do
      local n = torelativenumber(lastx, word)
      if n then
        xs[startcol] = n
        lastx = n
      end
    end
  end
forths["2Dx"] = dxy2Dx

firstxin = function (s, e)
    for i=s,e do if xs[i] then return xs[i] end end
  end
dxy2Ddo = function (y, word)
    if word == "#" then getrestofline(); return end
    local x = firstxin(startcol, endcol-1)
    if not x then return end
    storenode {x=x, y=y, tag=word}
  end
dxy2D = function ()
    if not getword() then return end
    thisy = torelativenumber(lasty, word)
    if not thisy then getrestofline(); return end
    while getword() do dxy2Ddo(thisy, word) end
    lasty = thisy
  end
forths["2D"]  = dxy2D



-- «forths»  (to ".forths")
forths["#"] = function () getrestofline() end

-- «nodes»  (to ".nodes")
forths["node:"] = function ()
    local x,y = getwordasluaexpr()
    local tag = getword()
    ds:push(storenode {x=x, y=y, tag=tag})
  end
forths[".tex="] = function () ds:pick(0).tex = getword() or werror() end
forths[".TeX="] = function () ds:pick(0).TeX = getword() or werror() end

-- «arrow-modifiers»  (to ".arrow-modifiers")
-- (find-dn4 "dednat4.lua" "diag-arrows")
forths[".p="] = function () ds:pick(0).placement = getword() or werror() end
forths[".slide="] = function () ds:pick(0).slide = getword() or werror() end
forths[".curve="] = function () ds:pick(0).curve = getword() or werror() end
forths[".label="] = function () ds:pick(0).label = getword() or werror() end
forths[".plabel="] = function ()
    ds:pick(0).placement = getword() or error()
    ds:pick(0).label     = getword() or error()
  end
-- (find-dn4 "dednat4.lua" "lplacement")
forths[".PLABEL="] = function ()
    ds:pick(0).lplacement = getword() or error()
    ds:pick(0).label      = getword() or error()
  end

-- «dxyren» (to ".dxyren")
dxyren = function (li)
    local a, b = li:match("^(.*) =+> (.*)$")
    if not a then error("No '==>': "..li) end
    local A, B = split(a), split(b)
    if #A ~= #B then error("Bad args to ren: "..li) end
    for i=1,#A do
      local tag, node = A[i], nodes[A[i]]
      if not node then error("No node with this tag: "..tag) end
      node.tex = B[i]
    end
  end
forths["ren"] = function () dxyren(getrestofline()) end

-- «arrows» (to ".arrows")
pusharrow = function (shape)
    local from, to = ds:pick(1), ds:pick(0)
    ds:push(storearrow(DxyArrow {from=from.noden, to=to.noden, shape=shape}))
  end

forths["->"] = function () pusharrow("->") end
forths["=>"] = function () pusharrow("=>") end
forths[".>"] = function () pusharrow(".>") end
forths[":>"] = function () pusharrow(":>") end
forths["|.>"] = function () pusharrow("|.>") end
forths["-->"] = function () pusharrow("-->") end
forths["==>"] = function () pusharrow("==>") end
forths["|->"] = function () pusharrow("|->") end
forths[">->"] = function () pusharrow(" >->") end
forths["`->"] = function () pusharrow("^{ (}->") end
forths[">-->"] = function () pusharrow(" >-->") end
forths["|-->"] = function () pusharrow("|-->") end

forths["<-"]  = function () pusharrow("<-") end
forths["<="]  = function () pusharrow("<=") end
forths["<."]  = function () pusharrow("<.") end
forths["<.|"] = function () pusharrow("<.|") end
forths["<--"] = function () pusharrow("<--") end
forths["<=="] = function () pusharrow("<==") end
forths["<-|"] = function () pusharrow("<-|") end
forths["<-<"] = function () pusharrow("<-< ") end
forths["<-'"] = function () pusharrow("<-^{) }") end
forths["<--|"] = function () pusharrow("<--|") end

forths["<->"] = function () pusharrow("<->") end
forths["="]   = function () pusharrow("=") end

forths["sl^^"] = function () ds:pick(0).slide =    "5pt" end
forths["sl^"]  = function () ds:pick(0).slide =  "2.5pt" end
forths["sl_"]  = function () ds:pick(0).slide = "-2.5pt" end
forths["sl__"] = function () ds:pick(0).slide =   "-5pt" end

defarrows = function (bigstr)
    for _,spec in ipairs(split(bigstr)) do
      forths[spec] = function () pusharrow(spec) end
    end
  end

forths["place"] = function ()
    ds:push(storearrow(DxyPlace {ds:pick(0)}))
  end

-- (find-es "diagxy" "loop")
forths["loop"] = function ()
    ds:push(storearrow(DxyLoop {ds:pick(0), dTeX=getword()}))
  end


-- (find-dn6grep "grep -nH -e forths diagforth.lua")
-- (find-LATEXgrep "grep -nH -e forths *.tex")
forths["x+="] = function () ds:pick(0).x = ds:pick(0).x + getwordasluaexpr() end
forths["y+="] = function () ds:pick(0).y = ds:pick(0).y + getwordasluaexpr() end

forths["xy+="] = function ()
    local dx,dy = getwordasluaexpr(), getwordasluaexpr()
    ds:pick(0).x = ds:pick(0).x + dx
    ds:pick(0).y = ds:pick(0).y + dy
  end

-- «relplace»  (to ".relplace")
-- (find-LATEXfile "2017elephant.tex" "relplace")
forths["relplace"] = function ()
    local x, y = ds:pick(0).x, ds:pick(0).y
    local dx, dy = getwordasluaexpr(), getwordasluaexpr()
    local TeX = getword()
    ds:push(storearrow(DxyPlace {{x=x+dx, y=y+dy, tex=TeX}}))
  end




-- «newnode:at:»  (to ".newnode:at:")
-- See: (find-es "dednat" "at:")
-- New, 2021feb26.
-- To do: move Node and storenode to the right places.

Node = Class {
  type       = "Node",
  __tostring = function (node) return mytostring(node) end,
  __index    = {
    v    = function (node) return v(node.x,node.y) end,
    setv = function (node,v) node.x=v[1]; node.y=v[2]; return node end,
  },
}
storenode = function (node)
    node = Node(node)
    table.insert(nodes, node)
    node.noden = #nodes         -- nodes[node.noden] == node
    if node.tag then            -- was: "and not nodes[node.tag]"...
      nodes[node.tag] = node    -- nodes[node.tag] == node
    end
    return node
  end

tow = function (vv, ww, a, b)
    local diff = ww-vv
    local diffrot90 = v(diff[2], -diff[1])
    return vv + (a or 0.5)*diff + (b or 0)*diffrot90
  end
ats_to_vs = function (str)
    return (str:gsub("@(%w+)", "nodes[\"%1\"]:v()"))
  end
forths["newnode:"] = function ()
    local tag = getword()
    ds:push(storenode({tag=tag, TeX=phantomnode}))
  end
forths["at:"] = function ()
    local node = ds:pick(0)
    local vexpr = getword()
    node:setv(expr(ats_to_vs(vexpr)))
  end





-- «high-level-tests» (to ".high-level-tests")
--[==[
 (eepitch-lua51)
 (eepitch-kill)
 (eepitch-lua51)
require "diagforth"
forths["PP"] = function () PP(getwordasluaexpr()) end
run = dxyrun
run [[ 2Dx     100     +20 ]]
run [[ 2D 100 a,b <=== a   ]]
run [[ 2D      -       -   ]]
run [[ 2D      |  <->  |   ]]
run [[ 2D      v       v   ]]
run [[ 2D +20  c ==> b|->c ]]
PP(xs)
PP(lasty)                 --> 120
= nodes
run [[ (( a,b a c b|->c    ]]
= ds
PP(ds:pick(0))            --> b|->c
PP(ds:pick(1))            --> c
PP(ds:pick(2))            --> a
= depths
PP(depths:metapick(0))
PP(depths:metapick(1))    --> a,b
PP(depths:metapick(2))    --> a
PP(depths:metapick(3))    --> c

run [[    @ 1 @ 0 =>       ]]
print(arrows_to_defdiag("foo"))


 (eepitch-lua51)
 (eepitch-kill)
 (eepitch-lua51)
require "diagforth"
forths["PP"] = function () PP(getwordasluaexpr()) end
run = dxyrun
run [[ node: 110,120 a    ]]
run [[ (( node: 120,130 b ]]
run [[    =>   a b |->    ]]
print(arrows_to_TeX())
run [[    PP ds         ]]
run [[ ))               ]]
run [[ PP ds            ]]
= ds
= depths
print(arrows_to_TeX())
print(arrows_to_defdiag("foo"))
run [[ )) ]]

--]==]



-- «low-level-tests» (to ".low-level-tests")
--[==[
 (eepitch-lua51)
 (eepitch-kill)
 (eepitch-lua51)
require "diagforth"
storenode {TeX="a", tag="a", x=100, y=100}
storenode {TeX="b", tag="b", x=140, y=100}
= nodes







storearrow(DxyArrow {from="a", to="b", shape="|->",
                     slide="5pt", label="up",
                     placement="a"})
storearrow(DxyArrow {from="a", to="b", shape=".>"})
storearrow(DxyPlace {nodes["a"]})
storearrow(DxyLiteral {"literal foobar"})
-- (find-dn6 "diags.lua")
= arrows

print(arrow_to_TeX(arrows[1]))
print(arrows[2]:TeX())
print(arrows[3]:TeX())
print(arrows[4]:TeX())
print(arrows_to_TeX())

--]==]

-- Local Variables:
-- coding:             utf-8-unix
-- End: