Example #1
0
        internal override Expression ToExpression(MethodBinderContext context, Expression[] parameters)
        {
            // Ideally we'd pass in Ast.ReadField(parameters[Index], "Value") but due to
            // a bug in partial trust we can't access the generic field.

            // arg is boxType ? &_tmp : throw new ArgumentTypeException()
            //   IncorrectBoxType throws the exception to avoid stack imbalance issues.
            return(Ast.Condition(
                       Ast.TypeIs(parameters[Index], BoxType),
                       Ast.Comma(
                           Ast.Assign(
                               _tmp,
                               Ast.Call(
                                   typeof(BinderOps).GetMethod("GetBox").MakeGenericMethod(_elementType),
                                   Ast.ConvertHelper(parameters[Index], typeof(StrongBox <>).MakeGenericType(_elementType))
                                   )
                               ),
                           Ast.Read(_tmp)
                           ),
                       // Condition requires types of both expressions to be identical.
                       // Putting the cast here is a temporary workaround until the
                       // emit address and reference argument passing is finished.
                       Ast.Convert(
                           Ast.Call(
                               typeof(BinderOps).GetMethod("IncorrectBoxType"),
                               Ast.Constant(BoxType),
                               Ast.ConvertHelper(parameters[Index], typeof(object))
                               ),
                           _elementType
                           )
                       ));
        }
Example #2
0
        internal override Expression GetBoundValue(ActionBinder binder, Type type, Expression instance)
        {
            if (DeclaringType.IsGenericType && DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox <>))
            {
                // work around a CLR bug where we can't access generic fields from dynamic methods.
                return(Ast.Call(
                           typeof(BinderOps).GetMethod("GetBox").MakeGenericMethod(DeclaringType.GetGenericArguments()),
                           Ast.ConvertHelper(instance, DeclaringType)
                           ));
            }

            if (IsPublic && DeclaringType.IsPublic)
            {
                return(Ast.ReadField(
                           Ast.Convert(instance, Field.DeclaringType),
                           Field
                           ));
            }

            return(Ast.Call(
                       Ast.ConvertHelper(Ast.RuntimeConstant(Field), typeof(FieldInfo)),
                       typeof(FieldInfo).GetMethod("GetValue"),
                       Ast.ConvertHelper(instance, typeof(object))
                       ));
        }
Example #3
0
        public static Expression MakeTypeTestExpression(Type t, Expression expr)
        {
            // we must always check for non-sealed types explicitly - otherwise we end up
            // doing fast-path behavior on a subtype which overrides behavior that wasn't
            // present for the base type.
            //TODO there's a question about nulls here
            if (CompilerHelpers.IsSealed(t) && t == expr.Type)
            {
                if (t.IsValueType)
                {
                    return(Ast.True());
                }
                return(Ast.NotEqual(expr, Ast.Null()));
            }

            return(Ast.AndAlso(
                       Ast.NotEqual(
                           expr,
                           Ast.Null()),
                       Ast.Equal(
                           Ast.Call(
                               Ast.ConvertHelper(expr, typeof(object)),
                               typeof(object).GetMethod("GetType")
                               ),
                           Ast.Constant(t)
                           )
                       ));
        }
Example #4
0
        public static Expression Apply(Expression[] args)
        {
            if (args.Length == 0)
            {
                return(null);
            }

            Expression c = Ast.ConvertHelper(args[0], typeof(Callable));

            if (args.Length > 1)
            {
                Expression arg = Ast.ConvertHelper(args[args.Length - 1], typeof(object));

                if (arg.IsConstant(null))
                {
                    Debugger.Break();
                }

                for (int i = args.Length - 2; i > 0; i--)
                {
                    arg = MakeCons(args[i], arg);
                }

                return(Ast.ComplexCallHelper(c, ICallable_Call, Ast.Call(ListToVector, arg)));
            }
            else
            {
                return(null);
            }
        }
Example #5
0
        static Expression MakeCallBack(Variable proc, Expression[] a)
        {
            var        procr = Ast.ConvertHelper(Ast.Read(proc), typeof(Callable));
            MethodInfo call  = GetCallable(a.Length);
            var        expr  = Ast.Call(procr, call, a);

            return(expr);
        }
Example #6
0
 public static Expression ByteVectorSet(Expression[] values)
 {
     if (values.Length == 3)
     {
         return(Ast.AssignArrayIndex(Ast.ConvertHelper(values[0], typeof(byte[])), Ast.ConvertHelper(values[1], typeof(int)), Ast.ConvertHelper(values[2], typeof(byte))));
     }
     UnsafeSyntaxError("$bytevector-set!", "expected 3 arguments", values);
     return(null);
 }
