Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/Match1.lua.html
--   http://anggtwu.net/LUA/Match1.lua
--          (find-angg "LUA/Match1.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- This will be the basis of a pattern-matcher based on Haskell, OCaml
-- and pcase... but it's incomplete.
--
-- (find-elnode "Pattern-Matching Conditional")
--
-- (defun e () (interactive) (find-angg "LUA/Match1.lua"))

-- «.basic»		(to "basic")
-- «.basic-tests»	(to "basic-tests")
-- «.matcherfor»	(to "matcherfor")
-- «.matcherfor-tests»	(to "matcherfor-tests")
-- «.MatchRep»		(to "MatchRep")
-- «.MatchRep-tests»	(to "MatchRep-tests")

require "Indent2"  -- (find-angg "LUA/Indent2.lua")


-- «basic»  (to ".basic")
Pict.__index["do+3"] = "do<i:ind(3);o=' '>"
Pict.__index["end"]  = "<i:pop();o='\\n'>end"
Pict.__index.doend   = function (p) return p:wrap0("do+3", "end") end
Pict.__index.testsub = function (p, field)
    return Pict { format("local subj = subj[%s]", mytostring(field)), p }:doend()
  end

Pict.isast2  = function (o0,n)
    return Pict { "if otype(subj) ~= 'AST' then return false end",
           format("if subj[0]     ~= %q then return false end", o0),
           format("if #subj       ~= %d then return false end", n) }
  end
Pict.saveinto = function (to,from)
    if not from then
      return Pict { format("saved[%s] = subj", mytostring(to)) }
    end
    return Pict { format("saved[%s] = subj[%s]", mytostring(to), mytostring(from)) }
  end
Pict.testsub = function (field, ...)
    return Pict({...}):testsub(field)
  end
Pict.matcher = function (...)
    return Pict { "local subj = ...",
                  "local saved = VTable {}",
                  Pict {...},
                  "return saved" }
  end


-- «basic-tests»  (to ".basic-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Match1.lua"

o = mkast("*", "x", mkast("+", "y", "z"))
= o

= Pict.isast2('"', 2)
= Pict.saveinto("a")
= Pict.saveinto("a", 1)
= Pict                  {"foo", "bar"} :testsub(1)
= Pict.testsub(1,        "foo", "bar")
= Pict.testsub("field",  "foo", "bar")
= Pict.testsub("field", {"foo", "bar"})

p1 = Pict { Pict.isast2('*', 2),
            Pict.saveinto("a", 1),
            Pict.testsub(2,
              Pict.isast2('+', 2),
              Pict.saveinto("b", 1),
              Pict.saveinto("c", 2)
            ),
          }
= p1

= Pict { Pict.isast2('*', 2),
         Pict.testsub(1, Pict.saveinto("a")),
         Pict.testsub(2, Pict.saveinto("b")),
       }
= Pict.matcher(
         Pict.isast2('*', 2),
         Pict.testsub(1, Pict.saveinto("a")),
         Pict.testsub(2, Pict.saveinto("b"))
       )

--]]

-- «matcherfor»  (to ".matcherfor")

matcherfor_ = function (o)
    if type(o) == "string" and o:match"^_"
    then return Pict.saveinto(o:sub(2))
    end
  end
matcherforAST = function (o)
    if otype(o) == "AST" then
      local p = Pict { Pict.isast2(o[0], #o) }
      for i=1,#o do
        table.insert(p, Pict.testsub(i, matcherfor(o[i])))
      end
      return p
    end
  end
matcherfor = function (o)
    return matcherfor_(o)
        or matcherforAST(o)
        or error("BANG!")
  end

add = function (...) return mkast("+", ...) end
mul = function (...) return mkast("*", ...) end

-- «matcherfor-tests»  (to ".matcherfor-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Match1.lua"
=              matcherfor     "_a"
=              matcherfor(          add("_b", "_c"))
=              matcherfor(          add("_b", "_c", "_d"))
=              matcherfor(mul("_a", add("_b", "_c", "_d")))
= Pict.matcher(matcherfor(mul("_a", add("_b", "_c", "_d"))))
abc = mul("_a", add("_b", "_c"))

--]]



--  __  __       _       _     ____            
-- |  \/  | __ _| |_ ___| |__ |  _ \ ___ _ __  
-- | |\/| |/ _` | __/ __| '_ \| |_) / _ \ '_ \ 
-- | |  | | (_| | || (__| | | |  _ <  __/ |_) |
-- |_|  |_|\__,_|\__\___|_| |_|_| \_\___| .__/ 
--                                      |_|    
-- «MatchRep»  (to ".MatchRep")

MatchRep = Class {
  type    = "MatchRep",
  __index = {
    code1_  = function (mr) return Pict.matcher(matcherfor(expr(mr[1]))) end,
    code1   = function (mr) return Code.eval(tostring(mr:code1_())) end,
    coden   = function (mr,n) return Code.ve("_ => "..mr[n]) end,
    match_  = function (mr,o) return mr:code1()(o) end,
    match_n = function (mr,o,n) return mr:coden(n)(mr:match_(o)) end,
  },
}

-- «MatchRep-tests»  (to ".MatchRep-tests")

mr = MatchRep {
  'mul("_a", add("_b", "_c"))',
  'add(mul(_.a, _.b), mul(_.a, _.c))',
}

--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Match1.lua"
= mr[1]
= expr(mr[1])
= matcherfor(expr(mr[1]))
= Pict.matcher(matcherfor(expr(mr[1])))

= mr:code1_()
= mr:code1 ()

  o = mul(2, add(3, 4))
= o
= mr:match_ (o)
= mr:match_n(o, 2)

--]==]





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