comparison sema/CheckScopes.d @ 194:08f68d684047

Rename some files. Hopefully we can get a more iterative sema pass, that's a lot easier to "get startet with". Also added support for alias.
author Anders Johnsen <skabet@gmail.com>
date Tue, 29 Jul 2008 13:54:44 +0200
parents sema/ScopeCheck.d@01c2c49775ef
children
comparison
equal deleted inserted replaced
193:658178183018 194:08f68d684047
1 module sema.CheckScopes;
2
3 import sema.Visitor,
4 sema.Symbol,
5 sema.Scope,
6 sema.DType;
7
8 import basic.Message,
9 basic.Attribute;
10
11 import tango.io.Stdout;
12
13 class CheckScopes : Visitor!(void)
14 {
15
16 this(MessageHandler messages)
17 {
18 this.messages = messages;
19 }
20
21 override void visitIdentifier(Identifier i)
22 {
23 auto symbol = i.env.find(i.get);
24
25 if(symbol is null)
26 messages.report(UndefinedIdentifier, i.loc)
27 .arg(i.get);
28 }
29
30 override void visitVarDecl(VarDecl d)
31 {
32 if(d.identifier.get is null)
33 messages.report(UndefinedType, d.varType.loc)
34 .arg(d.varType.get);
35
36 auto env = d.env;
37 if (d.env.enclosing)
38 if (d.env.enclosing.find(d.identifier.get) !is null)
39 if (d.env.parentFunction !is null)
40 while( d.env.parentFunction.env !is env)
41 {
42 if (d.env.enclosing.find(d.identifier.get)[0].env == env)
43 messages.report(CannotRedeclare, d.identifier.loc)
44 .arg(d.identifier.get);
45 env = env.enclosing;
46 }
47
48 visitExp(d.identifier);
49 if (d.init)
50 visitExp(d.init);
51 }
52
53 override void visitFuncDecl(FuncDecl f)
54 {
55 visitExp(f.identifier);
56
57 inFunction = true;
58 foreach (stmt; f.statements)
59 visitStmt(stmt);
60 inFunction = false;
61 }
62
63 override void visitImportDecl(ImportDecl) { }
64
65 override void visitCastExp(CastExp exp)
66 {
67 visitExp(exp.exp);
68 }
69
70 override void visitMemberReference(MemberReference m)
71 {
72 internalVisitMemberRef(m);
73 }
74
75 private Symbol internalVisitMemberRef(MemberReference m)
76 {
77 Symbol visitRef(MemberReference m, Identifier target, Symbol st)
78 {
79 auto child = m.child;
80 auto res = st.findMembers(child.get);
81
82 if(!res.length)
83 messages.report(MissingMember, m.loc)
84 .arg(st.type.name)
85 .arg(target.get)
86 .arg(child.get);
87 else
88 internalCheckProtection(res[0], child);
89
90 return res.length ? res[0] : null;
91 }
92 switch(m.target.expType)
93 {
94 case ExpType.Identifier:
95 return visitRef(m, cast(Identifier)m.target,
96 (cast(Identifier)m.target).getSymbol);
97 case ExpType.MemberReference:
98 Symbol s = internalVisitMemberRef(cast(MemberReference)m.target);
99 if(!s)
100 return null;
101 return visitRef(m, cast(Identifier)m.target, s);
102 }
103 }
104
105 override void visitExp(Exp exp)
106 {
107 if (exp.expType == ExpType.Identifier && inFunction
108 && exp.env.find((cast(Identifier)exp).get) !is null)
109 {
110 if (exp.env.findType((cast(Identifier)exp).get) is null)
111 internalCheckProtection(
112 exp.env.find((cast(Identifier)exp).get)[0].sym,
113 cast(Identifier)exp);
114 }
115
116 super.visitExp(exp);
117 }
118
119 private void internalCheckProtection(Symbol sym, Identifier iden)
120 {
121 if (isChildOf(sym.decl.env, iden.env))
122 return;
123
124 switch(sym.decl.att.getProtection)
125 {
126 case Protection.Private:
127 /* if (iden.env.inModule == sym.decl.getIdentifier.env.inModule
128 && sym.decl.getIdentifier.env.enclosing == iden.env.inModule)
129 {}
130 else*/
131 messages.report(CannotAccessPrivate, iden.loc);
132 return;
133 default:
134 return;
135 }
136 }
137
138 private bool isChildOf(Scope parent, Scope child)
139 {
140 if (child is parent)
141 return true;
142
143 if (child.enclosing !is null)
144 return isChildOf(parent, child.enclosing);
145
146 return false;
147 }
148
149 private bool isType(char[] s)
150 {
151 return (s in types? true : false);
152 }
153
154 int[char[]] types;
155 MessageHandler messages;
156 bool inFunction;
157 }
158