Mercurial > projects > dil
comparison trunk/src/dil/semantic/Pass2.d @ 684:10b314bf37e3
Added module dil.semantic.Pass2.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Mon, 21 Jan 2008 18:40:55 +0100 |
parents | |
children | d33895f679eb |
comparison
equal
deleted
inserted
replaced
683:1ae72234db26 | 684:10b314bf37e3 |
---|---|
1 /++ | |
2 Author: Aziz Köksal | |
3 License: GPL3 | |
4 +/ | |
5 module dil.semantic.Pass2; | |
6 | |
7 import dil.ast.DefaultVisitor; | |
8 import dil.ast.Node, | |
9 dil.ast.Declarations, | |
10 dil.ast.Expressions, | |
11 dil.ast.Statements, | |
12 dil.ast.Types, | |
13 dil.ast.Parameters; | |
14 import dil.lexer.Identifier; | |
15 import dil.semantic.Symbol, | |
16 dil.semantic.Symbols, | |
17 dil.semantic.Types, | |
18 dil.semantic.Scope, | |
19 dil.semantic.Module, | |
20 dil.semantic.Analysis; | |
21 import dil.parser.Parser; | |
22 import dil.Location; | |
23 import dil.Information; | |
24 import dil.Messages; | |
25 import dil.Enums; | |
26 import dil.CompilerInfo; | |
27 import common; | |
28 | |
29 class SemanticPass2 : DefaultVisitor | |
30 { | |
31 Scope scop; /// The current scope. | |
32 Module modul; /// The module to be semantically checked. | |
33 | |
34 this(Module modul) | |
35 { | |
36 this.modul = modul; | |
37 } | |
38 | |
39 /// Start semantic analysis. | |
40 void start() | |
41 { | |
42 assert(modul.root !is null); | |
43 // Create module scope. | |
44 scop = new Scope(); | |
45 scop.symbol = modul; // Set this module as the scope's symbol. | |
46 scop.infoMan = modul.infoMan; | |
47 visit(modul.root); | |
48 } | |
49 | |
50 void enterScope(ScopeSymbol s) | |
51 { | |
52 scop = scop.enter(s); | |
53 } | |
54 | |
55 void exitScope() | |
56 { | |
57 scop = scop.exit(); | |
58 } | |
59 | |
60 void error(Token* token, char[] formatMsg, ...) | |
61 { | |
62 auto location = token.getErrorLocation(); | |
63 auto msg = Format(_arguments, _argptr, formatMsg); | |
64 modul.infoMan ~= new SemanticError(location, msg); | |
65 } | |
66 | |
67 private alias Declaration D; | |
68 private alias Expression E; | |
69 private alias Statement S; | |
70 private alias TypeNode T; | |
71 | |
72 override | |
73 { | |
74 D visit(CompoundDeclaration d) | |
75 { | |
76 return super.visit(d); | |
77 } | |
78 | |
79 D visit(MixinDeclaration md) | |
80 { | |
81 /+ | |
82 if (type) | |
83 return this.expr; | |
84 // TODO: | |
85 auto expr = this.expr.semantic(scop); | |
86 expr = expr.evaluate(); | |
87 if (expr is null) | |
88 return this; | |
89 auto strExpr = TryCast!(StringExpression)(expr); | |
90 if (strExpr is null) | |
91 error(scop, MSG.MixinArgumentMustBeString); | |
92 else | |
93 { | |
94 auto loc = this.begin.getErrorLocation(); | |
95 auto filePath = loc.filePath; | |
96 auto parser = new_ExpressionParser(strExpr.getString(), filePath, scop.infoMan); | |
97 expr = parser.parse(); | |
98 expr = expr.semantic(scop); | |
99 } | |
100 this.expr = expr; | |
101 this.type = expr.type; | |
102 return expr; | |
103 +/ | |
104 return md; | |
105 } | |
106 | |
107 T visit(PointerType t) | |
108 { | |
109 t.type = visitT(t.next).type.ptrTo(); | |
110 return t; | |
111 } | |
112 | |
113 T visit(IntegralType t) | |
114 { | |
115 // A table mapping the kind of a token to its corresponding semantic Type. | |
116 TypeBasic[TOK] tok2Type = [ | |
117 TOK.Char : Types.Char, TOK.Wchar : Types.Wchar, TOK.Dchar : Types.Dchar, TOK.Bool : Types.Bool, | |
118 TOK.Byte : Types.Byte, TOK.Ubyte : Types.Ubyte, TOK.Short : Types.Short, TOK.Ushort : Types.Ushort, | |
119 TOK.Int : Types.Int, TOK.Uint : Types.Uint, TOK.Long : Types.Long, TOK.Ulong : Types.Ulong, | |
120 TOK.Cent : Types.Cent, TOK.Ucent : Types.Ucent, | |
121 TOK.Float : Types.Float, TOK.Double : Types.Double, TOK.Real : Types.Real, | |
122 TOK.Ifloat : Types.Ifloat, TOK.Idouble : Types.Idouble, TOK.Ireal : Types.Ireal, | |
123 TOK.Cfloat : Types.Cfloat, TOK.Cdouble : Types.Cdouble, TOK.Creal : Types.Creal, TOK.Void : Types.Void | |
124 ]; | |
125 t.type = tok2Type[t.tok]; | |
126 return t; | |
127 } | |
128 | |
129 E visit(ParenExpression e) | |
130 { | |
131 if (!e.type) | |
132 { | |
133 e.next = visitE(e.next); | |
134 e.type = e.next.type; | |
135 } | |
136 return e; | |
137 } | |
138 | |
139 E visit(CommaExpression e) | |
140 { | |
141 if (!e.type) | |
142 { | |
143 e.left = visitE(e.left); | |
144 e.right = visitE(e.right); | |
145 e.type = e.right.type; | |
146 } | |
147 return e; | |
148 } | |
149 | |
150 E visit(OrOrExpression) | |
151 { return null; } | |
152 | |
153 E visit(AndAndExpression) | |
154 { return null; } | |
155 | |
156 E visit(SpecialTokenExpression e) | |
157 { | |
158 if (e.type) | |
159 return e.value; | |
160 switch (e.specialToken.kind) | |
161 { | |
162 case TOK.LINE, TOK.VERSION: | |
163 e.value = new IntExpression(e.specialToken.uint_, Types.Uint); | |
164 break; | |
165 case TOK.FILE, TOK.DATE, TOK.TIME, TOK.TIMESTAMP, TOK.VENDOR: | |
166 e.value = new StringExpression(e.specialToken.str); | |
167 break; | |
168 default: | |
169 assert(0); | |
170 } | |
171 e.type = e.value.type; | |
172 return e.value; | |
173 } | |
174 | |
175 E visit(DollarExpression e) | |
176 { | |
177 if (e.type) | |
178 return e; | |
179 e.type = Types.Size_t; | |
180 // if (!inArraySubscript) | |
181 // error("$ can only be in an array subscript."); | |
182 return e; | |
183 } | |
184 | |
185 E visit(NullExpression e) | |
186 { | |
187 if (!e.type) | |
188 e.type = Types.Void_ptr; | |
189 return e; | |
190 } | |
191 | |
192 E visit(BoolExpression e) | |
193 { | |
194 if (e.type) | |
195 return e; | |
196 e.value = new IntExpression(e.toBool(), Types.Bool); | |
197 e.type = Types.Bool; | |
198 return e; | |
199 } | |
200 | |
201 E visit(IntExpression e) | |
202 { | |
203 if (e.type) | |
204 return e; | |
205 | |
206 if (e.number & 0x8000_0000_0000_0000) | |
207 e.type = Types.Ulong; // 0xFFFF_FFFF_FFFF_FFFF | |
208 else if (e.number & 0xFFFF_FFFF_0000_0000) | |
209 e.type = Types.Long; // 0x7FFF_FFFF_FFFF_FFFF | |
210 else if (e.number & 0x8000_0000) | |
211 e.type = Types.Uint; // 0xFFFF_FFFF | |
212 else | |
213 e.type = Types.Int; // 0x7FFF_FFFF | |
214 return e; | |
215 } | |
216 | |
217 E visit(RealExpression e) | |
218 { | |
219 if (e.type) | |
220 e.type = Types.Double; | |
221 return e; | |
222 } | |
223 | |
224 E visit(ComplexExpression e) | |
225 { | |
226 if (!e.type) | |
227 e.type = Types.Cdouble; | |
228 return e; | |
229 } | |
230 | |
231 E visit(CharExpression e) | |
232 { | |
233 if (e.type) | |
234 return e; | |
235 if (e.character <= 0xFF) | |
236 e.type = Types.Char; | |
237 else if (e.character <= 0xFFFF) | |
238 e.type = Types.Wchar; | |
239 else | |
240 e.type = Types.Dchar; | |
241 return e; | |
242 } | |
243 | |
244 E visit(StringExpression e) | |
245 { | |
246 return e; | |
247 } | |
248 | |
249 E visit(MixinExpression me) | |
250 { | |
251 if (me.type) | |
252 return me.expr; | |
253 auto expr = visitE(me.expr); | |
254 // TODO: expr = expr.evaluate(); | |
255 if (expr is null) | |
256 return me; | |
257 auto stringExpr = expr.Is!(StringExpression); | |
258 if (stringExpr is null) | |
259 error(me.begin, MSG.MixinArgumentMustBeString); | |
260 else | |
261 { | |
262 auto loc = me.begin.getErrorLocation(); | |
263 auto filePath = loc.filePath; | |
264 auto parser = new Parser(stringExpr.getString(), filePath, scop.infoMan); | |
265 expr = parser.start2(); | |
266 expr = visitE(expr); // Check expression. | |
267 } | |
268 me.expr = expr; | |
269 me.type = expr.type; | |
270 return me.expr; | |
271 } | |
272 | |
273 E visit(ImportExpression e) | |
274 { | |
275 return e; | |
276 } | |
277 } | |
278 } |