コード例 #1
0
        protected static Expression CallNormal(CodeBlockExpression cbe, params Expression[] ppp)
        {
            bool       needscontext = NeedsContext(cbe); // true;
            int        pc           = ppp.Length;
            MethodInfo dc           = GetDirectCallable(needscontext, pc, cbe.Type);

            List <Variable> paruninit = new List <Variable>(cbe.Block.Parameters);

            for (int i = 0; i < ppp.Length; i++)
            {
                if (ppp[i].Type == typeof(Uninitialized))
                {
                    paruninit[i].SetUnInitialized();
                }
            }

            if (needscontext)
            {
                ppp = ArrayUtils.Insert <Expression>(Ast.CodeContext(), ppp);
            }

            var delegatetype = cbe.Type != typeof(Delegate) ? cbe.Type : CallTargets.GetTargetType(needscontext, pc, false);

            cbe = Ast.CodeBlockReference(cbe.Block, delegatetype);

            cbe.Block.Bind();

            var r = Ast.ComplexCallHelper(cbe, dc, ppp);

            if (SpanHint.IsValid)
            {
                r.SetLoc(SpanHint);
            }
            return(r);
        }
コード例 #2
0
 private static MethodCallExpression GetNotImplemented()
 {
     return(Ast.Call(
                Ast.ReadProperty(
                    Ast.CodeContext(),
                    typeof(CodeContext),
                    "LanguageContext"
                    ),
                typeof(LanguageContext).GetMethod("GetNotImplemented"),
                Ast.NewArray(typeof(MethodCandidate[]))
                ));
 }
コード例 #3
0
        protected static Expression MakeTypedCaseClosure(string name, List <CodeBlockDescriptor> cases)
        {
            List <Expression> targets = new List <Expression>();
            List <Expression> arities = new List <Expression>();

            foreach (CodeBlockDescriptor c in cases)
            {
                targets.Add(c.callable);
                arities.Add(Ast.Constant(c.arity));
            }

            return(Ast.SimpleCallHelper(Closure_MakeTypedCase, Ast.CodeContext(),
                                        Ast.NewArrayHelper(typeof(Callable[]), targets), Ast.NewArrayHelper(typeof(int[]), arities)));
        }
コード例 #4
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))
                                 )
                             )
                         )
         );
 }
コード例 #5
0
 private void MakeCustomMembersBody(Type type)
 {
     AddToBody(
         Ast.If(
             Ast.Call(
                 Ast.Convert(Instance, typeof(ICustomMembers)),
                 typeof(ICustomMembers).GetMethod("DeleteCustomMember"),
                 Ast.CodeContext(),
                 Ast.Constant(Action.Name)
                 ),
             Rule.MakeReturn(Binder, Ast.Null())
             )
         );
     // if the lookup fails throw an exception
     MakeMissingMemberError(type);
 }
コード例 #6
0
        internal override Expression ToExpression(MethodBinderContext context, IList <ArgBuilder> args, IList <Expression> parameters, Expression ret)
        {
            if (_returnArgs.Count == 1)
            {
                if (_returnArgs[0] == -1)
                {
                    return(ret);
                }
                return(Ast.Comma(ret, args[_returnArgs[0]].ToReturnExpression(context)));
            }

            Expression[] retValues = new Expression[_returnArgs.Count];
            int          rIndex    = 0;
            bool         usesRet   = false;

            foreach (int index in _returnArgs)
            {
                if (index == -1)
                {
                    usesRet             = true;
                    retValues[rIndex++] = ret;
                }
                else
                {
                    retValues[rIndex++] = args[index].ToReturnExpression(context);
                }
            }

            Expression retArray = Ast.NewArrayHelper(typeof(object[]), retValues);

            if (!usesRet)
            {
                retArray = Ast.Comma(ret, retArray);
            }

            return(Ast.Call(
                       Ast.ReadProperty(
                           Ast.ReadProperty(
                               Ast.CodeContext(),
                               typeof(CodeContext).GetProperty("LanguageContext")
                               ),
                           typeof(LanguageContext).GetProperty("Binder")
                           ),
                       typeof(ActionBinder).GetMethod("GetByRefArray"),
                       retArray
                       ));
        }
