Browse Source

Dynamic Expressions, enhanced debugger

Xanathar 11 years ago
parent
commit
f55f263467
52 changed files with 1077 additions and 217 deletions
  1. 2 0
      LICENSE
  2. 1 0
      src/Flash/org.moonsharp.debugger.client/html-template/index.template.html
  3. 5 0
      src/Flash/org.moonsharp.debugger.client/src/AboutBox.mxml
  4. 39 4
      src/Flash/org.moonsharp.debugger.client/src/DebuggerViewLogic.as
  5. 5 0
      src/Flash/org.moonsharp.debugger.client/src/Main.css
  6. 247 107
      src/Flash/org.moonsharp.debugger.client/src/Main.mxml
  7. 34 2
      src/Flash/org.moonsharp.debugger.client/src/SourceCode.as
  8. 6 4
      src/MoonSharp.Debugger/MainForm.cs
  9. 1 1
      src/MoonSharp.Interpreter/Debugging/IDebugger.cs
  10. 61 0
      src/MoonSharp.Interpreter/Debugging/SourceRef.cs
  11. 1 0
      src/MoonSharp.Interpreter/Debugging/WatchItem.cs
  12. 16 0
      src/MoonSharp.Interpreter/Errors/DynamicExpressionException.cs
  13. 74 0
      src/MoonSharp.Interpreter/Execution/DynamicExpression.cs
  14. 33 2
      src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs
  15. 2 2
      src/MoonSharp.Interpreter/Execution/ScriptLoadingContext.cs
  16. 71 14
      src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs
  17. 18 15
      src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Scope.cs
  18. 10 0
      src/MoonSharp.Interpreter/Grammar/Lua.g4
  19. 3 0
      src/MoonSharp.Interpreter/MoonSharp.Interpreter.csproj
  20. 29 1
      src/MoonSharp.Interpreter/Script.cs
  21. 26 1
      src/MoonSharp.Interpreter/Tree/Antlr_Interface/Loader_Antlr.cs
  22. 6 0
      src/MoonSharp.Interpreter/Tree/Expression.cs
  23. 4 1
      src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs
  24. 139 7
      src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs
  25. 36 0
      src/MoonSharp.Interpreter/Tree/Expressions/DynamicExpression.cs
  26. 8 0
      src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs
  27. 4 1
      src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallChainExpression.cs
  28. 7 2
      src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs
  29. 10 0
      src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs
  30. 4 0
      src/MoonSharp.Interpreter/Tree/Expressions/LiteralExpression.cs
  31. 14 0
      src/MoonSharp.Interpreter/Tree/Expressions/PowerOperatorExpression.cs
  32. 27 2
      src/MoonSharp.Interpreter/Tree/Expressions/SymbolRefExpression.cs
  33. 5 0
      src/MoonSharp.Interpreter/Tree/Expressions/TableConstructor.cs
  34. 24 0
      src/MoonSharp.Interpreter/Tree/Expressions/UnaryOperatorExpression.cs
  35. 9 8
      src/MoonSharp.Interpreter/Tree/NodeBase.cs
  36. 1 1
      src/MoonSharp.Interpreter/Tree/NodeFactory.cs
  37. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs
  38. 1 1
      src/MoonSharp.Interpreter/Tree/Statements/BreakStatement.cs
  39. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/ForEachLoopStatement.cs
  40. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/ForLoopStatement.cs
  41. 1 1
      src/MoonSharp.Interpreter/Tree/Statements/FunctionCallStatement.cs
  42. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/FunctionDefinitionStatement.cs
  43. 3 3
      src/MoonSharp.Interpreter/Tree/Statements/IfStatement.cs
  44. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/RepeatStatement.cs
  45. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/ReturnStatement.cs
  46. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/ScopeBlockStatement.cs
  47. 2 2
      src/MoonSharp.Interpreter/Tree/Statements/WhileStatement.cs
  48. 56 15
      src/MoonSharp.RemoteDebugger/DebugServer.cs
  49. 2 2
      src/MoonSharp/MoonSharp.csproj
  50. 16 4
      src/MoonSharp/Program.cs
  51. BIN
      src/MoonSharp/moonsharp.ico
  52. BIN
      src/MoonSharp/moonsharp256.ico

+ 2 - 0
LICENSE

@@ -10,6 +10,8 @@ Copyright (c) 2012 LoDC
 Debugger icons are from the Eclipse project (https://www.eclipse.org/).
 Debugger icons are from the Eclipse project (https://www.eclipse.org/).
 Copyright of The Eclipse Foundation
 Copyright of The Eclipse Foundation
 
 
+The MoonSharp icon is (c) Voontrag, 2014
+
 
 
 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:

+ 1 - 0
src/Flash/org.moonsharp.debugger.client/html-template/index.template.html

@@ -58,6 +58,7 @@
             // JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
             // JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
             swfobject.createCSS("#flashContent", "display:block;text-align:left;");
             swfobject.createCSS("#flashContent", "display:block;text-align:left;");
         </script>
         </script>
+       
     </head>
     </head>
     <body>
     <body>
         <!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough 
         <!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough 

+ 5 - 0
src/Flash/org.moonsharp.debugger.client/src/AboutBox.mxml

@@ -36,6 +36,8 @@
 					"Debugger icons are from the Eclipse project (https://www.eclipse.org/).\n"+ 
 					"Debugger icons are from the Eclipse project (https://www.eclipse.org/).\n"+ 
 					"Copyright of The Eclipse Foundation\n"+ 
 					"Copyright of The Eclipse Foundation\n"+ 
 					"\n"+ 
 					"\n"+ 
+					"The MoonSharp icon is (c) Voontrag, 2014\n" +
+					"\n"+
 					"\n"+ 
 					"\n"+ 
 					"Redistribution and use in source and binary forms, with or without\n"+ 
 					"Redistribution and use in source and binary forms, with or without\n"+ 
 					"modification, are permitted provided that the following conditions are met:\n"+ 
 					"modification, are permitted provided that the following conditions are met:\n"+ 
@@ -85,5 +87,8 @@
 	<s:Label id="lblVersion" x="19" y="46" text="Version x.xx.xxxx"/>
 	<s:Label id="lblVersion" x="19" y="46" text="Version x.xx.xxxx"/>
 	<s:Label x="19" y="66" text="(C) Marco Mastropaolo 2014 - Released under BSD license"/>
 	<s:Label x="19" y="66" text="(C) Marco Mastropaolo 2014 - Released under BSD license"/>
 	<mx:LinkButton x="10" y="81" label="http://www.moonsharp.org" click="navigateToURL(new URLRequest('http://www.moonsharp.org/'), '_blank');"/>
 	<mx:LinkButton x="10" y="81" label="http://www.moonsharp.org" click="navigateToURL(new URLRequest('http://www.moonsharp.org/'), '_blank');"/>
+	<s:Image x="528" y="10" width="100" height="98" scaleMode="stretch" smooth="true"
+			 smoothingQuality="high" source="@Embed('assets/moonsharp.png')"/>
+	
 	<!-- <s:SWFLoader x="59" y="24" width="128" height="128" source="../icons/app/icon128.png"/> -->
 	<!-- <s:SWFLoader x="59" y="24" width="128" height="128" source="../icons/app/icon128.png"/> -->
 </s:TitleWindow>
 </s:TitleWindow>

+ 39 - 4
src/Flash/org.moonsharp.debugger.client/src/DebuggerViewLogic.as

@@ -87,6 +87,10 @@ package
 			{
 			{
 				logMessage(xml.toString());	
 				logMessage(xml.toString());	
 			}
 			}
+			else if (cmd == "breakpoints")
+			{
+				refreshBreakpoints(xml);
+			}
 		}
 		}
 		
 		
 		public function getInstructionPtrHighlight():Highlight
 		public function getInstructionPtrHighlight():Highlight
@@ -129,7 +133,7 @@ package
 			}
 			}
 			else
 			else
 			{
 			{
-				trace("defaulting to default highlight...");
+				logMessage("ERROR: Highlighted source " + srcid.toString() + " not found in sources list.");
 				return null;	
 				return null;	
 			}
 			}
 		}
 		}
@@ -160,8 +164,24 @@ package
 		
 		
 		private function securityErrorHandler(event:SecurityErrorEvent):void {
 		private function securityErrorHandler(event:SecurityErrorEvent):void {
 			onFatalError("IO Error : " + event.text);
 			onFatalError("IO Error : " + event.text);
-		}				
-	
+		}			
+		
+		private function refreshBreakpoints(xml : XML): void
+		{
+			for(var i:int = 0; i < m_SourceList.length; i++)
+				m_SourceList.getItemAt(i).Breakpoints= new Vector.<Highlight>();
+			
+			for each(var x:XML in xml.elements())
+			{
+				var hl:Highlight = parseHighlight(x);
+				
+				if (hl != null)
+					hl.Source.Breakpoints.push(hl);	
+			}
+			
+			m_View.refreshBreakpoints();
+		}
+		
 		public function refresh() : void
 		public function refresh() : void
 		{
 		{
 			m_Socket.send(<Command cmd="refresh" />);		
 			m_Socket.send(<Command cmd="refresh" />);		
@@ -187,6 +207,11 @@ package
 			m_Socket.send(<Command cmd="run" />);		
 			m_Socket.send(<Command cmd="run" />);		
 		}
 		}
 		
 		
+		public function pause() : void
+		{
+			m_Socket.send(<Command cmd="pause" />);		
+		}
+		
 		public function addWatch(varNames : String) : void
 		public function addWatch(varNames : String) : void
 		{
 		{
 			var cmd:XML = <Command cmd="addWatch" />;
 			var cmd:XML = <Command cmd="addWatch" />;
@@ -199,7 +224,17 @@ package
 			var cmd:XML = <Command cmd="delWatch" />;
 			var cmd:XML = <Command cmd="delWatch" />;
 			cmd.@arg = varNames;
 			cmd.@arg = varNames;
 			m_Socket.send(cmd);			
 			m_Socket.send(cmd);			
-		}		
+		}	
+		
+		
+		public function toggleBreakpoint(src:int, line:int, col:int) : void
+		{
+			var cmd:XML = <Command cmd="breakpoint" arg="toggle" />;
+			cmd.@src = src;
+			cmd.@line = line;
+			cmd.@col = col;
+			m_Socket.send(cmd);		
+		}	
 		
 		
 	}
 	}
 }
 }

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

@@ -96,6 +96,8 @@ s|Panel,mx|TitleWindow
 s|TextArea
 s|TextArea
 {
 {
 	color: #CCCCCC;
 	color: #CCCCCC;
+	background-color: #555555;
+	contentBackgroundColor: #555555;
 }
 }
 
 
 s|Panel
 s|Panel
@@ -147,3 +149,6 @@ mx|MenuBar
 	roll-over-color: #B1AEFA;
 	roll-over-color: #B1AEFA;
 }
 }
 
 
+
+
+

+ 247 - 107
src/Flash/org.moonsharp.debugger.client/src/Main.mxml

@@ -8,7 +8,7 @@
 			   >
 			   >
 	<fx:Style source="MXFTEText.css"/>
 	<fx:Style source="MXFTEText.css"/>
 	<fx:Style source="Main.css"/>
 	<fx:Style source="Main.css"/>
