Skip to content

Commit

Permalink
honestly really cursed code
Browse files Browse the repository at this point in the history
  • Loading branch information
ZeWaka committed Jan 15, 2024
1 parent 70774e4 commit d63de28
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 11 deletions.
6 changes: 6 additions & 0 deletions DMCompiler/Compiler/DM/DMAST.cs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,12 @@ public sealed class DMASTProcBlockInner : DMASTNode {
/// </remarks>
public readonly DMASTProcStatement[] SetStatements;

/// <summary>
/// This is used to determine if we should flag for <c>WarningCode.EmptyBlock</c>,
/// which we don't do if there was a manually entered semicolon within.
/// </summary>
public bool NotCompletelyEmpty;

/// <summary> Initializes an empty block. </summary>
public DMASTProcBlockInner(Location location) : base(location) {
Statements = Array.Empty<DMASTProcStatement>();
Expand Down
57 changes: 47 additions & 10 deletions DMCompiler/Compiler/DM/DMParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ public DMASTFile File() {
var loc = Current().Location;
if (Check(TokenType.DM_LeftCurlyBracket)) {
DMASTProcBlockInner? block;
bool hadSemicolon = false;

Whitespace();
Newline();
Expand All @@ -535,9 +536,13 @@ public DMASTFile File() {
List<DMASTProcStatement> setStatements = new(); // set statements are weird and must be held separately.

do {
(List<DMASTProcStatement>? stmts, List<DMASTProcStatement>? setStmts) = ProcBlockInner(); // Hope you understand tuples
if (stmts is not null) statements.AddRange(stmts);
if (setStmts is not null) setStatements.AddRange(setStmts);
(List<DMASTProcStatement>? stmts, List<DMASTProcStatement>? setStmts, bool innerHadSemicolon) = ProcBlockInner(); // Hope you understand tuples
if (stmts is not null)
statements.AddRange(stmts);
if (setStmts is not null)
setStatements.AddRange(setStmts);
if (innerHadSemicolon)
hadSemicolon = innerHadSemicolon;

if (!Check(TokenType.DM_RightCurlyBracket)) {
Error(WarningCode.BadToken, "Expected end of braced block");
Expand All @@ -550,7 +555,10 @@ public DMASTFile File() {
}
} while (true);

block = new DMASTProcBlockInner(loc, statements.ToArray(), setStatements.ToArray());
block = new DMASTProcBlockInner(loc, statements.ToArray(), setStatements.ToArray())
{
NotCompletelyEmpty = hadSemicolon
};
}

return block;
Expand All @@ -564,13 +572,16 @@ public DMASTFile File() {
if (Check(TokenType.DM_Indent)) {
List<DMASTProcStatement> statements = new();
List<DMASTProcStatement> setStatements = new(); // set statements are weird and must be held separately.
bool hadSemicolon = false;

do {
(List<DMASTProcStatement>? statements, List<DMASTProcStatement>? setStatements) blockInner = ProcBlockInner();
(List<DMASTProcStatement>? statements, List<DMASTProcStatement>? setStatements, bool hadSemicolon) blockInner = ProcBlockInner();
if (blockInner.statements is not null)
statements.AddRange(blockInner.statements);
if (blockInner.setStatements is not null)
setStatements.AddRange(blockInner.setStatements);
if (blockInner.hadSemicolon)
hadSemicolon = blockInner.hadSemicolon;

if (!Check(TokenType.DM_Dedent)) {
Error("Expected end of proc statement", throwException: false);
Expand All @@ -581,17 +592,26 @@ public DMASTFile File() {
}
} while (true);

return new DMASTProcBlockInner(loc, statements.ToArray(), setStatements.ToArray());
return new DMASTProcBlockInner(loc, statements.ToArray(), setStatements.ToArray())
{
NotCompletelyEmpty = hadSemicolon
};
}

return null;
}

public (List<DMASTProcStatement>?, List<DMASTProcStatement>?) ProcBlockInner() {
/// <summary>
/// Parses the inner of a proc block
/// </summary>
/// <remarks> We return if there was a semicolon within for <c>WarningCode.EmptyBlock</c></remarks>
/// <returns>(list of proc statements, list of set statements, had a semicolon within)</returns>
public (List<DMASTProcStatement>?, List<DMASTProcStatement>?, bool) ProcBlockInner() {
List<DMASTProcStatement> procStatements = new();
List<DMASTProcStatement> setStatements = new(); // We have to store them separately because they're evaluated first

DMASTProcStatement? statement = null;
bool hadSemicolon = false;
do {
Whitespace();

Expand All @@ -611,11 +631,14 @@ public DMASTFile File() {
DMASTProcBlockInner? blockInner = ProcBlock();
if (blockInner != null) procStatements.AddRange(blockInner.Statements);
}
} while (Delimiter() || statement is DMASTProcStatementLabel);
} while (DelimiterHasSemicolon(ref hadSemicolon) || statement is DMASTProcStatementLabel);

Whitespace();

if (procStatements.Count == 0) return (null,null);
return (procStatements, setStatements);
if (procStatements.Count == 0)
return (null, null, hadSemicolon);

return (procStatements, setStatements, hadSemicolon);
}

public DMASTProcStatement? ProcStatement() {
Expand Down Expand Up @@ -2617,5 +2640,19 @@ private bool Delimiter() {

return hasDelimiter;
}

private bool DelimiterHasSemicolon(ref bool hasSemicolon) {
bool hasDelimiter = false;
while (
// Once it is set to true, keep it that way
(!hasSemicolon && (hasSemicolon = Current().Type == TokenType.DM_Semicolon))
|| Check(TokenType.DM_Semicolon)
|| Newline()
) {
hasDelimiter = true;
}

return hasDelimiter;
}
}
}
2 changes: 1 addition & 1 deletion DMCompiler/DM/Visitors/DMProcBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private void ProcessBlockInner(DMASTProcBlockInner block, bool silenceEmptyBlock
DMCompiler.Emit(e.Error);
}
}
if(!silenceEmptyBlockWarning && block.Statements.Length == 0) { // If this block has no real statements
if(!silenceEmptyBlockWarning && block.Statements.Length == 0 && !block.NotCompletelyEmpty) { // If this block has no real statements
// Not an error in BYOND, but we do have an emission for this!
if(block.SetStatements.Length != 0) { // Give a more articulate message about this, since it's kinda weird
DMCompiler.Emit(WarningCode.EmptyBlock,block.Location,"Empty block detected - set statements are executed outside of, before, and unconditional to, this block");
Expand Down

0 comments on commit d63de28

Please sign in to comment.