public static Expr UnaryMinus(Context context, DynamicMetaObject target) { return Expr.Invoke( Expr.Constant((Func<Context, object, object>)LuaOps.UnaryMinusMetamethod), Expr.Constant(context, typeof(Context)), Expr.Convert(target.Expression, typeof(object))); }
public static object Concat(Context context, object left, object right) { if ((left is string || left is double) && (right is double || right is string)) return String.Concat(left, right); return ConcatMetamethod(context, left, right); }
public static Expr Index(Context context, DynamicMetaObject target, DynamicMetaObject[] indexes) { return Expr.Invoke( Expr.Constant((Func<Context, object, object, object>)LuaOps.IndexMetamethod), Expr.Constant(context, typeof(Context)), Expr.Convert(target.Expression, typeof(object)), Expr.Convert(indexes[0].Expression, typeof(object))); }
public static Expr BinaryOp(Context context, ExprType operation, DynamicMetaObject left, DynamicMetaObject right) { return Expr.Invoke( Expr.Constant((Func<Context, ExprType, object, object, object>)LuaOps.BinaryOpMetamethod), Expr.Constant(context, typeof(Context)), Expr.Constant(operation), Expr.Convert(left.Expression, typeof(object)), Expr.Convert(right.Expression, typeof(object))); }
public static object ConcatMetamethod(Context context, object left, object right) { var metamethod = GetMetamethod(context, left, Constant.CONCAT_METAMETHOD) ?? GetMetamethod(context, right, Constant.CONCAT_METAMETHOD); if (metamethod != null) return Context.DynamicCache.GetDynamicCall2()(metamethod, left, right); var typeName = left is string ? BaseLibrary.Type(left) : BaseLibrary.Type(right); throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_ERROR, "concatenate", typeName); }
public static object GetMetamethod(Context context, object obj, string methodName) { LuaTable table; if ((table = obj as LuaTable) != null) table = table.Metatable; else if (context != null) table = context.GetTypeMetatable(obj); return methodName == null || table == null ? null : table.GetValue(methodName); }
public static Expr Call(Context context, DynamicMetaObject target, DynamicMetaObject[] args) { var expression = Expr.Invoke( Expr.Constant((Func<Context, object, object[], object>)LuaOps.CallMetamethod), Expr.Constant(context, typeof(Context)), Expr.Convert(target.Expression, typeof(object)), Expr.NewArrayInit( typeof(object), args.Select(arg => Expr.Convert(arg.Expression, typeof(object))))); return expression; }
public static object CallMetamethod(Context context, object obj, object[] args) { var metamethod = GetMetamethod(context, obj, Constant.CALL_METAMETHOD); if (metamethod != null) { var array = new object[args.Length + 1]; array[0] = obj; Array.Copy(args, 0, array, 1, args.Length); return Context.DynamicCache.GetDynamicCall1()(metamethod, new Varargs(array)); } throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_ERROR, "call", BaseLibrary.Type(obj)); }
public static Expr ConvertToNumberAndCheck(Context context, Expr expression, string format, params object[] args) { var numberVar = Expr.Variable(typeof(double)); var assignNumber = Expr.Assign(numberVar, ConvertToNumber(context, expression)); return Expr.Block( new[] {numberVar}, assignNumber, Expr.Condition( Expr.Invoke( Expr.Constant((Func<double, bool>)Double.IsNaN), numberVar), Expr.Block( Expr.Throw(Expr.New(MemberInfos.NewRuntimeException, Expr.Constant(format), Expr.Constant(args))), Expr.Constant(Double.NaN)), numberVar)); }
public static object BinaryOpMetamethod(Context context, ExprType op, object left, object right) { switch (op) { case ExprType.Add: case ExprType.Subtract: case ExprType.Multiply: case ExprType.Divide: case ExprType.Modulo: case ExprType.Power: return NumericMetamethod(context, op, left, right); case ExprType.GreaterThan: case ExprType.GreaterThanOrEqual: case ExprType.LessThan: case ExprType.LessThanOrEqual: return RelationalMetamethod(context, op, left, right); default: throw new ArgumentOutOfRangeException("op"); } }
public static object Length(Context context, object obj) { string str; LuaTable table; if ((str = obj as string) != null) return str.Length; if ((table = obj as LuaTable) != null) return table.Length(); return LengthMetamethod(context, obj); }
static object GetRelationalMetamethod(Context context, ExprType op, object left, object right) { var methodName = GetMethodName(op); var metamethodLeft = GetMetamethod(context, left, methodName); var metamethodRight = GetMetamethod(context, right, methodName); return metamethodLeft != metamethodRight ? null : metamethodLeft; }
public static object UnaryMinusMetamethod(Context context, object obj) { var metamethod = GetMetamethod(context, obj, Constant.UNARYMINUS_METAMETHOD); if (metamethod != null) return Context.DynamicCache.GetDynamicCall1()(metamethod, obj); throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_ERROR, "perform arithmetic on", BaseLibrary.Type(obj)); }
public static object RelationalMetamethod(Context context, ExprType op, object left, object right) { if (left.GetType() != right.GetType()) return false; // There are no metamethods for 'a > b' and 'a >= b' so they are translated to 'b < a' and 'b <= a' respectively var invert = op == ExprType.GreaterThan || op == ExprType.GreaterThanOrEqual; var metamethod = GetRelationalMetamethod(context, op, left, right); if (metamethod != null) { if (invert) Context.DynamicCache.GetDynamicCall2()(metamethod, right, left); else Context.DynamicCache.GetDynamicCall2()(metamethod, left, right); } // In the absence of a '<=' metamethod, try '<', 'a <= b' is translated to 'not (b < a)' if (op != ExprType.LessThanOrEqual && op != ExprType.GreaterThanOrEqual) return false; metamethod = GetRelationalMetamethod(context, ExprType.LessThan, left, right); if (metamethod != null) { if (invert) Not(Context.DynamicCache.GetDynamicCall2()(metamethod, right, left)); else Not(Context.DynamicCache.GetDynamicCall2()(metamethod, left, right)); } var leftTypeName = BaseLibrary.Type(left); var rightTypeName = BaseLibrary.Type(right); if (leftTypeName == rightTypeName) throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_TWO_ERROR, "compare", leftTypeName); throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_WITH_ERROR, "compare", leftTypeName, rightTypeName); }
public static Expr ConvertToNumber(Context context, Expr expression) { var convertBinder = Context.DynamicCache.GetConvertBinder(typeof(double)); return Expr.Dynamic(convertBinder, typeof(double), expression); }
public static object IndexMetamethod(Context context, object obj, object key) { var metamethod = GetMetamethod(context, obj, Constant.INDEX_METAMETHOD); if (metamethod != null) { if (metamethod is Delegate) return Context.DynamicCache.GetDynamicCall2()(metamethod, obj, key); if (metamethod is LuaTable) return Context.DynamicCache.GetDynamicIndex()(obj, key); } if (obj is LuaTable) return null; throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_ERROR, "index", BaseLibrary.Type(obj)); }
public BaseLibrary(Context context) : base(context) { }
public StringLibrary(Context context) : base(context) { }
public static object LengthMetamethod(Context context, object obj) { var metamethod = GetMetamethod(context, obj, Constant.LENGTH_METAMETHOD); if (metamethod != null) return Context.DynamicCache.GetDynamicCall1()(metamethod, obj); throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_ERROR, "get length of", BaseLibrary.Type(obj)); }
public static object NumericMetamethod(Context context, ExprType op, object left, object right) { var methodName = GetMethodName(op); var metamethod = GetMetamethod(context, left, methodName) ?? GetMetamethod(context, right, methodName); if (metamethod != null) return Context.DynamicCache.GetDynamicCall2()(metamethod, left, right); var typeName = BaseLibrary.Type(BaseLibrary.ToNumber(left) == null ? left : right); throw new LuaRuntimeException(ExceptionMessage.OP_TYPE_ERROR, "perform arithmetic on", typeName); }
protected Library(Context context) { Context = context; }
public static Expr ConvertToBoolean(Context context, Expr expression) { var convertBinder = Context.DynamicCache.GetConvertBinder(typeof(bool)); return Expr.Dynamic(convertBinder, typeof(bool), expression); }