public DekiScriptOutputBuffer.Range Visit(DekiScriptSwitch expr, DekiScriptExpressionEvaluationState state) { DekiScriptLiteral value = state.Pop(expr.Value.VisitWith(this, state)); DekiScriptSwitch.CaseBlock caseBlock = null; // have to use for instead of foreach, since a fallthrough default case needs to be able to look ahead for (int i = 0; i < expr.Cases.Length; i++) { DekiScriptSwitch.CaseBlock current = expr.Cases[i]; // check for default case foreach (DekiScriptExpression condition in current.Conditions) { if (condition == null) { // check if this is the first default we've found if (caseBlock == null) { caseBlock = current; } // continue in case loop, since default only gets executed if there is no match continue; } // evaluate test DekiScriptExpression test = DekiScriptExpression.BinaryOp(current.Location, DekiScriptBinary.Op.Equal, value, condition); DekiScriptLiteral caseMatch = state.Pop(test.VisitWith(this, state)); // evaluate body on success if (!caseMatch.IsNilFalseZero) { // found a matching cast statement caseBlock = current; break; } } } // haven't found a match yet, so if we have a default, return it if (caseBlock != null) { int marker = state.Buffer.Marker; try { return(caseBlock.Body.VisitWith(this, state)); } catch (DekiScriptBreakException) { // nothing to do } return(state.Buffer.Since(marker)); } return(DekiScriptOutputBuffer.Range.Empty); }
public DekiScriptLiteral Visit(DekiScriptSwitch expr, DekiScriptEnv env) { DekiScriptLiteral value = expr.Value.VisitWith(this, env); DekiScriptCaseBlock defaultCase = null; // have to use for instead of foreach, since a fallthrough default case needs to be able to look ahead for (int i = 0; i < expr.Cases.Length; i++) { DekiScriptCaseBlock c = expr.Cases[i]; // check for default case DekiScriptEnv locals = env.NewLocalScope(); foreach (DekiScriptExpression condition in c.Conditions) { if (condition == null) { // check if this is the first default we've found if (defaultCase == null) { defaultCase = c; } // continue in case loop, since default only gets executed if there is no match continue; } // evaluate test DekiScriptBinary test = new DekiScriptBinary(0, 0, DekiScriptBinary.Op.Equal, value, condition); DekiScriptLiteral caseMatch = test.VisitWith(this, locals); // evaluate body on success if (!caseMatch.IsNilFalseZero) { return(EvalBody(locals, c.Body)); } } } // haven't found a match yet, so if we have a default, return it if (defaultCase != null) { return(EvalBody(env.NewLocalScope(), defaultCase.Body)); } return(DekiScriptNil.Value); }
public DekiScriptExpression Visit(DekiScriptSwitch expr, DekiScriptExpressionEvaluationState state) { DekiScriptExpression value = expr.Value.VisitWith(this, state); List <DekiScriptSwitch.CaseBlock> cases = new List <DekiScriptSwitch.CaseBlock>(); int defaultCaseIndex = -1; for (int i = 0; i < expr.Cases.Length; ++i) { bool isDefaultCase; object outcome = Optimize(expr.Cases[i], value, state, out isDefaultCase); if (outcome is DekiScriptExpression) { return((DekiScriptExpression)outcome); } if (outcome != null) { cases.Add((DekiScriptSwitch.CaseBlock)outcome); } // check if case block contains a default case statement if (isDefaultCase && (defaultCaseIndex == -1)) { defaultCaseIndex = cases.Count - 1; } } // check if all matches failed, but we found a default branch if ((cases.Count == 1) && (defaultCaseIndex == 0) && (cases[0].Conditions.Length == 1)) { return(cases[0].Body); } if (cases.Count > 0) { return(DekiScriptExpression.SwitchStatement(expr.Location, value, cases.ToArray())); } return(DekiScriptNil.Value); }
void CaseStatement(out DekiScriptSwitch.CaseBlock block) { List<DekiScriptExpression> conditions = new List<DekiScriptExpression>(); DekiScriptExpression caseexpr = null; DekiScriptExpression expr = DekiScriptNil.Value; Location location = t.Location; if (la.kind == 30) { Get(); Expression(out caseexpr); Expect(31); conditions.Add(caseexpr); } else if (la.kind == 32) { Get(); Expect(31); conditions.Add(null); } else SynErr(81); while (la.kind == 30 || la.kind == 32) { if (la.kind == 30) { Get(); Expression(out caseexpr); Expect(31); conditions.Add(caseexpr); } else { Get(); Expect(31); conditions.Add(null); } } if (StartOf(1)) { if (la.kind == 9) { Get(); if (StartOf(1)) { Statements(out expr); } Expect(10); } else { Statements(out expr); } } block = DekiScriptExpression.SwitchCaseBlock(location, conditions, expr); }