Example #7
0
 /// <summary>
 /// Helper to produce a rule when no conversion is required (the strong type of the expression
 /// input matches the type we're converting to or has an implicit conversion at the IL level)
 /// </summary>
 private void MakeSimpleConversionTarget(Type toType)
 {
     _rule.SetTarget(
         _rule.MakeReturn(
             Binder,
             Ast.ConvertHelper(_rule.Parameters[0], toType)
             )
         );
 }
Example #8
0
 public static Expression ByteVectorRef(Expression[] values)
 {
     if (values.Length == 2)
     {
         return(Ast.Convert(Ast.ArrayIndex(Ast.ConvertHelper(values[0], typeof(byte[])), Ast.ConvertHelper(values[1], typeof(int))), typeof(int)));
     }
     UnsafeSyntaxError("$bytevector-ref", "expected 2 arguments", values);
     return(null);
 }
Example #9
0
        public override Expression Generate(object args, CodeBlock cb)
        {
            SymbolId s = (SymbolId)Builtins.First(args);

            assigns[s] = true;

            if (libraryglobals.ContainsKey(s))
            {
                libraryglobals.Remove(s);
            }

            if (libraryglobalsN.ContainsKey(s))
            {
                libraryglobalsN.Remove(s);
            }

            if (libraryglobalsX.ContainsKey(s))
            {
                libraryglobalsX.Remove(s);
            }


            setstack.Push(s);

            NameHint = Builtins.UnGenSymInternal(s);
            var prevvh = VarHint;

            VarHint = s;
            Expression value = GetAst(Builtins.Second(args), cb);

            VarHint = prevvh;
            setstack.Pop();

            NameHint = SymbolId.Invalid;

            Variable  v = cb.Lookup(s);
            Statement r = null;

            if (v == null)
            {
                r = Ast.Statement(Ast.SimpleCallHelper(SetSymbolValue, Ast.Constant(s), value));
            }
            else
            {
                //Trace.Assert(cb.Parent != null);
                value = Ast.ConvertHelper(value, v.Type);
                r     = Ast.Write(v, value);
            }

            if (SpanHint != SourceSpan.Invalid || SpanHint != SourceSpan.None)
            {
                r.SetLoc(SpanHint);
            }

            return(Ast.Void(r));
        }
Example #10
0
 static Expression UnwrapAndCast <T>(Expression e)
 {
     e = Unwrap(e);
     if (e.Type == typeof(object) || e.Type == typeof(T) || (typeof(T) == typeof(int) && e.Type == typeof(byte)))
     {
         return(Ast.ConvertHelper(Unwrap(e), typeof(T)));
     }
     UnsafeSyntaxError("UnwrapAndCast", "Expected fixnum, but got " + e.Type.Name + ".", e);
     return(null);
 }
Example #11
0
 /// <summary>
 /// Helper to extract the Value of an Extensible of T from the
 /// expression being converted.
 /// </summary>
 private Expression GetExtensibleValue(Type extType)
 {
     return(Ast.ReadProperty(
                Ast.ConvertHelper(
                    _rule.Parameters[0],
                    extType
                    ),
                extType.GetProperty("Value")
                ));
 }
Example #12
0
        protected static Expression ConvertToHelper(Type t, Expression e)
        {
            if (t.IsAssignableFrom(e.Type))
            {
                return(e);
            }

            else
            if (t.BaseType == typeof(MulticastDelegate))
            {
                return(Ast.SimpleCallHelper(Helpers_ConvertToDelegate.MakeGenericMethod(t), e));
            }
            else
            if (t.BaseType == typeof(Enum))
            {
                if (e.Type.IsValueType)
                {
                    e = Ast.ConvertHelper(e, typeof(object));
                }
                return(Ast.SimpleCallHelper(Helpers_SymbolToEnum.MakeGenericMethod(t), e));
            }
            else
            {
                // prevent boxing
                if (e is UnaryExpression && e.Type == typeof(object))
                {
                    var ue = (UnaryExpression)e;
                    if (t.IsAssignableFrom(ue.Operand.Type))
                    {
                        return(ue.Operand);
                    }
                }
                if (t.IsArray && t != typeof(byte[]) && t != typeof(char[]))
                {
                    return(Ast.SimpleCallHelper(Helpers_RequiresArray.MakeGenericMethod(t.GetElementType()), e));
                }
                else
                {
                    //if (e is ConstantExpression && ((ConstantExpression)e).Value == null)
                    //{
                    //  return e;
                    //}

                    if (TypeHelpersEnabled)
                    {
                        return(Ast.SimpleCallHelper(Helpers_Requires.MakeGenericMethod(t), e));
                    }
                    else
                    {
                        return(Ast.ConvertHelper(e, t));
                    }
                }
            }
        }
