5 module("yu",package
.seeall
)
8 local getType
,getTypeDecl
,newTypeRef
,checkType
=getType
,getTypeDecl
,newTypeRef
,checkType
9 local getExprTypeList
=getExprTypeList
16 local function _findExternSymbol(entryModule
,name
,found
)
18 local externModules
=entryModule
.externModules
21 for p
,m
in pairs(externModules
) do
22 if m
.__seq
~=__searchSeq
then
24 local decl
=m
.scope
[name
]
25 if decl
and not decl
.private
then
26 found
[#found
+1]={module
=m
,decl
=decl
}
28 _findExternSymbol(m
,name
,found
)
36 local function _findSymbol(vi
,name
,token
,limit
)
37 local t
=vi
.nodeStack
.stack
38 local outClas
,outFunc
,outMethod
=0,0,0
42 local scope
=node
.scope
46 if tag=='clasdecl' then outClas
=outClas
+1 end
47 if tag=='funcdecl' then outFunc
=outFunc
+1 end
48 if tag=='methoddecl' then outMethod
=outMethod
+1 end
51 if tag=='classdecl' then
55 if decl
then break end
63 -- print('found:',scope,decl.name,node.tag,decl.p0,token.p0)
65 (limit
=='global' and isMemberDecl(decl
))
68 if dtag
=='var' then --variable?
69 if decl
.vtype
=='local' then --local?
70 if not ((outFunc
>0 and limit
~='upvalue') or decl
.p0
>token
.p0
) then return decl
end
71 elseif decl
.vtype
=='field' then
72 if outMethod
==1 then return decl
end
76 elseif dtag
=='methoddecl' then
77 if outMethod
==1 then return decl
end
83 decl
.tag=='var' and decl
.vtype
=='local'
84 and (decl
.p0
>token
.p0
or outFunc
)
95 --search extern modules
96 __searchSeq
=__searchSeq
+1
98 if not token
.module
then
102 local found
=_findExternSymbol(token
.module
,name
)
105 local foundCount
=#found
107 msg
='multiple declaration found:'..name
..'\n'
108 for i
,f
in pairs(found
) do
109 msg
=msg
..getTokenPosString(f
.decl
)..'\n'
111 return vi
:err(msg
,token
)
113 elseif foundCount
==1 then
120 function newResolver()
124 findSymbol
=_findSymbol
126 return yu
.newVisitor(r
)
130 ----------------TOPLEVEL
132 -- print('resoving..',n.tag)
133 local state
=n
.resolveState
134 if state
=='done' then
136 elseif state
=='resolving' then
137 self
:err('cyclic delcaration dependecy',n
)
140 n
.resolveState
='resolving'
142 local b
=self
.currentBlock
143 if b
and b
.endState
then
144 self
:err('unreachable statement',n
)
150 n
.resolveState
='done'
153 function pre
:module(m
)
157 function post
:module(m
)
160 -- function pre:block(b)
164 -- function post:block(b)
168 ---------------Directive
169 -- function post:import(im)
174 -- function post:private()
178 -- function post:public()
182 function post
:rawlua(r
)
183 local f
,err
=loadstring(r
.src
)
185 self
:err('error in Lua code:'..err
,r
)
189 ------------------------------CONTROL
190 function post
:exprstmt(e
)
192 if not is(expr
.tag,'new','call') then
193 self
:err("call/new/statement expected, given "..expr
.tag,e
)
198 function post
:continuestmt(c
)
199 local l
=self
:findParentLoop()
201 self
:err("'continue' must be inside loop block",c
)
204 self
.currentBlock
.endState
=true
208 function post
:breakstmt(b
)
209 local l
=self
:findParentLoop()
211 self
:err("'break' must be inside loop block",b
)
214 self
.currentBlock
.endState
=true
218 function post
:returnstmt(r
)
219 local f
=self
:findParentFunc()
221 self
:err("'return'/'yield' should be inside function",r
)
223 self
.currentBlock
.endState
=true
224 local rettype
=getTypeDecl(f
.type.rettype
)
227 if rettype
==voidType
then
228 if not (#r
.values
==1 and getType(r
.values
[1])==voidType
) then
229 self
:err('function should return no value',r
)
231 elseif rettype
.tag=='mulrettype' then
233 --TODO!!!!!!!!!!!!!!!!!
237 self
:err('unexpected return value',r
.values
[2])
239 local rt
=getType(r
.values
[1])
240 if not checkType(rettype
,'>=',rt
) then
241 self
:err('return type mismatch:'..rettype
.name
..'<-'..rt
.name
,r
.values
[1])
244 elseif rettype
~=voidType
then
245 self
:err('return value expected',r
)
251 function post
:yieldstmt(y
,p
)
252 return post
.returnstmt(self
,y
,p
)
255 -- function post:dostmt(d)
259 function post
:ifstmt(s
)
260 s
.cond
=convertToBool(s
.cond
)
261 self
:visitNode(s
.cond
)
265 function post
:switchstmt(s
)
266 local condtype
=getType(s
.cond
)
268 for i
,c
in ipairs(s
.cases
) do
269 for i
,v
in ipairs(c
.conds
) do
270 if not checkType(condtype
,'>=',getType(v
)) then
271 self
:err('case expression type mismatch',v
)
279 -- function post:case(c)
284 function post
:forstmt(f
)
285 local tt
,mulret
=getExprTypeList(f
.range
)
286 for i
,t
in ipairs(tt
) do
287 if t
~=numberType
then
288 self
:err('for-loop range must be number type, given:'..t
.name
,f
)
293 function post
:foreachstmt(f
)
295 --todo:typecheck vars type <=iterator return type
298 function post
:whilestmt(s
)
299 s
.cond
=convertToBool(s
.cond
)
300 self
:visitNode(s
.cond
)
304 -- function post:trystmt(t)
308 -- function post:throwstmt(t)
312 function post
:catch(c
)
317 -----------------#ASSIGNSTMT
318 local function isAssignable(var
)
323 if tag=='varacc' or tag=='member' then
328 return decl
.vtype
~='const'
331 elseif tag=='index' then
338 function post
:assignstmt(a
)
340 local vars
,values
=a
.vars
,a
.values
342 for i
,var
in ipairs(vars
) do
343 if not isAssignable(var
) then
344 self
:err('non-assignable symbol:'..var
.id
)
348 --todo: different variable type(member/index/indexoverride)
350 --todo typecheck for value/var
351 local valtypes
,mulretcount
=getExprTypeList(values
)
352 local valcount
,varcount
=#valtypes
,#vars
354 if valcount
<varcount
or (valcount
-mulretcount
+(mulretcount
>0 and 1 or 0))>varcount
then
355 self
:err('variable/value count mismatch:'..varcount
..'<-'..valcount
)
358 for i
,var
in ipairs(vars
) do
360 local vart
=getType(var
)
362 if not checkType(vart
,'>=',vt
) then
363 self
:err('variable/value type mismatch:'..vart
.name
..'<-'..vt
.name
)
370 function post
:assopstmt(a
)
371 --todo: check is isAssignable
372 --todo: different variable type(member/index/indexoverride)
373 -- pendTypeCheck('==',a.var,a.value)
378 function post
:batchassign(a
)
379 --todo: replace batch with assigns?
380 --todo: check is isAssignable
381 --todo: different variable type(member/index/indexoverride)
382 --todo typecheck for value/var
384 -- return 'replace',{
386 -- block={tag='block',
387 -- {tag='vardecl', vars={
394 -----------------#DECLARATION
395 -- function pre:vardecl(vd)
400 function post
:tvar(v
)
401 --todo:!!!!!!!!!!!!!!!!!!!
406 if v
.vtype
=='const' and not v
.value
then
407 self
:err('const variable has no value:'..v
.name
,v
)
412 self
:err('unresolved type',v
)
418 if not checkType(v
.type,'>=',getType(v
.value
)) then
419 self
:err('type mismatch',v
)
431 function post
:enumdecl(e
)
433 for i
,item
in ipairs(e
.items
) do
435 if ii
[iv
] then self
:err('duplicated enum item value',item
) end
441 function post
:enumitem(i
,e
)
444 local v
=getConstNode(i
.value
)
446 if not v
or getType(v
).tag~='numbertype' then
447 self
:err('enum item must be constant number')
451 local cv
=e
.currentValue
453 cv
=makeNumberConst(1)
455 cv
=makeNumberConst(tonumber(cv
.v
)+1)
463 local function checkConst(n
)
465 if is(tag,'number','nil','boolean','string') then return true
466 elseif tag=='var' and n
.vtype
=='const' then return true
467 elseif tag=='varacc' or tag=='member' then
468 if checkConst(n
.decl
) then return true end
469 elseif tag=='binop' then
470 if checkConst(n
.l
) and checkConst(n
.r
) then return true end
471 elseif tag=='unop' then
472 return checkConst(n
.l
)
477 function pre
:classdecl(c
)
478 local supername
=c
.supername
480 local s
=self
:findSymbol(supername
.id
,c
)
481 --todo check template
483 self
:err('symbol not found:'..supername
.id
,c
)
485 if s
.tag~='classdecl' then self
:err(supername
.id
..'is not a class',c
) end
488 c
.resolveState
='done'
491 function post
:classdecl(c
)
495 function pre
:methoddecl(m
,parent
)
496 return pre
.funcdecl(self
,m
,parent
)
499 function post
:methoddecl(m
,parent
)
500 if m
.extern
then return end
502 assert(m
.block
or m
.abstract
,'abstract?'..m
.name
)
504 local c
=parent
.superclass
507 local m
=c
.scope
[m
.name
]
509 if m
.tag=='methoddecl' then superMethod
=m
end
515 if not superMethod
then
516 self
:err('cannot find method to inherit:'..m
.name
,m
)
519 return post
.funcdecl(self
,m
)
522 function pre
:funcdecl(f
)
523 if f
.extern
then return end
524 if f
.block
.tag=='exprbody' and f
.type.rettype
==voidType
then
525 local expr
=f
.block
.expr
526 f
.type.rettype
=newTypeRef(expr
)
528 f
.resolveState
='done'
531 function post
:funcdecl(f
)
532 if f
.extern
then return end
534 local rettype
=f
.type.rettype
535 if not f
.hasReturn
and rettype
.tag~='voidtype' then
536 self
:err('return statement not found in function block',f
)
541 function post
:exprbody(e
)
542 self
:findParentFunc().hasReturn
=true
546 ----------------------EXPRESSION
547 function post
:varacc(v
)
548 local d
=self
:findSymbol(v
.id
, v
, v
.global
and 'global' or nil)
549 if not d
then self
:err("symbol not found:'"..v
.id
.."'",v
) end
551 if isMemberDecl(d
) then
552 return 'replace', {tag='member',l
={tag='self'},id
=v
.id
, decl
=d
, type=getType(d
)}
569 local function rateFuncProto(f
,c
)
571 local cargs
=c
.args
or {}
572 local targs
=t
.args
or {}
574 local ctypes
,mulret
=getExprTypeList(cargs
)
576 if #ctypes
<#targs
then
577 return 0, 'argument count mismatch', c
581 local lastArg
=targs
[#targs
] --last func decl arg
582 if lastArg
and lastArg
.vararg
then
583 varargType
=getType(lastArg
)
586 for i
,ca
in ipairs(cargs
) do
591 if not varargType
then
592 return 0,'argument count mismatch', c
599 local cat
=getType(ca
)
601 if not checkType(tat
,'>=',cat
) then
602 return 0, 'argument type mismatch,expecting:'..tat
.name
..',given:'..cat
.name
, ca
605 --TODO:rate by type matches
609 local function findCallProto(f
,c
)
615 local rate
,err
,errnode
=rateFuncProto(f
,c
)
619 elseif rate
>topRate
then
622 elseif rate
==topRate
then
623 topProto
[#topProto
+1]=f
629 --TODO:with same rate? order by argument type(the more specific, the better)
630 --fixed arg > optional arg > vararg
635 function post
:call(c
)
637 if f
.tag=='closure' then
638 self
:err('cannot call a closure directly',c
)
641 if f
.decl
and is(f
.decl
.tag,'funcdecl','methoddecl') then
643 local proto
=findCallProto(f
.decl
,c
)
645 self
:err('cannot find match function overload',c
)
648 f
.type=getType(proto
)
651 local lt
=getType(c
.l
)
656 function post
:spawn(s
)
657 local pt
=getType(s
.proto
)
658 if pt
.tag~='functype' then
659 self
:err('coroutine proto must be a function,given:'..pt
.name
,s
)
666 --todo: find constructor proto
668 local clas
=getTypeDecl(c
)
670 if clas
.tag~='classdecl' then
671 self
:err('instance can be only create from a class',n
)
674 if clas
.abstract
then
676 for i
, m
in ipairs(clas
.decls
) do
678 msg
=msg
..'\n'..m
.name
681 self
:err('class has abstract method(s):'..msg
,n
)
688 function post
:binop(b
)
689 local tl
=getType(b
.l
)
690 local tr
=getType(b
.r
)
695 function post
:unop(u
)
696 local tl
=getType(u
.l
)
701 function post
:ternary(t
)
702 t
.l
=convertToBool(t
.l
)
704 local tt
,tf
=getType(t
.vtrue
),getType(t
.vfalse
)
705 local ts
=getSharedSuperType(tt
,tf
)
707 self
:err('ternary result values must be of same type',t
)
713 function post
:member(m
)
714 local td
=getType(m
.l
)
717 self
:err('unresolved type<member>',m
)
724 function post
:index(i
)
726 local td
=getType(i
.l
)
728 self
:err('unresolved type<index>',i
)
730 if not yu
.resolveIndex(td
,i
) then
731 self
:err('invalid index expression',i
)
737 function post
:table(t
)
739 for i
,item
in ipairs(t
.items
) do
740 kts
[#kts
+1]=getType(item
.key
)
744 for i
,item
in ipairs(t
.items
) do
745 vts
[#vts
+1]=getType(item
.value
)
747 local kt
=getSharedSuperType(unpack(kts
))
748 local vt
=getSharedSuperType(unpack(vts
))
751 self
:err('cannot determine table key type',t
)
754 self
:err('cannot determine table value type',t
)
757 t
.type={tag='tabletype',etype
=vt
,ktype
=kt
,name
=vt
.name
..'['..kt
.name
..']'}
761 function post
:item(i
)
765 -- function pre:seq(t)
772 for i
,item
in ipairs(t
.items
) do
773 vts
[#vts
+1]=getType(item
)
775 local vt
=getSharedSuperType(unpack(vts
))
778 self
:err('cannot determine table value type',t
)
781 t
.type={tag='tabletype',etype
=vt
,ktype
=numberType
,name
=vt
.name
..'[]'}
784 t
.type=emptyTableType
790 function post
:cast(a
)
791 --todo: typecheck l><a.dst
792 resolveCast(getType(a
.l
),a
)
796 --todo: typecheck l>=a.dst
797 -- pendTypeCheck('>=',i.l,i.dst)
799 local lt
=getType(i
.l
)
800 if not checkType(lt
,'><',i
.dst
) then
801 self
:err('unrelated type:'..lt
.name
..','..i
.dst
.name
)
807 function pre
:closure(c
)
808 return pre
.funcdecl(self
,c
)
811 function post
:closure(c
)
812 return post
.funcdecl(self
,c
)
815 function post
:self(s
)
816 local c
=self
:findParentClass()
817 local f
=self
:findParentFunc()
819 if not (c
and f
and f
.tag=='methoddecl') then
820 self
:err("'self' should be inside method",s
)
826 function post
:super(s
)
827 local c
=self
:findParentClass()
828 local f
=self
:findParentFunc()
830 if not (c
and f
and f
.tag=='methoddecl') then
831 self
:err("'super' should be inside method",s
)
833 local sc
=c
.superclass
835 self
:err("super type not defined",s
)
841 ---------------------EXTERN
842 -- function post:extern(e)
846 -- function post:externfunc(f)
850 -- function post:externclass(c)
854 -- function post:externmethod(m)
858 ------------------TYPE
859 function post
:ttype(t
) --template type
860 local d
=self
:findSymbol(t
.name
,t
)
862 if not d
or d
.tag~='classdecl' then
863 self
:err("class not found:'"..t
.name
.."'",t
)
867 --TODO:check argument
875 self
:err("expecting"..tc
.."template variable count,given"..ac
,t
)
877 for i
,a
in ipairs(args
) do
878 if getType(a
).tag=='nil' then
879 self
:err("invalid type for template variable:".."nil",t
)
884 function post
:type(t
,parent
) --symbol type
885 if isBuiltinType(t
.name
) then
886 t
.decl
=getBuiltinType(t
.name
)
888 if t
.decl
==anyType
then
889 local isExternArg
=false
891 if parent
.tag~='arg' then break end
892 local f
=self
:findParentFunc()
893 if not (f
and f
.extern
) then break end
896 if not isExternArg
then
897 self
:err("'any' type can only used for extern function argument",t
)
904 local d
=self
:findSymbol(t
.name
,t
)
905 if not (d
and isTypeDecl(d
)) then self
:err("type symbol not found:'"..t
.name
.."'",t
) end
910 function post
:tabletype(t
)
911 --TODO:make proper tabletype name
915 function post
.mulrettype(vi
,t
)
916 --TODO:make proper tabletype name
920 function pre
:functype(ft
)
922 --TODO:make proper functype name
931 self
:err('only the last argument can be defined as vararg',arg
)