From fe4fc00a1c8d8797b72de2d905fbaa9d72e74c25 Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 10 Aug 2023 18:29:18 +0100 Subject: [PATCH 1/4] += etc assignment operators --- src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs | 15 +++++++---- .../Tree/Statements/AssignmentStatement.cs | 26 ++++++++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs b/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs index de47d322..b3fd4f3e 100755 --- a/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs +++ b/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs @@ -182,7 +182,7 @@ private Token ReadToken() return CreateToken(TokenType.Dot, fromLine, fromCol, "."); } case '+': - return CreateSingleCharToken(TokenType.Op_Add, fromLine, fromCol); + return PotentiallyDoubleCharOperator('=', TokenType.Op_Add, TokenType.Op_Assignment, fromLine, fromCol); case '-': { char next = CursorCharNext(); @@ -190,19 +190,24 @@ private Token ReadToken() { return ReadComment(fromLine, fromCol); } + else if (next == '=') + { + CursorCharNext(); + return CreateToken(TokenType.Op_Assignment, fromLine, fromCol, "-="); + } else { return CreateToken(TokenType.Op_MinusOrSub, fromLine, fromCol, "-"); } } case '*': - return CreateSingleCharToken(TokenType.Op_Mul, fromLine, fromCol); + return PotentiallyDoubleCharOperator('=', TokenType.Op_Mul, TokenType.Op_Assignment, fromLine, fromCol); case '/': - return CreateSingleCharToken(TokenType.Op_Div, fromLine, fromCol); + return PotentiallyDoubleCharOperator('=', TokenType.Op_Div, TokenType.Op_Assignment, fromLine, fromCol); case '%': - return CreateSingleCharToken(TokenType.Op_Mod, fromLine, fromCol); + return PotentiallyDoubleCharOperator('=', TokenType.Op_Mod, TokenType.Op_Assignment, fromLine, fromCol); case '^': - return CreateSingleCharToken(TokenType.Op_Pwr, fromLine, fromCol); + return PotentiallyDoubleCharOperator('=', TokenType.Op_Pwr, TokenType.Op_Assignment, fromLine, fromCol); case '$': return PotentiallyDoubleCharOperator('{', TokenType.Op_Dollar, TokenType.Brk_Open_Curly_Shared, fromLine, fromCol); case '#': diff --git a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs index a82fe67a..31a22023 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs @@ -68,14 +68,36 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres m_LValues.Add(CheckVar(lcontext, e)); } + char assignmentType = lcontext.Lexer.Current.Text[0]; + CheckTokenType(lcontext, TokenType.Op_Assignment); m_RValues = Expression.ExprList(lcontext); + // Replace e.g. "a += b" with "a = a + b" + if (assignmentType != '=') + { + TokenType ArithmeticOperation = assignmentType switch + { + '+' => TokenType.Op_Add, + '-' => TokenType.Op_MinusOrSub, + '*' => TokenType.Op_Mul, + '/' => TokenType.Op_Div, + '%' => TokenType.Op_Mod, + '^' => TokenType.Op_Pwr, + _ => throw new InternalErrorException($"Assignment operator not recognised: {assignmentType}"), + }; + + object operatorChain = BinaryOperatorExpression.BeginOperatorChain(); + BinaryOperatorExpression.AddExpressionToChain(operatorChain, firstExpression); + BinaryOperatorExpression.AddOperatorToChain(operatorChain, new Token(ArithmeticOperation, first.SourceId, first.FromLine, first.FromCol, first.ToLine, first.ToCol, first.PrevLine, first.PrevCol)); + BinaryOperatorExpression.AddExpressionToChain(operatorChain, m_RValues[0]); + m_RValues[0] = BinaryOperatorExpression.CommitOperatorChain(operatorChain, lcontext); + } + Token last = lcontext.Lexer.Current; m_Ref = first.GetSourceRefUpTo(last); lcontext.Source.Refs.Add(m_Ref); - } private IVariable CheckVar(ScriptLoadingContext lcontext, Expression firstExpression) @@ -88,7 +110,6 @@ private IVariable CheckVar(ScriptLoadingContext lcontext, Expression firstExpres return v; } - public override void Compile(Execution.VM.ByteCode bc) { using (bc.EnterSource(m_Ref)) @@ -106,6 +127,5 @@ public override void Compile(Execution.VM.ByteCode bc) bc.Emit_Pop(m_RValues.Count); } } - } } From 267a1400616d711d53ae98b1f4cb321f3112726c Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:00:27 +0100 Subject: [PATCH 2/4] Added ..= operator --- src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs | 24 ++++++++++++++----- .../Tree/Statements/AssignmentStatement.cs | 17 ++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs b/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs index b3fd4f3e..7082f621 100755 --- a/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs +++ b/src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs @@ -175,7 +175,7 @@ private Token ReadToken() { char next = CursorCharNext(); if (next == '.') - return PotentiallyDoubleCharOperator('.', TokenType.Op_Concat, TokenType.VarArgs, fromLine, fromCol); + return PotentiallyDoubleCharOperator(TokenType.Op_Concat, '.', TokenType.VarArgs, "...", '=', TokenType.Op_Assignment, "..=", fromLine, fromCol); else if (LexerUtils.CharIsDigit(next)) return ReadNumberToken(fromLine, fromCol, true); else @@ -545,8 +545,25 @@ private Token PotentiallyDoubleCharOperator(char expectedSecondChar, TokenType s else return CreateToken(singleCharToken, fromLine, fromCol, op); } + private Token PotentiallyDoubleCharOperator(TokenType singleCharToken, char expectedSecondChar, TokenType doubleCharToken, string doubleCharText, char alternateExpectedSecondChar, TokenType alternateDoubleCharToken, string alternateDoubleCharText, int fromLine, int fromCol) + { + string op = CursorChar().ToString(); + CursorCharNext(); + if (CursorChar() == expectedSecondChar) + { + CursorCharNext(); + return CreateToken(doubleCharToken, fromLine, fromCol, doubleCharText); + } + else if (CursorChar() == alternateExpectedSecondChar) + { + CursorCharNext(); + return CreateToken(alternateDoubleCharToken, fromLine, fromCol, alternateDoubleCharText); + } + else + return CreateToken(singleCharToken, fromLine, fromCol, op); + } private Token CreateNameToken(string name, int fromLine, int fromCol) { @@ -562,7 +579,6 @@ private Token CreateNameToken(string name, int fromLine, int fromCol) } } - private Token CreateToken(TokenType tokenType, int fromLine, int fromCol, string text = null) { Token t = new Token(tokenType, m_SourceId, fromLine, fromCol, m_Line, m_Col, m_PrevLineTo, m_PrevColTo) @@ -588,9 +604,5 @@ private string ReadNameToken() return name.ToString(); } - - - - } } diff --git a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs index 31a22023..92abdd31 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs @@ -68,23 +68,24 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres m_LValues.Add(CheckVar(lcontext, e)); } - char assignmentType = lcontext.Lexer.Current.Text[0]; + string assignmentType = lcontext.Lexer.Current.Text; CheckTokenType(lcontext, TokenType.Op_Assignment); m_RValues = Expression.ExprList(lcontext); // Replace e.g. "a += b" with "a = a + b" - if (assignmentType != '=') + if (assignmentType != "=") { TokenType ArithmeticOperation = assignmentType switch { - '+' => TokenType.Op_Add, - '-' => TokenType.Op_MinusOrSub, - '*' => TokenType.Op_Mul, - '/' => TokenType.Op_Div, - '%' => TokenType.Op_Mod, - '^' => TokenType.Op_Pwr, + "+=" => TokenType.Op_Add, + "-=" => TokenType.Op_MinusOrSub, + "*=" => TokenType.Op_Mul, + "/=" => TokenType.Op_Div, + "%=" => TokenType.Op_Mod, + "^=" => TokenType.Op_Pwr, + "..=" => TokenType.Op_Concat, _ => throw new InternalErrorException($"Assignment operator not recognised: {assignmentType}"), }; From 9d4d90fd772bbb863a9e2200c3eed34f1e28e57d Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:04:17 +0100 Subject: [PATCH 3/4] Small grammar fix --- .../Tree/Statements/AssignmentStatement.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs index 92abdd31..a3bbcccf 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs @@ -77,7 +77,7 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres // Replace e.g. "a += b" with "a = a + b" if (assignmentType != "=") { - TokenType ArithmeticOperation = assignmentType switch + TokenType operationTokenType = assignmentType switch { "+=" => TokenType.Op_Add, "-=" => TokenType.Op_MinusOrSub, @@ -91,7 +91,7 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres object operatorChain = BinaryOperatorExpression.BeginOperatorChain(); BinaryOperatorExpression.AddExpressionToChain(operatorChain, firstExpression); - BinaryOperatorExpression.AddOperatorToChain(operatorChain, new Token(ArithmeticOperation, first.SourceId, first.FromLine, first.FromCol, first.ToLine, first.ToCol, first.PrevLine, first.PrevCol)); + BinaryOperatorExpression.AddOperatorToChain(operatorChain, new Token(operationTokenType, first.SourceId, first.FromLine, first.FromCol, first.ToLine, first.ToCol, first.PrevLine, first.PrevCol)); BinaryOperatorExpression.AddExpressionToChain(operatorChain, m_RValues[0]); m_RValues[0] = BinaryOperatorExpression.CommitOperatorChain(operatorChain, lcontext); } From b1618b7614b782a750532a283afd0ddc5a1cb6d6 Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 10 Aug 2023 21:38:30 +0100 Subject: [PATCH 4/4] Fix compound assignment for tuples e.g. local a, b = 1, 2 a, b += 1, 1, 5 print(a) --2 print(b) --3 --- .../Tree/Statements/AssignmentStatement.cs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs index a3bbcccf..0c96d347 100644 --- a/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs +++ b/src/MoonSharp.Interpreter/Tree/Statements/AssignmentStatement.cs @@ -61,11 +61,14 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres { m_LValues.Add(CheckVar(lcontext, firstExpression)); + List leftExpressions = new() {firstExpression}; + while (lcontext.Lexer.Current.Type == TokenType.Comma) { lcontext.Lexer.Next(); - Expression e = Expression.PrimaryExp(lcontext); - m_LValues.Add(CheckVar(lcontext, e)); + Expression exp = Expression.PrimaryExp(lcontext); + m_LValues.Add(CheckVar(lcontext, exp)); + leftExpressions.Add(exp); } string assignmentType = lcontext.Lexer.Current.Text; @@ -89,11 +92,17 @@ public AssignmentStatement(ScriptLoadingContext lcontext, Expression firstExpres _ => throw new InternalErrorException($"Assignment operator not recognised: {assignmentType}"), }; - object operatorChain = BinaryOperatorExpression.BeginOperatorChain(); - BinaryOperatorExpression.AddExpressionToChain(operatorChain, firstExpression); - BinaryOperatorExpression.AddOperatorToChain(operatorChain, new Token(operationTokenType, first.SourceId, first.FromLine, first.FromCol, first.ToLine, first.ToCol, first.PrevLine, first.PrevCol)); - BinaryOperatorExpression.AddExpressionToChain(operatorChain, m_RValues[0]); - m_RValues[0] = BinaryOperatorExpression.CommitOperatorChain(operatorChain, lcontext); + for (int valueIndex = 0; valueIndex < m_RValues.Count; valueIndex++) + { + if (leftExpressions.Count > valueIndex) + { + object operatorChain = BinaryOperatorExpression.BeginOperatorChain(); + BinaryOperatorExpression.AddExpressionToChain(operatorChain, leftExpressions[valueIndex]); + BinaryOperatorExpression.AddOperatorToChain(operatorChain, new Token(operationTokenType, first.SourceId, first.FromLine, first.FromCol, first.ToLine, first.ToCol, first.PrevLine, first.PrevCol)); + BinaryOperatorExpression.AddExpressionToChain(operatorChain, m_RValues[valueIndex]); + m_RValues[valueIndex] = BinaryOperatorExpression.CommitOperatorChain(operatorChain, lcontext); + } + } } Token last = lcontext.Lexer.Current;