-
+	
 	<fx:Script>
 	<fx:Script>
 		
 		
 		<![CDATA[
 		<![CDATA[
@@ -19,26 +19,43 @@
 			import mx.events.FlexEvent;
 			import mx.events.FlexEvent;
 			import mx.events.MenuEvent;
 			import mx.events.MenuEvent;
 			
 			
+			import spark.components.TextSelectionHighlighting;
 			import spark.events.IndexChangeEvent;
 			import spark.events.IndexChangeEvent;
 			import spark.events.TextOperationEvent;
 			import spark.events.TextOperationEvent;
-
+			
 			[Bindable]
 			[Bindable]
 			public var menuBarCollection:XMLListCollection;
 			public var menuBarCollection:XMLListCollection;
 			
 			
+			[Bindable][Embed (source="assets/stepin.gif" )] public var  stepin:Class;
+			[Bindable][Embed (source="assets/stepout.gif" )] public var  stepout:Class;
+			[Bindable][Embed (source="assets/stepover.gif" )] public var  stepover:Class;
+
+			[Bindable][Embed (source="assets/run.gif" )] public var  run:Class;
+			[Bindable][Embed (source="assets/pause.gif" )] public var  pause:Class;
+
+			[Bindable][Embed (source="assets/add.gif" )] public var add:Class;
+			[Bindable][Embed (source="assets/breakpoint.gif" )] public var  breakpoint:Class;
+			[Bindable][Embed (source="assets/remove.gif" )] public var  remove:Class;
+			[Bindable][Embed (source="assets/step_current.gif" )] public var  step_current:Class;
+			
+			
 			private var menubarXML:XMLList =
 			private var menubarXML:XMLList =
 				<>
 				<>
 					<menuitem label="Debug" data="top">
 					<menuitem label="Debug" data="top">
-						<menuitem label="Step In - F11" data="1A" icon="@Embed('assets/stepin.gif')"/>
-						<menuitem label="Step Over" data="1B"/>
+						<menuitem label="(I) - Step In" data="stepin" icon="stepin"/>
+						<menuitem label="(O) - Step Over" data="stepover" icon="stepover"/>
+						<menuitem label="(U) - Step Out" data="stepout" icon="stepout"/>
+						<menuitem type="separator"/>
+						<menuitem label="(R) - Run" data="run" icon="run" />
+						<menuitem label="(P) - Pause" data="pause" icon="pause" />
 						<menuitem type="separator"/>
 						<menuitem type="separator"/>
-						<menuitem label="Run" data="1B"/>
-						<menuitem label="Pause" data="1B"/>
+						<menuitem label="(B) - Toggle breakpoint" data="breakpoint" icon="breakpoint" />
 						<menuitem type="separator"/>
 						<menuitem type="separator"/>
-						<menuitem label="Toggle breakpoint" data="1B"/>
+						<menuitem label="(G) - Go to current" data="step_current" icon="step_current" />
 					</menuitem>
 					</menuitem>
 					<menuitem label="Watches" data="top">
 					<menuitem label="Watches" data="top">
-						<menuitem label="Add..." data="1A"/>
-						<menuitem label="Remove" data="1B"/>
+						<menuitem label="(Ins) - Add..." data="add" icon="add" />
+						<menuitem label="(Del) - Remove" data="remove" icon="remove" />
 					</menuitem>
 					</menuitem>
 					<menuitem label="Help" data="top">
 					<menuitem label="Help" data="top">
 						<menuitem label="About..." data="about"/>
 						<menuitem label="About..." data="about"/>
@@ -53,8 +70,7 @@
 			{
 			{
 				var cmd : String = evt.item.@data; 
 				var cmd : String = evt.item.@data; 
 				
 				
-				if (cmd == "top") return;
-				else if (cmd == "about") AboutBox.show(this); 
+				if (cmd != "top") exec(cmd);
 			}
 			}
 			
 			
 			
 			
@@ -63,6 +79,43 @@
 			protected function application_creationCompleteHandler(event:FlexEvent):void
 			protected function application_creationCompleteHandler(event:FlexEvent):void
 			{
 			{
 				m_Debugger = new DebuggerViewLogic(this);
 				m_Debugger = new DebuggerViewLogic(this);
+				systemManager.addEventListener(KeyboardEvent.KEY_UP, shortcutListener, true);   
+			}
+			
+			private function shortcutListener(e:KeyboardEvent):void
+			{
+				switch(e.keyCode)
+				{
+					case 73:
+						exec("stepin");
+						break;
+					case 79:
+						exec("stepover");
+						break;
+					case 85:
+						exec("stepout");
+						break;
+					case 82:
+						exec("run");
+						break;
+					case 80:
+						exec("pause");
+						break;
+					case 66:
+						exec("breakpoint");
+						break;
+					case 71:
+						exec("step_current");
+						break;
+					case 45:
+						exec("add");
+						break;
+					case 46:
+						exec("remove");
+						break;
+				}
+				
+				
 			}
 			}
 			
 			
 			public function refreshSourceCode(s : SourceCode, l : ArrayList) : void
 			public function refreshSourceCode(s : SourceCode, l : ArrayList) : void
@@ -103,6 +156,26 @@
 					tlf2.backgroundColor = 0xb1aefa;
 					tlf2.backgroundColor = 0xb1aefa;
 					
 					
 					txtCode.setFormatOfRange(tlf2, hl.From, hl.To);
 					txtCode.setFormatOfRange(tlf2, hl.From, hl.To);
+					moveCaret(hl.To);
+				}
+			}
+			
+			public function refreshBreakpoints() : void
+			{
+				if (m_CurrentSrc == null) return;
+				
+				var tlf:TextLayoutFormat = new TextLayoutFormat();
+				tlf.color = 0xEEEEEE;
+				
+				txtCode.setFormatOfRange(tlf, 0, txtCode.text.length - 1);
+				
+				var tlf2:TextLayoutFormat = new TextLayoutFormat();
+				tlf2.color = 0xff0000;
+				
+				for(var i:int = 0; i < m_CurrentSrc.Breakpoints.length; i++)
+				{
+					var hl:Highlight =  m_CurrentSrc.Breakpoints[i];
+					txtCode.setFormatOfRange(tlf2, hl.From, hl.To);
 				}
 				}
 			}
 			}
 			
 			
@@ -130,6 +203,8 @@
 				txtCode.text = S.getText();
 				txtCode.text = S.getText();
 				m_CurrentSrc = S;
 				m_CurrentSrc = S;
 				refreshInstructionPtrHighlight(false);
 				refreshInstructionPtrHighlight(false);
+				refreshBreakpoints();
+				updateCaretLabel();
 			}
 			}
 			
 			
 			protected function getSourceName(o : Object) : String
 			protected function getSourceName(o : Object) : String
@@ -143,131 +218,196 @@
 				titleBar.text = "MoonSharp Remote Debugger - [" + appName + "] - v" + ver;
 				titleBar.text = "MoonSharp Remote Debugger - [" + appName + "] - v" + ver;
 			}
 			}
 			
 			
-			protected function btnRemoveWatch_clickHandler(event:MouseEvent):void
+			public function appendMessage(text : String) : void
 			{
 			{
-				var str:String = "";
+				textOutput.text += text + "\n";
+				textOutput.scrollToRange(int.MAX_VALUE, int.MAX_VALUE);
+			}
+			
+			protected function txtCode_changingHandler(event:TextOperationEvent):void
+			{
+				event.preventDefault();
+			}
+			
+			protected function toggleBreakpoint() : void
+			{
+				if (m_CurrentSrc == null) return;
 				
 				
-				for each(var wi:WatchItem in gridWatches.selectedItems)
-				{
-					if (str.length > 0)
-						str += ",";
-					
-					str += wi.Name;	
-				}
+				var cursor:int = txtCode.selectionActivePosition;
+				var line:int = m_CurrentSrc.inflateLocationLine(cursor);
+				var col:int = m_CurrentSrc.inflateLocationColumn(cursor, line);
 				
 				
-				if (str.length > 0)
-					m_Debugger.removeWatch(str);
+				m_Debugger.toggleBreakpoint(m_CurrentSrc.getId(), line, col);
 			}
 			}
 			
 			
-			protected function btnAddWatch_clickHandler(event:MouseEvent):void
+			protected function moveCaret(where : int) : void
 			{
 			{
-				InputBox.show(this, "Add watch...", "Enter the name of the variables you want to watch, separated by ',' if more than one is desired", "", function(str:String):void
-				{
-					if (str !== null && str !== "")
-						m_Debugger.addWatch(str);
-				});
+				txtCode.setFocus();
+				txtCode.selectRange(where, where);
+				updateCaretLabel();
 			}
 			}
 			
 			
-			public function appendMessage(text : String) : void
+			protected function updateCaretLabel() : void
 			{
 			{
-				textOutput.text += text + "\n";
-				textOutput.scrollToRange(int.MAX_VALUE, int.MAX_VALUE);
+				if (m_CurrentSrc == null) return;
+
+				var cursor:int = txtCode.selectionActivePosition;
+				var line:int = m_CurrentSrc.inflateLocationLine(cursor);
+				var col:int = m_CurrentSrc.inflateLocationColumn(cursor, line);
+				
+				txtCaret.text = m_CurrentSrc.getName() + ":" + line.toString() + ","+col.toString();
 			}
 			}
 			
 			
-			protected function txtCode_changingHandler(event:TextOperationEvent):void
+			private function deepWatch() : void
 			{
 			{
-				event.preventDefault();
+				var wi:WatchItem = gridWatches.selectedItem as WatchItem;
+				
+				if (wi != null)
+				{
+					Alert.show("Value = " + wi.Value + "\n" + 
+						"Type = " + wi.Type + "\n" + 
+						"Scope = " + wi.LValue, wi.Name); 
+				}
 			}
 			}
 			
 			
-			protected function toggleBreakpoint() : void
+			
+			public function exec(cmd:String) : void
 			{
 			{
-				
+				if (cmd == "about") AboutBox.show(this);
+				else if (cmd == "stepin") m_Debugger.stepIn();
+				else if (cmd == "stepout") m_Debugger.stepOut();
+				else if (cmd == "stepover") m_Debugger.stepOver();
+				else if (cmd == "run") m_Debugger.run();
+				else if (cmd == "pause") m_Debugger.pause();
+				else if (cmd == "step_current") refreshInstructionPtrHighlight(true);
+				else if (cmd == "breakpoint") toggleBreakpoint();
+				else if (cmd == "expand") deepWatch();
+				else if (cmd == "add") 
+				{
+					InputBox.show(this, "Add watch...", "Enter the name of the variables you want to watch, separated by ',' if more than one is desired", "", function(str:String):void
+					{
+						if (str !== null && str !== "")
+							m_Debugger.addWatch(str);
+					});
+				}
+				else if (cmd == "remove") 
+				{
+					var str:String = "";
+					
+					for each(var wi:WatchItem in gridWatches.selectedItems)
+					{
+						if (str.length > 0)
+							str += ",";
+						
+						str += wi.Name;	
+					}
+					
+					if (str.length > 0)
+						m_Debugger.removeWatch(str);
+				}
+				else
+				{
+					Alert.show("Unknown command " + cmd, "Error", Alert.OK, this);
+				}
 			}
 			}
+				
+			
+			
+			
 			
 			
 		]]>
 		]]>
 	</fx:Script> 
 	</fx:Script> 
 	
 	
 	<fx:Declarations>
 	<fx:Declarations>
 		<!-- Place non-visual elements (e.g., services, value objects) here -->
 		<!-- Place non-visual elements (e.g., services, value objects) here -->
-	
+		
 	</fx:Declarations>
 	</fx:Declarations>
