1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity high)
4 module dil.ast.Declarations;
5 
6 public import dil.ast.Declaration;
7 import dil.ast.Node,
8        dil.ast.Expression,
9        dil.ast.Types,
10        dil.ast.Statements,
11        dil.ast.Parameters,
12        dil.ast.NodeCopier,
13        dil.ast.Meta;
14 import dil.lexer.IdTable;
15 import dil.semantic.Symbols;
16 import dil.Enums;
17 import common;
18 
19 class CompoundDecl : Declaration
20 {
21   this()
22   {
23     mixin(set_kind);
24   }
25 
26   this(Declaration[] decls)
27   {
28     this();
29     this.decls = decls;
30   }
31 
32   void opCatAssign(Declaration d)
33   {
34     addChild(d);
35   }
36 
37   void opCatAssign(CompoundDecl ds)
38   {
39     addChildren(ds.children);
40   }
41 
42   Declaration[] decls() @property
43   {
44     return cast(Declaration[])this.children;
45   }
46 
47   void decls(Declaration[] decls) @property
48   {
49     this.children = cast(Node[])decls;
50   }
51 
52   mixin(memberInfo("decls"));
53 
54   mixin methods;
55 }
56 
57 /// $(BNF ColonBlockDecl := ":" CompoundDecl)
58 class ColonBlockDecl : Declaration
59 {
60   CompoundDecl decls;
61   mixin(memberInfo("decls"));
62   this(CompoundDecl decls)
63   {
64     mixin(set_kind);
65     addChild(decls);
66     this.decls = decls;
67   }
68   mixin methods;
69 }
70 
71 /// Single semicolon.
72 class EmptyDecl : Declaration
73 {
74   mixin(memberInfo());
75   this()
76   {
77     mixin(set_kind);
78   }
79   mixin methods;
80 }
81 
82 /// Illegal declarations encompass all tokens that don't
83 /// start a DeclarationDefinition.
84 /// See_Also: dil.lexer.Token.isDeclDefStartToken()
85 class IllegalDecl : Declaration
86 {
87   mixin(memberInfo());
88   this()
89   {
90     mixin(set_kind);
91   }
92   mixin methods;
93 }
94 
95 /// FQN means "fully qualified name".
96 /// $(BNF ModuleFQN := Identifier ("." Identifier)*)
97 alias ModuleFQN = Token*[];
98 
99 class ModuleDecl : Declaration
100 {
101   Token* type; /// safe | system
102   Token* name; /// E.g.: Declarations
103   Token*[] packages; /// E.g.: [dil, ast]
104   Token*[] fqn; /// E.g.: [dil, ast, Declarations]
105   mixin(memberInfo("type", "fqn"));
106 
107   this(Token* type, ModuleFQN fqn)
108   {
109     mixin(set_kind);
110     assert(fqn.length != 0);
111     this.type = type;
112     this.fqn = fqn;
113     this.name = fqn[$-1];
114     this.packages = fqn[0..$-1];
115   }
116 
117   /// Returns the fully qualified name. E.g.: "dil.ast.Declarations"
118   cstring getFQN()
119   {
120     auto fqn = getPackageName('.');
121     if (fqn.length)
122       fqn ~= '.';
123     fqn ~= getName();
124     return fqn;
125   }
126 
127   /// Returns the name of this module. E.ǵ.: "Declarations"
128   cstring getName()
129   {
130     return name ? name.ident.str : "";
131   }
132 
133   /// Returns the packages of this module. E.g.: "dil.ast"
134   char[] getPackageName(char separator)
135   {
136     char[] pname;
137     foreach (pckg; packages)
138       if (pckg)
139         pname ~= pckg.ident.str ~ separator;
140     if (pname.length)
141       pname = pname[0..$-1]; // Remove last separator
142     return pname;
143   }
144 
145   mixin methods;
146 }
147 
148 class ImportDecl : Declaration
149 {
150   private alias Ids = Token*[];
151   ModuleFQN[] moduleFQNs;
152   Ids moduleAliases;
153   Ids bindNames;
154   Ids bindAliases;
155   mixin(memberInfo("moduleFQNs", "moduleAliases", "bindNames", "bindAliases",
156     "isStatic"));
157 
158   this(ModuleFQN[] moduleFQNs, Ids moduleAliases, Ids bindNames,
159        Ids bindAliases, bool isStatic)
160   {
161     mixin(set_kind);
162     this.moduleFQNs = moduleFQNs;
163     this.moduleAliases = moduleAliases;
164     this.bindNames = bindNames;
165     this.bindAliases = bindAliases;
166     if (isStatic)
167       this.stcs |= StorageClass.Static;
168   }
169 
170   cstring[] getModuleFQNs(char separator)
171   {
172     cstring[] FQNs;
173     foreach (moduleFQN; moduleFQNs)
174     {
175       char[] FQN;
176       foreach (ident; moduleFQN)
177         if (ident)
178           FQN ~= ident.ident.str ~ separator;
179       FQNs ~= FQN[0..$-1]; // Remove last separator
180     }
181     return FQNs;
182   }
183 
184   mixin methods;
185 }
186 
187 class AliasDecl : Declaration
188 {
189   Declaration decl;
190   /// Shortcut that skips any attributes inbetween.
191   /// Eg.: alias extern(C) void function() C_funcptr;
192   ///        decl^  vardecl^
193   Declaration vardecl;
194   mixin(memberInfo("decl"));
195   this(Declaration decl)
196   {
197     mixin(set_kind);
198     addChild(decl);
199     this.decl = decl;
200   }
201   AliasSymbol[] symbols;
202   mixin methods;
203 }
204 
205 class AliasesDecl : Declaration
206 {
207   Token*[] idents;
208   TypeNode[] types;
209   mixin(memberInfo("idents", "types"));
210   this(Token*[] idents, TypeNode[] types)
211   {
212     mixin(set_kind);
213     addChildren(types);
214     this.idents = idents;
215     this.types = types;
216   }
217   AliasSymbol[] symbols;
218   mixin methods;
219 }
220 
221 class AliasThisDecl : Declaration
222 {
223   Token* name;
224   AliasSymbol symbol; /// Semantic symbol.
225   mixin(memberInfo("name"));
226   this(Token* name)
227   {
228     mixin(set_kind);
229     this.name = name;
230   }
231   mixin methods;
232 }
233 
234 class TypedefDecl : Declaration
235 {
236   Declaration decl;
237   Declaration vardecl;
238   TypedefSymbol[] symbols; /// Semantic symbols.
239   mixin(memberInfo("decl"));
240   this(Declaration decl)
241   {
242     mixin(set_kind);
243     addChild(decl);
244     this.decl = decl;
245   }
246   mixin methods;
247 }
248 
249 class EnumDecl : Declaration
250 {
251   Token* name;
252   TypeNode baseType;
253   EnumMemberDecl[] members;
254   EnumSymbol symbol; /// Semantic symbol.
255   mixin(memberInfo("name", "baseType?", "members"));
256 
257   this(Token* name, TypeNode baseType, EnumMemberDecl[] members)
258   {
259     mixin(set_kind);
260     addOptChild(baseType);
261     addOptChildren(members);
262 
263     this.name = name;
264     this.baseType = baseType;
265     this.members = members;
266   }
267 
268   /// Returns the Identifier of this enum, or null if anonymous.
269   Identifier* nameId()
270   {
271     return name ? name.ident : null;
272   }
273 
274   mixin methods;
275 }
276 
277 class EnumMemberDecl : Declaration
278 {
279   TypeNode type; // D 2.0
280   Token* name;
281   Expression value;
282   EnumMemberSymbol symbol; /// Semantic symbol.
283   mixin(memberInfo("type?", "name", "value?"));
284 
285   private this(Token* name, Expression value)
286   {
287     mixin(set_kind);
288     addOptChild(value);
289 
290     this.name = name;
291     this.value = value;
292   }
293 
294   // D 2.0
295   this(TypeNode type, Token* name, Expression value)
296   {
297     addOptChild(type);
298     this.type = type;
299     this(name, value);
300   }
301 
302   mixin methods;
303 }
304 
305 class TemplateDecl : Declaration
306 {
307   Token* name;
308   TemplateParameters tparams;
309   Expression constraint; /// If-constraint in D2.
310   CompoundDecl decls;
311   bool isMixin; /// Is this a mixin template? (D2 feature.)
312   bool isWrapper; /// Is this wrapping a func/class/struct/etc. declaration?
313   TemplateSymbol symbol; /// Semantic symbol.
314   mixin(memberInfo("name", "tparams", "constraint?", "decls"));
315 
316   this(Token* name, TemplateParameters tparams, Expression constraint,
317        CompoundDecl decls)
318   {
319     mixin(set_kind);
320     addChild(tparams);
321     addOptChild(constraint);
322     addChild(decls);
323 
324     this.name = name;
325     this.tparams = tparams;
326     this.constraint = constraint;
327     this.decls = decls;
328 
329     auto list = decls.decls;
330     alias NK = NodeKind;
331     if (list.length == 1 && list[0].kind.In(NK.FunctionDecl, NK.ClassDecl,
332           NK.InterfaceDecl, NK.StructDecl, NK.UnionDecl, NK.ConstructorDecl))
333       this.isWrapper = true;
334   }
335 
336   /// Returns the Identifier of this template.
337   Identifier* nameId()
338   {
339     return name.ident;
340   }
341 
342   mixin methods;
343 }
344 
345 abstract class AggregateDecl : Declaration
346 {
347   Token* name;
348   CompoundDecl decls;
349   this(Token* name, CompoundDecl decls)
350   {
351     this.name = name;
352     this.decls = decls;
353   }
354 
355   /// Returns the Identifier of this declaration, or null if anonymous.
356   Identifier* nameId()
357   {
358     return name ? name.ident : null;
359   }
360 }
361 
362 class ClassDecl : AggregateDecl
363 {
364   BaseClassType[] bases;
365   ClassSymbol symbol; /// Semantic symbol.
366   mixin(memberInfo("name", "bases", "decls?"));
367   this(Token* name, BaseClassType[] bases, CompoundDecl decls)
368   {
369     super(name, decls);
370     mixin(set_kind);
371     addOptChildren(bases);
372     addOptChild(decls);
373 
374     this.bases = bases;
375   }
376   mixin methods;
377 }
378 
379 class InterfaceDecl : AggregateDecl
380 {
381   BaseClassType[] bases;
382   InterfaceSymbol symbol; /// Semantic symbol.
383   mixin(memberInfo("name", "bases", "decls?"));
384   this(Token* name, BaseClassType[] bases, CompoundDecl decls)
385   {
386     super(name, decls);
387     mixin(set_kind);
388     addOptChildren(bases);
389     addOptChild(decls);
390 
391     this.bases = bases;
392   }
393   mixin methods;
394 }
395 
396 class StructDecl : AggregateDecl
397 {
398   uint alignSize;
399   StructSymbol symbol; /// Semantic type.
400   mixin(memberInfo("name?", "decls?", "alignSize"));
401   this(Token* name, CompoundDecl decls)
402   {
403     super(name, decls);
404     mixin(set_kind);
405     addOptChild(decls);
406   }
407 
408   /// For ASTSerializer.
409   this(Token* name, CompoundDecl decls, uint alignSize)
410   {
411     this(name, decls);
412     setAlignSize(alignSize);
413   }
414 
415   void setAlignSize(uint alignSize)
416   {
417     this.alignSize = alignSize;
418   }
419 
420   mixin methods;
421 }
422 
423 class UnionDecl : AggregateDecl
424 {
425   UnionSymbol symbol; /// Semantic symbol.
426   mixin(memberInfo("name?", "decls?"));
427   this(Token* name, CompoundDecl decls)
428   {
429     super(name, decls);
430     mixin(set_kind);
431     addOptChild(decls);
432   }
433   mixin methods;
434 }
435 
436 class ConstructorDecl : Declaration
437 {
438   Parameters params;
439   FuncBodyStmt funcBody;
440   mixin(memberInfo("params", "funcBody"));
441   this(Parameters params, FuncBodyStmt funcBody)
442   {
443     mixin(set_kind);
444     addChild(params);
445     addChild(funcBody);
446 
447     this.params = params;
448     this.funcBody = funcBody;
449   }
450   mixin methods;
451 }
452 
453 class StaticCtorDecl : Declaration
454 {
455   FuncBodyStmt funcBody;
456   mixin(memberInfo("funcBody"));
457   this(FuncBodyStmt funcBody)
458   {
459     mixin(set_kind);
460     addChild(funcBody);
461 
462     this.funcBody = funcBody;
463   }
464   mixin methods;
465 }
466 
467 class DestructorDecl : Declaration
468 {
469   FuncBodyStmt funcBody;
470   mixin(memberInfo("funcBody"));
471   this(FuncBodyStmt funcBody)
472   {
473     mixin(set_kind);
474     addChild(funcBody);
475 
476     this.funcBody = funcBody;
477   }
478   mixin methods;
479 }
480 
481 class StaticDtorDecl : Declaration
482 {
483   FuncBodyStmt funcBody;
484   mixin(memberInfo("funcBody"));
485   this(FuncBodyStmt funcBody)
486   {
487     mixin(set_kind);
488     addChild(funcBody);
489 
490     this.funcBody = funcBody;
491   }
492   mixin methods;
493 }
494 
495 class FunctionDecl : Declaration
496 {
497   TypeNode returnType;
498   Token* name;
499   Parameters params;
500   FuncBodyStmt funcBody;
501   LinkageType lnkg;
502   bool cantInterpret = false;
503 
504   mixin(memberInfo("returnType?", "name", "params", "funcBody", "lnkg"));
505   this(TypeNode returnType, Token* name,
506        Parameters params, FuncBodyStmt funcBody,
507        LinkageType lnkg = LinkageType.None)
508   {
509     mixin(set_kind);
510     addOptChild(returnType);
511     addChild(params);
512     addChild(funcBody);
513 
514     this.returnType = returnType;
515     this.name = name;
516     this.params = params;
517     this.funcBody = funcBody;
518     this.lnkg = lnkg;
519   }
520 
521   bool isTemplatized()
522   { // E.g.: void func(T)(T t)
523     //                  ^ params.begin.prevNWS
524     return params.begin.prevNWS.kind == TOK.RParen;
525   }
526 
527   mixin methods;
528 }
529 
530 /// $(BNF VariablesDecl :=
531 ///  Type? Identifier ("=" Init)? ("," Identifier ("=" Init)?)* ";")
532 class VariablesDecl : Declaration
533 {
534   TypeNode type; /// The type of the variables.
535   Token*[] names; /// Variable names.
536   Expression[] inits; /// Respective initial values.
537   LinkageType lnkg; /// They linkage type.
538   mixin(memberInfo("type?", "names", "inits?", "lnkg"));
539 
540   this(TypeNode type, Token*[] names, Expression[] inits,
541        LinkageType lnkg = LinkageType.None)
542   {
543     // No empty arrays allowed. Both arrays must be of same size.
544     assert(names.length != 0 && names.length == inits.length);
545     // If no type (in case of AutoDecl), first value mustn't be null.
546     assert(type || inits[0] !is null);
547     mixin(set_kind);
548     addOptChild(type);
549     foreach (init; inits)
550       addOptChild(init);
551 
552     this.type = type;
553     this.names = names;
554     this.inits = inits;
555     this.lnkg = lnkg;
556   }
557 
558   /// Returns the first non-null init expression, or null if there is none.
559   Expression firstInit()
560   {
561     foreach (init; inits)
562       if (init !is null)
563         return init;
564     return null;
565   }
566 
567   VariableSymbol[] variables;
568 
569   mixin methods;
570 }
571 
572 class InvariantDecl : Declaration
573 {
574   FuncBodyStmt funcBody;
575   mixin(memberInfo("funcBody"));
576   this(FuncBodyStmt funcBody)
577   {
578     mixin(set_kind);
579     addChild(funcBody);
580 
581     this.funcBody = funcBody;
582   }
583   mixin methods;
584 }
585 
586 class UnittestDecl : Declaration
587 {
588   FuncBodyStmt funcBody;
589   mixin(memberInfo("funcBody"));
590   this(FuncBodyStmt funcBody)
591   {
592     mixin(set_kind);
593     addChild(funcBody);
594 
595     this.funcBody = funcBody;
596   }
597   mixin methods;
598 }
599 
600 abstract class ConditionalCompilationDecl : Declaration
601 {
602   Token* spec;
603   Token* cond;
604   Declaration decls, elseDecls;
605 
606   this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
607   {
608     addOptChild(decls);
609     addOptChild(elseDecls);
610 
611     this.spec = spec;
612     this.cond = cond;
613     this.decls = decls;
614     this.elseDecls = elseDecls;
615   }
616 
617   bool isSpecification()
618   {
619     return decls is null;
620   }
621 
622   bool isCondition()
623   {
624     return decls !is null;
625   }
626 
627   /// The branch to be compiled in.
628   Declaration compiledDecls;
629 }
630 
631 class DebugDecl : ConditionalCompilationDecl
632 {
633   mixin(memberInfo("spec?", "cond?", "decls?", "elseDecls?"));
634   this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
635   {
636     super(spec, cond, decls, elseDecls);
637     mixin(set_kind);
638   }
639   mixin methods;
640 }
641 
642 class VersionDecl : ConditionalCompilationDecl
643 {
644   mixin(memberInfo("spec?", "cond?", "decls?", "elseDecls?"));
645   this(Token* spec, Token* cond, Declaration decls, Declaration elseDecls)
646   {
647     super(spec, cond, decls, elseDecls);
648     mixin(set_kind);
649   }
650   mixin methods;
651 }
652 
653 class StaticIfDecl : Declaration
654 {
655   Expression condition;
656   Declaration ifDecls, elseDecls;
657   mixin(memberInfo("condition", "ifDecls", "elseDecls?"));
658   this(Expression condition, Declaration ifDecls, Declaration elseDecls)
659   {
660     mixin(set_kind);
661     addChild(condition);
662     addChild(ifDecls);
663     addOptChild(elseDecls);
664 
665     this.condition = condition;
666     this.ifDecls = ifDecls;
667     this.elseDecls = elseDecls;
668   }
669   mixin methods;
670 }
671 
672 class StaticAssertDecl : Declaration
673 {
674   Expression condition, message;
675   mixin(memberInfo("condition", "message?"));
676   this(Expression condition, Expression message)
677   {
678     mixin(set_kind);
679     addChild(condition);
680     addOptChild(message);
681 
682     this.condition = condition;
683     this.message = message;
684   }
685   mixin methods;
686 }
687 
688 class NewDecl : Declaration
689 {
690   Parameters params;
691   FuncBodyStmt funcBody;
692   mixin(memberInfo("params", "funcBody"));
693   this(Parameters params, FuncBodyStmt funcBody)
694   {
695     mixin(set_kind);
696     addChild(params);
697     addChild(funcBody);
698 
699     this.params = params;
700     this.funcBody = funcBody;
701   }
702   mixin methods;
703 }
704 
705 class DeleteDecl : Declaration
706 {
707   Parameters params;
708   FuncBodyStmt funcBody;
709   mixin(memberInfo("params", "funcBody"));
710   this(Parameters params, FuncBodyStmt funcBody)
711   {
712     mixin(set_kind);
713     addChild(params);
714     addChild(funcBody);
715 
716     this.params = params;
717     this.funcBody = funcBody;
718   }
719   mixin methods;
720 }
721 
722 abstract class AttributeDecl : Declaration
723 {
724   Declaration decls;
725   this(Declaration decls)
726   {
727     addChild(decls);
728     this.decls = decls;
729   }
730 
731   void setDecls(Declaration decls)
732   {
733     this.decls = decls;
734     if (children.length)
735       children[0] = decls;
736     else
737       addChild(decls);
738   }
739 }
740 
741 class ProtectionDecl : AttributeDecl
742 {
743   Protection prot;
744   mixin(memberInfo("prot", "decls"));
745   this(Protection prot, Declaration decls)
746   {
747     super(decls);
748     mixin(set_kind);
749     this.prot = prot;
750   }
751   mixin methods;
752 }
753 
754 class StorageClassDecl : AttributeDecl
755 {
756   StorageClass stc;
757   mixin(memberInfo("stc", "decls"));
758   this(StorageClass stc, Declaration decls)
759   {
760     super(decls);
761     mixin(set_kind);
762 
763     this.stc = stc;
764   }
765   mixin methods;
766 }
767 
768 class LinkageDecl : AttributeDecl
769 {
770   LinkageType linkageType;
771   mixin(memberInfo("linkageType", "decls"));
772   this(LinkageType linkageType, Declaration decls)
773   {
774     super(decls);
775     mixin(set_kind);
776 
777     this.linkageType = linkageType;
778   }
779   mixin methods;
780 }
781 
782 class AlignDecl : AttributeDecl
783 {
784   int size;
785   Token* sizetok;
786   mixin(memberInfo("sizetok", "decls"));
787   this(Token* sizetok, Declaration decls)
788   {
789     super(decls);
790     mixin(set_kind);
791     this.size = sizetok ? sizetok.int_ : -1;
792     this.sizetok = sizetok;
793   }
794   mixin methods;
795 }
796 
797 class PragmaDecl : AttributeDecl
798 {
799   Token* name;
800   Expression[] args;
801   mixin(memberInfo("name", "args", "decls"));
802   this(Token* name, Expression[] args, Declaration decls)
803   {
804     addOptChildren(args); // Add args before calling super().
805     super(decls);
806     mixin(set_kind);
807 
808     this.name = name;
809     this.args = args;
810   }
811 
812   mixin methods;
813 }
814 
815 class MixinDecl : Declaration
816 {
817   /// IdExpr := IdentifierExpr | TmplInstanceExpr
818   /// MixinTemplate := IdExpr ("." IdExpr)*
819   Expression templateExpr;
820   Token* mixinIdent; /// Optional mixin identifier.
821   Expression argument; /// "mixin" "(" AssignExpr ")"
822 
823   mixin(memberInfo("templateExpr?", "mixinIdent?", "argument?"));
824   this(Expression templateExpr, Token* mixinIdent)
825   {
826     mixin(set_kind);
827     addChild(templateExpr);
828 
829     this.templateExpr = templateExpr;
830     this.mixinIdent = mixinIdent;
831   }
832 
833   this(Expression argument)
834   {
835     mixin(set_kind);
836     addChild(argument);
837 
838     this.argument = argument;
839   }
840 
841   /// Constructor for the deserializer.
842   this(Expression templateExpr, Token* mixinIdent, Expression argument)
843   {
844     if (argument)
845       this(argument);
846     else
847       this(templateExpr, mixinIdent);
848   }
849 
850   bool isMixinExpr()
851   {
852     return argument !is null;
853   }
854 
855   Declaration decls; /// Initialized in the semantic phase.
856 
857   mixin methods;
858 }