initial stage...
[yu.git] / yu / resolver.lua
blob7d601da800ff66f4887841687624274e8dae7879
1 require "yu.visitor"
2 require "yu.type"
5 module("yu",package.seeall)
7 local is=is
8 local getType,getTypeDecl,newTypeRef,checkType=getType,getTypeDecl,newTypeRef,checkType
9 local getExprTypeList=getExprTypeList
11 local pre={}
12 local post={}
14 local __searchSeq=0
16 local function _findExternSymbol(entryModule,name,found)
17 found=found or {}
18 local externModules=entryModule.externModules
20 if externModules then
21 for p,m in pairs(externModules) do
22 if m.__seq~=__searchSeq then
23 m.__seq=__searchSeq
24 local decl=m.scope[name]
25 if decl and not decl.private then
26 found[#found+1]={module=m,decl=decl}
27 end
28 _findExternSymbol(m,name,found)
29 end
30 end
31 end
33 return found
34 end
36 local function _findSymbol(vi,name,token,limit)
37 local t=vi.nodeStack.stack
38 local outClas,outFunc,outMethod=0,0,0
40 for i=#t,1,-1 do
41 local node=t[i]
42 local scope=node.scope
44 if scope then
45 local tag=node.tag
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
50 local decl
51 if tag=='classdecl' then
52 local clas=node
53 while clas do
54 decl=clas.scope[name]
55 if decl then break end
56 clas=clas.superclass
57 end
58 else
59 decl=scope[name]
60 end
62 if decl then
63 -- print('found:',scope,decl.name,node.tag,decl.p0,token.p0)
64 if not (
65 (limit=='global' and isMemberDecl(decl))
66 ) then
67 local dtag=decl.tag
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
73 else
74 return decl
75 end
76 elseif dtag=='methoddecl' then
77 if outMethod==1 then return decl end
78 else
79 return decl
80 end
82 if not (
83 decl.tag=='var' and decl.vtype=='local'
84 and (decl.p0>token.p0 or outFunc)
85 ) then
87 end
88 end
89 end
91 end
93 end
95 --search extern modules
96 __searchSeq=__searchSeq+1
98 if not token.module then
99 -- print(token.tag)
102 local found=_findExternSymbol(token.module,name)
104 local i=0
105 local foundCount=#found
106 if foundCount>1 then
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
114 return found[1].decl
117 return nil
120 function newResolver()
121 local r={
122 pre=pre,
123 post=post,
124 findSymbol=_findSymbol
126 return yu.newVisitor(r)
130 ----------------TOPLEVEL
131 function pre:any(n)
132 -- print('resoving..',n.tag)
133 local state=n.resolveState
134 if state=='done' then
135 return 'skip'
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)
149 function post:any(n)
150 n.resolveState='done'
153 function pre:module(m)
154 m.resolving=true
157 function post:module(m)
160 -- function pre:block(b)
162 -- end
164 -- function post:block(b)
166 -- end
168 ---------------Directive
169 -- function post:import(im)
170 -- local m=im.mod
171 -- --TODO!
172 -- end
174 -- function post:private()
175 -- return true
176 -- end
178 -- function post:public()
179 -- return true
180 -- end
182 function post:rawlua(r)
183 local f,err=loadstring(r.src)
184 if not f then
185 self:err('error in Lua code:'..err,r)
189 ------------------------------CONTROL
190 function post:exprstmt(e)
191 local expr=e.expr
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()
200 if not l then
201 self:err("'continue' must be inside loop block",c)
203 l.hasContinue=true
204 self.currentBlock.endState=true
205 return true
208 function post:breakstmt(b)
209 local l=self:findParentLoop()
210 if not l then
211 self:err("'break' must be inside loop block",b)
213 l.hasBreak=true
214 self.currentBlock.endState=true
215 return true
218 function post:returnstmt(r)
219 local f=self:findParentFunc()
220 if not f then
221 self:err("'return'/'yield' should be inside function",r)
223 self.currentBlock.endState=true
224 local rettype=getTypeDecl(f.type.rettype)
226 if r.values then
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
232 f.hasReturn=true
233 --TODO!!!!!!!!!!!!!!!!!
234 else
235 f.hasReturn=true
236 if #r.values>1 then
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)
248 return true
251 function post:yieldstmt(y,p)
252 return post.returnstmt(self,y,p)
255 -- function post:dostmt(d)
256 -- return true
257 -- end
259 function post:ifstmt(s)
260 s.cond=convertToBool(s.cond)
261 self:visitNode(s.cond)
262 return true
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)
276 return true
279 -- function post:case(c)
280 -- return true
281 -- end
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)
294 --todo:!!!!
295 --todo:typecheck vars type <=iterator return type
298 function post:whilestmt(s)
299 s.cond=convertToBool(s.cond)
300 self:visitNode(s.cond)
301 return true
304 -- function post:trystmt(t)
305 -- return true
306 -- end
308 -- function post:throwstmt(t)
309 -- return true
310 -- end
312 function post:catch(c)
313 --todo:!!!!
314 return true
317 -----------------#ASSIGNSTMT
318 local function isAssignable(var)
319 local tag=var.tag
323 if tag=='varacc' or tag=='member' then
324 local decl=var.decl
325 local dtag=decl.tag
327 if dtag=='var' then
328 return decl.vtype~='const'
331 elseif tag=='index' then
332 return true
334 return false
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
359 local vt=valtypes[i]
360 local vart=getType(var)
362 if not checkType(vart,'>=',vt) then
363 self:err('variable/value type mismatch:'..vart.name..'<-'..vt.name)
367 return true
370 function post:assopstmt(a)
371 --todo: check is isAssignable
372 --todo: different variable type(member/index/indexoverride)
373 -- pendTypeCheck('==',a.var,a.value)
375 return true
376 end
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',{
385 -- tag='dostmt',
386 -- block={tag='block',
387 -- {tag='vardecl', vars={
388 -- }
389 -- }
390 -- }
394 -----------------#DECLARATION
395 -- function pre:vardecl(vd)
397 -- end
400 function post:tvar(v)
401 --todo:!!!!!!!!!!!!!!!!!!!
402 return true
405 function post:var(v)
406 if v.vtype=='const' and not v.value then
407 self:err('const variable has no value:'..v.name,v)
410 local td=getType(v)
411 if not td then
412 self:err('unresolved type',v)
413 else
414 v.type=td
417 if v.value then
418 if not checkType(v.type,'>=',getType(v.value)) then
419 self:err('type mismatch',v)
422 --TODO:
423 return true
426 function post:arg(a)
428 return true
431 function post:enumdecl(e)
432 local ii={}
433 for i,item in ipairs(e.items) do
434 local iv=item.value
435 if ii[iv] then self:err('duplicated enum item value',item) end
436 ii[iv]=true
438 e.type=enumMetaType
441 function post:enumitem(i,e)
443 if i.value then
444 local v=getConstNode(i.value)
445 i.value=v
446 if not v or getType(v).tag~='numbertype' then
447 self:err('enum item must be constant number')
449 e.currentValue=v
450 else
451 local cv=e.currentValue
452 if not cv then
453 cv=makeNumberConst(1)
454 else
455 cv=makeNumberConst(tonumber(cv.v)+1)
457 i.value=cv
458 e.currentValue=cv
460 i.type=i.value.type
463 local function checkConst(n)
464 local tag=n.tag
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)
474 return false
477 function pre:classdecl(c)
478 local supername=c.supername
479 if supername then
480 local s=self:findSymbol(supername.id,c)
481 --todo check template
482 if not s then
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
486 c.superclass=s
488 c.resolveState='done'
491 function post:classdecl(c)
492 ------------TODO:!
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
501 local ftype=m.type
502 assert(m.block or m.abstract,'abstract?'..m.name)
503 if m.inherit then
504 local c=parent.superclass
505 local superMethod
506 while c do
507 local m=c.scope[m.name]
508 if m then
509 if m.tag=='methoddecl' then superMethod=m end
510 break
512 c=c.superclass
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)
538 return true
541 function post:exprbody(e)
542 self:findParentFunc().hasReturn=true
543 --TODO:check type
544 return 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)}
555 self:visitNode(d)
557 v.decl=d
558 local td=getType(d)
559 if td then
560 v.type=td
561 else
562 v.type=d.type
563 assert(d.type)
566 return false
569 local function rateFuncProto(f,c)
570 local t=getType(f)
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
580 local varargType
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
587 local ta=targs[i]
588 local tat
590 if not ta then
591 if not varargType then
592 return 0,'argument count mismatch', c
594 tat=varargType
595 else
596 tat=getType(ta)
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
606 return 1
609 local function findCallProto(f,c)
610 -- local rates={}
611 local topRate=0
612 local topProto={}
614 while f do
615 local rate,err,errnode=rateFuncProto(f,c)
617 if rate==0 then
619 elseif rate>topRate then
620 topRate=rate
621 topProto={f}
622 elseif rate==topRate then
623 topProto[#topProto+1]=f
626 f=f.nextProto
629 --TODO:with same rate? order by argument type(the more specific, the better)
630 --fixed arg > optional arg > vararg
631 return topProto[1]
635 function post:call(c)
636 local f=c.l
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)
644 if not proto then
645 self:err('cannot find match function overload',c)
647 f.decl=proto
648 f.type=getType(proto)
651 local lt=getType(c.l)
652 yu.resolveCall(lt,c)
653 return true
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)
661 s.type=pt
662 return true
665 function post:new(n)
666 --todo: find constructor proto
667 local c=n.class
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
675 local msg=''
676 for i, m in ipairs(clas.decls) do
677 if m.abstract then
678 msg=msg..'\n'..m.name
681 self:err('class has abstract method(s):'..msg,n)
684 n.type=n.class
685 return true
688 function post:binop(b)
689 local tl=getType(b.l)
690 local tr=getType(b.r)
691 yu.resolveOP(tl,b)
692 return false
695 function post:unop(u)
696 local tl=getType(u.l)
697 yu.resolveOP(tl,u)
698 return true
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)
706 if not ts then
707 self:err('ternary result values must be of same type',t)
709 t.type=ts
710 return true
711 end
713 function post:member(m)
714 local td=getType(m.l)
716 if not td then
717 self:err('unresolved type<member>',m)
720 resolveMember(td,m)
724 function post:index(i)
726 local td=getType(i.l)
727 if not td then
728 self:err('unresolved type<index>',i)
730 if not yu.resolveIndex(td,i) then
731 self:err('invalid index expression',i)
734 return false
737 function post:table(t)
738 local kts={}
739 for i,item in ipairs(t.items) do
740 kts[#kts+1]=getType(item.key)
743 local vts={}
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))
750 if not kt then
751 self:err('cannot determine table key type',t)
753 if not vt then
754 self:err('cannot determine table value type',t)
757 t.type={tag='tabletype',etype=vt,ktype=kt,name=vt.name..'['..kt.name..']'}
758 return true
761 function post:item(i)
762 return true
765 -- function pre:seq(t)
767 -- end
769 function post:seq(t)
770 local vts={}
771 if t.items then
772 for i,item in ipairs(t.items) do
773 vts[#vts+1]=getType(item)
775 local vt=getSharedSuperType(unpack(vts))
777 if not vt then
778 self:err('cannot determine table value type',t)
781 t.type={tag='tabletype',etype=vt,ktype=numberType,name=vt.name..'[]'}
782 else
783 --TODO:empty one
784 t.type=emptyTableType
787 return true
790 function post:cast(a)
791 --todo: typecheck l><a.dst
792 resolveCast(getType(a.l),a)
795 function post:is(i)
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)
804 i.type=booleanType
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)
822 s.type=c
823 return true
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
834 if not sc then
835 self:err("super type not defined",s)
837 s.type=sc
838 return true
841 ---------------------EXTERN
842 -- function post:extern(e)
843 -- return true
844 -- end
846 -- function post:externfunc(f)
847 -- return true
848 -- end
850 -- function post:externclass(c)
851 -- return true
852 -- end
854 -- function post:externmethod(m)
855 -- return true
856 -- end
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 )
865 t.class=d
867 --TODO:check argument
868 local args=t.args
869 local tvars=d.tvars
871 local ac=#args
872 local tc=#tvars
874 if ac~=tc then
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
890 repeat
891 if parent.tag~='arg' then break end
892 local f=self:findParentFunc()
893 if not (f and f.extern) then break end
894 isExternArg=true
895 until true
896 if not isExternArg then
897 self:err("'any' type can only used for extern function argument",t)
901 return
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
906 t.decl=d
910 function post:tabletype(t)
911 --TODO:make proper tabletype name
912 t.name='TABLE'
915 function post.mulrettype(vi,t)
916 --TODO:make proper tabletype name
917 t.name='(...'..')'
920 function pre:functype(ft)
921 local rt=ft.rettype
922 --TODO:make proper functype name
923 ft.name='FUNCTION'
924 local ac=#ft.args
925 for i=ac,1,-1 do
926 local arg=ft.args[i]
927 if arg.vararg then
928 if i==ac then
929 --ok, vararg
930 else
931 self:err('only the last argument can be defined as vararg',arg)