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); }