public MondValue Call(MondValue closure, params MondValue[] arguments) { if (closure.Type != MondValueType.Closure) throw new MondRuntimeException("Attempt to call non-closure"); var closureValue = closure.ClosureValue; if (closureValue.Type == ClosureType.Mond) { var argFrame = closureValue.Arguments; if (argFrame == null) argFrame = new Frame(0, null, arguments.Length); else argFrame = new Frame(argFrame.Depth + 1, argFrame, arguments.Length); for (var i = 0; i < arguments.Length; i++) { argFrame.Values[i] = arguments[i]; } _callStack.Push(new ReturnAddress(closureValue.ProgramId, closureValue.Address, argFrame)); if (closureValue.Locals != null) _localStack.Push(closureValue.Locals); } else { throw new NotSupportedException(); } return Run(); }
static ArrayPrototype() { Value = new MondValue(MondValueType.Object); Value["prototype"] = ObjectPrototype.Value; Value["length"] = new MondInstanceFunction(Length); }
public void Creation() { var empty = Script.Run(@" return []; "); Assert.AreEqual(empty.Type, MondValueType.Array); Assert.True(empty.Array.SequenceEqual(Enumerable.Empty<MondValue>())); var array = Script.Run(@" var a = 'test'; return [ 1, a, 3, 4 ]; "); var expected = new MondValue[] { 1, "test", 3, 4 }; Assert.AreEqual(array.Type, MondValueType.Array); Assert.True(array.Array.SequenceEqual(expected)); array = Script.Run(@" return [ 1, 2, 3, ]; "); expected = new MondValue[] { 1, 2, 3 }; Assert.AreEqual(array.Type, MondValueType.Array); Assert.True(array.Array.SequenceEqual(expected)); }
static StringPrototype() { Value = MondPrototypeBinder.Bind(typeof(StringPrototype)); Value.Prototype = ValuePrototype.Value; Value.Lock(); }
private static MondValue Length(MondState state, MondValue instance, params MondValue[] arguments) { if (instance.Type != MondValueType.Array) throw new MondRuntimeException("Array.length must be called on a String"); return instance.ArrayValue.Count; }
public void Register(MondState state, MondValue function) { if (function.Type != MondValueType.Function) throw new MondRuntimeException("register: first argument must be a function"); CancellationToken.Register(() => state.Call(function)); }
public static bool MatchTypes( MondValue[] values, Type[] types ) { if( values.Length != types.Length ) return false; return values.Zip( types, ( a, b ) => new { Value = a, Type = b } ).All( x => MatchType( x.Value, x.Type ) ); }
public void Add() { _result = Script.Run(@" var a = 100, b = 10; return a + b; "); Assert.True(_result == 110); _result = Script.Run(@" var a = 'test', b = 10; return a + b; "); Assert.True(_result == "test10"); Assert.Throws<MondRuntimeException>(() => Script.Run(@" var a = null, b = 10; return a + b; ")); Assert.Throws<MondCompilerException>(() => Script.Run(@" return 1 += 2; ")); }
static ObjectPrototype() { Value = MondPrototypeBinder.Bind(typeof(ObjectPrototype)); Value.Prototype = ValuePrototype.Value; Value.Lock(); }
public void FizzBuzz() { MondState state; var result = Script.Run(out state, @" seq fizzBuzz() { var n = 1; while (true) { if (n % 15 == 0) yield 'FizzBuzz'; else if (n % 3 == 0) yield 'Fizz'; else if (n % 5 == 0) yield 'Buzz'; else yield '' + n; n++; } } return fizzBuzz(); "); var expected = new MondValue[] { "1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz" }; Assert.True(result.IsEnumerable); Assert.True(result.Enumerate(state).Take(expected.Length).SequenceEqual(expected)); }
public Object() { Values = new Dictionary<MondValue, MondValue>(); Locked = false; Prototype = null; UserData = null; ThisEnabled = false; }
public MondValue Load(MondProgram program) { if (program == null) throw new ArgumentNullException("program"); var function = new MondValue(new Closure(program, 0, null, null)); return Call(function); }
public static string Serialize(MondValue value) { var sb = new StringBuilder(); SerializeImpl(value, sb, 0); return sb.ToString(); }
public static MondValue JsonWatch(Watch watch) { var obj = new MondValue(MondValueType.Object); obj["Id"] = watch.Id; obj["Expression"] = watch.Expression; obj["Value"] = watch.Value; return obj; }
public void BitNot() { _result = Script.Run(@" var a = 100; return ~a; "); Assert.True(_result == -101); }
public static void Add([MondInstance] MondValue instance, MondValue key, MondValue value) { EnsureObject("add", instance); if (instance.ObjectValue.Locked) throw new MondRuntimeException(LockedError, "add"); instance.ObjectValue.Values[key] = value; }
static ValuePrototype() { Value = MondPrototypeBinder.Bind(typeof(ValuePrototype)); // we dont use MondValue.Prototype here because this should not have a prototype Value.ObjectValue.Prototype = MondValue.Undefined; Value.Lock(); }
public static MondValue JsonProgram(ProgramInfo program) { var obj = new MondValue(MondValueType.Object); obj["FileName"] = program.FileName; obj["SourceCode"] = program.DebugInfo.SourceCode; obj["FirstLine"] = FirstLineNumber(program.DebugInfo); obj["Breakpoints"] = new MondValue(program.Breakpoints.Select(e => new MondValue(e))); return obj; }
public static MondValue JsonCallStackEntry(MondDebugContext.CallStackEntry callStackEntry) { var obj = new MondValue(MondValueType.Object); obj["FileName"] = callStackEntry.FileName; obj["Function"] = callStackEntry.Function; obj["LineNumber"] = callStackEntry.LineNumber; obj["ColumnNumber"] = callStackEntry.ColumnNumber; return obj; }
public MondValue Get( MondState state, MondValue instance, string name ) { var newPath = _path + "." + name; var type = InteropLibrary.LookupType( newPath ); if( type != null ) return MondObjectBinder.Bind( type, state, MondBindingOptions.AutoLock ); return new NamespaceReference( newPath ).ToMond( state ); }
public static bool MatchType( MondValue value, Type type ) { if( type == typeof( char ) ) return value.Type == MondValueType.String && value.ToString().Length == 1; if( value.Type == MondValueType.Object ) return value.UserData != null && type.IsAssignableFrom( value.UserData.GetType() ); return MatchType( value.Type, type ); }
public MondValue Get( MondState state, MondValue instance, string name ) { var typeName = this.Type.FullName + "+" + name; var type = InteropLibrary.LookupType( typeName ); if( type == null ) throw new Exception( "Could not find type: " + typeName ); return MondObjectBinder.Bind( type, state, MondBindingOptions.AutoLock ); }
public MondValue Load(MondProgram program) { if (program == null) throw new ArgumentNullException("program"); var programId = _programs.Count; _programs.Add(program); var closure = new MondValue(new Closure(programId, 0, null, null)); return Call(closure); }
public Machine(MondState state) { _state = state; _programs = new List<MondProgram>(); _callStack = new Stack<ReturnAddress>(); _localStack = new Stack<Frame>(); _evalStack = new Stack<MondValue>(); Global = new MondValue(MondValueType.Object); }
public MondValue Call( MondState state, MondValue instance, params MondValue[] args ) { var types = InteropLibrary.GetTypeArray( args ); var typeName = _path + "`" + types.Length; var type = InteropLibrary.LookupType( typeName ); if( type == null ) throw new Exception( "Could not find type: " + typeName ); var boundType = type.MakeGenericType( types ); return MondObjectBinder.Bind( boundType, state, MondBindingOptions.AutoLock ); }
public MondValue ToMond( MondState state ) { MondValue prototype; MondClassBinder.Bind<NamespaceReference>( out prototype, state ); var obj = new MondValue( state ); obj.UserData = this; obj.Prototype = prototype; obj.Lock(); return obj; }
public void ArrayIndexer() { var array = new MondValue(MondValueType.Array); array.ArrayValue.Add("test"); array.ArrayValue.Add(123); Assert.True(array[0] == "test"); Assert.True(array[1] == 123); Assert.Throws<MondRuntimeException>(() => { var a = array[2]; }); }
public Machine(MondState state) : this() { _state = state; Global = new MondValue(state); Global["__ops"] = new MondValue(state); _debugAction = MondDebugAction.Run; _debugSkip = false; _debugAlign = false; _debugDepth = 0; Debugger = null; }
public void BasicArrayDestructuring() { var result = Script.Run(@" var array = [ 1, 2, 3, 4, 5 ]; var [ a, b ] = array; var [ y, x ] = array[4:0]; return [ a, b, x, y ]; "); var expected = new MondValue[] { 1, 2, 4, 5 }; Assert.True(result.Array.SequenceEqual(expected)); }
public void BitOr() { _result = Script.Run(@" var a = 2, b = 4; return a | b; "); Assert.True(_result == 6); Assert.Throws<MondRuntimeException>(() => Script.Run(@" var a = 'test', b = 4; return a | b; ")); }
public void SliceRange() { var expected = new MondValue[] { 2, 3 }; CollectionAssert.AreEqual(expected, _sliceState.Run("return global.arr[1:2];").AsList); }
public static bool Contains([MondInstance] MondValue instance, MondValue item) { EnsureArray("contains", instance); return(instance.ArrayValue.Contains(item)); }
public void SliceAllValues() { var expected = new MondValue[] { 1, 3, 5 }; CollectionAssert.AreEqual(expected, _sliceState.Run("return global.arr[0:4:2];").AsList); }
public static int Length([MondInstance] MondValue instance) { EnsureArray("length", instance); return(instance.ArrayValue.Count); }
/// <summary> /// endsWith(value: string): bool /// </summary> private static MondValue EndsWith(MondState state, MondValue instance, params MondValue[] arguments) { Check("endsWith", instance.Type, arguments, MondValueType.String); return(((string)instance).EndsWith(arguments[0])); }
public int Visit(StringExpression expression) { MondValue.String(expression.Value).Serialize(_writer); return(0); }
public static MondValue ConditionalOr(MondValue x, MondValue y) => x || y;
/// <summary> /// trim(): string /// </summary> private static MondValue Trim(MondState state, MondValue instance, params MondValue[] arguments) { Check("trim", instance.Type, arguments); return(((string)instance).Trim()); }
public static int LastIndexOf([MondInstance] MondValue instance, MondValue item) { EnsureArray("lastIndexOf", instance); return(instance.ArrayValue.LastIndexOf(item)); }
static void MessageReceived(object peerObj) { NetPeer peer = (NetPeer)peerObj; NetIncomingMessage inc = peer.ReadMessage(); NetOutgoingMessage outMsg = client.CreateMessage(); switch (inc.MessageType) { case NetIncomingMessageType.DebugMessage: case NetIncomingMessageType.VerboseDebugMessage: case NetIncomingMessageType.WarningMessage: case NetIncomingMessageType.ErrorMessage: Console.WriteLine("Lidgren: {0}", inc.ReadString()); return; case NetIncomingMessageType.Data: //Console.WriteLine("Message received"); string command = inc.ReadString(); if (command == "prgm") { outMsg.Write("result"); List <MondValue> args = new List <MondValue>(); int argCount = inc.ReadInt32(); if (argCount > 0) { for (var i = 0; i < argCount; i++) { string argType = inc.ReadString(); Console.WriteLine(argType); switch (argType) { case "Int32": args.Add(new MondValue(inc.ReadInt32())); break; case "String": args.Add(new MondValue(inc.ReadString())); break; case "Boolean": args.Add(new MondValue(inc.ReadBoolean() ? 1 : 0)); break; default: Console.WriteLine("Invalid argument type: {0}", argType); break; } } } string prgm = inc.ReadString(); string file = inc.ReadString(); Console.WriteLine("Program received. Args: {0}", argCount); MondValue func = null; try { func = mondState.Run(prgm, file); } catch (MondCompilerException ex) { Console.WriteLine("MondCompilerException: {0}", ex.Message); if (ex.InnerException != null) { Console.WriteLine("Inner ({0}): {1}", ex.GetType().Name, ex.InnerException.Message); } outMsg.Write("error"); outMsg.Write(ex.Message); client.SendMessage(outMsg, NetDeliveryMethod.ReliableOrdered); break; } if (func.Type != MondValueType.Function) { Console.WriteLine("Invalid return type: {0} ({1})", func.Type, func.Serialize()); outMsg.Write("error"); outMsg.Write("wrong return type; expected function"); client.SendMessage(outMsg, NetDeliveryMethod.ReliableOrdered); break; } string result; string type; try { MondValue res = mondState.Call(func, args.ToArray()); result = res.Serialize(); type = res.Type.GetName(); //Console.WriteLine(type); } catch (MondRuntimeException ex) { Console.WriteLine("MondRuntimeException: {0}", ex.Message); if (ex.InnerException != null) { Console.WriteLine("Inner ({0}): {1}", ex.GetType().Name, ex.InnerException.Message); } outMsg.Write("error"); outMsg.Write(ex.Message); client.SendMessage(outMsg, NetDeliveryMethod.ReliableOrdered); break; } Console.WriteLine("Done. Result: {0}", result); outMsg.Write(result); outMsg.Write(type); client.SendMessage(outMsg, NetDeliveryMethod.ReliableOrdered); } break; //case NetIncomingMessageType.DiscoveryRequest: // Console.WriteLine("Discovery request from {0}", inc.SenderEndPoint.ToString()); // outMsg = client.CreateMessage("slave"); // outMsg.Write(name); // client.SendDiscoveryResponse(outMsg, inc.SenderEndPoint); // break; case NetIncomingMessageType.DiscoveryResponse: string peerName = inc.ReadString(); if (peerName == "master") { Console.WriteLine("Found master at {0}", inc.SenderEndPoint); outMsg.Write("slave"); outMsg.Write(name); client.Connect(inc.SenderEndPoint, outMsg); } break; case NetIncomingMessageType.StatusChanged: Console.WriteLine("Status of {0}: {1}", inc.SenderEndPoint.ToString(), ((NetConnectionStatus)inc.ReadByte()).ToString()); string addit = inc.ReadString(); if (!String.IsNullOrEmpty(addit)) { Console.WriteLine("Addit: {0}", addit); } break; } }
public static bool ContainsKey([MondInstance] MondValue instance, MondValue key) { EnsureObject("containsKey", instance); return(instance.ObjectValue.Values.ContainsKey(key)); }
/// <summary> /// length(): number /// </summary> private static MondValue Length(MondState state, MondValue instance, params MondValue[] arguments) { Check("length", instance.Type, arguments); return(((string)instance).Length); }
public static MondValue Dot(MondValue x, MondValue y) => x[y];
/// <summary> /// indexOf(value: string): number /// </summary> private static MondValue IndexOf(MondState state, MondValue instance, params MondValue[] arguments) { Check("indexOf", instance.Type, arguments, MondValueType.String); return(((string)instance).IndexOf(arguments[0])); }
public void SliceOnlyStep() { var expected = new MondValue[] { 5, 4, 3, 2, 1 }; CollectionAssert.AreEqual(expected, _sliceState.Run("return global.arr[::-1];").AsList); }
public static void SortDescending([MondInstance] MondValue instance) => SortImpl("sortDescending", instance, 0, instance.ArrayValue.Count, true);
public void SliceOnlyBegin() { var expected = new MondValue[] { 4, 5 }; CollectionAssert.AreEqual(expected, _sliceState.Run("return global.arr[3:];").AsList); }
public static void Sort([MondInstance] MondValue instance, int index, int count) => SortImpl("sort", instance, index, count, false);
public void ChangeInstance([MondInstance] MondValue instance) { instance["test"] = 100; }
public static void Sort([MondInstance] MondValue instance) => SortImpl("sort", instance, 0, instance.ArrayValue.Count, false);
public static void SortDescending([MondInstance] MondValue instance, int index, int count) => SortImpl("sortDescending", instance, index, count, true);
public static object MarshalToClr( MondValue value, Type expectedType, MondState state, MondBindingOptions options) { if (!TypeConverter.MatchType(value, expectedType)) { throw new ArgumentException("Given value does not match expected type", nameof(value)); } if (expectedType == typeof(MondValue)) { return(value); } // ReSharper disable once SwitchStatementMissingSomeCases switch (value.Type) { case MondValueType.False: case MondValueType.True: return((bool)value); case MondValueType.Null: case MondValueType.Undefined: if (!expectedType.GetTypeInfo().IsValueType) { return(null); } if (expectedType.IsConstructedGenericType && (expectedType.GetGenericTypeDefinition() == typeof(Nullable <>))) { return(Activator.CreateInstance(expectedType)); } throw new InvalidOperationException( $"Cannot bind {value.Type.GetName()} value to " + $"{expectedType.FullName} because it is a value type"); case MondValueType.String: var str = value.ToString(); if (expectedType != typeof(char)) { return(str); } if (str.Length != 1) { throw new ArgumentException("Value cannot be converted to char", nameof(value)); } return(str[0]); case MondValueType.Number: if (expectedType.IsConstructedGenericType && (expectedType.GetGenericTypeDefinition() == typeof(Nullable <>))) { var innerType = expectedType.GetGenericArguments()[0]; var converted = Convert.ChangeType((double)value, innerType); return(Activator.CreateInstance(expectedType, converted)); } if (!expectedType.GetTypeInfo().IsEnum) { return(Convert.ChangeType((double)value, expectedType)); } var underlying = Enum.GetUnderlyingType(expectedType); var rawValue = Convert.ChangeType((double)value, underlying); var valueName = Enum.GetName(expectedType, rawValue); // ReSharper disable once AssignNullToNotNullAttribute return(Enum.Parse(expectedType, valueName)); case MondValueType.Object: return(value.UserData); case MondValueType.Function: object Shim(object[] args) { MondValue result; if ((args == null) || (args.Length == 0)) { result = state.Call(value); } else { var mondTypes = TypeConverter.ToMondTypes( args.Select(a => a.GetType()).ToArray()); var mondValues = TypeConverter.MarshalToMond(args, mondTypes, state, options); result = state.Call(value, mondValues); } if ((result.Type == MondValueType.Null) || (result.Type == MondValueType.Undefined)) { return(null); } var clrType = TypeConverter.ToClrType(result); return(TypeConverter.MarshalToClr(result, clrType, state, options)); } if (!typeof(Delegate).IsAssignableFrom(expectedType)) { return((Func <object[], object>)Shim); } var invoke = expectedType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance); var parameters = invoke.GetParameters().Select(p => p.ParameterType).ToArray(); var delegateType = invoke.ReturnType == typeof(void) ? Expression.GetActionType(parameters) : Expression.GetFuncType(parameters.Concat(invoke.ReturnType).ToArray()); var shim = (Func <object[], object>)Shim; var paramsExpr = parameters.Select(Expression.Parameter).ToArray(); // ReSharper disable once CoVariantArrayConversion var paramsArr = Expression.NewArrayInit(typeof(object), paramsExpr); var invokeExpr = Expression.Call( Expression.Constant(shim.Target), shim.GetMethodInfo(), paramsArr); // ReSharper disable once TooWideLocalVariableScope BlockExpression body; if (invoke.ReturnType == typeof(void)) { body = Expression.Block(invokeExpr); } else { var castExpr = Expression.Convert(invokeExpr, invoke.ReturnType); body = Expression.Block(castExpr); } var method = typeof(Expression) .GetMethods(BindingFlags.Public | BindingFlags.Static) .Where(m => m.Name == "Lambda") .First(m => m.IsGenericMethodDefinition); var lambda = method.MakeGenericMethod(delegateType); return(((LambdaExpression)lambda.Invoke(null, new object[] { body, paramsExpr })).Compile()); default: TypeConverter.UnsupportedMondTypeError(value.Type); break; } return(null); // we should never get here }
public static void Clear([MondInstance] MondValue instance) { EnsureArray("clear", instance); instance.ArrayValue.Clear(); }
public static MondValue ConditionalAnd(MondValue x, MondValue y) => x && y;
public MondValue Require(MondState state, string fileName) { if (_require.Resolver == null) { throw new MondRuntimeException("require: module resolver is not set"); } if (_require.Loader == null) { throw new MondRuntimeException("require: module loader is not set"); } const string cacheObjectName = "__modules"; MondValue cacheObject; // make sure we have somewhere to cache modules if (state[cacheObjectName].Type != MondValueType.Object) { cacheObject = MondValue.Object(state); cacheObject.Prototype = MondValue.Null; state[cacheObjectName] = cacheObject; } else { cacheObject = state[cacheObjectName]; } // gather search directories IEnumerable <string> searchDirectories = _require.SearchDirectories ?? Array.Empty <string>(); if (_require.SearchBesideScript) { var currentDir = Path.GetDirectoryName(state.CurrentScript); searchDirectories = Enumerable.Repeat(currentDir, 1) .Concat(searchDirectories); } // resolve the module name so we have a consistent caching key var resovledName = _require.Resolver(fileName, searchDirectories); // return cached module if it exists var cachedExports = cacheObject[resovledName]; if (cachedExports.Type == MondValueType.Object) { return(cachedExports); } // create a new object to store the exports var exports = MondValue.Object(state); exports.Prototype = MondValue.Null; // instantly cache it so we can have circular dependencies cacheObject[resovledName] = exports; try { var moduleSource = _require.Loader(resovledName); // wrap the module script in a function so we can pass out exports object to it var source = _require.Definitions + "return fun (exports) {\n" + moduleSource + "\n return exports; };"; var options = new MondCompilerOptions { FirstLineNumber = -1 }; var requireOptions = _require.Options; if (requireOptions != null) { options.DebugInfo = requireOptions.DebugInfo; options.MakeRootDeclarationsGlobal = requireOptions.MakeRootDeclarationsGlobal; options.UseImplicitGlobals = requireOptions.UseImplicitGlobals; } var program = MondProgram.Compile(source, resovledName, options); var initializer = state.Load(program); var result = state.Call(initializer, exports); if (result.Type != MondValueType.Object) { throw new MondRuntimeException("require: module must return an object (`{0}`)", fileName); } if (!ReferenceEquals(exports.AsDictionary, result.AsDictionary)) { // module returned a different object, merge with ours foreach (var kv in result.AsDictionary) { var key = kv.Key; var value = kv.Value; exports[key] = value; } exports.Prototype = result.Prototype; if (result.IsLocked) { exports.Lock(); } } } catch { // if something goes wrong, remove the entry from the cache cacheObject[resovledName] = MondValue.Undefined; throw; } return(exports); }
public static MondValue Remove([MondInstance] MondValue instance, MondValue item) { EnsureArray("remove", instance); return(instance.ArrayValue.Remove(item)); }
public static int Length([MondInstance] MondValue instance) { EnsureObject("length", instance); return(instance.ObjectValue.Values.Count); }
public static MondValue SetPrototypeAndLock([MondInstance] MondValue instance, MondValue value) { EnsureObject("setPrototypeAndLock", instance); SetPrototype(instance, value); Lock(instance); return(instance); }
/// <summary> /// contains(value: string): bool /// </summary> private static MondValue Contains(MondState state, MondValue instance, params MondValue[] arguments) { Check("contains", instance.Type, arguments, MondValueType.String); return(((string)instance).Contains(arguments[0])); }
public static void Add([MondInstance] MondValue instance, MondValue item) { EnsureArray("add", instance); instance.ArrayValue.Add(item); }