IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(AssignExpr expr)
        {
            var value = expr.Value.Accept(this);

            if (expr.Target is TupleExpr) throw new NotSupportedException("Assignment to a tuple must be simplified before binding.");

            // handle a name target: foo <- 3
            var nameTarget = expr.Target as NameExpr;
            if (nameTarget != null)
            {
                // see if it's a local
                if (Scope.Contains(nameTarget.Name))
                {
                    if (!Scope.IsMutable(nameTarget.Name)) throw new CompileException(expr.Position, "Cannot assign to immutable local.");

                    // direct assign to local
                    return new StoreExpr(new LocalsExpr(), Scope[nameTarget.Name], value);
                }

                // look for an assignment function
                return TranslateAssignment(nameTarget.Position, nameTarget.Name, nameTarget.TypeArgs, new UnitExpr(Position.None), value);
            }

            // handle a function apply target: Foo 1 <- 3  ==> Foo<- (1, 3)
            var callTarget = expr.Target as CallExpr;
            if (callTarget != null)
            {
                var callArg = callTarget.Arg.Accept(this);

                // see if it's a direct function call
                var funcName = callTarget.Target as NameExpr;
                if ((funcName != null) && !mContext.Compiler.IsLocal(mFunction, Scope, funcName.Name))
                {
                    // translate the call
                    return TranslateAssignment(callTarget.Position, funcName.Name, funcName.TypeArgs, callArg, value);
                }

                // not calling a function, so try to desugar to a __Call<-
                var desugaredCallTarget = callTarget.Target.Accept(this);
                var desugaredCallArg = new BoundTupleExpr(new IBoundExpr[] { desugaredCallTarget, callArg, value });

                var call = mContext.ResolveFunction(mFunction, expr.Target.Position,
                    "__Call<-", new IUnboundDecl[0], desugaredCallArg);

                if (call != null) return call;

                throw new CompileException(expr.Position, "Couldn't figure out what you're trying to do on the left side of an assignment.");
            }

            // if we got here, it's not a valid assignment expression
            throw new CompileException(expr.Position, "Cannot assign to " + expr.Target);
        }
        public override IUnboundExpr Transform(AssignExpr expr)
        {
            // replaces:
            //
            //     a, b <- Foo
            //
            // with:
            //
            //     def __temp1 <- Foo
            //     a <- _temp1.0
            //     b <- _temp1.1

            TupleExpr tuple = expr.Target as TupleExpr;

            // ignore other assignments
            if (tuple == null)
            {
                return(expr);
            }

            var exprs = new List <IUnboundExpr>();

            var temp = mNameGenerator.Generate();

            // evaluate the right-hand side once
            exprs.Add(new DefineExpr(expr.Target.Position, temp, expr.Value, false));

            // split out the fields
            int index = 0;

            foreach (var field in tuple.Fields)
            {
                exprs.Add(new AssignExpr(expr.Position, field, new CallExpr(new IntExpr(index), new NameExpr(expr.Position, temp))));
                index++;
            }

            return(new BlockExpr(false, exprs));
        }
 public virtual IUnboundExpr Transform(AssignExpr expr)
 {
     return(expr);
 }
Exemple #4
0
 IUnboundExpr IUnboundExprVisitor <IUnboundExpr> .Visit(AssignExpr expr)
 {
     return(Call("AssignExpr", Tuple(expr.Target.Accept(this), expr.Value.Accept(this))));
 }