1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity low)
4 /// Description: This module is here for testing
5 /// a different algorithm to do semantic analysis
6 /// compared to SemanticPass1 and SemanticPass2!
7 module dil.semantic.Passes;
8 
9 import dil.ast.DefaultVisitor,
10        dil.ast.Node,
11        dil.ast.Declarations,
12        dil.ast.Expressions,
13        dil.ast.Statements,
14        dil.ast.Types,
15        dil.ast.Parameters;
16 import dil.lexer.IdTable;
17 import dil.parser.Parser;
18 import dil.semantic.Symbol,
19        dil.semantic.Symbols,
20        dil.semantic.Types,
21        dil.semantic.Scope,
22        dil.semantic.Module,
23        dil.semantic.Analysis;
24 import dil.code.Interpreter;
25 import dil.i18n.Messages;
26 import dil.Compilation,
27        dil.SourceText,
28        dil.Diagnostics,
29        dil.Enums;
30 import common;
31 
32 /// Some handy aliases.
33 private alias D = Declaration;
34 private alias E = Expression; /// ditto
35 private alias S = Statement; /// ditto
36 private alias T = TypeNode; /// ditto
37 private alias P = Parameter; /// ditto
38 private alias N = Node; /// ditto
39 
40 /// A Scope class with added semantic information.
41 /// (May be merged together with class Scope in the future.)
42 class SemanticScope
43 {
44   Scope scop; /// The current basic scope.
45   Module modul; /// The module to be semantically checked.
46 
47   /// Constructs a SemanticScope object.
48   /// Params:
49   ///   modul = The module to be processed.
50   this(Module modul)
51   {
52     this.modul = modul;
53     this.scop = new Scope(null, modul);
54   }
55 
56   /// Returns the ScopeSymbol of this scope (class/function/etc.)
57   ScopeSymbol symbol() @property
58   {
59     return scop.symbol;
60   }
61 
62   /// Returns true if this is the module scope.
63   bool isModuleScope() @property
64   {
65     return scop.symbol.isModule();
66   }
67 
68   void enter(ScopeSymbol s)
69   {
70     scop = scop.enter(s);
71   }
72 
73   void exit()
74   {
75     scop = scop.exit();
76   }
77 
78   /// Inserts a symbol into the current scope.
79   void insert(Symbol symbol)
80   {
81     insert(symbol, symbol.name);
82   }
83 
84   /// Inserts a symbol into the current scope.
85   void insert(Symbol symbol, Identifier* name)
86   {
87     auto symX = scop.symbol.lookup(name);
88     if (symX)
89       reportSymbolConflict(symbol, symX, name);
90     else
91       scop.symbol.insert(symbol, name);
92     // Set the current scope symbol as the parent.
93     symbol.parent = scop.symbol;
94   }
95 
96   /// Inserts a symbol into scopeSym.
97   void insert(Symbol symbol, ScopeSymbol scopeSym)
98   {
99     auto symX = scopeSym.lookup(symbol.name);
100     if (symX)
101       reportSymbolConflict(symbol, symX, symbol.name);
102     else
103       scopeSym.insert(symbol, symbol.name);
104     // Set the current scope symbol as the parent.
105     symbol.parent = scopeSym;
106   }
107 
108   /// Inserts a symbol, overloading on the name, into the current scope.
109   void insertOverload(Symbol sym)
110   {
111     auto name = sym.name;
112     auto sym2 = scop.symbol.lookup(name);
113     if (sym2)
114     {
115       if (sym2.isOverloadSet)
116         sym2.to!(OverloadSet).add(sym);
117       else
118         reportSymbolConflict(sym, sym2, name);
119     }
120     else
121       // Create a new overload set.
122       scop.symbol.insert(new OverloadSet(name, sym.loc), name);
123     // Set the current scope symbol as the parent.
124     sym.parent = scop.symbol;
125   }
126 
127   /// Reports an error: new symbol s1 conflicts with existing symbol s2.
128   void reportSymbolConflict(Symbol s1, Symbol s2, Identifier* name)
129   {
130     auto loc = s2.loc.t.getErrorLocation(modul.filePath());
131     error(modul, s1.loc.t, MID.DeclConflictsWithDecl, name.str, loc.repr());
132   }
133 
134   /// Error messages are reported for undefined identifiers if true.
135   bool reportUndefinedIds;
136   /// Incremented when an undefined identifier was found.
137   uint undefinedIdsCount;
138   /// The symbol that must be ignored and skipped during a symbol search.
139   Symbol ignoreSymbol;
140   /// The current scope symbol to use for looking up identifiers.
141   ///
142   /// E.g.:
143   /// ---
144   /// / // * "object" is looked up in the current scope.
145   /// / // * idScope is set if "object" is a ScopeSymbol.
146   /// / // * "method" will be looked up in idScope.
147   /// object.method();
148   /// / // * "dil" is looked up in the current scope
149   /// / // * idScope is set if "dil" is a ScopeSymbol.
150   /// / // * "ast" will be looked up in idScope.
151   /// / // * idScope is set if "ast" is a ScopeSymbol.
152   /// / // * etc.
153   /// dil.ast.Node.Node node;
154   /// ---
155   ScopeSymbol idScope;
156 
157   /// The root of the Identifier tree.
158   Node rootIdNode;
159 
160   /// This object is assigned to idScope when a symbol lookup
161   /// returned no valid symbol.
162   static ScopeSymbol emptyIdScope;
163   static this()
164   {
165     emptyIdScope = new ScopeSymbol();
166   }
167 
168   // Sets a new idScope symbol.
169   void setIdScope(Symbol symbol)
170   {
171     if (symbol) {
172       if (auto scopSymbol = cast(ScopeSymbol)symbol)
173         idScope = scopSymbol;
174     }
175     else
176       idScope = emptyIdScope;
177   }
178 
179   /// Searches for a symbol.
180   Symbol search(Token* idTok)
181   {
182     assert(idTok.kind == TOK.Identifier);
183     auto id = idTok.ident;
184     Symbol symbol;
185 
186     if (idScope is null)
187       // Search in the table of another symbol.
188       symbol = ignoreSymbol ?
189                scop.search(id, ignoreSymbol) :
190                scop.search(id);
191     else
192       // Search: symbol.id
193       symbol = idScope.lookup(id);
194 
195     if (!symbol)
196     {
197       if (reportUndefinedIds)
198         error(modul, idTok, MID.UndefinedIdentifier, id.str);
199       undefinedIdsCount++;
200     }
201 
202     return symbol;
203   }
204 }
205 
206 /// Common interface for semantic passes.
207 interface SemanticPass
208 {
209   void run();
210   void run(SemanticScope scop, Node node);
211 }
212 
213 /// The first pass only declares symbols and handles imports.
214 class FirstSemanticPass : DefaultVisitor2, SemanticPass
215 {
216   Module modul; /// The module to be analyzed.
217   SemanticScope scop; /// Which scope to use for this pass.
218   ImportDecl[] imports; /// Modules to be imported.
219   // Attributes:
220   LinkageType linkageType; /// Current linkage type.
221   Protection protection; /// Current protection attribute.
222   StorageClass storageClass; /// Current storage classes.
223   uint alignSize; /// Current align size.
224 
225 
226   /// Constructs a SemanticPass object.
227   /// Params:
228   ///   modul = The module to be processed.
229   this(Module modul)
230   {
231     this.alignSize = modul.cc.structAlign;
232     this.modul = modul;
233   }
234 
235   /// Runs the semantic pass on the module.
236   override void run()
237   {
238     modul.semanticPass = 1;
239     run(new SemanticScope(modul), modul.root);
240   }
241 
242   override void run(SemanticScope scop, Node node)
243   {
244     this.scop = scop;
245     visitN(node);
246   }
247 
248   /// Looks for special classes and stores them in a table.
249   /// May modify d.symbol and assign a SpecialClassSymbol to it.
250   void lookForSpecialClasses(ClassDecl d)
251   {
252     if (!scop.isModuleScope)
253       return; // Only consider top-level classes.
254     modul.cc.tables.classes.lookForSpecialClasses(modul, d,
255       (name, format, ...) => error(modul, _arguments, _argptr, format, name));
256   }
257 
258   /// Appends the AliasSymbol to a list of the current ScopeSymbol.
259   /// Reports an error if it doesn't support "alias this".
260   void insertAliasThis(AliasSymbol s)
261   {
262     if (auto as = cast(AggregateSymbol)scop.symbol)
263       as.aliases ~= s;
264     else if (auto ts = cast(TemplateSymbol)scop.symbol)
265       ts.aliases ~= s;
266     else
267       error(modul, s.loc.t, "‘alias this’ works only in classes/structs");
268   }
269 
270   /// Forwards to SemanticScope.
271   void enterScope(ScopeSymbol s)
272   {
273     scop.enter(s);
274   }
275   /// ditto
276   void exitScope()
277   {
278     scop.exit();
279   }
280   /// ditto
281   void insert(Symbol s)
282   {
283     scop.insert(s);
284   }
285   /// ditto
286   void insert(Symbol s, Identifier* name)
287   {
288     scop.insert(s, name);
289   }
290   /// ditto
291   void insert(Symbol s, ScopeSymbol ss)
292   {
293     scop.insert(s, ss);
294   }
295   /// ditto
296   void insertOverload(Symbol s)
297   {
298     scop.insertOverload(s);
299   }
300 
301   /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302   |                                Declarations                               |
303    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
304 
305 override
306 {
307   //alias visit = super.visit;
308 
309   void visit(CompoundDecl d)
310   {
311     foreach (decl; d.decls)
312       visitD(decl);
313   }
314 
315   void visit(IllegalDecl)
316   { assert(0, "semantic pass on invalid AST"); }
317 
318   // void visit(EmptyDecl ed)
319   // {}
320 
321   // void visit(ModuleDecl)
322   // {}
323 
324   void visit(ImportDecl d)
325   {
326     imports ~= d;
327   }
328 
329   void visit(AliasDecl d)
330   {
331     auto vd = d.vardecl.to!(VariablesDecl);
332     d.symbols = new AliasSymbol[vd.names.length];
333     // Insert alias symbols in this declaration into the symbol table.
334     foreach (i, name; vd.names)
335       insert(d.symbols[i] = new AliasSymbol(name.ident, SLoc(name, d)));
336   }
337 
338   void visit(AliasesDecl d)
339   {
340     d.symbols = new AliasSymbol[d.idents.length];
341     // Insert alias symbols in this declaration into the symbol table.
342     foreach (i, name; d.idents)
343     {
344       auto s = d.symbols[i] = new AliasSymbol(name.ident, SLoc(name, d));
345       if (name.ident is Keyword.This)
346         insertAliasThis(s);
347       else
348         insert(s);
349     }
350   }
351 
352   void visit(AliasThisDecl d)
353   {
354     insertAliasThis(d.symbol = new AliasSymbol(d.name.ident, SLoc(d.name, d)));
355   }
356 
357   void visit(TypedefDecl d)
358   {
359     auto vd = d.vardecl.to!(VariablesDecl);
360     d.symbols = new TypedefSymbol[vd.names.length];
361     // Insert typedef symbols in this declaration into the symbol table.
362     foreach (i, name; vd.names)
363       insert(d.symbols[i] = new TypedefSymbol(name.ident, SLoc(name, d)));
364   }
365 
366   void visit(EnumDecl d)
367   {
368     if (d.symbol)
369       return;
370     // Create the symbol.
371     d.symbol = new EnumSymbol(d.nameId, SLoc(d.name ? d.name : d.begin, d));
372     bool isAnonymous = d.symbol.isAnonymous;
373     if (isAnonymous)
374       d.symbol.name = modul.cc.tables.idents.genAnonEnumID();
375     insert(d.symbol);
376     // Visit members.
377     auto parentScopeSymbol = scop.symbol;
378     auto enumSymbol = d.symbol;
379     enterScope(d.symbol);
380     // Declare members.
381     foreach (member; d.members)
382     {
383       visitD(member);
384       if (isAnonymous) // Also insert into parent scope if enum is anonymous.
385         insert(member.symbol, parentScopeSymbol);
386       member.symbol.type = enumSymbol.type; // Assign TypeEnum.
387     }
388     exitScope();
389   }
390 
391   void visit(EnumMemberDecl d)
392   {
393     d.symbol = new EnumMemberSymbol(
394       d.name.ident, protection, storageClass, linkageType, SLoc(d.name, d));
395     insert(d.symbol);
396   }
397 
398   void visit(ClassDecl d)
399   {
400     if (d.symbol)
401       return;
402     // Create the symbol.
403     d.symbol = new ClassSymbol(d.nameId, SLoc(d.name, d));
404     lookForSpecialClasses(d);
405     // Insert into current scope.
406     insert(d.symbol);
407     enterScope(d.symbol);
408     // Continue semantic analysis.
409     d.decls && visitD(d.decls);
410     exitScope();
411   }
412 
413   void visit(InterfaceDecl d)
414   {
415     if (d.symbol)
416       return;
417     // Create the symbol.
418     d.symbol = new InterfaceSymbol(d.nameId, SLoc(d.name, d));
419     // Insert into current scope.
420     insert(d.symbol);
421     enterScope(d.symbol);
422       // Continue semantic analysis.
423       d.decls && visitD(d.decls);
424     exitScope();
425   }
426 
427   void visit(StructDecl d)
428   {
429     auto s = d.symbol;
430     if (s)
431       return;
432     // Create the symbol.
433     auto loc = SLoc(d.name ? d.name : d.begin, d);
434     s = d.symbol = new StructSymbol(d.nameId, loc);
435     if (s.isAnonymous)
436       s.name = modul.cc.tables.idents.genAnonStructID();
437     // Insert into current scope.
438     insert(s);
439     enterScope(s);
440       // Continue semantic analysis.
441       d.decls && visitD(d.decls);
442     exitScope();
443     if (s.isAnonymous)
444       // Insert members into parent scope as well.
445       foreach (member; s.members)
446         insert(member);
447   }
448 
449   void visit(UnionDecl d)
450   {
451     auto s = d.symbol;
452     if (s)
453       return;
454     // Create the symbol.
455     auto loc = SLoc(d.name ? d.name : d.begin, d);
456     s = d.symbol = new UnionSymbol(d.nameId, loc);
457     if (s.isAnonymous)
458       s.name = modul.cc.tables.idents.genAnonUnionID();
459     // Insert into current scope.
460     insert(s);
461     enterScope(s);
462       // Continue semantic analysis.
463       d.decls && visitD(d.decls);
464     exitScope();
465     if (s.isAnonymous)
466       // Insert members into parent scope as well.
467       foreach (member; s.members)
468         insert(member);
469   }
470 
471   void visit(ConstructorDecl d)
472   {
473     auto func = new FunctionSymbol(Ident.Ctor, SLoc(d.begin, d));
474     insertOverload(func);
475     enterScope(func);
476     visitN(d.funcBody);
477     exitScope();
478   }
479 
480   void visit(StaticCtorDecl d)
481   {
482     auto func = new FunctionSymbol(Ident.Ctor, SLoc(d.begin, d));
483     func.type = Types.Void_0Args_DFunc;
484     insertOverload(func);
485     enterScope(func);
486     visitN(d.funcBody);
487     exitScope();
488   }
489 
490   void visit(DestructorDecl d)
491   {
492     auto func = new FunctionSymbol(Ident.Dtor, SLoc(d.begin, d));
493     func.type = Types.Void_0Args_DFunc;
494     insertOverload(func);
495     enterScope(func);
496     visitN(d.funcBody);
497     exitScope();
498   }
499 
500   void visit(StaticDtorDecl d)
501   {
502     auto func = new FunctionSymbol(Ident.Dtor, SLoc(d.begin, d));
503     func.type = Types.Void_0Args_DFunc;
504     insertOverload(func);
505     enterScope(func);
506     visitN(d.funcBody);
507     exitScope();
508   }
509 
510   void visit(FunctionDecl d)
511   {
512     auto func = new FunctionSymbol(d.name.ident, SLoc(d.name, d));
513     insertOverload(func);
514     enterScope(func);
515     visitN(d.funcBody);
516     exitScope();
517   }
518 
519   void visit(VariablesDecl vd)
520   { // Error if we are in an interface.
521     if (scop.symbol.isInterface &&
522         !(vd.isStatic || vd.isConst || vd.isManifest))
523       return error(modul, vd, MID.InterfaceCantHaveVariables);
524     // Insert variable symbols in this declaration into the symbol table.
525     vd.variables = new VariableSymbol[vd.names.length];
526     foreach (i, name; vd.names)
527     {
528       auto variable = new VariableSymbol(name.ident, protection, storageClass,
529         linkageType, SLoc(name, vd));
530       variable.value = vd.inits[i];
531       vd.variables[i] = variable;
532       insert(variable);
533     }
534   }
535 
536   void visit(InvariantDecl d)
537   {
538     auto func = new FunctionSymbol(Ident.InvariantFn, SLoc(d.begin, d));
539     insert(func);
540     enterScope(func);
541     visitN(d.funcBody);
542     exitScope();
543   }
544 
545   void visit(UnittestDecl d)
546   {
547     if (!modul.cc.unittestBuild)
548       return;
549     // TODO: generate anonymous unittest id?
550     auto func = new FunctionSymbol(Ident.UnittestFn, SLoc(d.begin, d));
551     func.type = Types.Void_0Args_DFunc;
552     insertOverload(func);
553     enterScope(func);
554     visitN(d.funcBody);
555     exitScope();
556   }
557 
558   void visit(DebugDecl d)
559   {
560     if (d.isSpecification)
561     { // debug = Id | Int
562       if (!scop.isModuleScope)
563         error(modul, d, MID.DebugSpecModuleLevel, d.spec.text);
564       else if (d.spec.kind == TOK.Identifier)
565         modul.cc.addDebugId(d.spec.ident.str);
566       else
567         modul.cc.debugLevel = d.spec.uint_;
568     }
569     else
570     { // debug ( Condition )
571       if (debugBranchChoice(d.cond, modul.cc))
572         d.compiledDecls = d.decls;
573       else
574         d.compiledDecls = d.elseDecls;
575       d.compiledDecls && visitD(d.compiledDecls);
576     }
577   }
578 
579   void visit(VersionDecl d)
580   {
581     if (d.isSpecification)
582     { // version = Id | Int
583       if (!scop.isModuleScope)
584         error(modul, d, MID.VersionSpecModuleLevel, d.spec.text);
585       else if (d.spec.kind == TOK.Identifier)
586         modul.cc.addVersionId(d.spec.ident.str);
587       else
588         modul.cc.versionLevel = d.spec.uint_;
589     }
590     else
591     { // version ( Condition )
592       if (versionBranchChoice(d.cond, modul.cc))
593         d.compiledDecls = d.decls;
594       else
595         d.compiledDecls = d.elseDecls;
596       d.compiledDecls && visitD(d.compiledDecls);
597     }
598   }
599 
600   void visit(TemplateDecl d)
601   {
602     if (d.symbol)
603       return;
604     // Create the symbol.
605     d.symbol = new TemplateSymbol(d.nameId, SLoc(d.name, d));
606     // Insert into current scope.
607     insertOverload(d.symbol);
608     enterScope(d.symbol);
609     // Declare template parameters.
610     visitN(d.tparams);
611     // Continue with the declarations inside.
612     d.decls && visitD(d.decls);
613     exitScope();
614   }
615 
616   void visit(NewDecl d)
617   {
618     auto func = new FunctionSymbol(Ident.NewFn, SLoc(d.begin, d));
619     insert(func);
620     enterScope(func);
621     visitN(d.funcBody);
622     exitScope();
623   }
624 
625   void visit(DeleteDecl d)
626   {
627     auto func = new FunctionSymbol(Ident.DeleteFn, SLoc(d.begin, d));
628     insert(func);
629     enterScope(func);
630     visitN(d.funcBody);
631     exitScope();
632   }
633 
634   // Attributes:
635 
636   void visit(ProtectionDecl d)
637   {
638     auto saved = protection; // Save.
639     protection = d.prot; // Set.
640     visitD(d.decls);
641     protection = saved; // Restore.
642   }
643 
644   void visit(StorageClassDecl d)
645   {
646     auto saved = storageClass; // Save.
647     storageClass = d.stc; // Set.
648     visitD(d.decls);
649     storageClass = saved; // Restore.
650   }
651 
652   void visit(LinkageDecl d)
653   {
654     auto saved = linkageType; // Save.
655     linkageType = d.linkageType; // Set.
656     visitD(d.decls);
657     linkageType = saved; // Restore.
658   }
659 
660   void visit(AlignDecl d)
661   {
662     auto saved = alignSize; // Save.
663     alignSize = d.size; // Set.
664     visitD(d.decls);
665     alignSize = saved; // Restore.
666   }
667 } // override
668 }
669 
670 
671 /// The second pass resolves variable types, base classes,
672 /// evaluates static ifs/asserts etc.
673 class SecondSemanticPass : DefaultVisitor, SemanticPass
674 {
675   Module modul;
676   SemanticScope scop;
677   Interpreter ip; /// Used to evaluate expressions.
678 
679   this(Module modul)
680   {
681     this.modul = modul;
682     this.ip = new Interpreter(modul.cc.diag);
683   }
684 
685   /// Runs the semantic pass on the module.
686   override void run()
687   {
688     modul.semanticPass = 2;
689     run(new SemanticScope(modul), modul.root);
690   }
691 
692   override void run(SemanticScope scop, Node node)
693   {
694     this.scop = scop;
695     visitN(node);
696   }
697 
698   Symbol search(Token* idTok)
699   {
700     return scop.search(idTok);
701   }
702 
703 override
704 {
705   D visit(CompoundDecl d)
706   {
707     foreach (decl; d.decls)
708       visitD(decl);
709     return d;
710   }
711 
712   D visit(AliasDecl d)
713   {
714     return d;
715   }
716 
717   D visit(TypedefDecl d)
718   {
719     return d;
720   }
721 
722   D visit(EnumDecl d)
723   {
724     return d;
725   }
726 
727   D visit(EnumMemberDecl d)
728   {
729     return d;
730   }
731 
732   D visit(ClassDecl d)
733   {
734     return d;
735   }
736 
737   D visit(InterfaceDecl d)
738   {
739     return d;
740   }
741 
742   D visit(StructDecl d)
743   {
744     return d;
745   }
746 
747   D visit(UnionDecl d)
748   {
749     return d;
750   }
751 
752   D visit(ConstructorDecl d)
753   {
754     return d;
755   }
756 
757   D visit(StaticCtorDecl d)
758   {
759     return d;
760   }
761 
762   D visit(DestructorDecl d)
763   {
764     return d;
765   }
766 
767   D visit(StaticDtorDecl d)
768   {
769     return d;
770   }
771 
772   D visit(FunctionDecl d)
773   {
774     return d;
775   }
776 
777   D visit(VariablesDecl d)
778   {
779     return d;
780   }
781 
782   D visit(InvariantDecl d)
783   {
784     return d;
785   }
786 
787   D visit(UnittestDecl d)
788   {
789     return d;
790   }
791 
792   D visit(TemplateDecl d)
793   {
794     return d;
795   }
796 
797   D visit(NewDecl d)
798   {
799     return d;
800   }
801 
802   D visit(DeleteDecl d)
803   {
804     return d;
805   }
806 
807   D visit(StaticAssertDecl d)
808   {
809     d.condition = visitE(d.condition);
810     if (d.condition.isChecked())
811     {
812       auto r = ip.eval(d.condition);
813       if (r !is Interpreter.NAR && ip.EM.isBool(r) == 0)
814       {
815         cstring errorMsg = "static assert is false";
816         if (d.message)
817         {
818           d.message = visitE(d.message);
819           r = ip.eval(d.message);
820           auto se = r.Is!(StringExpr);
821           if (se) // TODO: allow non-string expressions?
822             errorMsg = se.getString();
823         }
824         error(modul, d, errorMsg);
825       }
826     }
827     return d;
828   }
829 
830   D visit(StaticIfDecl d)
831   {
832     // Eval condition
833     return d;
834   }
835 
836   D visit(MixinDecl d)
837   {
838     // Eval d.argument
839     return d;
840   }
841 
842   D visit(PragmaDecl d)
843   {
844     if (d.name.ident is Ident.msg)
845     { // Write arguments to standard output.
846       foreach (arg; d.args)
847       {
848         cstring msg;
849         arg = visitE(arg);
850         auto r = ip.eval(arg);
851         if (auto se = r.Is!(StringExpr))
852           msg = se.getString();
853         else
854           msg = "FIXME: can't print AST yet"; // = astPrinter.print(r)
855         Stdout(msg);
856       }
857     }
858     else
859     {
860       pragmaSemantic(scop.scop, d.begin, d.name.ident, d.args);
861       visitD(d.decls);
862     }
863     return d;
864   }
865 } // override
866 
867   /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
868   |                                 Statements                                |
869    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
870 
871   /// The current surrounding, breakable statement.
872   S breakableStmt;
873 
874   S setBS(S s)
875   {
876     auto old = breakableStmt;
877     breakableStmt = s;
878     return old;
879   }
880 
881   void restoreBS(S s)
882   {
883     breakableStmt = s;
884   }
885 
886 override
887 {
888   S visit(CompoundStmt s)
889   {
890     foreach (stmnt; s.stmnts)
891       visitS(stmnt);
892     return s;
893   }
894 
895   S visit(IllegalStmt)
896   { assert(0, "semantic pass on invalid AST"); return null; }
897 
898   S visit(EmptyStmt s)
899   {
900     return s;
901   }
902 
903   S visit(FuncBodyStmt s)
904   {
905     return s;
906   }
907 
908   S visit(ScopeStmt s)
909   {
910 //     enterScope();
911     visitS(s.stmnt);
912 //     exitScope();
913     return s;
914   }
915 
916   S visit(LabeledStmt s)
917   {
918     return s;
919   }
920 
921   S visit(ExpressionStmt s)
922   {
923     return s;
924   }
925 
926   S visit(DeclarationStmt s)
927   {
928     return s;
929   }
930 
931   S visit(IfStmt s)
932   {
933     return s;
934   }
935 
936   S visit(WhileStmt s)
937   {
938     auto saved = setBS(s);
939     // TODO:
940     restoreBS(saved);
941     return s;
942   }
943 
944   S visit(DoWhileStmt s)
945   {
946     auto saved = setBS(s);
947     // TODO:
948     restoreBS(saved);
949     return s;
950   }
951 
952   S visit(ForStmt s)
953   {
954     auto saved = setBS(s);
955     // TODO:
956     restoreBS(saved);
957     return s;
958   }
959 
960   S visit(ForeachStmt s)
961   {
962     auto saved = setBS(s);
963     // TODO:
964     // find overload opApply or opApplyReverse.
965     restoreBS(saved);
966     return s;
967   }
968 
969   S visit(SwitchStmt s)
970   {
971     auto saved = setBS(s);
972     // TODO:
973     restoreBS(saved);
974     return s;
975   }
976 
977   S visit(CaseStmt s)
978   {
979     auto saved = setBS(s);
980     // TODO:
981     restoreBS(saved);
982     return s;
983   }
984 
985   S visit(DefaultStmt s)
986   {
987     auto saved = setBS(s);
988     // TODO:
989     restoreBS(saved);
990     return s;
991   }
992 
993   S visit(ContinueStmt s)
994   {
995     return s;
996   }
997 
998   S visit(BreakStmt s)
999   {
1000     return s;
1001   }
1002 
1003   S visit(ReturnStmt s)
1004   {
1005     return s;
1006   }
1007 
1008   S visit(GotoStmt s)
1009   {
1010     return s;
1011   }
1012 
1013   S visit(WithStmt s)
1014   {
1015     return s;
1016   }
1017 
1018   S visit(SynchronizedStmt s)
1019   {
1020     return s;
1021   }
1022 
1023   S visit(TryStmt s)
1024   {
1025     return s;
1026   }
1027 
1028   S visit(CatchStmt s)
1029   {
1030     return s;
1031   }
1032 
1033   S visit(FinallyStmt s)
1034   {
1035     return s;
1036   }
1037 
1038   S visit(ScopeGuardStmt s)
1039   {
1040     return s;
1041   }
1042 
1043   S visit(ThrowStmt s)
1044   {
1045     return s;
1046   }
1047 
1048   S visit(VolatileStmt s)
1049   {
1050     return s;
1051   }
1052 
1053   S visit(AsmBlockStmt s)
1054   {
1055     foreach (stmnt; s.statements.stmnts)
1056       visitS(stmnt);
1057     return s;
1058   }
1059 
1060   S visit(AsmStmt s)
1061   {
1062     return s;
1063   }
1064 
1065   S visit(AsmAlignStmt s)
1066   {
1067     return s;
1068   }
1069 
1070   S visit(IllegalAsmStmt)
1071   { assert(0, "semantic pass on invalid AST"); return null; }
1072 
1073   S visit(PragmaStmt s)
1074   {
1075     return s;
1076   }
1077 
1078   S visit(MixinStmt s)
1079   {
1080     return s;
1081   }
1082 
1083   S visit(StaticIfStmt s)
1084   {
1085     return s;
1086   }
1087 
1088   S visit(StaticAssertStmt s)
1089   {
1090     return s;
1091   }
1092 
1093   S visit(DebugStmt s)
1094   {
1095     return s;
1096   }
1097 
1098   S visit(VersionStmt s)
1099   {
1100     return s;
1101   }
1102 } // override
1103 
1104   /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1105   |                                Expressions                                |
1106    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1107 
1108   /// Determines whether to issue an error when a symbol couldn't be found.
1109   bool errorOnUndefinedSymbol;
1110   //bool errorOnUnknownSymbol;
1111 
1112   /// Reports an error if the type of e is not bool.
1113   void errorIfBool(Expression e)
1114   {
1115     assert(e.type !is null);
1116     if (e.type.isBaseBool())
1117       error(modul, e, "the operation is undefined for type bool");
1118   }
1119 
1120   /// Reports an error if e has no boolean result.
1121   void errorIfNonBool(Expression e)
1122   {
1123     assert(e.type !is null);
1124     switch (e.kind)
1125     {
1126     case NodeKind.DeleteExpr:
1127       error(modul, e, "the delete operator has no boolean result");
1128       break;
1129     case NodeKind.AssignExpr:
1130       error(modul, e, "the assignment operator '=' has no boolean result");
1131       break;
1132     case NodeKind.CondExpr:
1133       auto cond = e.to!(CondExpr);
1134       errorIfNonBool(cond.lhs);
1135       errorIfNonBool(cond.rhs);
1136       break;
1137     default:
1138       if (!e.type.isBaseScalar()) // Only scalar types can be bool.
1139         error(modul, e, "expression has no boolean result");
1140     }
1141   }
1142 
1143   /// Returns a call expression if 'e' overrides
1144   /// an operatorwith the name 'id'.
1145   /// Params:
1146   ///   e = The binary expression to be checked.
1147   ///   id = The name of the overload function.
1148   Expression findOverload(UnaryExpr e, Identifier* id)
1149   {
1150     // TODO:
1151     // check e for struct or class
1152     // search for function named id
1153     // return call expression: e.opXYZ()
1154     return null;
1155   }
1156 
1157   /// Returns a call expression if 'e' overrides
1158   /// an operator with the name 'id' or 'id_r'.
1159   /// Params:
1160   ///   e = The binary expression to be checked.
1161   ///   id = The name of the overload function.
1162   ///   id_r = The name of the reverse overload function.
1163   Expression findOverload(BinaryExpr e, Identifier* id, Identifier* id_r)
1164   {
1165     // TODO:
1166     return null;
1167   }
1168 
1169   /// Visit the operands of a binary operator.
1170   void visitBinary(BinaryExpr e)
1171   {
1172     e.lhs = visitE(e.lhs);
1173     e.rhs = visitE(e.rhs);
1174   }
1175 
1176 override
1177 {
1178   E visit(IllegalExpr)
1179   { assert(0, "semantic pass on invalid AST"); return null; }
1180 
1181   E visit(CondExpr e)
1182   {
1183     return e;
1184   }
1185 
1186   E visit(CommaExpr e)
1187   {
1188     if (!e.isChecked)
1189     {
1190       e.lhs = visitE(e.lhs);
1191       e.rhs = visitE(e.rhs);
1192       e.type = e.rhs.type; // Take the type of the right hand side.
1193     }
1194     return e;
1195   }
1196 
1197   E visit(OrOrExpr e)
1198   {
1199     if (!e.isChecked)
1200     {
1201       e.lhs = visitE(e.lhs);
1202       errorIfNonBool(e.lhs); // Left operand must be bool.
1203       e.rhs = visitE(e.rhs);
1204       if (e.rhs.type is Types.Void)
1205         e.type = Types.Void; // According to spec.
1206       else
1207         (e.type = Types.Bool), // Otherwise type is bool and
1208         errorIfNonBool(e.rhs); // right operand must be bool.
1209     }
1210     return e;
1211   }
1212 
1213   E visit(AndAndExpr e)
1214   {
1215     if (!e.isChecked)
1216     {
1217       e.lhs = visitE(e.lhs);
1218       errorIfNonBool(e.lhs); // Left operand must be bool.
1219       e.rhs = visitE(e.rhs);
1220       if (e.rhs.type is Types.Void)
1221         e.type = Types.Void; // According to spec.
1222       else
1223         (e.type = Types.Bool), // Otherwise type is bool and
1224         errorIfNonBool(e.rhs); // right operand must be bool.
1225     }
1226     return e;
1227   }
1228 
1229   E visit(OrExpr e)
1230   {
1231     if (auto o = findOverload(e, Ident.opOr, Ident.opOr_r))
1232       return o;
1233     return e;
1234   }
1235 
1236   E visit(XorExpr e)
1237   {
1238     if (auto o = findOverload(e, Ident.opXor, Ident.opXor_r))
1239       return o;
1240     return e;
1241   }
1242 
1243   E visit(AndExpr e)
1244   {
1245     if (auto o = findOverload(e, Ident.opAnd, Ident.opAnd_r))
1246       return o;
1247     return e;
1248   }
1249 
1250   E visit(EqualExpr e)
1251   {
1252     visitBinary(e);
1253     if (auto o = findOverload(e, Ident.opEquals, null))
1254       return o;
1255     // TODO:
1256     e.type = Types.Bool;
1257     return e;
1258   }
1259 
1260   E visit(IdentityExpr e)
1261   {
1262     return e;
1263   }
1264 
1265   E visit(RelExpr e)
1266   {
1267     visitBinary(e);
1268     if (auto o = findOverload(e, Ident.opCmp, null))
1269       return o;
1270     // TODO: check for more errors?
1271     if (e.lhs.type.isBaseComplex() || e.rhs.type.isBaseComplex())
1272     {
1273       auto whichOp = e.lhs.type.isBaseComplex() ? e.lhs.begin : e.rhs.begin;
1274       error(modul, whichOp,
1275         "the operator '{}' is undefined for complex numbers", e.optok.text);
1276     }
1277     e.type = Types.Bool;
1278     return e;
1279   }
1280 
1281   E visit(InExpr e)
1282   {
1283     visitBinary(e);
1284     if (auto o = findOverload(e, Ident.opIn, Ident.opIn_r))
1285       return o;
1286     if (!e.rhs.type.baseType().isAArray())
1287     {
1288       error(modul, e.rhs,
1289         "right operand of 'in' operator must be an associative array");
1290       // Don't use Types.Error. Cascading error msgs are irritating.
1291       e.type = e.rhs.type;
1292     }
1293     else
1294       // Result type is pointer to element type of AA.
1295       e.type = e.rhs.type.next.ptrTo();
1296     return e;
1297   }
1298 
1299   E visit(LShiftExpr e)
1300   {
1301     if (auto o = findOverload(e, Ident.opShl, Ident.opShl_r))
1302       return o;
1303     return e;
1304   }
1305 
1306   E visit(RShiftExpr e)
1307   {
1308     if (auto o = findOverload(e, Ident.opShr, Ident.opShr_r))
1309       return o;
1310     return e;
1311   }
1312 
1313   E visit(URShiftExpr e)
1314   {
1315     if (auto o = findOverload(e, Ident.opUShr, Ident.opUShr_r))
1316       return o;
1317     return e;
1318   }
1319 
1320   E visit(PlusExpr e)
1321   {
1322     if (auto o = findOverload(e, Ident.opAdd, Ident.opAdd_r))
1323       return o;
1324     return e;
1325   }
1326 
1327   E visit(MinusExpr e)
1328   {
1329     if (auto o = findOverload(e, Ident.opSub, Ident.opSub_r))
1330       return o;
1331     return e;
1332   }
1333 
1334   E visit(CatExpr e)
1335   {
1336     visitBinary(e);
1337     if (auto o = findOverload(e, Ident.opCat, Ident.opCat_r))
1338       return o;
1339     // Need to check the base types if they are arrays.
1340     // This will allow for concatenating typedef types:
1341     // typedef Handle[] Handles; Handles hlist; hlist ~ element;
1342     auto tl = e.lhs.type.baseType(),
1343          tr = e.rhs.type.baseType();
1344     if (tl.isDorSArray() || tr.isDorSArray())
1345     {
1346       // TODO:
1347       // e.type = ;
1348     }
1349     else
1350     {
1351       error(modul, e.optok,
1352         "concatenation operator '~' is undefined for: {} ~ {}", e.lhs, e.rhs);
1353       e.type = e.lhs.type; // Use Types.Error if e.lhs.type is not a good idea.
1354     }
1355     return e;
1356   }
1357 
1358   E visit(MulExpr e)
1359   {
1360     if (auto o = findOverload(e, Ident.opMul, Ident.opMul_r))
1361       return o;
1362     return e;
1363   }
1364 
1365   E visit(DivExpr e)
1366   {
1367     if (auto o = findOverload(e, Ident.opDiv, Ident.opDiv_r))
1368       return o;
1369     return e;
1370   }
1371 
1372   E visit(ModExpr e)
1373   {
1374     if (auto o = findOverload(e, Ident.opMod, Ident.opMod_r))
1375       return o;
1376     return e;
1377   }
1378 
1379   E visit(AssignExpr e)
1380   {
1381     if (auto o = findOverload(e, Ident.opAssign, null))
1382       return o;
1383     // TODO: also check for opIndexAssign and opSliceAssign.
1384     return e;
1385   }
1386 
1387   E visit(LShiftAssignExpr e)
1388   {
1389     if (auto o = findOverload(e, Ident.opShlAssign, null))
1390       return o;
1391     return e;
1392   }
1393 
1394   E visit(RShiftAssignExpr e)
1395   {
1396     if (auto o = findOverload(e, Ident.opShrAssign, null))
1397       return o;
1398     return e;
1399   }
1400 
1401   E visit(URShiftAssignExpr e)
1402   {
1403     if (auto o = findOverload(e, Ident.opUShrAssign, null))
1404       return o;
1405     return e;
1406   }
1407 
1408   E visit(OrAssignExpr e)
1409   {
1410     if (auto o = findOverload(e, Ident.opOrAssign, null))
1411       return o;
1412     return e;
1413   }
1414 
1415   E visit(AndAssignExpr e)
1416   {
1417     if (auto o = findOverload(e, Ident.opAndAssign, null))
1418       return o;
1419     return e;
1420   }
1421 
1422   E visit(PlusAssignExpr e)
1423   {
1424     if (auto o = findOverload(e, Ident.opAddAssign, null))
1425       return o;
1426     return e;
1427   }
1428 
1429   E visit(MinusAssignExpr e)
1430   {
1431     if (auto o = findOverload(e, Ident.opSubAssign, null))
1432       return o;
1433     return e;
1434   }
1435 
1436   E visit(DivAssignExpr e)
1437   {
1438     auto o = findOverload(e, Ident.opDivAssign, null);
1439     if (o)
1440       return o;
1441     return e;
1442   }
1443 
1444   E visit(MulAssignExpr e)
1445   {
1446     auto o = findOverload(e, Ident.opMulAssign, null);
1447     if (o)
1448       return o;
1449     return e;
1450   }
1451 
1452   E visit(ModAssignExpr e)
1453   {
1454     auto o = findOverload(e, Ident.opModAssign, null);
1455     if (o)
1456       return o;
1457     return e;
1458   }
1459 
1460   E visit(XorAssignExpr e)
1461   {
1462     auto o = findOverload(e, Ident.opXorAssign, null);
1463     if (o)
1464       return o;
1465     return e;
1466   }
1467 
1468   E visit(CatAssignExpr e)
1469   {
1470     auto o = findOverload(e, Ident.opCatAssign, null);
1471     if (o)
1472       return o;
1473     return e;
1474   }
1475 
1476   E visit(AddressExpr e)
1477   {
1478     if (e.isChecked)
1479       return e;
1480     e.una = visitE(e.una);
1481     e.type = e.una.type.ptrTo();
1482     return e;
1483   }
1484 
1485   E visit(PreIncrExpr e)
1486   {
1487     if (e.isChecked)
1488       return e;
1489     // TODO: rewrite to e+=1
1490     e.una = visitE(e.una);
1491     e.type = e.una.type;
1492     errorIfBool(e.una);
1493     return e;
1494   }
1495 
1496   E visit(PreDecrExpr e)
1497   {
1498     if (e.isChecked)
1499       return e;
1500     // TODO: rewrite to e-=1
1501     e.una = visitE(e.una);
1502     e.type = e.una.type;
1503     errorIfBool(e.una);
1504     return e;
1505   }
1506 
1507   E visit(PostIncrExpr e)
1508   {
1509     if (e.isChecked)
1510       return e;
1511     if (auto o = findOverload(e, Ident.opPostInc))
1512       return o;
1513     e.una = visitE(e.una);
1514     e.type = e.una.type;
1515     errorIfBool(e.una);
1516     return e;
1517   }
1518 
1519   E visit(PostDecrExpr e)
1520   {
1521     if (e.isChecked)
1522       return e;
1523     if (auto o = findOverload(e, Ident.opPostDec))
1524       return o;
1525     e.una = visitE(e.una);
1526     e.type = e.una.type;
1527     errorIfBool(e.una);
1528     return e;
1529   }
1530 
1531   E visit(DerefExpr e)
1532   {
1533     if (e.isChecked)
1534       return e;
1535   version(D2)
1536     if (auto o = findOverload(e, Ident.opStar))
1537       return o;
1538     e.una = visitE(e.una);
1539     e.type = e.una.type.next;
1540     if (!e.una.type.isPointer)
1541     {
1542       error(modul, e.una,
1543         "dereference operator '*x' not defined for expression of type '{}'",
1544         e.una.type.toString());
1545       e.type = Types.Error;
1546     }
1547     // TODO:
1548     // if (e.una.type.isVoid)
1549     //   error();
1550     return e;
1551   }
1552 
1553   E visit(SignExpr e)
1554   {
1555     if (e.isChecked)
1556       return e;
1557     if (auto o = findOverload(e, e.isNeg ? Ident.opNeg : Ident.opPos))
1558       return o;
1559     e.una = visitE(e.una);
1560     e.type = e.una.type;
1561     errorIfBool(e.una);
1562     return e;
1563   }
1564 
1565   E visit(NotExpr e)
1566   {
1567     if (e.isChecked)
1568       return e;
1569     e.una = visitE(e.una);
1570     e.type = Types.Bool;
1571     errorIfNonBool(e.una);
1572     return e;
1573   }
1574 
1575   E visit(CompExpr e)
1576   {
1577     if (e.isChecked)
1578       return e;
1579     if (auto o = findOverload(e, Ident.opCom))
1580       return o;
1581     e.una = visitE(e.una);
1582     e.type = e.una.type;
1583     if (e.type.isBaseFloating() || e.type.isBaseBool())
1584     {
1585       error(modul, e, "the operator '~x' is undefined for the type '{}'",
1586             e.type.toString());
1587       e.type = Types.Error;
1588     }
1589     return e;
1590   }
1591 
1592   E visit(CallExpr e)
1593   {
1594     if (auto o = findOverload(e, Ident.opCall))
1595       return o;
1596     return e;
1597   }
1598 
1599   E visit(NewExpr e)
1600   {
1601     return e;
1602   }
1603 
1604   E visit(NewClassExpr e)
1605   {
1606     return e;
1607   }
1608 
1609   E visit(DeleteExpr e)
1610   {
1611     return e;
1612   }
1613 
1614   E visit(CastExpr e)
1615   {
1616     if (auto o = findOverload(e, Ident.opCast))
1617       return o;
1618     return e;
1619   }
1620 
1621   E visit(IndexExpr e)
1622   {
1623     if (auto o = findOverload(e, Ident.opIndex))
1624       return o;
1625     return e;
1626   }
1627 
1628   E visit(SliceExpr e)
1629   {
1630     if (auto o = findOverload(e, Ident.opSlice))
1631       return o;
1632     return e;
1633   }
1634 
1635   E visit(ModuleScopeExpr e)
1636   {
1637     return e;
1638   }
1639 
1640   E visit(IdentifierExpr e)
1641   {
1642     if (e.isChecked)
1643       return e;
1644     debug(sema) Stdout.formatln("", e);
1645     e.symbol = search(e.name);
1646     return e;
1647   }
1648 
1649   E visit(TmplInstanceExpr e)
1650   {
1651     if (e.isChecked)
1652       return e;
1653     debug(sema) Stdout.formatln("", e);
1654     e.symbol = search(e.name);
1655     return e;
1656   }
1657 
1658   E visit(SpecialTokenExpr e)
1659   {
1660     if (e.isChecked)
1661       return e.value;
1662     switch (e.specialToken.ident.idKind)
1663     {
1664     case IDK.LINE, IDK.VERSION:
1665       e.value = new IntExpr(e.specialToken.uint_, Types.UInt32);
1666       break;
1667     case IDK.FILE, IDK.DATE, IDK.TIME, IDK.TIMESTAMP, IDK.VENDOR:
1668       e.value = new StringExpr(e.specialToken.strval.str);
1669       break;
1670     default:
1671       assert(0);
1672     }
1673     e.type = e.value.type;
1674     return e.value;
1675   }
1676 
1677   E visit(ThisExpr e)
1678   {
1679     return e;
1680   }
1681 
1682   E visit(SuperExpr e)
1683   {
1684     return e;
1685   }
1686 
1687   E visit(NullExpr e)
1688   {
1689     if (!e.isChecked)
1690       e.type = Types.Void_ptr;
1691     return e;
1692   }
1693 
1694   E visit(DollarExpr e)
1695   {
1696     if (e.isChecked)
1697       return e;
1698     e.type = modul.cc.tables.types.Size_t;
1699     // if (!inArraySubscript)
1700     //   error("$ can only be in an array subscript.");
1701     return e;
1702   }
1703 
1704   E visit(BoolExpr e)
1705   {
1706     assert(e.isChecked);
1707     return e.value;
1708   }
1709 
1710   E visit(IntExpr e)
1711   {
1712     if (e.isChecked)
1713       return e;
1714 
1715     if (e.number & 0x8000_0000_0000_0000)
1716       e.type = Types.UInt64; // 0xFFFF_FFFF_FFFF_FFFF
1717     else if (e.number & 0xFFFF_FFFF_0000_0000)
1718       e.type = Types.Int64; // 0x7FFF_FFFF_FFFF_FFFF
1719     else if (e.number & 0x8000_0000)
1720       e.type = Types.UInt32; // 0xFFFF_FFFF
1721     else
1722       e.type = Types.Int32; // 0x7FFF_FFFF
1723     return e;
1724   }
1725 
1726   E visit(FloatExpr e)
1727   {
1728     if (!e.isChecked)
1729       e.type = Types.Float64;
1730     return e;
1731   }
1732 
1733   E visit(ComplexExpr e)
1734   {
1735     if (!e.isChecked)
1736       e.type = Types.CFloat64;
1737     return e;
1738   }
1739 
1740   E visit(CharExpr e)
1741   {
1742     assert(e.isChecked);
1743     return e.value;
1744   }
1745 
1746   E visit(StringExpr e)
1747   {
1748     assert(e.isChecked);
1749     return e;
1750   }
1751 
1752   E visit(ArrayLiteralExpr e)
1753   {
1754     return e;
1755   }
1756 
1757   E visit(AArrayLiteralExpr e)
1758   {
1759     return e;
1760   }
1761 
1762   E visit(AssertExpr e)
1763   {
1764     return e;
1765   }
1766 
1767   E visit(MixinExpr e)
1768   {
1769     return e;
1770   }
1771 
1772   E visit(ImportExpr e)
1773   {
1774     return e;
1775   }
1776 
1777   E visit(TypeofExpr e)
1778   {
1779     return e;
1780   }
1781 
1782   E visit(TypeDotIdExpr e)
1783   {
1784     return e;
1785   }
1786 
1787   E visit(TypeidExpr e)
1788   {
1789     return e;
1790   }
1791 
1792   E visit(IsExpr e)
1793   {
1794     return e;
1795   }
1796 
1797   E visit(ParenExpr e)
1798   {
1799     if (!e.isChecked)
1800     {
1801       e.next = visitE(e.next);
1802       e.type = e.next.type;
1803     }
1804     return e;
1805   }
1806 
1807   E visit(FuncLiteralExpr e)
1808   {
1809     return e;
1810   }
1811 
1812   E visit(LambdaExpr e)
1813   {
1814     return e;
1815   }
1816 
1817   E visit(TraitsExpr e) // D2.0
1818   {
1819     return e;
1820   }
1821 
1822   E visit(VoidInitExpr e)
1823   {
1824     return e;
1825   }
1826 
1827   E visit(ArrayInitExpr e)
1828   {
1829     return e;
1830   }
1831 
1832   E visit(StructInitExpr e)
1833   {
1834     return e;
1835   }
1836 
1837   E visit(AsmTypeExpr e)
1838   {
1839     return e;
1840   }
1841 
1842   E visit(AsmOffsetExpr e)
1843   {
1844     return e;
1845   }
1846 
1847   E visit(AsmSegExpr e)
1848   {
1849     return e;
1850   }
1851 
1852   E visit(AsmPostBracketExpr e)
1853   {
1854     return e;
1855   }
1856 
1857   E visit(AsmBracketExpr e)
1858   {
1859     return e;
1860   }
1861 
1862   E visit(AsmLocalSizeExpr e)
1863   {
1864     return e;
1865   }
1866 
1867   E visit(AsmRegisterExpr e)
1868   {
1869     return e;
1870   }
1871 } // override
1872 
1873   /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1874   |                                   Types                                   |
1875    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1876 
1877 override
1878 {
1879   T visit(IllegalType)
1880   { assert(0, "semantic pass on invalid AST"); return null; }
1881 
1882   T visit(IntegralType t)
1883   {
1884     t.type = Types.fromTOK(t.tok);
1885     return t;
1886   }
1887 
1888   T visit(ModuleScopeType t)
1889   {
1890     return t;
1891   }
1892 
1893   T visit(IdentifierType t)
1894   {
1895     //auto idToken = t.begin;
1896     //auto symbol = search(idToken);
1897     // TODO: save symbol or its type in t.
1898     return t;
1899   }
1900 
1901   T visit(TypeofType t)
1902   {
1903     t.expr = visitE(t.expr);
1904     t.type = t.expr.type;
1905     return t;
1906   }
1907 
1908   T visit(TmplInstanceType t)
1909   {
1910     auto idToken = t.begin;
1911     auto symbol = search(idToken);
1912     // TODO: save symbol or its type in t.
1913     return t;
1914   }
1915 
1916   T visit(PointerType t)
1917   {
1918     t.type = visitT(t.next).type.ptrTo();
1919     return t;
1920   }
1921 
1922   T visit(ArrayType t)
1923   {
1924     auto baseType = visitT(t.next).type;
1925     if (t.isAssociative)
1926       t.type = baseType.arrayOf(visitT(t.assocType).type);
1927     else if (t.isDynamic)
1928       t.type = baseType.arrayOf();
1929     else if (t.isStatic)
1930     {}
1931     else
1932       assert(t.isSlice);
1933     return t;
1934   }
1935 
1936   T visit(FunctionType t)
1937   {
1938     return t;
1939   }
1940 
1941   T visit(DelegateType t)
1942   {
1943     return t;
1944   }
1945 
1946   T visit(BaseClassType t)
1947   {
1948     return t;
1949   }
1950 
1951   T visit(ModifierType t) // D2.0
1952   {
1953     return t;
1954   }
1955 } // override
1956 
1957   /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1958   |                                 Parameters                                |
1959    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1960 
1961 override
1962 {
1963   N visit(Parameter p)
1964   {
1965     return p;
1966   }
1967 
1968   N visit(Parameters p)
1969   {
1970     return p;
1971   }
1972 
1973   N visit(TemplateAliasParam p)
1974   {
1975     return p;
1976   }
1977 
1978   N visit(TemplateTypeParam p)
1979   {
1980     return p;
1981   }
1982 
1983   N visit(TemplateThisParam p) // D2.0
1984   {
1985     return p;
1986   }
1987 
1988   N visit(TemplateValueParam p)
1989   {
1990     return p;
1991   }
1992 
1993   N visit(TemplateTupleParam p)
1994   {
1995     return p;
1996   }
1997 
1998   N visit(TemplateParameters p)
1999   {
2000     return p;
2001   }
2002 
2003   N visit(TemplateArguments p)
2004   {
2005     return p;
2006   }
2007 } // override
2008 }
2009 
2010 /// Creates an error report.
2011 void error(Module m, Token* token, cstring formatMsg, ...)
2012 {
2013   error(m, _arguments, _argptr, formatMsg, token);
2014 }
2015 
2016 /// ditto
2017 void error(Module m, Node n, cstring formatMsg, ...)
2018 {
2019   error(m, _arguments, _argptr, formatMsg, n.begin);
2020 }
2021 
2022 /// ditto
2023 void error(Module m, Token* token, MID mid, ...)
2024 {
2025   error(m, _arguments, _argptr, m.cc.diag.msg(mid), token);
2026 }
2027 
2028 /// ditto
2029 void error(Module m, Node n, MID mid, ...)
2030 {
2031   error(m, _arguments, _argptr, m.cc.diag.msg(mid), n.begin);
2032 }
2033 
2034 /// ditto
2035 void error(Module m, TypeInfo[] _arguments, va_list _argptr,
2036   cstring msg, Token* token)
2037 {
2038   auto loc = token.getErrorLocation(m.filePath());
2039   msg = m.cc.diag.format(_arguments, _argptr, msg);
2040   m.cc.diag ~= new SemanticError(loc, msg);
2041 }