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); }
private static MethodCallExpression GetNotImplemented() { return(Ast.Call( Ast.ReadProperty( Ast.CodeContext(), typeof(CodeContext), "LanguageContext" ), typeof(LanguageContext).GetMethod("GetNotImplemented"), Ast.NewArray(typeof(MethodCandidate[])) )); }
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))); }
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)) ) ) ) ); }
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); }
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 )); }
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); }
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); }
//(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)); }
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); }
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(); } }
internal override Expression ToExpression(MethodBinderContext context, Expression[] parameters) { return(Ast.CodeContext()); }
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)); } }
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 }); }