Exemplo n.º 1
0
        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 }));
        }
Exemplo n.º 2
0
        IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(DefineExpr expr)
        {
            var stores = new List<IBoundExpr>();

            foreach (var define in expr.Definitions)
            {
                foreach (var name in define.Names)
                {
                    if (Scope.Contains(name)) throw new CompileException(define.Position,
                        "A local variable named \"" + name + "\" is already defined in this scope.");
                }

                var value = define.Value.Accept(this);

                if (define.Names.Count > 1)
                {

                    // splitting a tuple
                    var tupleType = value.Type as BoundTupleType;

                    if (tupleType == null) throw new CompileException(define.Position,
                        "Cannot define multiple names if the value is not a tuple.");

                    if (tupleType.Fields.Count < define.Names.Count) throw new CompileException(define.Position,
                        "Cannot bind more names in a define than the tuple has fields.");

                    // define a temporary for the entire tuple expression
                    var temp = mContext.NameGenerator.Generate();
                    Scope.Define(temp, value.Type, false);

                    // split out the fields
                    int field = 0;
                    foreach (var name in define.Names)
                    {
                        Scope.Define(name, tupleType.Fields[field], expr.IsMutable);

                        // assign it
                        var fieldValue = new LoadExpr(value, tupleType.Fields[field], field);
                        stores.Add(new StoreExpr(new LocalsExpr(), Scope[name], fieldValue));

                        field++;
                    }
                }
                else
                {
                    // just a single variable

                    // add it to the scope
                    Scope.Define(define.Names[0], value.Type, expr.IsMutable);

                    // assign it
                    stores.Add(new StoreExpr(new LocalsExpr(), Scope[define.Names[0]], value));
                }
            }

            return new BoundBlockExpr(stores);
        }
Exemplo n.º 3
0
 IUnboundExpr IUnboundExprVisitor <IUnboundExpr> .Visit(DefineExpr expr)
 {
     /*
      * //### bob: hack temp. doesn't work with multiple defines
      * return Call("DefineExpr", Tuple(
      *  Bool(expr.IsMutable),
      *  String(expr.Definitions[0].Name),
      *  expr.Definitions[0].Value.Accept(this)));
      */
     throw new NotImplementedException();
 }
 public virtual IUnboundExpr Transform(DefineExpr expr)
 {
     return(expr);
 }