Ver Fonte

Debugger progress

Xanathar há 11 anos atrás
pai
commit
a84342c8b0

+ 6 - 0
LICENSE

@@ -4,6 +4,12 @@ All rights reserved.
 This work is based on the ANTLR4 Lua grammar 
 Copyright (c) 2013, Kazunori Sakamoto
 
+Parts of the string library are based on the KopiLua project (https://github.com/NLua/KopiLua)
+Copyright (c) 2012 LoDC
+
+Debugger icons are from the Eclipse project (https://www.eclipse.org/).
+Copyright of The Eclipse Foundation
+
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

+ 5 - 1
README.md

@@ -15,4 +15,8 @@ The program and libraries are released under a 3-clause BSD license - see the li
 
 This work is based on the ANTLR4 Lua grammar Copyright (c) 2013, Kazunori Sakamoto.
 
-Parts of the string library are based on the UniLua project.
+Parts of the string library are based on the KopiLua project (https://github.com/NLua/KopiLua).
+
+Debugger icons are from the Eclipse project (https://www.eclipse.org/).
+
+

+ 2 - 1
src/Flash/org.moonsharp.debugger.client/.actionScriptProperties

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <actionScriptProperties analytics="false" mainApplicationPath="Main.mxml" projectUUID="eae8fade-1148-4d51-b958-a8080aadc1cc" version="10">
-  <compiler additionalCompilerArguments="-locale en_US" autoRSLOrdering="true" copyDependentFiles="true" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="true" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin-debug" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
+  <compiler additionalCompilerArguments="-locale en_US -show-unused-type-selector-warnings=false" autoRSLOrdering="true" copyDependentFiles="true" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="true" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin-debug" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
     <compilerSourcePath/>
     <libraryPath defaultLinkType="1">
       <libraryPathEntry kind="4" path="">
@@ -13,6 +13,7 @@
     </libraryPath>
     <sourceAttachmentPath/>
   </compiler>
+  <theme themeIsDefault="false" themeIsSDK="true" themeLocation="${SDK_THEMES_DIR}/samples/themes/spark_graphite"/>
   <applications>
     <application path="Main.mxml"/>
   </applications>

+ 13 - 2
src/Flash/org.moonsharp.debugger.client/src/DebuggerViewLogic.as

@@ -65,7 +65,13 @@ package
 			else if (cmd == "source-loc")
 			{
 				m_InstructionPtrHighlight = parseHighlight(xml);
-				m_View.refreshInstructionPtrHighlight();
+				m_View.refreshInstructionPtrHighlight(true);
+			}			
+			else if (cmd == "execution-completed")
+			{
+				m_InstructionPtrHighlight = null;
+				m_View.refreshInstructionPtrHighlight(true);
+				logMessage("Execution completed.");
 			}
 			else if (cmd == "callstack")
 			{
@@ -165,7 +171,12 @@ package
 		{
 			m_Socket.send(<Command cmd="stepIn" />);		
 		}
-
+		
+		public function stepOut() : void
+		{
+			m_Socket.send(<Command cmd="stepOut" />);		
+		}
+		
 		public function stepOver() : void
 		{
 			m_Socket.send(<Command cmd="stepOver" />);		

+ 141 - 5
src/Flash/org.moonsharp.debugger.client/src/Main.css

@@ -1,13 +1,149 @@
-/* CSS file */
 @namespace s "library://ns.adobe.com/flex/spark";
 @namespace mx "library://ns.adobe.com/flex/mx";
 
+@font-face 
+{ 
+	src: url("assets/Ubuntu-R.ttf"); 
+	fontFamily: Ubuntu; 
+	fontStyle: normal; 
+	fontWeight: normal; 
+	embed-as-cff: true;
+	advancedAntiAliasing: false;
+}
+
+@font-face 
+{ 
+	src: url("assets/Ubuntu-B.ttf"); 
+	fontFamily: Ubuntu; 
+	fontStyle: normal; 
+	fontWeight: bold; 
+	embed-as-cff: true;
+	advancedAntiAliasing: false;
+}
+
+@font-face 
+{ 
+	src: url("assets/UbuntuMono-R.ttf"); 
+	fontFamily: UbuntuMono; 
+	fontStyle: normal; 
+	fontWeight: normal; 
+	advancedAntiAliasing: true;
+}
 
 global
 {
-	font-family: Arial;
-	font-size: 12;
-	content-background-color: #FFFFFF;
+	fontFamily: Ubuntu;
+	contentBackgroundColor: #555555;
+	chrome-color: #333333;
+	color: #EEEEEE;
+	symbol-color: #000000;
+	roll-over-color: #777777;
+	selection-color: #B1AEFA;
+	accent-color: #8C8C8C;
+	focus-color: #B1AEFA;
+	focusAlpha: 1;
+}
+
+mx|Alert, mx|TitleWindow, mx|MenuBar, mx|Panel
+{
+	/* fontFamily: UbuntuMx; */	
+}
+
+
+mx|CheckBox,s|CheckBox
+{
+	symbolColor: #b1aefa;	
+}
+
+
+s|List
+{
+	roll-over-color: #777777;
+	selection-color: #B1AEFA;
+}
+
+s|Button
+{ 
+	cornerRadius: 0;
+	skinClass:ClassReference("CustomButtonSkin");
+	borderWeight: 1;
+	borderColor: #000000;
+}
+
+s|Button:over
+{
+	chrome-color: #999999; 
+	borderColor: #b1aefa;
+	borderWeight: 1;
+	cornerRadius: 0;
+}
+
+s|Button:down
+{
+	chrome-color: #222222; 
+	borderColor: #b1aefa;
+	borderWeight: 1;
+	cornerRadius: 0;
+}
+
+/* // mx|TabNavigator,mx|SwatchPanel */
+
+s|Panel,mx|TitleWindow 
+{
+	background-color: #666666;
+}
+
+s|TextArea
+{
+	color: #CCCCCC;
+}
+
+s|Panel
+{
+	chrome-color: #222222;
+	borderAlpha: 0.5;
+	borderColor: 0;
+	cornerRadius: 0;
+	dropShadowVisible: true;
+	background-color: #484848;
+}
+
+s|RichEditableText
+{
+	focusedTextSelectionColor: #777777;
+	unfocusedTextSelectionColor: #777777;
+}
+
+
+mx|Accordion
+{
+	openDuration: 320;
+	chrome-color: #222222;
+}
+
+s|DropDownList
+{
+	borderVisible : false;
+	contentBackgroundColor: #555555;
+}
+
+s|DataGrid
+{  
+	alternatingRowColors : #505050, #555555;
+	skinClass: ClassReference("CustomDataGridSkin")
+}
+
+mx|ToolTip
+{
 	color: #000000;
 }
-	
+	
+
+mx|MenuBar
+{
+	selectionColor: #B1AEFA;
+	leading: 0;
+	contentBackgroundColor: #777777;
+	roll-over-color: #B1AEFA;
+}
+

+ 86 - 29
src/Flash/org.moonsharp.debugger.client/src/Main.mxml

@@ -3,32 +3,64 @@
 			   xmlns:s="library://ns.adobe.com/flex/spark" 
 			   xmlns:mx="library://ns.adobe.com/flex/mx" 
 			   minWidth="955" minHeight="600" width="100%" height="100%"
-			   creationComplete="application1_creationCompleteHandler(event)"
+			   creationComplete="application_creationCompleteHandler(event)"
+			   initialize="initializeApp();"
 			   >
+	<fx:Style source="MXFTEText.css"/>
 	<fx:Style source="Main.css"/>
-	<!-- fx:Style>
-	@namespace s "library://ns.adobe.com/flex/spark";
-	@namespace mx "library://ns.adobe.com/flex/mx";
-	
-	s|Panel #titleDisplay {
-	color: white;
-	} 
-	
-	</fx:Style -->	
-	
+
 	<fx:Script>
 		
-		<![CDATA[ 
+		<![CDATA[
 			import flashx.textLayout.formats.TextLayoutFormat;
 			
+			import mx.collections.XMLListCollection;
+			import mx.controls.Alert;
 			import mx.events.FlexEvent;
+			import mx.events.MenuEvent;
 			
 			import spark.events.IndexChangeEvent;
 			import spark.events.TextOperationEvent;
+
+			[Bindable]
+			public var menuBarCollection:XMLListCollection;
+			
+			private var menubarXML:XMLList =
+				<>
+					<menuitem label="Debug" data="top">
+						<menuitem label="Step In - F11" data="1A" icon="@Embed('assets/stepin.gif')"/>
+						<menuitem label="Step Over" data="1B"/>
+						<menuitem type="separator"/>
+						<menuitem label="Run" data="1B"/>
+						<menuitem label="Pause" data="1B"/>
+						<menuitem type="separator"/>
+						<menuitem label="Toggle breakpoint" data="1B"/>
+					</menuitem>
+					<menuitem label="Watches" data="top">
+						<menuitem label="Add..." data="1A"/>
+						<menuitem label="Remove" data="1B"/>
+					</menuitem>
+					<menuitem label="Help" data="top">
+						<menuitem label="About..." data="about"/>
+					</menuitem>
+				</>;			
+			
+			private function initializeApp():void {
+				menuBarCollection = new XMLListCollection(menubarXML);
+			}
+			
+			private function menuHandler(evt:MenuEvent):void  
+			{
+				var cmd : String = evt.item.@data; 
+				
+				if (cmd == "top") return;
+				else if (cmd == "about") AboutBox.show(this); 
+			}
+			
 			
 			private var m_Debugger : DebuggerViewLogic; 
 			
-			protected function application1_creationCompleteHandler(event:FlexEvent):void
+			protected function application_creationCompleteHandler(event:FlexEvent):void
 			{
 				m_Debugger = new DebuggerViewLogic(this);
 			}
@@ -51,24 +83,24 @@
 				}
 			}
 			
-			public function refreshInstructionPtrHighlight() : void
+			public function refreshInstructionPtrHighlight(switchToSource:Boolean) : void
 			{
 				var hl:Highlight = m_Debugger.getInstructionPtrHighlight();
 				
-				if (hl !== null && hl.Source !== m_CurrentSrc)
+				if (switchToSource && hl !== null && hl.Source !== m_CurrentSrc)
 				{
 					selectSource(hl.Source);
 				}
 				
 				var tlf:TextLayoutFormat = new TextLayoutFormat();
-				tlf.backgroundColor = 0xFFFFFF;
+				tlf.backgroundColor = 0x444444;
 				
 				txtCode.setFormatOfRange(tlf, 0, txtCode.text.length - 1);
 				
 				if (hl !== null && hl.Source === m_CurrentSrc)
 				{
 					var tlf2:TextLayoutFormat = new TextLayoutFormat();
-					tlf2.backgroundColor = 0x0080FF;
+					tlf2.backgroundColor = 0xb1aefa;
 					
 					txtCode.setFormatOfRange(tlf2, hl.From, hl.To);
 				}
@@ -97,6 +129,7 @@
 				var S : SourceCode = (SourceCode)(lstSources.selectedItem);
 				txtCode.text = S.getText();
 				m_CurrentSrc = S;
+				refreshInstructionPtrHighlight(false);
 			}
 			
 			protected function getSourceName(o : Object) : String
@@ -107,7 +140,7 @@
 			
 			public function welcome(appName : String, ver : String): void
 			{
-				titleBar.title = "MoonSharp Remote Debugger - [" + appName + "] - v" + ver;
+				titleBar.text = "MoonSharp Remote Debugger - [" + appName + "] - v" + ver;
 			}
 			
 			protected function btnRemoveWatch_clickHandler(event:MouseEvent):void
@@ -141,6 +174,16 @@
 				textOutput.scrollToRange(int.MAX_VALUE, int.MAX_VALUE);
 			}
 			
+			protected function txtCode_changingHandler(event:TextOperationEvent):void
+			{
+				event.preventDefault();
+			}
+			
+			protected function toggleBreakpoint() : void
+			{
+				
+			}
+			
 		]]>
 	</fx:Script> 
 	
@@ -148,15 +191,30 @@
 		<!-- Place non-visual elements (e.g., services, value objects) here -->
 	
 	</fx:Declarations>
-	<s:Panel id="titleBar" width="100%" height="100%" title="MoonSharp Remote Debugger - Connecting...">
 		<mx:VBox width="100%" height="100%">
 			
+			<s:Label width="100%" id="titleBar" height="24" text="MoonSharp Remote Debugger - Connecting..."
+					 verticalAlign="middle"
+					 textAlign="center"
+					 fontSize="14"
+					 fontWeight="bold"
+					 paddingTop="8"
+					 color="0xFFFFFF"
+					 />
+			
+			
+			<mx:MenuBar labelField="@label" iconField="@icon" itemClick="menuHandler(event);" dataProvider="{menuBarCollection}" width="100%"
+						cornerRadius="0" 
+						/>
 			
-			<mx:HBox width="100%" paddingTop="4" paddingLeft="4">
-				<s:Button label="Step in" click="m_Debugger.stepIn();"/> 
-				<s:Button label="Step over" click="m_Debugger.stepOver();"/>
-				<s:Button label="Run" click="m_Debugger.run();"/>
-				<s:Button label="Toggle breakpoint" /> 
+			<mx:HBox width="100%" paddingTop="0" paddingLeft="4">
+				<s:Button height="20" label="Step in" click="m_Debugger.stepIn();" icon="@Embed('assets/stepin.gif')"/> 
+				<s:Button height="20" label="Step out" click="m_Debugger.stepOut();" icon="@Embed('assets/stepout.gif')"/> 
+				<s:Button height="20" label="Step over" click="m_Debugger.stepOver();" icon="@Embed('assets/stepover.gif')"/>
+				<s:Button height="20" label="Run" click="m_Debugger.run();" icon="@Embed('assets/run.gif')"/>
+				<s:Button height="20" label="Pause" click="m_Debugger.run();" icon="@Embed('assets/pause.gif')"/>
+				<s:Button height="20" label="Go to current" click="refreshInstructionPtrHighlight(true);" icon="@Embed('assets/step_current.gif')"/> 
+				<s:Button height="20" label="Toggle breakpoint"  icon="@Embed('assets/breakpoint.gif')" click="toggleBreakpoint();"/> 
 			</mx:HBox>
 			
 			<mx:HDividedBox width="100%" height="100%" liveDragging="true">
@@ -164,8 +222,8 @@
 					<s:Panel title="Watches" width="100%" height="50%">
 						<mx:VBox width="100%"  height="100%">
 							<mx:HBox width="100%" paddingTop="4" paddingLeft="4">
-								<s:Button id="btnAddWatch" label="Add" click="btnAddWatch_clickHandler(event)"/>
-								<s:Button id="btnRemoveWatch" label="Remove" click="btnRemoveWatch_clickHandler(event)"/>
+								<s:Button height="20" id="btnAddWatch" label="Add" click="btnAddWatch_clickHandler(event)" icon="@Embed('assets/add.gif')"/>
+								<s:Button height="20" id="btnRemoveWatch" label="Remove" click="btnRemoveWatch_clickHandler(event)" icon="@Embed('assets/remove.gif')"/>
 							</mx:HBox>
 							<s:DataGrid id="gridWatches" width="100%" height="100%" selectionMode="multipleRows">
 								<s:columns>
@@ -200,17 +258,16 @@
 							</mx:HBox>
 							
 							<s:Scroller width="100%"  height="100%">  
-								<s:RichEditableText id="txtCode" width="100%"  height="100%" fontFamily="Consolas" fontSize="12"  editable="false" />
+								<s:RichEditableText id="txtCode" width="100%" backgroundColor="0x444444"  height="100%" fontFamily="UbuntuMono" fontSize="14"  editable="true" changing="txtCode_changingHandler(event)" />
 							</s:Scroller>
 						</mx:VBox>
 					</s:Panel>
 					<s:Panel id="outputBox" width="100%" height="30%" title="Output">
-						<s:TextArea id="textOutput" width="100%" height="100%" /> 
+						<s:TextArea id="textOutput" width="100%" height="100%" editable="false" /> 
 					</s:Panel>
 			</mx:VDividedBox>
 				
 			</mx:HDividedBox>
 			
 		</mx:VBox>
-	</s:Panel>
 </s:Application>

+ 16 - 6
src/MoonSharp.Debugger/MainForm.cs

@@ -192,12 +192,12 @@ namespace MoonSharp.Debugger
 
 		private void StepIN()
 		{
-			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepIn });
+			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.ByteCodeStepIn });
 		}
 
 		private void StepOVER()
 		{
-			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOver });
+			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.ByteCodeStepOver });
 		}
 
 		private void GO()