-		<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="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">
-				<mx:VDividedBox width="30%" height="100%">
-					<s:Panel title="Watches" width="100%" height="50%">
-						<mx:VBox width="100%"  height="100%">
-							<mx:HBox width="100%" paddingTop="4" paddingLeft="4">
-								<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>
-									<s:ArrayList>
-										<s:GridColumn dataField="Name" headerText="Name" ></s:GridColumn>
-										<s:GridColumn dataField="Value" headerText="Value" ></s:GridColumn>
-										<s:GridColumn dataField="Type" headerText="Type" ></s:GridColumn>
-										<s:GridColumn dataField="LValue" headerText="Scope" ></s:GridColumn>
-									</s:ArrayList>
-								</s:columns>
-							</s:DataGrid>
-						</mx:VBox>
-					</s:Panel>				
-					<s:Panel title="Stack" width="100%" height="50%">
-						<s:DataGrid id="gridStack" width="100%" height="100%" sortableColumns="false">
+	<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="0" paddingLeft="4">
+			<s:Button height="20" label="Step in" click="exec('stepin');" icon="{stepin}"/> 
+			<s:Button height="20" label="Step out" click="exec('stepout');" icon="{stepout}"/> 
+			<s:Button height="20" label="Step over" click="exec('stepover');" icon="{stepover}"/>
+			<s:Button height="20" label="Run" click="exec('run');" icon="{run}"/>
+			<s:Button height="20" label="Pause" click="exec('pause');" icon="{pause}"/>
+			<s:Button height="20" label="Go to current" click="exec('step_current');" icon="{step_current}"/> 
+			<s:Button height="20" label="Toggle breakpoint"  icon="{breakpoint}" click="exec('breakpoint');"/> 
+		</mx:HBox>
+		
+		<mx:HDividedBox width="100%" height="100%" liveDragging="true">
+			<mx:VDividedBox width="30%" height="100%">
+				<s:Panel title="Watches" width="100%" height="50%">
+					<mx:VBox width="100%"  height="100%">
+						<mx:HBox width="100%" paddingTop="4" paddingLeft="4">
+							<s:Button height="20" id="btnAddWatch" label="Add" click="exec('add');" icon="{add}"/>
+							<s:Button height="20" id="btnRemoveWatch" label="Remove" click="exec('remove');" icon="{remove}"/>
+							<s:Button height="20" id="btnExpand" label="Expand" click="exec('expand');" />
+						</mx:HBox>
+						<s:DataGrid id="gridWatches" width="100%" height="100%" selectionMode="multipleRows">
 							<s:columns>
 							<s:columns>
 								<s:ArrayList>
 								<s:ArrayList>
-									<s:GridColumn dataField="Address" headerText="Address" ></s:GridColumn>
 									<s:GridColumn dataField="Name" headerText="Name" ></s:GridColumn>
 									<s:GridColumn dataField="Name" headerText="Name" ></s:GridColumn>
-									<s:GridColumn dataField="RetAddress" headerText="Return" ></s:GridColumn>
-									<s:GridColumn dataField="BasePtr" headerText="Base Ptr" ></s:GridColumn>
+									<s:GridColumn dataField="Value" headerText="Value" ></s:GridColumn>
+									<s:GridColumn dataField="Type" headerText="Type" ></s:GridColumn>
+									<s:GridColumn dataField="LValue" headerText="Scope" ></s:GridColumn>
 								</s:ArrayList>
 								</s:ArrayList>
 							</s:columns>
 							</s:columns>
 						</s:DataGrid>
 						</s:DataGrid>
-					</s:Panel>
-				</mx:VDividedBox>
-				<mx:VDividedBox width="70%" height="100%">
-					<s:Panel id="codeBox" width="100%" height="70%" title="Code">
-						<mx:VBox width="100%"  height="100%">
-							<mx:HBox width="100%">
-								<s:DropDownList width="100%" id="lstSources" change="lstSources_changeHandler(event)" labelFunction="getSourceName" />
-							</mx:HBox>
-							
-							<s:Scroller width="100%"  height="100%">  
-								<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%" editable="false" /> 
-					</s:Panel>
+					</mx:VBox>
+				</s:Panel>				
+				<s:Panel title="Stack" width="100%" height="50%">
+					<s:DataGrid id="gridStack" width="100%" height="100%" sortableColumns="false">
+						<s:columns>
+							<s:ArrayList>
+								<s:GridColumn dataField="Address" headerText="Address" ></s:GridColumn>
+								<s:GridColumn dataField="Name" headerText="Name" ></s:GridColumn>
+								<s:GridColumn dataField="RetAddress" headerText="Return" ></s:GridColumn>
+								<s:GridColumn dataField="BasePtr" headerText="Base Ptr" ></s:GridColumn>
+							</s:ArrayList>
+						</s:columns>
+					</s:DataGrid>
+				</s:Panel>
+			</mx:VDividedBox>
+			<mx:VDividedBox width="70%" height="100%">
+				<s:Panel id="codeBox" width="100%" height="70%" title="Code">
+					<mx:VBox width="100%"  height="100%">
+						<mx:HBox width="100%">
+							<s:DropDownList width="100%" id="lstSources" change="lstSources_changeHandler(event)" labelFunction="getSourceName" />
+						</mx:HBox>
+						
+						<s:Scroller width="100%"  height="100%">  
+							<s:RichEditableText id="txtCode" width="100%" backgroundColor="0x444444"  height="100%" 
+												fontFamily="UbuntuMono" fontSize="14"  editable="true" 
+												selectionHighlighting="always"
+												selectionChange="updateCaretLabel();"
+												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%" editable="false"  /> 
+				</s:Panel>
 			</mx:VDividedBox>
 			</mx:VDividedBox>
-				
-			</mx:HDividedBox>
 			
 			
-		</mx:VBox>
+		</mx:HDividedBox>
+		
+		<mx:HBox height="24" paddingTop="4" paddingLeft="8">
+			<s:Label id="txtCaret" verticalAlign="middle" />
+		</mx:HBox>
+		
+	</mx:VBox>
 </s:Application>
 </s:Application>

+ 34 - 2
src/Flash/org.moonsharp.debugger.client/src/SourceCode.as

@@ -8,7 +8,7 @@ package
 		private var m_Text : String;
 		private var m_Text : String;
 		private var m_CumulativeLength : Vector.<int> = new Vector.<int>();
 		private var m_CumulativeLength : Vector.<int> = new Vector.<int>();
 		
 		
-	
+		public var Breakpoints : Vector.<Highlight> = new Vector.<Highlight>();
 		
 		
 		public function SourceCode(xml: XML)
 		public function SourceCode(xml: XML)
 		{
 		{
@@ -47,5 +47,37 @@ package
 			return m_CumulativeLength[line] + col;
 			return m_CumulativeLength[line] + col;
 		}
 		}
 		
 		
+		
+		public function inflateLocationLine(pos : int) : int 
+		{
+			for(var line:int = 0; line < m_CumulativeLength.length; line++)
+			{
+				if (pos < m_CumulativeLength[line])
+					return line - 1;
+			}
+			
+			return m_CumulativeLength.length - 1;
+		}
+		
+		public function inflateLocationColumn(pos : int, line : int) : int
+		{
+			if (line <= 0) return pos;
+			return pos - m_CumulativeLength[line];
+		}
+		
 	}
 	}
-}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+

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

@@ -20,7 +20,7 @@ namespace MoonSharp.Debugger
 {
 {
 	public partial class MainForm : Form, IDebugger
 	public partial class MainForm : Form, IDebugger
 	{
 	{
-		List<string> m_Watches = new List<string>();
+		List<DynamicExpression> m_Watches = new List<DynamicExpression>();
 
 
 		public MainForm()
 		public MainForm()
 		{
 		{
@@ -281,7 +281,7 @@ namespace MoonSharp.Debugger
 
 
 
 
 
 
-		List<string> IDebugger.GetWatchItems()
+		List<DynamicExpression> IDebugger.GetWatchItems()
 		{
 		{
 			return m_Watches;
 			return m_Watches;
 		}
 		}
@@ -292,7 +292,9 @@ namespace MoonSharp.Debugger
 
 
 			if (!string.IsNullOrEmpty(text))
 			if (!string.IsNullOrEmpty(text))
 			{
 			{
-				m_Watches.AddRange(text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
+				string[] codeToAdd = text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+
+				m_Watches.AddRange(codeToAdd.Select(code => m_Script.CreateDynamicExpression(code)));
 				DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Refresh });
 				DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Refresh });
 			}
 			}
 		}
 		}
@@ -301,7 +303,7 @@ namespace MoonSharp.Debugger
 		{
 		{
 			HashSet<string> itemsToRemove = new HashSet<string>(lvWatches.SelectedItems.OfType<ListViewItem>().Select(lvi => lvi.Text));
 			HashSet<string> itemsToRemove = new HashSet<string>(lvWatches.SelectedItems.OfType<ListViewItem>().Select(lvi => lvi.Text));
 
 
-			int i = m_Watches.RemoveAll(w => itemsToRemove.Contains(w));
+			int i = m_Watches.RemoveAll(w => itemsToRemove.Contains(w.ExpressionCode));
 
 
 			if (i != 0)
 			if (i != 0)
 				DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Refresh });
 				DebugAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Refresh });

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

@@ -14,7 +14,7 @@ namespace MoonSharp.Interpreter.Debugging
 		DebuggerAction GetAction(int ip, SourceRef sourceref);
 		DebuggerAction GetAction(int ip, SourceRef sourceref);
 		void SignalExecutionEnded();
 		void SignalExecutionEnded();
 		void Update(WatchType watchType, IEnumerable<WatchItem> items);
 		void Update(WatchType watchType, IEnumerable<WatchItem> items);
-		List<string> GetWatchItems();
+		List<DynamicExpression> GetWatchItems();
 		void RefreshBreakpoints(IEnumerable<SourceRef> refs);
 		void RefreshBreakpoints(IEnumerable<SourceRef> refs);
 	}
 	}
 }
 }

+ 61 - 0
src/MoonSharp.Interpreter/Debugging/SourceRef.cs

@@ -15,6 +15,9 @@ namespace MoonSharp.Interpreter.Debugging
 		public bool IsStepStop { get; private set; }
 		public bool IsStepStop { get; private set; }
 
 
 		public bool Breakpoint;
 		public bool Breakpoint;
+		public bool CannotBreakpoint { get; private set; }
+
+		public string Type { get; set; }
 
 
 		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)
 		{
 		{
@@ -35,6 +38,57 @@ namespace MoonSharp.Interpreter.Debugging
 				ToLine, ToChar);
 				ToLine, ToChar);
 		}
 		}
 
 
+		public int GetLocationDistance(int sourceIdx, int line, int col)
+		{
+			const int PER_LINE_FACTOR = 1600; // we avoid computing real lines length and approximate with heuristics..
+
+			if (sourceIdx != SourceIdx)
+				return int.MaxValue;
+
+			if (FromLine == ToLine)
+			{
+				if (line == FromLine)
+				{
+					if (col >= FromChar && col <= ToChar)
+						return 0;
+					else if (col < FromChar)
+						return FromChar - col;
+					else
+						return col - ToChar;
+				}
+				else
+				{
+					return Math.Abs(line - FromLine) * PER_LINE_FACTOR;
+				}
+			}
+			else if (line == FromLine)
+			{
+				if (col < FromChar)
+					return FromChar - col;
+				else
+					return 0;
+			}
+			else if (line == ToLine)
+			{
+				if (col > ToChar)
+					return col - ToChar;
+				else
+					return 0;
+			}
+			else if (line > FromLine && line < ToLine)
+			{
+				return 0;
+			}
+			else if (line < FromLine)
+			{
+				return (FromLine - line) * PER_LINE_FACTOR;
+			}
+			else
+			{
+				return (line - ToLine) * PER_LINE_FACTOR;
+			}
+		}
+
 		public bool IncludesLocation(int sourceIdx, int line, int col)
 		public bool IncludesLocation(int sourceIdx, int line, int col)
 		{
 		{
 			if (sourceIdx != SourceIdx || line < FromLine || line > ToLine)
 			if (sourceIdx != SourceIdx || line < FromLine || line > ToLine)
@@ -51,5 +105,12 @@ namespace MoonSharp.Interpreter.Debugging
 		}
 		}
 
 
 
 
