| |
| /* Compiler implementation of the D programming language |
| * Copyright (C) 1999-2019 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" |
| |
| Expression *semantic(Expression *e, Scope *sc); |
| |
| /******************************************** |
| * 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) |
| { |
| AndAndExp *aae = (AndAndExp *)e; |
| bool result = evalStaticCondition(sc, exp, aae->e1, errors); |
| if (errors || !result) |
| return false; |
| result = evalStaticCondition(sc, exp, aae->e2, errors); |
| return !errors && result; |
| } |
| |
| if (e->op == TOKoror) |
| { |
| OrOrExp *ooe = (OrOrExp *)e; |
| bool result = evalStaticCondition(sc, exp, ooe->e1, errors); |
| if (errors) |
| return false; |
| if (result) |
| return true; |
| result = evalStaticCondition(sc, exp, ooe->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 = semantic(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; |
| } |