1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity very high) 4 module dil.ast.Parameters; 5 6 import dil.ast.Node, 7 dil.ast.Type, 8 dil.ast.Expression, 9 dil.ast.NodeCopier, 10 dil.ast.Meta; 11 import dil.lexer.Identifier; 12 import dil.semantic.Symbols; 13 import dil.Enums; 14 15 import common; 16 17 /// A function or foreach parameter. 18 class Parameter : Node 19 { 20 StorageClass stcs; /// The storage classes of the parameter. 21 Token* stok; /// Token of the last storage class. 22 TypeNode type; /// The parameter's type. 23 Token* name; /// The name of the parameter. 24 Expression defValue; /// The default initialization value. 25 ParameterSymbol symbol; /// Semantic symbol. 26 mixin(memberInfo("stcs", "stok?", "type?", "name?", "defValue?")); 27 28 this(StorageClass stcs, Token* stok, TypeNode type, 29 Token* name, Expression defValue) 30 { 31 mixin(set_kind); 32 // type can be null when param in foreach statement 33 addOptChild(type); 34 addOptChild(defValue); 35 36 this.stcs = stcs; 37 this.stok = stok; 38 this.type = type; 39 this.name = name; 40 this.defValue = defValue; 41 } 42 43 /// Returns true if this parameter has a name. 44 bool hasName() 45 { 46 return name !is null; 47 } 48 49 /// Returns the name of the parameter as a string. 50 cstring nameStr() 51 { 52 assert(hasName); 53 return name.ident.str; 54 } 55 56 /// Returns true if this is a D-style variadic parameter. 57 /// E.g.: func(int[] values ...) 58 bool isDVariadic() 59 { 60 return isVariadic && !isCVariadic; 61 } 62 63 /// Returns true if this is a C-style variadic parameter. 64 /// E.g.: func(...) 65 bool isCVariadic() 66 { 67 return stcs == StorageClass.Variadic && 68 type is null && name is null; 69 } 70 71 /// Returns true if this is a D- or C-style variadic parameter. 72 bool isVariadic() 73 { 74 return !!(stcs & StorageClass.Variadic); 75 } 76 77 /// Returns true if this parameter is lazy. 78 bool isLazy() 79 { 80 return !!(stcs & StorageClass.Lazy); 81 } 82 83 /// Returns the token of the storage class that comes before the type. 84 Token* tokenOfLastSTC() 85 { 86 return stok; 87 } 88 89 mixin methods; 90 } 91 92 /// Array of parameters. 93 class Parameters : Node 94 { 95 StorageClass postSTCs; 96 ParametersSymbol symbol; /// Semantic symbol. 97 98 this() 99 { 100 mixin(set_kind); 101 } 102 103 /// For ASTSerializer. 104 this(Parameter[] params) 105 { 106 this(); 107 addChildren(params); 108 } 109 110 bool hasVariadic() 111 { 112 if (children.length != 0) 113 return items[$-1].isVariadic(); 114 return false; 115 } 116 117 bool hasLazy() 118 { 119 foreach (param; items) 120 if (param.isLazy()) 121 return true; 122 return false; 123 } 124 125 void opCatAssign(Parameter param) 126 { addChild(param); } 127 128 Parameter[] items() @property 129 { return cast(Parameter[])children; } 130 131 void items(Parameter[] items) @property 132 { children = cast(Node[])items; } 133 134 size_t length() 135 { return children.length; } 136 137 mixin(memberInfo("items")); 138 mixin methods; 139 } 140 141 /*~~~~~~~~~~~~~~~~~~~~~~ 142 ~ Template parameters: ~ 143 ~~~~~~~~~~~~~~~~~~~~~~*/ 144 145 /// Abstract base class for all template parameters. 146 abstract class TemplateParam : Node 147 { 148 Token* name; 149 this(Token* name) 150 { 151 this.name = name; 152 } 153 154 /// Returns the name of the parameter as a string. 155 cstring nameStr() 156 { 157 return name.ident.str; 158 } 159 160 override TemplateParam copy(); 161 } 162 163 /// $(BNF TemplateAliasParam := "alias" Identifier SpecOrDefaultType) 164 class TemplateAliasParam : TemplateParam 165 { 166 Node spec; /// Specialization. Can be a Type or an Expression (in D2). 167 Node def; /// Default. Can be a Type or an Expression (in D2). 168 mixin(memberInfo("name", "spec?", "def?")); 169 this(Token* name, Node spec, Node def) 170 { 171 assert(!spec || spec.isType() || spec.isExpression()); 172 assert(!def || def.isType() || def.isExpression()); 173 super(name); 174 mixin(set_kind); 175 addOptChild(spec); 176 addOptChild(def); 177 this.spec = spec; 178 this.def = def; 179 } 180 mixin methods; 181 } 182 183 /// $(BNF TemplateTypeParam := Identifier SpecOrDefaultType) 184 class TemplateTypeParam : TemplateParam 185 { 186 TypeNode specType, defType; 187 mixin(memberInfo("name", "specType?", "defType?")); 188 this(Token* name, TypeNode specType, TypeNode defType) 189 { 190 super(name); 191 mixin(set_kind); 192 addOptChild(specType); 193 addOptChild(defType); 194 this.specType = specType; 195 this.defType = defType; 196 } 197 mixin methods; 198 } 199 200 // version(D2) 201 // { 202 /// $(BNF TemplateThisParam := "this" Identifier SpecOrDefaultType) 203 class TemplateThisParam : TemplateParam 204 { 205 TypeNode specType, defType; 206 mixin(memberInfo("name", "specType?", "defType?")); 207 this(Token* name, TypeNode specType, TypeNode defType) 208 { 209 super(name); 210 mixin(set_kind); 211 addOptChild(specType); 212 addOptChild(defType); 213 this.specType = specType; 214 this.defType = defType; 215 } 216 mixin methods; 217 } 218 // } 219 220 /// $(BNF TemplateValueParamer := Declarator SpecOrDefaultValue) 221 class TemplateValueParam : TemplateParam 222 { 223 TypeNode valueType; 224 Expression specValue, defValue; 225 mixin(memberInfo("valueType", "name", "specValue?", "defValue?")); 226 this(TypeNode valueType, Token* name, Expression specValue, 227 Expression defValue) 228 { 229 super(name); 230 mixin(set_kind); 231 addChild(valueType); 232 addOptChild(specValue); 233 addOptChild(defValue); 234 this.valueType = valueType; 235 this.specValue = specValue; 236 this.defValue = defValue; 237 } 238 mixin methods; 239 } 240 241 /// $(BNF TemplateTupleParam := Identifier "...") 242 class TemplateTupleParam : TemplateParam 243 { 244 mixin(memberInfo("name")); 245 this(Token* name) 246 { 247 super(name); 248 mixin(set_kind); 249 } 250 mixin methods; 251 } 252 253 /// Array of template parameters. 254 class TemplateParameters : Node 255 { 256 this() 257 { 258 mixin(set_kind); 259 } 260 261 /// For ASTSerializer. 262 this(TemplateParam[] params) 263 { 264 this(); 265 addChildren(params); 266 } 267 268 void opCatAssign(TemplateParam parameter) 269 { 270 addChild(parameter); 271 } 272 273 TemplateParam[] items() @property 274 { 275 return cast(TemplateParam[])children; 276 } 277 278 void items(TemplateParam[] items) @property 279 { 280 children = cast(Node[])items; 281 } 282 283 mixin(memberInfo("items")); 284 mixin methods; 285 } 286 287 /// Array of template arguments. 288 class TemplateArguments : Node 289 { 290 this() 291 { 292 mixin(set_kind); 293 } 294 295 /// For ASTSerializer. 296 this(Node[] args) 297 { 298 this(); 299 addChildren(args); 300 } 301 302 void opCatAssign(Node argument) 303 { 304 addChild(argument); 305 } 306 307 Node[] items() @property 308 { 309 return children; 310 } 311 312 void items(Node[] items) @property 313 { 314 children = items; 315 } 316 317 mixin(memberInfo("items")); 318 mixin methods; 319 }