+
+
+		public SourceRef SetNoBreakPoint()
+		{
+			CannotBreakpoint = true;
+			return this;
+		}
 	}
 	}
 }
 }

+ 1 - 0
src/MoonSharp.Interpreter/Debugging/WatchItem.cs

@@ -14,6 +14,7 @@ namespace MoonSharp.Interpreter.Debugging
 		public string Name { get; set; }
 		public string Name { get; set; }
 		public DynValue Value { get; set; }
 		public DynValue Value { get; set; }
 		public SymbolRef LValue { get; set; }
 		public SymbolRef LValue { get; set; }
+		public bool IsError { get; set; }
 
 
 		public override string ToString()
 		public override string ToString()
 		{
 		{

+ 16 - 0
src/MoonSharp.Interpreter/Errors/DynamicExpressionException.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter
+{
+	public class DynamicExpressionException : ScriptRuntimeException
+	{
+		public DynamicExpressionException(string format, params object[] args)
+			: base("<dynamic>: " + format, args)
+		{
+
+		}
+	}
+}

+ 74 - 0
src/MoonSharp.Interpreter/Execution/DynamicExpression.cs

@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter.Execution;
+using MoonSharp.Interpreter.Tree.Expressions;
+
+namespace MoonSharp.Interpreter
+{
+	public class DynamicExpression : IScriptPrivateResource
+	{
+		DynamicExprExpression m_Exp;
+		DynValue m_Constant;
+
+		public readonly string ExpressionCode;
+
+		internal DynamicExpression(Script S, string strExpr, DynamicExprExpression expr)
+		{
+			ExpressionCode = strExpr;
+			OwnerScript = S;
+			m_Exp = expr;
+		}
+
+		internal DynamicExpression(Script S, string strExpr, DynValue constant)
+		{
+			ExpressionCode = strExpr;
+			OwnerScript = S;
+			m_Constant = constant;
+		}
+
+		public DynValue Evaluate(ScriptExecutionContext context)
+		{
+			if (m_Constant != null)
+				return m_Constant;
+
+			return m_Exp.Eval(context);
+		}
+
+		public SymbolRef FindSymbol(ScriptExecutionContext context)
+		{
+			if (m_Exp != null)
+				return m_Exp.FindDynamic(context);
+			else
+				return null;
+		}
+
+		public Script OwnerScript
+		{
+			get;
+			private set;
+		}
+
+		public bool IsConstant()
+		{
+			return m_Constant != null;
+		}
+
+		public override int GetHashCode()
+		{
+			return ExpressionCode.GetHashCode();
+		}
+
+		public override bool Equals(object obj)
+		{
+			DynamicExpression o = obj as DynamicExpression;
+			
+			if (o == null)
+				return false;
+
+			return o.ExpressionCode == this.ExpressionCode;
+		}
+
+	}
+}

+ 33 - 2
src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs

@@ -26,8 +26,12 @@ namespace MoonSharp.Interpreter.Execution
 		/// </summary>
 		/// </summary>
 		public object AdditionalData 
 		public object AdditionalData 
 		{
 		{
-			get { return m_Callback.AdditionalData; }
-			set { m_Callback.AdditionalData = value; } 
+			get { return (m_Callback != null) ? m_Callback.AdditionalData : null; }
+			set 
+			{
+				if (m_Callback == null) throw new InvalidOperationException("Cannot set additional data on a context which has no callback");
+				m_Callback.AdditionalData = value; 
+			} 
 		}
 		}
 
 
 
 
@@ -173,5 +177,32 @@ namespace MoonSharp.Interpreter.Execution
 				throw ScriptRuntimeException.LoopInCall();
 				throw ScriptRuntimeException.LoopInCall();
 			}
 			}
 		}
 		}
+
+		/// <summary>
+		/// Tries to get the reference of a symbol in the current execution state
+		/// </summary>
+		public DynValue EvaluateSymbol(SymbolRef symref)
+		{
+			if (symref == null)
+				return DynValue.Nil;
+
+			return m_Processor.GetGenericSymbol(symref);
+		}
+
+		/// <summary>
+		/// Tries to get the value of a symbol in the current execution state
+		/// </summary>
+		public DynValue EvaluateSymbolByName(string symbol)
+		{
+			return this.EvaluateSymbol(this.FindSymbolByName(symbol));
+		}
+
+		/// <summary>
+		/// Finds a symbol by name in the current execution state
+		/// </summary>
+		public SymbolRef FindSymbolByName(string symbol)
+		{
+			return m_Processor.FindSymbolByName(symbol);
+		}
 	}
 	}
 }
 }

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

@@ -10,7 +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; }
-
-
+		public bool Anonymous { get; set; }
+		public bool IsDynamicExpression { get; set; }
 	}
 	}
 }
 }

+ 71 - 14
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Debugger.cs

@@ -40,7 +40,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 					if (m_ExecutionStack.Count >= m_Debug.ExStackDepthAtStep) return;
 					if (m_ExecutionStack.Count >= m_Debug.ExStackDepthAtStep) return;
 					break;
 					break;
 				case DebuggerAction.ActionType.StepIn:
 				case DebuggerAction.ActionType.StepIn:
-					if (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef) return;
+					if ((m_ExecutionStack.Count >= m_Debug.ExStackDepthAtStep) && (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef)) return;
 					break;
 					break;
 				case DebuggerAction.ActionType.StepOver:
 				case DebuggerAction.ActionType.StepOver:
 					if (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef || m_ExecutionStack.Count > m_Debug.ExStackDepthAtStep) return;
 					if (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef || m_ExecutionStack.Count > m_Debug.ExStackDepthAtStep) return;
@@ -95,14 +95,22 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 
 
 
 
 
-		private void ToggleBreakPoint(DebuggerAction action)
+		private bool ToggleBreakPoint(DebuggerAction action)
 		{
 		{
 			SourceCode src = m_Script.GetSourceCode(action.SourceID);
 			SourceCode src = m_Script.GetSourceCode(action.SourceID);
 
 
+			bool found = false;
 			foreach (SourceRef srf in src.Refs)
 			foreach (SourceRef srf in src.Refs)
 			{
 			{
+				if (srf.CannotBreakpoint)
+					continue;
+
 				if (srf.IncludesLocation(action.SourceID, action.SourceLine, action.SourceCol))
 				if (srf.IncludesLocation(action.SourceID, action.SourceLine, action.SourceCol))
 				{
 				{
+					found = true;
+
+					System.Diagnostics.Debug.WriteLine(string.Format("BRK: found {0} for {1} on contains", srf, srf.Type));
+
 					srf.Breakpoint = !srf.Breakpoint;
 					srf.Breakpoint = !srf.Breakpoint;
 
 
 					if (srf.Breakpoint)
 					if (srf.Breakpoint)
@@ -116,14 +124,58 @@ namespace MoonSharp.Interpreter.Execution.VM
 				}
 				}
 			}
 			}
 
 
+			if (!found)
+			{
+				int minDistance = int.MaxValue;
+				SourceRef nearest = null;
+
+				foreach (SourceRef srf in src.Refs)
+				{
+					if (srf.CannotBreakpoint)
+						continue;
+
+					int dist = srf.GetLocationDistance(action.SourceID, action.SourceLine, action.SourceCol);
+
+					if (dist < minDistance)
+					{
+						minDistance = dist;
+						nearest = srf;
+					}
+				}
+
+				if (nearest != null)
+				{
+					System.Diagnostics.Debug.WriteLine(string.Format("BRK: found {0} for {1} on distance {2}", nearest, nearest.Type, minDistance));
+
+					nearest.Breakpoint = !nearest.Breakpoint;
+
+					if (nearest.Breakpoint)
+					{
+						m_Debug.BreakPoints.Add(nearest);
+					}
+					else
+					{
+						m_Debug.BreakPoints.Remove(nearest);
+					}
+
+					return true;
+				}
+				else
+					return false;
+			}
+			else
+				return true;
 		}
 		}
 
 
 		private void RefreshDebugger(bool hard)
 		private void RefreshDebugger(bool hard)
 		{
 		{
-			List<string> watchList = m_Debug.DebuggerAttached.GetWatchItems();
+			ScriptExecutionContext context = new ScriptExecutionContext(this, null);
+
+			List<DynamicExpression> watchList = m_Debug.DebuggerAttached.GetWatchItems();
 			List<WatchItem> callStack = Debugger_GetCallStack();
 			List<WatchItem> callStack = Debugger_GetCallStack();
-			List<WatchItem> watches = Debugger_RefreshWatches(watchList);
+			List<WatchItem> watches = Debugger_RefreshWatches(context, watchList);
 			List<WatchItem> vstack = Debugger_RefreshVStack();
 			List<WatchItem> vstack = Debugger_RefreshVStack();
+
 			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);
@@ -147,29 +199,34 @@ namespace MoonSharp.Interpreter.Execution.VM
 			return lwi;
 			return lwi;
 		}
 		}
 
 
-		private List<WatchItem> Debugger_RefreshWatches(List<string> watchList)
+		private List<WatchItem> Debugger_RefreshWatches(ScriptExecutionContext context, List<DynamicExpression> watchList)
 		{
 		{
-			return watchList.Select(w => Debugger_RefreshWatch(w)).ToList();
+			return watchList.Select(w => Debugger_RefreshWatch(context, w)).ToList();
 		}
 		}
 
 
-		private WatchItem Debugger_RefreshWatch(string name)
+		private WatchItem Debugger_RefreshWatch(ScriptExecutionContext context, DynamicExpression dynExpr)
 		{
 		{
-			SymbolRef L = FindSymbolByName(name);
-
-			if (L != null)
+			try
 			{
 			{
-				DynValue v = this.GetGenericSymbol(L);
+				SymbolRef L = dynExpr.FindSymbol(context);
+				DynValue v = dynExpr.Evaluate(context);
 
 
 				return new WatchItem()
 				return new WatchItem()
 				{
 				{
+					IsError = dynExpr.IsConstant(),
 					LValue = L,
 					LValue = L,
 					Value = v,
 					Value = v,
-					Name = name
+					Name = dynExpr.ExpressionCode
 				};
 				};
 			}
 			}
-			else
+			catch (Exception ex)
 			{
 			{
-				return new WatchItem() { Name = name };
+				return new WatchItem()
+				{
+					IsError = true,
+					Value = DynValue.NewString(ex.Message),
+					Name = dynExpr.ExpressionCode
+				};
 			}
 			}
 		}
 		}
 
 

+ 18 - 15
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Scope.cs

