} // ctor public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { // Defer the parameters if (!target.HasValue || indexes.Any(c => !c.HasValue)) { DynamicMetaObject[] def = new DynamicMetaObject[indexes.Length + 1]; def[0] = target; Array.Copy(indexes, 0, def, 1, indexes.Length); return(Defer(def)); } Expression expr; if (target.Value == null) { if (errorSuggestion != null) { return(errorSuggestion); } expr = ThrowExpression(Properties.Resources.rsNullReference, ReturnType); } else { try { expr = Lua.EnsureType(LuaEmit.SetIndex(lua, target, indexes, value, mo => mo.Expression, mo => mo.LimitType, false), ReturnType); } catch (LuaEmitException e) { if (errorSuggestion != null) { return(errorSuggestion); } expr = ThrowExpression(e.Message, ReturnType); } } return(new DynamicMetaObject(expr, GetMethodSignatureRestriction(target, indexes).Merge(Lua.GetSimpleRestriction(value)))); } // func FallbackSetIndex
} // ctor public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { // defer the target if (!target.HasValue) { return(Defer(target)); } if (target.Value == null) { return(errorSuggestion ?? new DynamicMetaObject( ThrowExpression(String.Format(Properties.Resources.rsMemberNotResolved, target.LimitType.Name, Name), ReturnType), target.Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, null)) )); } else { Expression expr; try { expr = Lua.EnsureType(LuaEmit.SetMember(lua, target.Expression, target.LimitType, Name, IgnoreCase, value.Expression, value.LimitType, false), ReturnType); } catch (LuaEmitException e) { if (errorSuggestion != null) { return(errorSuggestion); } expr = ThrowExpression(e.Message, ReturnType); } return(new DynamicMetaObject( expr, target.Restrictions.Merge(BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType).Merge(Lua.GetSimpleRestriction(value))) )); } } // func FallbackSetMember
} // ctor public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { // Defer the parameters if (!target.HasValue || indexes.Any(c => !c.HasValue)) { return(Defer(target, indexes)); } Expression expr; if (target.Value == null) { if (errorSuggestion != null) { return(errorSuggestion); } expr = ThrowExpression(Properties.Resources.rsNullReference, ReturnType); } else { try { expr = Lua.EnsureType(LuaEmit.GetIndex(lua, target, indexes, mo => mo.Expression, mo => mo.LimitType, false), ReturnType); } catch (LuaEmitException e) { if (errorSuggestion != null) { return(errorSuggestion); } expr = ThrowExpression(e.Message, ReturnType); } } return(new DynamicMetaObject(expr, GetMethodSignatureRestriction(target, indexes))); } // func FallbackGetIndex
} // func InvokeMemberExpressionBind private static Expression InvokeMemberExpressionDynamic(Scope scope, Token tStart, Expression instance, string sMember, InvokeResult result, ArgumentsList arguments) { 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 a in arguments.Expressions select Lua.EnsureType(a, typeof(object))).ToArray() ), result, instance, sMember )); } // func InvokeMemberExpressionDynamic
} // func InvokeMemberExpression private static Expression InvokeMemberExpressionBind(MethodInfo method, Lua runtime, Expression instance, ArgumentsList arguments) { if (method.IsStatic) { return(LuaEmit.BindParameter(runtime, args => Expression.Call(null, method, args), method.GetParameters(), arguments.CallInfo, new Expression[] { instance }.Concat( from a in arguments.Expressions select Lua.EnsureType(a, typeof(object)) ).ToArray(), getExpressionFunction, getExpressionTypeFunction, true)); } else { return(LuaEmit.BindParameter(runtime, args => Expression.Call(instance, method, args), method.GetParameters(), arguments.CallInfo, arguments.Expressions, getExpressionFunction, getExpressionTypeFunction, true)); } } // func InvokeMemberExpressionBind
} // 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 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