private bool TryNumericComparison(OperatorInfo info)
        {
            MethodInfo[] targets = FilterNonMethods(_types[0], Binder.GetMember(Action, _types[0], "Compare"));
            if (targets.Length > 0)
            {
                MethodBinder    mb = MethodBinder.MakeBinder(Binder, targets[0].Name, targets, BinderType.Normal);
                MethodCandidate mc = mb.MakeBindingTarget(CallType.None, _types);
                if (mc != null)
                {
                    Expression call = Ast.Convert(mc.Target.MakeExpression(Binder, _rule, _rule.Parameters, _types), typeof(int));
                    switch (info.Operator)
                    {
                    case Operators.GreaterThan: call = Ast.GreaterThan(call, Ast.Constant(0)); break;

                    case Operators.LessThan: call = Ast.LessThan(call, Ast.Constant(0)); break;

                    case Operators.GreaterThanOrEqual: call = Ast.GreaterThanEquals(call, Ast.Constant(0)); break;

                    case Operators.LessThanOrEqual: call = Ast.LessThanEquals(call, Ast.Constant(0)); break;

                    case Operators.Equals: call = Ast.Equal(call, Ast.Constant(0)); break;

                    case Operators.NotEquals: call = Ast.NotEqual(call, Ast.Constant(0)); break;

                    case Operators.Compare:
                        break;
                    }
                    _rule.SetTarget(_rule.MakeReturn(Binder, call));
                    return(true);
                }
            }
            return(false);
        }
        private bool TryMakeInvertedBindingTarget(MethodInfo[] targets)
        {
            MethodBinder    mb = MethodBinder.MakeBinder(Binder, targets[0].Name, targets, BinderType.Normal);
            MethodCandidate mc = mb.MakeBindingTarget(CallType.None, _types);

            if (mc != null)
            {
                Expression call = mc.Target.MakeExpression(Binder, _rule, _rule.Parameters, _types);
                _rule.SetTarget(_rule.MakeReturn(Binder, Ast.Not(call)));
                return(true);
            }
            return(false);
        }
 /// <summary>
 /// We expand params arrays for library methods. Splat operator needs to be used to pass content of an array/list into params array method.
 /// </summary>
 protected override bool BindToUnexpandedParams(MethodCandidate /*!*/ candidate)
 {
     // TODO: separate flag?
     return(_implicitProtocolConversions);
 }
예제 #4
0
        // (clr-new type arg1 ... )
        public override Expression Generate(object args, CodeBlock cb)
        {
            Type   t;
            string type;
            bool   inferred;

            object rtype = Builtins.First(args);

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

            if (t == null)
            {
                ClrSyntaxError("clr-new", "type not found", type);
            }

            Expression[] arguments = GetAstListNoCast(Builtins.Cdr(args) as Cons, cb);

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

            foreach (ConstructorInfo c in t.GetConstructors())
            {
                bool add = true;

                foreach (var pi in c.GetParameters())
                {
                    if (pi.ParameterType.IsPointer)
                    {
                        add = false;
                        break;
                    }
                }

                if (add)
                {
                    candidates.Add(c);
                }
            }

            if (t.IsValueType && arguments.Length == 0)
            {
                // create default valuetype here
                return(Ast.DefaultValueType(t));
            }

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

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

            CallType ct = CallType.None;

            MethodBinder mb = MethodBinder.MakeBinder(Binder, "ctr", 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);
            }

            ConstructorInfo ci = null;

            if (mc == null && candidates.Count > 0)
            {
                foreach (ConstructorInfo c in candidates)
                {
                    if (c.GetParameters().Length == arguments.Length)
                    {
                        ci = c;
                        break; // tough luck for now
                    }
                }
            }
            else
            {
                ci = mc.Target.Method as ConstructorInfo;
            }

            if (ci != null)
            {
                ParameterInfo[] pars = ci.GetParameters();
                for (int i = 0; i < arguments.Length; i++)
                {
                    Type tt = pars[i].ParameterType;
                    arguments[i] = ConvertToHelper(tt, arguments[i]);
                }

                Expression r = Ast.New(ci, arguments);
                return(r);
            }

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

            return(null);
        }