@@ -111,27 +111,30 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 
 		public SymbolRef FindSymbolByName(string name)
 		public SymbolRef FindSymbolByName(string name)
 		{
 		{
-			var stackframe = m_ExecutionStack.Peek();
-
-			if (stackframe.Debug_Symbols != null)
+			if (m_ExecutionStack.Count > 0)
 			{
 			{
-				for (int i = stackframe.Debug_Symbols.Length - 1; i >= 0; i--)
+				var stackframe = m_ExecutionStack.Peek();
+
+				if (stackframe.Debug_Symbols != null)
 				{
 				{
-					var l = stackframe.Debug_Symbols[i];
+					for (int i = stackframe.Debug_Symbols.Length - 1; i >= 0; i--)
+					{
+						var l = stackframe.Debug_Symbols[i];
 
 
-					if (l.i_Name == name && stackframe.LocalScope[i] != null)
-						return l;
+						if (l.i_Name == name && stackframe.LocalScope[i] != null)
+							return l;
+					}
 				}
 				}
-			}
 
 
-			
-			var closure = stackframe.ClosureScope;
 
 
-			if (closure != null)
-			{
-				for (int i = 0; i < closure.Symbols.Length; i++)
-					if (closure.Symbols[i] == name)
-						return SymbolRef.Upvalue(name, i);
+				var closure = stackframe.ClosureScope;
+
+				if (closure != null)
+				{
+					for (int i = 0; i < closure.Symbols.Length; i++)
+						if (closure.Symbols[i] == name)
+							return SymbolRef.Upvalue(name, i);
+				}
 			}
 			}
 
 
 			if (name != WellKnownSymbols.ENV)
 			if (name != WellKnownSymbols.ENV)

+ 10 - 0
src/MoonSharp.Interpreter/Grammar/Lua.g4

@@ -4,6 +4,15 @@ chunk
     : block (EOF)
     : block (EOF)
     ;
     ;
 
 
+dynamicexp
+	: exp EOF
+	;
+
+singlefunc
+	: anonfunctiondef EOF
+	;
+
+
 block
 block
     : stat* retstat?
     : stat* retstat?
     ;
     ;
@@ -55,6 +64,7 @@ explist
     : exp (',' exp)*
     : exp (',' exp)*
     ;
     ;
 
 
+
 exp
 exp
     : NIL												#exp_nil
     : NIL												#exp_nil
 	| FALSE												#exp_false
 	| FALSE												#exp_false

+ 3 - 0
src/MoonSharp.Interpreter/MoonSharp.Interpreter.csproj

@@ -92,6 +92,8 @@
     <Compile Include="CoreLib\StringLib\KopiLua_StrLib.cs" />
     <Compile Include="CoreLib\StringLib\KopiLua_StrLib.cs" />
     <Compile Include="DataTypes\ScriptFunctionDelegate.cs" />
     <Compile Include="DataTypes\ScriptFunctionDelegate.cs" />
     <Compile Include="DataTypes\TypeValidationFlags.cs" />
     <Compile Include="DataTypes\TypeValidationFlags.cs" />
+    <Compile Include="Errors\DynamicExpressionException.cs" />
+    <Compile Include="Execution\DynamicExpression.cs" />
     <Compile Include="Interop\LuaStateInterop\CharPtr.cs" />
     <Compile Include="Interop\LuaStateInterop\CharPtr.cs" />
     <Compile Include="Interop\LuaStateInterop\LuaBase.cs" />
     <Compile Include="Interop\LuaStateInterop\LuaBase.cs" />
     <Compile Include="CoreLib\StringLib\MatchState.cs">
     <Compile Include="CoreLib\StringLib\MatchState.cs">
@@ -222,6 +224,7 @@
     <Compile Include="Tree\Antlr_Interface\AntlrErrorListener.cs" />
     <Compile Include="Tree\Antlr_Interface\AntlrErrorListener.cs" />
     <Compile Include="Tree\Expressions\AdjustmentExpression.cs" />
     <Compile Include="Tree\Expressions\AdjustmentExpression.cs" />
     <Compile Include="Tree\Expressions\BinaryOperatorExpression.cs" />
     <Compile Include="Tree\Expressions\BinaryOperatorExpression.cs" />
+    <Compile Include="Tree\Expressions\DynamicExpression.cs" />
     <Compile Include="Tree\Expressions\PowerOperatorExpression.cs" />
     <Compile Include="Tree\Expressions\PowerOperatorExpression.cs" />
     <Compile Include="Tree\Expressions\UnaryOperatorExpression.cs" />
     <Compile Include="Tree\Expressions\UnaryOperatorExpression.cs" />
     <Compile Include="Tree\IVariable.cs" />
     <Compile Include="Tree\IVariable.cs" />

+ 29 - 1
src/MoonSharp.Interpreter/Script.cs

@@ -7,10 +7,12 @@ using Antlr4.Runtime;
 using MoonSharp.Interpreter.CoreLib;
 using MoonSharp.Interpreter.CoreLib;
 using MoonSharp.Interpreter.Debugging;
 using MoonSharp.Interpreter.Debugging;
 using MoonSharp.Interpreter.Diagnostics;
 using MoonSharp.Interpreter.Diagnostics;
+using MoonSharp.Interpreter.Execution;
 using MoonSharp.Interpreter.Execution.VM;
 using MoonSharp.Interpreter.Execution.VM;
 using MoonSharp.Interpreter.Interop;
 using MoonSharp.Interpreter.Interop;
 using MoonSharp.Interpreter.Loaders;
 using MoonSharp.Interpreter.Loaders;
 using MoonSharp.Interpreter.Tree;
 using MoonSharp.Interpreter.Tree;
+using MoonSharp.Interpreter.Tree.Expressions;
 using MoonSharp.Interpreter.Tree.Statements;
 using MoonSharp.Interpreter.Tree.Statements;
 
 
 namespace MoonSharp.Interpreter
 namespace MoonSharp.Interpreter
@@ -493,8 +495,34 @@ namespace MoonSharp.Interpreter
 		}
 		}
 
 
 
 
+		/// <summary>
+		/// Creates a new dynamic expression.
+		/// </summary>
+		/// <param name="code">The code of the expression.</param>
+		/// <returns></returns>
+		public DynamicExpression CreateDynamicExpression(string code)
+		{
+			DynamicExprExpression dee = Loader_Antlr.LoadDynamicExpr(this, new SourceCode("__dynamic", code, -1, this));
+			return new DynamicExpression(this, code, dee);
+		}
 
 
+		/// <summary>
+		/// Creates a new dynamic expression.
+		/// </summary>
+		/// <param name="code">The code of the expression.</param>
+		/// <returns></returns>
+		public DynamicExpression CreateConstantDynamicExpression(string code, DynValue constant)
+		{
+			return new DynamicExpression(this, code, constant);
+		}
 
 
-
+		/// <summary>
+		/// Gets an execution context exposing only partial functionality
+		/// </summary>
+		/// <returns></returns>
+		public ScriptExecutionContext CreateMockExecutionContext()
+		{
+			return new ScriptExecutionContext(m_MainProcessor, null);
+		}
 	}
 	}
 }
 }

+ 26 - 1
src/MoonSharp.Interpreter/Tree/Antlr_Interface/Loader_Antlr.cs

@@ -24,6 +24,31 @@ namespace MoonSharp.Interpreter.Tree
 	/// </summary>
 	/// </summary>
 	internal static class Loader_Antlr
 	internal static class Loader_Antlr
 	{
 	{
+		internal static DynamicExprExpression LoadDynamicExpr(Script script, SourceCode source)
+		{
+			AntlrErrorListener listener = new AntlrErrorListener(source);
+
+			try
+			{
+				LuaParser parser = CreateParser(script, new AntlrInputStream(source.Code), source.SourceID, p => p.dynamicexp(), listener);
+
+				ScriptLoadingContext lcontext = CreateLoadingContext(source);
+				lcontext.IsDynamicExpression = true;
+				lcontext.Anonymous = true;
+
+				DynamicExprExpression stat;
+
+				using (script.PerformanceStats.StartStopwatch(Diagnostics.PerformanceCounter.AstCreation))
+					stat = new DynamicExprExpression(parser.dynamicexp(), lcontext);
+
+				return stat;
+			}
+			catch (ParseCanceledException ex)
+			{
+				HandleParserError(ex, listener);
+				throw;
+			}
+		}
 
 
 		internal static int LoadChunk(Script script, SourceCode source, ByteCode bytecode, Table globalContext)
 		internal static int LoadChunk(Script script, SourceCode source, ByteCode bytecode, Table globalContext)
 		{
 		{
@@ -68,7 +93,7 @@ namespace MoonSharp.Interpreter.Tree
 			AntlrErrorListener listener = new AntlrErrorListener(source);
 			AntlrErrorListener listener = new AntlrErrorListener(source);
 			try
 			try
 			{
 			{
-				LuaParser parser = CreateParser(script, new AntlrInputStream(source.Code), source.SourceID, p => p.anonfunctiondef(), listener);
+				LuaParser parser = CreateParser(script, new AntlrInputStream(source.Code), source.SourceID, p => p.singlefunc(), listener);
 
 
 				ScriptLoadingContext lcontext = CreateLoadingContext(source);
 				ScriptLoadingContext lcontext = CreateLoadingContext(source);
 				FunctionDefinitionExpression fndef;
 				FunctionDefinitionExpression fndef;

+ 6 - 0
src/MoonSharp.Interpreter/Tree/Expression.cs

@@ -14,5 +14,11 @@ namespace MoonSharp.Interpreter.Tree
 			: base(node, lcontext)
 			: base(node, lcontext)
 		{ }
 		{ }
 
 
+		public abstract DynValue Eval(ScriptExecutionContext context);
+
+		public virtual SymbolRef FindDynamic(ScriptExecutionContext context)
+		{
+			return null;
+		}
 	}
 	}
 }
 }

+ 4 - 1
src/MoonSharp.Interpreter/Tree/Expressions/AdjustmentExpression.cs

@@ -24,6 +24,9 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			bc.Emit_Scalar();
 			bc.Emit_Scalar();
 		}
 		}
 
 
-
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			return expression.Eval(context).ToScalar();
+		}
 	}
 	}
 }
 }

+ 139 - 7
src/MoonSharp.Interpreter/Tree/Expressions/BinaryOperatorExpression.cs

@@ -51,6 +51,13 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			public Node Last;
 			public Node Last;
 		}
 		}
 
 
