private LuaScope(LuaScope parent) { this.context = parent.context; this.parent = parent; this.variables = new Dictionary<string, ParamExpr>(); this.labels = new Dictionary<string, LabelTarget>(); }
public static LuaScope CreateRoot(CodeContext context) { Contract.Requires(context != null); var scope = new LuaScope(context); scope.labels.Add(ReturnLabelName, Expr.Label(typeof(object))); return scope; }
public static object BinaryOpMetamethod(CodeContext context, ExprType op, object left, object right) { ContractUtils.RequiresNotNull(context, "context"); 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); case ExprType.Equal: return EquateMetamethod(context, op, left, right); case ExprType.NotEqual: return Not(EquateMetamethod(context, ExprType.Equal, left, right)); default: throw new ArgumentOutOfRangeException("op"); } }
private LuaScope(CodeContext context) { this.context = context; this.parent = null; this.variables = new Dictionary<string, ParamExpr>(); this.labels = new Dictionary<string, LabelTarget>(); }
/// <summary> /// Wraps a new function definition, so that the function can be registered as a Lua function with the relevant /// CodeContext. This allows the function to benefit from custom execution environments. /// </summary> public FunctionDefinitionExpression(CodeContext context, LuaScope scope, IEnumerable<string> identifiers, LambdaExpression function) { _context = context; _scope = scope; _body = function; _identifier = identifiers.Merge((s1, s2) => s1 + "." + s2); }
public static object Concat(CodeContext context, object left, object right) { ContractUtils.RequiresNotNull(context, "context"); if ((left is string || left is double) && (right is double || right is string)) return String.Concat(left, right); return ConcatMetamethod(context, left, right); }
/// <summary> /// Creates a wrapper around a function which represents entry into its scope /// </summary> /// <param name="context">The context under which this function is compiled</param> /// <param name="body">The block expression which represents this function's execution</param> /// <param name="evalScope">The scope in which the body will be executed, holding local values</param> /// <param name="upScope">The scope in which the function will execute, storing up values (which persist between calls)</param> public FunctionScopeExpression(CodeContext context, LuaScope evalScope, LuaScope upScope, string identifier, Expression body) { _context = Expression.Constant(context); _body = body; _stack = Expression.Constant(new FunctionStack(context, upScope, evalScope, identifier)); _evalScope = evalScope; _upScope = upScope; }
public static object ConcatMetamethod(CodeContext context, object left, object right) { ContractUtils.RequiresNotNull(context, "context"); 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 LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_ERROR, "concatenate", typeName); }
public static object CallMetamethod(CodeContext context, object obj, object[] args) { ContractUtils.RequiresNotNull(context, "context"); 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 LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_ERROR, "call", BaseLibrary.Type(obj)); }
public static Expr ConvertToNumberAndCheck(CodeContext 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(context), Expr.Constant(format), Expr.Constant(args))), Expr.Constant(Double.NaN)), numberVar)); }
public static Expr BinaryOp(CodeContext context, ExprType operation, DynamicMetaObject left, DynamicMetaObject right) { return BinaryOp(Expr.Constant(context, typeof(CodeContext)), operation, left, right); }
public static Expr WrapStackTrace(Expr expr, CodeContext context, FunctionStack callSite) { var tempVar = Expr.Variable(typeof(object), "$metamethod_result$"); return Expr.Block(new[] { tempVar }, LuaExpr.FunctionScope(context, callSite.ExecScope, callSite.UpScope, new[] { callSite.Identifier }, Expr.Assign(tempVar, expr))); }
public static Expr UnaryMinus(CodeContext context, DynamicMetaObject target) { return UnaryMinus(Expr.Constant(context, typeof(CodeContext)), target); }
public static object NewIndexMetamethod(CodeContext context, object obj, object key, object value) { ContractUtils.RequiresNotNull(context, "context"); var metamethod = GetMetamethod(context, obj, Constant.NEWINDEX_METAMETHOD); if (metamethod != null) { if (metamethod is Delegate) return context.DynamicCache.GetDynamicCall3()(metamethod, obj, key, value); if (metamethod is LuaTable) return context.DynamicCache.GetDynamicNewIndex()(obj, key, value); } if (obj is LuaTable) { return (obj as LuaTable).SetValue(key, value); //var targetParam = Expr.Parameter(typeof(object)); //var keyParam = Expr.Parameter(typeof(object)); //var valParam = Expr.Parameter(typeof(object)); //var expression = Expr.Call( // Expr.Convert(targetParam, typeof(LuaTable)), // MemberInfos.LuaTableSetValue, // keyParam, // valParam); //return Expr.Lambda<Func<object, object, object, object>>( // Expr.Block(typeof(object), // new[] { targetParam, keyParam, valParam }, // expression) // , targetParam, keyParam, valParam).Compile()(obj, key, value); } throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_ERROR, "index", BaseLibrary.Type(obj)); }
public InteropLibrary(CodeContext context, params Type[] types) : base(context) { InteropMetatable = GenerateMetatable(context); }
public static Expr NewIndex(CodeContext context, DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value) { return NewIndex(Expr.Constant(context, typeof(CodeContext)), target, indexes, value); }
public static object EquateMetamethod(CodeContext context, ExprType op, object left, object right) { ContractUtils.RequiresNotNull(context, "context"); var leftTypeName = BaseLibrary.Type(left); var rightTypeName = BaseLibrary.Type(right); if (left == null && right == null) return true; var metamethod = GetRelationalMetamethod(context, op, left, right); if (metamethod != null) return context.DynamicCache.GetDynamicCall2()(metamethod, left, right); else return left == null ? right.Equals(left) : left.Equals(right); }
public static object Length(CodeContext context, object obj) { ContractUtils.RequiresNotNull(context, "context"); 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); }
public static object LengthMetamethod(CodeContext context, object obj) { ContractUtils.RequiresNotNull(context, "context"); var metamethod = GetMetamethod(context, obj, Constant.LENGTH_METAMETHOD); if (metamethod != null) return context.DynamicCache.GetDynamicCall1()(metamethod, obj); throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_ERROR, "get length of", BaseLibrary.Type(obj)); }
static object GetRelationalMetamethod(CodeContext 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(CodeContext context, object obj) { ContractUtils.RequiresNotNull(context, "context"); var metamethod = GetMetamethod(context, obj, Constant.UNARYMINUS_METAMETHOD); if (metamethod != null) return context.DynamicCache.GetDynamicCall1()(metamethod, obj); throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_ERROR, "perform arithmetic on", BaseLibrary.Type(obj)); }
public static object RelationalMetamethod(CodeContext context, ExprType op, object left, object right) { ContractUtils.RequiresNotNull(context, "context"); var leftTypeName = BaseLibrary.Type(left); var rightTypeName = BaseLibrary.Type(right); //if (left.GetType() != right.GetType()) // throw LuaRuntimeException.Create(ExceptionMessage.OP_TYPE_WITH_ERROR, "compare", leftTypeName, rightTypeName); // 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) return context.DynamicCache.GetDynamicCall2()(metamethod, right, left); else return 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) throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_WITH_ERROR, "compare", leftTypeName, rightTypeName); metamethod = GetRelationalMetamethod(context, ExprType.LessThan, left, right); if (metamethod != null) { if (invert) return Not(context.DynamicCache.GetDynamicCall2()(metamethod, right, left)); else return Not(context.DynamicCache.GetDynamicCall2()(metamethod, left, right)); } if (leftTypeName == rightTypeName) throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_TWO_ERROR, "compare", leftTypeName); throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_WITH_ERROR, "compare", leftTypeName, rightTypeName); }
public static Expr Call(CodeContext context, DynamicMetaObject target, DynamicMetaObject[] args) { return Call(Expr.Constant(context, typeof(CodeContext)), target, args); }
public static Expr CheckNumberForNan(CodeContext context, Expr number, string format, params object[] args) { return Expr.IfThen( Expr.Invoke(Expr.Constant((Func<double, bool>)Double.IsNaN), number), Expr.Throw(Expr.New(MemberInfos.NewRuntimeException, Expr.Constant(context), Expr.Constant(format), Expr.Constant(args)))); }
public static Expr Index(CodeContext context, DynamicMetaObject target, DynamicMetaObject[] indexes) { return Index(Expr.Constant(context, typeof(CodeContext)), target, indexes); }
public static Expr ConvertToBoolean(CodeContext context, Expr expression) { var convertBinder = context.CreateConvertBinder(typeof(bool), false); return Expr.Dynamic(convertBinder, typeof(bool), expression); }
internal LuaTable GenerateMetatable(CodeContext context) { LuaTable table = new LuaTable(context); table.SetConstant(Constant.INDEX_METAMETHOD, (Func<object, object, object>)InteropIndex); table.SetConstant(Constant.NEWINDEX_METAMETHOD, (Func<object, object, object, object>)InteropNewIndex); table.SetConstant(Constant.CALL_METAMETHOD, (Func<object, object[], object>)InteropCall); table.SetConstant(Constant.CONCAT_METAMETHOD, (Func<string, object, string>)Concat); table.SetConstant(Constant.TOSTRING_METAFIELD, (Func<object, string>)ToString); table.SetConstant(Constant.LENGTH_METAMETHOD, (Func<object, object>)InteropLength); return table; }
public static Expr ConvertToNumber(CodeContext context, Expr expression) { var convertBinder = context.CreateConvertBinder(typeof(double), false); return Expr.Dynamic(convertBinder, typeof(double), expression); }
public OSLibrary(CodeContext context) : base(context) { }
public static object NumericMetamethod(CodeContext context, ExprType op, object left, object right) { ContractUtils.RequiresNotNull(context, "context"); 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(context, left) == null ? left : right); throw LuaRuntimeException.Create(context, ExceptionMessage.OP_TYPE_ERROR, "perform arithmetic on", typeName); }