@@ -206,7 +206,7 @@ namespace MoonSharp.Debugger
 		}
 
 
-		void IDebugger.Update(WatchType watchType, List<WatchItem> items)
+		void IDebugger.Update(WatchType watchType, IEnumerable<WatchItem> items)
 		{
 			if (watchType == WatchType.CallStack)
 				m_Ctx.Post(UpdateCallStack, items);
@@ -217,7 +217,7 @@ namespace MoonSharp.Debugger
 		}
 		void UpdateVStack(object o)
 		{
-			List<WatchItem> items = (List<WatchItem>)o;
+			IEnumerable<WatchItem> items = (IEnumerable<WatchItem>)o;
 
 			lvVStack.BeginUpdate();
 			lvVStack.Items.Clear();
@@ -238,7 +238,7 @@ namespace MoonSharp.Debugger
 
 		void UpdateWatches(object o)
 		{
-			List<WatchItem> items = (List<WatchItem>)o;
+			IEnumerable<WatchItem> items = (IEnumerable<WatchItem>)o;
 
 			lvWatches.BeginUpdate();
 			lvWatches.Items.Clear();
@@ -259,7 +259,7 @@ namespace MoonSharp.Debugger
 
 		void UpdateCallStack(object o)
 		{
-			List<WatchItem> items = (List<WatchItem>)o;
+			IEnumerable<WatchItem> items = (IEnumerable<WatchItem>)o;
 
 			lvCallStack.BeginUpdate();
 			lvCallStack.Items.Clear();
@@ -416,5 +416,15 @@ namespace MoonSharp.Debugger
 		{
 			return false;
 		}
+
+
+		public void SignalExecutionEnded()
+		{
+		}
+
+
+		public void RefreshBreakpoints(IEnumerable<SourceRef> refs)
+		{
+		}
 	}
 }

+ 17 - 2
src/MoonSharp.Interpreter/Debugging/DebuggerAction.cs

@@ -9,18 +9,26 @@ namespace MoonSharp.Interpreter.Debugging
 	{
 		public enum ActionType
 		{
+			ByteCodeStepIn,
+			ByteCodeStepOver,
+			ByteCodeStepOut,
 			StepIn,
 			StepOver,
+			StepOut,
 			Run,
 			ToggleBreakpoint,
 			Refresh,
+			HardRefresh,
 			None,
 		}
 
-		public int InstructionPtr { get; set; }
 		public ActionType Action { get; set; }
 		public DateTime TimeStampUTC { get; private set; }
 
+		public int SourceID { get; set; }
+		public int SourceLine { get; set; }
+		public int SourceCol { get; set; }
+
 		public DebuggerAction()
 		{
 			TimeStampUTC = DateTime.UtcNow;
@@ -31,7 +39,14 @@ namespace MoonSharp.Interpreter.Debugging
 
 		public override string ToString()
 		{
-			return string.Format("{0}({1})", Action, InstructionPtr);
+			if (Action == ActionType.ToggleBreakpoint)
+			{
+				return string.Format("{0} {1}:({2},{3})", Action, SourceID, SourceLine, SourceCol);
+			}
+			else
+			{
+				return Action.ToString();
+			}
 		}
 	}
 }

+ 3 - 1
src/MoonSharp.Interpreter/Debugging/IDebugger.cs

@@ -12,7 +12,9 @@ namespace MoonSharp.Interpreter.Debugging
 		void SetByteCode(string[] byteCode);
 		bool IsPauseRequested();
 		DebuggerAction GetAction(int ip, SourceRef sourceref);
-		void Update(WatchType watchType, List<WatchItem> items);
+		void SignalExecutionEnded();
+		void Update(WatchType watchType, IEnumerable<WatchItem> items);
 		List<string> GetWatchItems();
+		void RefreshBreakpoints(IEnumerable<SourceRef> refs);
 	}
 }