Example #13
0
 public static Expression VectorSet(Expression[] values)
 {
     if (values.Length == 3)
     {
         if (!typeof(Array).IsAssignableFrom(values[0].Type))
         {
             values[0] = Ast.ConvertHelper(values[0], typeof(object[]));
         }
         return(Ast.AssignArrayIndex(values[0], Ast.ConvertHelper(values[1], typeof(int)), values[2]));
     }
     UnsafeSyntaxError("$vector-set!", "expected 3 arguments", values);
     return(null);
 }
Example #14
0
 /// <summary>
 /// Helper to produce the rule for converting T to Nullable of T
 /// </summary>
 private void MakeTToNullableOfTTarget(Type toType, Type knownType)
 {
     // T -> Nullable<T>
     _rule.SetTarget(
         _rule.MakeReturn(
             Binder,
             Ast.New(
                 toType.GetConstructor(new Type[] { knownType }),
                 Ast.ConvertHelper(_rule.Parameters[0], knownType)
                 )
             )
         );
 }
Example #15
0
        /// <summary>
        /// Helper to produce a rule when no conversion is required from an extensible type's
        /// underlying storage to the type we're converting to.  The type of extensible type
        /// matches the type we're converting to or has an implicit conversion at the IL level.
        /// </summary>
        /// <param name="toType"></param>
        private void MakeSimpleExtensibleConversionTarget(Type toType)
        {
            Type extType = typeof(Extensible <>).MakeGenericType(toType);

            _rule.SetTarget(
                _rule.MakeReturn(
                    Binder,
                    Ast.ConvertHelper(
                        GetExtensibleValue(extType),
                        toType
                        )
                    )
                );
        }
        public override Expression ConvertExpression(Expression expr, Type toType)
        {
            if (toType == typeof(object))
            {
                return(expr);
            }
            Expression expr2 = IronScheme.Compiler.Generator.Unwrap(expr);

            if (expr2.Type == toType)
            {
                return(expr2);
            }
            return(Ast.ConvertHelper(expr, toType));
        }
Example #17
0
        static Expression RewriteExpression(CodeBlock cb, Expression e)
        {
            if (e is MethodCallExpression)
            {
                MethodCallExpression mce  = (MethodCallExpression)e;
                List <Expression>    args = new List <Expression>();
                foreach (var arg in mce.Arguments)
                {
                    args.Add(RewriteExpression(cb, arg));
                }

                return(Ast.Call(RewriteExpression(cb, mce.Instance), mce.Method, args.ToArray()));
            }
            if (e is BoundExpression)
            {
                BoundExpression be = (BoundExpression)e;
                return(Ast.Read(cb.Lookup(be.Variable.Name)));
            }

            if (e is BinaryExpression)
            {
                BinaryExpression be = (BinaryExpression)e;
                return(new BinaryExpression(be.NodeType, RewriteExpression(cb, be.Left), RewriteExpression(cb, be.Right)));
            }

            if (e is UnaryExpression)
            {
                UnaryExpression ue = (UnaryExpression)e;
                if (ue.NodeType == AstNodeType.Convert)
                {
                    return(Ast.ConvertHelper(RewriteExpression(cb, ue.Operand), ue.Type));
                }
                return(null);
            }

            if (e is TypeBinaryExpression)
            {
                TypeBinaryExpression tbe = (TypeBinaryExpression)e;
                return(Ast.TypeIs(RewriteExpression(cb, tbe.Expression), tbe.TypeOperand));
            }

            if (e is ConditionalExpression)
            {
                ConditionalExpression ce = (ConditionalExpression)e;
                return(Ast.Condition(RewriteExpression(cb, ce.Test), RewriteExpression(cb, ce.IfTrue), RewriteExpression(cb, ce.IfFalse)));
            }

            return(e);
        }
Example #18
0
            public static Expression BooleanOr(Expression[] args)
            {
                int len = args.Length;

                switch (len)
                {
                case 0:
                    return(Ast.Constant(false));

                default:
                    var rargs = new Expression[len - 1];
                    Array.Copy(args, 1, rargs, 0, rargs.Length);
                    return(Ast.OrElse(Ast.ConvertHelper(args[0], typeof(bool)), BooleanOr(rargs)));
                }
            }
