3 module("yu",package
.seeall
)
7 local getOpPrecedence
=getOpPrecedence
8 local getDeclName
=getDeclName
9 local getConst
=getConst
11 local function codegen(m
)
12 -- print('gen...'..m.tag)
18 error("generator not defined for:"..t
)
22 local function codegenList(l
)
25 for i
,t
in ipairs(l
) do
35 local function codegenEntry(m
)
39 local function wrapp(s
)
43 function gen
.module(m
)
44 local b
=codegen(m
.block
)
50 for i
,s
in ipairs(b
) do
59 -----------------------------CONTROL
60 function gen
.import(im
)
61 --currentModule.import
64 function gen
.private()
70 function gen
.rawlua(r
)
75 --------------------TYPE
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
88 function gen
.tabletype(t
)
93 function gen
.functype(ft
)
94 -- if ft.args then resolveEach(ft.args) end
95 -- if ft.rettype then resolveEach(ft.rettype) end
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
)
114 function gen
.switchstmt(s
)
116 local head
='do local __SWITCH='..codegen(s
.cond
)
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
)
127 if body
~='' then body
=body
..' else ' end
128 body
=body
..codegen(s
.default
)
130 return head
..body
..' end end'
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
)
147 local head
='for '..codegen(f
.var
)..'='..codegenList(f
.range
)..' do '
148 return head
..codegen(f
.block
)..' end'
151 function gen
.foreachstmt(f
)
156 function gen
.whilestmt(s
)
157 local out
=' while '..codegen(s
.cond
)..' do '
159 if s
.hasContinue
then
160 out
=out
..'local __dobreak=true '
164 out
=out
..codegen(s
.block
)
166 if s
.hasContinue
then
168 out
=out
..'__dobreak=false until false '
169 out
=out
..'if __dobreak then break end'
171 out
=out
..'until true'
179 function gen
.continuestmt(c
)
180 return ' __dobreak=false break '
183 function gen
.breakstmt(b
)
187 function gen
.trystmt(t
)
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
)
208 function gen
.batchassign(a
)
213 function gen
.exprstmt(e
)
214 return codegen(e
.expr
)
220 function gen
.vardecl(vd
)
222 if vtype
=='const' then
223 --no code generation for const
227 if vtype
=='local' then
228 local v
=codegenList(vd
.vars
)
231 out
=out
..'='..codegenList(vd
.values
)
233 elseif vtype
=='global' then
235 out
=codegenList(vd
.vars
)..'='..codegenList(vd
.values
)
237 elseif vtype
=='field' then
252 if vtype
=='local' then
254 elseif vtype
=='global' then --TODO:get full spaced name
256 elseif vtype
=='field' then
263 if a
.vararg
then return '...' end
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
277 function gen
.classdecl(c
)
278 --TODO:!!!!!!!!!!!!!!!!!
280 for i
,s
in ipairs(c
.decls
) do
290 function gen
.funcdecl(f
)
291 --TODO:!!!!!!!!!!!!!!!
292 if f
.extern
then return nil end
294 local out
='function '..getDeclName(f
)
296 if f
.type.args
then out
=out
..codegenList(f
.type.args
) end
298 out
=out
..codegen(f
.block
)
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
)..' '
315 gen
["nil"]=function(n
)
319 function gen
.number(n
)
323 function gen
.string(n
)
325 return string.format('%q',yu
.unescape(n
.v
))
326 -- return '"'..n.v..'"'
329 function gen
.boolean(b
)
335 function gen
.varacc(v
)
337 return yu
.getDeclName(d
)
341 -- local l=codegen(c.l)
343 if c
.l
.tag=='closure' then
344 return wrapp(codegen(c
.l
))..wrapp(codegenList(c
.args
))
346 return codegen(c
.l
)..wrapp(codegenList(c
.args
))
350 function gen
.spawn(s
)
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
368 if b
.r
.tag=='binop' and getOpPrecedence(b
.r
.op
)<p
then
371 return outl
..' '..b
.op
..' '..outr
372 --TODO:operator override
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
))
384 function gen
.member(m
)
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
)
393 return codegen(i
.l
)..'['..codegen(i
.key
)..']'
396 function gen
.table(t
)
409 --TODO:!!!! add runtime typecheck
417 function gen
.closure(c
)
419 local out
='function '
421 if c
.type.args
then out
=out
..codegenList(c
.type.args
) end
423 out
=out
..codegen(c
.block
)
431 function gen
.super(s
)
437 --------------------EXTERN
438 function gen
.extern(e
)
441 for i
,s
in ipairs(e
.decls
) do
450 function gen
.externfunc(f
)
454 function gen
.externclass(c
)
458 function gen
.externmethod(m
)
464 _M
.codegen
=codegenEntry