+ 3 - 0
src/MoonSharp.Interpreter/Debugging/SourceCode.cs

@@ -12,9 +12,12 @@ namespace MoonSharp.Interpreter.Debugging
 		public string[] Lines { get; private set; }
 		public Script OwnerScript { get; private set; }
 		public int SourceID { get; private set; }
+		internal List<SourceRef> Refs { get; private set; }
 
 		internal SourceCode(string name, string code, int sourceID, Script ownerScript)
 		{
+			Refs = new List<SourceRef>();
+
 			List<string> lines = new List<string>();
 
 			Name = name;

+ 19 - 4
src/MoonSharp.Interpreter/Debugging/SourceRef.cs

@@ -14,6 +14,8 @@ namespace MoonSharp.Interpreter.Debugging
 		public int ToLine { get; private set; }
 		public bool IsStepStop { get; private set; }
 
+		public bool Breakpoint;
+
 		internal SourceRef(int sourceIdx, int from, int to, int fromline, int toline, bool isStepStop)
 		{
 			SourceIdx = sourceIdx;
@@ -24,10 +26,6 @@ namespace MoonSharp.Interpreter.Debugging
 			IsStepStop = isStepStop;
 		}
 
-		public SourceRef(int sourceIdx)
-			: this(sourceIdx, 0, int.MaxValue, 0, 0, true)
-		{
-		}
 
 		public override string ToString()
 		{
@@ -36,5 +34,22 @@ namespace MoonSharp.Interpreter.Debugging
 				FromLine, FromChar,
 				ToLine, ToChar);
 		}
