Mercurial > projects > dang
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 |