瀏覽代碼

Debugger progress

Xanathar 11 年之前
父節點
當前提交
a84342c8b0

+ 6 - 0
LICENSE

@@ -4,6 +4,12 @@ All rights reserved.
 This work is based on the ANTLR4 Lua grammar 
 This work is based on the ANTLR4 Lua grammar 
 Copyright (c) 2013, Kazunori Sakamoto
 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
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 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.
 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"?>
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <actionScriptProperties analytics="false" mainApplicationPath="Main.mxml" projectUUID="eae8fade-1148-4d51-b958-a8080aadc1cc" version="10">
 <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/>
     <compilerSourcePath/>
     <libraryPath defaultLinkType="1">
     <libraryPath defaultLinkType="1">
       <libraryPathEntry kind="4" path="">
       <libraryPathEntry kind="4" path="">
@@ -13,6 +13,7 @@
     </libraryPath>
     </libraryPath>
     <sourceAttachmentPath/>
     <sourceAttachmentPath/>
   </compiler>
   </compiler>
+  <theme themeIsDefault="false" themeIsSDK="true" themeLocation="${SDK_THEMES_DIR}/samples/themes/spark_graphite"/>
   <applications>
   <applications>
     <application path="Main.mxml"/>
     <application path="Main.mxml"/>
   </applications>
   </applications>

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

