Пример #1
0
 public override Node AcceptTransformer(AbstractHirTransformer transformer, bool forceDefaultImpl)
 {
     if (forceDefaultImpl)
     {
         var args  = Args.Select(arg => transformer.Transform(arg)).AssertCast <Expression>();
         var clone = Operator.Create(OperatorType, args);
         clone.Proto = this;
         return(clone);
     }
     else
     {
         return(transformer.TransformOperator(this).HasProto(this));
     }
 }
        public static Node UnsafeExpandOpAssign(this Node root)
        {
            return(root.Transform((Operator op) =>
            {
                var opt = op.OperatorType;
                if (!opt.IsAssign())
                {
                    return (Expression)op.DefaultTransform();
                }

                var lhs = op.Args.FirstOrDefault();
                var rhs = op.Args.SecondOrDefault() ?? new Const(1); // hack for inc/decrements
                return new Assign(lhs, Operator.Create(opt.Unassign(), lhs, rhs));
            }).AssertCast <Node>());
        }
        public static Node SafeExpandOpAssign(this Node root, out Dictionary <Operator, Assign> out_roots)
        {
            var roots  = new Dictionary <Operator, Assign>();
            var x_root = root.Transform((Operator op) =>
            {
                var opt = op.OperatorType;
                if (!opt.IsAssign())
                {
                    return((Expression)op.DefaultTransform());
                }

                Func <Expression, Expression> mk_safe_lhs = lhs =>
                {
                    var @ref = lhs as Ref;
                    if (@ref != null)
                    {
                        return(lhs);
                    }

                    var slot = lhs as Slot;
                    if (slot != null)
                    {
                        var @this = slot.This;
                        if (@this == null || @this is Ref)
                        {
                            return(lhs);
                        }
                        else
                        {
                            var ass_root = @this.DeepClone();
                            var ref_root = new Ref(new Local(null, ass_root.Type()));
                            var ass      = new Assign(ref_root, ass_root);
                            roots.Add(op, ass);

                            var fld = slot as Fld;
                            if (fld != null)
                            {
                                return(new Fld(fld.Field, ref_root));
                            }

                            var prop = slot as Prop;
                            if (prop != null)
                            {
                                return(new Prop(prop.Property, ref_root, prop.InvokedAsVirtual));
                            }

                            throw AssertionHelper.Fail();
                        }
                    }

                    var eval = lhs as Eval;
                    var m    = eval == null ? null : eval.InvokedMethod();
                    if (m != null && m.IsArrayGetter())
                    {
                        var app   = eval.Callee;
                        var @this = eval.Callee.Args.First();

                        if (@this == null || @this is Ref)
                        {
                            return(lhs);
                        }
                        else
                        {
                            var ass_root = @this.DeepClone();
                            var ref_root = new Ref(new Local(null, ass_root.Type()));
                            var ass      = new Assign(ref_root, ass_root);
                            roots.Add(op, ass);

                            return(new Eval(new Apply(new Lambda(m), ref_root.Concat(app.Args.Skip(1)))));
                        }
                    }

                    throw AssertionHelper.Fail();
                };

                var safe_lhs = mk_safe_lhs(op.Args.FirstOrDefault());
                var rhs      = op.Args.SecondOrDefault() ?? new Const(1); // hack for inc/decrements
                return(new Assign(safe_lhs, Operator.Create(opt.Unassign(), safe_lhs, rhs)));
            }).AssertCast <Node>();

            out_roots = roots;
            return(x_root);
        }