]> git.lizzy.rs Git - metalua.git/blob - src/compiler/mlp_meta.lua
hygienic macros, take two: H{ }+{ } and -{! }
[metalua.git] / src / compiler / mlp_meta.lua
1 ----------------------------------------------------------------------
2 -- Metalua:  $Id: mlp_meta.lua,v 1.4 2006/11/15 09:07:50 fab13n Exp $
3 --
4 -- Summary: Meta-operations: AST quasi-quoting and splicing
5 --
6 ----------------------------------------------------------------------
7 --
8 -- Copyright (c) 2006, Fabien Fleutot <metalua@gmail.com>.
9 --
10 -- This software is released under the MIT Licence, see licence.txt
11 -- for details.
12 --
13 ----------------------------------------------------------------------
14 -- History:
15 -- $Log: mlp_meta.lua,v $
16 -- Revision 1.4  2006/11/15 09:07:50  fab13n
17 -- debugged meta operators.
18 --
19 -- Revision 1.2  2006/11/09 09:39:57  fab13n
20 -- some cleanup
21 --
22 -- Revision 1.1  2006/11/07 21:29:02  fab13n
23 -- improved quasi-quoting
24 --
25 -- Revision 1.3  2006/11/07 04:38:00  fab13n
26 -- first bootstrapping version.
27 --
28 -- Revision 1.2  2006/11/05 15:08:34  fab13n
29 -- updated code generation, to be compliant with 5.1
30 --
31 ----------------------------------------------------------------------
32
33
34 --------------------------------------------------------------------------------
35 --
36 -- Exported API:
37 -- * [mlp.splice_content()]
38 -- * [mlp.quote_content()]
39 --
40 --------------------------------------------------------------------------------
41
42 --require "compile"
43 --require "ldump"
44
45 module ("mlp", package.seeall)
46
47 --------------------------------------------------------------------------------
48 -- External splicing: compile an AST into a chunk, load and evaluate
49 -- that chunk, and replace the chunk by its result (which must also be
50 -- an AST).
51 --------------------------------------------------------------------------------
52
53 function splice (ast)
54    --printf(" [SPLICE] Ready to compile:\n%s", _G.table.tostring (ast, "nohash", 60))
55    local f = mlc.function_of_ast(ast)
56    --printf " [SPLICE] Splice Compiled."
57    local result = f()   
58    --printf " [SPLICE] Splice Evaled."
59    return result
60 end
61
62 --------------------------------------------------------------------------------
63 -- Going from an AST to an AST representing that AST
64 -- the only key being lifted in this version is ["tag"]
65 --------------------------------------------------------------------------------
66 function quote (t)
67    --print("QUOTING:", _G.table.tostring(t, 60))
68    local cases = { }
69    function cases.table (t)
70       local mt = { tag = "Table" }
71       --_G.table.insert (mt, { tag = "Pair", quote "quote", { tag = "True" } })
72       if t.tag == "Splice" then
73          assert (#t==1, "Invalid splice")
74          local sp = t[1]
75          return sp
76       elseif t.tag then
77          _G.table.insert (mt, { tag = "Pair", quote "tag", quote (t.tag) })
78       end
79       for _, v in ipairs (t) do
80          _G.table.insert (mt, quote(v))
81       end
82       return mt
83    end
84    function cases.number (t) return { tag = "Number", t, quote = true } end
85    function cases.string (t) return { tag = "String", t, quote = true } end
86    return cases [ type (t) ] (t)
87 end
88
89 --------------------------------------------------------------------------------
90 -- when this variable is false, code inside [-{...}] is compiled and
91 -- avaluated immediately. When it's true (supposedly when we're
92 -- parsing data inside a quasiquote), [-{foo}] is replaced by
93 -- [`Splice{foo}], which will be unpacked by [quote()].
94 --------------------------------------------------------------------------------
95 in_a_quote = false
96
97 --------------------------------------------------------------------------------
98 -- Parse the inside of a "-{ ... }"
99 --------------------------------------------------------------------------------
100 function splice_content (lx)
101    local parser_name = "expr"
102    if lx:is_keyword (lx:peek(2), ":") then
103       local a = lx:next()
104       lx:next() -- skip ":"
105       assert (a.tag=="Id", "Invalid splice parser name")
106       parser_name = a[1]
107 --       printf("this splice is a %s", parser_name)
108 --    else
109 --       printf("no splice specifier:\npeek(1)")
110 --       _G.table.print(lx:peek(1))
111 --       printf("peek(2)")
112 --       _G.table.print(lx:peek(2))
113    end
114    local ast = mlp[parser_name](lx)
115    if in_a_quote then
116       --printf("SPLICE_IN_QUOTE:\n%s", _G.table.tostring(ast, "nohash", 60))
117       return { tag="Splice", ast }
118    else
119       if parser_name == "expr" then ast = { { tag="Return", ast } }
120       elseif parser_name == "stat"  then ast = { ast }
121       elseif parser_name ~= "block" then
122          error ("splice content must be an expr, stat or block") end
123       --printf("EXEC THIS SPLICE:\n%s", _G.table.tostring(ast, "nohash", 60))
124       return splice (ast)
125    end
126 end
127
128 --------------------------------------------------------------------------------
129 -- Parse the inside of a "+{ ... }"
130 --------------------------------------------------------------------------------
131 function quote_content (lx)
132    local parser 
133    if lx:is_keyword (lx:peek(1), ":") then -- +{:parser: content }
134       lx:next()
135       errory "NOT IMPLEMENTED"
136    elseif lx:is_keyword (lx:peek(2), ":") then -- +{parser: content }
137       parser = mlp[id(lx)[1]]
138       lx:next()
139    else -- +{ content }
140       parser = mlp.expr
141    end
142
143    --assert(not in_a_quote, "Nested quotes not handled yet")
144    local prev_iq = in_a_quote
145    in_a_quote = true
146    --print("IN_A_QUOTE")
147    local content = parser (lx)
148    local q_content = quote (content)
149 --     printf("/IN_A_QUOTE:\n* content=\n%s\n* q_content=\n%s\n",
150 --            _G.table.tostring(content, "nohash", 60),
151 --            _G.table.tostring(q_content, "nohash", 60))
152    in_a_quote = prev_iq
153    return q_content
154 end
155