+		const Operator MUL_DIV_MOD = Operator.Mul | Operator.Div | Operator.Mod;
+		const Operator ADD_SUB = Operator.Add | Operator.Sub;
+		const Operator STRCAT = Operator.StrConcat;
+		const Operator COMPARES = Operator.Less | Operator.Greater | Operator.GreaterOrEqual | Operator.LessOrEqual | Operator.Equal | Operator.NotEqual;
+		const Operator LOGIC_AND = Operator.And;
+		const Operator LOGIC_OR = Operator.Or;
+
 		private static Operator CreateLinkedList(LinkedList list, IParseTree root, ScriptLoadingContext lcontext)
 		private static Operator CreateLinkedList(LinkedList list, IParseTree root, ScriptLoadingContext lcontext)
 		{
 		{
 			Operator opfound = 0;
 			Operator opfound = 0;
@@ -102,13 +109,6 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 		/// </summary>
 		/// </summary>
 		public static Expression CreateSubTree(IParseTree tree, ScriptLoadingContext lcontext)
 		public static Expression CreateSubTree(IParseTree tree, ScriptLoadingContext lcontext)
 		{
 		{
-			const Operator MUL_DIV_MOD = Operator.Mul | Operator.Div | Operator.Mod;
-			const Operator ADD_SUB = Operator.Add | Operator.Sub;
-			const Operator STRCAT = Operator.StrConcat;
-			const Operator COMPARES = Operator.Less | Operator.Greater | Operator.GreaterOrEqual | Operator.LessOrEqual | Operator.Equal | Operator.NotEqual;
-			const Operator LOGIC_AND = Operator.And;
-			const Operator LOGIC_OR = Operator.Or;
-
 			LinkedList list = new LinkedList();
 			LinkedList list = new LinkedList();
 
 
 			Operator opfound = CreateLinkedList(list, tree, lcontext);
 			Operator opfound = CreateLinkedList(list, tree, lcontext);
@@ -324,5 +324,137 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			if (ShouldInvertBoolean(m_Operator))
 			if (ShouldInvertBoolean(m_Operator))
 				bc.Emit_Operator(OpCode.Not);
 				bc.Emit_Operator(OpCode.Not);
 		}
 		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			DynValue v1 = m_Exp1.Eval(context).ToScalar();
+
+			if (m_Operator == Operator.Or)
+			{
+				if (v1.CastToBool())
+					return v1;
+				else
+					return m_Exp2.Eval(context).ToScalar();
+			}
+
+			if (m_Operator == Operator.And)
+			{
+				if (!v1.CastToBool())
+					return v1;
+				else
+					return m_Exp2.Eval(context).ToScalar();
+			}
+
+			DynValue v2 = m_Exp2.Eval(context).ToScalar();
+
+			if ((m_Operator & COMPARES) != 0)
+			{
+				return DynValue.NewBoolean(EvalComparison(v1, v2, m_Operator));				
+			}
+			else if (m_Operator == Operator.StrConcat)
+			{
+				string s1 = v1.CastToString();
+				string s2 = v2.CastToString();
+
+				if (s1 == null || s2 == null)
+					throw new DynamicExpressionException("Attempt to perform concatenation on non-strings.");
+
+				return DynValue.NewString(s1 + s2);
+			}
+			else
+			{
+				return DynValue.NewNumber(EvalArithmetic(v1, v2));
+			}
+		}
+
+		private double EvalArithmetic(DynValue v1, DynValue v2)
+		{
+			double? nd1 = v1.CastToNumber();
+			double? nd2 = v2.CastToNumber();
+
+			if (nd1 == null || nd2 == null)
+				throw new DynamicExpressionException("Attempt to perform arithmetic on non-numbers.");
+
+			double d1 = nd1.Value;
+			double d2 = nd2.Value;
+
+			switch (m_Operator)
+			{
+				case Operator.Add:
+					return d1 + d2;
+				case Operator.Sub:
+					return d1 - d2;
+				case Operator.Mul:
+					return d1 * d2;
+				case Operator.Div:
+					return d1 / d2;
+				case Operator.Mod:
+					{
+						double mod = Math.IEEERemainder(d1, d2);
+						if (mod < 0) mod += d2;
+						return mod;
+					}
+				default:
+					throw new DynamicExpressionException("Unsupported operator {0}", m_Operator);
+			}
+		}
+
+		private bool EvalComparison(DynValue l, DynValue r, Operator op)
+		{
+			switch (op)
+			{
+				case Operator.Less:
+					if (l.Type == DataType.Number && r.Type == DataType.Number)
+					{
+						return (l.Number < r.Number);
+					}
+					else if (l.Type == DataType.String && r.Type == DataType.String)
+					{
+						return (l.String.CompareTo(r.String) < 0);
+					}
+					else
+					{
+						throw new DynamicExpressionException("Attempt to compare non-numbers, non-strings.");
+					}
+				case Operator.LessOrEqual:
+					if (l.Type == DataType.Number && r.Type == DataType.Number)
+					{
+						return (l.Number <= r.Number);
+					}
+					else if (l.Type == DataType.String && r.Type == DataType.String)
+					{
+						return (l.String.CompareTo(r.String) <= 0);
+					}
+					else
+					{
+						throw new DynamicExpressionException("Attempt to compare non-numbers, non-strings.");
+					}
+				case Operator.Equal:
+					if (object.ReferenceEquals(r, l))
+					{
+						return true;
+					}
+					else if (r.Type != l.Type)
+					{
+						if ((l.Type == DataType.Nil && r.Type == DataType.Void)
+							|| (l.Type == DataType.Void && r.Type == DataType.Nil))
+							return true;
+						else
+							return false;
+					}
+					else
+					{
+						return r.Equals(l);
+					}
+				case Operator.Greater:
+					return !EvalComparison(l, r, Operator.LessOrEqual);
+				case Operator.GreaterOrEqual:
+					return !EvalComparison(l, r, Operator.Less);
+				case Operator.NotEqual:
+					return !EvalComparison(l, r, Operator.Equal);
+				default:
+					throw new DynamicExpressionException("Unsupported operator {0}", op);
+			}
+		}
 	}
 	}
 }
 }

+ 36 - 0
src/MoonSharp.Interpreter/Tree/Expressions/DynamicExpression.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter.Execution;
+using MoonSharp.Interpreter.Grammar;
+
+namespace MoonSharp.Interpreter.Tree.Expressions
+{
+	class DynamicExprExpression : Expression
+	{
+		Expression m_Exp;
+
+		public DynamicExprExpression(LuaParser.DynamicexpContext context, ScriptLoadingContext lcontext)
+			: base(context, lcontext)
+		{
+			lcontext.Anonymous = true;
+			m_Exp = NodeFactory.CreateExpression(context.exp(), lcontext);
+		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			return m_Exp.Eval(context);
+		}
+
+		public override void Compile(Execution.VM.ByteCode bc)
+		{
+			throw new InvalidOperationException();
+		}
+
+		public override SymbolRef FindDynamic(ScriptExecutionContext context)
+		{
+			return m_Exp.FindDynamic(context);
+		}
+	}
+}

+ 8 - 0
src/MoonSharp.Interpreter/Tree/Expressions/ExprListExpression.cs

@@ -34,5 +34,13 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			if (expressions.Length > 1)
 			if (expressions.Length > 1)
 				bc.Emit_MkTuple(expressions.Length);
 				bc.Emit_MkTuple(expressions.Length);
 		}
 		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			if (expressions.Length > 1)
+				return expressions[0].Eval(context);
+
+			return DynValue.Void;
+		}
 	}
 	}
 }
 }

+ 4 - 1
src/MoonSharp.Interpreter/Tree/Expressions/FunctionCallChainExpression.cs

@@ -50,6 +50,9 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			}
 			}
 		}
 		}
 
 
-
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			throw new DynamicExpressionException("Dynamic Expressions cannot call functions.");
+		}
 	}
 	}
 }
 }

+ 7 - 2
src/MoonSharp.Interpreter/Tree/Expressions/FunctionDefinitionExpression.cs

@@ -77,8 +77,8 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 
 
 			m_StackFrame = lcontext.Scope.PopFunction();
 			m_StackFrame = lcontext.Scope.PopFunction();
 
 
-			m_Begin = BuildSourceRef(lcontext, declarationContext.Start, context.PAREN_CLOSE().Symbol);
-			m_End = BuildSourceRef(lcontext, context.Stop, context.END());
+			m_Begin = BuildSourceRef(declarationContext.Start, context.PAREN_CLOSE().Symbol);
+			m_End = BuildSourceRef(context.Stop, context.END());
 		}
 		}
 
 
 		public SymbolRef CreateUpvalue(BuildTimeScope scope, SymbolRef symbol)
 		public SymbolRef CreateUpvalue(BuildTimeScope scope, SymbolRef symbol)
@@ -173,5 +173,10 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			Compile(bc, () => 0, null);
 			Compile(bc, () => 0, null);
 		}
 		}
 
 
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			throw new DynamicExpressionException("Dynamic Expressions cannot define new functions.");
+		}
 	}
 	}
 }
 }

+ 10 - 0
src/MoonSharp.Interpreter/Tree/Expressions/IndexExpression.cs

@@ -56,5 +56,15 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 
 
 
 
 		}
 		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			DynValue b = m_BaseExp.Eval(context).ToScalar();
+			DynValue i = m_IndexExp.Eval(context).ToScalar();
+
+			if (b.Type != DataType.Table) throw new DynamicExpressionException("Attempt to index non-table.");
+			else if (i.IsNilOrNan()) throw new DynamicExpressionException("Attempt to index with nil or nan key.");
+			return b.Table.Get(i) ?? DynValue.Nil;
+		}
 	}
 	}
 }
 }

+ 4 - 0
src/MoonSharp.Interpreter/Tree/Expressions/LiteralExpression.cs

@@ -265,5 +265,9 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			throw new SyntaxErrorException("hex floats are not supported: '{0}'", s);
 			throw new SyntaxErrorException("hex floats are not supported: '{0}'", s);
 		}
 		}
 
 
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			return m_Value;
+		}
 	}
 	}
 }
 }

+ 14 - 0
src/MoonSharp.Interpreter/Tree/Expressions/PowerOperatorExpression.cs

@@ -26,5 +26,19 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			m_Exp2.Compile(bc);
 			m_Exp2.Compile(bc);
 			bc.Emit_Operator(OpCode.Power);
 			bc.Emit_Operator(OpCode.Power);
 		}
 		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			DynValue v1 = m_Exp1.Eval(context).ToScalar();
+			DynValue v2 = m_Exp1.Eval(context).ToScalar();
+
+			double? d1 = v1.CastToNumber();
+			double? d2 = v1.CastToNumber();
+
+			if (d1.HasValue && d2.HasValue)
+				return DynValue.NewNumber(Math.Pow(d1.Value, d2.Value));
+
+			throw new DynamicExpressionException("Attempt to perform arithmetic on non-numbers.");
+		}
 	}
 	}
 }
 }

+ 27 - 2
src/MoonSharp.Interpreter/Tree/Expressions/SymbolRefExpression.cs

@@ -11,11 +11,17 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 	class SymbolRefExpression : Expression, IVariable
 	class SymbolRefExpression : Expression, IVariable
 	{
 	{
 		SymbolRef m_Ref;
 		SymbolRef m_Ref;
+		string m_VarName;
 
 
 		public SymbolRefExpression(IParseTree context, ScriptLoadingContext lcontext, SymbolRef refr)
 		public SymbolRefExpression(IParseTree context, ScriptLoadingContext lcontext, SymbolRef refr)
 			: base(context, lcontext)
 			: base(context, lcontext)
 		{
 		{
 			m_Ref = refr;
 			m_Ref = refr;
+
+			if (lcontext.IsDynamicExpression)
+			{
+				throw new DynamicExpressionException("Unsupported symbol reference expression detected.");
+			}
 		}
 		}
 
 
 
 
@@ -28,14 +34,23 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			{
 			{
 				throw new SyntaxErrorException("error:0: cannot use '...' outside a vararg function");
 				throw new SyntaxErrorException("error:0: cannot use '...' outside a vararg function");
 			}
 			}
+
+			if (lcontext.IsDynamicExpression)
+			{
+				throw new DynamicExpressionException("Cannot use '...' in a dynamic expression.");
+			}
 		}
 		}
 
 
 
 
 		public SymbolRefExpression(ITerminalNode terminalNode, ScriptLoadingContext lcontext)
 		public SymbolRefExpression(ITerminalNode terminalNode, ScriptLoadingContext lcontext)
 			: base(terminalNode, lcontext)
 			: base(terminalNode, lcontext)
 		{
 		{
-			string varName = terminalNode.GetText();
-			m_Ref = lcontext.Scope.Find(varName);
+			m_VarName = terminalNode.GetText();
+
+			if (!lcontext.IsDynamicExpression)
+			{
+				m_Ref = lcontext.Scope.Find(m_VarName);
+			}
 		}
 		}
 
 
 
 
@@ -49,5 +64,15 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 		{
 		{
 			bc.Emit_Store(m_Ref, stackofs, tupleidx);
 			bc.Emit_Store(m_Ref, stackofs, tupleidx);
 		}
 		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			return context.EvaluateSymbolByName(m_VarName);
+		}
+
+		public override SymbolRef FindDynamic(ScriptExecutionContext context)
+		{
+			return context.FindSymbolByName(m_VarName);
+		}
 	}
 	}
 }
 }

+ 5 - 0
src/MoonSharp.Interpreter/Tree/Expressions/TableConstructor.cs

