1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
/* Compiler implementation of the D programming language
* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* http://www.boost.org/LICENSE_1_0.txt
* https://github.com/D-Programming-Language/dmd/blob/master/src/staticcond.c
*/
#include "mars.h"
#include "expression.h"
#include "mtype.h"
#include "scope.h"
/********************************************
* Semantically analyze and then evaluate a static condition at compile time.
* This is special because short circuit operators &&, || and ?: at the top
* level are not semantically analyzed if the result of the expression is not
* necessary.
* Params:
* exp = original expression, for error messages
* Returns:
* true if evaluates to true
*/
bool evalStaticCondition(Scope *sc, Expression *exp, Expression *e, bool &errors)
{
if (e->op == TOKandand || e->op == TOKoror)
{
LogicalExp *aae = (LogicalExp *)e;
bool result = evalStaticCondition(sc, exp, aae->e1, errors);
if (errors)
return false;
if (e->op == TOKandand)
{
if (!result)
return false;
}
else
{
if (result)
return true;
}
result = evalStaticCondition(sc, exp, aae->e2, errors);
return !errors && result;
}
if (e->op == TOKquestion)
{
CondExp *ce = (CondExp *)e;
bool result = evalStaticCondition(sc, exp, ce->econd, errors);
if (errors)
return false;
Expression *leg = result ? ce->e1 : ce->e2;
result = evalStaticCondition(sc, exp, leg, errors);
return !errors && result;
}
unsigned nerrors = global.errors;
sc = sc->startCTFE();
sc->flags |= SCOPEcondition;
e = expressionSemantic(e, sc);
e = resolveProperties(sc, e);
sc = sc->endCTFE();
e = e->optimize(WANTvalue);
if (nerrors != global.errors ||
e->op == TOKerror ||
e->type->toBasetype() == Type::terror)
{
errors = true;
return false;
}
if (!e->type->isBoolean())
{
exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars());
errors = true;
return false;
}
e = e->ctfeInterpret();
if (e->isBool(true))
return true;
else if (e->isBool(false))
return false;
e->error("expression %s is not constant", e->toChars());
errors = true;
return false;
}
|