1 module d.ast.identifier;
2 
3 import d.ast.declaration;
4 import d.ast.expression;
5 import d.ast.type;
6 
7 import d.common.node;
8 
9 import source.context;
10 import source.name;
11 
12 abstract class Identifier : Node {
13 	this(Location location) {
14 		super(location);
15 	}
16 
17 	string toString(const Context c) const {
18 		assert(0, "toString not implement for " ~ typeid(this).toString());
19 	}
20 }
21 
22 final:
23 /**
24  * An identifier.
25  */
26 class BasicIdentifier : Identifier {
27 	Name name;
28 
29 	this(Location location, Name name) {
30 		super(location);
31 
32 		this.name = name;
33 	}
34 
35 	override string toString(const Context c) const {
36 		return name.toString(c);
37 	}
38 }
39 
40 /**
41  * An identifier qualified by an identifier (identifier.identifier)
42  */
43 class IdentifierDotIdentifier : Identifier {
44 	Name name;
45 	Identifier identifier;
46 
47 	this(Location location, Name name, Identifier identifier) {
48 		super(location);
49 
50 		this.name = name;
51 		this.identifier = identifier;
52 	}
53 
54 	override string toString(const Context c) const {
55 		return identifier.toString(c) ~ "." ~ name.toString(c);
56 	}
57 }
58 
59 /**
60  * An identifier qualified by a type (type.identifier)
61  */
62 class TypeDotIdentifier : Identifier {
63 	Name name;
64 	AstType type;
65 
66 	this(Location location, Name name, AstType type) {
67 		super(location);
68 
69 		this.name = name;
70 		this.type = type;
71 	}
72 
73 	override string toString(const Context c) const {
74 		return type.toString(c) ~ "." ~ name.toString(c);
75 	}
76 }
77 
78 /**
79  * An identifier qualified by an expression (expression.identifier)
80  */
81 class ExpressionDotIdentifier : Identifier {
82 	Name name;
83 	AstExpression expression;
84 
85 	this(Location location, Name name, AstExpression expression) {
86 		super(location);
87 
88 		this.name = name;
89 		this.expression = expression;
90 	}
91 
92 	override string toString(const Context c) const {
93 		return expression.toString(c) ~ "." ~ name.toString(c);
94 	}
95 }
96 
97 /**
98  * Template instantiation (identifier!(arguments...))
99  */
100 class TemplateInstantiation : Identifier {
101 	Identifier identifier;
102 	AstTemplateArgument[] arguments;
103 
104 	this(Location location, Identifier identifier,
105 	     AstTemplateArgument[] arguments) {
106 		super(location);
107 
108 		this.identifier = identifier;
109 		this.arguments = arguments;
110 	}
111 
112 	override string toString(const Context c) const {
113 		// Unfortunately, apply isn't const compliant so we cast it away.
114 		import std.algorithm, std.range;
115 		auto args = arguments.map!(a => (cast() a).apply!(a => a.toString(c)))
116 			.join(", ");
117 		return identifier.toString(c) ~ "!(" ~ args ~ ")";
118 	}
119 }
120 
121 alias AstTemplateArgument = AstType.UnionType!(AstExpression, Identifier);
122 
123 auto apply(alias handler)(AstTemplateArgument a) {
124 	alias Tag = typeof(a.tag);
125 	final switch (a.tag) with (Tag) {
126 		case AstExpression:
127 			return handler(a.get!AstExpression);
128 
129 		case Identifier:
130 			return handler(a.get!Identifier);
131 
132 		case AstType:
133 			return handler(a.get!AstType);
134 	}
135 }
136 
137 /**
138  * A module level identifier (.identifier)
139  */
140 class DotIdentifier : Identifier {
141 	Name name;
142 	this(Location location, Name name) {
143 		super(location);
144 
145 		this.name = name;
146 	}
147 
148 	override string toString(const Context c) const {
149 		return "." ~ name.toString(c);
150 	}
151 }
152 
153 /**
154  * An identifier of the form identifier[identifier]
155  */
156 class IdentifierBracketIdentifier : Identifier {
157 	Identifier indexed;
158 	Identifier index;
159 
160 	this(Location location, Identifier indexed, Identifier index) {
161 		super(location);
162 
163 		this.indexed = indexed;
164 		this.index = index;
165 	}
166 
167 	override string toString(const Context c) const {
168 		return indexed.toString(c) ~ "[" ~ index.toString(c) ~ "]";
169 	}
170 }
171 
172 /**
173  * An identifier of the form identifier[expression]
174  */
175 class IdentifierBracketExpression : Identifier {
176 	Identifier indexed;
177 	AstExpression index;
178 
179 	this(Location location, Identifier indexed, AstExpression index) {
180 		super(location);
181 
182 		this.indexed = indexed;
183 		this.index = index;
184 	}
185 
186 	override string toString(const Context c) const {
187 		return indexed.toString(c) ~ "[" ~ index.toString(c) ~ "]";
188 	}
189 }