@@ -67,5 +67,10 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			}
 			}
 		}
 		}
 
 
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			throw new DynamicExpressionException("Dynamic Expressions cannot define new tables.");
+		}
 	}
 	}
 }
 }

+ 24 - 0
src/MoonSharp.Interpreter/Tree/Expressions/UnaryOperatorExpression.cs

@@ -46,5 +46,29 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 
 
 
 
 		}
 		}
+
+		public override DynValue Eval(ScriptExecutionContext context)
+		{
+			DynValue v = m_Exp.Eval(context).ToScalar();
+
+			switch (m_OpText)
+			{
+				case "not":
+					return DynValue.NewBoolean(!v.CastToBool());
+				case "#":
+					return v.GetLength();
+				case "-":
+					{
+						double? d = v.CastToNumber();
+
+						if (d.HasValue)
+							return DynValue.NewNumber(-d.Value);
+
+						throw new DynamicExpressionException("Attempt to perform arithmetic on non-numbers.");
+					}
+				default:
+					throw new DynamicExpressionException("Unexpected unary operator '{0}'", m_OpText);
+			}
+		}
 	}
 	}
 }
 }

+ 9 - 8
src/MoonSharp.Interpreter/Tree/NodeBase.cs

@@ -34,25 +34,26 @@ namespace MoonSharp.Interpreter.Tree
 
 
 		public abstract void Compile(ByteCode bc);
 		public abstract void Compile(ByteCode bc);
 
 
-		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, IToken token, ITerminalNode terminalNode)
+		protected SourceRef BuildSourceRef(IToken token, ITerminalNode terminalNode)
 		{
 		{
-			return RegisterSourceRef(lcontext, new SourceRef(lcontext.Source.SourceID, token.Column, token.Column + terminalNode.GetText().Length, token.Line, token.Line, true));
+			return RegisterSourceRef(new SourceRef(LoadingContext.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 SourceRef BuildSourceRef(IToken token1, IToken token2 = null)
 		{
 		{
 			token2 = token2 ?? token1;
 			token2 = token2 ?? token1;
-			return RegisterSourceRef(lcontext, new SourceRef(lcontext.Source.SourceID, token1.Column, token2.Column + token2.Text.Length, token1.Line, token2.Line, true));
+			return RegisterSourceRef(new SourceRef(LoadingContext.Source.SourceID, token1.Column, token2.Column + token2.Text.Length, token1.Line, token2.Line, true));
 		}
 		}
 
 
-		protected static SourceRef BuildSourceRef(ScriptLoadingContext lcontext, ITerminalNode terminalNode)
+		protected SourceRef BuildSourceRef(ITerminalNode terminalNode)
 		{
 		{
-			return BuildSourceRef(lcontext, terminalNode.Symbol, terminalNode);
+			return BuildSourceRef(terminalNode.Symbol, terminalNode);
 		}
 		}
 
 
-		private static SourceRef RegisterSourceRef(ScriptLoadingContext lcontext, SourceRef sourceRef)
+		private SourceRef RegisterSourceRef(SourceRef sourceRef)
 		{
 		{
-			lcontext.Source.Refs.Add(sourceRef);
+			LoadingContext.Source.Refs.Add(sourceRef);
+			sourceRef.Type = this.GetType().Name;
 			return sourceRef;
 			return sourceRef;
 		}
 		}
 
 

+ 1 - 1
src/MoonSharp.Interpreter/Tree/NodeFactory.cs

@@ -211,7 +211,7 @@ namespace MoonSharp.Interpreter.Tree
 				else
 				else
 					indexExp = new LiteralExpression(suff_NAME, lcontext, DynValue.NewString(suff_NAME.GetText()));
 					indexExp = new LiteralExpression(suff_NAME, lcontext, DynValue.NewString(suff_NAME.GetText()));
 
 
-				if (nameAndArgs != null)
+				if (nameAndArgs != null && nameAndArgs.Length > 0)
 				{
 				{
 					varExp = new FunctionCallChainExpression(suffix, lcontext, varExp, nameAndArgs);
 					varExp = new FunctionCallChainExpression(suffix, lcontext, varExp, nameAndArgs);
 				}
 				}

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs

@@ -28,7 +28,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				.Select(e => NodeFactory.CreateExpression(e, lcontext))
 				.Select(e => NodeFactory.CreateExpression(e, lcontext))
 				.ToArray();
 				.ToArray();
 
 
-			m_Ref = BuildSourceRef(lcontext, context.Start, context.Stop);
+			m_Ref = BuildSourceRef(context.Start, context.Stop);
 		}
 		}
 
 
 		public AssignmentStatement(LuaParser.Stat_localassignmentContext context, ScriptLoadingContext lcontext)
 		public AssignmentStatement(LuaParser.Stat_localassignmentContext context, ScriptLoadingContext lcontext)
@@ -53,7 +53,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				.Cast<IVariable>()
 				.Cast<IVariable>()
 				.ToArray();
 				.ToArray();
 
 
-			m_Ref = BuildSourceRef(lcontext, context.Start, context.Stop);
+			m_Ref = BuildSourceRef(context.Start, context.Stop);
 		}
 		}
 
 
 
 

+ 1 - 1
src/MoonSharp.Interpreter/Tree/Statements/BreakStatement.cs

@@ -16,7 +16,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 		public BreakStatement(LuaParser.Stat_breakContext context, ScriptLoadingContext lcontext)
 		public BreakStatement(LuaParser.Stat_breakContext context, ScriptLoadingContext lcontext)
 			: base(context, lcontext)
 			: base(context, lcontext)
 		{
 		{
-			m_Ref = BuildSourceRef(lcontext, context.Start, context.Stop);
+			m_Ref = BuildSourceRef(context.Start, context.Stop);
 		}
 		}
 
 
 
 

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/ForEachLoopStatement.cs

@@ -48,8 +48,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			m_StackFrame = lcontext.Scope.PopBlock();
 			m_StackFrame = lcontext.Scope.PopBlock();
 			m_DebugText = context.GetText();
 			m_DebugText = context.GetText();
 
 
-			m_RefFor = BuildSourceRef(lcontext, context.Start, context.FOR());
-			m_RefEnd = BuildSourceRef(lcontext, context.Stop, context.END());
+			m_RefFor = BuildSourceRef(context.Start, context.FOR());
+			m_RefEnd = BuildSourceRef(context.Stop, context.END());
 		}
 		}
 
 
 		public override void Compile(ByteCode bc)
 		public override void Compile(ByteCode bc)

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/ForLoopStatement.cs

@@ -37,8 +37,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			m_InnerBlock = NodeFactory.CreateStatement(context.block(), lcontext);
 			m_InnerBlock = NodeFactory.CreateStatement(context.block(), lcontext);
 			m_StackFrame = lcontext.Scope.PopBlock();
 			m_StackFrame = lcontext.Scope.PopBlock();
 
 
-			m_RefFor = BuildSourceRef(lcontext, context.Start, context.FOR());
-			m_RefEnd = BuildSourceRef(lcontext, context.Stop, context.END());
+			m_RefFor = BuildSourceRef(context.Start, context.FOR());
+			m_RefEnd = BuildSourceRef(context.Stop, context.END());
 		}
 		}
 
 
 		public override void Compile(ByteCode bc)
 		public override void Compile(ByteCode bc)

+ 1 - 1
src/MoonSharp.Interpreter/Tree/Statements/FunctionCallStatement.cs

@@ -20,7 +20,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			: base(context, lcontext)
 			: base(context, lcontext)
 		{
 		{
 			m_FunctionCallChain = new FunctionCallChainExpression(context, lcontext);
 			m_FunctionCallChain = new FunctionCallChainExpression(context, lcontext);
-			m_SourceRef = BuildSourceRef(lcontext, context.Start, context.Stop);
+			m_SourceRef = BuildSourceRef(context.Start, context.Stop);
 		}
 		}
 
 
 
 

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/FunctionDefinitionStatement.cs

@@ -27,7 +27,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			m_FuncSymbol = lcontext.Scope.TryDefineLocal(context.NAME().GetText());
 			m_FuncSymbol = lcontext.Scope.TryDefineLocal(context.NAME().GetText());
 			m_FuncDef = new FunctionDefinitionExpression(context.funcbody(), lcontext, context);
 			m_FuncDef = new FunctionDefinitionExpression(context.funcbody(), lcontext, context);
 
 
-			m_SourceRef = BuildSourceRef(lcontext, context.Start, context.Stop);
+			m_SourceRef = BuildSourceRef(context.Start, context.Stop);
 
 
 			m_FriendlyName = string.Format("{0} (local)", m_FuncSymbol.i_Name);
 			m_FriendlyName = string.Format("{0} (local)", m_FuncSymbol.i_Name);
 		}
 		}
@@ -44,7 +44,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			string nameOfMethodAccessor = methodaccessor != null ? methodaccessor.Text : null;
 			string nameOfMethodAccessor = methodaccessor != null ? methodaccessor.Text : null;
 			m_TableAccessors = tableaccessor != null ? tableaccessor.Select(s => s.NAME().GetText()).ToList() : new List<string>();
 			m_TableAccessors = tableaccessor != null ? tableaccessor.Select(s => s.NAME().GetText()).ToList() : new List<string>();
 
 
-			m_SourceRef = BuildSourceRef(lcontext, context.Start, context.Stop);
+			m_SourceRef = BuildSourceRef(context.Start, context.Stop).SetNoBreakPoint();
 
 
 			m_FuncDef = new FunctionDefinitionExpression(context.funcbody(), lcontext, context, nameOfMethodAccessor != null);
 			m_FuncDef = new FunctionDefinitionExpression(context.funcbody(), lcontext, context, nameOfMethodAccessor != null);
 
 

+ 3 - 3
src/MoonSharp.Interpreter/Tree/Statements/IfStatement.cs

@@ -42,7 +42,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				{ 
 				{ 
 					Exp = NodeFactory.CreateExpression(exp, lcontext), 
 					Exp = NodeFactory.CreateExpression(exp, lcontext), 
 					Block = NodeFactory.CreateStatement(blk, lcontext),
 					Block = NodeFactory.CreateStatement(blk, lcontext),
-					Source = BuildSourceRef(lcontext, 
+					Source = BuildSourceRef(
 						i == 0 ? context.IF().Symbol : context.ELSEIF()[i - 1].Symbol 
 						i == 0 ? context.IF().Symbol : context.ELSEIF()[i - 1].Symbol 
 						, exp.Stop)
 						, exp.Stop)
 				};
 				};
@@ -56,10 +56,10 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				lcontext.Scope.PushBlock();
 				lcontext.Scope.PushBlock();
 				m_Else = NodeFactory.CreateStatement(context.block()[bcount - 1], lcontext);
 				m_Else = NodeFactory.CreateStatement(context.block()[bcount - 1], lcontext);
 				m_ElseStackFrame = lcontext.Scope.PopBlock();
 				m_ElseStackFrame = lcontext.Scope.PopBlock();
-				m_ElseRef = BuildSourceRef(lcontext, context.ELSE()); 
+				m_ElseRef = BuildSourceRef(context.ELSE()); 
 			}
 			}
 
 
-			m_End = BuildSourceRef(lcontext, context.Stop, context.END());
+			m_End = BuildSourceRef(context.Stop, context.END());
 		}
 		}
 
 
 
 

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/RepeatStatement.cs

@@ -26,8 +26,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			m_Condition = NodeFactory.CreateExpression(exp, lcontext);
 			m_Condition = NodeFactory.CreateExpression(exp, lcontext);
 			m_StackFrame = lcontext.Scope.PopBlock();
 			m_StackFrame = lcontext.Scope.PopBlock();
 
 