예제 #5
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);
        }
예제 #6
0
                protected override bool Walk(MethodCallExpression node)
                {
                    var i = node.Instance;

                    if (node.Method != Generator.ICallable_CallN)
                    {
                        while (i is UnaryExpression && i.NodeType == AstNodeType.Convert)
                        {
                            i = ((UnaryExpression)i).Operand;
                        }

                        if (i is BoundExpression)
                        {
                            var be = (BoundExpression)i;
                            var v  = be.Variable.Name;

                            if (Builtins.IsTrue(Builtins.IsSymbolBound(v)))
                            {
                                var val = Builtins.SymbolValue(v);

                                var c = val as BuiltinMethod;
                                if (c != null)
                                {
                                    var mb = c.Binder;

                                    var pars = new Expression[node.Arguments.Count];
                                    node.Arguments.CopyTo(pars, 0);

                                    Type[]          types = Array.ConvertAll(pars, x => x.Type);
                                    MethodCandidate mc    = mb.MakeBindingTarget(CallType.None, types);
                                    if (mc != null)
                                    {
                                        var meth = mc.Target.Method as MethodInfo;

                                        node.Method   = meth;
                                        node.Instance = null;
                                    }
                                }
                                else if (val is Closure)
                                {
                                    var cc = val as Closure;

                                    // will not work on varargs, need to somehow decorate them
                                    var meth = Array.Find(cc.Targets,
                                                          x => x.GetParameters().Length == node.Arguments.Count && (Generator.AllowTransientBinding || !Generator.IsTransient(x.Module)));

                                    if (meth != null)
                                    {
                                        node.Method   = meth;
                                        node.Instance = null;
                                    }
                                    else
                                    {
                                        meth = Array.Find(cc.VarargTargets,
                                                          x => x.GetParameters().Length - 1 <= node.Arguments.Count && (Generator.AllowTransientBinding || !Generator.IsTransient(x.Module)));

                                        if (meth != null)
                                        {
                                            var newargs = new List <Expression>();

                                            var pars   = meth.GetParameters();
                                            var parlen = pars.Length;
                                            int x      = 0;
                                            for (; x < parlen - 1; x++)
                                            {
                                                newargs.Add(node.Arguments[x]);
                                            }

                                            var tail = new List <Expression>();
                                            for (; x < node.Arguments.Count; x++)
                                            {
                                                tail.Add(node.Arguments[x]);
                                            }

                                            var tailarr = tail.ToArray();

                                            newargs.Add(Ast.ComplexCallHelper(Compiler.Generator.MakeList(tailarr, true), tailarr));

                                            node.Arguments.Clear();
                                            node.Arguments.AddRange(newargs);

                                            node.Method = meth;

                                            node.ParameterInfos = pars;

                                            node.Instance = null;
                                        }
                                    }
                                }
                            }
                        }
                    }

                    return(base.Walk(node));
                }
