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/).
 Copyright of The Eclipse Foundation
 
+The MoonSharp icon is (c) Voontrag, 2014
+
 
 Redistribution and use in source and binary forms, with or without
 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.
             swfobject.createCSS("#flashContent", "display:block;text-align:left;");
         </script>
+       
     </head>
     <body>
         <!-- 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"+ 
 					"Copyright of The Eclipse Foundation\n"+ 
 					"\n"+ 
+					"The MoonSharp icon is (c) Voontrag, 2014\n" +
+					"\n"+
 					"\n"+ 
 					"Redistribution and use in source and binary forms, with or without\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 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');"/>
+	<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:TitleWindow>

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

@@ -87,6 +87,10 @@ package
 			{
 				logMessage(xml.toString());	
 			}
+			else if (cmd == "breakpoints")
+			{
+				refreshBreakpoints(xml);
+			}
 		}
 		
 		public function getInstructionPtrHighlight():Highlight
@@ -129,7 +133,7 @@ package
 			}
 			else
 			{
-				trace("defaulting to default highlight...");
+				logMessage("ERROR: Highlighted source " + srcid.toString() + " not found in sources list.");
 				return null;	
 			}
 		}
@@ -160,8 +164,24 @@ package
 		
 		private function securityErrorHandler(event:SecurityErrorEvent):void {
 			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
 		{
 			m_Socket.send(<Command cmd="refresh" />);		
@@ -187,6 +207,11 @@ package
 			m_Socket.send(<Command cmd="run" />);		
 		}
 		
+		public function pause() : void
+		{
+			m_Socket.send(<Command cmd="pause" />);		
+		}
+		
 		public function addWatch(varNames : String) : void
 		{
 			var cmd:XML = <Command cmd="addWatch" />;
@@ -199,7 +224,17 @@ package
 			var cmd:XML = <Command cmd="delWatch" />;
 			cmd.@arg = varNames;
 			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
 {
 	color: #CCCCCC;
+	background-color: #555555;
+	contentBackgroundColor: #555555;
 }
 
 s|Panel
@@ -147,3 +149,6 @@ mx|MenuBar
 	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="Main.css"/>
-
+	
 	<fx:Script>
 		
 		<![CDATA[
@@ -19,26 +19,43 @@
 			import mx.events.FlexEvent;
 			import mx.events.MenuEvent;
 			
+			import spark.components.TextSelectionHighlighting;
 			import spark.events.IndexChangeEvent;
 			import spark.events.TextOperationEvent;
-
+			
 			[Bindable]
 			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 =
 				<>
 					<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 label="Run" data="1B"/>
-						<menuitem label="Pause" data="1B"/>
+						<menuitem label="(B) - Toggle breakpoint" data="breakpoint" icon="breakpoint" />
 						<menuitem type="separator"/>
-						<menuitem label="Toggle breakpoint" data="1B"/>
+						<menuitem label="(G) - Go to current" data="step_current" icon="step_current" />
 					</menuitem>
 					<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 label="Help" data="top">
 						<menuitem label="About..." data="about"/>
@@ -53,8 +70,7 @@
 			{
 				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
 			{
 				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
@@ -103,6 +156,26 @@
 					tlf2.backgroundColor = 0xb1aefa;
 					
 					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();
 				m_CurrentSrc = S;
 				refreshInstructionPtrHighlight(false);
+				refreshBreakpoints();
+				updateCaretLabel();
 			}
 			
 			protected function getSourceName(o : Object) : String
@@ -143,131 +218,196 @@
 				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:Declarations>
 		<!-- Place non-visual elements (e.g., services, value objects) here -->
-	
+		
 	</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: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: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>
-					</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: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>

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

@@ -8,7 +8,7 @@ package
 		private var m_Text : String;
 		private var m_CumulativeLength : Vector.<int> = new Vector.<int>();
 		
-	
+		public var Breakpoints : Vector.<Highlight> = new Vector.<Highlight>();
 		
 		public function SourceCode(xml: XML)
 		{
@@ -47,5 +47,37 @@ package
 			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
 	{
-		List<string> m_Watches = new List<string>();
+		List<DynamicExpression> m_Watches = new List<DynamicExpression>();
 
 		public MainForm()
 		{
@@ -281,7 +281,7 @@ namespace MoonSharp.Debugger
 
 
 
-		List<string> IDebugger.GetWatchItems()
+		List<DynamicExpression> IDebugger.GetWatchItems()
 		{
 			return m_Watches;
 		}
@@ -292,7 +292,9 @@ namespace MoonSharp.Debugger
 
 			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 });
 			}
 		}
@@ -301,7 +303,7 @@ namespace MoonSharp.Debugger
 		{
 			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)
 				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);
 		void SignalExecutionEnded();
 		void Update(WatchType watchType, IEnumerable<WatchItem> items);
-		List<string> GetWatchItems();
+		List<DynamicExpression> GetWatchItems();
 		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 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)
 		{
@@ -35,6 +38,57 @@ namespace MoonSharp.Interpreter.Debugging
 				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)
 		{
 			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 DynValue Value { get; set; }
 		public SymbolRef LValue { get; set; }
+		public bool IsError { get; set; }
 
 		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>
 		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();
 			}
 		}
+
+		/// <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 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;
 					break;
 				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;
 				case DebuggerAction.ActionType.StepOver:
 					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);
 
