2 * Defines initializers of variables, e.g. the array literal in `int[3] x = [0, 1, 2]`.
4 * Copyright: Copyright (C) 1999-2024 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
;
16 import dmd
.arraytypes
;
19 import dmd
.expression
;
20 import dmd
.identifier
;
23 import dmd
.rootobject
;
26 enum NeedInterpret
: int
32 alias INITnointerpret
= NeedInterpret
.INITnointerpret
;
33 alias INITinterpret
= NeedInterpret
.INITinterpret
;
35 /***********************************************************
37 extern (C
++) class Initializer
: ASTNode
42 override DYNCAST
dyncast() const
44 return DYNCAST
.initializer
;
48 extern (D
) this(const ref Loc loc
, InitKind kind
) @safe
54 final inout(ErrorInitializer
) isErrorInitializer() inout @nogc nothrow pure
56 // Use void* cast to skip dynamic casting call
57 return kind
== InitKind
.error ?
cast(inout ErrorInitializer
)cast(void*)this : null;
60 final inout(VoidInitializer
) isVoidInitializer() inout @nogc nothrow pure
62 return kind
== InitKind
.void_ ?
cast(inout VoidInitializer
)cast(void*)this : null;
65 final inout(DefaultInitializer
) isDefaultInitializer() inout @nogc nothrow pure
67 return kind
== InitKind
.default_ ?
cast(inout DefaultInitializer
)cast(void*)this : null;
70 final inout(StructInitializer
) isStructInitializer() inout @nogc nothrow pure
72 return kind
== InitKind
.struct_ ?
cast(inout StructInitializer
)cast(void*)this : null;
75 final inout(ArrayInitializer
) isArrayInitializer() inout @nogc nothrow pure
77 return kind
== InitKind
.array ?
cast(inout ArrayInitializer
)cast(void*)this : null;
80 final inout(ExpInitializer
) isExpInitializer() inout @nogc nothrow pure
82 return kind
== InitKind
.exp ?
cast(inout ExpInitializer
)cast(void*)this : null;
85 final inout(CInitializer
) isCInitializer() inout @nogc nothrow pure
87 return kind
== InitKind
.C_ ?
cast(inout CInitializer
)cast(void*)this : null;
90 override void accept(Visitor v
)
96 /***********************************************************
98 extern (C
++) final class VoidInitializer
: Initializer
100 Type type
; // type that this will initialize to
102 extern (D
) this(const ref Loc loc
) @safe
104 super(loc
, InitKind
.void_
);
107 override void accept(Visitor v
)
113 /***********************************************************
114 * The C23 default initializer `{ }`
116 extern (C
++) final class DefaultInitializer
: Initializer
118 Type type
; // type that this will initialize to
120 extern (D
) this(const ref Loc loc
) @safe
122 super(loc
, InitKind
.default_
);
125 override void accept(Visitor v
)
131 /***********************************************************
133 extern (C
++) final class ErrorInitializer
: Initializer
135 extern (D
) this() @safe
137 super(Loc
.initial
, InitKind
.error
);
140 override void accept(Visitor v
)
146 /***********************************************************
148 extern (C
++) final class StructInitializer
: Initializer
150 Identifiers field
; // of Identifier *'s
151 Initializers value
; // parallel array of Initializer *'s
153 extern (D
) this(const ref Loc loc
)
155 super(loc
, InitKind
.struct_
);
158 extern (D
) void addInit(Identifier field
, Initializer value
)
160 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
161 this.field
.push(field
);
162 this.value
.push(value
);
165 override void accept(Visitor v
)
171 /***********************************************************
173 extern (C
++) final class ArrayInitializer
: Initializer
175 Expressions index
; // indices
176 Initializers value
; // of Initializer *'s
177 uint dim
; // length of array being initialized
178 Type type
; // type that array will be used to initialize
179 bool sem
; // true if semantic() is run
180 bool isCarray
; // C array semantics
182 extern (D
) this(const ref Loc loc
)
184 super(loc
, InitKind
.array
);
187 extern (D
) void addInit(Expression index
, Initializer value
)
189 this.index
.push(index
);
190 this.value
.push(value
);
195 bool isAssociativeArray() const pure
205 override void accept(Visitor v
)
211 /***********************************************************
213 extern (C
++) final class ExpInitializer
: Initializer
218 extern (D
) this(const ref Loc loc
, Expression exp
) @safe
220 super(loc
, InitKind
.exp
);
224 override void accept(Visitor v
)
230 /*********************************************
231 * Holds the `designator` for C initializers
235 Expression exp
; /// [ constant-expression ]
236 Identifier ident
; /// . identifier
238 this(Expression exp
) @safe { this.exp
= exp
; }
239 this(Identifier ident
) @safe { this.ident
= ident
; }
242 /*********************************************
243 * Holds the `designation (opt) initializer` for C initializers
247 Designators
* designatorList
; /// designation (opt)
248 Initializer initializer
; /// initializer
251 /********************************
252 * C11 6.7.9 Initialization
253 * Represents the C initializer-list
255 extern (C
++) final class CInitializer
: Initializer
257 DesigInits initializerList
; /// initializer-list
258 Type type
; /// type that array will be used to initialize
259 bool sem
; /// true if semantic() is run
261 extern (D
) this(const ref Loc loc
)
263 super(loc
, InitKind
.C_
);
266 override void accept(Visitor v
)
272 /****************************************
273 * Copy the AST for Initializer.
275 * inx = Initializer AST to copy
279 Initializer
syntaxCopy(Initializer inx
)
281 static Initializer
visitVoid(VoidInitializer vi
)
283 return new VoidInitializer(vi
.loc
);
286 static Initializer
visitDefault(DefaultInitializer vi
)
288 return new DefaultInitializer(vi
.loc
);
291 static Initializer
visitError(ErrorInitializer vi
)
296 static Initializer
visitExp(ExpInitializer vi
)
298 return new ExpInitializer(vi
.loc
, vi
.exp
.syntaxCopy());
301 static Initializer
visitStruct(StructInitializer vi
)
303 auto si
= new StructInitializer(vi
.loc
);
304 assert(vi
.field
.length
== vi
.value
.length
);
305 si
.field
.setDim(vi
.field
.length
);
306 si
.value
.setDim(vi
.value
.length
);
307 foreach (const i
; 0 .. vi
.field
.length
)
309 si
.field
[i
] = vi
.field
[i
];
310 si
.value
[i
] = vi
.value
[i
].syntaxCopy();
315 static Initializer
visitArray(ArrayInitializer vi
)
317 auto ai
= new ArrayInitializer(vi
.loc
);
318 assert(vi
.index
.length
== vi
.value
.length
);
319 ai
.index
.setDim(vi
.index
.length
);
320 ai
.value
.setDim(vi
.value
.length
);
321 foreach (const i
; 0 .. vi
.value
.length
)
323 ai
.index
[i
] = vi
.index
[i
] ? vi
.index
[i
].syntaxCopy() : null;
324 ai
.value
[i
] = vi
.value
[i
].syntaxCopy();
329 static Initializer
visitC(CInitializer vi
)
331 auto ci
= new CInitializer(vi
.loc
);
332 ci
.initializerList
.setDim(vi
.initializerList
.length
);
333 foreach (const i
; 0 .. vi
.initializerList
.length
)
335 DesigInit
* cdi
= &ci
.initializerList
[i
];
336 DesigInit
* vdi
= &ci
.initializerList
[i
];
337 cdi
.initializer
= vdi
.initializer
.syntaxCopy();
338 if (vdi
.designatorList
)
340 cdi
.designatorList
= new Designators();
341 cdi
.designatorList
.setDim(vdi
.designatorList
.length
);
342 foreach (const j
; 0 .. vdi
.designatorList
.length
)
344 Designator
* cdid
= &(*cdi
.designatorList
)[j
];
345 Designator
* vdid
= &(*vdi
.designatorList
)[j
];
346 cdid
.exp
= vdid
.exp ? vdid
.exp
.syntaxCopy() : null;
347 cdid
.ident
= vdid
.ident
;
354 mixin VisitInitializer
!Initializer visit
;
355 return visit
.VisitInitializer(inx
);
358 /***********************************************************
359 * Visit each Initializer in init. Call a function visit%s(init) for
360 * each node, where %s is the op of the node. Otherwise call visitDefault(init)
361 * for that node. If the visit function returns R.init, continue
362 * visiting each node, otherwise return the value of R.
364 * Result = return type
365 * init = Initializer tree to traverse
367 * Result.init for continue, value of type Result for early exit
370 mixin template VisitInitializer(Result
)
372 Result
VisitInitializer(Initializer init
)
374 final switch (init
.kind
)
376 case InitKind
.void_
: mixin(visitCase("Void")); break;
377 case InitKind
.default_
: mixin(visitCase("Default")); break;
378 case InitKind
.error
: mixin(visitCase("Error")); break;
379 case InitKind
.struct_
: mixin(visitCase("Struct")); break;
380 case InitKind
.array
: mixin(visitCase("Array")); break;
381 case InitKind
.exp
: mixin(visitCase("Exp")); break;
382 case InitKind
.C_
: mixin(visitCase("C")); break;
384 static if (is(Result
== void)) { } else
389 /****************************************
390 * CTFE-only helper function for VisitInitializer.
392 * handler = string for the name of the visit handler
393 * Returns: boilerplate code for a case
395 string
visitCase(string handler
) pure @safe
401 auto ix = init.is"~handler
~"Initializer();
402 static if (is(Result == void))
403 visit"~handler
~"(ix);
406 Result r = visit"~handler
~"(ix);
407 if (r !is Result.init)