예제 #7
0
        public override object Call(object[] args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args cannot be null");
            }

            int nargs = args.Length;

            Callable c;

            if (cache.TryGetValue(-1, out c) ||
                cache.TryGetValue(nargs, out c))
            {
                return(c.Call(args));
            }

            if (!baked)
            {
                try
                {
                    if (methods.Length == 1)
                    {
                        // make c fast
                        MethodBase mb = methods[0];

                        bool needContext = false;

#warning Remove when Mono fixed: https:                         //bugzilla.novell.com/show_bug.cgi?id=655439
                        Type dt = (nargs > 8 || IsParams(mb)) ? // for mono
                                  typeof(CallTargetN) : CallTargets.GetTargetType(needContext, nargs, false);
                        Delegate d = Delegate.CreateDelegate(dt, mb as MethodInfo, false);
                        if (d == null)
                        {
                            d = Delegate.CreateDelegate(typeof(CallTargetN), needContext ? context : null, mb as MethodInfo, false);
                        }

                        if (d != null)
                        {
                            if (dt == typeof(CallTargetN))
                            {
                                cache[-1] = c = Closure.Create(d);
                            }
                            else
                            {
                                cache[nargs] = c = Closure.Create(d);
                            }
                        }
                    }
                    else
                    {
                        Type[] targs = Array.ConvertAll <object, Type>(args, delegate(object input)
                        {
                            if (input == null)
                            {
                                return(typeof(object));
                            }
                            else
                            {
                                return(input.GetType());
                            }
                        });

                        MethodCandidate mc = meth.MakeBindingTarget(CallType.None, targs);
                        if (mc != null)
                        {
                            MethodBase mb = mc.Target.Method;

                            bool needContext = NeedContext(mb);     // TODO: check if can remove

#warning Remove when Mono fixed: https:                             //bugzilla.novell.com/show_bug.cgi?id=655439
                            Type dt = (nargs > 8 || IsParams(mb)) ? // for mono
                                      typeof(CallTargetN) : CallTargets.GetTargetType(needContext, nargs, false);
                            Delegate d = Delegate.CreateDelegate(dt, mb as MethodInfo, false);
                            if (d == null)
                            {
                                d = Delegate.CreateDelegate(typeof(CallTargetN), needContext ? context : null, mb as MethodInfo, false);
                            }

                            if (d != null)
                            {
                                cache[nargs] = c = Closure.Create(d);
                            }
                        }
                    }
                }
                catch
                {
                    ;
                }

                if (c != null)
                {
                    return(c.Call(args));
                }
            }
            // fallback
            baked = true;

            try
            {
                // DO NOT WANT!!!!
                return(meth.CallReflected(context, CallType.None, args));
            }
            catch (ArgumentTypeException ex)
            {
                return(Closure.AssertionViolation(meth.ToString(), ex.Message, args));
            }
        }
