} // func InvokeExpression private static Expression InvokeMemberExpression(Scope scope, Token tStart, Expression instance, string sMember, InvokeResult result, ArgumentsList arguments) { if (LuaEmit.IsDynamicType(instance.Type)) { return(EnsureInvokeResult(scope, tStart, DynamicExpression.Dynamic(scope.Runtime.GetInvokeMemberBinder(sMember, arguments.CallInfo), typeof(object), new Expression[] { ConvertExpression(scope.Runtime, tStart, instance, typeof(object)) }.Concat( from c in arguments.Expressions select Lua.EnsureType(c, typeof(object)) ).ToArray() ), result, instance, sMember )); } else { // look up the method MethodInfo method = LuaEmit.FindMethod( LuaType.GetType(instance.Type).GetInstanceMethods(sMember, false), arguments.CallInfo, arguments.Expressions, getExpressionTypeFunction, true); if (method != null) { return(EnsureInvokeResult(scope, tStart, SafeExpression(() => InvokeMemberExpressionBind(method, scope.Runtime, instance, arguments), tStart), result, instance, sMember)); } else { return(InvokeMemberExpressionDynamic(scope, tStart, instance, sMember, result, arguments)); } } } // func InvokeMemberExpression
} // func InvokeMemberExpressionDynamic private static Expression EnsureInvokeResult(Scope scope, Token tStart, Expression expr, InvokeResult result, Expression instance, string memberName) { switch (result) { case InvokeResult.LuaResult: if (expr.Type == typeof(object)) { return(ConvertExpression(scope.Runtime, tStart, expr, typeof(LuaResult))); } else { return(MemberGetSandbox(scope, expr, instance, memberName)); } case InvokeResult.Object: if (LuaEmit.IsDynamicType(expr.Type)) { return(MemberGetSandbox(scope, DynamicExpression.Dynamic(scope.Runtime.GetConvertBinder(typeof(object)), typeof(object), ConvertExpression(scope.Runtime, tStart, expr, typeof(object))), instance, memberName)); } else { return(MemberGetSandbox(scope, expr, instance, memberName)); } default: return(MemberGetSandbox(scope, expr, instance, memberName)); } } // func EnsureInvokeResult
private static Expression MemberSetExpressionCore(Lua lua, Token tokenStart, Expression instance, string memberName, Expression set) { if (LuaEmit.IsDynamicType(instance.Type)) // first call the dynamic interface { return(DynamicExpression.Dynamic(lua.GetSetMemberBinder(memberName), typeof(object), ConvertObjectExpression(lua, tokenStart, instance, true), ConvertObjectExpression(lua, tokenStart, set, true) )); } else { Expression result; switch (LuaEmit.TrySetMember(instance, instance.Type, memberName, false, (setType) => ConvertExpression(lua, tokenStart, set, setType), out result)) { case LuaTrySetMemberReturn.None: throw ParseError(tokenStart, LuaEmitException.GetMessageText(LuaEmitException.MemberNotFound, instance.Type.Name, memberName)); case LuaTrySetMemberReturn.NotWritable: throw ParseError(tokenStart, LuaEmitException.GetMessageText(LuaEmitException.CanNotWriteMember, instance.Type.Name, memberName)); case LuaTrySetMemberReturn.ValidExpression: return(result); default: throw new ArgumentException("Internal return type of TrySetMember"); } } } // func MemberSetExpressionCore
} // func MemberGetSandbox private static Expression MemberGetExpressionCore(Lua lua, Token tokenStart, Expression instance, string memberName) { // if this is a dynamic type, let the type deside what is to do if (LuaEmit.IsDynamicType(instance.Type)) { return(DynamicExpression.Dynamic(lua.GetGetMemberBinder(memberName), typeof(object), ConvertObjectExpression(lua, tokenStart, instance, true))); } else { Expression result; switch (LuaEmit.TryGetMember(instance, instance.Type, memberName, false, out result)) { case LuaTryGetMemberReturn.None: throw ParseError(tokenStart, LuaEmitException.GetMessageText(LuaEmitException.MemberNotFound, instance.Type.Name, memberName)); case LuaTryGetMemberReturn.NotReadable: throw ParseError(tokenStart, LuaEmitException.GetMessageText(LuaEmitException.CanNotReadMember, instance.Type.Name, memberName)); case LuaTryGetMemberReturn.ValidExpression: return(result); default: throw new ArgumentException("Internal return type of TryGetMember"); } } } // func MemberGetExpressionCore
} // func IndexSetExpression private static Expression InvokeExpression(Scope scope, Token tStart, Expression instance, InvokeResult result, ArgumentsList arguments, bool lParse) { MethodInfo mi; ConstantExpression constInstance = instance as ConstantExpression; LuaType t; if (constInstance != null && (t = constInstance.Value as LuaType) != null && t.Type != null) // we have a type, bind the ctor { var type = t.Type; var typeInfo = type.GetTypeInfo(); var ci = typeInfo.IsValueType && arguments.Count == 0 ? null : LuaEmit.FindMember(typeInfo.DeclaredConstructors.Where(c => c.IsPublic), arguments.CallInfo, arguments.Expressions, getExpressionTypeFunction, false); if (ci == null && !typeInfo.IsValueType) { throw ParseError(tStart, String.Format(Properties.Resources.rsMemberNotResolved, type.Name, "ctor")); } return(SafeExpression(() => LuaEmit.BindParameter(scope.Runtime, args => ci == null ? Expression.New(type) : Expression.New(ci, args), ci == null ? new ParameterInfo[0] : ci.GetParameters(), arguments.CallInfo, arguments.Expressions, getExpressionFunction, getExpressionTypeFunction, true), tStart)); } else if (LuaEmit.IsDynamicType(instance.Type)) { // fallback is a dynamic call return(EnsureInvokeResult(scope, tStart, DynamicExpression.Dynamic(scope.Runtime.GetInvokeBinder(arguments.CallInfo), typeof(object), new Expression[] { ConvertExpression(scope.Runtime, tStart, instance, typeof(object)) }.Concat( from c in arguments.Expressions select Lua.EnsureType(c, typeof(object)) ) ), result, instance, null )); } else if (typeof(Delegate).GetTypeInfo().IsAssignableFrom(instance.Type.GetTypeInfo()) && // test if the type is assignable from delegate (mi = instance.Type.GetRuntimeMethods().Where(c => !c.IsStatic && c.IsPublic && c.Name == "Invoke").FirstOrDefault()) != null) // Search the Invoke method for the arguments { return(EnsureInvokeResult(scope, tStart, SafeExpression(() => LuaEmit.BindParameter <Expression>( scope.Runtime, args => Expression.Invoke(instance, args), mi.GetParameters(), arguments.CallInfo, arguments.Expressions, getExpressionFunction, getExpressionTypeFunction, true), tStart), result, instance, null )); } else { throw ParseError(tStart, LuaEmitException.GetMessageText(LuaEmitException.InvokeNoDelegate, instance.Type.Name)); } } // func InvokeExpression
} // func BinaryOperationExpression private static Expression ConcatOperationExpression(Lua runtime, Token tStart, Expression[] args) { if (Array.Exists(args, c => LuaEmit.IsDynamicType(c.Type))) // we have a dynamic type in the list -> to the concat on runtime { return(SafeExpression(() => Expression.Call(Lua.ConcatStringMethodInfo, Expression.NewArrayInit(typeof(object), from e in args select ConvertObjectExpression(runtime, tStart, e, true))), tStart)); } else { return(SafeExpression(() => Expression.Call(Lua.StringConcatMethodInfo, Expression.NewArrayInit(typeof(string), from e in args select LuaEmit.Convert(runtime, e, e.Type, typeof(string), true))), tStart)); } } // func ConcatOperationExpression
} // func InvokeExpression private static Expression InvokeMemberExpression(Scope scope, Token tStart, Expression instance, string memberName, InvokeResult result, ArgumentsList arguments) { if (LuaEmit.IsDynamicType(instance.Type) || arguments.Expressions.Any(c => LuaEmit.IsDynamicType(c.Type))) { var dynamicArguments = new Expression[arguments.Count + 1]; // first argument is the instance dynamicArguments[0] = ConvertObjectExpression(scope.Runtime, tStart, instance, false); if (arguments.Count > 0) { // single object for (var i = 0; i < arguments.Count - 1; i++) { dynamicArguments[i + 1] = ConvertObjectExpression(scope.Runtime, tStart, arguments.Expressions[i], false); } // last argument is different if (arguments.CallInfo.ArgumentNames.Count > 0) { dynamicArguments[dynamicArguments.Length - 1] = ConvertObjectExpression(scope.Runtime, tStart, arguments.Expressions[arguments.Count - 1], false); } else { dynamicArguments[dynamicArguments.Length - 1] = Lua.EnsureType(arguments.Expressions[arguments.Count - 1], typeof(object)); } } return(EnsureInvokeResult(scope, tStart, DynamicExpression.Dynamic(scope.Runtime.GetInvokeMemberBinder(memberName, arguments.CallInfo), typeof(object), dynamicArguments), result, instance, memberName )); } else { return(EnsureInvokeResult(scope, tStart, SafeExpression(() => { Expression expr; if (!LuaEmit.TryInvokeMember <Expression>(scope.Runtime, LuaType.GetType(instance.Type), instance, arguments.CallInfo, arguments.Expressions, memberName, false, e => e, e => e.Type, true, out expr)) { throw new LuaEmitException(LuaEmitException.MemberNotFound, instance.Type, memberName); } return expr; }, tStart), result, instance, memberName )); } } // func InvokeMemberExpression