-- This file:
--   http://anggtwu.net/LuaTreeLean/LT.lean.pyg.html
--   http://anggtwu.net/LuaTreeLean/LT.lean.html
--   http://anggtwu.net/LuaTreeLean/LT.lean
--          (find-angg "LuaTreeLean/LT.lean")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--    See: https://github.com/edrx/LuaTreeLean
--
-- (defun e () (interactive) (find-angg "LuaTreeLean/LT.lean"))
--
-- Example:
--   #eval toLT      [2, 3]      --> LT.LT.t "[]" [LT.LT.s "2", LT.LT.s "3"]
--   #eval toLuaExpr [2, 3]      --> "{[0]=\"[]\", \"2\", \"3\"}"
--   #eval printTree [2, 3]      --> []__.
--                               --  |   |
--                               --  2   3

import Lean
open Lean Elab
namespace LT


/- Basic operations with strings
-/
open String

def q   s  :=     "\"" ++ s ++ "\""   -- quote
def zq  s  := "[0]=\"" ++ s ++ "\""   -- zero/quote
def br  s  :=      "{" ++ s ++ "}"    -- bracket
def ac  s  :=     ", " ++ s           -- add comma

def acs (strs : List String) : String := join (List.map ac strs)
def zacs (head : String) (strs : List String) : String :=
  br ((zq head) ++ (acs strs))
def zconcat := zacs

#eval zconcat "a" [  "b",   "c"]      --> "{[0]=\"a\", b, c}"
#eval zconcat "a" [q "b", q "c"]      --> "{[0]=\"a\", \"b\", \"c\"}"


/- IO
-- See: (find-angg "luatree/luatree.lua")
-/
def mkfilepath (fname : String) : System.FilePath :=
  System.mkFilePath [fname]
def readfile   (fname : String) : IO String :=
  IO.FS.readFile (mkfilepath fname)
def writefile  (fname content : String) : IO Unit :=
  IO.FS.writeFile (mkfilepath fname) content
def getoutput (cmd : String) (args : Array String) : IO String := do
  let out  IO.Process.output { cmd := cmd, args := args }
  return out.stdout

def luatreescript  := "/home/edrx/luatree/luatree.lua"
def luatreetmpfile := "/tmp/o1.lua"

def luatreerun (luaexpr : String) : IO String := do
  writefile luatreetmpfile luaexpr
  return ( getoutput luatreescript #[luatreetmpfile])
def luatreeprint (luaexpr : String) : IO Unit := do
  IO.println ( luatreerun luaexpr)


/- LT: structure and class
-/
inductive LT where
  | s (s : String) : LT
  | t (h : String) (l : List LT) : LT
  deriving Repr

partial def toLuaExpr0 : LT  String
  | .s s   => q s
  | .t h l => zconcat h (List.map toLuaExpr0 l)

class ToLT (α : Type) where
  toLT      : α  LT
  toLuaExpr : α  String  := fun o => toLuaExpr0 (toLT o)
  printTree : α  IO Unit := fun o => do IO.print ( luatreerun (toLuaExpr o))

export ToLT (toLT toLuaExpr printTree)


/- LT: basic instances
-/
instance : ToLT String     where toLT str := LT.s str
instance : ToLT Int        where toLT n   := LT.s (toString n)
instance : ToLT Nat        where toLT n   := LT.s (toString n)

instance {α} [ToLT α] : ToLT (List α)  where toLT as :=
  (LT.t "[]"  (List.map  toLT as))
instance {α} [ToLT α] : ToLT (Array α) where toLT as :=
  (LT.t "#[]" (Array.map toLT as).toList)


/- High-level tests
-/
#eval toLT      [2, 3]
#eval toLuaExpr [2, 3]
#eval printTree [2, 3]



/- A DSL for tests
-/
namespace DSL

inductive A where
  | n     (n : Nat) : A
  | minus (b c : A) : A
  | pow   (b c : A) : A
  deriving Repr

def paren : A  String
  | .n n       => toString n
  | .minus b c => "(" ++ paren b ++ "-" ++ paren c ++ ")"
  | .pow   b c => "(" ++ paren b ++ "^" ++ paren c ++ ")"

declare_syntax_cat catA

syntax num                      : catA
syntax:50 catA:50 " - " catA:51 : catA
syntax:70 catA:71 " ^ " catA:70 : catA
syntax "[: " catA " :]"         : term

macro_rules | `([: $n:num :]) => `(A.n ($n))
macro_rules | `([: $b:catA - $c:catA :]) => `(A.minus ([: $b :]) ([: $c :]))
macro_rules | `([: $b:catA ^ $c:catA :]) => `(A.pow   ([: $b :]) ([: $c :]))

#check      [: 1 - 2 - 3 - 4 ^ 5 ^ 6 :]
#eval paren [: 1 - 2 - 3 - 4 ^ 5 ^ 6 :]   --> "(((1-2)-3)-(4^(5^6)))"

def toLT_A : A  LT
  | .n n       => LT.s (toString n)
  | .minus b c => LT.t "-" [toLT_A b, toLT_A c]
  | .pow   b c => LT.t "^" [toLT_A b, toLT_A c]

instance : ToLT A   where toLT := toLT_A

#eval toLT      [: 1 - 2 - 3 - 4 ^ 5 ^ 6 :]
#eval printTree [: 1 - 2 - 3 - 4 ^ 5 ^ 6 :]

-- -________.
-- |        |
-- -_____.  ^__.
-- |     |  |  |
-- -__.  3  4  ^__.
-- |  |        |  |
-- 1  2        5  6

end DSL
end LT



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