+
+		public bool IncludesLocation(int sourceIdx, int line, int col)
+		{
+			if (sourceIdx != SourceIdx || line < FromLine || line > ToLine)
+				return false;
+
+			if (FromLine == ToLine)
+				return col >= FromChar && col <= ToChar;
+			if (line == FromLine)
+				return col >= FromChar;
+			if (line == ToLine)
+				return col <= ToChar;
+
+			return true;
+		}
+
+
 	}
 }

+ 2 - 0
src/MoonSharp.Interpreter/Execution/ScriptLoadingContext.cs

@@ -10,5 +10,7 @@ namespace MoonSharp.Interpreter.Execution
 	{
 		public BuildTimeScope Scope { get; set; }
 		public SourceCode Source { get; set; }
+
+
 	}
 }

+ 1 - 1
src/MoonSharp.Interpreter/Execution/VM/ByteCode.cs

@@ -154,7 +154,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 		}
 
 
-		//[Conditional("EMIT_DEBUG_OPS")]
+		[Conditional("EMIT_DEBUG_OPS")]
 		public void Emit_Debug(string str)
 		{
 			AppendInstruction(new Instruction(m_CurrentSourceRef) { OpCode = OpCode.Debug, Name = str.Substring(0, Math.Min(32, str.Length)) });

+ 0 - 1
src/MoonSharp.Interpreter/Execution/VM/Instruction.cs

@@ -15,7 +15,6 @@ namespace MoonSharp.Interpreter.Execution.VM
 		public DynValue Value;
 		public int NumVal;
 		public int NumVal2;
-		public bool Breakpoint;
 		public SourceRef SourceCodeRef;
 
 		public Instruction(SourceRef sourceref)

+ 3 - 0
src/MoonSharp.Interpreter/Execution/VM/Processor/DebugContext.cs

@@ -13,6 +13,9 @@ namespace MoonSharp.Interpreter.Execution.VM
 			public IDebugger DebuggerAttached = null;
 			public DebuggerAction.ActionType DebuggerCurrentAction = DebuggerAction.ActionType.None;
 			public int DebuggerCurrentActionTarget = -1;
+			public SourceRef LastHlRef = null;
+			public int ExStackDepthAtStep = -1;
+			public List<SourceRef> BreakPoints = new List<SourceRef>();
 		}
 	}
 }

