63
|
1 module dmd.interpret.Util;
|
|
2
|
|
3 import dmd.StructDeclaration;
|
|
4 import dmd.Expression;
|
|
5 import dmd.InterState;
|
|
6 import dmd.ArrayTypes;
|
|
7 import dmd.GlobalExpressions;
|
|
8 import dmd.TOK;
|
|
9 import dmd.AssocArrayLiteralExp;
|
|
10 import dmd.IntegerExp;
|
|
11 import dmd.Type;
|
|
12 import dmd.Declaration;
|
|
13 import dmd.Loc;
|
|
14 import dmd.ArrayLiteralExp;
|
|
15 import dmd.TypeAArray;
|
|
16 import dmd.TypeSArray;
|
|
17 import dmd.STC;
|
|
18 import dmd.SymbolDeclaration;
|
|
19 import dmd.StructLiteralExp;
|
|
20 import dmd.VarDeclaration;
|
|
21 import dmd.Util;
|
|
22
|
|
23 Expression interpret_aaLen(InterState istate, Expressions arguments)
|
|
24 {
|
|
25 if (!arguments || arguments.dim != 1)
|
|
26 return null;
|
|
27 Expression earg = cast(Expression)arguments.data[0];
|
|
28 earg = earg.interpret(istate);
|
|
29 if (earg is EXP_CANT_INTERPRET)
|
|
30 return null;
|
|
31 if (earg.op != TOKassocarrayliteral)
|
|
32 return null;
|
|
33 AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
|
|
34 Expression e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t);
|
|
35 return e;
|
|
36 }
|
|
37
|
|
38 Expression interpret_aaKeys(InterState istate, Expressions arguments)
|
|
39 {
|
|
40 version (LOG) {
|
|
41 printf("interpret_aaKeys()\n");
|
|
42 }
|
|
43 if (!arguments || arguments.dim != 2)
|
|
44 return null;
|
|
45 Expression earg = cast(Expression)arguments.data[0];
|
|
46 earg = earg.interpret(istate);
|
|
47 if (earg is EXP_CANT_INTERPRET)
|
|
48 return null;
|
|
49 if (earg.op != TOKassocarrayliteral)
|
|
50 return null;
|
|
51 AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
|
|
52 Expression e = new ArrayLiteralExp(aae.loc, aae.keys);
|
|
53 Type elemType = (cast(TypeAArray)aae.type).index;
|
|
54 e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0));
|
|
55 return e;
|
|
56 }
|
|
57
|
|
58 Expression interpret_aaValues(InterState istate, Expressions arguments)
|
|
59 {
|
|
60 //printf("interpret_aaValues()\n");
|
|
61 if (!arguments || arguments.dim != 3)
|
|
62 return null;
|
|
63 Expression earg = cast(Expression)arguments.data[0];
|
|
64 earg = earg.interpret(istate);
|
|
65 if (earg is EXP_CANT_INTERPRET)
|
|
66 return null;
|
|
67 if (earg.op != TOKassocarrayliteral)
|
|
68 return null;
|
|
69 AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
|
|
70 Expression e = new ArrayLiteralExp(aae.loc, aae.values);
|
|
71 Type elemType = (cast(TypeAArray)aae.type).next;
|
|
72 e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0));
|
|
73 //printf("result is %s\n", e.toChars());
|
|
74 return e;
|
|
75 }
|
|
76
|
|
77 Expression getVarExp(Loc loc, InterState istate, Declaration d)
|
|
78 {
|
|
79 Expression e = EXP_CANT_INTERPRET;
|
|
80 VarDeclaration v = d.isVarDeclaration();
|
|
81 SymbolDeclaration s = d.isSymbolDeclaration();
|
|
82 if (v)
|
|
83 {
|
|
84 ///version (DMDV2) {
|
|
85 if ((v.isConst() || v.isInvariant() || v.storage_class & STCmanifest) && v.init && !v.value)
|
|
86 ///} else {
|
|
87 /// if (v.isConst() && v.init)
|
|
88 ///}
|
|
89 {
|
|
90 e = v.init.toExpression();
|
|
91 if (e && !e.type)
|
|
92 e.type = v.type;
|
|
93 }
|
|
94 else
|
|
95 {
|
|
96 e = v.value;
|
|
97 if (v.isDataseg())
|
|
98 {
|
|
99 error(loc, "static variable %s cannot be read at compile time", v.toChars());
|
|
100 e = EXP_CANT_INTERPRET;
|
|
101 }
|
|
102 else if (!e)
|
|
103 error(loc, "variable %s is used before initialization", v.toChars());
|
|
104 else if (e !is EXP_CANT_INTERPRET)
|
|
105 e = e.interpret(istate);
|
|
106 }
|
|
107 if (!e)
|
|
108 e = EXP_CANT_INTERPRET;
|
|
109 }
|
|
110 else if (s)
|
|
111 {
|
|
112 if (s.dsym.toInitializer() == s.sym)
|
|
113 {
|
|
114 Expressions exps = new Expressions();
|
|
115 e = new StructLiteralExp(Loc(0), s.dsym, exps);
|
|
116 e = e.semantic(null);
|
|
117 }
|
|
118 }
|
|
119 return e;
|
|
120 }
|
|
121
|
|
122 /* Helper functions for BinExp.interpretAssignCommon
|
|
123 */
|
|
124
|
|
125 /***************************************
|
|
126 * Duplicate the elements array, then set field 'indexToChange' = newelem.
|
|
127 */
|
|
128 Expressions changeOneElement(Expressions oldelems, size_t indexToChange, void* newelem)
|
|
129 {
|
|
130 Expressions expsx = new Expressions();
|
|
131 expsx.setDim(oldelems.dim);
|
|
132 for (size_t j = 0; j < expsx.dim; j++)
|
|
133 {
|
|
134 if (j == indexToChange)
|
|
135 expsx.data[j] = newelem;
|
|
136 else
|
|
137 expsx.data[j] = oldelems.data[j];
|
|
138 }
|
|
139 return expsx;
|
|
140 }
|
|
141
|
|
142 /***************************************
|
|
143 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$]
|
|
144 */
|
|
145 Expressions spliceElements(Expressions oldelems, Expressions newelems, size_t insertpoint)
|
|
146 {
|
|
147 Expressions expsx = new Expressions();
|
|
148 expsx.setDim(oldelems.dim);
|
|
149 for (size_t j = 0; j < expsx.dim; j++)
|
|
150 {
|
|
151 if (j >= insertpoint && j < insertpoint + newelems.dim)
|
|
152 expsx.data[j] = newelems.data[j - insertpoint];
|
|
153 else
|
|
154 expsx.data[j] = oldelems.data[j];
|
|
155 }
|
|
156 return expsx;
|
|
157 }
|
|
158
|
|
159 /******************************
|
|
160 * Create an array literal consisting of 'elem' duplicated 'dim' times.
|
|
161 */
|
|
162 ArrayLiteralExp createBlockDuplicatedArrayLiteral(Type type, Expression elem, size_t dim)
|
|
163 {
|
|
164 Expressions elements = new Expressions();
|
|
165 elements.setDim(dim);
|
|
166 for (size_t i = 0; i < dim; i++) {
|
|
167 elements.data[i] = cast(void*)elem;
|
|
168 }
|
|
169
|
|
170 ArrayLiteralExp ae = new ArrayLiteralExp(Loc(0), elements);
|
|
171 ae.type = type;
|
|
172 return ae;
|
|
173 }
|
|
174
|
|
175
|
|
176 /********************************
|
|
177 * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp.
|
|
178 */
|
|
179 StructLiteralExp createDefaultInitStructLiteral(Loc loc, StructDeclaration sym)
|
|
180 {
|
|
181 Expressions structelems = new Expressions();
|
|
182 structelems.setDim(sym.fields.dim);
|
|
183 for (size_t j = 0; j < structelems.dim; j++)
|
|
184 {
|
|
185 structelems.data[j] = cast(void*)(cast(VarDeclaration)(sym.fields.data[j])).type.defaultInit(Loc(0));
|
|
186 }
|
|
187 StructLiteralExp structinit = new StructLiteralExp(loc, sym, structelems);
|
|
188 // Why doesn't the StructLiteralExp constructor do this, when
|
|
189 // sym.type != null ?
|
|
190 structinit.type = sym.type;
|
|
191 return structinit;
|
|
192 }
|
|
193
|
|
194 /********************************
|
|
195 * Add v to the istate list, unless it already exists there.
|
|
196 */
|
|
197 void addVarToInterstate(InterState istate, VarDeclaration v)
|
|
198 {
|
|
199 if (!v.isParameter())
|
|
200 {
|
|
201 for (size_t i = 0; 1; i++)
|
|
202 {
|
|
203 if (i == istate.vars.dim)
|
|
204 {
|
|
205 istate.vars.push(cast(void*)v);
|
|
206 //printf("\tadding %s to istate\n", v.toChars());
|
|
207 break;
|
|
208 }
|
|
209 if (v == cast(VarDeclaration)istate.vars.data[i])
|
|
210 break;
|
|
211 }
|
|
212 }
|
|
213 } |