protected SemanticContext _getPredicates(NFAState s, NFAState altStartState) { // System.out.println("_getPredicates("+s+")"); if (s.isAcceptState()) { return null; } // avoid infinite loops from (..)* etc... if (lookBusy.contains(s)) { return null; } lookBusy.add(s); Transition transition0 = s.transition[0]; // no transitions if (transition0 == null) { return null; } // not a predicate and not even an epsilon if (!(transition0.label.isSemanticPredicate() || transition0.label.isEpsilon())) { return null; } SemanticContext p = null; SemanticContext p0 = null; SemanticContext p1 = null; if (transition0.label.isSemanticPredicate()) { // System.out.println("pred "+transition0.label); p = transition0.label.getSemanticContext(); // ignore backtracking preds not on left edge for this decision if (((SemanticContext.Predicate) p).predicateAST.getType() == ANTLRParser.BACKTRACK_SEMPRED && s == altStartState.transition[0].target) { p = null; // don't count } } // get preds from beyond this state p0 = _getPredicates((NFAState) transition0.target, altStartState); // get preds from other transition Transition transition1 = s.transition[1]; if (transition1 != null) { p1 = _getPredicates((NFAState) transition1.target, altStartState); } // join this&following-right|following-down return SemanticContext.and(p, SemanticContext.or(p0, p1)); }
@Override public Statement syntaxCopy(SemanticContext context) { CaseStatement s = context.newCaseStatement( filename, lineNumber, exp.syntaxCopy(context), statement.syntaxCopy(context)); s.copySourceRange(this); return s; }
@Override public boolean canThrow(SemanticContext context) { if (context.isD2()) { VarDeclaration v = declaration.isVarDeclaration(); if (v != null && v.init != null) { ExpInitializer ie = v.init.isExpInitializer(); return ie != null && ie.exp.canThrow(context); } return false; } else { return super.canThrow(context); } }
@Override public Expression interpret(InterState istate, SemanticContext context) { Expression e = EXP_CANT_INTERPRET; VarDeclaration v = declaration.isVarDeclaration(); if (v != null) { Dsymbol s = v.toAlias(context); if (s == v && !v.isStatic() && v.init() != null) { ExpInitializer ie = v.init().isExpInitializer(); if (ie != null) { e = ie.exp.interpret(istate, context); } else if (v.init().isVoidInitializer() != null) { e = null; } } else { boolean condition; if (context.isD2()) { condition = s == v && (v.isConst() || v.isInvariant(context)) && v.init != null; } else { condition = s == v && v.isConst() && v.init() != null; } if (condition) { e = v.init().toExpression(context); if (null == e) { e = EXP_CANT_INTERPRET; } else if (null == e.type) { e.type = v.type; } } else if (declaration.isAttribDeclaration() != null || declaration.isTemplateMixin() != null || declaration.isTupleDeclaration() != null) { // These can be made to work, too lazy now e = EXP_CANT_INTERPRET; } else { // Others should not contain executable code, so are trivial to evaluate e = null; } } } return e; }
@Override public Expression semantic(Scope sc, SemanticContext context) { if (type != null) { return this; } /* This is here to support extern(linkage) declaration, * where the extern(linkage) winds up being an AttribDeclaration * wrapper. */ Dsymbol s = declaration; AttribDeclaration ad = declaration.isAttribDeclaration(); if (ad != null) { if (ad.decl != null && ad.decl.size() == 1) { s = ad.decl.get(0); } } if (s.isVarDeclaration() != null) { // Do semantic() on initializer first, so: // int a = a; // will be illegal. declaration.semantic(sc, context); s.parent = sc.parent; } // Insert into both local scope and function scope. // Must be unique in both. if (s.ident != null) { if (sc.insert(s) == null) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.DeclarationIsAlreadyDefined, s, s.toChars(context))); } } else if (sc.func != null) { // VarDeclaration v = s.isVarDeclaration(); if ((s.isFuncDeclaration() != null /*|| v && v.storage_class & STCstatic*/) && sc.func.localsymtab.insert(s) == null) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeError( IProblem.DeclarationIsAlreadyDefinedInAnotherScope, this, s.toPrettyChars(context), sc.func.toChars(context))); } } else if (!context.global.params.useDeprecated) { // Disallow shadowing for (Scope scx = sc.enclosing; scx != null && scx.func == sc.func; scx = scx.enclosing) { Dsymbol s2; if (scx.scopesym != null && scx.scopesym.symtab != null && (s2 = scx.scopesym.symtab.lookup(s.ident)) != null && s != s2) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.ShadowingDeclarationIsDeprecated, s, s.toPrettyChars(context))); } } } } } } if (s.isVarDeclaration() == null) { declaration.semantic(sc, context); s.parent = sc.parent; } // Commented this for Descent: we want semantic even if there are errors // if (context.global.errors == 0) { declaration.semantic2(sc, context); // if (context.global.errors == 0) { declaration.semantic3(sc, context); // } // } type = Type.tvoid; return this; }
@Override public Statement semantic(Scope sc, SemanticContext context) { SwitchStatement sw = sc.sw; this.sw = sw; exp = exp.semantic(sc, context); if (sw != null) { int i; exp = exp.implicitCastTo(sc, sw.condition.type, context); exp = exp.optimize(WANTvalue | WANTinterpret, context); boolean gotoL1 = false; if (context.isD2()) { /* This is where variables are allowed as case expressions. */ if (exp.op == TOKvar) { VarExp ve = (VarExp) exp; VarDeclaration v = ve.var.isVarDeclaration(); Type t = exp.type.toBasetype(context); if (v != null && (t.isintegral() || t.ty == Tclass)) { /* Flag that we need to do special code generation * for this, i.e. generate a sequence of if-then-else */ sw.hasVars = 1; // goto L1; gotoL1 = true; } } } if (!gotoL1) { if (exp.op != TOKstring && exp.op != TOKint64) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeError( IProblem.CaseMustBeAnIntegralOrStringConstant, sourceExp, exp.toChars(context))); } exp = new IntegerExp(0); } } // L1: for (i = 0; i < sw.cases.size(); i++) { CaseStatement cs = (CaseStatement) sw.cases.get(i); if (cs.exp.equals(exp, context)) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.DuplicateCaseInSwitchStatement, this, exp.toChars(context))); } break; } } sw.cases.add(this); // Resolve any goto case's with no exp to this case statement if (sw.gotoCases != null) { for (i = 0; i < sw.gotoCases.size(); i++) { GotoCaseStatement gcs = (GotoCaseStatement) sw.gotoCases.get(i); if (gcs.exp == null) { gcs.cs = this; sw.gotoCases.remove(i); // remove from array } } } if (context.isD2()) { if (sc.sw.tf != sc.tf) { if (context.acceptsErrors()) { context.acceptProblem( Problem.newSemanticTypeErrorLoc( IProblem.SwitchAndCaseAreInDifferentFinallyBlocks, this)); } } } } else { if (context.acceptsErrors()) { context.acceptProblem(Problem.newSemanticTypeError(IProblem.CaseIsNotInSwitch, this)); } } statement = statement.semantic(sc, context); return this; }