Example #19
0
 private void MakeSetCustomMemberRule()
 {
     AddToBody(
         Rule.MakeReturn(Binder,
                         MakeReturnValue(
                             Ast.Call(
                                 Ast.Convert(Rule.Parameters[0], typeof(ICustomMembers)),
                                 typeof(ICustomMembers).GetMethod("SetCustomMember"),
                                 Ast.CodeContext(),
                                 Ast.Constant(Action.Name),
                                 Ast.ConvertHelper(Rule.Parameters[1], typeof(object))
                                 )
                             )
                         )
         );
 }
Example #20
0
 protected static Expression ConvertFromHelper(Type t, Expression e)
 {
     if (t == typeof(void))
     {
         return(Ast.Comma(e, Ast.ReadField(null, Unspecified)));
     }
     else if (t.BaseType == typeof(Enum))
     {
         return(Ast.SimpleCallHelper(Helpers_EnumToSymbol.MakeGenericMethod(t), e));
     }
     else if (t.IsValueType)
     {
         return(Ast.ConvertHelper(e, typeof(object)));
     }
     else
     {
         return(e);
     }
 }
Example #21
0
        static Expression GetConsVector(object[] v, CodeBlock cb)
        {
            List <Expression> e = new List <Expression>();

            foreach (object var in v)
            {
                Cons c = var as Cons;
                e.Add(GetCons(var, cb));
            }

            for (int i = 0; i < e.Count; i++)
            {
                if (e[i].Type.IsValueType)
                {
                    e[i] = Ast.ConvertHelper(e[i], typeof(object));
                }
            }

            return(Ast.NewArray(typeof(object[]), e.ToArray()));
        }
Example #22
0
        static Expression ConsAccessor(Expression[] values, FieldInfo field)
        {
            if (values.Length != 1)
            {
                return(null);
            }
            Expression         e = values[0];
            ConstantExpression c = e as ConstantExpression;

            if (c != null && c.Value == null)
            {
                return(null);
            }

            if (e.Type != typeof(object) && e.Type != typeof(Cons))
            {
                return(null);
            }
            return(Ast.ReadField(Ast.ConvertHelper(e, typeof(Cons)), field));
        }
Example #23
0
            static Expression ConsAccessor(Expression[] values, FieldInfo field)
            {
                if (values.Length != 1)
                {
                    UnsafeSyntaxError(field.Name, "incorrect number of arguments", values);
                }
                Expression         e = values[0];
                ConstantExpression c = e as ConstantExpression;

                if (c != null && c.Value == null)
                {
                    UnsafeSyntaxError(field.Name, "unexpected constant expression", values);
                }

                if (e.Type != typeof(object) && e.Type != typeof(Cons))
                {
                    UnsafeSyntaxError(field.Name, "unexpected type", values);
                }
                return(Ast.ReadField(Ast.ConvertHelper(e, typeof(Cons)), field));
            }
Example #24
0
                protected override void PostWalk(WriteStatement node)
                {
                    base.PostWalk(node);

                    var v   = node.Variable;
                    var val = node.Value;

                    if (v.Type == typeof(object))
                    {
                        if (val.Type != typeof(object) && val.Type != typeof(SymbolId) && !v.Uninitialized)
                        {
                            v.Type = val.Type;
                        }
                    }
                    else if (v.Type != val.Type)
                    {
                        v.Type = typeof(object);
                    }
                    else if (v.Type == typeof(Callable))
                    {
                        var uv = Unwrap(val);
                        if (!uv.Type.IsAssignableFrom(v.Type))
                        {
                            v.Type     = typeof(object);
                            node.Value = Ast.ConvertHelper(Unwrap(val), typeof(object));
                        }
                        else
                        {
                            writecounts[node.Variable]--;
                        }
                    }
                    else
                    {
                        writecounts[node.Variable]--;
                    }

                    if (writecounts[node.Variable] > 1)
                    {
                        v.Type = typeof(object);
                    }
                }
Example #25
0
        protected static Expression[] GetAstList(Cons c, CodeBlock cb, bool castdown)
        {
            List <Expression> e = new List <Expression>();

            while (c != null)
            {
                if (c.cdr != null && !(c.cdr is Cons))
                {
                    Builtins.SyntaxError("GetAstList", "improper list cant be used as an expression", c, Builtins.FALSE);
                }
                iscontinuation = e.Count == 0;
                Expression ex = GetAst(c.car, cb);
                iscontinuation = false;

                if (castdown && ex.Type.IsValueType)
                {
                    ex = Ast.ConvertHelper(ex, typeof(object));
                }
                e.Add(ex);
                c = c.cdr as Cons;
            }
            return(e.ToArray());
        }