-			m_Repeat = BuildSourceRef(lcontext, context.Start, context.REPEAT());
-			m_Until = BuildSourceRef(lcontext, exp.Start, exp.Stop);
+			m_Repeat = BuildSourceRef(context.Start, context.REPEAT());
+			m_Until = BuildSourceRef(exp.Start, exp.Stop);
 		}
 		}
 
 
 
 

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/ReturnStatement.cs

@@ -22,11 +22,11 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			if (expr != null)
 			if (expr != null)
 			{
 			{
 				m_Expression = NodeFactory.CreateExpression(expr, lcontext);
 				m_Expression = NodeFactory.CreateExpression(expr, lcontext);
-				m_Ref = BuildSourceRef(lcontext, context.Start, expr.Stop);
+				m_Ref = BuildSourceRef(context.Start, expr.Stop);
 			}
 			}
 			else
 			else
 			{
 			{
-				m_Ref = BuildSourceRef(lcontext, context.Start, context.RETURN());
+				m_Ref = BuildSourceRef(context.Start, context.RETURN());
 			}
 			}
 		}
 		}
 
 

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/ScopeBlockStatement.cs

@@ -20,8 +20,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			lcontext.Scope.PushBlock();
 			lcontext.Scope.PushBlock();
 			m_Block = NodeFactory.CreateStatement(context.block(), lcontext);
 			m_Block = NodeFactory.CreateStatement(context.block(), lcontext);
 
 
-			m_Do = BuildSourceRef(lcontext, context.Start, context.DO());
-			m_End = BuildSourceRef(lcontext, context.Stop, context.END());
+			m_Do = BuildSourceRef(context.Start, context.DO());
+			m_End = BuildSourceRef(context.Stop, context.END());
 
 
 			m_StackFrame = lcontext.Scope.PopBlock();
 			m_StackFrame = lcontext.Scope.PopBlock();
 		}
 		}

+ 2 - 2
src/MoonSharp.Interpreter/Tree/Statements/WhileStatement.cs

@@ -22,8 +22,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			var exp = context.exp();
 			var exp = context.exp();
 			m_Condition = NodeFactory.CreateExpression(exp, lcontext);
 			m_Condition = NodeFactory.CreateExpression(exp, lcontext);
 
 
-			m_Start = BuildSourceRef(lcontext, context.Start, exp.Stop);
-			m_End = BuildSourceRef(lcontext, context.Stop, context.END());
+			m_Start = BuildSourceRef(context.Start, exp.Stop);
+			m_End = BuildSourceRef(context.Stop, context.END());
 
 
 			lcontext.Scope.PushBlock();
 			lcontext.Scope.PushBlock();
 			m_Block = NodeFactory.CreateStatement(context.block(), lcontext);
 			m_Block = NodeFactory.CreateStatement(context.block(), lcontext);

+ 56 - 15
src/MoonSharp.RemoteDebugger/DebugServer.cs

@@ -14,12 +14,18 @@ namespace MoonSharp.RemoteDebugger
 {
 {
 	public class DebugServer : IDebugger
 	public class DebugServer : IDebugger
 	{
 	{
-		List<string> m_Watches = new List<string>();
+		List<DynamicExpression> m_Watches = new List<DynamicExpression>();
 		HashSet<string> m_WatchesChanging = new HashSet<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;
 		object m_Lock = new object();
 		object m_Lock = new object();
+		BlockingQueue<DebuggerAction> m_QueuedActions = new BlockingQueue<DebuggerAction>();
+		SourceRef m_LastSentSourceRef = null;
+		bool m_InGetActionLoop = false;
+		bool m_HostBusySent = false;
+		private bool m_RequestPause = false;
+		string[] m_CachedWatches = new string[(int)WatchType.MaxValue];
 
 
 
 
 		public DebugServer(string appName, Script script, int port, bool localOnly)
 		public DebugServer(string appName, Script script, int port, bool localOnly)
@@ -85,7 +91,7 @@ namespace MoonSharp.RemoteDebugger
 
 
 			string xml = sb.ToString();
 			string xml = sb.ToString();
 			m_Server.BroadcastMessage(xml);
 			m_Server.BroadcastMessage(xml);
-			Console.WriteLine(xml);
+			//Console.WriteLine(xml);
 		}
 		}
 
 
 
 
@@ -102,9 +108,6 @@ namespace MoonSharp.RemoteDebugger
 			});
 			});
 		}
 		}
 
 
-		string[] m_CachedWatches = new string[(int)WatchType.MaxValue];
-
-
 		public void Update(WatchType watchType, IEnumerable<WatchItem> items)
 		public void Update(WatchType watchType, IEnumerable<WatchItem> items)
 		{
 		{
 			if (watchType != WatchType.CallStack && watchType != WatchType.Watches)
 			if (watchType != WatchType.CallStack && watchType != WatchType.Watches)
@@ -147,7 +150,9 @@ namespace MoonSharp.RemoteDebugger
 								if (wi.Value != null)
 								if (wi.Value != null)
 								{
 								{
 									xw.Attribute("value", wi.Value.ToString());
 									xw.Attribute("value", wi.Value.ToString());
-									xw.Attribute("type", wi.Value.Type.ToLuaDebuggerString());
+									xw.Attribute("type", 
+										wi.IsError ? "error" : 
+										wi.Value.Type.ToLuaDebuggerString());
 								}
 								}
 
 
 								xw.Attribute("address", wi.Address.ToString("X8"));
 								xw.Attribute("address", wi.Address.ToString("X8"));
@@ -176,11 +181,6 @@ namespace MoonSharp.RemoteDebugger
 
 
 		#endregion
 		#endregion
 
 
-		BlockingQueue<DebuggerAction> m_QueuedActions = new BlockingQueue<DebuggerAction>();
-		SourceRef m_LastSentSourceRef = null;
-		bool m_InGetActionLoop = false;
-		bool m_HostBusySent = false;
-
 		public void QueueAction(DebuggerAction action)
 		public void QueueAction(DebuggerAction action)
 		{
 		{
 			m_QueuedActions.Enqueue(action);
 			m_QueuedActions.Enqueue(action);
@@ -191,6 +191,7 @@ namespace MoonSharp.RemoteDebugger
 			try
 			try
 			{
 			{
 				m_InGetActionLoop = true;
 				m_InGetActionLoop = true;
+				m_RequestPause = false;
 
 
 				if (m_HostBusySent)
 				if (m_HostBusySent)
 				{
 				{
@@ -214,8 +215,17 @@ namespace MoonSharp.RemoteDebugger
 					{
 					{
 						lock (m_Lock)
 						lock (m_Lock)
 						{
 						{
-							m_Watches.Clear();
-							m_Watches.AddRange(m_WatchesChanging);
+							HashSet<string> existing = new HashSet<string>();
+
+							// remove all not present anymore
+							m_Watches.RemoveAll(de => !m_WatchesChanging.Contains(de.ExpressionCode));
+
+							// add all missing
+							existing.UnionWith(m_Watches.Select(de => de.ExpressionCode));
+
+							m_Watches.AddRange(m_WatchesChanging
+								.Where(code => !existing.Contains(code))
+								.Select(code => CreateDynExpr(code)));
 						}
 						}
 
 
 						return da;
 						return da;
@@ -234,6 +244,19 @@ namespace MoonSharp.RemoteDebugger
 			}
 			}
 		}
 		}
 
 
+		private DynamicExpression CreateDynExpr(string code)
+		{
+			try
+			{
+				return m_Script.CreateDynamicExpression(code);
+			}
+			catch (Exception ex)
+			{
+				SendMessage(string.Format("Error setting watch {0} :\n{1}", code, ex.Message));
+				return m_Script.CreateConstantDynamicExpression(code, DynValue.NewString(ex.Message));
+			}
+		}
+
 		private void SendSourceRef(XmlWriter xw, SourceRef sourceref)
 		private void SendSourceRef(XmlWriter xw, SourceRef sourceref)
 		{
 		{
 			using (xw.Element("source-loc"))
 			using (xw.Element("source-loc"))
@@ -278,6 +301,9 @@ namespace MoonSharp.RemoteDebugger
 					case "stepout":
 					case "stepout":
 						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOut });
 						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOut });
 						break;
 						break;
+					case "pause":
+						m_RequestPause = true;
+						break;
 					case "addwatch":
 					case "addwatch":
 						lock (m_Lock)
 						lock (m_Lock)
 							m_WatchesChanging.UnionWith(arg.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()));
 							m_WatchesChanging.UnionWith(arg.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()));
@@ -294,6 +320,15 @@ namespace MoonSharp.RemoteDebugger
 						}
 						}
 						QueueRefresh();
 						QueueRefresh();
 						break;
 						break;
+					case "breakpoint":
+						QueueAction(new DebuggerAction() 
+						{
+							Action = DebuggerAction.ActionType.ToggleBreakpoint,
+							SourceID = int.Parse(xdoc.DocumentElement.GetAttribute("src")),
+							SourceLine = int.Parse(xdoc.DocumentElement.GetAttribute("line")),
+							SourceCol = int.Parse(xdoc.DocumentElement.GetAttribute("col")),
+						});
+						break;
 				}
 				}
 
 
 			}
 			}
@@ -319,7 +354,7 @@ namespace MoonSharp.RemoteDebugger
 		}
 		}
 
 
 
 
-		public List<string> GetWatchItems()
+		public List<DynamicExpression> GetWatchItems()
 		{
 		{
 			return m_Watches;
 			return m_Watches;
 		}
 		}
@@ -327,7 +362,7 @@ namespace MoonSharp.RemoteDebugger
 
 
 		public bool IsPauseRequested()
 		public bool IsPauseRequested()
 		{
 		{
-			return false;
+			return m_RequestPause;
 		}
 		}
 
 
 
 
@@ -348,5 +383,11 @@ namespace MoonSharp.RemoteDebugger
 				}
 				}
 			});
 			});
 		}
 		}
+
+
+
+
+
+
 	}
 	}
 }
 }

+ 2 - 2
src/MoonSharp/MoonSharp.csproj

@@ -41,7 +41,7 @@
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup>
   <PropertyGroup>
-    <ApplicationIcon>moonsharp256.ico</ApplicationIcon>
+    <ApplicationIcon>moonsharp.ico</ApplicationIcon>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
@@ -87,7 +87,7 @@
     <None Include="app.config" />
     <None Include="app.config" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <Content Include="moonsharp256.ico" />
+    <Content Include="moonsharp.ico" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 16 - 4
src/MoonSharp/Program.cs

@@ -90,13 +90,25 @@ namespace MoonSharp
 
 
 					try
 					try
 					{
 					{
-						var v = script.LoadString(cmd, null, "stdin");
-
-						Console.WriteLine("={0}", script.Call(v));
+						DynValue result = null;
+
+						if (cmd.StartsWith("?"))
+						{
+							var code = cmd.Substring(1);
+							var exp = script.CreateDynamicExpression(code);
+							result = exp.Evaluate(script.CreateMockExecutionContext());
+						}
+						else
+						{
+							var v = script.LoadString(cmd, null, "stdin");
+							result = script.Call(v);
+						}
+
+						Console.WriteLine("={0}", result);
 					}
 					}
 					catch (ScriptRuntimeException ex)
 					catch (ScriptRuntimeException ex)
 					{
 					{
-						Console.WriteLine("{0}", ex.DecoratedMessage);
+						Console.WriteLine("{0}", ex.DecoratedMessage ?? ex.Message);
 					}
 					}
 					catch (Exception ex)
 					catch (Exception ex)
 					{
 					{

BIN
src/MoonSharp/moonsharp.ico


BIN
src/MoonSharp/moonsharp256.ico