public static IUnboundExpr Match(BindingContext context, MatchExpr expr, IBoundExpr boundValue) { // validate the patterns ShapeChecker.Validate(expr, boundValue.Type); Coverage.Validate(expr, boundValue.Type); // convert the cases to vanilla if/then blocks var valueName = context.NameGenerator.Generate(); var defineValueExpr = new DefineExpr(expr.Value.Position, valueName, expr.Value, false); var valueExpr = new NameExpr(expr.Value.Position, valueName); var conditions = new List <DesugaredMatchCase>(); foreach (var matchCase in expr.Cases) { var result = new DesugaredMatchCase(); result.Condition = Match(context, boundValue.Type, matchCase.Pattern, valueExpr, result.Variables); conditions.Add(result); } // build a single compound "if" expression var ifExpr = (IUnboundExpr)null; if (expr.Cases.Count == 0) { throw new CompileException(expr.Position, "Match expression has no cases."); } else if (expr.Cases.Count == 1) { // if there is only a since case, and we've ensured exhaustivity already, // then it must match all values, so just use the body directly ifExpr = CreateCaseBody(conditions[0].Variables, expr.Cases[0].Body); } else { // go in reverse order so that we start with the trailing else and build // forward for (int i = expr.Cases.Count - 1; i >= 0; i--) { if (ifExpr == null) { // for the first popped (i.e. last appearing) case, we know it must // match because the match expression is exhaustive, so just use its // body directly ifExpr = CreateCaseBody(conditions[i].Variables, expr.Cases[i].Body); } else { var body = CreateCaseBody(conditions[i].Variables, expr.Cases[i].Body); ifExpr = new IfExpr(expr.Cases[i].Position, conditions[i].Condition, body, ifExpr); } } } return(new BlockExpr(new IUnboundExpr[] { defineValueExpr, ifExpr })); }
public static void Validate(MatchExpr expr, IBoundDecl valueType) { foreach (var matchCase in expr.Cases) { var usedVariables = new Dictionary <string, bool>(); matchCase.Pattern.Accept(new ShapeChecker(valueType, usedVariables)); } }
IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(MatchExpr expr) { // bind the value expression var boundValue = expr.Value.Accept(this); // convert the patterns to desugared conditional expressions var desugaredMatch = PatternMatcher.Match(mContext, expr, boundValue); // bind the desugared form return desugaredMatch.Accept(this); }
public static void Validate(MatchExpr expr, IBoundDecl valueType) { var coverage = new Coverage(valueType); foreach (var matchCase in expr.Cases) { if (coverage.CoverPattern(matchCase.Pattern)) { throw new CompileException(matchCase.Position, "This pattern will never be matched because previous patterns cover it."); } } // make sure the cases are exhaustive if (!coverage.FullyCovered) { throw new CompileException(expr.Position, "Not all possible values will be matched."); } }
public virtual IUnboundExpr Transform(MatchExpr expr) { return(expr); }
IUnboundExpr IUnboundExprVisitor <IUnboundExpr> .Visit(MatchExpr expr) { throw new NotImplementedException(); }