Ejemplo n.º 1
0
        public static Block DoRestoreTypeIs(Block hir)
        {
            if (hir.Family().OfType<TypeAs>().None()) return hir;
            else
            {
                return hir.Transform((Operator op) =>
                {
                    var is_rel = op.OperatorType.IsRelational();
                    if (is_rel)
                    {
                        var bin = op.AssertCast<BinaryOperator>();
                        var opt = bin.OperatorType;

                        var needs_xform = bin.Lhs is TypeAs ^ bin.Rhs is TypeAs;
                        if (needs_xform)
                        {
                            var type_as = bin.Lhs as TypeAs ?? bin.Rhs as TypeAs;
                            var other = bin.Lhs == type_as ? bin.Rhs : bin.Lhs;
                            other.AssertCast<Const>().AssertThat(c => c.Value == null);

                            var pos = opt == OperatorType.NotEqual || opt == OperatorType.GreaterThan;
                            var neg = opt == OperatorType.Equal || opt == OperatorType.LessThanOrEqual;
                            (pos || neg).AssertTrue();

                            var type_is = new TypeIs(type_as.Type, type_as.Target) as Expression;
                            return pos ? type_is : Operator.Negate(type_is);
                        }
                        else
                        {
                            return op.DefaultTransform();
                        }
                    }
                    else
                    {
                        return op.DefaultTransform();
                    }
                }).AssertCast<Block>();
            }
        }
Ejemplo n.º 2
0
        public static Block DoRestoreBooleans(Block hir)
        {
            // todo. also think about how to support nullables
            var types = hir.InferTypes();
            return (Block)hir.Transform(
                (If @if) =>
                {
                    var is_bool = types[@if.Test] == typeof(bool);
                    var ensuredTest = is_bool ? @if.Test.CurrentTransform() : @if.Test.EnsureBoolean(types);
                    var ifTrue = @if.IfTrue.CurrentTransform();
                    var ifFalse = @if.IfFalse.CurrentTransform();
                    return new If(ensuredTest, ifTrue, ifFalse);
                },
                (Assign ass) =>
                {
                    if (types[ass.Lhs] == typeof(bool))
                    {
                        var lhs = ass.Lhs.CurrentTransform();
                        var ensuredRhs = ass.Rhs.EnsureBoolean(types);
                        return new Assign(lhs, ensuredRhs);
                    }
                    else
                    {
                        return ass.DefaultTransform();
                    }
                },
                (Apply app) =>
                {
                    ReadOnlyCollection<Type> targs = null;
                    if (app.Callee is Prop)
                    {
                        var p = app.Callee.InvokedProperty();
                        if (p != null) targs = p.GetIndexParameters().Select(pi => pi.ParameterType).ToReadOnly();
                    }
                    else
                    {
                        var ftype = types[app.Callee];
                        if (ftype != null) targs = ftype.DasmFType().SkipLast(1).ToReadOnly();
                    }

                    if (targs == null) return app.DefaultTransform();
                    var ensuredArgs = targs.Select((targ, i) =>
                    {
                        var arg = app.Args[i];
                        var is_bool = targ == typeof(bool);
                        return is_bool ? arg.EnsureBoolean(types) : arg.CurrentTransform();
                    });

                    var callee = app.Callee.CurrentTransform();
                    return new Apply(callee, ensuredArgs);
                },
                (Conditional cond) =>
                {
                    var anyBool = types[cond.IfTrue] == typeof(bool) || types[cond.IfFalse] == typeof(bool);
                    var is_bool = types[cond.Test] == typeof(bool);
                    var ensuredTest = is_bool ? cond.Test.CurrentTransform() : cond.Test.EnsureBoolean(types);
                    var ifTrue = anyBool ? cond.IfTrue.EnsureBoolean(types) : cond.IfTrue.CurrentTransform();
                    var ifFalse = anyBool ? cond.IfFalse.EnsureBoolean(types) : cond.IfFalse.CurrentTransform();
                    return new Conditional(ensuredTest, ifTrue, ifFalse);
                },
                (Operator op) =>
                {
                    var opt = op.OperatorType;
                    var anyBool = op.Args.Any(arg => types[arg] == typeof(bool));
                    var alwaysBool = opt == OperatorType.AndAlso || 
                        opt == OperatorType.OrElse || opt == OperatorType.Not;
                    var ensureBool = anyBool || alwaysBool;
                    if (ensureBool)
                    {
                        if (opt == OperatorType.And) opt = OperatorType.AndAlso;
                        if (opt == OperatorType.Or) opt = OperatorType.OrElse;
                        if (opt == OperatorType.Negate) opt = OperatorType.Not;

                        var ensuredArgs = op.Args.Select(arg => arg.EnsureBoolean(types));
                        return Operator.Create(opt, ensuredArgs);
                    }
                    else
                    {
                        return op.DefaultTransform();
                    }
                });
        }