d: Merge dmd, druntime d8e3976a58, phobos 7a6e95688
[official-gcc.git] / gcc / d / dmd / init.d
blob62bd41eea9382d0fba0da3d9771f3fcd3f3c7cbd
1 /**
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
12 module dmd.init;
14 import core.stdc.stdio;
16 import dmd.arraytypes;
17 import dmd.astenums;
18 import dmd.ast_node;
19 import dmd.expression;
20 import dmd.identifier;
21 import dmd.location;
22 import dmd.mtype;
23 import dmd.rootobject;
24 import dmd.visitor;
26 enum NeedInterpret : int
28 INITnointerpret,
29 INITinterpret,
32 alias INITnointerpret = NeedInterpret.INITnointerpret;
33 alias INITinterpret = NeedInterpret.INITinterpret;
35 /***********************************************************
37 extern (C++) class Initializer : ASTNode
39 Loc loc;
40 InitKind kind;
42 override DYNCAST dyncast() const
44 return DYNCAST.initializer;
48 extern (D) this(const ref Loc loc, InitKind kind) @safe
50 this.loc = loc;
51 this.kind = kind;
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)
92 v.visit(this);
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)
109 v.visit(this);
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)
127 v.visit(this);
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)
142 v.visit(this);
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)
167 v.visit(this);
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);
191 dim = 0;
192 type = null;
195 bool isAssociativeArray() const pure
197 foreach (idx; index)
199 if (idx)
200 return true;
202 return false;
205 override void accept(Visitor v)
207 v.visit(this);
211 /***********************************************************
213 extern (C++) final class ExpInitializer : Initializer
215 bool expandTuples;
216 Expression exp;
218 extern (D) this(const ref Loc loc, Expression exp) @safe
220 super(loc, InitKind.exp);
221 this.exp = exp;
224 override void accept(Visitor v)
226 v.visit(this);
230 /*********************************************
231 * Holds the `designator` for C initializers
233 struct Designator
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
245 struct DesigInit
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)
268 v.visit(this);
272 /****************************************
273 * Copy the AST for Initializer.
274 * Params:
275 * inx = Initializer AST to copy
276 * Returns:
277 * the 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)
293 return 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();
312 return si;
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();
326 return ai;
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;
351 return ci;
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.
363 * Params:
364 * Result = return type
365 * init = Initializer tree to traverse
366 * Returns:
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
385 return Result.init;
389 /****************************************
390 * CTFE-only helper function for VisitInitializer.
391 * Params:
392 * handler = string for the name of the visit handler
393 * Returns: boilerplate code for a case
395 string visitCase(string handler) pure @safe
397 if (__ctfe)
399 return
401 auto ix = init.is"~handler~"Initializer();
402 static if (is(Result == void))
403 visit"~handler~"(ix);
404 else
406 Result r = visit"~handler~"(ix);
407 if (r !is Result.init)
408 return r;
412 assert(0);