diff --git a/Core/EVIL.Grammar/AST/Statements/ExpressionStatement.cs b/Core/EVIL.Grammar/AST/Statements/ExpressionStatement.cs index 7b9ec9ba..052ae037 100644 --- a/Core/EVIL.Grammar/AST/Statements/ExpressionStatement.cs +++ b/Core/EVIL.Grammar/AST/Statements/ExpressionStatement.cs @@ -9,6 +9,8 @@ public sealed class ExpressionStatement : Statement public ExpressionStatement(Expression expression) { Expression = expression; + Reparent(Expression); + Line = expression.Line; } } diff --git a/FrontEnd/EVIL.evil/EVIL.evil.csproj b/FrontEnd/EVIL.evil/EVIL.evil.csproj index 29d4b47e..8353d6a8 100644 --- a/FrontEnd/EVIL.evil/EVIL.evil.csproj +++ b/FrontEnd/EVIL.evil/EVIL.evil.csproj @@ -4,7 +4,7 @@ net7.0 enable evil - 1.6.0 + 1.7.0 diff --git a/FrontEnd/EVIL.evil/EvmFrontEnd.cs b/FrontEnd/EVIL.evil/EvmFrontEnd.cs index 47bc9c2a..b4eedc86 100644 --- a/FrontEnd/EVIL.evil/EvmFrontEnd.cs +++ b/FrontEnd/EVIL.evil/EvmFrontEnd.cs @@ -30,12 +30,14 @@ public partial class EvmFrontEnd { "h|help", "display this message and quit.", (h) => _displayHelpAndQuit = h != null }, { "v|version", "display compiler and VM version information.", (v) => _displayVersionAndQuit = v != null }, { "I|include-dir=", "add include directory to the list of search paths.", (I) => _includeHandler.AddIncludeSearchPath(I) }, - { "g|gen-docs", "generate documentation for all detected native modules.", (g) => _generateModuleDocsAndQuit = g != null } + { "g|gen-docs", "generate documentation for all detected native modules.", (g) => _generateModuleDocsAndQuit = g != null }, + { "d|disasm", "disassemble the compiled script.", (d) => _disassembleCompiledScript = d != null } }; private static bool _displayHelpAndQuit; private static bool _displayVersionAndQuit; - private static bool _generateModuleDocsAndQuit; + private static bool _generateModuleDocsAndQuit; + private static bool _disassembleCompiledScript; public async Task Run(string[] args) { @@ -122,6 +124,16 @@ public async Task Run(string[] args) Terminate(msg, exitCode: ExitCode.CompilerError); } + if (_disassembleCompiledScript) + { + Console.WriteLine($"Disassembly of '{scriptPath}'\n-------------------"); + + foreach (var chunk in script.Chunks) + { + Disassembler.Disassemble(chunk, Console.Out); + } + } + if (!script.TryFindChunkByName("main", out var mainChunk)) { Terminate( diff --git a/VirtualMachine/Ceres/Ceres.csproj b/VirtualMachine/Ceres/Ceres.csproj index 2e193d58..e0945ff6 100644 --- a/VirtualMachine/Ceres/Ceres.csproj +++ b/VirtualMachine/Ceres/Ceres.csproj @@ -5,7 +5,7 @@ enable 11.0 - 1.3.0 + 1.3.1 Ceres Ceres diff --git a/VirtualMachine/Ceres/TranslationEngine/Compiler.Expression.Assignment.cs b/VirtualMachine/Ceres/TranslationEngine/Compiler.Expression.Assignment.cs index b6a3c177..181bb96e 100644 --- a/VirtualMachine/Ceres/TranslationEngine/Compiler.Expression.Assignment.cs +++ b/VirtualMachine/Ceres/TranslationEngine/Compiler.Expression.Assignment.cs @@ -2,6 +2,7 @@ using Ceres.TranslationEngine.Diagnostics; using EVIL.Grammar; using EVIL.Grammar.AST.Expressions; +using EVIL.Grammar.AST.Statements; namespace Ceres.TranslationEngine { @@ -22,6 +23,7 @@ public override void Visit(AssignmentExpression assignmentExpression) Chunk.CodeGenerator.Emit(OpCode.LDNIL); Chunk.CodeGenerator.Emit(OpCode.CNE); Chunk.CodeGenerator.Emit(OpCode.TJMP, valueNotNilLabel); + Chunk.CodeGenerator.Emit(OpCode.POP); Visit(assignmentExpression.Right); Chunk.CodeGenerator.Emit(OpCode.DUP); EmitVarSet(symRef.Identifier); @@ -29,7 +31,7 @@ public override void Visit(AssignmentExpression assignmentExpression) return; } - + if (assignmentExpression.OperationType != AssignmentOperationType.Direct) { EmitVarGet(symRef.Identifier); @@ -77,6 +79,7 @@ public override void Visit(AssignmentExpression assignmentExpression) Chunk.CodeGenerator.Emit(OpCode.LDNIL); Chunk.CodeGenerator.Emit(OpCode.CNE); Chunk.CodeGenerator.Emit(OpCode.TJMP, valueNotNilLabel); + Chunk.CodeGenerator.Emit(OpCode.POP); Visit(assignmentExpression.Right); Chunk.CodeGenerator.Emit(OpCode.DUP); Visit(ie.Indexable); @@ -86,7 +89,7 @@ public override void Visit(AssignmentExpression assignmentExpression) return; } - + if (assignmentExpression.OperationType != AssignmentOperationType.Direct) { Visit(ie); diff --git a/VirtualMachine/Tests/Ceres.LanguageTests/tests/004_assignment_operators.vil b/VirtualMachine/Tests/Ceres.LanguageTests/tests/004_assignment_operators.vil index 43e1c0c1..e71dcf5d 100644 --- a/VirtualMachine/Tests/Ceres.LanguageTests/tests/004_assignment_operators.vil +++ b/VirtualMachine/Tests/Ceres.LanguageTests/tests/004_assignment_operators.vil @@ -194,10 +194,10 @@ fn coalescing_assignment_table_entry() { #[test] fn chained_coalescing_assignment_table_entry_when_first_is_nil() { val t = { }; - val a = ""; + val a = "string"; rw val b = nil; - t.entry ??= b ??= a; + t.entry ??= (b ??= a); assert.equal(b, a); assert.equal(t.entry, a);