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