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 }