protected internal static Expression InlineCall(CodeBlock parent, CodeBlockExpression cbe, bool istailpostion, params Expression[] pp) { // all var names are unique. CodeBlock cb = cbe.Block; if (parent.IsGlobal) { return(CallNormal(cbe, pp)); } List <Statement> assigns = new List <Statement>(); int i = 0; cb.Inlined = true; if (parent.Filename == null && cb.Filename != null) { parent.Filename = cb.Filename; } var parentvars = new List <Variable>(parent.Variables); foreach (Variable p in cb.Parameters) { SymbolId origname = p.Name; p.Name = (SymbolId)Builtins.GenSym(p.Name); p.Block = parent; p.Kind = Variable.VariableKind.Local; parent.AddVariable(p); Expression val = Unwrap(pp[i]); if (val.Type != typeof(SymbolId) && !Generator.assigns.ContainsKey(origname)) { if (p.Type == typeof(object)) { p.Type = val.Type; assigns.Add(Ast.Write(p, val)); } else { assigns.Add(Ast.Write(p, Ast.ConvertHelper(val, p.Type))); } } else { if (p.Type == typeof(object)) { assigns.Add(Ast.Write(p, pp[i])); } else { assigns.Add(Ast.Write(p, Ast.ConvertHelper(pp[i], p.Type))); } } if (p.Lift) { parent.HasEnvironment = true; } i++; } foreach (Variable l in cb.Variables) { if (l.DefaultValue == null && l.Kind != Variable.VariableKind.Global) { l.Name = (SymbolId)Builtins.GenSym(l.Name); } l.Block = parent; parent.AddVariable(l); if (l.Lift) { parent.HasEnvironment = true; } } Expression body = RewriteReturn(cb.Body); if (assigns.Count > 0) { return(Ast.Comma(Ast.Void(Ast.Block(assigns)), body)); } else { return(body); } }
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) { if (!Parser.sourcemap.TryGetValue(c, out spanhint)) { spanhint = SourceSpan.None; } 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)); } }
static Expression RewriteReturn(Statement statement) { if (statement is BlockStatement) { BlockStatement bs = (BlockStatement)statement; List <Statement> newbody = new List <Statement>(bs.Statements); Statement last = newbody[newbody.Count - 1]; newbody.RemoveAt(newbody.Count - 1); Statement fb = FlattenStatement(Ast.Block(newbody)); Expression eb = Ast.Void(fb); if (fb is ExpressionStatement) { eb = ((ExpressionStatement)fb).Expression; } return(Ast.Comma(eb, Unwrap(RewriteReturn(last)))); } if (statement is ReturnStatement) { Expression e = ((ReturnStatement)statement).Expression; if (e is MethodCallExpression) { ((MethodCallExpression)e).TailCall = false; } if (e.Type != typeof(object)) { return(e); } else { return(Unwrap(e)); } } if (statement is IfStatement) { IfStatement ifs = (IfStatement)statement; Debug.Assert(ifs.Tests.Count == 1); var a = Unwrap(RewriteReturn(ifs.Tests[0].Body)); var b = Unwrap(RewriteReturn(ifs.ElseStatement)); if (a.Type != b.Type) { a = Ast.ConvertHelper(a, typeof(object)); b = Ast.ConvertHelper(b, typeof(object)); } return(Ast.Condition(ifs.Tests[0].Test, a, b)); } if (statement is LabeledStatement) { var ls = statement as LabeledStatement; return(Ast.Void(ls)); } throw new ArgumentException("Unexpected"); }
public Expression MakeExpression(ActionBinder binder, StandardRule rule, Expression[] parameters) { MethodBinderContext context = new MethodBinderContext(binder, rule); Expression check = Ast.True(); if (_binder.IsBinaryOperator) { // TODO: only if we have a narrowing level // need to emit check to see if args are convertible... for (int i = 0; i < _argBuilders.Count; i++) { Expression checkedExpr = _argBuilders[i].CheckExpression(context, parameters); if (checkedExpr != null) { check = Ast.AndAlso(check, checkedExpr); } } } Expression[] args = new Expression[_argBuilders.Count]; for (int i = 0; i < _argBuilders.Count; i++) { args[i] = _argBuilders[i].ToExpression(context, parameters); } MethodInfo mi = Method as MethodInfo; Expression ret, call; if (!Method.IsPublic || !Method.DeclaringType.IsVisible) { if (mi != null) { mi = CompilerHelpers.GetCallableMethod(mi); } } if (Method.IsPublic && Method.DeclaringType.IsVisible) { // public method if (mi != null) { Expression instance = mi.IsStatic ? null : _instanceBuilder.ToExpression(context, parameters); call = Ast.SimpleCallHelper(instance, mi, args); } else { call = Ast.SimpleNewHelper((ConstructorInfo)Method, args); } } else { // Private binding, invoke via reflection if (mi != null) { Expression instance = mi.IsStatic ? null : _instanceBuilder.ToExpression(context, parameters); call = Ast.Call( Ast.RuntimeConstant(mi), typeof(MethodInfo).GetMethod("Invoke", new Type[] { typeof(object), typeof(object[]) }), Ast.ConvertHelper(instance, typeof(object)), Ast.NewArrayHelper(typeof(object[]), args) ); } else { call = Ast.Call( Ast.RuntimeConstant((ConstructorInfo)Method), typeof(ConstructorInfo).GetMethod("Invoke", new Type[] { typeof(object[]) }), Ast.NewArrayHelper(typeof(object[]), args) ); } } ret = _returnBuilder.ToExpression(context, _argBuilders, parameters, call); List <Expression> updates = null; for (int i = 0; i < _argBuilders.Count; i++) { Expression next = _argBuilders[i].UpdateFromReturn(context, parameters); if (next != null) { if (updates == null) { updates = new List <Expression>(); } updates.Add(next); } } if (updates != null) { updates.Insert(0, ret); ret = Ast.Comma(0, updates.ToArray()); } if (!check.IsConstant(true)) { ret = Ast.Condition( check, Ast.ConvertHelper(ret, typeof(object)), GetNotImplemented() ); } return(ret); }
public static Expression MakeRecordTypeDescriptor(Expression[] obj) { if ((obj.Length == 6 || obj.Length == 7) && IronScheme.Compiler.Generator.VarHint != SymbolId.Empty) { try { var name = Unwrap(obj[0]); var parent = Unwrap(obj[1]); var uid = Unwrap(obj[2]); var issealed = Unwrap(obj[3]); var isopaque = Unwrap(obj[4]); var fields = obj[5]; if (fields is BoundExpression) { return(null); } if (name is BoundExpression) { return(null); } var rname = ((ConstantExpression)name).Value; var ruid = ((ConstantExpression)uid).Value; var rsealed = ((ConstantExpression)issealed).Value; var ropaque = ((ConstantExpression)isopaque).Value; object[] rfields = { }; if (fields is NewArrayExpression) { var ff = ((NewArrayExpression)fields).Expressions; var dfields = new Expression[ff.Count]; ff.CopyTo(dfields, 0); rfields = Array.ConvertAll(dfields, x => ((ConstantExpression)x).Value); } object[] tfields = Array.ConvertAll(rfields, x => SymbolTable.StringToObject("Object")); if (obj.Length == 7) { var ftypes = obj[6]; if (ftypes is NewArrayExpression) { var ff = ((NewArrayExpression)ftypes).Expressions; var dfields = new Expression[ff.Count]; ff.CopyTo(dfields, 0); tfields = Array.ConvertAll(dfields, x => ((ConstantExpression)((UnaryExpression)x).Operand).Value); } } if (!Builtins.IsTrue(ruid)) { ruid = Guid.NewGuid().ToString(); //TODO: recall why this was done :\ Change to gensym if possible obj[2] = Ast.Convert(Ast.Constant(ruid), typeof(object)); } object par = null; if (parent is BoundExpression) { par = ((BoundExpression)parent).Variable.Name; } var rtdc = new RecordTypeDescriptorConstant { RecordName = rname, Uid = ruid, Sealed = rsealed, Opaque = ropaque, Parent = par, Fields = rfields, FieldTypes = tfields, NameHint = IronScheme.Compiler.Generator.VarHint, }; var at = rtdc.Generate(); if (at != null) { ClrGenerator.AddCompileTimeType(at); } var e = Ast.Constant(rtdc); return(Ast.Comma(e, Ast.Call(typeof(Records).GetMethod("MakeRecordTypeDescriptor"), obj))); } catch { throw; //kaboom, redirect to runtime } } return(null); }
// (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, ref 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, ref 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 (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); }