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