1 ----------------------------------------------------------------------
2 -- Metalua: $Id: mlp_meta.lua,v 1.4 2006/11/15 09:07:50 fab13n Exp $
4 -- Summary: Meta-operations: AST quasi-quoting and splicing
6 ----------------------------------------------------------------------
8 -- Copyright (c) 2006, Fabien Fleutot <metalua@gmail.com>.
10 -- This software is released under the MIT Licence, see licence.txt
13 ----------------------------------------------------------------------
15 -- $Log: mlp_meta.lua,v $
16 -- Revision 1.4 2006/11/15 09:07:50 fab13n
17 -- debugged meta operators.
19 -- Revision 1.2 2006/11/09 09:39:57 fab13n
22 -- Revision 1.1 2006/11/07 21:29:02 fab13n
23 -- improved quasi-quoting
25 -- Revision 1.3 2006/11/07 04:38:00 fab13n
26 -- first bootstrapping version.
28 -- Revision 1.2 2006/11/05 15:08:34 fab13n
29 -- updated code generation, to be compliant with 5.1
31 ----------------------------------------------------------------------
34 --------------------------------------------------------------------------------
37 -- * [mlp.splice_content()]
38 -- * [mlp.quote_content()]
40 --------------------------------------------------------------------------------
45 module ("mlp", package.seeall)
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
51 --------------------------------------------------------------------------------
54 --printf(" [SPLICE] Ready to compile:\n%s", _G.table.tostring (ast, "nohash", 60))
55 local f = mlc.function_of_ast(ast, '=splice')
56 --printf " [SPLICE] Splice Compiled."
57 --local status, result = pcall(f)
58 --printf " [SPLICE] Splice Evaled."
59 --if not status then print 'ERROR IN SPLICE' end
64 --------------------------------------------------------------------------------
65 -- Going from an AST to an AST representing that AST
66 -- the only key being lifted in this version is ["tag"]
67 --------------------------------------------------------------------------------
69 --print("QUOTING:", _G.table.tostring(t, 60))
71 function cases.table (t)
72 local mt = { tag = "Table" }
73 --_G.table.insert (mt, { tag = "Pair", quote "quote", { tag = "True" } })
74 if t.tag == "Splice" then
75 assert (#t==1, "Invalid splice")
79 _G.table.insert (mt, { tag = "Pair", quote "tag", quote (t.tag) })
81 for _, v in ipairs (t) do
82 _G.table.insert (mt, quote(v))
86 function cases.number (t) return { tag = "Number", t, quote = true } end
87 function cases.string (t) return { tag = "String", t, quote = true } end
88 return cases [ type (t) ] (t)
91 --------------------------------------------------------------------------------
92 -- when this variable is false, code inside [-{...}] is compiled and
93 -- avaluated immediately. When it's true (supposedly when we're
94 -- parsing data inside a quasiquote), [-{foo}] is replaced by
95 -- [`Splice{foo}], which will be unpacked by [quote()].
96 --------------------------------------------------------------------------------
99 --------------------------------------------------------------------------------
100 -- Parse the inside of a "-{ ... }"
101 --------------------------------------------------------------------------------
102 function splice_content (lx)
103 local parser_name = "expr"
104 if lx:is_keyword (lx:peek(2), ":") then
106 lx:next() -- skip ":"
107 assert (a.tag=="Id", "Invalid splice parser name")
109 -- printf("this splice is a %s", parser_name)
111 -- printf("no splice specifier:\npeek(1)")
112 -- _G.table.print(lx:peek(1))
114 -- _G.table.print(lx:peek(2))
116 local ast = mlp[parser_name](lx)
118 --printf("SPLICE_IN_QUOTE:\n%s", _G.table.tostring(ast, "nohash", 60))
119 return { tag="Splice", ast }
121 if parser_name == "expr" then ast = { { tag="Return", ast } }
122 elseif parser_name == "stat" then ast = { ast }
123 elseif parser_name ~= "block" then
124 error ("splice content must be an expr, stat or block") end
125 --printf("EXEC THIS SPLICE:\n%s", _G.table.tostring(ast, "nohash", 60))
130 --------------------------------------------------------------------------------
131 -- Parse the inside of a "+{ ... }"
132 --------------------------------------------------------------------------------
133 function quote_content (lx)
135 if lx:is_keyword (lx:peek(1), ":") then -- +{:parser: content }
137 errory "NOT IMPLEMENTED"
138 elseif lx:is_keyword (lx:peek(2), ":") then -- +{parser: content }
139 parser = mlp[id(lx)[1]]
145 --assert(not in_a_quote, "Nested quotes not handled yet")
146 local prev_iq = in_a_quote
148 --print("IN_A_QUOTE")
149 local content = parser (lx)
150 local q_content = quote (content)
151 -- printf("/IN_A_QUOTE:\n* content=\n%s\n* q_content=\n%s\n",
152 -- _G.table.tostring(content, "nohash", 60),
153 -- _G.table.tostring(q_content, "nohash", 60))