/* 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; }