コード例 #7
0
        protected static Expression CallVarArgs(CodeBlockExpression cbe, Expression[] ppp)
        {
            bool needscontext = NeedsContext(cbe); //true;

            int pc = cbe.Block.ParameterCount;

            Expression[] tail = new Expression[ppp.Length - (pc - 1)];

            Array.Copy(ppp, ppp.Length - tail.Length, tail, 0, tail.Length);

            Expression[] nppp = new Expression[pc];

            Array.Copy(ppp, nppp, ppp.Length - tail.Length);

            if (tail.Length > 0)
            {
                nppp[nppp.Length - 1] = Ast.ComplexCallHelper(MakeList(tail, true), tail);
            }
            else
            {
                nppp[nppp.Length - 1] = Ast.Null();
            }

            ppp = nppp;

            MethodInfo dc = GetDirectCallable(needscontext, pc, cbe.Type);

            if (needscontext)
            {
                ppp = ArrayUtils.Insert <Expression>(Ast.CodeContext(), ppp);
            }

            cbe = Ast.CodeBlockReference(cbe.Block, CallTargets.GetTargetType(needscontext, pc, false));

            cbe.Block.Bind();

            var r = Ast.ComplexCallHelper(cbe, dc, ppp);

            if (SpanHint.IsValid)
            {
                r.SetLoc(SpanHint);
            }
            return(r);
        }
コード例 #8
0
        private void MakeCustomMembersBody(Type type)
        {
            Variable tmp = Rule.GetTemporary(typeof(object), "lookupRes");

            AddToBody(
                Ast.If(
                    Ast.Call(
                        Ast.Convert(Instance, typeof(ICustomMembers)),
                        GetCustomGetMembersMethod(),
                        Ast.CodeContext(),
                        Ast.Constant(Action.Name),
                        Ast.Read(tmp)
                        ),
                    Rule.MakeReturn(Binder, Ast.Read(tmp))
                    )
                );
            // if the lookup fails throw an exception
            MakeMissingMemberRuleForGet(type);
        }
コード例 #9
0
        //(import (ironscheme clr))
        //(define f (ffi-callback int32 (void* uint16)))
        public override Expression Generate(object args, CodeBlock cb)
        {
            Cons c          = args as Cons;
            Type returntype = GetFFIType(Unquote(c.car));

            c = c.cdr as Cons;

            List <Type> paramtypes = new List <Type>();

            while (c != null)
            {
                paramtypes.Add(GetFFIType(Unquote(c.car)));
                c = c.cdr as Cons;
            }

            CodeBlock outer = Ast.CodeBlock("outer");

            outer.Parent = cb;

            Variable proc = Variable.Parameter(outer, SymbolTable.StringToId("proc"), typeof(object));

            outer.AddParameter(proc);

            Type sig = MakeDelegateType(returntype, paramtypes);

            CodeBlock inner = GenerateCallback("ffi-callback",
                                               a => MakeCallBack(proc, a),
                                               returntype,
                                               paramtypes,
                                               outer);

            var del = Ast.CodeBlockReference(inner, sig);

            outer.Body = Ast.Block(
                Ast.Statement(MakeClosure(inner, false)),
                Ast.Return(Ast.Call(FFIFunctionPointer, Ast.Constant(sig), del, Ast.CodeContext())));

            return(MakeClosure(outer, false));
        }
コード例 #10
0
        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);
        }
コード例 #11
0
        protected internal static void FillBody(CodeBlock cb, List <Statement> stmts, Cons body, bool allowtailcall)
        {
            Cons c = body;

            while (c != null)
            {
                Expression e = GetAst(c.car, cb, c.cdr == null);
                Statement  s = null;
                if (c.cdr == null)
                {
                    if (e.Type != cb.ReturnType)
                    {
                        Expression ee = e;
                        while (ee is UnaryExpression)
                        {
                            var ue = ee as UnaryExpression;
                            if (ue.NodeType != AstNodeType.Convert)
                            {
                                break;
                            }
                            if (ue.Operand.Type == cb.ReturnType)
                            {
                                e = ue.Operand;
                                break;
                            }
                            ee = ue.Operand;
                        }
                        if (!(e is VoidExpression))
                        {
                            e = Ast.ConvertHelper(e, cb.ReturnType);
                        }
                    }
                    s = MakeTailCallReturn(allowtailcall, e);
                }
                else
                {
                    s = Ast.Statement(e);
                }

                stmts.Add(s);
                c = c.cdr as Cons;
            }

            if (stmts.Count == 0)
            {
                stmts.Add(Ast.Return(Ast.ReadField(null, Unspecified)));
            }

            if (cb.Body != null)
            {
                stmts.InsertRange(0, (cb.Body as BlockStatement).Statements);
            }

            cb.Body = Ast.Block(stmts);
            cb.Body = OptimizeBody(cb.Body);

            if (cb.Parent == null || (cb.Parent.IsGlobal && cb.ParameterCount < 9))
            {
                cb.ExplicitCodeContextExpression = Ast.CodeContext();
            }
        }