@@ -65,7 +65,13 @@ package
 			else if (cmd == "source-loc")
 			else if (cmd == "source-loc")
 			{
 			{
 				m_InstructionPtrHighlight = parseHighlight(xml);
 				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")
 			else if (cmd == "callstack")
 			{
 			{
@@ -165,7 +171,12 @@ package
 		{
 		{
 			m_Socket.send(<Command cmd="stepIn" />);		
 			m_Socket.send(<Command cmd="stepIn" />);		
 		}
 		}
-
+		
+		public function stepOut() : void
+		{
+			m_Socket.send(<Command cmd="stepOut" />);		
+		}
+		
 		public function stepOver() : void
 		public function stepOver() : void
 		{
 		{
 			m_Socket.send(<Command cmd="stepOver" />);		
 			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 s "library://ns.adobe.com/flex/spark";
 @namespace mx "library://ns.adobe.com/flex/mx";
 @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
 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;
 	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:s="library://ns.adobe.com/flex/spark" 
 			   xmlns:mx="library://ns.adobe.com/flex/mx" 
 			   xmlns:mx="library://ns.adobe.com/flex/mx" 
 			   minWidth="955" minHeight="600" width="100%" height="100%"
 			   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 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>
 	<fx:Script>
 		
 		
-		<![CDATA[ 
+		<![CDATA[
 			import flashx.textLayout.formats.TextLayoutFormat;
 			import flashx.textLayout.formats.TextLayoutFormat;
 			
 			
+			import mx.collections.XMLListCollection;
+			import mx.controls.Alert;
 			import mx.events.FlexEvent;
 			import mx.events.FlexEvent;
+			import mx.events.MenuEvent;
 			
 			
 			import spark.events.IndexChangeEvent;
 			import spark.events.IndexChangeEvent;
 			import spark.events.TextOperationEvent;
 			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; 
 			private var m_Debugger : DebuggerViewLogic; 
 			
 			
-			protected function application1_creationCompleteHandler(event:FlexEvent):void
+			protected function application_creationCompleteHandler(event:FlexEvent):void
 			{
 			{
 				m_Debugger = new DebuggerViewLogic(this);
 				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();
 				var hl:Highlight = m_Debugger.getInstructionPtrHighlight();
 				
 				
-				if (hl !== null && hl.Source !== m_CurrentSrc)
+				if (switchToSource && hl !== null && hl.Source !== m_CurrentSrc)
 				{
 				{
 					selectSource(hl.Source);
 					selectSource(hl.Source);
 				}
 				}
 				
 				
 				var tlf:TextLayoutFormat = new TextLayoutFormat();
 				var tlf:TextLayoutFormat = new TextLayoutFormat();
-				tlf.backgroundColor = 0xFFFFFF;
+				tlf.backgroundColor = 0x444444;
 				
 				
 				txtCode.setFormatOfRange(tlf, 0, txtCode.text.length - 1);
 				txtCode.setFormatOfRange(tlf, 0, txtCode.text.length - 1);
 				
 				
 				if (hl !== null && hl.Source === m_CurrentSrc)
 				if (hl !== null && hl.Source === m_CurrentSrc)
 				{
 				{
 					var tlf2:TextLayoutFormat = new TextLayoutFormat();
 					var tlf2:TextLayoutFormat = new TextLayoutFormat();
-					tlf2.backgroundColor = 0x0080FF;
+					tlf2.backgroundColor = 0xb1aefa;
 					
 					
 					txtCode.setFormatOfRange(tlf2, hl.From, hl.To);
 					txtCode.setFormatOfRange(tlf2, hl.From, hl.To);
 				}
 				}
@@ -97,6 +129,7 @@
 				var S : SourceCode = (SourceCode)(lstSources.selectedItem);
 				var S : SourceCode = (SourceCode)(lstSources.selectedItem);
 				txtCode.text = S.getText();
 				txtCode.text = S.getText();
 				m_CurrentSrc = S;
 				m_CurrentSrc = S;
+				refreshInstructionPtrHighlight(false);
 			}
 			}
 			
 			
 			protected function getSourceName(o : Object) : String
 			protected function getSourceName(o : Object) : String
@@ -107,7 +140,7 @@
 			
 			
 			public function welcome(appName : String, ver : String): void
 			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
 			protected function btnRemoveWatch_clickHandler(event:MouseEvent):void
@@ -141,6 +174,16 @@
 				textOutput.scrollToRange(int.MAX_VALUE, int.MAX_VALUE);
 				textOutput.scrollToRange(int.MAX_VALUE, int.MAX_VALUE);
 			}
 			}
 			
 			
+			protected function txtCode_changingHandler(event:TextOperationEvent):void
+			{
+				event.preventDefault();
+			}
+			
+			protected function toggleBreakpoint() : void
+			{
+				
+			}
+			
 		]]>
 		]]>
 	</fx:Script> 
 	</fx:Script> 
 	
 	
@@ -148,15 +191,30 @@
 		<!-- Place non-visual elements (e.g., services, value objects) here -->
 		<!-- Place non-visual elements (e.g., services, value objects) here -->
 	
 	
 	</fx:Declarations>
 	</fx:Declarations>
-	<s:Panel id="titleBar" width="100%" height="100%" title="MoonSharp Remote Debugger - Connecting...">
 		<mx:VBox width="100%" height="100%">
 		<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:HBox>
 			
 			
 			<mx:HDividedBox width="100%" height="100%" liveDragging="true">
 			<mx:HDividedBox width="100%" height="100%" liveDragging="true">
@@ -164,8 +222,8 @@
 					<s:Panel title="Watches" width="100%" height="50%">
 					<s:Panel title="Watches" width="100%" height="50%">
 						<mx:VBox width="100%"  height="100%">
 						<mx:VBox width="100%"  height="100%">
 							<mx:HBox width="100%" paddingTop="4" paddingLeft="4">
 							<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>
 							</mx:HBox>
 							<s:DataGrid id="gridWatches" width="100%" height="100%" selectionMode="multipleRows">
 							<s:DataGrid id="gridWatches" width="100%" height="100%" selectionMode="multipleRows">
 								<s:columns>
 								<s:columns>
@@ -200,17 +258,16 @@
 							</mx:HBox>
 							</mx:HBox>
 							
 							
 							<s:Scroller width="100%"  height="100%">  
 							<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>
 							</s:Scroller>
 						</mx:VBox>
 						</mx:VBox>
 					</s:Panel>
 					</s:Panel>
 					<s:Panel id="outputBox" width="100%" height="30%" title="Output">
 					<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>
 					</s:Panel>
 			</mx:VDividedBox>
 			</mx:VDividedBox>
 				
 				
 			</mx:HDividedBox>
 			</mx:HDividedBox>
 			
 			
 		</mx:VBox>
 		</mx:VBox>
-	</s:Panel>
 </s:Application>
 </s:Application>

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

@@ -192,12 +192,12 @@ namespace MoonSharp.Debugger
 
 
 		private void StepIN()
 		private void StepIN()
 		{
 		{
-			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepIn });
+			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.ByteCodeStepIn });
 		}
 		}
 
 
 		private void StepOVER()
 		private void StepOVER()
 		{
 		{
-			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOver });
+			DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.ByteCodeStepOver });
 		}
 		}
 
 
 		private void GO()
 		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)
 			if (watchType == WatchType.CallStack)
 				m_Ctx.Post(UpdateCallStack, items);
 				m_Ctx.Post(UpdateCallStack, items);