+ 45 - 9
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using System.Threading;
 using MoonSharp.Interpreter.DataStructs;
 using MoonSharp.Interpreter.Debugging;
 
@@ -45,21 +46,30 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 		public DynValue Call(DynValue function, DynValue[] args)
 		{
-			var stopwatch = this.m_Script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Execution);
-
-			m_CanYield = false;
+			EnterProcessor();
 
 			try
 			{
-				int entrypoint = PushClrToScriptStackFrame(function, args);
-				return Processing_Loop(entrypoint);
+				var stopwatch = this.m_Script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Execution);
+
+				m_CanYield = false;
+
+				try
+				{
+					int entrypoint = PushClrToScriptStackFrame(function, args);
+					return Processing_Loop(entrypoint);
+				}
+				finally
+				{
+					m_CanYield = true;
+
+					if (stopwatch != null)
+						stopwatch.Dispose();
+				}
 			}
 			finally
 			{
-				m_CanYield = true;
-
-				if (stopwatch != null)
-					stopwatch.Dispose();
+				LeaveProcessor();
 			}
 		}
 
@@ -91,7 +101,33 @@ namespace MoonSharp.Interpreter.Execution.VM
 		}
 
 
+		int m_OwningThreadID = -1;
+		int m_ExecutionNesting = 0;
+
+		private void LeaveProcessor()
+		{
+			m_ExecutionNesting -= 1;
+
+			if (m_ExecutionNesting == 0 && m_Debug != null && m_Debug.DebuggerAttached != null)
+			{
+				m_Debug.DebuggerAttached.SignalExecutionEnded();
+			}
+		}
 