コード例 #12
0
 internal override Expression ToExpression(MethodBinderContext context, Expression[] parameters)
 {
     return(Ast.CodeContext());
 }
コード例 #13
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));
            }
        }
コード例 #14
0
ファイル: CallBinderHelper.cs プロジェクト: clorton/IDM-CMS
        protected Expression[] GetICallableParameters(Type t, StandardRule <T> rule)
        {
            List <Expression> plainArgs = new List <Expression>();
            List <KeyValuePair <SymbolId, Expression> > named = new List <KeyValuePair <SymbolId, Expression> >();
            Expression splat = null, kwSplat = null;
            Expression instance = null;

            for (int i = 1; i < rule.Parameters.Length; i++)
            {
                switch (Action.Signature.GetArgumentKind(i - 1))
                {
                case ArgumentKind.Simple: plainArgs.Add(rule.Parameters[i]); break;

                case ArgumentKind.List: splat = rule.Parameters[i]; break;

                case ArgumentKind.Dictionary: kwSplat = rule.Parameters[i]; break;

                case ArgumentKind.Named: named.Add(new KeyValuePair <SymbolId, Expression>(Action.Signature.GetArgumentName(i - 1), rule.Parameters[i])); break;

                case ArgumentKind.Instance: instance = rule.Parameters[i]; break;

                case ArgumentKind.Block:
                default:
                    throw new NotImplementedException();
                }
            }

            Expression argsArray = Ast.NewArrayHelper(typeof(object[]), plainArgs.ToArray());

            if (splat != null)
            {
                argsArray = Ast.Call(
                    typeof(BinderOps).GetMethod("GetCombinedParameters"),
                    argsArray,
                    Ast.ConvertHelper(splat, typeof(object))
                    );
            }

            if (kwSplat != null || named.Count > 0)
            {
                // IFancyCallable.Call(context, args, names)
                Debug.Assert(instance == null); // not supported, no IFancyCallableWithInstance
                Expression names;

                if (named.Count > 0)
                {
                    List <Expression> constNames  = new List <Expression>();
                    List <Expression> namedValues = new List <Expression>();
                    foreach (KeyValuePair <SymbolId, Expression> kvp in named)
                    {
                        constNames.Add(Ast.Constant(SymbolTable.IdToString(kvp.Key)));
                        namedValues.Add(kvp.Value);
                    }

                    argsArray = Ast.Call(
                        typeof(BinderOps).GetMethod("GetCombinedParameters"),
                        argsArray,
                        Ast.NewArrayHelper(typeof(object[]), namedValues.ToArray())
                        );

                    names = Ast.NewArrayHelper(typeof(string[]), constNames.ToArray());
                }
                else
                {
                    names = Ast.Null(typeof(string[]));
                }

                if (kwSplat != null)
                {
                    Variable namesVar = rule.GetTemporary(typeof(string[]), "names");
                    argsArray = Ast.Comma(
                        Ast.Assign(namesVar, names),
                        Ast.Call(
                            typeof(BinderOps).GetMethod("GetCombinedKeywordParameters"),
                            argsArray,
                            Ast.ConvertHelper(kwSplat, typeof(IAttributesCollection)),
                            Ast.Read(namesVar)
                            )
                        );

                    return(new Expression[] { Ast.CodeContext(), argsArray, Ast.Read(namesVar) });
                }
                return(new Expression[] { Ast.CodeContext(), argsArray, names });
            }

            // ICallable.Call(context, args)
            if (instance != null && typeof(ICallableWithThis).IsAssignableFrom(t))
            {
                return(new Expression[] { Ast.CodeContext(), instance, argsArray });
            }

            return(new Expression[] { Ast.CodeContext(), argsArray });
        }