public void OnOpen(WebSocket socket) { _socket = socket; _socket.DataReceived += OnMessage; _debugger.GetState( out var isRunning, out var programs, out var position, out var watches, out var callStack); var message = MondValue.Object(); message["Type"] = "InitialState"; message["Programs"] = MondValue.Array(programs.Select(Utility.JsonProgram)); message["Running"] = isRunning; message["Id"] = position.Id; message["StartLine"] = position.StartLine; message["StartColumn"] = position.StartColumn; message["EndLine"] = position.EndLine; message["EndColumn"] = position.EndColumn; message["Watches"] = MondValue.Array(watches.Select(Utility.JsonWatch)); if (callStack != null) { message["CallStack"] = _debugger.BuildCallStackArray(callStack); } Send(Json.Serialize(message)); }
public MondValue Serialize(MondState state, params MondValue[] args) { var result = MondValue.Object(state); result["$ctor"] = "Regex"; result["$args"] = MondValue.Array(new MondValue[] { _pattern, _ignoreCase, _multiline }); return(result); }
public MondValue Serialize(MondState state, params MondValue[] args) { var result = MondValue.Object(state); result["$ctor"] = "Color"; result["$args"] = MondValue.Array(new MondValue[] { Red, Green, Blue, Alpha }); return(result); }
public ArrayTests() { var arr = MondValue.Array(); arr.ArrayValue.AddRange(new MondValue[] { 1, 2, 3, 4, 5 }); _sliceState = new MondState { ["arr"] = arr }; }
public static MondValue JsonProgram(ProgramInfo program) { var obj = MondValue.Object(); obj["FileName"] = program.FileName; obj["SourceCode"] = program.DebugInfo.SourceCode; obj["FirstLine"] = FirstLineNumber(program.DebugInfo); obj["Breakpoints"] = MondValue.Array(program.Breakpoints.Select(e => MondValue.Number(e))); return(obj); }
private static MondValue ToMond(MatchCollection matchCollection) { var value = MondValue.Array(); foreach (Match m in matchCollection) { value.AsList.Add(ToMond(m)); } return(value); }
public void ArrayIndexer() { var array = MondValue.Array(); array.AsList.Add("test"); array.AsList.Add(123); Assert.True(array[0] == "test"); Assert.True(array[1] == 123); Assert.Throws <MondRuntimeException>(() => { var a = array[2]; }); }
internal MondValue BuildCallStackArray(ReadOnlyCollection <MondDebugContext.CallStackEntry> entries) { var objs = new List <MondValue>(entries.Count); foreach (var entry in entries) { VisitProgram(entry.Program); var programId = FindProgramIndex(entry.Program); objs.Add(Utility.JsonCallStackEntry(programId, entry)); } return(MondValue.Array(objs)); }
public static MondValue WhenAll(MondState state, params MondValue[] tasks) { AsyncUtil.EnsureAsync(); var taskArray = AsyncUtil.ToTaskArray(state, tasks); var task = Task.WhenAll(taskArray).ContinueWith(t => { var array = MondValue.Array(); array.ArrayValue.AddRange(t.Result); return(array); }); return(AsyncUtil.ToObject(task)); }
public static MondValue JsonValueProperties(MondValue value) { switch (value.Type) { case MondValueType.Object: var objProperties = value.AsDictionary .Where(kvp => IsPrimitive(kvp.Key)) .Select(kvp => JsonValueProperty(kvp.Key, kvp.Value)); return(MondValue.Array(objProperties)); case MondValueType.Array: var arrayProperties = value.AsList .Select((v, i) => JsonValueProperty(i, v)); return(MondValue.Array(arrayProperties)); default: return(MondValue.Array()); } }
private MondValue ParseArray() { var arr = MondValue.Array(); if (Match(TokenType.ArrayEnd)) { Take(); return(arr); } arr.AsList.Add(ParseValue()); while (!Match(TokenType.ArrayEnd)) { Require(TokenType.Comma); arr.AsList.Add(ParseValue()); } Require(TokenType.ArrayEnd); return(arr); }
public void Slice() { var state = new MondState(); var arr = MondValue.Array(); var str = MondValue.String("HelloWorld"); arr.ArrayValue.AddRange(new MondValue[] { 1, 2, 3, 4, 5 }); Assert.True(str.Slice(1, 3, 1).Equals(MondValue.String("ell"))); Assert.True(arr.Slice().Enumerate(state).SequenceEqual(arr.Enumerate(state)), "clone"); Assert.True(arr.Slice(step: -1).Enumerate(state).SequenceEqual(new MondValue[] { 5, 4, 3, 2, 1 }), "reverse"); Assert.True(arr.Slice(1, 3).Enumerate(state).SequenceEqual(new MondValue[] { 2, 3, 4 }), "range"); Assert.True(arr.Slice(3, 1).Enumerate(state).SequenceEqual(new MondValue[] { 4, 3, 2 }), "reverse range"); Assert.True(arr.Slice(0, 0).Enumerate(state).SequenceEqual(new MondValue[] { 1 }), "same start and end"); Assert.True(arr.Slice(-4, -2).Enumerate(state).SequenceEqual(new MondValue[] { 2, 3, 4 }), "negative range"); Assert.True(arr.Slice(-2, -4).Enumerate(state).SequenceEqual(new MondValue[] { 4, 3, 2 }), "negative range reverse"); Assert.True(arr.Slice(step: 2).Enumerate(state).SequenceEqual(new MondValue[] { 1, 3, 5 }), "skip"); Assert.True(arr.Slice(step: -2).Enumerate(state).SequenceEqual(new MondValue[] { 5, 3, 1 }), "skip negative"); Assert.Throws <MondRuntimeException>(() => arr.Slice(-6, 0, "out of bounds 1")); Assert.Throws <MondRuntimeException>(() => arr.Slice(0, 5, "out of bounds 2")); Assert.Throws <MondRuntimeException>(() => arr.Slice(step: 0), "invalid step"); Assert.Throws <MondRuntimeException>(() => arr.Slice(4, 0, 1), "invalid range"); Assert.Throws <MondRuntimeException>(() => arr.Slice(0, 4, -1), "invalid range negative"); Assert.Throws <MondRuntimeException>(() => MondValue.Undefined.Slice(), "slice non-array"); var empty = MondValue.Array(); Assert.True(!empty.Slice().Enumerate(state).Any(), "clone empty"); }
private void VisitProgram(MondProgram program) { var debugInfo = program.DebugInfo; if (IsMissingDebugInfo(debugInfo)) { return; } int id; ProgramInfo programInfo; lock (_sync) { if (_seenPrograms.Contains(program)) { return; } _seenPrograms.Add(program); id = _programs.Count; programInfo = new ProgramInfo(program); _programs.Add(programInfo); } var message = MondValue.Object(); message["Type"] = "NewProgram"; message["Id"] = id; message["FileName"] = programInfo.FileName; message["SourceCode"] = debugInfo.SourceCode; message["FirstLine"] = Utility.FirstLineNumber(debugInfo); message["Breakpoints"] = MondValue.Array(programInfo.Breakpoints.Select(e => MondValue.Number(e))); Broadcast(message); }
public void Contains() { var arr = MondValue.Array(); arr.ArrayValue.AddRange(new MondValue[] { 1, 2, 3, 4, 5 }); Assert.True(arr.Contains(3)); Assert.False(arr.Contains(10)); var str = MondValue.String("hello world"); Assert.True(str.Contains("hello")); Assert.False(str.Contains("asdf")); var obj = MondValue.Object(new MondState()); obj["__in"] = new MondFunction((state, args) => args[1].Type == MondValueType.Number); Assert.True(obj.Contains(3)); Assert.False(obj.Contains("hello")); Assert.Throws <MondRuntimeException>(() => MondValue.False.Contains(0)); }
public void ImplicitBool() { var value = MondValue.Undefined; Assert.False(value); value = MondValue.Null; Assert.False(value); value = MondValue.False; Assert.False(value); value = MondValue.True; Assert.True(value); value = 0; Assert.True(value); value = 1; Assert.True(value); value = double.NaN; Assert.False(value); value = "hello"; Assert.True(value); value = MondValue.Object(); Assert.True(value); value = MondValue.Array(); Assert.True(value); value = MondValue.Function((state, arguments) => MondValue.Undefined); Assert.True(value); }
private MondValue Run() { var functionAddress = PeekCall(); var program = functionAddress.Program; var code = program.Bytecode; var initialCallDepth = _callStackSize - 1; // "- 1" to not include values pushed by Call() var initialLocalDepth = _localStackSize - 1; var initialEvalDepth = _evalStackSize; var ip = functionAddress.Address; var errorIp = 0; var args = functionAddress.Arguments; Frame locals = null; try { while (true) { if (Debugger != null) { var skip = _debugSkip; _debugSkip = false; var shouldStopAtStmt = (_debugAction == MondDebugAction.StepInto) || (_debugAction == MondDebugAction.StepOver && _debugDepth == 0); var shouldBreak = (_debugAlign && program.DebugInfo == null) || (_debugAlign && program.DebugInfo.IsStatementStart(ip)) || (Debugger.ShouldBreak(program, ip)) || (shouldStopAtStmt && program.DebugInfo != null && program.DebugInfo.IsStatementStart(ip)); if (!skip && shouldBreak) { DebuggerBreak(program, locals, args, ip, initialCallDepth); } } errorIp = ip; switch (code[ip++]) { #region Stack Manipulation case (int)InstructionType.Dup: { Push(Peek()); break; } case (int)InstructionType.Dup2: { var value2 = Pop(); var value1 = Pop(); Push(value1); Push(value2); Push(value1); Push(value2); break; } case (int)InstructionType.Drop: { Pop(); break; } case (int)InstructionType.Swap: { var value1 = Pop(); var value2 = Pop(); Push(value1); Push(value2); break; } case (int)InstructionType.Swap1For2: { var one = Pop(); var two2 = Pop(); var two1 = Pop(); Push(one); Push(two1); Push(two2); break; } #endregion #region Constants case (int)InstructionType.LdUndef: { Push(MondValue.Undefined); break; } case (int)InstructionType.LdNull: { Push(MondValue.Null); break; } case (int)InstructionType.LdTrue: { Push(MondValue.True); break; } case (int)InstructionType.LdFalse: { Push(MondValue.False); break; } case (int)InstructionType.LdNum: { var numId = ReadInt32(code, ref ip); Push(program.Numbers[numId]); break; } case (int)InstructionType.LdStr: { var strId = ReadInt32(code, ref ip); Push(program.Strings[strId]); break; } case (int)InstructionType.LdGlobal: { Push(Global); break; } #endregion #region Storables case (int)InstructionType.LdLocF: { var index = ReadInt32(code, ref ip); Push(locals.Values[index]); break; } case (int)InstructionType.StLocF: { var index = ReadInt32(code, ref ip); locals.Values[index] = Pop(); break; } case (int)InstructionType.LdLoc: { var depth = ReadInt32(code, ref ip); var index = ReadInt32(code, ref ip); if (depth < 0) { Push(args.Get(-depth, index)); } else { Push(locals.Get(depth, index)); } break; } case (int)InstructionType.StLoc: { var depth = ReadInt32(code, ref ip); var index = ReadInt32(code, ref ip); if (depth < 0) { args.Set(-depth, index, Pop()); } else { locals.Set(depth, index, Pop()); } break; } case (int)InstructionType.LdFld: { var obj = Pop(); Push(obj[program.Strings[ReadInt32(code, ref ip)]]); break; } case (int)InstructionType.StFld: { var obj = Pop(); var value = Pop(); obj[program.Strings[ReadInt32(code, ref ip)]] = value; break; } case (int)InstructionType.LdArr: { var index = Pop(); var array = Pop(); Push(array[index]); break; } case (int)InstructionType.StArr: { var index = Pop(); var array = Pop(); var value = Pop(); array[index] = value; break; } case (int)InstructionType.LdState: { var depth = ReadInt32(code, ref ip); var frame = locals.GetFrame(depth); locals = frame.StoredFrame; PopLocal(); PushLocal(locals); var evals = frame.StoredEvals; if (evals != null) { for (var i = evals.Count - 1; i >= 0; i--) { Push(evals[i]); } evals.Clear(); } break; } case (int)InstructionType.StState: { var depth = ReadInt32(code, ref ip); var frame = locals.GetFrame(depth); frame.StoredFrame = locals; var initialEvals = _callStackSize > 0 ? PeekCall().EvalDepth : 0; var currentEvals = _evalStackSize; if (currentEvals != initialEvals) { var evals = frame.StoredEvals ?? (frame.StoredEvals = new List <MondValue>()); while (currentEvals != initialEvals) { evals.Add(Pop()); currentEvals--; } } break; } #endregion #region Object Creation case (int)InstructionType.NewObject: { var obj = MondValue.Object(_state); Push(obj); break; } case (int)InstructionType.NewArray: { var count = ReadInt32(code, ref ip); var array = MondValue.Array(); array.ArrayValue.Capacity = count; for (var i = 0; i < count; i++) { array.ArrayValue.Add(default(MondValue)); } Push(array); break; } case (int)InstructionType.Slice: { var step = Pop(); var end = Pop(); var start = Pop(); var array = Pop(); Push(array.Slice(start, end, step)); break; } #endregion #region Math case (int)InstructionType.Add: { var right = Pop(); var left = Pop(); Push(left + right); break; } case (int)InstructionType.Sub: { var right = Pop(); var left = Pop(); Push(left - right); break; } case (int)InstructionType.Mul: { var right = Pop(); var left = Pop(); Push(left * right); break; } case (int)InstructionType.Div: { var right = Pop(); var left = Pop(); Push(left / right); break; } case (int)InstructionType.Mod: { var right = Pop(); var left = Pop(); Push(left % right); break; } case (int)InstructionType.Exp: { var right = Pop(); var left = Pop(); Push(left.Pow(right)); break; } case (int)InstructionType.BitLShift: { var right = Pop(); var left = Pop(); Push(left.LShift(right)); break; } case (int)InstructionType.BitRShift: { var right = Pop(); var left = Pop(); Push(left.RShift(right)); break; } case (int)InstructionType.BitAnd: { var right = Pop(); var left = Pop(); Push(left & right); break; } case (int)InstructionType.BitOr: { var right = Pop(); var left = Pop(); Push(left | right); break; } case (int)InstructionType.BitXor: { var right = Pop(); var left = Pop(); Push(left ^ right); break; } case (int)InstructionType.Neg: { Push(-Pop()); break; } case (int)InstructionType.BitNot: { Push(~Pop()); break; } #endregion #region Logic case (int)InstructionType.Eq: { var right = Pop(); var left = Pop(); Push(left == right); break; } case (int)InstructionType.Neq: { var right = Pop(); var left = Pop(); Push(left != right); break; } case (int)InstructionType.Gt: { var right = Pop(); var left = Pop(); Push(left > right); break; } case (int)InstructionType.Gte: { var right = Pop(); var left = Pop(); Push(left >= right); break; } case (int)InstructionType.Lt: { var right = Pop(); var left = Pop(); Push(left < right); break; } case (int)InstructionType.Lte: { var right = Pop(); var left = Pop(); Push(left <= right); break; } case (int)InstructionType.Not: { Push(!Pop()); break; } case (int)InstructionType.In: { var right = Pop(); var left = Pop(); Push(right.Contains(left)); break; } case (int)InstructionType.NotIn: { var right = Pop(); var left = Pop(); Push(!right.Contains(left)); break; } #endregion #region Functions case (int)InstructionType.Closure: { var address = ReadInt32(code, ref ip); Push(new MondValue(new Closure(program, address, args, locals))); break; } case (int)InstructionType.Call: { var argCount = ReadInt32(code, ref ip); var unpackCount = code[ip++]; var function = Pop(); List <MondValue> unpackedArgs = null; if (unpackCount > 0) { unpackedArgs = UnpackArgs(code, ref ip, argCount, unpackCount); } var returnAddress = ip; if (function.Type == MondValueType.Object) { MondValue[] argArr; if (unpackedArgs == null) { argArr = new MondValue[argCount + 1]; for (var i = argCount; i >= 1; i--) { argArr[i] = Pop(); } argArr[0] = function; } else { unpackedArgs.Insert(0, function); argArr = unpackedArgs.ToArray(); } if (function.TryDispatch("__call", out var result, argArr)) { Push(result); break; } } if (function.Type != MondValueType.Function) { var ldFldBase = ip - 1 - 4 - 1 - 4 - 1; if (ldFldBase >= 0 && code[ldFldBase] == (int)InstructionType.LdFld) { var ldFldIdx = ldFldBase + 1; var fieldNameIdx = ReadInt32(code, ref ldFldIdx); if (fieldNameIdx >= 0 && fieldNameIdx < program.Strings.Count) { var fieldName = program.Strings[fieldNameIdx]; throw new MondRuntimeException(RuntimeError.FieldNotCallable, (string)fieldName); } } throw new MondRuntimeException(RuntimeError.ValueNotCallable, function.Type.GetName()); } var closure = function.FunctionValue; var argFrame = function.FunctionValue.Arguments; var argFrameCount = unpackedArgs?.Count ?? argCount; if (argFrame == null) { argFrame = new Frame(1, null, argFrameCount); } else { argFrame = new Frame(argFrame.Depth + 1, argFrame, argFrameCount); } // copy arguments into frame if (unpackedArgs == null) { for (var i = argFrameCount - 1; i >= 0; i--) { argFrame.Values[i] = Pop(); } } else { for (var i = 0; i < argFrameCount; i++) { argFrame.Values[i] = unpackedArgs[i]; } } switch (closure.Type) { case ClosureType.Mond: PushCall(new ReturnAddress(program, returnAddress, argFrame, _evalStackSize)); PushLocal(closure.Locals); program = closure.Program; code = program.Bytecode; ip = closure.Address; args = argFrame; locals = closure.Locals; if (Debugger != null) { DebuggerCheckCall(); } break; case ClosureType.Native: var result = closure.NativeFunction(_state, argFrame.Values); Push(result); break; default: throw new MondRuntimeException(RuntimeError.UnhandledClosureType); } break; } case (int)InstructionType.TailCall: { var argCount = ReadInt32(code, ref ip); var address = ReadInt32(code, ref ip); var unpackCount = code[ip++]; List <MondValue> unpackedArgs = null; if (unpackCount > 0) { unpackedArgs = UnpackArgs(code, ref ip, argCount, unpackCount); } var returnAddress = PopCall(); var argFrame = returnAddress.Arguments; var argFrameCount = unpackedArgs?.Count ?? argCount; // make sure we have the correct number of values if (argFrameCount != argFrame.Values.Length) { argFrame.Values = new MondValue[argFrameCount]; } // copy arguments into frame if (unpackedArgs == null) { for (var i = argFrameCount - 1; i >= 0; i--) { argFrame.Values[i] = Pop(); } } else { for (var i = 0; i < argFrameCount; i++) { argFrame.Values[i] = unpackedArgs[i]; } } // get rid of old locals PushLocal(PopLocal().Previous); PushCall(new ReturnAddress(returnAddress.Program, returnAddress.Address, argFrame, _evalStackSize)); ip = address; break; } case (int)InstructionType.Enter: { var localCount = ReadInt32(code, ref ip); var frame = PopLocal(); frame = new Frame(frame?.Depth + 1 ?? 0, frame, localCount); PushLocal(frame); locals = frame; break; } case (int)InstructionType.Leave: { var frame = PopLocal(); frame = frame.Previous; PushLocal(frame); locals = frame; break; } case (int)InstructionType.Ret: { var returnAddress = PopCall(); PopLocal(); program = returnAddress.Program; code = program.Bytecode; ip = returnAddress.Address; args = _callStackSize > 0 ? PeekCall().Arguments : null; locals = _localStackSize > 0 ? PeekLocal() : null; if (_callStackSize == initialCallDepth) { return(Pop()); } if (Debugger != null && DebuggerCheckReturn()) { DebuggerBreak(program, locals, args, ip, initialCallDepth); } break; } case (int)InstructionType.VarArgs: { var fixedCount = ReadInt32(code, ref ip); var varArgs = MondValue.Array(); for (var i = fixedCount; i < args.Values.Length; i++) { varArgs.ArrayValue.Add(args.Values[i]); } args.Set(args.Depth, fixedCount, varArgs); break; } #endregion #region Branching case (int)InstructionType.Jmp: { var address = ReadInt32(code, ref ip); ip = address; break; } case (int)InstructionType.JmpTrueP: { var address = ReadInt32(code, ref ip); if (Peek()) { ip = address; } break; } case (int)InstructionType.JmpFalseP: { var address = ReadInt32(code, ref ip); if (!Peek()) { ip = address; } break; } case (int)InstructionType.JmpTrue: { var address = ReadInt32(code, ref ip); if (Pop()) { ip = address; } break; } case (int)InstructionType.JmpFalse: { var address = ReadInt32(code, ref ip); if (!Pop()) { ip = address; } break; } case (int)InstructionType.JmpTable: { var start = ReadInt32(code, ref ip); var count = ReadInt32(code, ref ip); var endIp = ip + count * 4; var value = Pop(); if (value.Type == MondValueType.Number) { var number = (double)value; var numberInt = (int)number; if (number >= start && number < start + count && Math.Abs(number - numberInt) <= double.Epsilon) { ip += (numberInt - start) * 4; ip = ReadInt32(code, ref ip); break; } } ip = endIp; break; } #endregion case (int)InstructionType.Breakpoint: { if (Debugger == null) { break; } DebuggerBreak(program, locals, args, ip, initialCallDepth); // we stop for the statement *after* the debugger statement so we // skip the next break opportunity, otherwise we break twice _debugSkip = true; break; } default: throw new MondRuntimeException(RuntimeError.UnhandledOpcode); } } } catch (Exception e) { var message = e.Message.Trim(); // we skip the OOB checks in the stack methods because the CLR has issues eliminating // its own checks, so we let it throw and check here for a bit of a speed boost if (e is IndexOutOfRangeException) { if (_callStackSize >= CallStackCapacity || _localStackSize >= CallStackCapacity || _evalStackSize >= EvalStackCapacity) { message = RuntimeError.StackOverflow; } else if (_callStackSize < 0 || _localStackSize < 0 || _evalStackSize < 0) { message = RuntimeError.StackEmpty; } } StringBuilder stackTraceBuilder; if (e is MondRuntimeException runtimeException && runtimeException.MondStackTrace != null) { stackTraceBuilder = new StringBuilder(runtimeException.MondStackTrace); // check if we are running in a wrapped function var stackTrace = new System.Diagnostics.StackTrace(e, false); var frames = stackTrace.GetFrames(); var foundWrapper = false; // skip the first frame because it's this method? need to verify for (var i = 1; i < frames.Length; i++) { var method = frames[i].GetMethod(); if (method == null) { continue; // ??? } var type = method.DeclaringType; // stop at the next call to Machine.Run because it can be recursive if (type == typeof(Machine) && method.Name == "Run") { break; } // the wrapper is a lambda so it's in a compiler generated type, which will be nested var parentType = type.DeclaringType; if (parentType == null) { continue; } // the type and method are compiler generated so they have a weird (and compiler specific) name const string wrapperMagic = "<CheckWrapFunction>"; // make sure the type is nested in MondValue and check both the type and method name if (parentType == typeof(MondValue) && (method.Name.Contains(wrapperMagic) || type.Name.Contains(wrapperMagic))) { foundWrapper = true; break; } } // don't show a native transition for wrappers if (!foundWrapper) { stackTraceBuilder.AppendLine("[... native ...]"); } }
private void UpdateState(MondDebugContext context, int address) { var program = context.Program; var debugInfo = program.DebugInfo; // find out where we are in the source code var statement = debugInfo.FindStatement(address); if (!statement.HasValue) { var position = debugInfo.FindPosition(address); if (position.HasValue) { var line = position.Value.LineNumber; var column = position.Value.ColumnNumber; statement = new MondDebugInfo.Statement(0, line, column, line, column); } else { statement = new MondDebugInfo.Statement(0, -1, -1, -1, -1); } } // refresh all watches List <Watch> watches; lock (_sync) watches = _watches.ToList(); foreach (var watch in watches) { RefreshWatch(_context, watch); } // apply new state and broadcast it MondValue message; lock (_sync) { var stmtValue = statement.Value; var programId = FindProgramIndex(program); _position = new BreakPosition( programId, stmtValue.StartLineNumber, stmtValue.StartColumnNumber, stmtValue.EndLineNumber, stmtValue.EndColumnNumber); message = MondValue.Object(); message["Type"] = "State"; message["Running"] = false; message["Id"] = _position.Id; message["StartLine"] = _position.StartLine; message["StartColumn"] = _position.StartColumn; message["EndLine"] = _position.EndLine; message["EndColumn"] = _position.EndColumn; message["Watches"] = MondValue.Array(watches.Select(Utility.JsonWatch)); message["CallStack"] = BuildCallStackArray(_context.CallStack); } Broadcast(message); }
public MondValue Split(string input, int count = -1, int startat = 0) { var items = _regex.Split(input, count, startat); return(MondValue.Array(items.Select(MondValue.String))); }
public void OnMessage(string data) { MondValue obj; try { obj = Json.Deserialize(data); } catch { return; } try { switch (obj["type"]) { case "action": { var value = (string)obj["action"]; if (value == "break") { _debugger.RequestBreak(); break; } _debugger.PerformAction(ParseAction(value)); ReplyWithOk(); break; } case "stackTrace": { var stackFrames = _debugger.GetStackFramesArray(); var response = MondValue.Object(); response["stackFrames"] = stackFrames; ReplyWithOk(response); break; } case "setBreakpoints": { var programId = GetProgramId(); var breakpoints = obj["breakpoints"].AsList .Select(o => (Line: (int)o["line"], Column: o.GetInt("column"))); var breakpointStatements = _debugger.SetBreakpoints(programId, breakpoints); var response = MondValue.Object(); response["programId"] = programId; response["breakpoints"] = MondValue.Array(breakpointStatements.Select(Utility.JsonBreakpoint)); ReplyWithOk(response); break; } case "getBreakpointLocations": { var programId = GetProgramId(); var startLine = (int)obj["line"]; var startColumn = obj.GetInt("column") ?? int.MinValue; var endLine = obj.GetInt("endLine") ?? startLine; var endColumn = obj.GetInt("endColumn") ?? int.MaxValue; var breakpointLocations = _debugger.GetBreakpointLocations(programId, startLine, startColumn, endLine, endColumn); var response = MondValue.Object(); response["programId"] = programId; response["locations"] = MondValue.Array(breakpointLocations.Select(Utility.JsonBreakpoint)); ReplyWithOk(response); break; } case "eval": { var expression = (string)obj["expression"]; var value = string.IsNullOrEmpty(expression) ? _debugger.GetLocals() : _debugger.Evaluate(expression); var response = MondValue.Object(); response["value"] = value.ToString(); response["type"] = value.Type.GetName(); response["properties"] = Utility.JsonValueProperties(value); ReplyWithOk(response); break; } default: { Console.WriteLine("Unhandled message type: " + obj.Type); var response = MondValue.Object(); response["status"] = "error"; response["error"] = $"unhandled type {obj["type"]}"; ReplyWith(response); break; } } int GetProgramId() { var programId = obj["programId"]; if (programId.Type == MondValueType.Number) { return((int)programId); } var programPath = obj["programPath"]; if (programPath.Type == MondValueType.String) { return(_debugger.FindProgramIndex(programPath)); } throw new InvalidOperationException("Both Program ID and Program Path were unspecified"); } } catch (Exception e) { Console.WriteLine(e); var response = MondValue.Object(); response["status"] = "error"; response["error"] = e.Message; ReplyWith(response); } void ReplyWithOk(MondValue responseObj = default)
public static MondValue Split([MondInstance] MondValue instance, string separator) { var values = ((string)instance).Split(new [] { separator }, StringSplitOptions.None); return(MondValue.Array(values.Select(v => (MondValue)v))); }