+			bool found = false;
 			foreach (SourceRef srf in src.Refs)
 			{
+				if (srf.CannotBreakpoint)
+					continue;
+
 				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;
 
 					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)
 		{
-			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> watches = Debugger_RefreshWatches(watchList);
+			List<WatchItem> watches = Debugger_RefreshWatches(context, watchList);
 			List<WatchItem> vstack = Debugger_RefreshVStack();
+
 			m_Debug.DebuggerAttached.Update(WatchType.CallStack, callStack);
 			m_Debug.DebuggerAttached.Update(WatchType.Watches, watches);
 			m_Debug.DebuggerAttached.Update(WatchType.VStack, vstack);
@@ -147,29 +199,34 @@ namespace MoonSharp.Interpreter.Execution.VM
 			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()
 				{
+					IsError = dynExpr.IsConstant(),
 					LValue = L,
 					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)
 		{
-			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)

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

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

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

@@ -92,6 +92,8 @@
     <Compile Include="CoreLib\StringLib\KopiLua_StrLib.cs" />
     <Compile Include="DataTypes\ScriptFunctionDelegate.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\LuaBase.cs" />
     <Compile Include="CoreLib\StringLib\MatchState.cs">
@@ -222,6 +224,7 @@
     <Compile Include="Tree\Antlr_Interface\AntlrErrorListener.cs" />
     <Compile Include="Tree\Expressions\AdjustmentExpression.cs" />
     <Compile Include="Tree\Expressions\BinaryOperatorExpression.cs" />
+    <Compile Include="Tree\Expressions\DynamicExpression.cs" />
     <Compile Include="Tree\Expressions\PowerOperatorExpression.cs" />
     <Compile Include="Tree\Expressions\UnaryOperatorExpression.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.Debugging;
 using MoonSharp.Interpreter.Diagnostics;
+using MoonSharp.Interpreter.Execution;
 using MoonSharp.Interpreter.Execution.VM;
 using MoonSharp.Interpreter.Interop;
 using MoonSharp.Interpreter.Loaders;
 using MoonSharp.Interpreter.Tree;
+using MoonSharp.Interpreter.Tree.Expressions;
 using MoonSharp.Interpreter.Tree.Statements;
 
 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>
 	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)
 		{
@@ -68,7 +93,7 @@ namespace MoonSharp.Interpreter.Tree
 			AntlrErrorListener listener = new AntlrErrorListener(source);
 			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);
 				FunctionDefinitionExpression fndef;

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

@@ -14,5 +14,11 @@ namespace MoonSharp.Interpreter.Tree
 			: 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();
 		}
 
-
+		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;
 		}
 
+		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)
 		{
 			Operator opfound = 0;
@@ -102,13 +109,6 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 		/// </summary>
 		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();
 
 			Operator opfound = CreateLinkedList(list, tree, lcontext);
@@ -324,5 +324,137 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			if (ShouldInvertBoolean(m_Operator))
 				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)
 				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_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)
@@ -173,5 +173,10 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			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);
 		}
 
+		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);
 			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
 	{
 		SymbolRef m_Ref;
+		string m_VarName;
 
 		public SymbolRefExpression(IParseTree context, ScriptLoadingContext lcontext, SymbolRef refr)
 			: base(context, lcontext)
 		{
 			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");
 			}
+
+			if (lcontext.IsDynamicExpression)
+			{
+				throw new DynamicExpressionException("Cannot use '...' in a dynamic expression.");
+			}
 		}
 
 
 		public SymbolRefExpression(ITerminalNode terminalNode, ScriptLoadingContext 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);
 		}
