initial stage...
[yu.git] / yu / decl.lua
blob8ed9d34cce99eee8ff0093c80ad0f4c0c577e4b6
1 require "yu.visitor"
2 require "yu.type"
4 local is=yu.is
5 local getTypeDecl,newTypeRef=yu.getTypeDecl,yu.newTypeRef
6 local ipairs,print=ipairs,print
8 module("yu",package.seeall)
10 local pre={}
11 local post={}
13 local isConst,isDecl,isGlobalDecl=isConst,isDecl,isGlobalDecl
14 local is=yu.is
15 local function makeNamePrefix(stack)
16 local out='_yu'
17 for i,n in ipairs(stack) do
18 if out then
19 out=out..'_'..n
20 else
21 out=n
22 end
23 end
24 return out or ''
25 end
27 function newDeclCollector()
29 return yu.newVisitor({
30 pre=pre,
31 post=post,
33 nameStack=yu.newStack(),
34 scopeStack=yu.newStack(),
36 currentNamePrefix="",
37 currentScope=false,
39 pushName=function(self,name)
40 self.nameStack:push(name)
41 self.currentNamePrefix=makeNamePrefix(self.nameStack.stack)
42 end,
44 popName=function(self)
45 self.nameStack:pop()
46 self.currentNamePrefix=makeNamePrefix(self.nameStack.stack)
47 end,
49 pushScope=function(self)
50 local scope={}
51 self.scopeStack:push(scope)
52 self.currentScope=scope
53 self.currentNode.scope=scope
54 return scope
55 end,
57 popScope=function(self)
58 self.currentScope=self.scopeStack:pop()
59 return self.currentScope
60 end,
62 addEachDecl=function(self,list)
63 for i,n in ipairs(list) do
64 if isDecl(n) or is(n.tag,"public","private") then
65 self:addDecl(n)
66 end
67 end
68 end,
70 addDecl=function(self,decl)
71 local currentScope=self.currentScope
73 if isBuiltinType(decl.name) then
74 self:err(decl.name..' is builtin type',decl,self.currentModule)
75 end
77 local tag=decl.tag
79 if tag=="private" then
80 currentScope.private=true
81 return
82 elseif tag=="public" then
83 currentScope.private=false
84 return
85 end
87 if tag=="vardecl" then
88 for i,var in ipairs(decl.vars) do
89 var.vtype=decl.vtype
90 self:addDecl(var)
91 end
92 return
93 end
95 if tag=="import" then
96 decl.name=decl.alias
97 end
99 local scope=currentScope
100 decl.private=scope.private
102 local name=decl.name
103 local decl0=scope[name]
105 if decl0 then --duplicated?
106 local tag0=decl0.tag
107 if tag==tag0 and is(tag,"funcdecl","methoddecl") then
108 --TODO:function overload
109 if decl0.private ~= decl.private then
110 self:err('function overload must be both private or public',decl)
113 local dd=decl0
114 local n=1
115 while true do
116 local d1=dd.nextProto
117 if not d1 then
118 dd.nextProto=decl
119 break
121 n=n+1
122 dd=d1
124 decl.protoId=n
125 else
126 self:err(
127 "duplicated declaration:'"..decl.name
128 .."',first defined at"
129 ..getTokenPosString(decl0,self.currentModule)
130 ,decl,self.currentModule)
132 else
133 scope[decl.name]=decl
136 if decl.alias then
137 decl.fullname=decl.alias
138 else
139 if decl.extern then
140 decl.fullname=decl.name
141 else
142 local currentNamePrefix=self.currentNamePrefix
144 if currentNamePrefix~='' then
145 decl.fullname=currentNamePrefix..'_'..name
146 else
147 decl.fullname=name
150 if decl.protoId then
151 decl.fullname='_'..decl.protoId..decl.fullname
159 -- print("..added decl:",decl.tag,decl.name,decl.fullname,decl.vtype)
167 -------------
168 function pre.any(vi,n)
169 if vi.currentModule then
170 n.module=vi.currentModule
174 function pre.module(vi,m)
175 vi:pushScope()
176 vi:pushName(m.name)
177 vi.currentModule=m
178 m.module=m
181 function post.module(vi,m)
182 vi:popName()
183 vi:popScope()
187 ---------------
189 function pre.block(vi,b,parent)
190 -- if not is(parent.tag,'funcdecl','methoddecl','forstmt','catch','foreachstmt')
191 -- b.scope=vi:pushScope()
192 -- end
193 vi:addEachDecl(b)
195 local pn=vi.nodeStack:peek(1)
196 if pn.tag=='module' then -- top block? add named imported module into scope
197 for i,h in ipairs(pn.heads) do
198 if h.tag=='import' and h.alias then
199 h.type=moduleMetaType
200 vi:addDecl(h)
207 function post.block(vi,b)
208 -- vi:popScope()
211 function pre.dostmt(vi,d)
212 vi:pushScope()
215 function post.dostmt(vi,d)
216 vi:popScope()
219 -----------
221 function pre.extern(vi,e)
222 for i,s in ipairs(e.decls) do
223 if isDecl(s) or is(s.tag,"public","private") then
224 vi:addDecl(s)
229 -----------
232 local function spreadVarTypes(vars,vardecl)
233 local lasttype=nil
234 for i=#vars,1,-1 do
235 local var=vars[i]
236 if var.type then
237 lasttype=var.type
238 elseif lasttype then
239 var.type=lasttype
240 else
241 -- table.foreach(var,print)
242 return yu.compileErr("type identifier expected",var,vardecl.module)
248 function pre:vardecl(vd)
249 local vars=vd.vars
250 if vd.def then --should no type id
251 for i,var in ipairs(vars) do
252 if var.type then return self:err("unnecessary type identifier",var.type) end
254 --todo:mulitple return
255 for i,var in ipairs(vars) do
256 local v=vd.values[i]
257 var.value=v
258 var.type=newTypeRef(v)
261 else
262 spreadVarTypes(vars,vd)
263 --todo:mulitple return
264 if vd.values then
265 for i,var in ipairs(vars) do
266 var.value=vd.values[i]
271 return true
276 function pre.funcdecl(vi,f)
277 vi:pushName(f.name)
278 vi:pushScope()
281 function post.funcdecl(vi,f)
282 vi:popScope()
283 vi:popName()
286 function pre.closure(vi,f)
287 f.name='C'
288 vi:pushName(f.name)
289 vi:pushScope()
292 function post.closure(vi,f)
293 vi:popScope()
294 vi:popName()
298 -----------
299 function pre.methoddecl(vi,f,parent)
300 vi:pushName(f.name)
301 vi:pushScope()
302 if f.abstract then
303 parent.abstract=true
307 function post.methoddecl(vi,f)
309 vi:popScope()
310 vi:popName()
313 -----------
314 function pre.externfunc(vi,f)
315 vi:pushName(f.name)
316 vi:pushScope()
319 function post.externfunc(vi,f)
320 vi:popScope()
321 vi:popName()
324 -----------
325 function pre.externmethod(vi,f)
326 vi:pushName(f.name)
327 vi:pushScope()
330 function post.externmethod(vi,f)
331 vi:popScope()
332 vi:popName()
334 ------------
335 function pre.functype(vi,ft)
336 local args=ft.args
337 if args then
338 spreadVarTypes(args,ft)
339 for i,arg in ipairs(args) do
340 vi:addDecl(arg)
346 function post.functype(vi,ft)
352 ------------
353 function pre.catch(vi,c)
354 vi:pushScope()
355 for i,v in ipairs(c.vars) do
356 vi:addDecl(v)
360 function post.catch(vi,c)
361 vi:popScope()
364 ------------
365 function pre.foreachstmt(vi,f)
366 vi:pushScope()
367 for i,v in ipairs(f.vars) do
368 vi:addDecl(v)
369 end
372 function post.foreachstmt(vi,f)
373 vi:popScope()
377 function pre.forstmt(vi,f)
378 vi:pushScope()
379 f.var.type=numberType
380 f.var.vtype='local'
381 vi:addDecl(f.var)
384 function post.forstmt(vi,f)
385 vi:popScope()
388 ----------
390 function pre.classdecl(vi,c)
391 c.type=classMetaType
392 vi:pushName(c.name)
393 vi:pushScope()
396 function post.classdecl(vi,c)
397 if c.tvars then
398 for i,v in ipairs(c.tvars) do
399 vi:addDecl(v)
400 end
403 if c.decls then
404 for i,d in ipairs(c.decls) do
405 vi:addDecl(d)
409 vi:popScope()
410 vi:popName()
413 function pre.externclass(vi,c)
414 vi:pushName(c.name)
415 vi:pushScope()
416 if c.decls then
417 for i,d in ipairs(c.decls) do
418 vi:addDecl(d)
423 function post.externclass(vi,c)
424 vi:popScope()
425 vi:popName()
430 function pre.enumdecl(vi,e)
431 vi:pushName(e.name)
432 vi:pushScope()
434 for i,ei in ipairs(e.items) do
435 vi:addDecl(ei)
440 function post.enumdecl(vi,c)
441 vi:popScope()
442 vi:popName()