From ca4f0b8344e22e827799457c45ce40a6242657f5 Mon Sep 17 00:00:00 2001 From: wixoa Date: Mon, 12 Feb 2024 10:51:24 -0800 Subject: [PATCH] Add "null statements" to the compiler (#1670) --- .../DMProject/Tests/Statements/EmptyBlock.dm | 5 +++++ .../Tests/Statements/EmptyBlockSuppressed.dm | 5 +++++ DMCompiler/Compiler/DM/DMAST.cs | 12 ++++++++++++ DMCompiler/Compiler/DM/DMParser.cs | 7 +++++++ DMCompiler/DM/Visitors/DMASTSimplifier.cs | 2 ++ DMCompiler/DM/Visitors/DMProcBuilder.cs | 1 + 6 files changed, 32 insertions(+) create mode 100644 Content.Tests/DMProject/Tests/Statements/EmptyBlock.dm create mode 100644 Content.Tests/DMProject/Tests/Statements/EmptyBlockSuppressed.dm diff --git a/Content.Tests/DMProject/Tests/Statements/EmptyBlock.dm b/Content.Tests/DMProject/Tests/Statements/EmptyBlock.dm new file mode 100644 index 0000000000..44ef88f06c --- /dev/null +++ b/Content.Tests/DMProject/Tests/Statements/EmptyBlock.dm @@ -0,0 +1,5 @@ +// COMPILE ERROR +#pragma EmptyBlock error + +/proc/RunTest() + if (TRUE) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/Statements/EmptyBlockSuppressed.dm b/Content.Tests/DMProject/Tests/Statements/EmptyBlockSuppressed.dm new file mode 100644 index 0000000000..2d52b13608 --- /dev/null +++ b/Content.Tests/DMProject/Tests/Statements/EmptyBlockSuppressed.dm @@ -0,0 +1,5 @@ +#pragma EmptyBlock error + +/proc/RunTest() + if (TRUE) + ; \ No newline at end of file diff --git a/DMCompiler/Compiler/DM/DMAST.cs b/DMCompiler/Compiler/DM/DMAST.cs index e80b68851e..fc3ce3467e 100644 --- a/DMCompiler/Compiler/DM/DMAST.cs +++ b/DMCompiler/Compiler/DM/DMAST.cs @@ -37,6 +37,10 @@ public void VisitObjectVarOverride(DMASTObjectVarOverride objectVarOverride) { throw new NotImplementedException(); } + public void VisitNullProcStatement(DMASTNullProcStatement nullProcStatement) { + throw new NotImplementedException(); + } + public void VisitProcStatementExpression(DMASTProcStatementExpression statementExpression) { throw new NotImplementedException(); } @@ -772,6 +776,14 @@ public override void Visit(DMASTVisitor visitor) { } } + /// Lone semicolon, analogous to null statements in C. + /// Main purpose is to suppress EmptyBlock emissions. + public sealed class DMASTNullProcStatement(Location location) : DMASTProcStatement(location) { + public override void Visit(DMASTVisitor visitor) { + visitor.VisitNullProcStatement(this); + } + } + public sealed class DMASTProcStatementExpression : DMASTProcStatement { public DMASTExpression Expression; diff --git a/DMCompiler/Compiler/DM/DMParser.cs b/DMCompiler/Compiler/DM/DMParser.cs index d0de271eae..51da75118a 100644 --- a/DMCompiler/Compiler/DM/DMParser.cs +++ b/DMCompiler/Compiler/DM/DMParser.cs @@ -194,6 +194,7 @@ public DMASTFile File() { public DMASTStatement? Statement(bool requireDelimiter = true) { var loc = Current().Location; + DMASTPath? path = Path(); if (path is null) return null; @@ -618,6 +619,12 @@ public DMASTFile File() { public DMASTProcStatement? ProcStatement() { var loc = Current().Location; + + if (Current().Type == TokenType.DM_Semicolon) { // A lone semicolon creates a "null statement" (like C) + // Note that we do not consume the semicolon here + return new DMASTNullProcStatement(loc); + } + var leadingColon = Check(TokenType.DM_Colon); DMASTExpression? expression = null; diff --git a/DMCompiler/DM/Visitors/DMASTSimplifier.cs b/DMCompiler/DM/Visitors/DMASTSimplifier.cs index 1956f95884..5e9f1529e7 100644 --- a/DMCompiler/DM/Visitors/DMASTSimplifier.cs +++ b/DMCompiler/DM/Visitors/DMASTSimplifier.cs @@ -53,6 +53,8 @@ public void VisitProcBlockInner(DMASTProcBlockInner procBlockInner) { } } + public void VisitNullProcStatement(DMASTNullProcStatement nullProcStatement) { } + public void VisitProcStatementExpression(DMASTProcStatementExpression statementExpression) { SimplifyExpression(ref statementExpression.Expression); } diff --git a/DMCompiler/DM/Visitors/DMProcBuilder.cs b/DMCompiler/DM/Visitors/DMProcBuilder.cs index 59fa4828d1..7b946ffe3a 100644 --- a/DMCompiler/DM/Visitors/DMProcBuilder.cs +++ b/DMCompiler/DM/Visitors/DMProcBuilder.cs @@ -112,6 +112,7 @@ private void ProcessBlockInner(DMASTProcBlockInner block, bool silenceEmptyBlock public void ProcessStatement(DMASTProcStatement statement) { switch (statement) { + case DMASTNullProcStatement: break; case DMASTProcStatementExpression statementExpression: ProcessStatementExpression(statementExpression); break; case DMASTProcStatementContinue statementContinue: ProcessStatementContinue(statementContinue); break; case DMASTProcStatementGoto statementGoto: ProcessStatementGoto(statementGoto); break;