+
+		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);
 
-		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;
-			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;
 		}
 

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

@@ -211,7 +211,7 @@ namespace MoonSharp.Interpreter.Tree
 				else
 					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);
 				}

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

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

+ 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_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)

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

@@ -20,7 +20,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			: base(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_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);
 		}
@@ -44,7 +44,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			string nameOfMethodAccessor = methodaccessor != null ? methodaccessor.Text : null;
 			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);
 

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

@@ -42,7 +42,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				{ 
 					Exp = NodeFactory.CreateExpression(exp, lcontext), 
 					Block = NodeFactory.CreateStatement(blk, lcontext),
-					Source = BuildSourceRef(lcontext, 
+					Source = BuildSourceRef(
 						i == 0 ? context.IF().Symbol : context.ELSEIF()[i - 1].Symbol 
 						, exp.Stop)
 				};
@@ -56,10 +56,10 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				lcontext.Scope.PushBlock();
 				m_Else = NodeFactory.CreateStatement(context.block()[bcount - 1], lcontext);
 				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_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)
 			{
 				m_Expression = NodeFactory.CreateExpression(expr, lcontext);
-				m_Ref = BuildSourceRef(lcontext, context.Start, expr.Stop);
+				m_Ref = BuildSourceRef(context.Start, expr.Stop);
 			}
 			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();
 			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();
 		}

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

@@ -22,8 +22,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			var exp = context.exp();
 			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();
 			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
 	{
-		List<string> m_Watches = new List<string>();
+		List<DynamicExpression> m_Watches = new List<DynamicExpression>();
 		HashSet<string> m_WatchesChanging = new HashSet<string>();
 		Utf8TcpServer m_Server;
 		Script m_Script;
 		string m_AppName;
 		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)
@@ -85,7 +91,7 @@ namespace MoonSharp.RemoteDebugger
 
 			string xml = sb.ToString();
 			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)
 		{
 			if (watchType != WatchType.CallStack && watchType != WatchType.Watches)
@@ -147,7 +150,9 @@ namespace MoonSharp.RemoteDebugger
 								if (wi.Value != null)
 								{
 									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"));
@@ -176,11 +181,6 @@ namespace MoonSharp.RemoteDebugger
 
 		#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)
 		{
 			m_QueuedActions.Enqueue(action);
@@ -191,6 +191,7 @@ namespace MoonSharp.RemoteDebugger
 			try
 			{
 				m_InGetActionLoop = true;
+				m_RequestPause = false;
 
 				if (m_HostBusySent)
 				{
@@ -214,8 +215,17 @@ namespace MoonSharp.RemoteDebugger
 					{
 						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;
@@ -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)
 		{
 			using (xw.Element("source-loc"))
@@ -278,6 +301,9 @@ namespace MoonSharp.RemoteDebugger
 					case "stepout":
 						QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOut });
 						break;
+					case "pause":
+						m_RequestPause = true;
+						break;
 					case "addwatch":
 						lock (m_Lock)
 							m_WatchesChanging.UnionWith(arg.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()));
@@ -294,6 +320,15 @@ namespace MoonSharp.RemoteDebugger
 						}
 						QueueRefresh();
 						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;
 		}
@@ -327,7 +362,7 @@ namespace MoonSharp.RemoteDebugger
 
 		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>
   </PropertyGroup>
   <PropertyGroup>
-    <ApplicationIcon>moonsharp256.ico</ApplicationIcon>
+    <ApplicationIcon>moonsharp.ico</ApplicationIcon>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
     <DebugSymbols>true</DebugSymbols>
@@ -87,7 +87,7 @@
     <None Include="app.config" />
   </ItemGroup>
   <ItemGroup>
-    <Content Include="moonsharp256.ico" />
+    <Content Include="moonsharp.ico" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- 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
 					{
-						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)
 					{
-						Console.WriteLine("{0}", ex.DecoratedMessage);
+						Console.WriteLine("{0}", ex.DecoratedMessage ?? ex.Message);
 					}
 					catch (Exception ex)
 					{

BIN
src/MoonSharp/moonsharp.ico


BIN
src/MoonSharp/moonsharp256.ico