예제 #8
0
        protected internal static Expression GetAst(object args, CodeBlock cb, bool istailposition)
        {
            if (args is Annotation)
            {
                args = ((Annotation)args).stripped;
            }
            Cons c = args as Cons;

            if (c != null)
            {
                if (c.car is SymbolId)
                {
                    SymbolId f = (SymbolId)c.car;

                    Variable var = cb.Lookup(f);

                    if (var != null && !assigns.ContainsKey(f))
                    {
                        var = null;
                    }

                    object m;

#if OPTIMIZATIONS
#if !BLAH
                    CodeBlockExpression cbe;

                    //// needs to do the same for overloads...
                    if (SimpleGenerator.libraryglobals.TryGetValue(f, out cbe))
                    {
                        Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        if (cbe.Block.ParameterCount < 9 && cbe.Block.ParameterCount == ppp.Length)
                        {
                            //inline here? we could for simple bodies, but we need to copy the entire structure
                            if (!(cbe.Block.HasEnvironment || cbe.Block.IsClosure))
                            {
                                if (cbe.Block.Body is ReturnStatement)
                                {
                                    ReturnStatement rs = (ReturnStatement)cbe.Block.Body;

                                    if (!ScriptDomainManager.Options.DebugMode &&
                                        !ScriptDomainManager.Options.LightweightDebugging &&
                                        !cb.IsGlobal && IsSimpleExpression(rs.Expression))
                                    {
                                        return(InlineCall(cb, Ast.CodeBlockExpression(RewriteBody(cbe.Block), false, cbe.IsStronglyTyped), ppp));
                                    }
                                }
                            }
                            if (cbe.Block != cb.Parent && cbe.Block != cb) // do TCE later
                            {
                                return(CallNormal(cbe, ppp));
                            }
                        }
                    }

                    // varargs
                    if (SimpleGenerator.libraryglobalsX.TryGetValue(f, out cbe))
                    {
                        Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        if (cbe.Block.ParameterCount < 9 && cbe.Block.ParameterCount - 1 <= ppp.Length)
                        {
                            //inline here?
                            return(CallVarArgs(cbe, ppp));
                        }
                    }

                    // overloads
                    CodeBlockDescriptor[] cbd;
                    if (SimpleGenerator.libraryglobalsN.TryGetValue(f, out cbd))
                    {
                        Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        foreach (CodeBlockDescriptor d in cbd)
                        {
                            if (d.codeblock.Block.ParameterCount < 9)
                            {
                                if (ppp.Length == d.arity || (d.varargs && ppp.Length > d.arity))
                                {
                                    if (d.varargs)
                                    {
                                        //inline here?
                                        return(CallVarArgs(d.codeblock, ppp));
                                    }
                                    else
                                    {
                                        //inline here?
                                        //if (d.codeblock.Block != cb.Parent && d.codeblock.Block != cb) // do TCE later, not yet
                                        {
                                            return(CallNormal(d.codeblock, ppp));
                                        }
                                    }
                                }
                            }
                        }
                    }
#endif

                    //if (!ScriptDomainManager.Options.DebugMode)
                    {
                        if (f == SymbolTable.StringToId("call-with-values"))
                        {
                            Expression[] ppp = GetAstListNoCast(c.cdr as Cons, cb);
                            if (ppp.Length == 2 && ppp[1] is MethodCallExpression)
                            {
                                MethodCallExpression consumer = ppp[1] as MethodCallExpression;

                                if (ppp[0] is MethodCallExpression)
                                {
                                    MethodCallExpression producer = ppp[0] as MethodCallExpression;
                                    if (consumer.Method == Closure_Make && producer.Method == Closure_Make)
                                    {
                                        CodeBlockExpression ccbe = consumer.Arguments[0] as CodeBlockExpression;
                                        CodeBlockExpression pcbe = producer.Arguments[0] as CodeBlockExpression;

                                        pcbe.Block.Bind();
                                        ccbe.Block.Bind();

                                        if (ccbe.Block.ParameterCount == 0)
                                        {
                                            return(InlineCall(cb, ccbe));
                                        }
                                        else if (ccbe.Block.ParameterCount == 1)
                                        {
                                            return(InlineCall(cb, ccbe, Ast.SimpleCallHelper(typeof(Helpers).GetMethod("UnwrapValue"), InlineCall(cb, pcbe))));
                                        }
                                        else
                                        {
                                            Variable values = cb.CreateTemporaryVariable((SymbolId)Builtins.GenSym("values"), typeof(object[]));

                                            Expression valuesarr = Ast.Read(values);

                                            Expression[] pppp = new Expression[ccbe.Block.ParameterCount];

                                            for (int i = 0; i < pppp.Length; i++)
                                            {
                                                pppp[i] = Ast.ArrayIndex(valuesarr, Ast.Constant(i));
                                            }

                                            return(Ast.Comma(
                                                       Ast.Void(
                                                           Ast.Write(
                                                               values,
                                                               Ast.ComplexCallHelper(
                                                                   Ast.SimpleCallHelper(typeof(Helpers).GetMethod("WrapValue"), InlineCall(cb, pcbe)),
                                                                   typeof(MultipleValues).GetMethod("ToArray", new Type[] { typeof(int) }),
                                                                   Ast.Constant(pppp.Length)))),
                                                       InlineCall(cb, ccbe, pppp)));
                                        }
                                    }
                                }
                                if (consumer.Method == Closure_Make)
                                {
                                    CodeBlockExpression ccbe = consumer.Arguments[0] as CodeBlockExpression;
                                    ccbe.Block.Bind();

                                    Expression producer = ppp[0];

                                    Expression exx = Ast.ConvertHelper(producer, typeof(Callable));

                                    MethodInfo callx = GetCallable(0);

                                    if (ccbe.Block.ParameterCount == 0)
                                    {
                                        return(InlineCall(cb, ccbe));
                                    }
                                    else if (ccbe.Block.ParameterCount == 1)
                                    {
                                        return(InlineCall(cb, ccbe, Ast.SimpleCallHelper(typeof(Helpers).GetMethod("UnwrapValue"), Ast.Call(exx, callx))));
                                    }
                                    else
                                    {
                                        Variable values = cb.CreateTemporaryVariable((SymbolId)Builtins.GenSym("values"), typeof(object[]));

                                        Expression valuesarr = Ast.Read(values);

                                        Expression[] pppp = new Expression[ccbe.Block.ParameterCount];

                                        for (int i = 0; i < pppp.Length; i++)
                                        {
                                            pppp[i] = Ast.ArrayIndex(valuesarr, Ast.Constant(i));
                                        }

                                        return(Ast.Comma(
                                                   Ast.Void(
                                                       Ast.Write(
                                                           values,
                                                           Ast.ComplexCallHelper(
                                                               Ast.SimpleCallHelper(typeof(Helpers).GetMethod("WrapValue"),
                                                                                    Ast.Call(exx, callx)),
                                                               typeof(MultipleValues).GetMethod("ToArray", new Type[] { typeof(int) }),
                                                               Ast.Constant(pppp.Length)))),
                                                   InlineCall(cb, ccbe, pppp)));
                                    }
                                }
                            }
                            else
                            {
                                ;
                            }
                        }
                    }
#endif
                    // this can be enabled once builtins are auto CPS'd.
                    // ok I tried, but there are issues still, not sure what
#if OPTIMIZATIONS
                    // check for inline emitter
                    InlineEmitter ie;
                    if (TryGetInlineEmitter(f, out ie))
                    {
                        Expression result = ie(GetAstList(c.cdr as Cons, cb));
                        // if null is returned, the method cannot be inlined
                        if (result != null)
                        {
                            if (spanhint.IsValid)
                            {
                                result.SetLoc(spanhint);
                            }
                            return(result);
                        }
                    }
#endif

                    if (Context.Scope.TryLookupName(f, out m))
                    {
                        if (var == null)
                        {
                            IGenerator gh = m as IGenerator;
                            if (gh != null)
                            {
                                return(gh.Generate(c.cdr, cb));
                            }

                            BuiltinMethod bf = m as BuiltinMethod;
                            if (bf != null)
                            {
                                MethodBinder mb   = bf.Binder;
                                Expression[] pars = Array.ConvertAll(GetAstList(c.cdr as Cons, cb), e => Unwrap(e));

                                if (bf.AllowConstantFold && !ScriptDomainManager.Options.DebugMode)
                                {
                                    bool constant = Array.TrueForAll(pars, e => e is ConstantExpression && e.Type != typeof(BigInteger));

                                    if (constant)
                                    {
                                        object[]    cargs = Array.ConvertAll(pars, e => GetRuntimeConstant((ConstantExpression)e));
                                        CallTarget0 disp  = delegate
                                        {
                                            return(bf.Call(cargs));
                                        };
                                        CallTarget1 handler = delegate(object e)
                                        {
                                            throw new CompileTimeEvaluationException();
                                        };

                                        try
                                        {
                                            object result = Runtime.R6RS.Exceptions.WithExceptionHandler(
                                                Closure.Create(handler),
                                                Closure.Create(disp));
                                            var rrrr = GetCons(result, cb);
                                            if (spanhint.IsValid)
                                            {
                                                rrrr.SetLoc(spanhint);
                                            }
                                            return(rrrr);
                                        }
                                        catch (CompileTimeEvaluationException)
                                        {
                                        }
                                    }
                                }

                                Type[]          types = GetExpressionTypes(pars);
                                MethodCandidate mc    = mb.MakeBindingTarget(CallType.None, types);
                                if (mc != null)
                                {
                                    if (mc.Target.NeedsContext)
                                    {
                                        pars = ArrayUtils.Insert <Expression>(Ast.CodeContext(), pars);
                                    }
                                    MethodBase meth = mc.Target.Method;

                                    var rrrr = Ast.ComplexCallHelper(meth as MethodInfo, pars);
                                    if (spanhint.IsValid)
                                    {
                                        rrrr.SetLoc(spanhint);
                                    }
                                    return(rrrr);
                                }
                            }

                            Closure clos = m as Closure;
                            if (clos != null && !SetGenerator.IsAssigned(f))
                            {
                                // no provision for varargs
                                MethodInfo[] mis = clos.Targets;
                                if (mis.Length > 0)
                                {
                                    MethodBinder mb = MethodBinder.MakeBinder(binder, SymbolTable.IdToString(f), mis, BinderType.Normal);

                                    Expression[] pars = Array.ConvertAll(GetAstList(c.cdr as Cons, cb), e => Unwrap(e));

                                    if (clos.AllowConstantFold && !ScriptDomainManager.Options.DebugMode)
                                    {
                                        bool constant = Array.TrueForAll(pars, e => e is ConstantExpression && e.Type != typeof(BigInteger));

                                        if (constant)
                                        {
                                            object[] cargs = Array.ConvertAll(pars, e => GetRuntimeConstant((ConstantExpression)e));

                                            CallTarget0 disp = delegate
                                            {
                                                var rrrr = clos.Call(cargs);
                                                return(rrrr);
                                            };

                                            CallTarget1 handler = delegate(object e)
                                            {
                                                throw new CompileTimeEvaluationException();
                                            };

                                            try
                                            {
                                                object result = Runtime.R6RS.Exceptions.WithExceptionHandler(
                                                    Closure.Create(handler),
                                                    Closure.Create(disp));
                                                var rrrr = GetCons(result, cb);
                                                if (spanhint.IsValid)
                                                {
                                                    rrrr.SetLoc(spanhint);
                                                }
                                                return(rrrr);
                                            }
                                            catch (CompileTimeEvaluationException)
                                            {
                                            }
                                        }
                                    }

                                    // exclude transient members if needed
                                    if (!AllowTransientBinding)
                                    {
                                        mis = Array.FindAll(mis, x => !IsTransient(x.Module));
                                    }

                                    if (mis.Length > 0)
                                    {
                                        Type[]          types = GetExpressionTypes(pars);
                                        MethodCandidate mc    = mb.MakeBindingTarget(CallType.None, types);
                                        if (mc != null)
                                        {
                                            if (mc.Target.NeedsContext)
                                            {
                                                pars = ArrayUtils.Insert <Expression>(Ast.CodeContext(), pars);
                                            }
                                            MethodBase meth = mc.Target.Method;

                                            var rrrr = Ast.ComplexCallHelper(meth as MethodInfo, pars);
                                            if (spanhint.IsValid)
                                            {
                                                rrrr.SetLoc(spanhint);
                                            }
                                            return(rrrr);
                                        }
                                    }
                                }
                                // check for overload thing
                            }
                        }
                    }
                }


                Expression ex = Unwrap(GetAst(c.car, cb));

                // a 'let'
                if (ex is MethodCallExpression)
                {
                    var ppp = GetAstList(c.cdr as Cons, cb);
                    MethodCallExpression mcexpr = (MethodCallExpression)ex;
                    if (mcexpr.Method == Closure_Make)
                    {
                        CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;

                        if (ppp.Length < 9 && cbe.Block.ParameterCount == ppp.Length)
                        {
                            return(InlineCall(cb, cbe, istailposition, ppp));
                        }
                    }

                    // cater for varargs more efficiently, this does not seem to hit, probably needed somewhere else
                    if (mcexpr.Method == Closure_MakeVarArgsX)
                    {
                        CodeBlockExpression cbe = mcexpr.Arguments[0] as CodeBlockExpression;

                        if (ppp.Length < 9 && cbe.Block.ParameterCount <= ppp.Length)
                        {
                            return(CallVarArgs(cbe, ppp));
                        }
                    }
                }

                if (ex is NewExpression && typeof(ITypedCallable).IsAssignableFrom(ex.Type))
                {
                    NewExpression       mcexpr = ex as NewExpression;
                    CodeBlockExpression cbe    = mcexpr.Arguments[0] as CodeBlockExpression;
                    if (cbe == null && mcexpr.Arguments[0].Type == typeof(CodeContext) && mcexpr.Arguments[0] is ConstantExpression) // implies null
                    {
                        cbe = mcexpr.Arguments[1] as CodeBlockExpression;
                    }
                    if (cbe != null)
                    {
                        var ppp = GetAstListNoCast(c.cdr as Cons, cb);

                        if (ppp.Length < 9 && cbe.Block.ParameterCount == ppp.Length)
                        {
                            return(InlineCall(cb, cbe, istailposition, ppp));
                        }
                    }
                }

                if (ex is ConstantExpression)
                {
                    Builtins.SyntaxError(SymbolTable.StringToObject("generator"), "expecting a procedure", c.car, c);
                }

                Expression r = null;

                if (ex.Type.Name.Contains("TypedClosure"))
                {
                    Expression[] pp = GetAstListNoCast(c.cdr as Cons, cb);

                    var m = ex.Type.GetMethod("Invoke");
                    r = Ast.SimpleCallHelper(ex, m, pp);
                }
                else
                {
                    Expression[] pp = GetAstList(c.cdr as Cons, cb);

                    if (ex.Type != typeof(Callable))
                    {
                        ex = Ast.ConvertHelper(ex, typeof(Callable));
                    }

                    MethodInfo call = GetCallable(pp.Length);

                    r = pp.Length > 8 ?
                        Ast.Call(ex, call, Ast.NewArray(typeof(object[]), pp)) :
                        Ast.Call(ex, call, pp);
                }

                if (spanhint.IsValid)
                {
                    r.SetLoc(spanhint);
                }

                return(r);
            }

            object[] v = args as object[];

            if (v != null)
            {
                return(GetConsVector(v, cb));
            }
            else if (args is byte[])
            {
                Expression[] ba = Array.ConvertAll(args as byte[], b => Ast.Constant(b));
                return(Ast.NewArray(typeof(byte[]), ba));
            }
            else
            {
                if (args is SymbolId)
                {
                    SymbolId sym = (SymbolId)args;
                    if (sym == SymbolTable.StringToId("uninitialized"))
                    {
                        return(Ast.ReadField(null, typeof(Uninitialized), "Instance"));
                    }
                    else
                    {
                        return(Read(sym, cb, typeof(object)));
                    }
                }
                if (args == Builtins.Unspecified)
                {
                    return(Ast.ReadField(null, Unspecified));
                }
                if (args is Fraction)
                {
                    Fraction f = (Fraction)args;
                    return(Ast.Constant(new FractionConstant(f)));
                }
                if (args is ComplexFraction)
                {
                    ComplexFraction f = (ComplexFraction)args;
                    return(Ast.Constant(new ComplexFractionConstant(f)));
                }
                if (args != null && args.GetType().Name == "stx")
                {
                    args = new SerializedConstant(args);
                }
                return(Ast.Constant(args));
            }
        }
