initial stage...
[yu.git] / yu / codegen.lua
blob0f4c2e2c72cc1dc157b63cdc57c368085aa8c224
1 require "lpeg"
2 require "yu.resolver"
3 module("yu",package.seeall)
5 local gen={}
7 local getOpPrecedence=getOpPrecedence
8 local getDeclName=getDeclName
9 local getConst=getConst
11 local function codegen(m)
12 -- print('gen...'..m.tag)
13 local t=m.tag
14 local g=gen[t]
15 if g then
16 return g(m) or ''
17 else
18 error("generator not defined for:"..t)
19 end
20 end
22 local function codegenList(l)
23 local s=''
24 if l then
25 for i,t in ipairs(l) do
26 if i>1 then
27 s=s..','
28 end
29 s=s..codegen(t)
30 end
31 end
32 return s
33 end
35 local function codegenEntry(m)
36 return codegen(m)
37 end
39 local function wrapp(s)
40 return '('..s..')'
41 end
43 function gen.module(m)
44 local b=codegen(m.block)
45 return b
46 end
48 function gen.block(b)
49 local c=''
50 for i,s in ipairs(b) do
51 local v=codegen(s)
52 if v~='' then
53 c=c..v..'\n'
54 end
55 end
56 return c
57 end
59 -----------------------------CONTROL
60 function gen.import(im)
61 --currentModule.import
62 end
64 function gen.private()
65 end
67 function gen.public()
68 end
70 function gen.rawlua(r)
71 return r.src
72 end
75 --------------------TYPE
76 function gen.ttype(t)
77 --TODO:!!!!!!!!!!
78 end
80 function gen.type(t)
81 if isBuiltinType(t.name) then return true end
82 local d=findSymbol(t.name,t)
83 if not d then return resolveErr("symbol not found:'"..t.id.."'",t ) end
84 t.decl=d
85 return true
86 end
88 function gen.tabletype(t)
89 --TODO:!!!!
91 end
93 function gen.functype(ft)
94 -- if ft.args then resolveEach(ft.args) end
95 -- if ft.rettype then resolveEach(ft.rettype) end
96 -- return true
97 end
100 --#STATEMENTS
101 --#FLOW
102 function gen.dostmt(d)
103 return ' do '..codegen(d.block)..' end '
106 function gen.ifstmt(s)
107 local body=' if '..codegen(s.cond)..' then '..codegen(s.body.thenbody)
108 if s.body.elsebody then
109 body=body..' else '..codegen(s.body.elsebody)
111 return body..' end '
114 function gen.switchstmt(s)
115 --todo
116 local head='do local __SWITCH='..codegen(s.cond)
117 local body=''
118 for i, c in ipairs(s.cases) do
119 body=body..(i>1 and ' elseif ' or ' if ')
120 for j, cc in ipairs(c.conds) do
121 if j>1 then body=body..' or ' end
122 body=body..'__SWITCH=='..codegen(cc)
124 body=body..' then '..codegen(c.block)
126 if s.default then
127 if body~='' then body=body..' else ' end
128 body=body..codegen(s.default)
130 return head..body..' end end'
133 function gen.case(c)
134 --todo
137 function gen.returnstmt(r)
138 return 'return '..codegenList(r.values)
141 function gen.yieldstmt(y)
142 return '__YUYIELD('..codegenList(r.values)..')'
145 function gen.forstmt(f)
146 --todo
147 local head='for '..codegen(f.var)..'='..codegenList(f.range)..' do '
148 return head..codegen(f.block)..' end'
151 function gen.foreachstmt(f)
152 --todo
156 function gen.whilestmt(s)
157 local out=' while '..codegen(s.cond)..' do '
159 if s.hasContinue then
160 out=out..'local __dobreak=true '
161 out=out..'repeat '
164 out=out..codegen(s.block)
166 if s.hasContinue then
167 if s.hasBreak then
168 out=out..'__dobreak=false until false '
169 out=out..'if __dobreak then break end'
170 else
171 out=out..'until true'
175 out=out..' end '
176 return out
179 function gen.continuestmt(c)
180 return ' __dobreak=false break '
183 function gen.breakstmt(b)
184 return ' break '
187 function gen.trystmt(t)
188 --todo:!!!!!!!!!!!!
191 function gen.throwstmt(t)
192 --todo:!!!!!!!!!!!!!!
193 return ' __YUTHROW('..codegenList(t.values)..') '
196 function gen.catch(c)
197 --todo:..............
200 function gen.assignstmt(a)
201 return codegenList(a.vars)..' = '..codegenList(a.values)
204 function gen.assopstmt(a)
205 --todo:!!!!!!!!
206 end
208 function gen.batchassign(a)
209 --todo:!!!!!!!
213 function gen.exprstmt(e)
214 return codegen(e.expr)
218 --#VARIABLES
220 function gen.vardecl(vd)
221 local vtype=vd.vtype
222 if vtype=='const' then
223 --no code generation for const
224 return ''
226 local out=''
227 if vtype=='local' then
228 local v=codegenList(vd.vars)
229 out=out..'local '..v
230 if vd.values then
231 out=out..'='..codegenList(vd.values)
233 elseif vtype=='global' then
234 if vd.values then
235 out=codegenList(vd.vars)..'='..codegenList(vd.values)
237 elseif vtype=='field' then
240 --TODO:global/fields
241 return out
244 --#DECLARATION
245 function gen.tvar(v)
246 --todo:!!!!!!
250 function gen.var(v)
251 local vtype=v.vtype
252 if vtype=='local' then
253 return v.name
254 elseif vtype=='global' then --TODO:get full spaced name
255 return v.fullname
256 elseif vtype=='field' then
257 return v.name
262 function gen.arg(a)
263 if a.vararg then return '...' end
264 return a.name
267 function gen.enumdecl(e)
268 -- --todo:assign default const value
269 -- resolveEach(e.items)
272 function gen.enumitem(e)
273 -- if e.value then resolve(e.value) end
274 -- --todo:typecheck
277 function gen.classdecl(c)
278 --TODO:!!!!!!!!!!!!!!!!!
279 local o=''
280 for i,s in ipairs(c.decls) do
281 local v=codegen(s)
282 if v~='' then
283 o=o..v..'\n'
286 return o
290 function gen.funcdecl(f)
291 --TODO:!!!!!!!!!!!!!!!
292 if f.extern then return nil end
294 local out='function '..getDeclName(f)
295 out=out..'('
296 if f.type.args then out=out..codegenList(f.type.args) end
297 out=out..')\n'
298 out=out..codegen(f.block)
299 return out..'end'
302 function gen.methoddecl(m)
303 -- if m.extern then return nil end
304 return gen.funcdecl(m)
305 --TODO:!!!!!!!!!!!!!!!1
308 function gen.exprbody(e)
309 return ' return '..codegen(e.expr)..' '
312 --#EXPRESSION
314 -------CONST
315 gen["nil"]=function(n)
316 return 'nil'
319 function gen.number(n)
320 return n.v --raw
323 function gen.string(n)
324 --todo: escape?
325 return string.format('%q',yu.unescape(n.v))
326 -- return '"'..n.v..'"'
329 function gen.boolean(b)
330 return b.v
335 function gen.varacc(v)
336 local d=v.decl
337 return yu.getDeclName(d)
340 function gen.call(c)
341 -- local l=codegen(c.l)
342 --todo:arguments
343 if c.l.tag=='closure' then
344 return wrapp(codegen(c.l))..wrapp(codegenList(c.args))
345 else
346 return codegen(c.l)..wrapp(codegenList(c.args))
350 function gen.spawn(s)
351 --TODO:!!!!!!!
354 function gen.new(n)
355 --TODO:!!!!!!!!!!
358 function gen.binop(b)
360 local outl=codegen(b.l)
361 local outr=codegen(b.r)
363 local p=getOpPrecedence(b.op)
364 if b.l.tag=='binop' and getOpPrecedence(b.l.op)<p then
365 outl=wrapp(outl)
368 if b.r.tag=='binop' and getOpPrecedence(b.r.op)<p then
369 outr=wrapp(outr)
371 return outl..' '..b.op..' '..outr
372 --TODO:operator override
375 function gen.unop(u)
376 return ' '..u.op..' '..wrapp(codegen(u.l))
377 --TODO:operator override
380 function gen.ternary(t)
381 return wrapp(codegen(t.l)..' and '..codegen(t.vtrue)..' or '..codegen(t.vfalse))
382 end
384 function gen.member(m)
385 --TODO:!!!
386 local c=getConstNode(m)
387 if c then return codegen(c) end
388 return codegen(m.l)..'.'..m.id
391 function gen.index(i)
392 --TODO:!!!!
393 return codegen(i.l)..'['..codegen(i.key)..']'
396 function gen.table(t)
397 --TODO:!!!!
400 function gen.item(i)
401 --TODO:!!!!
404 function gen.seq(t)
405 --TODO:!!!!
408 function gen.cast(a)
409 --TODO:!!!! add runtime typecheck
410 return codegen(a.l)
413 function gen.is(i)
414 --TODO:!!!!
417 function gen.closure(c)
418 --TODO:!!!!
419 local out='function '
420 out=out..'('
421 if c.type.args then out=out..codegenList(c.type.args) end
422 out=out..')\n'
423 out=out..codegen(c.block)
424 return out..'end'
427 function gen.self(s)
428 return 'self'
431 function gen.super(s)
432 --TODO:!!!!
433 return 'self'
437 --------------------EXTERN
438 function gen.extern(e)
439 --TODO:!!!!
440 local c=''
441 for i,s in ipairs(e.decls) do
442 local v=codegen(s)
443 if v~='' then
444 c=c..v..'\n'
447 return c
450 function gen.externfunc(f)
451 --TODO:!!!!
454 function gen.externclass(c)
455 --TODO:!!!!
458 function gen.externmethod(m)
459 --TODO:!!!!
464 _M.codegen=codegenEntry