Example #26
0
        public Expression AddTemplatedWeakConstant(Type type, object value)
        {
            if (value != null)
            {
                if (!type.IsAssignableFrom(value.GetType()))
                {
                    throw new ArgumentException("type must be assignable from value");
                }
            }
            else
            {
                if (!type.IsValueType)
                {
                    throw new ArgumentException("value must not be null for value types");
                }
            }

            Expression expr = AddTemplatedConstant(typeof(WeakReference), new WeakReference(value));

            return(Ast.ConvertHelper(
                       Ast.ReadProperty(expr, typeof(WeakReference).GetProperty("Target")),
                       type
                       ));
        }
Example #27
0
        public override Expression GetValue(ActionBinder binder, Type type)
        {
            if (Field.IsLiteral)
            {
                return(Ast.Constant(Field.GetValue(null)));
            }

            if (!IsStatic)
            {
                // return the field tracker...
                return(binder.ReturnMemberTracker(type, this));
            }

            if (IsPublic && DeclaringType.IsPublic)
            {
                return(Ast.ReadField(null, Field));
            }

            return(Ast.Call(
                       Ast.ConvertHelper(Ast.RuntimeConstant(Field), typeof(FieldInfo)),
                       typeof(FieldInfo).GetMethod("GetValue"),
                       Ast.Null()
                       ));
        }
        public override Expression Generate(object args, CodeBlock c)
        {
            var ns = ClrGenerator.SaveReferences();

            Cons name = (args as Cons).car as Cons;

            bool isprogram = name == null;

            string[] fullname = Array.ConvertAll <object, string>(Builtins.ListToVector(name), SymbolToString);

            string n = string.Join(".", fullname);

            NameHint = SymbolTable.StringToId(n);
            CodeBlock cb = Ast.CodeBlock(SpanHint, GetLambdaName(c));

            cb.IsGlobal = true;

            List <SymbolId>   vars        = new List <SymbolId>();
            List <Variable>   locals      = new List <Variable>();
            List <Expression> assignments = new List <Expression>();

            List <object> defs    = new List <object>();
            List <object> bodies  = new List <object>();
            List <object> sources = new List <object>();

            args = (args as Cons).cdr;

            Cons a = (args as Cons).car as Cons;

            while (a != null)
            {
                Cons d = a.car as Cons;

                SymbolId v = (SymbolId)d.car;
                SymbolId l = (SymbolId)((Cons)d.cdr).car;
                vars.Add(l);
                locals.Add(Create(v, cb, typeof(object)));

                defs.Add(((Cons)((Cons)d.cdr).cdr).car);

                a = a.cdr as Cons;
            }

#if DONE
            // pass 0 - record defs
            for (int i = 0; i < vars.Count; i++)
            {
                if (IsMakeRecord(defs[i]))
                {
                    //Debugger.Break();

                    Type type = CreateRecordType(defs[i] as Cons);
                    if (type != null)
                    {
                        ClrGenerator.AddCompileTimeType(type);
                    }
                }
            }
#endif

            List <Statement> stmts = new List <Statement>();

            // pass 1
            for (int i = 0; i < vars.Count; i++)
            {
                sources.Add(null);
                bool annotated, typed;
                if (IsLambda(defs[i], out annotated, out typed))
                {
                    Cons cl = defs[i] as Cons;

                    sources[i] = Copy(cl);

                    int depth = GetDepth(sources[i]);

                    if (depth > 10)
                    {
                        sources[i] = null;
                    }

                    if (annotated)
                    {
                        cl = cl.cdr as Cons;
                    }

                    if (cl.cdr != null)
                    {
                        if (((Cons)cl.cdr).cdr == null)
                        {
                            Cons bh = (Cons)((Cons)cl.cdr).car;

                            if (typed)
                            {
                                bh = bh.cdr as Cons;
                            }

                            Cons b = bh.cdr as Cons;
                            bh.cdr = new Cons(Builtins.FALSE);

                            bodies.Add(b);
                        }
                        else
                        {
                            List <Cons> cbs = new List <Cons>();

                            Cons cc = cl.cdr as Cons;

                            while (cc != null)
                            {
                                Cons bh = (Cons)cc.car;

                                if (typed)
                                {
                                    bh = bh.cdr as Cons;
                                }

                                Cons b = bh.cdr as Cons;
                                bh.cdr = new Cons(Builtins.FALSE);
                                cbs.Add(b);
                                cc = cc.cdr as Cons;
                            }

                            bodies.Add(cbs);
                        }
                    }
                    else
                    {
                        bodies.Add(null);
                    }
                }
                else
                {
                    bodies.Add(null);
                }

                VarHint  = locals[i].Name;
                VarHint2 = vars[i];

                NameHint = SymbolTable.StringToId(n + "::" + Builtins.UnGenSymInternal(vars[i]));
                Expression e = GetAst(defs[i], cb);
                VarHint = VarHint2 = SymbolId.Empty;

                if (e is UnaryExpression && e.NodeType == AstNodeType.Convert && e.Type != typeof(object))
                {
                    locals[i].Type = e.Type;
                }
                else if (e.Type.IsValueType)
                {
                    e = Ast.ConvertHelper(e, typeof(object));
                }

                assignments.Add(e);

                if (e is MethodCallExpression)
                {
                    MethodCallExpression mce = e as MethodCallExpression;

                    if (mce.Method == Closure_Make)
                    {
                        var cbe = mce.Arguments[0] as CodeBlockExpression;
                        cbe.Block.Source = sources[i];

                        libraryglobals.Add(locals[i].Name, cbe);
                        libraryglobals.Add(vars[i], cbe);
                    }
                    else if (mce.Method == Closure_MakeVarArgsX)
                    {
                        libraryglobalsX.Add(locals[i].Name, mce.Arguments[0] as CodeBlockExpression);
                        libraryglobalsX.Add(vars[i], mce.Arguments[0] as CodeBlockExpression);
                    }
                    else if (mce.Method == Closure_MakeCase)
                    {
                        NewArrayExpression tcs = mce.Arguments[0] as NewArrayExpression;

                        List <CodeBlockDescriptor> cdbs = new List <CodeBlockDescriptor>();

                        foreach (CodeBlockExpression tc in tcs.Expressions)
                        {
                            //where do we clean this up??
                            cdbs.Add(descriptorshack[tc]);
                        }

                        libraryglobalsN.Add(locals[i].Name, cdbs.ToArray());
                        libraryglobalsN.Add(vars[i], cdbs.ToArray());
                    }
                    else if (mce.Method == Closure_MakeTypedCase)
                    {
                        NewArrayExpression tcs = mce.Arguments[0] as NewArrayExpression;

                        List <CodeBlockDescriptor> cdbs = new List <CodeBlockDescriptor>();

                        foreach (Expression tc in tcs.Expressions)
                        {
                            //where do we clean this up??
                            cdbs.Add(descriptorshack2[tc]);
                        }

                        libraryglobalsN.Add(locals[i].Name, cdbs.ToArray());
                        libraryglobalsN.Add(vars[i], cdbs.ToArray());
                    }
                }
                else if (e is NewExpression)
                {
                    NewExpression ne = e as NewExpression;
                    if (typeof(ITypedCallable).IsAssignableFrom(e.Type))
                    {
                        libraryglobals.Add(locals[i].Name, ne.Arguments[0] as CodeBlockExpression);
                        libraryglobals.Add(vars[i], ne.Arguments[0] as CodeBlockExpression);
                    }
                }
            }

            // pass 2, expand lambda bodies
            for (int i = 0; i < vars.Count; i++)
            {
                Expression e = assignments[i];
                NameHint = SymbolTable.StringToId(n + "::" + Builtins.UnGenSymInternal(vars[i]));

                if (bodies[i] != null)
                {
                    CodeBlockDescriptor[] cbds;
                    CodeBlockExpression   cbe;

                    if (libraryglobals.TryGetValue(locals[i].Name, out cbe))
                    {
                        Cons      b     = bodies[i] as Cons;
                        CodeBlock cbody = cbe.Block;
                        cbody.Body = null;

                        FillBody(cbody, new List <Statement>(), b, true);
                    }
                    else if (libraryglobalsX.TryGetValue(locals[i].Name, out cbe))
                    {
                        Cons      b     = bodies[i] as Cons;
                        CodeBlock cbody = cbe.Block;
                        cbody.Body = null;

                        FillBody(cbody, new List <Statement>(), b, true);
                    }
                    else if (libraryglobalsN.TryGetValue(locals[i].Name, out cbds))
                    {
                        List <Cons> b = bodies[i] as List <Cons>;

                        for (int j = 0; j < b.Count; j++)
                        {
                            CodeBlock cbody = cbds[j].codeblock.Block;
                            cbody.Body = null;

                            FillBody(cbody, new List <Statement>(), b[j], true);
                        }
                    }
                }

                stmts.Add(Ast.Write(locals[i], e));
                // needed indeed
                if (!isprogram)
                {
                    stmts.Add(Ast.Statement(Ast.SimpleCallHelper(SetSymbolValue, Ast.Constant(vars[i]), Ast.Read(locals[i]))));
                }
            }

            Cons body = Builtins.Cdr(args) as Cons;
            FillBody(cb, stmts, body, true);
            cb.ExplicitCodeContextExpression = Ast.CodeContext();

#if OPTIMIZATIONS
            Expression ex = InlineCall(c, Ast.CodeBlockExpression(cb, false));
#else
            Expression ex = Ast.SimpleCallHelper(MakeClosure(cb, false), GetCallable(0));
#endif

            NameHint = SymbolId.Invalid;
            ClrGenerator.ResetReferences(ns);
            return(ex);
        }
        internal override Expression ToExpression(MethodBinderContext context, IList <ArgBuilder> args, IList <Expression> parameters, Expression ret)
        {
            List <Expression> sets = new List <Expression>();

            Variable tmp = null;// context.GetTemporary(ret.Type, "val");

            for (int i = 0; i < _indexesUsed.Length; i++)
            {
                Expression value = parameters[parameters.Count - _kwArgCount + _indexesUsed[i]];
                switch (_membersSet[i].MemberType)
                {
                case MemberTypes.Field:
                    FieldInfo fi = (FieldInfo)_membersSet[i];
                    if (!fi.IsLiteral && !fi.IsInitOnly)
                    {
                        sets.Add(Ast.AssignField(Ast.Read(tmp), fi, Ast.ConvertHelper(value, fi.FieldType)));
                    }
                    else
                    {
                        // call a helper which throws the error but "returns object"
                        sets.Add(
                            Ast.Convert(
                                Ast.Call(
                                    typeof(RuntimeHelpers).GetMethod("ReadOnlyAssignError"),
                                    Ast.Constant(true),
                                    Ast.Constant(fi.Name)
                                    ),
                                fi.FieldType
                                )
                            );
                    }
                    break;

                case MemberTypes.Property:
                    PropertyInfo pi = (PropertyInfo)_membersSet[i];
                    if (pi.GetSetMethod(ScriptDomainManager.Options.PrivateBinding) != null)
                    {
                        sets.Add(Ast.AssignProperty(Ast.Read(tmp), pi, Ast.ConvertHelper(value, pi.PropertyType)));
                    }
                    else
                    {
                        // call a helper which throws the error but "returns object"
                        sets.Add(
                            Ast.Convert(
                                Ast.Call(
                                    typeof(RuntimeHelpers).GetMethod("ReadOnlyAssignError"),
                                    Ast.Constant(false),
                                    Ast.Constant(pi.Name)
                                    ),
                                pi.PropertyType
                                )
                            );
                    }
                    break;
                }
            }

            Expression newCall = Ast.Comma(
                0,
                ArrayUtils.Insert <Expression>(
                    Ast.Assign(tmp, ret),
                    sets.ToArray()
                    )
                );

            return(_builder.ToExpression(context, args, parameters, newCall));
        }
