public NoSuchMemberException(RelinqScriptExpression root, MemberAccessExpression mae, RelinqScriptType typeOfTarget) : base(mae.Parent is InvokeExpression && mae.ChildIndex == 0 ? JSToCSharpExceptionType.NoSuchMethod : JSToCSharpExceptionType.NoSuchFieldOrProp, root, mae) { InferredTypeOfTarget = typeOfTarget; MemberName = mae.Name; }
private void InferMemberAccess(MemberAccessExpression mae, TypeInferenceCache cache) { InferTypes(mae.Target, cache); var typeofTarget = cache[mae.Target]; if (typeofTarget is ClrType) { // nb: the member access also covers method group lookup // i.e. object.Method(arg1, arg2) is in fact resolved in two steps: // 1) object.Method -> resolves to all instance or extension methods // (on this step fields and properties are omitted because the expression // is being used in the context of an invocation) // 2) MG(arg1, arg2) -> picks up the best method from the MG that matches arglist var usedInContextOfInvocation = mae.Parent is InvokeExpression && mae.ChildIndex == 0; cache.Add(mae, usedInContextOfInvocation ? typeofTarget.LookupMethodGroup(mae.Name) : typeofTarget.LookupMemberAccess(mae.Name)); if (cache[mae] == null) { throw new NoSuchMemberException(Root, mae, typeofTarget); } } else if (typeofTarget is Variant) { cache.Add(mae, new Variant()); } else { throw new NoSuchMemberException(Root, mae, typeofTarget); } }
private LinqExpression CompileMemberAccess(MemberAccessExpression mae, CompilationContext ctx) { if (ctx.Types[mae] is ClrType) { var clrType = ((ClrType)ctx.Types[mae.Target]).Type; if (clrType.IsArray && mae.Name == "Length") { return LinqExpression.ArrayLength(Compile(mae.Target, ctx)); } else { var fop = clrType.GetFieldOrProperty(mae.Name); //no validation for fop != null and being only of 2 possible types - I'm sick & tired! return fop is FieldInfo ? LinqExpression.Field(Compile(mae.Target, ctx), (FieldInfo)fop) : LinqExpression.Property(Compile(mae.Target, ctx), (PropertyInfo)fop); } } else if (ctx.Types[mae] is MethodGroup) { // we have three variants here: // 1) mae is a target of an Invoke -> note. processed, but not here // 2) mae is an argument of a call -> we need to emit a CreateDelegate stuff // 3) mae is a branch of a conditional -> same as 2 var expected = AcquireExpectedTypeFromContext(mae, ctx); if (!expected.IsDelegate()) { throw new CSharpBuilderException( JSToCSharpExceptionType.UnexpectedInferredAst, Ast, mae, ctx); } var createDelegate = typeof(Delegate).GetMethod("CreateDelegate", new []{ typeof(Type), typeof(Object), typeof(MethodInfo)}); return LinqExpression.Call(createDelegate, new []{ LinqExpression.Constant(expected, typeof(Type)), Compile(mae.Target, ctx), LinqExpression.Constant(ctx.Invocations[mae], typeof(MethodInfo))}); } else { throw new CSharpBuilderException( JSToCSharpExceptionType.UnexpectedInferredAst, Ast, mae, ctx); } }