2 * Defines initializers of variables, e.g. the array literal in `int[3] x = [0, 1, 2]`.
4 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/init.d, _init.d)
8 * Documentation: https://dlang.org/phobos/dmd_init.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/init.d
14 import core
.stdc
.stdio
;
15 import core
.checkedint
;
17 import dmd
.arraytypes
;
21 import dmd
.expression
;
24 import dmd
.identifier
;
27 import dmd
.common
.outbuffer
;
28 import dmd
.rootobject
;
32 enum NeedInterpret
: int
38 alias INITnointerpret
= NeedInterpret
.INITnointerpret
;
39 alias INITinterpret
= NeedInterpret
.INITinterpret
;
41 /***********************************************************
43 extern (C
++) class Initializer
: ASTNode
48 override DYNCAST
dyncast() const
50 return DYNCAST
.initializer
;
54 extern (D
) this(const ref Loc loc
, InitKind kind
) @safe
60 final inout(ErrorInitializer
) isErrorInitializer() inout @nogc nothrow pure
62 // Use void* cast to skip dynamic casting call
63 return kind
== InitKind
.error ?
cast(inout ErrorInitializer
)cast(void*)this : null;
66 final inout(VoidInitializer
) isVoidInitializer() inout @nogc nothrow pure
68 return kind
== InitKind
.void_ ?
cast(inout VoidInitializer
)cast(void*)this : null;
71 final inout(DefaultInitializer
) isDefaultInitializer() inout @nogc nothrow pure
73 return kind
== InitKind
.default_ ?
cast(inout DefaultInitializer
)cast(void*)this : null;
76 final inout(StructInitializer
) isStructInitializer() inout @nogc nothrow pure
78 return kind
== InitKind
.struct_ ?
cast(inout StructInitializer
)cast(void*)this : null;
81 final inout(ArrayInitializer
) isArrayInitializer() inout @nogc nothrow pure
83 return kind
== InitKind
.array ?
cast(inout ArrayInitializer
)cast(void*)this : null;
86 final inout(ExpInitializer
) isExpInitializer() inout @nogc nothrow pure
88 return kind
== InitKind
.exp ?
cast(inout ExpInitializer
)cast(void*)this : null;
91 final inout(CInitializer
) isCInitializer() inout @nogc nothrow pure
93 return kind
== InitKind
.C_ ?
cast(inout CInitializer
)cast(void*)this : null;
96 override void accept(Visitor v
)
102 /***********************************************************
104 extern (C
++) final class VoidInitializer
: Initializer
106 Type type
; // type that this will initialize to
108 extern (D
) this(const ref Loc loc
) @safe
110 super(loc
, InitKind
.void_
);
113 override void accept(Visitor v
)
119 /***********************************************************
120 * The C23 default initializer `{ }`
122 extern (C
++) final class DefaultInitializer
: Initializer
124 Type type
; // type that this will initialize to
126 extern (D
) this(const ref Loc loc
) @safe
128 super(loc
, InitKind
.default_
);
131 override void accept(Visitor v
)
137 /***********************************************************
139 extern (C
++) final class ErrorInitializer
: Initializer
141 extern (D
) this() @safe
143 super(Loc
.initial
, InitKind
.error
);
146 override void accept(Visitor v
)
152 /***********************************************************
154 extern (C
++) final class StructInitializer
: Initializer
156 Identifiers field
; // of Identifier *'s
157 Initializers value
; // parallel array of Initializer *'s
159 extern (D
) this(const ref Loc loc
)
161 super(loc
, InitKind
.struct_
);
164 extern (D
) void addInit(Identifier field
, Initializer value
)
166 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
167 this.field
.push(field
);
168 this.value
.push(value
);
171 override void accept(Visitor v
)
177 /***********************************************************
179 extern (C
++) final class ArrayInitializer
: Initializer
181 Expressions index
; // indices
182 Initializers value
; // of Initializer *'s
183 uint dim
; // length of array being initialized
184 Type type
; // type that array will be used to initialize
185 bool sem
; // true if semantic() is run
186 bool isCarray
; // C array semantics
188 extern (D
) this(const ref Loc loc
)
190 super(loc
, InitKind
.array
);
193 extern (D
) void addInit(Expression index
, Initializer value
)
195 this.index
.push(index
);
196 this.value
.push(value
);
201 bool isAssociativeArray() const pure
211 override void accept(Visitor v
)
217 /***********************************************************
219 extern (C
++) final class ExpInitializer
: Initializer
224 extern (D
) this(const ref Loc loc
, Expression exp
) @safe
226 super(loc
, InitKind
.exp
);
230 override void accept(Visitor v
)
236 /*********************************************
237 * Holds the `designator` for C initializers
241 Expression exp
; /// [ constant-expression ]
242 Identifier ident
; /// . identifier
244 this(Expression exp
) @safe { this.exp
= exp
; }
245 this(Identifier ident
) @safe { this.ident
= ident
; }
248 /*********************************************
249 * Holds the `designation (opt) initializer` for C initializers
253 Designators
* designatorList
; /// designation (opt)
254 Initializer initializer
; /// initializer
257 /********************************
258 * C11 6.7.9 Initialization
259 * Represents the C initializer-list
261 extern (C
++) final class CInitializer
: Initializer
263 DesigInits initializerList
; /// initializer-list
264 Type type
; /// type that array will be used to initialize
265 bool sem
; /// true if semantic() is run
267 extern (D
) this(const ref Loc loc
)
269 super(loc
, InitKind
.C_
);
272 override void accept(Visitor v
)
278 /****************************************
279 * Copy the AST for Initializer.
281 * inx = Initializer AST to copy
285 Initializer
syntaxCopy(Initializer inx
)
287 static Initializer
visitVoid(VoidInitializer vi
)
289 return new VoidInitializer(vi
.loc
);
292 static Initializer
visitDefault(DefaultInitializer vi
)
294 return new DefaultInitializer(vi
.loc
);
297 static Initializer
visitError(ErrorInitializer vi
)
302 static Initializer
visitExp(ExpInitializer vi
)
304 return new ExpInitializer(vi
.loc
, vi
.exp
.syntaxCopy());
307 static Initializer
visitStruct(StructInitializer vi
)
309 auto si
= new StructInitializer(vi
.loc
);
310 assert(vi
.field
.length
== vi
.value
.length
);
311 si
.field
.setDim(vi
.field
.length
);
312 si
.value
.setDim(vi
.value
.length
);
313 foreach (const i
; 0 .. vi
.field
.length
)
315 si
.field
[i
] = vi
.field
[i
];
316 si
.value
[i
] = vi
.value
[i
].syntaxCopy();
321 static Initializer
visitArray(ArrayInitializer vi
)
323 auto ai
= new ArrayInitializer(vi
.loc
);
324 assert(vi
.index
.length
== vi
.value
.length
);
325 ai
.index
.setDim(vi
.index
.length
);
326 ai
.value
.setDim(vi
.value
.length
);
327 foreach (const i
; 0 .. vi
.value
.length
)
329 ai
.index
[i
] = vi
.index
[i
] ? vi
.index
[i
].syntaxCopy() : null;
330 ai
.value
[i
] = vi
.value
[i
].syntaxCopy();
335 static Initializer
visitC(CInitializer vi
)
337 auto ci
= new CInitializer(vi
.loc
);
338 ci
.initializerList
.setDim(vi
.initializerList
.length
);
339 foreach (const i
; 0 .. vi
.initializerList
.length
)
341 DesigInit
* cdi
= &ci
.initializerList
[i
];
342 DesigInit
* vdi
= &ci
.initializerList
[i
];
343 cdi
.initializer
= vdi
.initializer
.syntaxCopy();
344 if (vdi
.designatorList
)
346 cdi
.designatorList
= new Designators();
347 cdi
.designatorList
.setDim(vdi
.designatorList
.length
);
348 foreach (const j
; 0 .. vdi
.designatorList
.length
)
350 Designator
* cdid
= &(*cdi
.designatorList
)[j
];
351 Designator
* vdid
= &(*vdi
.designatorList
)[j
];
352 cdid
.exp
= vdid
.exp ? vdid
.exp
.syntaxCopy() : null;
353 cdid
.ident
= vdid
.ident
;
360 mixin VisitInitializer
!Initializer visit
;
361 return visit
.VisitInitializer(inx
);
364 /***********************************************************
365 * Visit each Initializer in init. Call a function visit%s(init) for
366 * each node, where %s is the op of the node. Otherwise call visitDefault(init)
367 * for that node. If the visit function returns R.init, continue
368 * visiting each node, otherwise return the value of R.
370 * Result = return type
371 * init = Initializer tree to traverse
373 * Result.init for continue, value of type Result for early exit
376 mixin template VisitInitializer(Result
)
378 Result
VisitInitializer(Initializer init
)
380 final switch (init
.kind
)
382 case InitKind
.void_
: mixin(visitCase("Void")); break;
383 case InitKind
.default_
: mixin(visitCase("Default")); break;
384 case InitKind
.error
: mixin(visitCase("Error")); break;
385 case InitKind
.struct_
: mixin(visitCase("Struct")); break;
386 case InitKind
.array
: mixin(visitCase("Array")); break;
387 case InitKind
.exp
: mixin(visitCase("Exp")); break;
388 case InitKind
.C_
: mixin(visitCase("C")); break;
390 static if (is(Result
== void)) { } else
395 /****************************************
396 * CTFE-only helper function for VisitInitializer.
398 * handler = string for the name of the visit handler
399 * Returns: boilerplate code for a case
401 string
visitCase(string handler
) pure @safe
407 auto ix = init.is"~handler
~"Initializer();
408 static if (is(Result == void))
409 visit"~handler
~"(ix);
412 Result r = visit"~handler
~"(ix);
413 if (r !is Result.init)