+		private void EnterProcessor()
+		{
+			int threadID = Thread.CurrentThread.ManagedThreadId;
+
+			if (m_OwningThreadID >= 0 && m_OwningThreadID != threadID)
+			{
+				string msg = string.Format("Cannot enter the same MoonSharp processor from two different threads : {0} and {1}", m_OwningThreadID, threadID);
+				throw new InvalidOperationException(msg);
+			}
+
+			m_OwningThreadID = threadID;
+
+			m_ExecutionNesting += 1;
+		}
 
 
 

+ 28 - 19
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Coroutines.cs

@@ -29,31 +29,40 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 		public DynValue Coroutine_Resume(DynValue[] args)
 		{
-			int entrypoint = 0;
+			EnterProcessor();
 
-			if (m_State != CoroutineState.NotStarted && m_State != CoroutineState.Suspended)
-				throw ScriptRuntimeException.CannotResumeNotSuspended(m_State);
-
-			if (m_State == CoroutineState.NotStarted)
-				entrypoint = PushClrToScriptStackFrame(null, args);
-			else
+			try
 			{
-				m_ValueStack.Push(DynValue.NewTuple(args));
-				entrypoint = m_SavedInstructionPtr;
-			}
+				int entrypoint = 0;
 
-			m_State = CoroutineState.Running;
-			DynValue retVal = Processing_Loop(entrypoint);
+				if (m_State != CoroutineState.NotStarted && m_State != CoroutineState.Suspended)
+					throw ScriptRuntimeException.CannotResumeNotSuspended(m_State);
 
-			if (retVal.Type == DataType.YieldRequest)
-			{
-				m_State = CoroutineState.Suspended;
-				return DynValue.NewTuple(retVal.YieldRequest.ReturnValues);
+				if (m_State == CoroutineState.NotStarted)
+					entrypoint = PushClrToScriptStackFrame(null, args);
+				else
+				{
+					m_ValueStack.Push(DynValue.NewTuple(args));
+					entrypoint = m_SavedInstructionPtr;
+				}
+
+				m_State = CoroutineState.Running;
+				DynValue retVal = Processing_Loop(entrypoint);
+
+				if (retVal.Type == DataType.YieldRequest)
+				{
+					m_State = CoroutineState.Suspended;
+					return DynValue.NewTuple(retVal.YieldRequest.ReturnValues);
+				}
+				else
+				{
+					m_State = CoroutineState.Dead;
+					return retVal;
+				}
 			}
-			else
+			finally
 			{
-				m_State = CoroutineState.Dead;
-				return retVal;
+				LeaveProcessor();
 			}
 		}
 

+ 67 - 11
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs

@@ -17,22 +17,38 @@ namespace MoonSharp.Interpreter.Execution.VM
 			m_Debug.DebuggerAttached = debugger;
 		}
 