@@ -217,7 +217,7 @@ namespace MoonSharp.Debugger
 		}
 		}
 		void UpdateVStack(object o)
 		void UpdateVStack(object o)
 		{
 		{
-			List<WatchItem> items = (List<WatchItem>)o;
+			IEnumerable<WatchItem> items = (IEnumerable<WatchItem>)o;
 
 
 			lvVStack.BeginUpdate();
 			lvVStack.BeginUpdate();
 			lvVStack.Items.Clear();
 			lvVStack.Items.Clear();
@@ -238,7 +238,7 @@ namespace MoonSharp.Debugger
 
 
 		void UpdateWatches(object o)
 		void UpdateWatches(object o)
 		{
 		{
-			List<WatchItem> items = (List<WatchItem>)o;
+			IEnumerable<WatchItem> items = (IEnumerable<WatchItem>)o;
 
 
 			lvWatches.BeginUpdate();
 			lvWatches.BeginUpdate();
 			lvWatches.Items.Clear();
 			lvWatches.Items.Clear();
@@ -259,7 +259,7 @@ namespace MoonSharp.Debugger
 
 
 		void UpdateCallStack(object o)
 		void UpdateCallStack(object o)
 		{
 		{
-			List<WatchItem> items = (List<WatchItem>)o;
+			IEnumerable<WatchItem> items = (IEnumerable<WatchItem>)o;
 
 
 			lvCallStack.BeginUpdate();
 			lvCallStack.BeginUpdate();
 			lvCallStack.Items.Clear();
 			lvCallStack.Items.Clear();
@@ -416,5 +416,15 @@ namespace MoonSharp.Debugger
 		{
 		{
 			return false;
 			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
 		public enum ActionType
 		{
 		{
+			ByteCodeStepIn,
+			ByteCodeStepOver,
+			ByteCodeStepOut,
 			StepIn,
 			StepIn,
 			StepOver,
 			StepOver,
+			StepOut,
 			Run,
 			Run,
 			ToggleBreakpoint,
 			ToggleBreakpoint,
 			Refresh,
 			Refresh,
+			HardRefresh,
 			None,
 			None,
 		}
 		}
 
 
-		public int InstructionPtr { get; set; }
 		public ActionType Action { get; set; }
 		public ActionType Action { get; set; }
 		public DateTime TimeStampUTC { get; private set; }
 		public DateTime TimeStampUTC { get; private set; }
 
 
+		public int SourceID { get; set; }
+		public int SourceLine { get; set; }
+		public int SourceCol { get; set; }
+
 		public DebuggerAction()
 		public DebuggerAction()
 		{
 		{
 			TimeStampUTC = DateTime.UtcNow;
 			TimeStampUTC = DateTime.UtcNow;
@@ -31,7 +39,14 @@ namespace MoonSharp.Interpreter.Debugging
 
 
 		public override string ToString()
 		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);
 		void SetByteCode(string[] byteCode);
 		bool IsPauseRequested();
 		bool IsPauseRequested();
 		DebuggerAction GetAction(int ip, SourceRef sourceref);
 		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();
 		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 string[] Lines { get; private set; }
 		public Script OwnerScript { get; private set; }
 		public Script OwnerScript { get; private set; }
 		public int SourceID { 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)
 		internal SourceCode(string name, string code, int sourceID, Script ownerScript)
 		{
 		{
+			Refs = new List<SourceRef>();
+
 			List<string> lines = new List<string>();
 			List<string> lines = new List<string>();
 
 
 			Name = name;
 			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 int ToLine { get; private set; }
 		public bool IsStepStop { 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)
 		internal SourceRef(int sourceIdx, int from, int to, int fromline, int toline, bool isStepStop)
 		{
 		{
 			SourceIdx = sourceIdx;
 			SourceIdx = sourceIdx;
@@ -24,10 +26,6 @@ namespace MoonSharp.Interpreter.Debugging
 			IsStepStop = isStepStop;
 			IsStepStop = isStepStop;
 		}
 		}
 
 
-		public SourceRef(int sourceIdx)
-			: this(sourceIdx, 0, int.MaxValue, 0, 0, true)
-		{
-		}
 
 
 		public override string ToString()
 		public override string ToString()
 		{
 		{
@@ -36,5 +34,22 @@ namespace MoonSharp.Interpreter.Debugging
 				FromLine, FromChar,
 				FromLine, FromChar,
 				ToLine, ToChar);
 				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 BuildTimeScope Scope { get; set; }
 		public SourceCode Source { 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)
 		public void Emit_Debug(string str)
 		{
 		{
 			AppendInstruction(new Instruction(m_CurrentSourceRef) { OpCode = OpCode.Debug, Name = str.Substring(0, Math.Min(32, str.Length)) });
 			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 DynValue Value;
 		public int NumVal;
 		public int NumVal;
 		public int NumVal2;
 		public int NumVal2;
-		public bool Breakpoint;
 		public SourceRef SourceCodeRef;
 		public SourceRef SourceCodeRef;
 
 
 		public Instruction(SourceRef sourceref)
 		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 IDebugger DebuggerAttached = null;
 			public DebuggerAction.ActionType DebuggerCurrentAction = DebuggerAction.ActionType.None;
 			public DebuggerAction.ActionType DebuggerCurrentAction = DebuggerAction.ActionType.None;
 			public int DebuggerCurrentActionTarget = -1;
 			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.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
+using System.Threading;
 using MoonSharp.Interpreter.DataStructs;
 using MoonSharp.Interpreter.DataStructs;
 using MoonSharp.Interpreter.Debugging;
 using MoonSharp.Interpreter.Debugging;
 
 
@@ -45,21 +46,30 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 
 		public DynValue Call(DynValue function, DynValue[] args)
 		public DynValue Call(DynValue function, DynValue[] args)
 		{
 		{
-			var stopwatch = this.m_Script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Execution);
-
-			m_CanYield = false;
+			EnterProcessor();
 
 
 			try
 			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
 			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)
 		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;
 			m_Debug.DebuggerAttached = debugger;
 		}
 		}
 
 
+
+
 		private void ListenDebugger(Instruction instr, int instructionPtr)
 		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.DebuggerCurrentAction = DebuggerAction.ActionType.None;
 				m_Debug.DebuggerCurrentActionTarget = -1;
 				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;
 					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)
 			while (true)
 			{
 			{
@@ -41,11 +57,19 @@ namespace MoonSharp.Interpreter.Execution.VM
 				switch (action.Action)
 				switch (action.Action)
 				{
 				{
 					case DebuggerAction.ActionType.StepIn:
 					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;
 						m_Debug.DebuggerCurrentActionTarget = -1;
 						return;
 						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;
 						m_Debug.DebuggerCurrentActionTarget = instructionPtr + 1;
 						return;
 						return;
 					case DebuggerAction.ActionType.Run:
 					case DebuggerAction.ActionType.Run:
@@ -53,10 +77,14 @@ namespace MoonSharp.Interpreter.Execution.VM
 						m_Debug.DebuggerCurrentActionTarget = -1;
 						m_Debug.DebuggerCurrentActionTarget = -1;
 						return;
 						return;
 					case DebuggerAction.ActionType.ToggleBreakpoint:
 					case DebuggerAction.ActionType.ToggleBreakpoint:
-						m_RootChunk.Code[action.InstructionPtr].Breakpoint = !m_RootChunk.Code[action.InstructionPtr].Breakpoint;
+						ToggleBreakPoint(action);
+						RefreshDebugger(true);
 						break;
 						break;
 					case DebuggerAction.ActionType.Refresh:
 					case DebuggerAction.ActionType.Refresh:
-						RefreshDebugger();
+						RefreshDebugger(false);
+						break;
+					case DebuggerAction.ActionType.HardRefresh:
+						RefreshDebugger(true);
 						break;
 						break;
 					case DebuggerAction.ActionType.None:
 					case DebuggerAction.ActionType.None:
 					default:
 					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<string> watchList = m_Debug.DebuggerAttached.GetWatchItems();
 			List<WatchItem> callStack = Debugger_GetCallStack();
 			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.CallStack, callStack);
 			m_Debug.DebuggerAttached.Update(WatchType.Watches, watches);
 			m_Debug.DebuggerAttached.Update(WatchType.Watches, watches);
 			m_Debug.DebuggerAttached.Update(WatchType.VStack, vstack);
 			m_Debug.DebuggerAttached.Update(WatchType.VStack, vstack);
+
+			if (hard)
+				m_Debug.DebuggerAttached.RefreshBreakpoints(m_Debug.BreakPoints);
 		}
 		}
 
 
 		private List<WatchItem> Debugger_RefreshVStack()
 		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;
 				int beginIp = -1;
 
 
-				var srcref = new SourceRef(source.SourceID);
+				//var srcref = new SourceRef(source.SourceID);
 
 
 				using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Compilation))
 				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));
 					bytecode.Emit_Nop(string.Format("Begin chunk {0}", source.Name));
 					beginIp = bytecode.GetJumpPointForLastInstruction();
 					beginIp = bytecode.GetJumpPointForLastInstruction();
@@ -78,10 +78,10 @@ namespace MoonSharp.Interpreter.Tree
 
 
 				int beginIp = -1;
 				int beginIp = -1;
 
 
-				var srcref = new SourceRef(source.SourceID);
+				// var srcref = new SourceRef(source.SourceID);
 
 
 				using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.Compilation))
 				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));
 					bytecode.Emit_Nop(string.Format("Begin function {0}", source.Name));
 					beginIp = fndef.CompileBody(bytecode, 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)
 		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)
 		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, IToken token1, IToken token2 = null)
 		{
 		{
 			token2 = token2 ?? token1;
 			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)
 		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, ITerminalNode terminalNode)
@@ -50,6 +50,11 @@ namespace MoonSharp.Interpreter.Tree
 			return BuildSourceRef(lcontext, terminalNode.Symbol, terminalNode);
 			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
 	public class DebugServer : IDebugger
 	{
 	{
 		List<string> m_Watches = new List<string>();
 		List<string> m_Watches = new List<string>();
-		List<string> m_WatchesChanging = new List<string>();
+		HashSet<string> m_WatchesChanging = new HashSet<string>();
 		Utf8TcpServer m_Server;
 		Utf8TcpServer m_Server;
 		Script m_Script;
 		Script m_Script;
 		string m_AppName;
 		string m_AppName;
@@ -105,7 +105,7 @@ namespace MoonSharp.RemoteDebugger
 		string[] m_CachedWatches = new string[(int)WatchType.MaxValue];
 		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)
 			if (watchType != WatchType.CallStack && watchType != WatchType.Watches)
 				return;
 				return;
@@ -202,14 +202,7 @@ namespace MoonSharp.RemoteDebugger
 				{
 				{
 					Send(xw =>
 					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();
 					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)
 						lock (m_Lock)
 						{
 						{
@@ -228,6 +221,9 @@ namespace MoonSharp.RemoteDebugger
 						return da;
 						return da;
 					}
 					}
 
 
+					if (da.Action == DebuggerAction.ActionType.ToggleBreakpoint)
+						return da;
+
 					if (da.Age < TimeSpan.FromMilliseconds(100))
 					if (da.Age < TimeSpan.FromMilliseconds(100))
 						return da;
 						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)
 		void m_Server_DataReceived(object sender, Utf8TcpPeerEventArgs e)
 		{
 		{
 			XmlDocument xdoc = new XmlDocument();
 			XmlDocument xdoc = new XmlDocument();
@@ -267,9 +275,12 @@ namespace MoonSharp.RemoteDebugger
 					case "stepover":
 					case "stepover":
 						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOver });
 						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOver });
 						break;
 						break;
+					case "stepout":
+						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOut });
+						break;
 					case "addwatch":
 					case "addwatch":
 						lock (m_Lock)
 						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();
 						QueueRefresh();
 						break;
 						break;
@@ -296,7 +307,7 @@ namespace MoonSharp.RemoteDebugger
 				m_HostBusySent = true;
 				m_HostBusySent = true;
 			}
 			}
 
 
-			QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Refresh });
+			QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.HardRefresh });
 		}
 		}
 
 
 		private void SendMessage(string text)
 		private void SendMessage(string text)
@@ -316,7 +327,26 @@ namespace MoonSharp.RemoteDebugger
 
 
 		public bool IsPauseRequested()
 		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);
 				m_DbgS = new DebugServer("MoonSharp REPL interpreter", S, 20001, false);
 				S.AttachDebugger(m_DbgS);
 				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)
 		static void m_Server_DataReceivedAny(object sender, Utf8TcpPeerEventArgs e)