Example #30
0
        // (clr-call type member obj arg1 ... )
        public override Expression Generate(object args, CodeBlock cb)
        {
            Type   t        = null;
            string type     = null;
            bool   inferred = false;

            object rtype = Builtins.First(args);

            ExtractTypeInfo(rtype, out t, out type, out inferred);

            string member = null;
            var    marg   = Builtins.Second(args);

            object memobj = null;

            Type[] argtypes = null;
            Type[] gentypes = null;

            if (marg is SymbolId)
            {
                var mem = Builtins.SymbolValue(marg);

                if (mem is Cons)
                {
                    ExtractMethodInfo(mem as Cons, out member, ref argtypes, ref gentypes);
                }
                else
                {
                    ClrSyntaxError("clr-call", "type member not supported", mem);
                }
            }
            else
            {
                memobj = Builtins.Second(marg);

                member = memobj is SymbolId?SymbolTable.IdToString((SymbolId)memobj) : "";

                if (memobj is string)
                {
                    string mems = memobj as string;
                    int    bi   = mems.IndexOf('(');
                    if (bi < 0)
                    {
                        member = mems;
                    }
                    else
                    {
                        member = mems.Substring(0, bi);
                    }
                }
                else if (memobj is Cons)
                {
                    ExtractMethodInfo(memobj as Cons, out member, ref argtypes, ref gentypes);
                }
            }

            Expression instance = GetAst(Builtins.Third(args), cb);

            CallType ct = CallType.ImplicitInstance;

            if (instance is ConstantExpression && ((ConstantExpression)instance).Value == null)
            {
                ct = CallType.None;

                if (inferred)
                {
                    ClrSyntaxError("clr-call", "type inference not possible on static member", member);
                }
            }
            else if (inferred)
            {
                if (instance is UnaryExpression && instance.Type == typeof(object))
                {
                    var ue = (UnaryExpression)instance;
                    instance = ue.Operand;
                }
                t = instance.Type;
            }
            else
            {
                instance = ConvertToHelper(t, instance);
            }

            type = t.Name;

            Expression[] arguments = GetAstListNoCast(Cdddr(args) as Cons, cb);

            if (member == "get_Item")
            {
                if (Attribute.IsDefined(t, typeof(DefaultMemberAttribute)))
                {
                    var dma = Attribute.GetCustomAttribute(t, typeof(DefaultMemberAttribute)) as DefaultMemberAttribute;
                    member = "get_" + dma.MemberName;
                }
                else if (t.IsArray)
                {
                    var index = arguments[0];
                    return(Ast.ArrayIndex(instance, Ast.ConvertHelper(index, typeof(int))));
                }
            }
            else if (member == "set_Item")
            {
                if (Attribute.IsDefined(t, typeof(DefaultMemberAttribute)))
                {
                    var dma = Attribute.GetCustomAttribute(t, typeof(DefaultMemberAttribute)) as DefaultMemberAttribute;
                    member = "set_" + dma.MemberName;
                }
                else if (t.IsArray)
                {
                    var index = arguments[0];
                    var v     = arguments[1];
                    return(Ast.Comma(Ast.AssignArrayIndex(instance, Ast.ConvertHelper(index, typeof(int)), v), Ast.ReadField(null, Unspecified)));
                }
            }

            List <MethodBase> candidates = new List <MethodBase>();

            BindingFlags bf = BindingFlags.Public | (ct == CallType.None ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.FlattenHierarchy;

            foreach (MethodInfo mi in t.GetMember(member, MemberTypes.Method, bf))
            {
                if (PAL.ExcludeParamtypes(mi))
                {
                    continue;
                }
                if (mi.ContainsGenericParameters)
                {
                    if (gentypes != null && mi.GetGenericArguments().Length == gentypes.Length)
                    {
                        candidates.Add(mi.MakeGenericMethod(gentypes));
                        continue;
                    }
                }
                candidates.Add(mi);
            }

            Type[] types = new Type[arguments.Length];

            for (int i = 0; i < types.Length; i++)
            {
                types[i] = arguments[i].Type;
            }

            if (memobj is string)
            {
                string mems = memobj as string;
                int    bi   = mems.IndexOf('(');
                if (bi < 0)
                {
                    // do notthig
                }
                else
                {
                    string[] typeargs = mems.Substring(bi + 1).TrimEnd(')').Split(',');

                    for (int i = 0; i < types.Length; i++)
                    {
                        if (typeargs[i].Length > 0)
                        {
                            types[i] = ScanForType(typeargs[i]);
                        }
                    }
                }
            }
            else if (argtypes != null)
            {
                for (int i = 0; i < types.Length; i++)
                {
                    types[i] = argtypes[i];
                }
            }

            if (ct == CallType.ImplicitInstance)
            {
                types = ArrayUtils.Insert(t, types);
            }

            MethodBinder mb = MethodBinder.MakeBinder(Binder, member, candidates, BinderType.Normal);

            MethodCandidate mc = mb.MakeBindingTarget(ct, types);

            if (mc == null)
            {
                types = new Type[arguments.Length];

                for (int i = 0; i < types.Length; i++)
                {
                    types[i] = typeof(object);
                }

                if (ct == CallType.ImplicitInstance)
                {
                    types = ArrayUtils.Insert(t, types);
                }

                mc = mb.MakeBindingTarget(ct, types);
            }

            if (mc != null)
            {
                MethodInfo meth = (MethodInfo)mc.Target.Method;
                // do implicit cast
                ParameterInfo[] pars = meth.GetParameters();
                for (int i = 0; i < arguments.Length; i++)
                {
                    Type tt = pars[i].ParameterType;
                    arguments[i] = ConvertToHelper(tt, arguments[i]);
                }

                Expression r = null;

                // o god...
                if (ct == CallType.ImplicitInstance)
                {
                    r = Ast.ComplexCallHelper(instance, (MethodInfo)mc.Target.Method, arguments);
                }
                else
                {
                    r = Ast.ComplexCallHelper((MethodInfo)mc.Target.Method, arguments);
                }

                return(ConvertFromHelper(meth.ReturnType, r));
            }

            ClrSyntaxError("clr-call", "member could not be resolved on type: " + type, args, member);

            return(null);
        }