예제 #9
0
        public void Add(MethodCandidate target) {
            Debug.Assert(target.Parameters.Count == _count);

            _targets.Add(target);
        }
예제 #10
0
 private static bool IsBest(MethodCandidate candidate, List<MethodCandidate> applicableTargets, CallType callType, Type[] actualTypes) {
     foreach (MethodCandidate target in applicableTargets) {
         if (candidate == target) continue;
         if (candidate.CompareTo(target, callType, actualTypes) != +1) return false;
     }
     return true;
 }
예제 #11
0
 private void AddSimpleTarget(MethodCandidate target) {
     AddTarget(target);
     if (CompilerHelpers.IsParamsMethod(target.Target.Method)) {
         if (_paramsCandidates == null) _paramsCandidates = new List<MethodCandidate>();
         _paramsCandidates.Add(target);
     }            
 }
예제 #12
0
 private void AddTarget(MethodCandidate target) {
     int count = target.Target.ParameterCount;
     TargetSet set;
     if (!_targetSets.TryGetValue(count, out set)) {
         set = new TargetSet(this, count);
         _targetSets[count] = set;
     }
     set.Add(target);
 }
        private bool MakeDefaultMemberRule(Operators oper)
        {
            if (_types[0].IsArray)
            {
                if (Binder.CanConvertFrom(_types[1], typeof(int), NarrowingLevel.All))
                {
                    if (oper == Operators.GetItem)
                    {
                        _rule.SetTarget(_rule.MakeReturn(Binder,
                                                         Ast.ArrayIndex(
                                                             Param0,
                                                             ConvertIfNeeded(Param1, typeof(int))
                                                             )
                                                         ));
                    }
                    else
                    {
                        _rule.SetTarget(_rule.MakeReturn(Binder,
                                                         Ast.AssignArrayIndex(
                                                             Param0,
                                                             ConvertIfNeeded(Param1, typeof(int)),
                                                             ConvertIfNeeded(Param2, _types[0].GetElementType())
                                                             )
                                                         ));
                    }
                    return(true);
                }
            }

            MethodInfo[] defaults = GetMethodsFromDefaults(_types[0].GetDefaultMembers(), oper);
            if (defaults.Length != 0)
            {
                MethodBinder binder = MethodBinder.MakeBinder(Binder,
                                                              oper == Operators.GetItem ? "get_Item" : "set_Item",
                                                              defaults,
                                                              BinderType.Normal);

                MethodCandidate cand = binder.MakeBindingTarget(CallType.ImplicitInstance, _types);

                if (cand != null)
                {
                    if (oper == Operators.GetItem)
                    {
                        _rule.SetTarget(_rule.MakeReturn(Binder, cand.Target.MakeExpression(Binder, _rule, _rule.Parameters, _types)));
                    }
                    else
                    {
                        _rule.SetTarget(_rule.MakeReturn(Binder,
                                                         Ast.Comma(0,
                                                                   _rule.Parameters[2],
                                                                   cand.Target.MakeExpression(Binder, _rule, _rule.Parameters, _types)
                                                                   )
                                                         ));
                    }
                }
                else
                {
                    _rule.SetTarget(Binder.MakeInvalidParametersError(binder, Action, CallType.None, defaults, _rule, _args));
                }
                return(true);
            }

            return(false);
        }
