public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) { LuaObject[] passingArgs = Array.ConvertAll <object, LuaObject>(args, x => (x is LuaObject ? (LuaObject)x : LuaObject.FromObject(x))); LuaArguments ret = this.Call(passingArgs); if (ret.Length == 1) { if (ret[0].IsNil) { result = null; } else { result = getObject(ret[0]); } return(true); } else { object[] res = Array.ConvertAll <LuaObject, object>(ret.ToArray(), x => getObject(x)); result = res; return(true); } }
static LuaArguments io_output(LuaArguments args) { var obj = args[0]; if (isStream(obj)) { currentOutput = obj; return(Lua.Return(currentOutput)); } else if (obj.IsString) { #if PORTABLE MemoryStream stream = new MemoryStream(); #else FileStream stream = new FileStream(obj.ToString(), FileMode.OpenOrCreate); #endif currentOutput = CreateFileObject(stream); return(Lua.Return(currentOutput)); } else if (args.Length == 0) { return(Lua.Return(currentOutput)); } else { throw new LuaException("Invalid argument"); } }
static LuaArguments EvalWhile(WhileStat stat, LuaContext Context, out LuaReturnStatus returned) { returned.returned = false; returned.broke = false; LuaObject cond = EvalExpression(stat.Condition, Context)[0]; LuaContext ctx = new LuaContext(Context); while (cond.AsBool()) { LuaArguments obj = EvalBlock(stat.Block, ctx, out returned); if (returned.broke) { break; } if (returned.returned) { return(obj); } else { cond = EvalExpression(stat.Condition, Context)[0]; } } return(Lua.Return()); }
static LuaArguments EvalRepeat(RepeatStat stat, LuaContext Context, out LuaReturnStatus returned) { returned.returned = false; returned.broke = false; LuaContext ctx = new LuaContext(Context); while (true) { LuaArguments obj = EvalBlock(stat.Block, ctx, out returned); if (returned.broke) { break; } if (returned.returned) { return(obj); } LuaObject cond = EvalExpression(stat.Condition, ctx)[0]; if (cond) { break; } } return(Lua.Return()); }
static LuaArguments write(LuaArguments args) { var self = args[0]; if (isStream(self)) { FileObject fobj = self.luaobj as FileObject; foreach (var arg in args) { if (arg == self) { continue; } if (!(arg.IsString || arg.IsNumber)) { Lua.Return(); } if (fobj.stream.CanWrite) { fobj.writer.Write(arg.ToString()); } else { Lua.Return(); } } return(Lua.Return(self)); } else { return(Lua.Return()); } }
static LuaArguments EvalNumericFor(NumericFor stat, LuaContext Context, out LuaReturnStatus returned) { returned.broke = false; returned.returned = false; var varList = EvalExpression(stat.Var, Context); var limitList = EvalExpression(stat.Limit, Context); var stepList = EvalExpression(stat.Step, Context); var var = LuaEvents.toNumber(varList[0]); var limit = LuaEvents.toNumber(limitList[0]); var step = LuaEvents.toNumber(stepList[0]); if (!(var & limit & step).AsBool()) { throw new LuaException("Error in for loop"); } LuaContext ctx = new LuaContext(Context); while ((step > 0 & var <= limit) | (step <= 0 & var >= limit)) { ctx.SetLocal(stat.Variable, var); LuaArguments obj = EvalBlock(stat.Block, ctx, out returned); if (returned.broke) { break; } if (returned.returned) { return(obj); } var = var + step; } return(Lua.Return()); }
LuaArguments type(LuaArguments args) { switch (args[0].Type) { case LuaType.boolean: return(Return("boolean")); case LuaType.function: return(Return("function")); case LuaType.nil: return(Return("nil")); case LuaType.number: return(Return("number")); case LuaType.@string: return(Return("string")); case LuaType.table: return(Return("table")); case LuaType.thread: return(Return("thread")); case LuaType.userdata: return(Return("userdata")); } return(Return()); }
LuaArguments tonumber(LuaArguments args) { LuaObject obj = args[0]; if (args.Length == 1) { double d = 0; if (obj.IsString) { if (double.TryParse(obj.AsString(), out d)) { return(Return(d)); } else { return(Return()); } } else if (obj.IsNumber) { return(Return(obj.AsNumber())); } else { return(Return()); } } else { //TODO: Implement tonumber for bases different from 10 throw new NotImplementedException(); } }
static LuaArguments io_temp(LuaArguments args) { string path = Path.GetTempFileName(); Stream s = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Write, Int16.MaxValue, FileOptions.DeleteOnClose); return(Lua.Return(CreateFileObject(s))); }
LuaArguments ipairs(LuaArguments args) { LuaObject handler = LuaEvents.getMetamethod(args[0], "__ipairs"); if (!handler.IsNil) { return(handler.Call(args)); } else { if (args[0].IsTable) { LuaFunction f = delegate(LuaArguments x) { var s = x[0]; var var = x[1].AsNumber() + 1; var val = s[var]; if (val == LuaObject.Nil) { return(Return(LuaObject.Nil)); } else { return(Return(var, val)); } }; return(Return(f, args[0], 0)); } else { throw new LuaException("t must be a table"); } } }
LuaArguments next(LuaArguments args) { var table = args[0]; var index = args[1]; if (!table.IsTable) { throw new LuaException("t must be a table"); } List <LuaObject> keys = new List <LuaObject>(table.AsTable().Keys); if (index.IsNil) { if (keys.Count == 0) { return(Return()); } return(Return(keys[0], table[keys[0]])); } else { int pos = keys.IndexOf(index); if (pos == keys.Count - 1) { return(Return()); } else { return(Return(keys[pos + 1], table[keys[pos + 1]])); } } }
static LuaArguments math_max(LuaArguments args) { var max = args[0]; foreach (LuaObject o in args) { max = Math.Max(max, o); } return(Lua.Return(max)); }
static LuaArguments math_min(LuaArguments args) { var min = args[0]; foreach (LuaObject o in args) { min = Math.Min(min, o); } return(Lua.Return(min)); }
static LuaArguments flush(LuaArguments args) { var obj = args[0]; if (isStream(obj)) { FileObject fobj = obj.luaobj as FileObject; fobj.writer.Flush(); } return(Lua.Return()); }
static LuaArguments close(LuaArguments args) { var obj = args[0]; if (isStream(obj)) { FileObject fobj = obj.luaobj as FileObject; fobj.stream.Close(); } return(Lua.Return()); }
/// <summary> /// Calls the object passing the instance as first argument. Uses the metafield __call /// </summary> /// <param name="instance">The object to be passed as first argument</param> /// <param name="args">Arguments to be passed after the object</param> public LuaArguments MethodCall(LuaObject instance, LuaArguments args) { LuaObject[] objs = new LuaObject[args.Length + 1]; objs[0] = instance; for (int i = 0; i < args.Length; i++) { objs[i + 1] = args[i]; } return(this.Call(objs)); }
static LuaArguments read(LuaArguments args) { var self = args[0]; if (isStream(self)) { var fobj = self.luaobj as FileObject; if (args.Length == 1) { var line = fobj.reader.ReadLine(); return(Lua.Return(line)); } else { List <LuaObject> ret = new List <LuaObject>(); foreach (var arg in args) { if (arg == self) { continue; } if (arg.IsNumber) { StringBuilder bld = new StringBuilder(); for (int i = 0; i < arg; i++) { bld.Append((char)fobj.reader.Read()); } ret.Add(bld.ToString()); } else if (arg == "*a") { ret.Add(fobj.reader.ReadToEnd()); } else if (arg == "*l") { ret.Add(fobj.reader.ReadLine()); } else if (arg == "*n") { //TODO: Implement io.read("*n") throw new NotImplementedException(); } } return(Lua.Return(ret.ToArray())); } } else { return(Lua.Return()); } }
LuaArguments pairs(LuaArguments args) { LuaObject handler = LuaEvents.getMetamethod(args[0], "__pairs"); if (!handler.IsNil) { return(handler.Call(args)); } else { return(Return((LuaFunction)next, args[0], LuaObject.Nil)); } }
static LuaArguments io_write(LuaArguments args) { var obj = args[0]; if (!obj.IsNil) { return(currentOutput["write"].MethodCall(currentOutput, args)); } else { return(Lua.Return()); } }
static LuaArguments io_close(LuaArguments args) { var obj = args[0]; if (obj.IsNil) { return(currentOutput["close"].MethodCall(currentOutput, args)); } else { return(obj["close"].MethodCall(obj, args)); } }
static LuaArguments EvalFunctionCall(FunctionCall Expression, LuaContext Context) { LuaObject func = EvalExpression(Expression.Function, Context)[0]; LuaArguments args = null; if (Expression.Arguments != null || Expression.Arguments.Count != 0) { List <LuaObject> values = new List <LuaObject>(); foreach (IExpression expr in Expression.Arguments) { values.AddRange(EvalExpression(expr, Context)); } args = values.ToArray(); } return(func.Call(args)); }
static LuaArguments EvalGenericFor(GenericFor stat, LuaContext Context, out LuaReturnStatus returned) { returned.broke = false; returned.returned = false; LuaArguments args = null; foreach (IExpression expr in stat.Expressions) { if (args == null) { args = EvalExpression(expr, Context); } else { args.Concat(EvalExpression(expr, Context)); } } LuaObject f = args[0], s = args[1], var = args[2]; LuaContext ctx = new LuaContext(Context); while (true) { LuaArguments res = f.Call(s, var); for (int i = 0; i < stat.Variables.Count; i++) { ctx.SetLocal(stat.Variables[i], res[i]); } if (res[0].IsNil) { break; } var = res[0]; LuaArguments obj = EvalBlock(stat.Block, ctx, out returned); if (returned.broke) { break; } if (returned.returned) { return(obj); } } return(Lua.Return()); }
LuaArguments rawlen(LuaArguments args) { LuaObject obj = args[0]; if (obj.IsString) { return(Return(obj.AsString().Length)); } else if (obj.IsTable) { return(Return(obj.AsTable().Count)); } else { throw new LuaException("invalid argument"); } }
static LuaArguments io_type(LuaArguments args) { var obj = args[0]; if (isStream(obj)) { FileObject fobj = obj.luaobj as FileObject; if (!fobj.stream.CanWrite && !fobj.stream.CanRead) { return(Lua.Return("closed file")); } else { return(Lua.Return("file")); } } return(Lua.Return()); }
LuaArguments assert(LuaArguments args) { if (args.Length > 0) { if (args[0].AsBool() == false) { if (args.Length == 1) { throw new LuaException("Assertion failed"); } else { throw new LuaException(args[1].ToString()); } } } return(Return()); }
static LuaObject EvalTableConstructor(TableConstructor tctor, LuaContext Context) { Dictionary <LuaObject, LuaObject> table = new Dictionary <LuaObject, LuaObject>(); int i = 0; foreach (KeyValuePair <IExpression, IExpression> pair in tctor.Values) { if (i == tctor.Values.Count - 1 && (pair.Value is FunctionCall || pair.Value is VarargsLiteral)) // This is the last element, and this is a function call or varargs, thus we will add // every return value to the table { LuaObject key = EvalExpression(pair.Key, Context)[0]; if (key.IsNumber) { LuaArguments values = EvalExpression(pair.Value, Context); double k = key; foreach (LuaObject v in values) { table.Add(k, v); k++; } } else { LuaObject value = EvalExpression(pair.Value, Context)[0]; table.Add(key, value); } } else { LuaObject key = EvalExpression(pair.Key, Context)[0]; LuaObject value = EvalExpression(pair.Value, Context)[0]; table.Add(key, value); } i++; } return(LuaObject.FromTable(table)); }
internal static LuaArguments call_event(LuaObject func, LuaArguments args) { if (func.IsFunction) { return(func.AsFunction()(args)); } else { var handler = getMetamethod(func, "__call"); if (handler.IsFunction) { var argslist = new List <LuaObject>(); argslist.Add(func); argslist.AddRange(args); return(handler.AsFunction()(argslist.ToArray())); } else { throw new LuaException("Cannot call nonfunction"); } } }
static LuaArguments io_open(LuaArguments args) { var file = args[0]; var mode = args[1]; if (file.IsString) { FileMode fmode = FileMode.Open; FileAccess faccess = FileAccess.Read; if (mode.IsString) { switch (mode.ToString()) { case "r": faccess = FileAccess.Read; break; case "w": fmode = FileMode.Create; faccess = FileAccess.ReadWrite; break; case "a": fmode = FileMode.Append; faccess = FileAccess.Write; break; case "r+": case "w+": case "a+": // TODO: Implement rwa+ throw new NotImplementedException(); } } FileStream stream = new FileStream(file.ToString(), fmode, faccess); return(Lua.Return(CreateFileObject(stream))); } else { return(Lua.Return()); } }
static LuaArguments io_input(LuaArguments args) { var obj = args[0]; if (isStream(obj)) { currentInput = obj; return(Lua.Return(currentInput)); } else if (obj.IsString) { currentInput = io_open(args)[0]; return(Lua.Return(currentInput)); } else if (args.Length == 0) { return(Lua.Return(currentInput)); } else { throw new LuaException("Invalid argument"); } }
static LuaArguments seek(LuaArguments args) { var obj = args[0]; var whence = args[1] | "cur"; var offset = args[2] | 0; if (isStream(obj)) { var fobj = obj.luaobj as FileObject; switch (whence.ToString()) { case "cur": fobj.stream.Position += (long)offset; break; case "set": fobj.stream.Position = (long)offset; break; case "end": fobj.stream.Position = fobj.stream.Length + (long)offset; break; } return(Lua.Return(fobj.stream.Position)); } return(Lua.Return()); }