+
+
 		private void ListenDebugger(Instruction instr, int instructionPtr)
 		{
-			if (instr.Breakpoint)
+			if (m_Debug.DebuggerAttached.IsPauseRequested() ||
+				(instr.SourceCodeRef != null && instr.SourceCodeRef.Breakpoint && instr.SourceCodeRef != m_Debug.LastHlRef))
 			{
 				m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.None;
 				m_Debug.DebuggerCurrentActionTarget = -1;
 			}
 
-			if ((m_Debug.DebuggerCurrentAction == DebuggerAction.ActionType.Run)
-				|| (m_Debug.DebuggerCurrentAction == DebuggerAction.ActionType.StepOver && m_Debug.DebuggerCurrentActionTarget != instructionPtr))
+			switch(m_Debug.DebuggerCurrentAction)
 			{
-				if (!m_Debug.DebuggerAttached.IsPauseRequested())
+				case DebuggerAction.ActionType.Run:
 					return;
+				case DebuggerAction.ActionType.ByteCodeStepOver:
+					if (m_Debug.DebuggerCurrentActionTarget != instructionPtr) return;
+					break;
+				case DebuggerAction.ActionType.ByteCodeStepOut:
+				case DebuggerAction.ActionType.StepOut:
+					if (m_ExecutionStack.Count >= m_Debug.ExStackDepthAtStep) return;
+					break;
+				case DebuggerAction.ActionType.StepIn:
+					if (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef) return;
+					break;
+				case DebuggerAction.ActionType.StepOver:
+					if (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef || m_ExecutionStack.Count > m_Debug.ExStackDepthAtStep) return;
+					break;
 			}
 
-			RefreshDebugger();
+						
+			RefreshDebugger(false);
 
 			while (true)
 			{
@@ -41,11 +57,19 @@ namespace MoonSharp.Interpreter.Execution.VM
 				switch (action.Action)
 				{
 					case DebuggerAction.ActionType.StepIn:
-						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.StepIn;
+					case DebuggerAction.ActionType.StepOver:
+					case DebuggerAction.ActionType.StepOut:
+					case DebuggerAction.ActionType.ByteCodeStepOut:
+						m_Debug.DebuggerCurrentAction = action.Action;
+						m_Debug.LastHlRef = instr.SourceCodeRef;
+						m_Debug.ExStackDepthAtStep = m_ExecutionStack.Count;
+						return;
+					case DebuggerAction.ActionType.ByteCodeStepIn:
+						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.ByteCodeStepIn;
 						m_Debug.DebuggerCurrentActionTarget = -1;
 						return;
-					case DebuggerAction.ActionType.StepOver:
-						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.StepOver;
+					case DebuggerAction.ActionType.ByteCodeStepOver:
+						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.ByteCodeStepOver;
 						m_Debug.DebuggerCurrentActionTarget = instructionPtr + 1;
 						return;
 					case DebuggerAction.ActionType.Run:
@@ -53,10 +77,14 @@ namespace MoonSharp.Interpreter.Execution.VM
 						m_Debug.DebuggerCurrentActionTarget = -1;
 						return;
 					case DebuggerAction.ActionType.ToggleBreakpoint:
-						m_RootChunk.Code[action.InstructionPtr].Breakpoint = !m_RootChunk.Code[action.InstructionPtr].Breakpoint;
+						ToggleBreakPoint(action);
+						RefreshDebugger(true);
 						break;
 					case DebuggerAction.ActionType.Refresh:
-						RefreshDebugger();
+						RefreshDebugger(false);
+						break;
+					case DebuggerAction.ActionType.HardRefresh:
+						RefreshDebugger(true);
 						break;
 					case DebuggerAction.ActionType.None:
 					default:
@@ -65,7 +93,32 @@ namespace MoonSharp.Interpreter.Execution.VM
 			}
 		}
 
-		private void RefreshDebugger()
+
+
+		private void ToggleBreakPoint(DebuggerAction action)
+		{
+			SourceCode src = m_Script.GetSourceCode(action.SourceID);
+
+			foreach (SourceRef srf in src.Refs)
+			{
+				if (srf.IncludesLocation(action.SourceID, action.SourceLine, action.SourceCol))
+				{
+					srf.Breakpoint = !srf.Breakpoint;
+
+					if (srf.Breakpoint)
+					{
+						m_Debug.BreakPoints.Add(srf);
+					}
+					else
+					{
+						m_Debug.BreakPoints.Remove(srf);
+					}
+				}
+			}
+
+		}
+
+		private void RefreshDebugger(bool hard)
 		{
 			List<string> watchList = m_Debug.DebuggerAttached.GetWatchItems();
 			List<WatchItem> callStack = Debugger_GetCallStack();
@@ -74,6 +127,9 @@ namespace MoonSharp.Interpreter.Execution.VM
 			m_Debug.DebuggerAttached.Update(WatchType.CallStack, callStack);
 			m_Debug.DebuggerAttached.Update(WatchType.Watches, watches);
 			m_Debug.DebuggerAttached.Update(WatchType.VStack, vstack);
+
+			if (hard)
+				m_Debug.DebuggerAttached.RefreshBreakpoints(m_Debug.BreakPoints);
 		}
 
 		private List<WatchItem> Debugger_RefreshVStack()

+ 4 - 4
src/MoonSharp.Interpreter/Tree/Antlr_Interface/Loader_Antlr.cs

@@ -41,10 +41,10 @@ namespace MoonSharp.Interpreter.Tree
 
 				int beginIp = -1;
 
-				var srcref = new SourceRef(source.SourceID);
+				//var srcref = new SourceRef(source.SourceID);
 
 				using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Compilation))
-				using (bytecode.EnterSource(srcref))
+				using (bytecode.EnterSource(null))
 				{
 					bytecode.Emit_Nop(string.Format("Begin chunk {0}", source.Name));
 					beginIp = bytecode.GetJumpPointForLastInstruction();
@@ -78,10 +78,10 @@ namespace MoonSharp.Interpreter.Tree
 
 				int beginIp = -1;
 
-				var srcref = new SourceRef(source.SourceID);
+				// var srcref = new SourceRef(source.SourceID);
 
 				using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Compilation))
-				using (bytecode.EnterSource(srcref))
+				using (bytecode.EnterSource(null))
 				{
 					bytecode.Emit_Nop(string.Format("Begin function {0}", source.Name));
 					beginIp = fndef.CompileBody(bytecode, source.Name);

+ 7 - 2
src/MoonSharp.Interpreter/Tree/NodeBase.cs

@@ -36,13 +36,13 @@ namespace MoonSharp.Interpreter.Tree
 
 		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, IToken token, ITerminalNode terminalNode)
 		{
-			return new SourceRef(lcontext.Source.SourceID, token.Column, token.Column + terminalNode.GetText().Length, token.Line, token.Line, true);
+			return RegisterSourceRef(lcontext, new SourceRef(lcontext.Source.SourceID, token.Column, token.Column + terminalNode.GetText().Length, token.Line, token.Line, true));
 		}
 
 		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, IToken token1, IToken token2 = null)
 		{
 			token2 = token2 ?? token1;
-			return new SourceRef(lcontext.Source.SourceID, token1.Column, token2.Column + token2.Text.Length, token1.Line, token2.Line, true);
+			return RegisterSourceRef(lcontext, new SourceRef(lcontext.Source.SourceID, token1.Column, token2.Column + token2.Text.Length, token1.Line, token2.Line, true));
 		}
 
 		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, ITerminalNode terminalNode)
