Browse Source

Working on ANTLR optimization - rewrote operators..

Xanathar 11 năm trước cách đây
mục cha
commit
d7e2480d74

+ 59 - 0
src/MoonSharp.Interpreter.Tests/EndToEnd/SimpleTests.cs

@@ -463,6 +463,65 @@ namespace MoonSharp.Interpreter.Tests
 			Assert.AreEqual(120.0, res.Number);
 		}
 
+		[Test]
+		public void OperatorPrecedence1()
+		{
+			string script = @"return 1+2*3";
+
+			DynValue res = Script.RunString(script);
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(7, res.Number);
+		}
+		[Test]
+		public void OperatorPrecedence2()
+		{
+			string script = @"return 2*3+1";
+
+			DynValue res = Script.RunString(script);
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(7, res.Number);
+		}
+
+		[Test]
+		public void OperatorAssociativity()
+		{
+			string script = @"return 2^3^2";
+
+			DynValue res = Script.RunString(script);
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(512, res.Number);
+		}
+
+		[Test]
+		public void OperatorPrecedence3()
+		{
+			string script = @"return 5-3-2";
+			Script S = new Script(CoreModules.None);
+
+			DynValue res = S.DoString(script);
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(0, res.Number);
+		}
+
+		[Test]
+		public void OperatorPrecedence4()
+		{
+			string script = @"return 3 + -1";
+			Script S = new Script(CoreModules.None);
+
+			DynValue res = S.DoString(script);
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(2, res.Number);
+		}
+
+
+
+
 		[Test]
 		public void OperatorPrecedenceAndAssociativity()
 		{

+ 46 - 19
src/MoonSharp.Interpreter/Grammar/Lua.g4

@@ -10,7 +10,7 @@ All rights reserved.
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
-
+ 
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
@@ -80,6 +80,7 @@ label
     : '::' NAME '::'
     ;
 
+// this is an addition
 funcnametableaccessor 
 	: ('.' NAME);
 
@@ -99,22 +100,48 @@ explist
     : exp (',' exp)*
     ;
 
-exp
-    : 'nil' | 'false' | 'true' | number | string		
+expterm 
+	: 'nil' | 'false' | 'true' | number | string		
 	| vararg
 	| anonfunctiondef								
-    | prefixexp										
-	| tableconstructor								
-	| <assoc=right> exp operatorPower exp			
-	| operatorUnary exp								
-	| exp operatorMulDivMod exp		
-	| exp operatorAddSub exp						
-	| <assoc=right> exp operatorStrcat exp			
-	| exp operatorComparison exp					
-	| exp operatorAnd exp							
-	| exp operatorOr exp	
+    | prefixexp										 
+	| tableconstructor
+	;
+	
+powerExp 
+	: expterm 													#exp_powerfallback
+	| expterm operatorPower powerExp							#exp_power
+	;
+unaryExp 
+	: powerExp 													#exp_unaryfallback
+	| operatorUnary unaryExp									#exp_unary
+	;
+muldivExp 
+	: unaryExp 													#exp_muldivfallback
+	| unaryExp operatorMulDivMod muldivExp						#exp_muldiv
+	;
+addsubExp 
+	: muldivExp 												#exp_addsubfallback
+	| muldivExp operatorAddSub addsubExp						#exp_addsub
+	;
+strcatExp 	
+	: addsubExp 												#exp_strcastfallback
+	| addsubExp operatorStrcat strcatExp						#exp_strcat
+	;
+compareExp 
+	: strcatExp 												#exp_comparefallback
+	| strcatExp operatorComparison compareExp                   #exp_compare
+	;
+logicAndExp 
+	: compareExp 												#exp_logicAndfallback
+	| compareExp operatorAnd logicAndExp                        #exp_logicAnd
+	;
+exp 
+	: logicAndExp 												#exp_logicOrfallback
+	| logicAndExp operatorOr exp								#exp_logicOr
 	;
 
+
 var
     : (NAME | '(' exp ')' varSuffix) varSuffix*
     ;
@@ -149,13 +176,13 @@ anonfunctiondef
     : 'function' funcbody
     ;
 
-lambdaexp
-	: '[' parlist ':' exp ']'
-	;
+//lambdaexp
+//	: '[' parlist ':' exp ']'
+//	;
 
-lambdastat
-	: '[' parlist ':' 'do' block 'end' ']'
-	;
+//lambdastat
+//	: '[' parlist ':' 'do' block 'end' ']'
+//	;
 
 // A func body from the parlist to end. 
 funcbody

+ 2 - 0
src/MoonSharp.Interpreter/Modules/CoreModules.cs

@@ -8,6 +8,8 @@ namespace MoonSharp.Interpreter
 	[Flags]
 	public enum CoreModules
 	{
+		None = 0,
+
 		Basic = 0x40,
 		GlobalConsts = 0x1,
 		TableIterators = 0x2,

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

@@ -246,6 +246,7 @@
       <CustomToolNamespace>MoonSharp.Interpreter.Grammar</CustomToolNamespace>
       <Listener>False</Listener>
       <Visitor>False</Visitor>
+      <ForceAtn>False</ForceAtn>
     </Antlr4>
   </ItemGroup>
   <ItemGroup>

+ 2 - 2
src/MoonSharp.Interpreter/Properties/AssemblyInfo.cs

@@ -27,10 +27,10 @@ using System.Runtime.InteropServices;
 //      Major Version
 //      Minor Version 
 //      Build Number
-//      Revision
+//      Revision 
 //
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.5.2.0")]
+[assembly: AssemblyVersion("0.5.4.0")]
 [assembly: AssemblyFileVersion("1.0.0.0")]

+ 78 - 16
src/MoonSharp.Interpreter/Tree/Expressions/OperatorExpression.cs

@@ -24,6 +24,7 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 		}
 
 		static HashSet<Type> s_OperatorTypes = new HashSet<Type>();
+		static HashSet<Type> s_LeftAssocOperatorTypes = new HashSet<Type>();
 
 		static OperatorExpression()
 		{
@@ -35,28 +36,71 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 			s_OperatorTypes.Add(typeof(LuaParser.OperatorMulDivModContext));
 			s_OperatorTypes.Add(typeof(LuaParser.OperatorUnaryContext));
 			s_OperatorTypes.Add(typeof(LuaParser.OperatorPowerContext));
+
+			s_LeftAssocOperatorTypes.Add(typeof(LuaParser.Exp_logicOrContext));
+			s_LeftAssocOperatorTypes.Add(typeof(LuaParser.Exp_logicAndContext));
+			s_LeftAssocOperatorTypes.Add(typeof(LuaParser.Exp_compareContext));
+			s_LeftAssocOperatorTypes.Add(typeof(LuaParser.Exp_addsubContext));
+			s_LeftAssocOperatorTypes.Add(typeof(LuaParser.Exp_muldivContext));
 		}
 
+		bool m_IsUnary = false;
 		Operator m_Operator;
-		Expression m_Exp1 = null;
-		Expression m_Exp2 = null;
+		Expression m_Exp1;
+		Expression m_Exp2;
+		List<Expression> m_Exps;
+		List<Operator> m_Ops;
 
-		public OperatorExpression(LuaParser.ExpContext tree, ScriptLoadingContext lcontext)
+		public OperatorExpression(IParseTree tree, ScriptLoadingContext lcontext)
 			: base(tree, lcontext)
 		{
-			if (s_OperatorTypes.Contains(tree.GetChild(0).GetType()))
+			var child0 = tree.GetChild(0);
+
+			if (s_OperatorTypes.Contains(child0.GetType()))
 			{
 				// unary op
 				SyntaxAssert(tree.ChildCount == 2, "Unexpected node found");
-				m_Operator = ParseUnaryOperator(tree.GetChild(0));
+				m_Operator = ParseUnaryOperator(child0);
 				m_Exp1 = NodeFactory.CreateExpression(tree.GetChild(1), lcontext);
+				m_IsUnary = true;
+			}
+			else if (s_LeftAssocOperatorTypes.Contains(tree.GetType()))
+			{
+				// binary right associative op or simple left associative
+				IParseTree child2 = tree.GetChild(2);
+
+				if(child2.GetType() == tree.GetType())
+				{
+					m_Exps = new List<Expression>();
+					m_Ops = new List<Operator>();
+
+					m_Operator = ParseBinaryOperator(tree.GetChild(1));
+
+					while (child2.GetType() == tree.GetType())
+					{
+						m_Exps.Add(NodeFactory.CreateExpression(child2.GetChild(0), lcontext));
+						m_Ops.Add(m_Operator);
+						m_Operator = ParseBinaryOperator(child2.GetChild(1));
+						child2 = child2.GetChild(2);
+					}
+
+					m_Exp1 = NodeFactory.CreateExpression(child0, lcontext);
+					m_Exp2 = NodeFactory.CreateExpression(child2, lcontext);
+				}
+				else
+				{
+					SyntaxAssert(tree.ChildCount == 3, "Unexpected node found");
+					m_Operator = ParseBinaryOperator(tree.GetChild(1));
+					m_Exp1 = NodeFactory.CreateExpression(child0, lcontext);
+					m_Exp2 = NodeFactory.CreateExpression(child2, lcontext);
+				}
 			}
 			else
 			{
-				// binary op
+				// binary right associative op or simple left associative
 				SyntaxAssert(tree.ChildCount == 3, "Unexpected node found");
 				m_Operator = ParseBinaryOperator(tree.GetChild(1));
-				m_Exp1 = NodeFactory.CreateExpression(tree.GetChild(0), lcontext);
+				m_Exp1 = NodeFactory.CreateExpression(child0, lcontext);
 				m_Exp2 = NodeFactory.CreateExpression(tree.GetChild(2), lcontext);
 			}
 
@@ -131,34 +175,52 @@ namespace MoonSharp.Interpreter.Tree.Expressions
 		{
 			m_Exp1.Compile(bc);
 
-			if (m_Operator == Operator.Or)
+			if (m_Exps != null)
+			{
+				for (int i = 0; i < m_Ops.Count; i++)
+				{
+					CompileOp(bc, m_Ops[i], m_Exps[i]);
+				}
+			}
+
+			{
+				CompileOp(bc, m_Operator, m_Exp2);
+			}
+
+		}
+
+		private void CompileOp(Execution.VM.ByteCode bc, Operator op, Expression exp)
+		{
+			if (op == Operator.Or)
 			{
 				Instruction i = bc.Emit_Jump(OpCode.JtOrPop, -1);
-				m_Exp2.Compile(bc);
+				exp.Compile(bc);
 				i.NumVal = bc.GetJumpPointForNextInstruction();
 				return;
 			}
 
-			if (m_Operator == Operator.And)
+			if (op == Operator.And)
 			{
 				Instruction i = bc.Emit_Jump(OpCode.JfOrPop, -1);
-				m_Exp2.Compile(bc);
+				exp.Compile(bc);
 				i.NumVal = bc.GetJumpPointForNextInstruction();
 				return;
 			}
-			
 
-			if (m_Exp2 != null)
+
+			if (exp != null)
 			{
-				m_Exp2.Compile(bc);
+				exp.Compile(bc);
 			}
 
-			bc.Emit_Operator(OperatorToOpCode(m_Operator));
+			bc.Emit_Operator(OperatorToOpCode(op));
 
-			if (ShouldInvertBoolean(m_Operator))
+			if (ShouldInvertBoolean(op))
 				bc.Emit_Operator(OpCode.Not);
 		}
 
+
+
 		private bool ShouldInvertBoolean(Operator op)
 		{
 			return (op == Operator.NotEqual)

+ 18 - 12
src/MoonSharp.Interpreter/Tree/Loader.cs

@@ -1,4 +1,4 @@
-#define DEBUG_COMPILER
+//#define DEBUG_COMPILER
 
 using System;
 using System.Collections.Generic;
@@ -6,6 +6,7 @@ using System.Diagnostics;
 using System.Linq;
 using System.Text;
 using Antlr4.Runtime;
+using Antlr4.Runtime.Atn;
 using Antlr4.Runtime.Misc;
 using Antlr4.Runtime.Tree;
 using MoonSharp.Interpreter.Diagnostics;
@@ -87,19 +88,19 @@ namespace MoonSharp.Interpreter.Tree
 		[Conditional("DEBUG_COMPILER")]
 		private static void Debug_DumpByteCode(ByteCode bytecode, int sourceIdx)
 		{
-			bytecode.Dump(string.Format(@"c:\temp\codedump_{0}.txt", sourceIdx));
+			//bytecode.Dump(string.Format(@"c:\temp\codedump_{0}.txt", sourceIdx));
 		}
 
 		[Conditional("DEBUG_COMPILER")]
 		private static void Debug_DumpAst(LuaParser parser, int sourceIdx, Func<LuaParser, IParseTree> dumper)
 		{
-			try
-			{
-				AstDump astDump = new AstDump();
-				astDump.DumpTree(dumper(parser), string.Format(@"c:\temp\treedump_{0:000}.txt", sourceIdx));
-			}
-			catch { }
-			parser.Reset();
+			//try
+			//{
+			//	AstDump astDump = new AstDump();
+			//	astDump.DumpTree(dumper(parser), string.Format(@"c:\temp\treedump_{0:000}.txt", sourceIdx));
+			//}
+			//catch { }
+			//parser.Reset();
 		}
 
 
@@ -121,11 +122,16 @@ namespace MoonSharp.Interpreter.Tree
 			//using (var _ = new CodeChrono("ChunkStatement.LoadFromICharStream/Parsing"))
 			{
 				lexer = new LuaLexer(charStream);
-				parser = new LuaParser(new CommonTokenStream(lexer));
-				parser.ErrorHandler = new BailErrorStrategy();
+				parser = new LuaParser(new CommonTokenStream(lexer))
+				{
+					ErrorHandler = new BailErrorStrategy(),
+				};
+
+				parser.Interpreter.PredictionMode = PredictionMode.Sll;
 			}
 
-			Debug_DumpAst(parser, sourceIdx, dumper);
+			//Debug_DumpAst(parser, sourceIdx, dumper);
+
 
 			return parser;
 		}

+ 20 - 19
src/MoonSharp.Interpreter/Tree/NodeFactory.cs

@@ -75,28 +75,32 @@ namespace MoonSharp.Interpreter.Tree
 
 
 
-		private static Expression CreateFromExpContext(LuaParser.ExpContext tree, ScriptLoadingContext lcontext)
+		public static Expression CreateExpression(IParseTree tree, ScriptLoadingContext lcontext)
 		{
-			if (OperatorExpression.IsOperatorExpression(tree))
+			// flatten tree for operators precedence 
+			if (tree is LuaParser.Exp_logicOrfallbackContext) tree = ((LuaParser.Exp_logicOrfallbackContext)tree).logicAndExp();
+			if (tree is LuaParser.Exp_logicAndfallbackContext) tree = ((LuaParser.Exp_logicAndfallbackContext)tree).compareExp();
+			if (tree is LuaParser.Exp_comparefallbackContext) tree = ((LuaParser.Exp_comparefallbackContext)tree).strcatExp();
+			if (tree is LuaParser.Exp_strcastfallbackContext) tree = ((LuaParser.Exp_strcastfallbackContext)tree).addsubExp();
+			if (tree is LuaParser.Exp_addsubfallbackContext) tree = ((LuaParser.Exp_addsubfallbackContext)tree).muldivExp();
+			if (tree is LuaParser.Exp_muldivfallbackContext) tree = ((LuaParser.Exp_muldivfallbackContext)tree).unaryExp();
+			if (tree is LuaParser.Exp_unaryfallbackContext) tree = ((LuaParser.Exp_unaryfallbackContext)tree).powerExp();
+			if (tree is LuaParser.Exp_powerfallbackContext) tree = ((LuaParser.Exp_powerfallbackContext)tree).expterm();
+			if (tree is LuaParser.ExptermContext) tree = tree.GetChild(0);
+
+			if (tree is LuaParser.Exp_addsubContext ||
+				tree is LuaParser.Exp_compareContext ||
+				tree is LuaParser.Exp_logicAndContext ||
+				tree is LuaParser.Exp_logicOrContext ||
+				tree is LuaParser.Exp_muldivContext ||
+				tree is LuaParser.Exp_powerContext ||
+				tree is LuaParser.Exp_strcatContext ||
+				tree is LuaParser.Exp_unaryContext)
 			{
 				return new OperatorExpression(tree, lcontext);
 			}
-			else if (tree.ChildCount > 1)
-			{
-				throw new NotImplementedException();
-			}
-			else
-			{
-				return CreateExpression(tree.GetChild(0), lcontext);
-			}
-		}
 
 
-
-
-
-		public static Expression CreateExpression(IParseTree tree, ScriptLoadingContext lcontext)
-		{
 			if (tree is LuaParser.VarOrExpContext)
 			{
 				// this whole rubbish just to detect adjustments to 1 arg of tuples
@@ -142,9 +146,6 @@ namespace MoonSharp.Interpreter.Tree
 			if (tree is LuaParser.AnonfunctiondefContext)
 				return new FunctionDefinitionExpression((LuaParser.AnonfunctiondefContext)tree, lcontext);
 
-			if (tree is LuaParser.ExpContext)
-				return CreateFromExpContext((LuaParser.ExpContext)tree, lcontext);
-
 			if (tree is LuaParser.StringContext)
 				return new LiteralExpression((LuaParser.StringContext)tree, lcontext);
 

+ 36 - 0
src/PerformanceComparison/HugeFile.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter;
+using MoonSharp.Interpreter.Grammar;
+
+namespace PerformanceComparison
+{
+	public class HugeFile
+	{
+		static void Main(string[] args)
+		{
+			Console.WriteLine("Started...");
+			Script.WarmUp();
+
+			Script s = new Script(CoreModules.None);
+			s.LoadFile(@"C:\gr\tsg\mod_assets\scripts\alcoves.lua");
+			//s.LoadFile(@"C:\temp\test3.lua");
+
+			Stopwatch sw = Stopwatch.StartNew();
+
+			//for (int i = 0; i < 10; i++)
+			s.LoadFile(@"C:\temp\test3.lua");
+
+
+			sw.Stop();
+			Console.WriteLine("Ended : {0} ms", sw.ElapsedMilliseconds);
+			Console.ReadLine();
+		}
+
+
+
+	}
+}

+ 1 - 0
src/PerformanceComparison/PerformanceComparison.csproj

@@ -76,6 +76,7 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="HugeFile.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>

+ 5 - 5
src/PerformanceComparison/Program.cs

@@ -25,7 +25,7 @@ namespace PerformanceComparison
 			function move(n, src, dst, via)
 				if n > 0 then
 					move(n - 1, src, via, dst)
-					--print(src, 'to', dst)
+					print(src, 'to', dst)
 					move(n - 1, via, dst, src)
 				end
 			end
@@ -81,7 +81,7 @@ if Find_Solution( 1 ) then
 else
     --print( 'NO!' )
 end
- 
+  
 			";
 		static StringBuilder g_MoonSharpStr = new StringBuilder();
 		static StringBuilder g_NLuaStr = new StringBuilder();
@@ -118,7 +118,7 @@ end
 		static Lua lua = new Lua();
 		static string testString = "world";
 
-		static void Main(string[] args)
+		static void xxMain(string[] args)
 		{
 			Stopwatch sw;
 
@@ -179,10 +179,10 @@ end
 			Console.WriteLine("M# == NL ? {0}", g_MoonSharpStr.ToString() == g_NLuaStr.ToString());
 
 			Console.WriteLine("=== Moon# ===");
-			Console.WriteLine(g_MoonSharpStr.ToString());
+			//Console.WriteLine(g_MoonSharpStr.ToString());
 			Console.WriteLine("");
 			Console.WriteLine("=== NLua  ===");
-			Console.WriteLine(g_NLuaStr.ToString());
+			//Console.WriteLine(g_NLuaStr.ToString());
 
 			Console.ReadKey();
 		}

+ 4 - 1
src/moonsharp.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 2013
-VisualStudioVersion = 12.0.30501.0
+VisualStudioVersion = 12.0.30723.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoonSharp", "MoonSharp\MoonSharp.csproj", "{2A4BD262-D6EB-4611-A28B-27B6DAEB089B}"
 EndProject
@@ -86,4 +86,7 @@ Global
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
 EndGlobal