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 }));
        }
Beispiel #2
0
 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);
        }
Beispiel #4
0
        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);
 }
Beispiel #6
0
 IUnboundExpr IUnboundExprVisitor <IUnboundExpr> .Visit(MatchExpr expr)
 {
     throw new NotImplementedException();
 }