@@ -50,6 +50,11 @@ namespace MoonSharp.Interpreter.Tree
 			return BuildSourceRef(lcontext, terminalNode.Symbol, terminalNode);
 		}
 
+		private static SourceRef RegisterSourceRef(ScriptLoadingContext lcontext, SourceRef sourceRef)
+		{
+			lcontext.Source.Refs.Add(sourceRef);
+			return sourceRef;
+		}
 
 	}
 }

+ 44 - 14
src/MoonSharp.RemoteDebugger/DebugServer.cs

@@ -15,7 +15,7 @@ namespace MoonSharp.RemoteDebugger
 	public class DebugServer : IDebugger
 	{
 		List<string> m_Watches = new List<string>();
-		List<string> m_WatchesChanging = new List<string>();
+		HashSet<string> m_WatchesChanging = new HashSet<string>();
 		Utf8TcpServer m_Server;
 		Script m_Script;
 		string m_AppName;
@@ -105,7 +105,7 @@ namespace MoonSharp.RemoteDebugger
 		string[] m_CachedWatches = new string[(int)WatchType.MaxValue];
 
 
-		public void Update(WatchType watchType, List<WatchItem> items)
+		public void Update(WatchType watchType, IEnumerable<WatchItem> items)
 		{
 			if (watchType != WatchType.CallStack && watchType != WatchType.Watches)
 				return;
@@ -202,14 +202,7 @@ namespace MoonSharp.RemoteDebugger
 				{
 					Send(xw =>
 						{
-							using (xw.Element("source-loc"))
-							{
-								xw.Attribute("srcid", sourceref.SourceIdx)
-									.Attribute("cf", sourceref.FromChar)
-									.Attribute("ct", sourceref.ToChar)
-									.Attribute("lf", sourceref.FromLine)
-									.Attribute("lt", sourceref.ToLine);
-							}
+							SendSourceRef(xw, sourceref);
 						});
 				}
 
@@ -217,7 +210,7 @@ namespace MoonSharp.RemoteDebugger
 				{
 					DebuggerAction da = m_QueuedActions.Dequeue();
 
-					if (da.Action == DebuggerAction.ActionType.Refresh)
+					if (da.Action == DebuggerAction.ActionType.Refresh || da.Action == DebuggerAction.ActionType.HardRefresh)
 					{
 						lock (m_Lock)
 						{
@@ -228,6 +221,9 @@ namespace MoonSharp.RemoteDebugger
 						return da;
 					}
 
+					if (da.Action == DebuggerAction.ActionType.ToggleBreakpoint)
+						return da;
+
 					if (da.Age < TimeSpan.FromMilliseconds(100))
 						return da;
 				}
@@ -238,6 +234,18 @@ namespace MoonSharp.RemoteDebugger
 			}
 		}
 
+		private void SendSourceRef(XmlWriter xw, SourceRef sourceref)
+		{
+			using (xw.Element("source-loc"))
+			{
+				xw.Attribute("srcid", sourceref.SourceIdx)
+					.Attribute("cf", sourceref.FromChar)
+					.Attribute("ct", sourceref.ToChar)
+					.Attribute("lf", sourceref.FromLine)
+					.Attribute("lt", sourceref.ToLine);
+			}
+		}
+
 		void m_Server_DataReceived(object sender, Utf8TcpPeerEventArgs e)
 		{
 			XmlDocument xdoc = new XmlDocument();
@@ -267,9 +275,12 @@ namespace MoonSharp.RemoteDebugger
 					case "stepover":
 						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOver });
 						break;
+					case "stepout":
+						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOut });
+						break;
 					case "addwatch":
 						lock (m_Lock)
-							m_WatchesChanging.AddRange(arg.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
+							m_WatchesChanging.UnionWith(arg.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()));
 
 						QueueRefresh();
 						break;
@@ -296,7 +307,7 @@ namespace MoonSharp.RemoteDebugger
 				m_HostBusySent = true;
 			}
 
-			QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Refresh });
+			QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.HardRefresh });
 		}
 
 		private void SendMessage(string text)
@@ -316,7 +327,26 @@ namespace MoonSharp.RemoteDebugger
 
 		public bool IsPauseRequested()
 		{
-			return true;
+			return false;
+		}
+
+
+		public void SignalExecutionEnded()
+		{
+			Send(xw => xw.Element("execution-completed", ""));
+		}
+
+
+		public void RefreshBreakpoints(IEnumerable<SourceRef> refs)
+		{
+			Send(xw =>
+			{
+				using (xw.Element("breakpoints"))
+				{
+					foreach (var rf in refs)
+						SendSourceRef(xw, rf);
+				}
+			});
 		}
 	}
 }

+ 6 - 0
src/MoonSharp/Program.cs

@@ -138,6 +138,12 @@ namespace MoonSharp
 				m_DbgS = new DebugServer("MoonSharp REPL interpreter", S, 20001, false);
 				S.AttachDebugger(m_DbgS);
 			}
+			if (p == "!")
+			{
+				m_DbgS = new DebugServer("MoonSharp REPL interpreter", S, 20001, false);
+				S.AttachDebugger(m_DbgS);
+				S.DoFile(@"c:\temp\test.lua");
+			}
 		}
 
 		static void m_Server_DataReceivedAny(object sender, Utf8TcpPeerEventArgs e)