internal override Expression ToExpression(MethodBinderContext context, Expression[] parameters) { // Ideally we'd pass in Ast.ReadField(parameters[Index], "Value") but due to // a bug in partial trust we can't access the generic field. // arg is boxType ? &_tmp : throw new ArgumentTypeException() // IncorrectBoxType throws the exception to avoid stack imbalance issues. return(Ast.Condition( Ast.TypeIs(parameters[Index], BoxType), Ast.Comma( Ast.Assign( _tmp, Ast.Call( typeof(BinderOps).GetMethod("GetBox").MakeGenericMethod(_elementType), Ast.ConvertHelper(parameters[Index], typeof(StrongBox <>).MakeGenericType(_elementType)) ) ), Ast.Read(_tmp) ), // Condition requires types of both expressions to be identical. // Putting the cast here is a temporary workaround until the // emit address and reference argument passing is finished. Ast.Convert( Ast.Call( typeof(BinderOps).GetMethod("IncorrectBoxType"), Ast.Constant(BoxType), Ast.ConvertHelper(parameters[Index], typeof(object)) ), _elementType ) )); }
internal override Expression GetBoundValue(ActionBinder binder, Type type, Expression instance) { if (DeclaringType.IsGenericType && DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox <>)) { // work around a CLR bug where we can't access generic fields from dynamic methods. return(Ast.Call( typeof(BinderOps).GetMethod("GetBox").MakeGenericMethod(DeclaringType.GetGenericArguments()), Ast.ConvertHelper(instance, DeclaringType) )); } if (IsPublic && DeclaringType.IsPublic) { return(Ast.ReadField( Ast.Convert(instance, Field.DeclaringType), Field )); } return(Ast.Call( Ast.ConvertHelper(Ast.RuntimeConstant(Field), typeof(FieldInfo)), typeof(FieldInfo).GetMethod("GetValue"), Ast.ConvertHelper(instance, typeof(object)) )); }
public static Expression MakeTypeTestExpression(Type t, Expression expr) { // we must always check for non-sealed types explicitly - otherwise we end up // doing fast-path behavior on a subtype which overrides behavior that wasn't // present for the base type. //TODO there's a question about nulls here if (CompilerHelpers.IsSealed(t) && t == expr.Type) { if (t.IsValueType) { return(Ast.True()); } return(Ast.NotEqual(expr, Ast.Null())); } return(Ast.AndAlso( Ast.NotEqual( expr, Ast.Null()), Ast.Equal( Ast.Call( Ast.ConvertHelper(expr, typeof(object)), typeof(object).GetMethod("GetType") ), Ast.Constant(t) ) )); }
public static Expression Apply(Expression[] args) { if (args.Length == 0) { return(null); } Expression c = Ast.ConvertHelper(args[0], typeof(Callable)); if (args.Length > 1) { Expression arg = Ast.ConvertHelper(args[args.Length - 1], typeof(object)); if (arg.IsConstant(null)) { Debugger.Break(); } for (int i = args.Length - 2; i > 0; i--) { arg = MakeCons(args[i], arg); } return(Ast.ComplexCallHelper(c, ICallable_Call, Ast.Call(ListToVector, arg))); } else { return(null); } }
static Expression MakeCallBack(Variable proc, Expression[] a) { var procr = Ast.ConvertHelper(Ast.Read(proc), typeof(Callable)); MethodInfo call = GetCallable(a.Length); var expr = Ast.Call(procr, call, a); return(expr); }
public static Expression ByteVectorSet(Expression[] values) { if (values.Length == 3) { return(Ast.AssignArrayIndex(Ast.ConvertHelper(values[0], typeof(byte[])), Ast.ConvertHelper(values[1], typeof(int)), Ast.ConvertHelper(values[2], typeof(byte)))); } UnsafeSyntaxError("$bytevector-set!", "expected 3 arguments", values); return(null); }
/// <summary> /// Helper to produce a rule when no conversion is required (the strong type of the expression /// input matches the type we're converting to or has an implicit conversion at the IL level) /// </summary> private void MakeSimpleConversionTarget(Type toType) { _rule.SetTarget( _rule.MakeReturn( Binder, Ast.ConvertHelper(_rule.Parameters[0], toType) ) ); }
public static Expression ByteVectorRef(Expression[] values) { if (values.Length == 2) { return(Ast.Convert(Ast.ArrayIndex(Ast.ConvertHelper(values[0], typeof(byte[])), Ast.ConvertHelper(values[1], typeof(int))), typeof(int))); } UnsafeSyntaxError("$bytevector-ref", "expected 2 arguments", values); return(null); }
public override Expression Generate(object args, CodeBlock cb) { SymbolId s = (SymbolId)Builtins.First(args); assigns[s] = true; if (libraryglobals.ContainsKey(s)) { libraryglobals.Remove(s); } if (libraryglobalsN.ContainsKey(s)) { libraryglobalsN.Remove(s); } if (libraryglobalsX.ContainsKey(s)) { libraryglobalsX.Remove(s); } setstack.Push(s); NameHint = Builtins.UnGenSymInternal(s); var prevvh = VarHint; VarHint = s; Expression value = GetAst(Builtins.Second(args), cb); VarHint = prevvh; setstack.Pop(); NameHint = SymbolId.Invalid; Variable v = cb.Lookup(s); Statement r = null; if (v == null) { r = Ast.Statement(Ast.SimpleCallHelper(SetSymbolValue, Ast.Constant(s), value)); } else { //Trace.Assert(cb.Parent != null); value = Ast.ConvertHelper(value, v.Type); r = Ast.Write(v, value); } if (SpanHint != SourceSpan.Invalid || SpanHint != SourceSpan.None) { r.SetLoc(SpanHint); } return(Ast.Void(r)); }
static Expression UnwrapAndCast <T>(Expression e) { e = Unwrap(e); if (e.Type == typeof(object) || e.Type == typeof(T) || (typeof(T) == typeof(int) && e.Type == typeof(byte))) { return(Ast.ConvertHelper(Unwrap(e), typeof(T))); } UnsafeSyntaxError("UnwrapAndCast", "Expected fixnum, but got " + e.Type.Name + ".", e); return(null); }
/// <summary> /// Helper to extract the Value of an Extensible of T from the /// expression being converted. /// </summary> private Expression GetExtensibleValue(Type extType) { return(Ast.ReadProperty( Ast.ConvertHelper( _rule.Parameters[0], extType ), extType.GetProperty("Value") )); }
protected static Expression ConvertToHelper(Type t, Expression e) { if (t.IsAssignableFrom(e.Type)) { return(e); } else if (t.BaseType == typeof(MulticastDelegate)) { return(Ast.SimpleCallHelper(Helpers_ConvertToDelegate.MakeGenericMethod(t), e)); } else if (t.BaseType == typeof(Enum)) { if (e.Type.IsValueType) { e = Ast.ConvertHelper(e, typeof(object)); } return(Ast.SimpleCallHelper(Helpers_SymbolToEnum.MakeGenericMethod(t), e)); } else { // prevent boxing if (e is UnaryExpression && e.Type == typeof(object)) { var ue = (UnaryExpression)e; if (t.IsAssignableFrom(ue.Operand.Type)) { return(ue.Operand); } } if (t.IsArray && t != typeof(byte[]) && t != typeof(char[])) { return(Ast.SimpleCallHelper(Helpers_RequiresArray.MakeGenericMethod(t.GetElementType()), e)); } else { //if (e is ConstantExpression && ((ConstantExpression)e).Value == null) //{ // return e; //} if (TypeHelpersEnabled) { return(Ast.SimpleCallHelper(Helpers_Requires.MakeGenericMethod(t), e)); } else { return(Ast.ConvertHelper(e, t)); } } } }
public static Expression VectorSet(Expression[] values) { if (values.Length == 3) { if (!typeof(Array).IsAssignableFrom(values[0].Type)) { values[0] = Ast.ConvertHelper(values[0], typeof(object[])); } return(Ast.AssignArrayIndex(values[0], Ast.ConvertHelper(values[1], typeof(int)), values[2])); } UnsafeSyntaxError("$vector-set!", "expected 3 arguments", values); return(null); }
/// <summary> /// Helper to produce the rule for converting T to Nullable of T /// </summary> private void MakeTToNullableOfTTarget(Type toType, Type knownType) { // T -> Nullable<T> _rule.SetTarget( _rule.MakeReturn( Binder, Ast.New( toType.GetConstructor(new Type[] { knownType }), Ast.ConvertHelper(_rule.Parameters[0], knownType) ) ) ); }
/// <summary> /// Helper to produce a rule when no conversion is required from an extensible type's /// underlying storage to the type we're converting to. The type of extensible type /// matches the type we're converting to or has an implicit conversion at the IL level. /// </summary> /// <param name="toType"></param> private void MakeSimpleExtensibleConversionTarget(Type toType) { Type extType = typeof(Extensible <>).MakeGenericType(toType); _rule.SetTarget( _rule.MakeReturn( Binder, Ast.ConvertHelper( GetExtensibleValue(extType), toType ) ) ); }
public override Expression ConvertExpression(Expression expr, Type toType) { if (toType == typeof(object)) { return(expr); } Expression expr2 = IronScheme.Compiler.Generator.Unwrap(expr); if (expr2.Type == toType) { return(expr2); } return(Ast.ConvertHelper(expr, toType)); }
static Expression RewriteExpression(CodeBlock cb, Expression e) { if (e is MethodCallExpression) { MethodCallExpression mce = (MethodCallExpression)e; List <Expression> args = new List <Expression>(); foreach (var arg in mce.Arguments) { args.Add(RewriteExpression(cb, arg)); } return(Ast.Call(RewriteExpression(cb, mce.Instance), mce.Method, args.ToArray())); } if (e is BoundExpression) { BoundExpression be = (BoundExpression)e; return(Ast.Read(cb.Lookup(be.Variable.Name))); } if (e is BinaryExpression) { BinaryExpression be = (BinaryExpression)e; return(new BinaryExpression(be.NodeType, RewriteExpression(cb, be.Left), RewriteExpression(cb, be.Right))); } if (e is UnaryExpression) { UnaryExpression ue = (UnaryExpression)e; if (ue.NodeType == AstNodeType.Convert) { return(Ast.ConvertHelper(RewriteExpression(cb, ue.Operand), ue.Type)); } return(null); } if (e is TypeBinaryExpression) { TypeBinaryExpression tbe = (TypeBinaryExpression)e; return(Ast.TypeIs(RewriteExpression(cb, tbe.Expression), tbe.TypeOperand)); } if (e is ConditionalExpression) { ConditionalExpression ce = (ConditionalExpression)e; return(Ast.Condition(RewriteExpression(cb, ce.Test), RewriteExpression(cb, ce.IfTrue), RewriteExpression(cb, ce.IfFalse))); } return(e); }
public static Expression BooleanOr(Expression[] args) { int len = args.Length; switch (len) { case 0: return(Ast.Constant(false)); default: var rargs = new Expression[len - 1]; Array.Copy(args, 1, rargs, 0, rargs.Length); return(Ast.OrElse(Ast.ConvertHelper(args[0], typeof(bool)), BooleanOr(rargs))); } }
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)) ) ) ) ); }
protected static Expression ConvertFromHelper(Type t, Expression e) { if (t == typeof(void)) { return(Ast.Comma(e, Ast.ReadField(null, Unspecified))); } else if (t.BaseType == typeof(Enum)) { return(Ast.SimpleCallHelper(Helpers_EnumToSymbol.MakeGenericMethod(t), e)); } else if (t.IsValueType) { return(Ast.ConvertHelper(e, typeof(object))); } else { return(e); } }
static Expression GetConsVector(object[] v, CodeBlock cb) { List <Expression> e = new List <Expression>(); foreach (object var in v) { Cons c = var as Cons; e.Add(GetCons(var, cb)); } for (int i = 0; i < e.Count; i++) { if (e[i].Type.IsValueType) { e[i] = Ast.ConvertHelper(e[i], typeof(object)); } } return(Ast.NewArray(typeof(object[]), e.ToArray())); }
static Expression ConsAccessor(Expression[] values, FieldInfo field) { if (values.Length != 1) { return(null); } Expression e = values[0]; ConstantExpression c = e as ConstantExpression; if (c != null && c.Value == null) { return(null); } if (e.Type != typeof(object) && e.Type != typeof(Cons)) { return(null); } return(Ast.ReadField(Ast.ConvertHelper(e, typeof(Cons)), field)); }
static Expression ConsAccessor(Expression[] values, FieldInfo field) { if (values.Length != 1) { UnsafeSyntaxError(field.Name, "incorrect number of arguments", values); } Expression e = values[0]; ConstantExpression c = e as ConstantExpression; if (c != null && c.Value == null) { UnsafeSyntaxError(field.Name, "unexpected constant expression", values); } if (e.Type != typeof(object) && e.Type != typeof(Cons)) { UnsafeSyntaxError(field.Name, "unexpected type", values); } return(Ast.ReadField(Ast.ConvertHelper(e, typeof(Cons)), field)); }
protected override void PostWalk(WriteStatement node) { base.PostWalk(node); var v = node.Variable; var val = node.Value; if (v.Type == typeof(object)) { if (val.Type != typeof(object) && val.Type != typeof(SymbolId) && !v.Uninitialized) { v.Type = val.Type; } } else if (v.Type != val.Type) { v.Type = typeof(object); } else if (v.Type == typeof(Callable)) { var uv = Unwrap(val); if (!uv.Type.IsAssignableFrom(v.Type)) { v.Type = typeof(object); node.Value = Ast.ConvertHelper(Unwrap(val), typeof(object)); } else { writecounts[node.Variable]--; } } else { writecounts[node.Variable]--; } if (writecounts[node.Variable] > 1) { v.Type = typeof(object); } }
protected static Expression[] GetAstList(Cons c, CodeBlock cb, bool castdown) { List <Expression> e = new List <Expression>(); while (c != null) { if (c.cdr != null && !(c.cdr is Cons)) { Builtins.SyntaxError("GetAstList", "improper list cant be used as an expression", c, Builtins.FALSE); } iscontinuation = e.Count == 0; Expression ex = GetAst(c.car, cb); iscontinuation = false; if (castdown && ex.Type.IsValueType) { ex = Ast.ConvertHelper(ex, typeof(object)); } e.Add(ex); c = c.cdr as Cons; } return(e.ToArray()); }
public Expression AddTemplatedWeakConstant(Type type, object value) { if (value != null) { if (!type.IsAssignableFrom(value.GetType())) { throw new ArgumentException("type must be assignable from value"); } } else { if (!type.IsValueType) { throw new ArgumentException("value must not be null for value types"); } } Expression expr = AddTemplatedConstant(typeof(WeakReference), new WeakReference(value)); return(Ast.ConvertHelper( Ast.ReadProperty(expr, typeof(WeakReference).GetProperty("Target")), type )); }
public override Expression GetValue(ActionBinder binder, Type type) { if (Field.IsLiteral) { return(Ast.Constant(Field.GetValue(null))); } if (!IsStatic) { // return the field tracker... return(binder.ReturnMemberTracker(type, this)); } if (IsPublic && DeclaringType.IsPublic) { return(Ast.ReadField(null, Field)); } return(Ast.Call( Ast.ConvertHelper(Ast.RuntimeConstant(Field), typeof(FieldInfo)), typeof(FieldInfo).GetMethod("GetValue"), Ast.Null() )); }
public override Expression Generate(object args, CodeBlock c) { var ns = ClrGenerator.SaveReferences(); Cons name = (args as Cons).car as Cons; bool isprogram = name == null; string[] fullname = Array.ConvertAll <object, string>(Builtins.ListToVector(name), SymbolToString); string n = string.Join(".", fullname); NameHint = SymbolTable.StringToId(n); CodeBlock cb = Ast.CodeBlock(SpanHint, GetLambdaName(c)); cb.IsGlobal = true; List <SymbolId> vars = new List <SymbolId>(); List <Variable> locals = new List <Variable>(); List <Expression> assignments = new List <Expression>(); List <object> defs = new List <object>(); List <object> bodies = new List <object>(); List <object> sources = new List <object>(); args = (args as Cons).cdr; Cons a = (args as Cons).car as Cons; while (a != null) { Cons d = a.car as Cons; SymbolId v = (SymbolId)d.car; SymbolId l = (SymbolId)((Cons)d.cdr).car; vars.Add(l); locals.Add(Create(v, cb, typeof(object))); defs.Add(((Cons)((Cons)d.cdr).cdr).car); a = a.cdr as Cons; } #if DONE // pass 0 - record defs for (int i = 0; i < vars.Count; i++) { if (IsMakeRecord(defs[i])) { //Debugger.Break(); Type type = CreateRecordType(defs[i] as Cons); if (type != null) { ClrGenerator.AddCompileTimeType(type); } } } #endif List <Statement> stmts = new List <Statement>(); // pass 1 for (int i = 0; i < vars.Count; i++) { sources.Add(null); bool annotated, typed; if (IsLambda(defs[i], out annotated, out typed)) { Cons cl = defs[i] as Cons; sources[i] = Copy(cl); int depth = GetDepth(sources[i]); if (depth > 10) { sources[i] = null; } if (annotated) { cl = cl.cdr as Cons; } if (cl.cdr != null) { if (((Cons)cl.cdr).cdr == null) { Cons bh = (Cons)((Cons)cl.cdr).car; if (typed) { bh = bh.cdr as Cons; } Cons b = bh.cdr as Cons; bh.cdr = new Cons(Builtins.FALSE); bodies.Add(b); } else { List <Cons> cbs = new List <Cons>(); Cons cc = cl.cdr as Cons; while (cc != null) { Cons bh = (Cons)cc.car; if (typed) { bh = bh.cdr as Cons; } Cons b = bh.cdr as Cons; bh.cdr = new Cons(Builtins.FALSE); cbs.Add(b); cc = cc.cdr as Cons; } bodies.Add(cbs); } } else { bodies.Add(null); } } else { bodies.Add(null); } VarHint = locals[i].Name; VarHint2 = vars[i]; NameHint = SymbolTable.StringToId(n + "::" + Builtins.UnGenSymInternal(vars[i])); Expression e = GetAst(defs[i], cb); VarHint = VarHint2 = SymbolId.Empty; if (e is UnaryExpression && e.NodeType == AstNodeType.Convert && e.Type != typeof(object)) { locals[i].Type = e.Type; } else if (e.Type.IsValueType) { e = Ast.ConvertHelper(e, typeof(object)); } assignments.Add(e); if (e is MethodCallExpression) { MethodCallExpression mce = e as MethodCallExpression; if (mce.Method == Closure_Make) { var cbe = mce.Arguments[0] as CodeBlockExpression; cbe.Block.Source = sources[i]; libraryglobals.Add(locals[i].Name, cbe); libraryglobals.Add(vars[i], cbe); } else if (mce.Method == Closure_MakeVarArgsX) { libraryglobalsX.Add(locals[i].Name, mce.Arguments[0] as CodeBlockExpression); libraryglobalsX.Add(vars[i], mce.Arguments[0] as CodeBlockExpression); } else if (mce.Method == Closure_MakeCase) { NewArrayExpression tcs = mce.Arguments[0] as NewArrayExpression; List <CodeBlockDescriptor> cdbs = new List <CodeBlockDescriptor>(); foreach (CodeBlockExpression tc in tcs.Expressions) { //where do we clean this up?? cdbs.Add(descriptorshack[tc]); } libraryglobalsN.Add(locals[i].Name, cdbs.ToArray()); libraryglobalsN.Add(vars[i], cdbs.ToArray()); } else if (mce.Method == Closure_MakeTypedCase) { NewArrayExpression tcs = mce.Arguments[0] as NewArrayExpression; List <CodeBlockDescriptor> cdbs = new List <CodeBlockDescriptor>(); foreach (Expression tc in tcs.Expressions) { //where do we clean this up?? cdbs.Add(descriptorshack2[tc]); } libraryglobalsN.Add(locals[i].Name, cdbs.ToArray()); libraryglobalsN.Add(vars[i], cdbs.ToArray()); } } else if (e is NewExpression) { NewExpression ne = e as NewExpression; if (typeof(ITypedCallable).IsAssignableFrom(e.Type)) { libraryglobals.Add(locals[i].Name, ne.Arguments[0] as CodeBlockExpression); libraryglobals.Add(vars[i], ne.Arguments[0] as CodeBlockExpression); } } } // pass 2, expand lambda bodies for (int i = 0; i < vars.Count; i++) { Expression e = assignments[i]; NameHint = SymbolTable.StringToId(n + "::" + Builtins.UnGenSymInternal(vars[i])); if (bodies[i] != null) { CodeBlockDescriptor[] cbds; CodeBlockExpression cbe; if (libraryglobals.TryGetValue(locals[i].Name, out cbe)) { Cons b = bodies[i] as Cons; CodeBlock cbody = cbe.Block; cbody.Body = null; FillBody(cbody, new List <Statement>(), b, true); } else if (libraryglobalsX.TryGetValue(locals[i].Name, out cbe)) { Cons b = bodies[i] as Cons; CodeBlock cbody = cbe.Block; cbody.Body = null; FillBody(cbody, new List <Statement>(), b, true); } else if (libraryglobalsN.TryGetValue(locals[i].Name, out cbds)) { List <Cons> b = bodies[i] as List <Cons>; for (int j = 0; j < b.Count; j++) { CodeBlock cbody = cbds[j].codeblock.Block; cbody.Body = null; FillBody(cbody, new List <Statement>(), b[j], true); } } } stmts.Add(Ast.Write(locals[i], e)); // needed indeed if (!isprogram) { stmts.Add(Ast.Statement(Ast.SimpleCallHelper(SetSymbolValue, Ast.Constant(vars[i]), Ast.Read(locals[i])))); } } Cons body = Builtins.Cdr(args) as Cons; FillBody(cb, stmts, body, true); cb.ExplicitCodeContextExpression = Ast.CodeContext(); #if OPTIMIZATIONS Expression ex = InlineCall(c, Ast.CodeBlockExpression(cb, false)); #else Expression ex = Ast.SimpleCallHelper(MakeClosure(cb, false), GetCallable(0)); #endif NameHint = SymbolId.Invalid; ClrGenerator.ResetReferences(ns); return(ex); }
internal override Expression ToExpression(MethodBinderContext context, IList <ArgBuilder> args, IList <Expression> parameters, Expression ret) { List <Expression> sets = new List <Expression>(); Variable tmp = null;// context.GetTemporary(ret.Type, "val"); for (int i = 0; i < _indexesUsed.Length; i++) { Expression value = parameters[parameters.Count - _kwArgCount + _indexesUsed[i]]; switch (_membersSet[i].MemberType) { case MemberTypes.Field: FieldInfo fi = (FieldInfo)_membersSet[i]; if (!fi.IsLiteral && !fi.IsInitOnly) { sets.Add(Ast.AssignField(Ast.Read(tmp), fi, Ast.ConvertHelper(value, fi.FieldType))); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(RuntimeHelpers).GetMethod("ReadOnlyAssignError"), Ast.Constant(true), Ast.Constant(fi.Name) ), fi.FieldType ) ); } break; case MemberTypes.Property: PropertyInfo pi = (PropertyInfo)_membersSet[i]; if (pi.GetSetMethod(ScriptDomainManager.Options.PrivateBinding) != null) { sets.Add(Ast.AssignProperty(Ast.Read(tmp), pi, Ast.ConvertHelper(value, pi.PropertyType))); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(RuntimeHelpers).GetMethod("ReadOnlyAssignError"), Ast.Constant(false), Ast.Constant(pi.Name) ), pi.PropertyType ) ); } break; } } Expression newCall = Ast.Comma( 0, ArrayUtils.Insert <Expression>( Ast.Assign(tmp, ret), sets.ToArray() ) ); return(_builder.ToExpression(context, args, parameters, newCall)); }
// (clr-call type member obj arg1 ... ) public override Expression Generate(object args, CodeBlock cb) { Type t = null; string type = null; bool inferred = false; object rtype = Builtins.First(args); ExtractTypeInfo(rtype, out t, out type, out inferred); string member = null; var marg = Builtins.Second(args); object memobj = null; Type[] argtypes = null; Type[] gentypes = null; if (marg is SymbolId) { var mem = Builtins.SymbolValue(marg); if (mem is Cons) { ExtractMethodInfo(mem as Cons, out member, ref argtypes, ref gentypes); } else { ClrSyntaxError("clr-call", "type member not supported", mem); } } else { memobj = Builtins.Second(marg); member = memobj is SymbolId?SymbolTable.IdToString((SymbolId)memobj) : ""; if (memobj is string) { string mems = memobj as string; int bi = mems.IndexOf('('); if (bi < 0) { member = mems; } else { member = mems.Substring(0, bi); } } else if (memobj is Cons) { ExtractMethodInfo(memobj as Cons, out member, ref argtypes, ref gentypes); } } Expression instance = GetAst(Builtins.Third(args), cb); CallType ct = CallType.ImplicitInstance; if (instance is ConstantExpression && ((ConstantExpression)instance).Value == null) { ct = CallType.None; if (inferred) { ClrSyntaxError("clr-call", "type inference not possible on static member", member); } } else if (inferred) { if (instance is UnaryExpression && instance.Type == typeof(object)) { var ue = (UnaryExpression)instance; instance = ue.Operand; } t = instance.Type; } else { instance = ConvertToHelper(t, instance); } type = t.Name; Expression[] arguments = GetAstListNoCast(Cdddr(args) as Cons, cb); if (member == "get_Item") { if (Attribute.IsDefined(t, typeof(DefaultMemberAttribute))) { var dma = Attribute.GetCustomAttribute(t, typeof(DefaultMemberAttribute)) as DefaultMemberAttribute; member = "get_" + dma.MemberName; } else if (t.IsArray) { var index = arguments[0]; return(Ast.ArrayIndex(instance, Ast.ConvertHelper(index, typeof(int)))); } } else if (member == "set_Item") { if (Attribute.IsDefined(t, typeof(DefaultMemberAttribute))) { var dma = Attribute.GetCustomAttribute(t, typeof(DefaultMemberAttribute)) as DefaultMemberAttribute; member = "set_" + dma.MemberName; } else if (t.IsArray) { var index = arguments[0]; var v = arguments[1]; return(Ast.Comma(Ast.AssignArrayIndex(instance, Ast.ConvertHelper(index, typeof(int)), v), Ast.ReadField(null, Unspecified))); } } List <MethodBase> candidates = new List <MethodBase>(); BindingFlags bf = BindingFlags.Public | (ct == CallType.None ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.FlattenHierarchy; foreach (MethodInfo mi in t.GetMember(member, MemberTypes.Method, bf)) { if (PAL.ExcludeParamtypes(mi)) { continue; } if (mi.ContainsGenericParameters) { if (gentypes != null && mi.GetGenericArguments().Length == gentypes.Length) { candidates.Add(mi.MakeGenericMethod(gentypes)); continue; } } candidates.Add(mi); } Type[] types = new Type[arguments.Length]; for (int i = 0; i < types.Length; i++) { types[i] = arguments[i].Type; } if (memobj is string) { string mems = memobj as string; int bi = mems.IndexOf('('); if (bi < 0) { // do notthig } else { string[] typeargs = mems.Substring(bi + 1).TrimEnd(')').Split(','); for (int i = 0; i < types.Length; i++) { if (typeargs[i].Length > 0) { types[i] = ScanForType(typeargs[i]); } } } } else if (argtypes != null) { for (int i = 0; i < types.Length; i++) { types[i] = argtypes[i]; } } if (ct == CallType.ImplicitInstance) { types = ArrayUtils.Insert(t, types); } MethodBinder mb = MethodBinder.MakeBinder(Binder, member, candidates, BinderType.Normal); MethodCandidate mc = mb.MakeBindingTarget(ct, types); if (mc == null) { types = new Type[arguments.Length]; for (int i = 0; i < types.Length; i++) { types[i] = typeof(object); } if (ct == CallType.ImplicitInstance) { types = ArrayUtils.Insert(t, types); } mc = mb.MakeBindingTarget(ct, types); } if (mc != null) { MethodInfo meth = (MethodInfo)mc.Target.Method; // do implicit cast ParameterInfo[] pars = meth.GetParameters(); for (int i = 0; i < arguments.Length; i++) { Type tt = pars[i].ParameterType; arguments[i] = ConvertToHelper(tt, arguments[i]); } Expression r = null; // o god... if (ct == CallType.ImplicitInstance) { r = Ast.ComplexCallHelper(instance, (MethodInfo)mc.Target.Method, arguments); } else { r = Ast.ComplexCallHelper((MethodInfo)mc.Target.Method, arguments); } return(ConvertFromHelper(meth.ReturnType, r)); } ClrSyntaxError("clr-call", "member could not be resolved on type: " + type, args, member); return(null); }