예제 #14
0
        private void MakeMethodBaseRule(MethodBase[] targets)
        {
            Type[]     testTypes, argTypes;
            SymbolId[] argNames;

            //If an instance is explicitly passed in as an argument, ignore it.
            //Calls that need an instance will pick it up from the bound objects
            //passed in or the rule. CallType can differentiate between the type
            //of call during method binding.
            int instanceIndex = Action.Signature.IndexOf(ArgumentKind.Instance);

            if (instanceIndex > -1)
            {
                _args = ArrayUtils.RemoveAt(_args, instanceIndex + 1);
            }

            GetArgumentNamesAndTypes(out argNames, out argTypes);

            Type[]   bindingArgs = argTypes;
            CallType callType    = CallType.None;

            if (_instance != null)
            {
                bindingArgs = ArrayUtils.Insert(_instance.Type, argTypes);
                callType    = CallType.ImplicitInstance;
            }

            if (_reversedOperator && bindingArgs.Length >= 2)
            {
                // we swap the arguments before binding, and swap back before calling.
                ArrayUtils.SwapLastTwo(bindingArgs);
                if (argNames.Length >= 2)
                {
                    ArrayUtils.SwapLastTwo(argNames);
                }
            }

            // attempt to bind to an individual method
            MethodBinder    binder = MethodBinder.MakeBinder(Binder, GetTargetName(targets), targets, GetBinderType(targets), argNames);
            MethodCandidate cand   = binder.MakeBindingTarget(callType, bindingArgs, out testTypes);

            if (cand != null)
            {
                // if we succeed make the target for the rule
                MethodBase target       = cand.Target.Method;
                MethodInfo targetMethod = target as MethodInfo;

                if (targetMethod != null)
                {
                    target = CompilerHelpers.GetCallableMethod(targetMethod);
                }

                if (!MakeActionOnCallRule(target))
                {
                    Expression[] exprargs = FinishTestForCandidate(testTypes, argTypes);

                    _rule.SetTarget(_rule.MakeReturn(
                                        Binder,
                                        cand.Target.MakeExpression(Binder, _rule, exprargs, testTypes)));
                }
            }
            else
            {
                // make an error rule
                MakeInvalidParametersRule(binder, callType, targets);
            }
        }