comparison src/dil/semantic/Pass2.d @ 806:bcb74c9b895c

Moved out files in the trunk folder to the root.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 09 Mar 2008 00:12:19 +0100
parents trunk/src/dil/semantic/Pass2.d@9e6c6bb73e5f
children 525ee3f848d9
comparison
equal deleted inserted replaced
805:a3fab8b74a7d 806:bcb74c9b895c
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 dil.semantic.Interpreter;
22 import dil.parser.Parser;
23 import dil.SourceText;
24 import dil.Location;
25 import dil.Information;
26 import dil.Messages;
27 import dil.Enums;
28 import dil.CompilerInfo;
29 import common;
30
31 /// The second pass determines the types of symbols and the types
32 /// of expressions and also evaluates them.
33 class SemanticPass2 : DefaultVisitor
34 {
35 Scope scop; /// The current scope.
36 Module modul; /// The module to be semantically checked.
37
38 /// Constructs a SemanticPass2 object.
39 /// Params:
40 /// modul = the module to be checked.
41 this(Module modul)
42 {
43 this.modul = modul;
44 }
45
46 /// Start semantic analysis.
47 void start()
48 {
49 assert(modul.root !is null);
50 // Create module scope.
51 scop = new Scope(null, modul);
52 visit(modul.root);
53 }
54
55 /// Enters a new scope.
56 void enterScope(ScopeSymbol s)
57 {
58 scop = scop.enter(s);
59 }
60
61 /// Exits the current scope.
62 void exitScope()
63 {
64 scop = scop.exit();
65 }
66
67 /// Evaluates e and returns the result.
68 Expression interpret(Expression e)
69 {
70 return Interpreter.interpret(e, modul.infoMan/+, scop+/);
71 }
72
73 /// Creates an error report.
74 void error(Token* token, char[] formatMsg, ...)
75 {
76 auto location = token.getErrorLocation();
77 auto msg = Format(_arguments, _argptr, formatMsg);
78 modul.infoMan ~= new SemanticError(location, msg);
79 }
80
81 /// Some handy aliases.
82 private alias Declaration D;
83 private alias Expression E; /// ditto
84 private alias Statement S; /// ditto
85 private alias TypeNode T; /// ditto
86
87 /// The current scope symbol to use for looking up identifiers.
88 /// E.g.:
89 /// ---
90 /// object.method(); // *) object is looked up in the current scope.
91 /// // *) idScope is set if object is a ScopeSymbol.
92 /// // *) method will be looked up in idScope.
93 /// dil.ast.Node.Node node; // A fully qualified type.
94 /// ---
95 ScopeSymbol idScope;
96
97 /// Searches for a symbol.
98 Symbol search(Token* idTok)
99 {
100 assert(idTok.kind == TOK.Identifier);
101 auto id = idTok.ident;
102 Symbol symbol;
103
104 if (idScope is null)
105 for (auto sc = scop; sc; sc = sc.parent)
106 {
107 symbol = sc.lookup(id);
108 if (symbol)
109 return symbol;
110 }
111 else
112 symbol = idScope.lookup(id);
113
114 if (symbol is null)
115 error(idTok, MSG.UndefinedIdentifier, id.str);
116 else if (auto scopSymbol = cast(ScopeSymbol)symbol)
117 idScope = scopSymbol;
118
119 return symbol;
120 }
121
122 override
123 {
124 D visit(CompoundDeclaration d)
125 {
126 return super.visit(d);
127 }
128
129 D visit(EnumDeclaration d)
130 {
131 d.symbol.setCompleting();
132
133 Type type = Types.Int; // Default to int.
134 if (d.baseType)
135 type = visitT(d.baseType).type;
136 d.symbol.type = new TypeEnum(d.symbol, type);
137
138 enterScope(d.symbol);
139
140 foreach (member; d.members)
141 {
142 Expression finalValue;
143 member.symbol.setCompleting();
144 if (member.value)
145 {
146 member.value = visitE(member.value);
147 finalValue = interpret(member.value);
148 if (finalValue is Interpreter.NAR)
149 finalValue = new IntExpression(0, d.symbol.type);
150 }
151 //else
152 // TODO: increment a number variable and assign that to value.
153 member.symbol.type = d.symbol.type; // Assign TypeEnum.
154 member.symbol.value = finalValue;
155 member.symbol.setComplete();
156 }
157
158 exitScope();
159 d.symbol.setComplete();
160 return d;
161 }
162
163 D visit(MixinDeclaration md)
164 {
165 if (md.decls)
166 return md.decls;
167 if (md.isMixinExpression)
168 {
169 md.argument = visitE(md.argument);
170 auto expr = interpret(md.argument);
171 if (expr is Interpreter.NAR)
172 return md;
173 auto stringExpr = expr.Is!(StringExpression);
174 if (stringExpr is null)
175 {
176 error(md.begin, MSG.MixinArgumentMustBeString);
177 return md;
178 }
179 else
180 { // Parse the declarations in the string.
181 auto loc = md.begin.getErrorLocation();
182 auto filePath = loc.filePath;
183 auto sourceText = new SourceText(filePath, stringExpr.getString());
184 auto parser = new Parser(sourceText, modul.infoMan);
185 md.decls = parser.start();
186 }
187 }
188 else
189 {
190 // TODO: implement template mixin.
191 }
192 return md.decls;
193 }
194
195 // Type nodes:
196
197 T visit(TypeofType t)
198 {
199 t.e = visitE(t.e);
200 t.type = t.e.type;
201 return t;
202 }
203
204 T visit(ArrayType t)
205 {
206 auto baseType = visitT(t.next).type;
207 if (t.isAssociative)
208 t.type = baseType.arrayOf(visitT(t.assocType).type);
209 else if (t.isDynamic)
210 t.type = baseType.arrayOf();
211 else if (t.isStatic)
212 {}
213 else
214 assert(t.isSlice);
215 return t;
216 }
217
218 T visit(PointerType t)
219 {
220 t.type = visitT(t.next).type.ptrTo();
221 return t;
222 }
223
224 T visit(QualifiedType t)
225 {
226 if (t.lhs.Is!(QualifiedType) is null)
227 idScope = null; // Reset at left-most type.
228 visitT(t.lhs);
229 visitT(t.rhs);
230 t.type = t.rhs.type;
231 return t;
232 }
233
234 T visit(IdentifierType t)
235 {
236 auto idToken = t.begin;
237 auto symbol = search(idToken);
238 // TODO: save symbol or its type in t.
239 return t;
240 }
241
242 T visit(TemplateInstanceType t)
243 {
244 auto idToken = t.begin;
245 auto symbol = search(idToken);
246 // TODO: save symbol or its type in t.
247 return t;
248 }
249
250 T visit(ModuleScopeType t)
251 {
252 idScope = modul;
253 return t;
254 }
255
256 T visit(IntegralType t)
257 {
258 // A table mapping the kind of a token to its corresponding semantic Type.
259 TypeBasic[TOK] tok2Type = [
260 TOK.Char : Types.Char, TOK.Wchar : Types.Wchar, TOK.Dchar : Types.Dchar, TOK.Bool : Types.Bool,
261 TOK.Byte : Types.Byte, TOK.Ubyte : Types.Ubyte, TOK.Short : Types.Short, TOK.Ushort : Types.Ushort,
262 TOK.Int : Types.Int, TOK.Uint : Types.Uint, TOK.Long : Types.Long, TOK.Ulong : Types.Ulong,
263 TOK.Cent : Types.Cent, TOK.Ucent : Types.Ucent,
264 TOK.Float : Types.Float, TOK.Double : Types.Double, TOK.Real : Types.Real,
265 TOK.Ifloat : Types.Ifloat, TOK.Idouble : Types.Idouble, TOK.Ireal : Types.Ireal,
266 TOK.Cfloat : Types.Cfloat, TOK.Cdouble : Types.Cdouble, TOK.Creal : Types.Creal, TOK.Void : Types.Void
267 ];
268 assert(t.tok in tok2Type);
269 t.type = tok2Type[t.tok];
270 return t;
271 }
272
273 // Expression nodes:
274
275 E visit(ParenExpression e)
276 {
277 if (!e.type)
278 {
279 e.next = visitE(e.next);
280 e.type = e.next.type;
281 }
282 return e;
283 }
284
285 E visit(CommaExpression e)
286 {
287 if (!e.type)
288 {
289 e.lhs = visitE(e.lhs);
290 e.rhs = visitE(e.rhs);
291 e.type = e.rhs.type;
292 }
293 return e;
294 }
295
296 E visit(OrOrExpression)
297 { return null; }
298
299 E visit(AndAndExpression)
300 { return null; }
301
302 E visit(SpecialTokenExpression e)
303 {
304 if (e.type)
305 return e.value;
306 switch (e.specialToken.kind)
307 {
308 case TOK.LINE, TOK.VERSION:
309 e.value = new IntExpression(e.specialToken.uint_, Types.Uint);
310 break;
311 case TOK.FILE, TOK.DATE, TOK.TIME, TOK.TIMESTAMP, TOK.VENDOR:
312 e.value = new StringExpression(e.specialToken.str);
313 break;
314 default:
315 assert(0);
316 }
317 e.type = e.value.type;
318 return e.value;
319 }
320
321 E visit(DollarExpression e)
322 {
323 if (e.type)
324 return e;
325 e.type = Types.Size_t;
326 // if (!inArraySubscript)
327 // error("$ can only be in an array subscript.");
328 return e;
329 }
330
331 E visit(NullExpression e)
332 {
333 if (!e.type)
334 e.type = Types.Void_ptr;
335 return e;
336 }
337
338 E visit(BoolExpression e)
339 {
340 if (e.type)
341 return e;
342 e.value = new IntExpression(e.toBool(), Types.Bool);
343 e.type = Types.Bool;
344 return e;
345 }
346
347 E visit(IntExpression e)
348 {
349 if (e.type)
350 return e;
351
352 if (e.number & 0x8000_0000_0000_0000)
353 e.type = Types.Ulong; // 0xFFFF_FFFF_FFFF_FFFF
354 else if (e.number & 0xFFFF_FFFF_0000_0000)
355 e.type = Types.Long; // 0x7FFF_FFFF_FFFF_FFFF
356 else if (e.number & 0x8000_0000)
357 e.type = Types.Uint; // 0xFFFF_FFFF
358 else
359 e.type = Types.Int; // 0x7FFF_FFFF
360 return e;
361 }
362
363 E visit(RealExpression e)
364 {
365 if (!e.type)
366 e.type = Types.Double;
367 return e;
368 }
369
370 E visit(ComplexExpression e)
371 {
372 if (!e.type)
373 e.type = Types.Cdouble;
374 return e;
375 }
376
377 E visit(CharExpression e)
378 {
379 if (e.type)
380 return e;
381 if (e.character <= 0xFF)
382 e.type = Types.Char;
383 else if (e.character <= 0xFFFF)
384 e.type = Types.Wchar;
385 else
386 e.type = Types.Dchar;
387 return e;
388 }
389
390 E visit(StringExpression e)
391 {
392 return e;
393 }
394
395 E visit(MixinExpression me)
396 {
397 if (me.type)
398 return me.expr;
399 me.expr = visitE(me.expr);
400 auto expr = interpret(me.expr);
401 if (expr is Interpreter.NAR)
402 return me;
403 auto stringExpr = expr.Is!(StringExpression);
404 if (stringExpr is null)
405 error(me.begin, MSG.MixinArgumentMustBeString);
406 else
407 {
408 auto loc = me.begin.getErrorLocation();
409 auto filePath = loc.filePath;
410 auto sourceText = new SourceText(filePath, stringExpr.getString());
411 auto parser = new Parser(sourceText, modul.infoMan);
412 expr = parser.start2();
413 expr = visitE(expr); // Check expression.
414 }
415 me.expr = expr;
416 me.type = expr.type;
417 return me.expr;
418 }
419
420 E visit(ImportExpression ie)
421 {
422 if (ie.type)
423 return ie.expr;
424 ie.expr = visitE(ie.expr);
425 auto expr = interpret(ie.expr);
426 if (expr is Interpreter.NAR)
427 return ie;
428 auto stringExpr = expr.Is!(StringExpression);
429 //if (stringExpr is null)
430 // error(me.begin, MSG.ImportArgumentMustBeString);
431 // TODO: load file
432 //ie.expr = new StringExpression(loadImportFile(stringExpr.getString()));
433 return ie.expr;
434 }
435 }
436 }