static void ScriptMain(TextReader input, string fileName) { var state = new MondState(); Functions.Register(state); string source; try { source = input.ReadToEnd(); } catch (Exception e) { Console.WriteLine("Failed to read '{0}':", fileName); Console.WriteLine(e); return; } try { var program = MondProgram.Compile(Functions.Definitions + source, Path.GetFileName(fileName)); var result = state.Load(program); if (result != MondValue.Undefined) { result.Serialize(Console.Out); Console.WriteLine(); } } catch (Exception e) { Console.WriteLine(e.Message); } }
public ReturnAddress(MondProgram program, int address, Frame arguments, int evalDepth) { Program = program; Address = address; Arguments = arguments; EvalDepth = evalDepth; }
public static MondValue Run(string source) { var state = new MondState(); var program = MondProgram.Compile(source); return(state.Load(program)); }
private static CallStackEntry GenerateCallStackEntry(MondProgram program, int address) { var debugInfo = program.DebugInfo; if (debugInfo == null) return new CallStackEntry(address, program.GetHashCode().ToString("X8"), address.ToString("X8"), 0, -1); var fileName = program.DebugInfo.FileName; string function = null; var lineNumber = 0; var columnNumber = -1; var func = program.DebugInfo.FindFunction(address); if (func.HasValue) function = program.Strings[func.Value.Name]; var position = program.DebugInfo.FindPosition(address); if (position.HasValue) { lineNumber = position.Value.LineNumber; columnNumber = position.Value.ColumnNumber; } if (fileName == null) fileName = program.GetHashCode().ToString("X8"); if (function == null) function = address.ToString("X8"); return new CallStackEntry(address, fileName, function, lineNumber, columnNumber); }
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); }
private static void InteractiveRun(MondState state, MondProgram program) { var result = state.Load(program); // get rid of leading whitespace while (_input.Count > 0 && char.IsWhiteSpace(_input.Peek())) { _input.Dequeue(); } if (_input.Count != 0) { return; } _first = true; // ignore undefined return value, it's almost always useless if (result == MondValue.Undefined) { return; } if (result["moveNext"].Type == MondValueType.Function && result.IsEnumerable) { Console.WriteLine(); foreach (var value in result.Enumerate(state).Take(25)) { value.Serialize(Console.Out); Console.WriteLine(); } if (state.Call(result["moveNext"])) { Console.WriteLine("..."); } Console.WriteLine(); } else { var resultStr = result.Serialize(); var multiline = resultStr.Contains("\n"); if (multiline) { Console.WriteLine(); Console.WriteLine(resultStr); Console.WriteLine(); } else { var lineNumberLen = Math.Max(_line.ToString("G").Length, 3); Console.WriteLine("{0}> {1}", new string('=', lineNumberLen), resultStr); } } }
public Closure(MondProgram program, int address, Frame arguments, Frame locals) { Type = ClosureType.Mond; Program = program; Address = address; Arguments = arguments; Locals = locals; }
public ProgramInfo(MondProgram program) { _breakpoints = new List <int>(16); Program = program; DebugInfo = program.DebugInfo; FileName = DebugInfo?.FileName ?? Program.GetHashCode().ToString("X8"); }
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 MondValue Load(MondProgram program) { if (program == null) { throw new ArgumentNullException(nameof(program)); } var function = new MondValue(new Closure(program, 0, null, null)); return(Call(function)); }
/// <summary> /// Removes a breakpoint from the given program. /// </summary> /// <param name="program"></param> /// <param name="address"></param> protected void RemoveBreakpoint(MondProgram program, int address) { lock (_sync) { if (!_programBreakpoints.TryGetValue(program, out var breakpoints)) { return; } breakpoints.Remove(address); } }
public static MondState Load(params string[] sources) { var state = new MondState(); foreach (var source in sources) { var program = MondProgram.Compile(source); state.Load(program); } return(state); }
public void NativeFunction() { var state = new MondState(); state["function"] = new MondFunction((_, args) => args[0]); var program = MondProgram.Compile(@" return global.function('arg'); "); var result = state.Load(program); Assert.True(result == "arg"); }
internal CallStackEntry( MondProgram program, int address, string fileName, string function, int lineNumber, int columnNumber) { Program = program; Address = address; FileName = fileName; Function = function; LineNumber = lineNumber; ColumnNumber = columnNumber; }
internal MondDebugContext( MondState state, MondProgram program, int address, Frame locals, Frame args, ReturnAddress[] callStack, int callStackTop, int callStackBottom) { _state = state; _address = address; _locals = locals; _args = args; Program = program; CallStack = GenerateCallStack(address, callStack, callStackTop, callStackBottom).AsReadOnly(); _localObject = CreateLocalObject(); }
public void NativeInstanceFunction() { var state = new MondState(); state["value"] = 123; state["function"] = new MondInstanceFunction((_, instance, arguments) => instance[arguments[0]]); var program = MondProgram.Compile(@" return global.function('value'); "); var result = state.Load(program); Assert.True(result == 123); }
private static MondValue Require(MondState state, params MondValue[] arguments) { if (arguments.Length < 1) { throw new MondRuntimeException("require: must be called with 1 argument"); } if (arguments[0].Type != MondValueType.String) { throw new MondRuntimeException("require: argument 1 must be of type String"); } var fileName = (string)arguments[0]; var program = MondProgram.Compile(Definitions + File.ReadAllText(fileName), fileName); return(state.Load(program)); }
internal MondDebugContext( MondState state, MondProgram program, int address, Frame locals, Frame args, ReturnAddress[] callStack, int callStackTop, int callStackBottom) { _state = state; _address = address; _locals = locals; _args = args; Program = program; DebugInfo = program.DebugInfo; CallStack = GenerateCallStack(address, callStack, callStackTop, callStackBottom).AsReadOnly(); _localObject = CreateLocalObject(); }
internal bool ShouldBreak(MondProgram program, int address) { lock (_sync) { if (IsBreakRequested) { IsBreakRequested = false; return true; } List<int> breakpoints; if (!_programBreakpoints.TryGetValue(program, out breakpoints)) return false; return breakpoints.Contains(address); } }
/// <summary> /// Adds a breakpoint to the given program. /// </summary> /// <param name="program"></param> /// <param name="address"></param> protected void AddBreakpoint(MondProgram program, int address) { lock (_sync) { if (!_programBreakpoints.TryGetValue(program, out var breakpoints)) { breakpoints = new List <int>(); _programBreakpoints.Add(program, breakpoints); } if (breakpoints.Contains(address)) { return; } breakpoints.Add(address); } }
internal bool ShouldBreak(MondProgram program, int address) { lock (_sync) { if (IsBreakRequested) { IsBreakRequested = false; return(true); } if (!_programBreakpoints.TryGetValue(program, out var breakpoints)) { return(false); } return(breakpoints.Contains(address)); } }
private static CallStackEntry GenerateCallStackEntry(MondProgram program, int address) { var debugInfo = program.DebugInfo; if (debugInfo == null) { return(new CallStackEntry( program, address, program.GetHashCode().ToString("X8"), address.ToString("X8"), 0, -1)); } var fileName = program.DebugInfo.FileName; string function = null; var lineNumber = 0; var columnNumber = -1; var func = program.DebugInfo.FindFunction(address); if (func.HasValue) { function = program.Strings[func.Value.Name]; } var position = program.DebugInfo.FindPosition(address); if (position.HasValue) { lineNumber = position.Value.LineNumber; columnNumber = position.Value.ColumnNumber; } if (fileName == null) { fileName = program.GetHashCode().ToString("X8"); } if (function == null) { function = address.ToString("X8"); } return(new CallStackEntry( program, address, fileName, function, lineNumber, columnNumber)); }
internal CallStackEntry( MondProgram program, int address, string fileName, string function, int startLineNumber, int startColumnNumber, int?endLineNumber = null, int?endColumnNumber = null) { Program = program; Address = address; FileName = fileName; Function = function; StartLineNumber = startLineNumber; StartColumnNumber = startColumnNumber; EndLineNumber = endLineNumber; EndColumnNumber = endColumnNumber; }
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 = new MondValue(MondValueType.Object); message["Type"] = "NewProgram"; message["Id"] = id; message["FileName"] = programInfo.FileName; message["SourceCode"] = debugInfo.SourceCode; message["FirstLine"] = Utility.FirstLineNumber(debugInfo); message["Breakpoints"] = new MondValue(programInfo.Breakpoints.Select(e => new MondValue(e))); Broadcast(message); }
private static void InteractiveMain() { var useColoredInput = !HasFlag("--no-color"); if (useColoredInput) { _readLine = () => Highlighted.ReadLine(ref _highlighter); Console.CancelKeyPress += (sender, eventArgs) => Console.ResetColor(); } else { _readLine = Console.ReadLine; } _input = new Queue <char>(); _first = true; var state = CreateState(true, out var options); while (true) { try { options.FirstLineNumber = _line + 1; foreach (var program in MondProgram.CompileStatements(ConsoleInput(), "stdin", options)) { InteractiveRun(state, program); } } catch (Exception e) { PrintException(e); } } }
private static string GetAddressDebugInfo(MondProgram program, int address) { if (program.DebugInfo != null) { var func = program.DebugInfo.FindFunction(address); var line = program.DebugInfo.FindLine(address); if (func.HasValue && line.HasValue) { var prefix = ""; var funcName = program.Strings[func.Value.Name]; var fileName = program.Strings[line.Value.FileName]; if (!string.IsNullOrEmpty(funcName)) { prefix = string.Format("at {0} ", funcName); } return(string.Format("{0}in {1}: line {2}", prefix, fileName, line.Value.LineNumber)); } } return(address.ToString("X8")); }
internal int FindProgramIndex(MondProgram p) => _programs.FindIndex(t => ReferenceEquals(t.Program, p));
static void InteractiveMain() { _input = new Queue <char>(); var state = new MondState(); var options = new MondCompilerOptions { GenerateDebugInfo = true, MakeRootDeclarationsGlobal = true, UseImplicitGlobals = true }; Functions.Register(state); var line = 1; while (true) { try { MondValue result; do { var program = MondProgram.CompileStatement(ConsoleInput(), string.Format("stdin_{0:D}", line), options); result = state.Load(program); // get rid of leading whitespace while (_input.Count > 0 && char.IsWhiteSpace(_input.Peek())) { _input.Dequeue(); } } while (_input.Count > 0); // we only want the result of the last statement line++; // ignore undefined return value, it's almost always useless if (result == MondValue.Undefined) { continue; } if (result["moveNext"] && result.IsEnumerable) { foreach (var value in result.Enumerate(state)) { value.Serialize(Console.Out); Console.WriteLine(); } } else { result.Serialize(Console.Out); Console.WriteLine(); } Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(); _input.Clear(); } } }
static void InteractiveRun(MondState state, MondProgram program) { var result = state.Load(program); // get rid of leading whitespace while (_input.Count > 0 && char.IsWhiteSpace(_input.Peek())) { _input.Dequeue(); } if (_input.Count != 0) return; _first = true; // ignore undefined return value, it's almost always useless if (result == MondValue.Undefined) return; if (result["moveNext"].Type == MondValueType.Function && result.IsEnumerable) { Console.WriteLine(); foreach (var value in result.Enumerate(state).Take(25)) { value.Serialize(Console.Out); Console.WriteLine(); } if (state.Call(result["moveNext"])) Console.WriteLine("..."); Console.WriteLine(); } else { var resultStr = result.Serialize(); var multiline = resultStr.Contains("\n"); if (multiline) { Console.WriteLine(); Console.WriteLine(resultStr); Console.WriteLine(); } else { var lineNumberLen = Math.Max(_line.ToString("G").Length, 3); Console.WriteLine("{0}> {1}", new string('=', lineNumberLen), resultStr); } } }
private void DebuggerBreak(MondProgram program, Frame locals, Frame args, int address, int initialCallDepth) { var context = new MondDebugContext( _state, program, address, locals, args, _callStack, _callStackSize, initialCallDepth); _debugAction = Debugger.Break(context, address); _debugAlign = false; _debugDepth = 0; }
/// <summary> /// Adds a breakpoint to the given program. /// </summary> /// <param name="program"></param> /// <param name="address"></param> protected void AddBreakpoint(MondProgram program, int address) { lock (_sync) { List<int> breakpoints; if (!_programBreakpoints.TryGetValue(program, out breakpoints)) { breakpoints = new List<int>(); _programBreakpoints.Add(program, breakpoints); } if (breakpoints.Contains(address)) return; breakpoints.Add(address); } }
private static string GetAddressDebugInfo(MondProgram program, int address) { if (program.DebugInfo != null) { var func = program.DebugInfo.FindFunction(address); var position = program.DebugInfo.FindPosition(address); if (func.HasValue && position.HasValue) { var prefix = ""; var funcName = program.Strings[func.Value.Name]; var fileName = program.DebugInfo.FileName ?? program.GetHashCode().ToString("X8"); if (!string.IsNullOrEmpty(funcName)) prefix = string.Format("at {0} ", funcName); return string.Format("{0}in {1}: line {2}:{3}", prefix, fileName, position.Value.LineNumber, position.Value.ColumnNumber); } } return address.ToString("X8"); }
/// <summary> /// Removes a breakpoint from the given program. /// </summary> /// <param name="program"></param> /// <param name="address"></param> protected void RemoveBreakpoint(MondProgram program, int address) { lock (_sync) { List<int> breakpoints; if (!_programBreakpoints.TryGetValue(program, out breakpoints)) return; breakpoints.Remove(address); } }
public MondValue Require(MondState state, string fileName) { 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 = new MondValue(state); cacheObject.Prototype = MondValue.Null; state[cacheObjectName] = cacheObject; } else { cacheObject = state[cacheObjectName]; } // return cached module if it exists var cachedExports = cacheObject[fileName]; if (cachedExports.Type == MondValueType.Object) { return(cachedExports); } // create a new object to store the exports var exports = new MondValue(state); exports.Prototype = MondValue.Null; // instantly cache it so we can have circular dependencies cacheObject[fileName] = exports; try { IEnumerable <string> searchDirectories = _require.SearchDirectories ?? Array.Empty <string>(); if (_require.SearchBesideScript) { var currentDir = Path.GetDirectoryName(state.CurrentScript); searchDirectories = Enumerable.Repeat(currentDir, 1) .Concat(searchDirectories); } var moduleSource = _require.Loader(fileName, searchDirectories); // 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 + " 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, fileName, 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, result)) { // module returned a different object, merge with ours foreach (var kv in result.Object) { 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[fileName] = MondValue.Undefined; throw; } return(exports); }
public ReturnAddress(MondProgram program, int address, Frame arguments) { Program = program; Address = address; Arguments = arguments; }