]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
8e788ac6 | 3 | * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved |
b4c522fa IB |
4 | * written by Walter Bright |
5 | * http://www.digitalmars.com | |
6 | * Distributed under the Boost Software License, Version 1.0. | |
7 | * http://www.boost.org/LICENSE_1_0.txt | |
8 | * https://github.com/dlang/dmd/blob/master/src/dmd/expression.h | |
9 | */ | |
10 | ||
11 | #pragma once | |
12 | ||
13 | #include "complex_t.h" | |
14 | #include "globals.h" | |
15 | #include "identifier.h" | |
16 | #include "arraytypes.h" | |
17 | #include "intrange.h" | |
18 | #include "visitor.h" | |
19 | #include "tokens.h" | |
20 | ||
21 | #include "root/rmem.h" | |
22 | ||
23 | class Type; | |
24 | class TypeVector; | |
25 | struct Scope; | |
26 | class TupleDeclaration; | |
27 | class VarDeclaration; | |
28 | class FuncDeclaration; | |
29 | class FuncLiteralDeclaration; | |
30 | class Declaration; | |
31 | class CtorDeclaration; | |
32 | class NewDeclaration; | |
33 | class Dsymbol; | |
34 | class Import; | |
35 | class Module; | |
36 | class ScopeDsymbol; | |
37 | class Expression; | |
38 | class Declaration; | |
39 | class AggregateDeclaration; | |
40 | class StructDeclaration; | |
41 | class TemplateInstance; | |
42 | class TemplateDeclaration; | |
43 | class ClassDeclaration; | |
44 | class BinExp; | |
45 | class OverloadSet; | |
46 | class Initializer; | |
47 | class StringExp; | |
48 | class ArrayExp; | |
49 | class SliceExp; | |
50 | struct UnionExp; | |
51 | #ifdef IN_GCC | |
52 | typedef union tree_node Symbol; | |
53 | #else | |
54 | struct Symbol; // back end symbol | |
55 | #endif | |
56 | ||
57 | Expression *resolveProperties(Scope *sc, Expression *e); | |
58 | Expression *resolvePropertiesOnly(Scope *sc, Expression *e1); | |
59 | bool checkAccess(Loc loc, Scope *sc, Expression *e, Declaration *d); | |
60 | bool checkAccess(Loc loc, Scope *sc, Package *p); | |
61 | Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d); | |
62 | Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid); | |
63 | void expandTuples(Expressions *exps); | |
64 | TupleDeclaration *isAliasThisTuple(Expression *e); | |
65 | int expandAliasThisTuples(Expressions *exps, size_t starti = 0); | |
66 | FuncDeclaration *hasThis(Scope *sc); | |
67 | Expression *fromConstInitializer(int result, Expression *e); | |
68 | bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors = false); | |
69 | TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); | |
70 | Expression *valueNoDtor(Expression *e); | |
71 | int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1); | |
72 | Expression *resolveAliasThis(Scope *sc, Expression *e, bool gag = false); | |
73 | Expression *doCopyOrMove(Scope *sc, Expression *e); | |
74 | Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0); | |
75 | Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0); | |
76 | Expression *integralPromotions(Expression *e, Scope *sc); | |
77 | bool discardValue(Expression *e); | |
78 | bool isTrivialExp(Expression *e); | |
79 | ||
80 | int isConst(Expression *e); | |
81 | Expression *toDelegate(Expression *e, Type* t, Scope *sc); | |
82 | AggregateDeclaration *isAggregate(Type *t); | |
83 | IntRange getIntRange(Expression *e); | |
84 | bool checkNonAssignmentArrayOp(Expression *e, bool suggestion = false); | |
85 | bool isUnaArrayOp(TOK op); | |
86 | bool isBinArrayOp(TOK op); | |
87 | bool isBinAssignArrayOp(TOK op); | |
88 | bool isArrayOpOperand(Expression *e); | |
89 | Expression *arrayOp(BinExp *e, Scope *sc); | |
90 | Expression *arrayOp(BinAssignExp *e, Scope *sc); | |
91 | bool hasSideEffect(Expression *e); | |
92 | bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow); | |
93 | Expression *Expression_optimize(Expression *e, int result, bool keepLvalue); | |
94 | MATCH implicitConvTo(Expression *e, Type *t); | |
95 | Expression *implicitCastTo(Expression *e, Scope *sc, Type *t); | |
96 | Expression *castTo(Expression *e, Scope *sc, Type *t); | |
97 | Expression *ctfeInterpret(Expression *); | |
98 | Expression *inlineCopy(Expression *e, Scope *sc); | |
99 | Expression *op_overload(Expression *e, Scope *sc); | |
100 | Type *toStaticArrayType(SliceExp *e); | |
101 | Expression *scaleFactor(BinExp *be, Scope *sc); | |
102 | Expression *typeCombine(BinExp *be, Scope *sc); | |
103 | Expression *inferType(Expression *e, Type *t, int flag = 0); | |
104 | Expression *semanticTraits(TraitsExp *e, Scope *sc); | |
105 | Type *getIndirection(Type *t); | |
106 | ||
107 | Expression *checkGC(Scope *sc, Expression *e); | |
108 | ||
109 | /* Run CTFE on the expression, but allow the expression to be a TypeExp | |
110 | * or a tuple containing a TypeExp. (This is required by pragma(msg)). | |
111 | */ | |
112 | Expression *ctfeInterpretForPragmaMsg(Expression *e); | |
113 | ||
114 | enum OwnedBy | |
115 | { | |
116 | OWNEDcode, // normal code expression in AST | |
117 | OWNEDctfe, // value expression for CTFE | |
118 | OWNEDcache // constant value cached for CTFE | |
119 | }; | |
120 | ||
121 | #define WANTvalue 0 // default | |
122 | #define WANTexpand 1 // expand const/immutable variables if possible | |
123 | ||
124 | class Expression : public RootObject | |
125 | { | |
126 | public: | |
127 | Loc loc; // file location | |
128 | Type *type; // !=NULL means that semantic() has been run | |
129 | TOK op; // to minimize use of dynamic_cast | |
130 | unsigned char size; // # of bytes in Expression so we can copy() it | |
131 | unsigned char parens; // if this is a parenthesized expression | |
132 | ||
133 | Expression(Loc loc, TOK op, int size); | |
134 | static void _init(); | |
135 | Expression *copy(); | |
136 | virtual Expression *syntaxCopy(); | |
137 | ||
138 | // kludge for template.isExpression() | |
139 | int dyncast() const { return DYNCAST_EXPRESSION; } | |
140 | ||
141 | void print(); | |
142 | const char *toChars(); | |
143 | void error(const char *format, ...) const; | |
144 | void warning(const char *format, ...) const; | |
145 | void deprecation(const char *format, ...) const; | |
146 | ||
147 | // creates a single expression which is effectively (e1, e2) | |
148 | // this new expression does not necessarily need to have valid D source code representation, | |
149 | // for example, it may include declaration expressions | |
150 | static Expression *combine(Expression *e1, Expression *e2); | |
151 | static Expression *extractLast(Expression *e, Expression **pe0); | |
152 | static Expressions *arraySyntaxCopy(Expressions *exps); | |
153 | ||
154 | virtual dinteger_t toInteger(); | |
155 | virtual uinteger_t toUInteger(); | |
156 | virtual real_t toReal(); | |
157 | virtual real_t toImaginary(); | |
158 | virtual complex_t toComplex(); | |
159 | virtual StringExp *toStringExp(); | |
5b74dd0a | 160 | virtual TupleExp *toTupleExp(); |
b4c522fa IB |
161 | virtual bool isLvalue(); |
162 | virtual Expression *toLvalue(Scope *sc, Expression *e); | |
163 | virtual Expression *modifiableLvalue(Scope *sc, Expression *e); | |
164 | Expression *implicitCastTo(Scope *sc, Type *t) | |
165 | { | |
166 | return ::implicitCastTo(this, sc, t); | |
167 | } | |
168 | MATCH implicitConvTo(Type *t) | |
169 | { | |
170 | return ::implicitConvTo(this, t); | |
171 | } | |
172 | Expression *castTo(Scope *sc, Type *t) | |
173 | { | |
174 | return ::castTo(this, sc, t); | |
175 | } | |
176 | virtual Expression *resolveLoc(Loc loc, Scope *sc); | |
177 | virtual bool checkType(); | |
178 | virtual bool checkValue(); | |
179 | bool checkScalar(); | |
180 | bool checkNoBool(); | |
181 | bool checkIntegral(); | |
182 | bool checkArithmetic(); | |
183 | void checkDeprecated(Scope *sc, Dsymbol *s); | |
184 | bool checkPurity(Scope *sc, FuncDeclaration *f); | |
185 | bool checkPurity(Scope *sc, VarDeclaration *v); | |
186 | bool checkSafety(Scope *sc, FuncDeclaration *f); | |
187 | bool checkNogc(Scope *sc, FuncDeclaration *f); | |
188 | bool checkPostblit(Scope *sc, Type *t); | |
189 | bool checkRightThis(Scope *sc); | |
190 | bool checkReadModifyWrite(TOK rmwOp, Expression *ex = NULL); | |
191 | virtual int checkModifiable(Scope *sc, int flag = 0); | |
192 | virtual Expression *toBoolean(Scope *sc); | |
193 | virtual Expression *addDtorHook(Scope *sc); | |
194 | Expression *addressOf(); | |
195 | Expression *deref(); | |
196 | ||
197 | Expression *optimize(int result, bool keepLvalue = false) | |
198 | { | |
199 | return Expression_optimize(this, result, keepLvalue); | |
200 | } | |
201 | ||
202 | // Entry point for CTFE. | |
203 | // A compile-time result is required. Give an error if not possible | |
204 | Expression *ctfeInterpret() | |
205 | { | |
206 | return ::ctfeInterpret(this); | |
207 | } | |
208 | ||
209 | int isConst() { return ::isConst(this); } | |
210 | virtual bool isBool(bool result); | |
211 | Expression *op_overload(Scope *sc) | |
212 | { | |
213 | return ::op_overload(this, sc); | |
214 | } | |
215 | ||
216 | virtual bool hasCode() | |
217 | { | |
218 | return true; | |
219 | } | |
220 | ||
221 | virtual void accept(Visitor *v) { v->visit(this); } | |
222 | }; | |
223 | ||
224 | class IntegerExp : public Expression | |
225 | { | |
226 | public: | |
227 | dinteger_t value; | |
228 | ||
229 | IntegerExp(Loc loc, dinteger_t value, Type *type); | |
230 | IntegerExp(dinteger_t value); | |
231 | static IntegerExp *create(Loc loc, dinteger_t value, Type *type); | |
232 | bool equals(RootObject *o); | |
233 | dinteger_t toInteger(); | |
234 | real_t toReal(); | |
235 | real_t toImaginary(); | |
236 | complex_t toComplex(); | |
237 | bool isBool(bool result); | |
238 | Expression *toLvalue(Scope *sc, Expression *e); | |
239 | void accept(Visitor *v) { v->visit(this); } | |
240 | dinteger_t getInteger() { return value; } | |
241 | void setInteger(dinteger_t value); | |
242 | void normalize(); | |
243 | }; | |
244 | ||
245 | class ErrorExp : public Expression | |
246 | { | |
247 | public: | |
248 | ErrorExp(); | |
249 | Expression *toLvalue(Scope *sc, Expression *e); | |
250 | void accept(Visitor *v) { v->visit(this); } | |
251 | ||
252 | static ErrorExp *errorexp; // handy shared value | |
253 | }; | |
254 | ||
255 | class RealExp : public Expression | |
256 | { | |
257 | public: | |
258 | real_t value; | |
259 | ||
260 | RealExp(Loc loc, real_t value, Type *type); | |
261 | static RealExp *create(Loc loc, real_t value, Type *type); | |
262 | bool equals(RootObject *o); | |
263 | dinteger_t toInteger(); | |
264 | uinteger_t toUInteger(); | |
265 | real_t toReal(); | |
266 | real_t toImaginary(); | |
267 | complex_t toComplex(); | |
268 | bool isBool(bool result); | |
269 | void accept(Visitor *v) { v->visit(this); } | |
270 | }; | |
271 | ||
272 | class ComplexExp : public Expression | |
273 | { | |
274 | public: | |
275 | complex_t value; | |
276 | ||
277 | ComplexExp(Loc loc, complex_t value, Type *type); | |
278 | static ComplexExp *create(Loc loc, complex_t value, Type *type); | |
279 | bool equals(RootObject *o); | |
280 | dinteger_t toInteger(); | |
281 | uinteger_t toUInteger(); | |
282 | real_t toReal(); | |
283 | real_t toImaginary(); | |
284 | complex_t toComplex(); | |
285 | bool isBool(bool result); | |
286 | void accept(Visitor *v) { v->visit(this); } | |
287 | }; | |
288 | ||
289 | class IdentifierExp : public Expression | |
290 | { | |
291 | public: | |
292 | Identifier *ident; | |
293 | ||
294 | IdentifierExp(Loc loc, Identifier *ident); | |
295 | static IdentifierExp *create(Loc loc, Identifier *ident); | |
296 | bool isLvalue(); | |
297 | Expression *toLvalue(Scope *sc, Expression *e); | |
298 | void accept(Visitor *v) { v->visit(this); } | |
299 | }; | |
300 | ||
301 | class DollarExp : public IdentifierExp | |
302 | { | |
303 | public: | |
304 | DollarExp(Loc loc); | |
305 | void accept(Visitor *v) { v->visit(this); } | |
306 | }; | |
307 | ||
308 | class DsymbolExp : public Expression | |
309 | { | |
310 | public: | |
311 | Dsymbol *s; | |
312 | bool hasOverloads; | |
313 | ||
314 | DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads = true); | |
315 | bool isLvalue(); | |
316 | Expression *toLvalue(Scope *sc, Expression *e); | |
317 | void accept(Visitor *v) { v->visit(this); } | |
318 | }; | |
319 | ||
320 | class ThisExp : public Expression | |
321 | { | |
322 | public: | |
323 | VarDeclaration *var; | |
324 | ||
325 | ThisExp(Loc loc); | |
326 | bool isBool(bool result); | |
327 | bool isLvalue(); | |
328 | Expression *toLvalue(Scope *sc, Expression *e); | |
329 | ||
330 | void accept(Visitor *v) { v->visit(this); } | |
331 | }; | |
332 | ||
333 | class SuperExp : public ThisExp | |
334 | { | |
335 | public: | |
336 | SuperExp(Loc loc); | |
337 | ||
338 | void accept(Visitor *v) { v->visit(this); } | |
339 | }; | |
340 | ||
341 | class NullExp : public Expression | |
342 | { | |
343 | public: | |
344 | unsigned char committed; // !=0 if type is committed | |
345 | ||
346 | NullExp(Loc loc, Type *t = NULL); | |
347 | bool equals(RootObject *o); | |
348 | bool isBool(bool result); | |
349 | StringExp *toStringExp(); | |
350 | void accept(Visitor *v) { v->visit(this); } | |
351 | }; | |
352 | ||
353 | class StringExp : public Expression | |
354 | { | |
355 | public: | |
356 | void *string; // char, wchar, or dchar data | |
357 | size_t len; // number of chars, wchars, or dchars | |
358 | unsigned char sz; // 1: char, 2: wchar, 4: dchar | |
359 | unsigned char committed; // !=0 if type is committed | |
360 | utf8_t postfix; // 'c', 'w', 'd' | |
361 | OwnedBy ownedByCtfe; | |
362 | ||
363 | StringExp(Loc loc, char *s); | |
364 | StringExp(Loc loc, void *s, size_t len); | |
365 | StringExp(Loc loc, void *s, size_t len, utf8_t postfix); | |
366 | static StringExp *create(Loc loc, char *s); | |
367 | static StringExp *create(Loc loc, void *s, size_t len); | |
368 | bool equals(RootObject *o); | |
369 | StringExp *toStringExp(); | |
370 | StringExp *toUTF8(Scope *sc); | |
371 | int compare(RootObject *obj); | |
372 | bool isBool(bool result); | |
373 | bool isLvalue(); | |
374 | Expression *toLvalue(Scope *sc, Expression *e); | |
375 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
376 | unsigned charAt(uinteger_t i) const; | |
377 | void accept(Visitor *v) { v->visit(this); } | |
378 | size_t numberOfCodeUnits(int tynto = 0) const; | |
379 | void writeTo(void* dest, bool zero, int tyto = 0) const; | |
380 | char *toPtr(); | |
381 | }; | |
382 | ||
383 | // Tuple | |
384 | ||
385 | class TupleExp : public Expression | |
386 | { | |
387 | public: | |
388 | Expression *e0; // side-effect part | |
389 | /* Tuple-field access may need to take out its side effect part. | |
390 | * For example: | |
391 | * foo().tupleof | |
392 | * is rewritten as: | |
393 | * (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...)) | |
394 | * The declaration of temporary variable __tup will be stored in TupleExp::e0. | |
395 | */ | |
396 | Expressions *exps; | |
397 | ||
398 | TupleExp(Loc loc, Expression *e0, Expressions *exps); | |
399 | TupleExp(Loc loc, Expressions *exps); | |
400 | TupleExp(Loc loc, TupleDeclaration *tup); | |
5b74dd0a | 401 | TupleExp *toTupleExp(); |
b4c522fa IB |
402 | Expression *syntaxCopy(); |
403 | bool equals(RootObject *o); | |
404 | ||
405 | void accept(Visitor *v) { v->visit(this); } | |
406 | }; | |
407 | ||
408 | class ArrayLiteralExp : public Expression | |
409 | { | |
410 | public: | |
411 | Expression *basis; | |
412 | Expressions *elements; | |
413 | OwnedBy ownedByCtfe; | |
414 | ||
255b2d91 IB |
415 | ArrayLiteralExp(Loc loc, Type *type, Expressions *elements); |
416 | ArrayLiteralExp(Loc loc, Type *type, Expression *e); | |
417 | ArrayLiteralExp(Loc loc, Type *type, Expression *basis, Expressions *elements); | |
b4c522fa IB |
418 | static ArrayLiteralExp *create(Loc loc, Expressions *elements); |
419 | Expression *syntaxCopy(); | |
420 | bool equals(RootObject *o); | |
421 | Expression *getElement(d_size_t i); | |
422 | static Expressions* copyElements(Expression *e1, Expression *e2 = NULL); | |
423 | bool isBool(bool result); | |
424 | StringExp *toStringExp(); | |
425 | ||
426 | void accept(Visitor *v) { v->visit(this); } | |
427 | }; | |
428 | ||
429 | class AssocArrayLiteralExp : public Expression | |
430 | { | |
431 | public: | |
432 | Expressions *keys; | |
433 | Expressions *values; | |
434 | OwnedBy ownedByCtfe; | |
435 | ||
436 | AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values); | |
437 | bool equals(RootObject *o); | |
438 | Expression *syntaxCopy(); | |
439 | bool isBool(bool result); | |
440 | ||
441 | void accept(Visitor *v) { v->visit(this); } | |
442 | }; | |
443 | ||
444 | // scrubReturnValue is running | |
445 | #define stageScrub 0x1 | |
446 | // hasNonConstPointers is running | |
447 | #define stageSearchPointers 0x2 | |
448 | // optimize is running | |
449 | #define stageOptimize 0x4 | |
450 | // apply is running | |
451 | #define stageApply 0x8 | |
452 | //inlineScan is running | |
453 | #define stageInlineScan 0x10 | |
454 | // toCBuffer is running | |
455 | #define stageToCBuffer 0x20 | |
456 | ||
457 | class StructLiteralExp : public Expression | |
458 | { | |
459 | public: | |
460 | StructDeclaration *sd; // which aggregate this is for | |
461 | Expressions *elements; // parallels sd->fields[] with NULL entries for fields to skip | |
462 | Type *stype; // final type of result (can be different from sd's type) | |
463 | ||
464 | bool useStaticInit; // if this is true, use the StructDeclaration's init symbol | |
465 | Symbol *sym; // back end symbol to initialize with literal | |
466 | ||
467 | OwnedBy ownedByCtfe; | |
468 | ||
469 | // pointer to the origin instance of the expression. | |
470 | // once a new expression is created, origin is set to 'this'. | |
471 | // anytime when an expression copy is created, 'origin' pointer is set to | |
472 | // 'origin' pointer value of the original expression. | |
473 | StructLiteralExp *origin; | |
474 | ||
475 | // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer. | |
476 | StructLiteralExp *inlinecopy; | |
477 | ||
478 | // anytime when recursive function is calling, 'stageflags' marks with bit flag of | |
479 | // current stage and unmarks before return from this function. | |
480 | // 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline' | |
481 | // (with infinite recursion) of this expression. | |
482 | int stageflags; | |
483 | ||
484 | StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL); | |
485 | static StructLiteralExp *create(Loc loc, StructDeclaration *sd, void *elements, Type *stype = NULL); | |
486 | bool equals(RootObject *o); | |
487 | Expression *syntaxCopy(); | |
488 | Expression *getField(Type *type, unsigned offset); | |
489 | int getFieldIndex(Type *type, unsigned offset); | |
490 | Expression *addDtorHook(Scope *sc); | |
491 | ||
492 | void accept(Visitor *v) { v->visit(this); } | |
493 | }; | |
494 | ||
495 | class DotIdExp; | |
496 | DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident); | |
497 | ||
498 | class TypeExp : public Expression | |
499 | { | |
500 | public: | |
501 | TypeExp(Loc loc, Type *type); | |
502 | Expression *syntaxCopy(); | |
503 | bool checkType(); | |
504 | bool checkValue(); | |
505 | void accept(Visitor *v) { v->visit(this); } | |
506 | }; | |
507 | ||
508 | class ScopeExp : public Expression | |
509 | { | |
510 | public: | |
511 | ScopeDsymbol *sds; | |
512 | ||
513 | ScopeExp(Loc loc, ScopeDsymbol *sds); | |
514 | Expression *syntaxCopy(); | |
515 | bool checkType(); | |
516 | bool checkValue(); | |
517 | void accept(Visitor *v) { v->visit(this); } | |
518 | }; | |
519 | ||
520 | class TemplateExp : public Expression | |
521 | { | |
522 | public: | |
523 | TemplateDeclaration *td; | |
524 | FuncDeclaration *fd; | |
525 | ||
526 | TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd = NULL); | |
527 | bool isLvalue(); | |
528 | Expression *toLvalue(Scope *sc, Expression *e); | |
529 | bool checkType(); | |
530 | bool checkValue(); | |
531 | void accept(Visitor *v) { v->visit(this); } | |
532 | }; | |
533 | ||
534 | class NewExp : public Expression | |
535 | { | |
536 | public: | |
537 | /* thisexp.new(newargs) newtype(arguments) | |
538 | */ | |
539 | Expression *thisexp; // if !NULL, 'this' for class being allocated | |
540 | Expressions *newargs; // Array of Expression's to call new operator | |
541 | Type *newtype; | |
542 | Expressions *arguments; // Array of Expression's | |
543 | ||
544 | Expression *argprefix; // expression to be evaluated just before arguments[] | |
545 | ||
546 | CtorDeclaration *member; // constructor function | |
547 | NewDeclaration *allocator; // allocator function | |
548 | int onstack; // allocate on stack | |
549 | ||
550 | NewExp(Loc loc, Expression *thisexp, Expressions *newargs, | |
551 | Type *newtype, Expressions *arguments); | |
552 | static NewExp *create(Loc loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments); | |
553 | Expression *syntaxCopy(); | |
554 | ||
555 | void accept(Visitor *v) { v->visit(this); } | |
556 | }; | |
557 | ||
558 | class NewAnonClassExp : public Expression | |
559 | { | |
560 | public: | |
561 | /* thisexp.new(newargs) class baseclasses { } (arguments) | |
562 | */ | |
563 | Expression *thisexp; // if !NULL, 'this' for class being allocated | |
564 | Expressions *newargs; // Array of Expression's to call new operator | |
565 | ClassDeclaration *cd; // class being instantiated | |
566 | Expressions *arguments; // Array of Expression's to call class constructor | |
567 | ||
568 | NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs, | |
569 | ClassDeclaration *cd, Expressions *arguments); | |
570 | Expression *syntaxCopy(); | |
571 | void accept(Visitor *v) { v->visit(this); } | |
572 | }; | |
573 | ||
574 | class SymbolExp : public Expression | |
575 | { | |
576 | public: | |
577 | Declaration *var; | |
578 | bool hasOverloads; | |
579 | SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads); | |
580 | ||
581 | void accept(Visitor *v) { v->visit(this); } | |
582 | }; | |
583 | ||
584 | // Offset from symbol | |
585 | ||
586 | class SymOffExp : public SymbolExp | |
587 | { | |
588 | public: | |
589 | dinteger_t offset; | |
590 | ||
591 | SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads = true); | |
592 | bool isBool(bool result); | |
593 | ||
594 | void accept(Visitor *v) { v->visit(this); } | |
595 | }; | |
596 | ||
597 | // Variable | |
598 | ||
599 | class VarExp : public SymbolExp | |
600 | { | |
601 | public: | |
602 | VarExp(Loc loc, Declaration *var, bool hasOverloads = true); | |
603 | static VarExp *create(Loc loc, Declaration *var, bool hasOverloads = true); | |
604 | bool equals(RootObject *o); | |
605 | int checkModifiable(Scope *sc, int flag); | |
606 | bool checkReadModifyWrite(); | |
607 | bool isLvalue(); | |
608 | Expression *toLvalue(Scope *sc, Expression *e); | |
609 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
610 | ||
611 | void accept(Visitor *v) { v->visit(this); } | |
612 | }; | |
613 | ||
614 | // Overload Set | |
615 | ||
616 | class OverExp : public Expression | |
617 | { | |
618 | public: | |
619 | OverloadSet *vars; | |
620 | ||
621 | OverExp(Loc loc, OverloadSet *s); | |
622 | bool isLvalue(); | |
623 | Expression *toLvalue(Scope *sc, Expression *e); | |
624 | void accept(Visitor *v) { v->visit(this); } | |
625 | }; | |
626 | ||
627 | // Function/Delegate literal | |
628 | ||
629 | class FuncExp : public Expression | |
630 | { | |
631 | public: | |
632 | FuncLiteralDeclaration *fd; | |
633 | TemplateDeclaration *td; | |
634 | TOK tok; | |
635 | ||
636 | FuncExp(Loc loc, Dsymbol *s); | |
637 | bool equals(RootObject *o); | |
638 | void genIdent(Scope *sc); | |
639 | Expression *syntaxCopy(); | |
640 | MATCH matchType(Type *to, Scope *sc, FuncExp **pfe, int flag = 0); | |
641 | const char *toChars(); | |
642 | bool checkType(); | |
643 | bool checkValue(); | |
644 | ||
645 | void accept(Visitor *v) { v->visit(this); } | |
646 | }; | |
647 | ||
648 | // Declaration of a symbol | |
649 | ||
650 | // D grammar allows declarations only as statements. However in AST representation | |
651 | // it can be part of any expression. This is used, for example, during internal | |
652 | // syntax re-writes to inject hidden symbols. | |
653 | class DeclarationExp : public Expression | |
654 | { | |
655 | public: | |
656 | Dsymbol *declaration; | |
657 | ||
658 | DeclarationExp(Loc loc, Dsymbol *declaration); | |
659 | Expression *syntaxCopy(); | |
660 | ||
661 | bool hasCode(); | |
662 | ||
663 | void accept(Visitor *v) { v->visit(this); } | |
664 | }; | |
665 | ||
666 | class TypeidExp : public Expression | |
667 | { | |
668 | public: | |
669 | RootObject *obj; | |
670 | ||
671 | TypeidExp(Loc loc, RootObject *obj); | |
672 | Expression *syntaxCopy(); | |
673 | void accept(Visitor *v) { v->visit(this); } | |
674 | }; | |
675 | ||
676 | class TraitsExp : public Expression | |
677 | { | |
678 | public: | |
679 | Identifier *ident; | |
680 | Objects *args; | |
681 | ||
682 | TraitsExp(Loc loc, Identifier *ident, Objects *args); | |
683 | Expression *syntaxCopy(); | |
684 | void accept(Visitor *v) { v->visit(this); } | |
685 | }; | |
686 | ||
687 | class HaltExp : public Expression | |
688 | { | |
689 | public: | |
690 | HaltExp(Loc loc); | |
691 | ||
692 | void accept(Visitor *v) { v->visit(this); } | |
693 | }; | |
694 | ||
695 | class IsExp : public Expression | |
696 | { | |
697 | public: | |
698 | /* is(targ id tok tspec) | |
699 | * is(targ id == tok2) | |
700 | */ | |
701 | Type *targ; | |
702 | Identifier *id; // can be NULL | |
703 | TOK tok; // ':' or '==' | |
704 | Type *tspec; // can be NULL | |
705 | TOK tok2; // 'struct', 'union', etc. | |
706 | TemplateParameters *parameters; | |
707 | ||
708 | IsExp(Loc loc, Type *targ, Identifier *id, TOK tok, Type *tspec, | |
709 | TOK tok2, TemplateParameters *parameters); | |
710 | Expression *syntaxCopy(); | |
711 | void accept(Visitor *v) { v->visit(this); } | |
712 | }; | |
713 | ||
714 | /****************************************************************/ | |
715 | ||
716 | class UnaExp : public Expression | |
717 | { | |
718 | public: | |
719 | Expression *e1; | |
720 | Type *att1; // Save alias this type to detect recursion | |
721 | ||
722 | UnaExp(Loc loc, TOK op, int size, Expression *e1); | |
723 | Expression *syntaxCopy(); | |
724 | Expression *incompatibleTypes(); | |
725 | Expression *resolveLoc(Loc loc, Scope *sc); | |
726 | ||
727 | void accept(Visitor *v) { v->visit(this); } | |
728 | }; | |
729 | ||
730 | typedef UnionExp (*fp_t)(Loc loc, Type *, Expression *, Expression *); | |
731 | typedef int (*fp2_t)(Loc loc, TOK, Expression *, Expression *); | |
732 | ||
733 | class BinExp : public Expression | |
734 | { | |
735 | public: | |
736 | Expression *e1; | |
737 | Expression *e2; | |
738 | ||
739 | Type *att1; // Save alias this type to detect recursion | |
740 | Type *att2; // Save alias this type to detect recursion | |
741 | ||
742 | BinExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2); | |
743 | Expression *syntaxCopy(); | |
744 | Expression *incompatibleTypes(); | |
745 | Expression *checkOpAssignTypes(Scope *sc); | |
746 | bool checkIntegralBin(); | |
747 | bool checkArithmeticBin(); | |
748 | ||
749 | Expression *reorderSettingAAElem(Scope *sc); | |
750 | ||
751 | void accept(Visitor *v) { v->visit(this); } | |
752 | }; | |
753 | ||
754 | class BinAssignExp : public BinExp | |
755 | { | |
756 | public: | |
757 | BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2); | |
758 | ||
759 | bool isLvalue(); | |
760 | Expression *toLvalue(Scope *sc, Expression *ex); | |
761 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
762 | void accept(Visitor *v) { v->visit(this); } | |
763 | }; | |
764 | ||
765 | /****************************************************************/ | |
766 | ||
767 | class CompileExp : public UnaExp | |
768 | { | |
769 | public: | |
770 | CompileExp(Loc loc, Expression *e); | |
771 | void accept(Visitor *v) { v->visit(this); } | |
772 | }; | |
773 | ||
774 | class ImportExp : public UnaExp | |
775 | { | |
776 | public: | |
777 | ImportExp(Loc loc, Expression *e); | |
778 | void accept(Visitor *v) { v->visit(this); } | |
779 | }; | |
780 | ||
781 | class AssertExp : public UnaExp | |
782 | { | |
783 | public: | |
784 | Expression *msg; | |
785 | ||
786 | AssertExp(Loc loc, Expression *e, Expression *msg = NULL); | |
787 | Expression *syntaxCopy(); | |
788 | ||
789 | void accept(Visitor *v) { v->visit(this); } | |
790 | }; | |
791 | ||
792 | class DotIdExp : public UnaExp | |
793 | { | |
794 | public: | |
795 | Identifier *ident; | |
796 | bool noderef; // true if the result of the expression will never be dereferenced | |
797 | bool wantsym; // do not replace Symbol with its initializer during semantic() | |
798 | ||
799 | DotIdExp(Loc loc, Expression *e, Identifier *ident); | |
800 | static DotIdExp *create(Loc loc, Expression *e, Identifier *ident); | |
801 | void accept(Visitor *v) { v->visit(this); } | |
802 | }; | |
803 | ||
804 | class DotTemplateExp : public UnaExp | |
805 | { | |
806 | public: | |
807 | TemplateDeclaration *td; | |
808 | ||
809 | DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td); | |
810 | void accept(Visitor *v) { v->visit(this); } | |
811 | }; | |
812 | ||
813 | class DotVarExp : public UnaExp | |
814 | { | |
815 | public: | |
816 | Declaration *var; | |
817 | bool hasOverloads; | |
818 | ||
819 | DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads = true); | |
820 | int checkModifiable(Scope *sc, int flag); | |
821 | bool checkReadModifyWrite(); | |
822 | bool isLvalue(); | |
823 | Expression *toLvalue(Scope *sc, Expression *e); | |
824 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
825 | void accept(Visitor *v) { v->visit(this); } | |
826 | }; | |
827 | ||
828 | class DotTemplateInstanceExp : public UnaExp | |
829 | { | |
830 | public: | |
831 | TemplateInstance *ti; | |
832 | ||
833 | DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs); | |
834 | DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti); | |
835 | Expression *syntaxCopy(); | |
836 | bool findTempDecl(Scope *sc); | |
837 | void accept(Visitor *v) { v->visit(this); } | |
838 | }; | |
839 | ||
840 | class DelegateExp : public UnaExp | |
841 | { | |
842 | public: | |
843 | FuncDeclaration *func; | |
844 | bool hasOverloads; | |
845 | ||
846 | DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, bool hasOverloads = true); | |
847 | ||
848 | void accept(Visitor *v) { v->visit(this); } | |
849 | }; | |
850 | ||
851 | class DotTypeExp : public UnaExp | |
852 | { | |
853 | public: | |
854 | Dsymbol *sym; // symbol that represents a type | |
855 | ||
856 | DotTypeExp(Loc loc, Expression *e, Dsymbol *sym); | |
857 | void accept(Visitor *v) { v->visit(this); } | |
858 | }; | |
859 | ||
860 | class CallExp : public UnaExp | |
861 | { | |
862 | public: | |
863 | Expressions *arguments; // function arguments | |
864 | FuncDeclaration *f; // symbol to call | |
865 | bool directcall; // true if a virtual call is devirtualized | |
866 | CallExp(Loc loc, Expression *e, Expressions *exps); | |
867 | CallExp(Loc loc, Expression *e); | |
868 | CallExp(Loc loc, Expression *e, Expression *earg1); | |
869 | CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2); | |
870 | ||
871 | static CallExp *create(Loc loc, Expression *e, Expressions *exps); | |
872 | static CallExp *create(Loc loc, Expression *e); | |
873 | static CallExp *create(Loc loc, Expression *e, Expression *earg1); | |
874 | ||
875 | Expression *syntaxCopy(); | |
876 | bool isLvalue(); | |
877 | Expression *toLvalue(Scope *sc, Expression *e); | |
878 | Expression *addDtorHook(Scope *sc); | |
879 | ||
880 | void accept(Visitor *v) { v->visit(this); } | |
881 | }; | |
882 | ||
883 | class AddrExp : public UnaExp | |
884 | { | |
885 | public: | |
886 | AddrExp(Loc loc, Expression *e); | |
887 | AddrExp(Loc loc, Expression *e, Type *t); | |
888 | ||
889 | void accept(Visitor *v) { v->visit(this); } | |
890 | }; | |
891 | ||
892 | class PtrExp : public UnaExp | |
893 | { | |
894 | public: | |
895 | PtrExp(Loc loc, Expression *e); | |
896 | PtrExp(Loc loc, Expression *e, Type *t); | |
897 | int checkModifiable(Scope *sc, int flag); | |
898 | bool isLvalue(); | |
899 | Expression *toLvalue(Scope *sc, Expression *e); | |
900 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
901 | ||
902 | void accept(Visitor *v) { v->visit(this); } | |
903 | }; | |
904 | ||
905 | class NegExp : public UnaExp | |
906 | { | |
907 | public: | |
908 | NegExp(Loc loc, Expression *e); | |
909 | ||
910 | void accept(Visitor *v) { v->visit(this); } | |
911 | }; | |
912 | ||
913 | class UAddExp : public UnaExp | |
914 | { | |
915 | public: | |
916 | UAddExp(Loc loc, Expression *e); | |
917 | ||
918 | void accept(Visitor *v) { v->visit(this); } | |
919 | }; | |
920 | ||
921 | class ComExp : public UnaExp | |
922 | { | |
923 | public: | |
924 | ComExp(Loc loc, Expression *e); | |
925 | ||
926 | void accept(Visitor *v) { v->visit(this); } | |
927 | }; | |
928 | ||
929 | class NotExp : public UnaExp | |
930 | { | |
931 | public: | |
932 | NotExp(Loc loc, Expression *e); | |
933 | void accept(Visitor *v) { v->visit(this); } | |
934 | }; | |
935 | ||
936 | class DeleteExp : public UnaExp | |
937 | { | |
938 | public: | |
939 | bool isRAII; | |
940 | DeleteExp(Loc loc, Expression *e, bool isRAII); | |
941 | Expression *toBoolean(Scope *sc); | |
942 | void accept(Visitor *v) { v->visit(this); } | |
943 | }; | |
944 | ||
945 | class CastExp : public UnaExp | |
946 | { | |
947 | public: | |
948 | // Possible to cast to one type while painting to another type | |
949 | Type *to; // type to cast to | |
950 | unsigned char mod; // MODxxxxx | |
951 | ||
952 | CastExp(Loc loc, Expression *e, Type *t); | |
953 | CastExp(Loc loc, Expression *e, unsigned char mod); | |
954 | Expression *syntaxCopy(); | |
955 | ||
956 | void accept(Visitor *v) { v->visit(this); } | |
957 | }; | |
958 | ||
959 | class VectorExp : public UnaExp | |
960 | { | |
961 | public: | |
962 | TypeVector *to; // the target vector type before semantic() | |
963 | unsigned dim; // number of elements in the vector | |
b9da0278 | 964 | OwnedBy ownedByCtfe; |
b4c522fa IB |
965 | |
966 | VectorExp(Loc loc, Expression *e, Type *t); | |
967 | static VectorExp *create(Loc loc, Expression *e, Type *t); | |
968 | Expression *syntaxCopy(); | |
969 | void accept(Visitor *v) { v->visit(this); } | |
970 | }; | |
971 | ||
b9da0278 IB |
972 | class VectorArrayExp : public UnaExp |
973 | { | |
974 | public: | |
975 | VectorArrayExp(Loc loc, Expression *e1); | |
976 | bool isLvalue(); | |
977 | Expression *toLvalue(Scope *sc, Expression *e); | |
978 | void accept(Visitor *v) { v->visit(this); } | |
979 | }; | |
980 | ||
b4c522fa IB |
981 | class SliceExp : public UnaExp |
982 | { | |
983 | public: | |
984 | Expression *upr; // NULL if implicit 0 | |
985 | Expression *lwr; // NULL if implicit [length - 1] | |
986 | VarDeclaration *lengthVar; | |
987 | bool upperIsInBounds; // true if upr <= e1.length | |
988 | bool lowerIsLessThanUpper; // true if lwr <= upr | |
989 | bool arrayop; // an array operation, rather than a slice | |
990 | ||
991 | SliceExp(Loc loc, Expression *e1, IntervalExp *ie); | |
992 | SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr); | |
993 | Expression *syntaxCopy(); | |
994 | int checkModifiable(Scope *sc, int flag); | |
995 | bool isLvalue(); | |
996 | Expression *toLvalue(Scope *sc, Expression *e); | |
997 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
998 | bool isBool(bool result); | |
999 | ||
1000 | void accept(Visitor *v) { v->visit(this); } | |
1001 | }; | |
1002 | ||
1003 | class ArrayLengthExp : public UnaExp | |
1004 | { | |
1005 | public: | |
1006 | ArrayLengthExp(Loc loc, Expression *e1); | |
1007 | ||
1008 | static Expression *rewriteOpAssign(BinExp *exp); | |
1009 | void accept(Visitor *v) { v->visit(this); } | |
1010 | }; | |
1011 | ||
1012 | class IntervalExp : public Expression | |
1013 | { | |
1014 | public: | |
1015 | Expression *lwr; | |
1016 | Expression *upr; | |
1017 | ||
1018 | IntervalExp(Loc loc, Expression *lwr, Expression *upr); | |
1019 | Expression *syntaxCopy(); | |
1020 | void accept(Visitor *v) { v->visit(this); } | |
1021 | }; | |
1022 | ||
1023 | class DelegatePtrExp : public UnaExp | |
1024 | { | |
1025 | public: | |
1026 | DelegatePtrExp(Loc loc, Expression *e1); | |
1027 | bool isLvalue(); | |
1028 | Expression *toLvalue(Scope *sc, Expression *e); | |
1029 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
1030 | void accept(Visitor *v) { v->visit(this); } | |
1031 | }; | |
1032 | ||
1033 | class DelegateFuncptrExp : public UnaExp | |
1034 | { | |
1035 | public: | |
1036 | DelegateFuncptrExp(Loc loc, Expression *e1); | |
1037 | bool isLvalue(); | |
1038 | Expression *toLvalue(Scope *sc, Expression *e); | |
1039 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
1040 | void accept(Visitor *v) { v->visit(this); } | |
1041 | }; | |
1042 | ||
1043 | // e1[a0,a1,a2,a3,...] | |
1044 | ||
1045 | class ArrayExp : public UnaExp | |
1046 | { | |
1047 | public: | |
1048 | Expressions *arguments; // Array of Expression's | |
1049 | size_t currentDimension; // for opDollar | |
1050 | VarDeclaration *lengthVar; | |
1051 | ||
1052 | ArrayExp(Loc loc, Expression *e1, Expression *index = NULL); | |
1053 | ArrayExp(Loc loc, Expression *e1, Expressions *args); | |
1054 | Expression *syntaxCopy(); | |
1055 | bool isLvalue(); | |
1056 | Expression *toLvalue(Scope *sc, Expression *e); | |
1057 | ||
1058 | void accept(Visitor *v) { v->visit(this); } | |
1059 | }; | |
1060 | ||
1061 | /****************************************************************/ | |
1062 | ||
1063 | class DotExp : public BinExp | |
1064 | { | |
1065 | public: | |
1066 | DotExp(Loc loc, Expression *e1, Expression *e2); | |
1067 | void accept(Visitor *v) { v->visit(this); } | |
1068 | }; | |
1069 | ||
1070 | class CommaExp : public BinExp | |
1071 | { | |
1072 | public: | |
1073 | bool isGenerated; | |
1074 | bool allowCommaExp; | |
1075 | CommaExp(Loc loc, Expression *e1, Expression *e2, bool generated = true); | |
1076 | int checkModifiable(Scope *sc, int flag); | |
1077 | bool isLvalue(); | |
1078 | Expression *toLvalue(Scope *sc, Expression *e); | |
1079 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
1080 | bool isBool(bool result); | |
1081 | Expression *toBoolean(Scope *sc); | |
1082 | Expression *addDtorHook(Scope *sc); | |
1083 | void accept(Visitor *v) { v->visit(this); } | |
1084 | }; | |
1085 | ||
1086 | class IndexExp : public BinExp | |
1087 | { | |
1088 | public: | |
1089 | VarDeclaration *lengthVar; | |
1090 | bool modifiable; | |
1091 | bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1 | |
1092 | ||
1093 | IndexExp(Loc loc, Expression *e1, Expression *e2); | |
1094 | Expression *syntaxCopy(); | |
1095 | int checkModifiable(Scope *sc, int flag); | |
1096 | bool isLvalue(); | |
1097 | Expression *toLvalue(Scope *sc, Expression *e); | |
1098 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
1099 | ||
1100 | Expression *markSettingAAElem(); | |
1101 | ||
1102 | void accept(Visitor *v) { v->visit(this); } | |
1103 | }; | |
1104 | ||
1105 | /* For both i++ and i-- | |
1106 | */ | |
1107 | class PostExp : public BinExp | |
1108 | { | |
1109 | public: | |
1110 | PostExp(TOK op, Loc loc, Expression *e); | |
1111 | void accept(Visitor *v) { v->visit(this); } | |
1112 | }; | |
1113 | ||
1114 | /* For both ++i and --i | |
1115 | */ | |
1116 | class PreExp : public UnaExp | |
1117 | { | |
1118 | public: | |
1119 | PreExp(TOK op, Loc loc, Expression *e); | |
1120 | void accept(Visitor *v) { v->visit(this); } | |
1121 | }; | |
1122 | ||
1123 | enum MemorySet | |
1124 | { | |
1125 | blockAssign = 1, // setting the contents of an array | |
1126 | referenceInit = 2 // setting the reference of STCref variable | |
1127 | }; | |
1128 | ||
1129 | class AssignExp : public BinExp | |
1130 | { | |
1131 | public: | |
1132 | int memset; // combination of MemorySet flags | |
1133 | ||
1134 | AssignExp(Loc loc, Expression *e1, Expression *e2); | |
1135 | bool isLvalue(); | |
1136 | Expression *toLvalue(Scope *sc, Expression *ex); | |
1137 | Expression *toBoolean(Scope *sc); | |
1138 | ||
1139 | void accept(Visitor *v) { v->visit(this); } | |
1140 | }; | |
1141 | ||
1142 | class ConstructExp : public AssignExp | |
1143 | { | |
1144 | public: | |
1145 | ConstructExp(Loc loc, Expression *e1, Expression *e2); | |
1146 | ConstructExp(Loc loc, VarDeclaration *v, Expression *e2); | |
1147 | void accept(Visitor *v) { v->visit(this); } | |
1148 | }; | |
1149 | ||
1150 | class BlitExp : public AssignExp | |
1151 | { | |
1152 | public: | |
1153 | BlitExp(Loc loc, Expression *e1, Expression *e2); | |
1154 | BlitExp(Loc loc, VarDeclaration *v, Expression *e2); | |
1155 | void accept(Visitor *v) { v->visit(this); } | |
1156 | }; | |
1157 | ||
1158 | class AddAssignExp : public BinAssignExp | |
1159 | { | |
1160 | public: | |
1161 | AddAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1162 | void accept(Visitor *v) { v->visit(this); } | |
1163 | }; | |
1164 | ||
1165 | class MinAssignExp : public BinAssignExp | |
1166 | { | |
1167 | public: | |
1168 | MinAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1169 | void accept(Visitor *v) { v->visit(this); } | |
1170 | }; | |
1171 | ||
1172 | class MulAssignExp : public BinAssignExp | |
1173 | { | |
1174 | public: | |
1175 | MulAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1176 | void accept(Visitor *v) { v->visit(this); } | |
1177 | }; | |
1178 | ||
1179 | class DivAssignExp : public BinAssignExp | |
1180 | { | |
1181 | public: | |
1182 | DivAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1183 | void accept(Visitor *v) { v->visit(this); } | |
1184 | }; | |
1185 | ||
1186 | class ModAssignExp : public BinAssignExp | |
1187 | { | |
1188 | public: | |
1189 | ModAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1190 | void accept(Visitor *v) { v->visit(this); } | |
1191 | }; | |
1192 | ||
1193 | class AndAssignExp : public BinAssignExp | |
1194 | { | |
1195 | public: | |
1196 | AndAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1197 | void accept(Visitor *v) { v->visit(this); } | |
1198 | }; | |
1199 | ||
1200 | class OrAssignExp : public BinAssignExp | |
1201 | { | |
1202 | public: | |
1203 | OrAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1204 | void accept(Visitor *v) { v->visit(this); } | |
1205 | }; | |
1206 | ||
1207 | class XorAssignExp : public BinAssignExp | |
1208 | { | |
1209 | public: | |
1210 | XorAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1211 | void accept(Visitor *v) { v->visit(this); } | |
1212 | }; | |
1213 | ||
1214 | class PowAssignExp : public BinAssignExp | |
1215 | { | |
1216 | public: | |
1217 | PowAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1218 | void accept(Visitor *v) { v->visit(this); } | |
1219 | }; | |
1220 | ||
1221 | class ShlAssignExp : public BinAssignExp | |
1222 | { | |
1223 | public: | |
1224 | ShlAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1225 | void accept(Visitor *v) { v->visit(this); } | |
1226 | }; | |
1227 | ||
1228 | class ShrAssignExp : public BinAssignExp | |
1229 | { | |
1230 | public: | |
1231 | ShrAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1232 | void accept(Visitor *v) { v->visit(this); } | |
1233 | }; | |
1234 | ||
1235 | class UshrAssignExp : public BinAssignExp | |
1236 | { | |
1237 | public: | |
1238 | UshrAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1239 | void accept(Visitor *v) { v->visit(this); } | |
1240 | }; | |
1241 | ||
1242 | class CatAssignExp : public BinAssignExp | |
1243 | { | |
1244 | public: | |
1245 | CatAssignExp(Loc loc, Expression *e1, Expression *e2); | |
1246 | void accept(Visitor *v) { v->visit(this); } | |
1247 | }; | |
1248 | ||
1249 | class AddExp : public BinExp | |
1250 | { | |
1251 | public: | |
1252 | AddExp(Loc loc, Expression *e1, Expression *e2); | |
1253 | ||
1254 | void accept(Visitor *v) { v->visit(this); } | |
1255 | }; | |
1256 | ||
1257 | class MinExp : public BinExp | |
1258 | { | |
1259 | public: | |
1260 | MinExp(Loc loc, Expression *e1, Expression *e2); | |
1261 | ||
1262 | void accept(Visitor *v) { v->visit(this); } | |
1263 | }; | |
1264 | ||
1265 | class CatExp : public BinExp | |
1266 | { | |
1267 | public: | |
1268 | CatExp(Loc loc, Expression *e1, Expression *e2); | |
1269 | ||
1270 | void accept(Visitor *v) { v->visit(this); } | |
1271 | }; | |
1272 | ||
1273 | class MulExp : public BinExp | |
1274 | { | |
1275 | public: | |
1276 | MulExp(Loc loc, Expression *e1, Expression *e2); | |
1277 | ||
1278 | void accept(Visitor *v) { v->visit(this); } | |
1279 | }; | |
1280 | ||
1281 | class DivExp : public BinExp | |
1282 | { | |
1283 | public: | |
1284 | DivExp(Loc loc, Expression *e1, Expression *e2); | |
1285 | ||
1286 | void accept(Visitor *v) { v->visit(this); } | |
1287 | }; | |
1288 | ||
1289 | class ModExp : public BinExp | |
1290 | { | |
1291 | public: | |
1292 | ModExp(Loc loc, Expression *e1, Expression *e2); | |
1293 | ||
1294 | void accept(Visitor *v) { v->visit(this); } | |
1295 | }; | |
1296 | ||
1297 | class PowExp : public BinExp | |
1298 | { | |
1299 | public: | |
1300 | PowExp(Loc loc, Expression *e1, Expression *e2); | |
1301 | ||
1302 | void accept(Visitor *v) { v->visit(this); } | |
1303 | }; | |
1304 | ||
1305 | class ShlExp : public BinExp | |
1306 | { | |
1307 | public: | |
1308 | ShlExp(Loc loc, Expression *e1, Expression *e2); | |
1309 | ||
1310 | void accept(Visitor *v) { v->visit(this); } | |
1311 | }; | |
1312 | ||
1313 | class ShrExp : public BinExp | |
1314 | { | |
1315 | public: | |
1316 | ShrExp(Loc loc, Expression *e1, Expression *e2); | |
1317 | ||
1318 | void accept(Visitor *v) { v->visit(this); } | |
1319 | }; | |
1320 | ||
1321 | class UshrExp : public BinExp | |
1322 | { | |
1323 | public: | |
1324 | UshrExp(Loc loc, Expression *e1, Expression *e2); | |
1325 | ||
1326 | void accept(Visitor *v) { v->visit(this); } | |
1327 | }; | |
1328 | ||
1329 | class AndExp : public BinExp | |
1330 | { | |
1331 | public: | |
1332 | AndExp(Loc loc, Expression *e1, Expression *e2); | |
1333 | ||
1334 | void accept(Visitor *v) { v->visit(this); } | |
1335 | }; | |
1336 | ||
1337 | class OrExp : public BinExp | |
1338 | { | |
1339 | public: | |
1340 | OrExp(Loc loc, Expression *e1, Expression *e2); | |
1341 | ||
1342 | void accept(Visitor *v) { v->visit(this); } | |
1343 | }; | |
1344 | ||
1345 | class XorExp : public BinExp | |
1346 | { | |
1347 | public: | |
1348 | XorExp(Loc loc, Expression *e1, Expression *e2); | |
1349 | ||
1350 | void accept(Visitor *v) { v->visit(this); } | |
1351 | }; | |
1352 | ||
1353 | class OrOrExp : public BinExp | |
1354 | { | |
1355 | public: | |
1356 | OrOrExp(Loc loc, Expression *e1, Expression *e2); | |
1357 | Expression *toBoolean(Scope *sc); | |
1358 | void accept(Visitor *v) { v->visit(this); } | |
1359 | }; | |
1360 | ||
1361 | class AndAndExp : public BinExp | |
1362 | { | |
1363 | public: | |
1364 | AndAndExp(Loc loc, Expression *e1, Expression *e2); | |
1365 | Expression *toBoolean(Scope *sc); | |
1366 | void accept(Visitor *v) { v->visit(this); } | |
1367 | }; | |
1368 | ||
1369 | class CmpExp : public BinExp | |
1370 | { | |
1371 | public: | |
1372 | CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2); | |
1373 | ||
1374 | void accept(Visitor *v) { v->visit(this); } | |
1375 | }; | |
1376 | ||
1377 | class InExp : public BinExp | |
1378 | { | |
1379 | public: | |
1380 | InExp(Loc loc, Expression *e1, Expression *e2); | |
1381 | ||
1382 | void accept(Visitor *v) { v->visit(this); } | |
1383 | }; | |
1384 | ||
1385 | class RemoveExp : public BinExp | |
1386 | { | |
1387 | public: | |
1388 | RemoveExp(Loc loc, Expression *e1, Expression *e2); | |
1389 | void accept(Visitor *v) { v->visit(this); } | |
1390 | }; | |
1391 | ||
1392 | // == and != | |
1393 | ||
1394 | class EqualExp : public BinExp | |
1395 | { | |
1396 | public: | |
1397 | EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2); | |
1398 | ||
1399 | void accept(Visitor *v) { v->visit(this); } | |
1400 | }; | |
1401 | ||
1402 | // is and !is | |
1403 | ||
1404 | class IdentityExp : public BinExp | |
1405 | { | |
1406 | public: | |
1407 | IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2); | |
1408 | void accept(Visitor *v) { v->visit(this); } | |
1409 | }; | |
1410 | ||
1411 | /****************************************************************/ | |
1412 | ||
1413 | class CondExp : public BinExp | |
1414 | { | |
1415 | public: | |
1416 | Expression *econd; | |
1417 | ||
1418 | CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2); | |
1419 | Expression *syntaxCopy(); | |
1420 | int checkModifiable(Scope *sc, int flag); | |
1421 | bool isLvalue(); | |
1422 | Expression *toLvalue(Scope *sc, Expression *e); | |
1423 | Expression *modifiableLvalue(Scope *sc, Expression *e); | |
1424 | Expression *toBoolean(Scope *sc); | |
1425 | void hookDtors(Scope *sc); | |
1426 | ||
1427 | void accept(Visitor *v) { v->visit(this); } | |
1428 | }; | |
1429 | ||
1430 | /****************************************************************/ | |
1431 | ||
1432 | class DefaultInitExp : public Expression | |
1433 | { | |
1434 | public: | |
1435 | TOK subop; // which of the derived classes this is | |
1436 | ||
1437 | DefaultInitExp(Loc loc, TOK subop, int size); | |
1438 | void accept(Visitor *v) { v->visit(this); } | |
1439 | }; | |
1440 | ||
1441 | class FileInitExp : public DefaultInitExp | |
1442 | { | |
1443 | public: | |
1444 | FileInitExp(Loc loc, TOK tok); | |
1445 | Expression *resolveLoc(Loc loc, Scope *sc); | |
1446 | void accept(Visitor *v) { v->visit(this); } | |
1447 | }; | |
1448 | ||
1449 | class LineInitExp : public DefaultInitExp | |
1450 | { | |
1451 | public: | |
1452 | LineInitExp(Loc loc); | |
1453 | Expression *resolveLoc(Loc loc, Scope *sc); | |
1454 | void accept(Visitor *v) { v->visit(this); } | |
1455 | }; | |
1456 | ||
1457 | class ModuleInitExp : public DefaultInitExp | |
1458 | { | |
1459 | public: | |
1460 | ModuleInitExp(Loc loc); | |
1461 | Expression *resolveLoc(Loc loc, Scope *sc); | |
1462 | void accept(Visitor *v) { v->visit(this); } | |
1463 | }; | |
1464 | ||
1465 | class FuncInitExp : public DefaultInitExp | |
1466 | { | |
1467 | public: | |
1468 | FuncInitExp(Loc loc); | |
1469 | Expression *resolveLoc(Loc loc, Scope *sc); | |
1470 | void accept(Visitor *v) { v->visit(this); } | |
1471 | }; | |
1472 | ||
1473 | class PrettyFuncInitExp : public DefaultInitExp | |
1474 | { | |
1475 | public: | |
1476 | PrettyFuncInitExp(Loc loc); | |
1477 | Expression *resolveLoc(Loc loc, Scope *sc); | |
1478 | void accept(Visitor *v) { v->visit(this); } | |
1479 | }; | |
1480 | ||
1481 | /****************************************************************/ | |
1482 | ||
1483 | /* A type meant as a union of all the Expression types, | |
1484 | * to serve essentially as a Variant that will sit on the stack | |
1485 | * during CTFE to reduce memory consumption. | |
1486 | */ | |
1487 | struct UnionExp | |
1488 | { | |
1489 | UnionExp() { } // yes, default constructor does nothing | |
1490 | ||
1491 | UnionExp(Expression *e) | |
1492 | { | |
1493 | memcpy(this, (void *)e, e->size); | |
1494 | } | |
1495 | ||
1496 | /* Extract pointer to Expression | |
1497 | */ | |
1498 | Expression *exp() { return (Expression *)&u; } | |
1499 | ||
1500 | /* Convert to an allocated Expression | |
1501 | */ | |
1502 | Expression *copy(); | |
1503 | ||
1504 | private: | |
f9ab59ff IB |
1505 | // Ensure that the union is suitably aligned. |
1506 | #if defined(__GNUC__) || defined(__clang__) | |
1507 | __attribute__((aligned(8))) | |
1508 | #elif defined(_MSC_VER) | |
1509 | __declspec(align(8)) | |
1510 | #elif defined(__DMC__) | |
1511 | #pragma pack(8) | |
1512 | #endif | |
b4c522fa IB |
1513 | union |
1514 | { | |
1515 | char exp [sizeof(Expression)]; | |
1516 | char integerexp[sizeof(IntegerExp)]; | |
1517 | char errorexp [sizeof(ErrorExp)]; | |
1518 | char realexp [sizeof(RealExp)]; | |
1519 | char complexexp[sizeof(ComplexExp)]; | |
1520 | char symoffexp [sizeof(SymOffExp)]; | |
1521 | char stringexp [sizeof(StringExp)]; | |
1522 | char arrayliteralexp [sizeof(ArrayLiteralExp)]; | |
1523 | char assocarrayliteralexp [sizeof(AssocArrayLiteralExp)]; | |
1524 | char structliteralexp [sizeof(StructLiteralExp)]; | |
1525 | char nullexp [sizeof(NullExp)]; | |
1526 | char dotvarexp [sizeof(DotVarExp)]; | |
1527 | char addrexp [sizeof(AddrExp)]; | |
1528 | char indexexp [sizeof(IndexExp)]; | |
1529 | char sliceexp [sizeof(SliceExp)]; | |
b9da0278 | 1530 | char vectorexp [sizeof(VectorExp)]; |
b4c522fa | 1531 | } u; |
f9ab59ff IB |
1532 | #if defined(__DMC__) |
1533 | #pragma pack() | |
1534 | #endif | |
b4c522fa IB |
1535 | }; |
1536 | ||
1537 | /****************************************************************/ | |
1538 | ||
1539 | /* Special values used by the interpreter | |
1540 | */ | |
1541 | ||
1542 | Expression *expType(Type *type, Expression *e); | |
1543 | ||
1544 | UnionExp Neg(Type *type, Expression *e1); | |
1545 | UnionExp Com(Type *type, Expression *e1); | |
1546 | UnionExp Not(Type *type, Expression *e1); | |
1547 | UnionExp Bool(Type *type, Expression *e1); | |
1548 | UnionExp Cast(Loc loc, Type *type, Type *to, Expression *e1); | |
1549 | UnionExp ArrayLength(Type *type, Expression *e1); | |
1550 | UnionExp Ptr(Type *type, Expression *e1); | |
1551 | ||
1552 | UnionExp Add(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1553 | UnionExp Min(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1554 | UnionExp Mul(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1555 | UnionExp Div(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1556 | UnionExp Mod(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1557 | UnionExp Pow(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1558 | UnionExp Shl(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1559 | UnionExp Shr(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1560 | UnionExp Ushr(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1561 | UnionExp And(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1562 | UnionExp Or(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1563 | UnionExp Xor(Loc loc, Type *type, Expression *e1, Expression *e2); | |
1564 | UnionExp Index(Type *type, Expression *e1, Expression *e2); | |
1565 | UnionExp Cat(Type *type, Expression *e1, Expression *e2); | |
1566 | ||
1567 | UnionExp Equal(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2); | |
1568 | UnionExp Cmp(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2); | |
1569 | UnionExp Identity(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2); | |
1570 | ||
1571 | UnionExp Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr); | |
1572 | ||
1573 | // Const-folding functions used by CTFE | |
1574 | ||
1575 | void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex); | |
1576 | void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex); | |
1577 | void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex); | |
1578 | ||
1579 | int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len); | |
1580 | int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len); |