Skip to content

Commit

Permalink
Optimize DMParser.Statement() a bit
Browse files Browse the repository at this point in the history
Remove a parameter only used by one thing and remove a try/finally
  • Loading branch information
wixoaGit committed Feb 14, 2024
1 parent a361270 commit 0c9def4
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 114 deletions.
202 changes: 94 additions & 108 deletions DMCompiler/Compiler/DM/DMParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,16 @@ public DMASTFile File() {

do {
Whitespace();
DreamPath oldPath = _currentPath;
DMASTStatement? statement = Statement();

_currentPath = oldPath;

if (statement != null) {
if (!PeekDelimiter() && Current().Type is not (TokenType.DM_Dedent or TokenType.DM_RightCurlyBracket or TokenType.EndOfFile)) {
Emit(WarningCode.BadToken, "Expected end of object statement");
}

Whitespace();
statements.Add(statement);
} else {
Expand All @@ -185,152 +192,131 @@ public DMASTFile File() {
return statements;
}

public DMASTStatement? Statement(bool requireDelimiter = true) {
var loc = Current().Location;
public DMASTStatement? Statement() {
var loc = CurrentLoc;

DMASTPath? path = Path();
if (path is null)
return null;
DreamPath oldPath = _currentPath;
Whitespace();
_currentPath = _currentPath.Combine(path.Path);

try {
DMASTStatement? statement = null;

//Proc definition
if (Check(TokenType.DM_LeftParenthesis)) {
DMCompiler.VerbosePrint($"Parsing proc {_currentPath}()");
BracketWhitespace();
var parameters = DefinitionParameters(out var wasIndeterminate);

if (Current().Type != TokenType.DM_RightParenthesis && Current().Type != TokenType.DM_Comma && !wasIndeterminate) {
if (parameters.Count > 0) // Separate error handling mentions the missing right-paren
Emit(WarningCode.BadToken, $"{parameters.Last().Name}: missing comma ',' or right-paren ')'");
//Proc definition
if (Check(TokenType.DM_LeftParenthesis)) {
DMCompiler.VerbosePrint($"Parsing proc {_currentPath}()");
BracketWhitespace();
var parameters = DefinitionParameters(out var wasIndeterminate);

parameters.AddRange(DefinitionParameters(out wasIndeterminate));
}
if (Current().Type != TokenType.DM_RightParenthesis && Current().Type != TokenType.DM_Comma && !wasIndeterminate) {
if (parameters.Count > 0) // Separate error handling mentions the missing right-paren
Emit(WarningCode.BadToken, $"{parameters.Last().Name}: missing comma ',' or right-paren ')'");

if (!wasIndeterminate && Current().Type != TokenType.DM_RightParenthesis && Current().Type != TokenType.EndOfFile) {
// BYOND doesn't specify the arg
Emit(WarningCode.BadToken, $"Bad argument definition '{Current().PrintableText}'");
Advance();
BracketWhitespace();
Check(TokenType.DM_Comma);
BracketWhitespace();
parameters.AddRange(DefinitionParameters(out _));
}
parameters.AddRange(DefinitionParameters(out wasIndeterminate));
}

if (!wasIndeterminate && Current().Type != TokenType.DM_RightParenthesis && Current().Type != TokenType.EndOfFile) {
// BYOND doesn't specify the arg
Emit(WarningCode.BadToken, $"Bad argument definition '{Current().PrintableText}'");
Advance();
BracketWhitespace();
ConsumeRightParenthesis();
Whitespace();
Check(TokenType.DM_Comma);
BracketWhitespace();
parameters.AddRange(DefinitionParameters(out _));
}

DMASTProcBlockInner? procBlock = ProcBlock();
if (procBlock is null) {
DMASTProcStatement? procStatement = ProcStatement();
BracketWhitespace();
ConsumeRightParenthesis();
Whitespace();

if (procStatement is not null) {
procBlock = new DMASTProcBlockInner(loc, procStatement);
}
DMASTProcBlockInner? procBlock = ProcBlock();
if (procBlock is null) {
DMASTProcStatement? procStatement = ProcStatement();

if (procStatement is not null) {
procBlock = new DMASTProcBlockInner(loc, procStatement);
}
if(path.IsOperator) {
DMCompiler.UnimplementedWarning(procBlock.Location, "Operator overloads are not implemented. They will be defined but never called.");
}

List<DMASTProcStatement> procStatements = procBlock.Statements.ToList();
Location tokenLoc = procBlock.Location;
//add ". = src" as the first expression in the operator
DMASTProcStatementExpression assignEqSrc = new DMASTProcStatementExpression(tokenLoc, new DMASTAssign(tokenLoc,new DMASTCallableSelf(tokenLoc), new DMASTIdentifier(tokenLoc, "src")));
procStatements.Insert(0, assignEqSrc);
if(path.IsOperator) {
DMCompiler.UnimplementedWarning(procBlock.Location, "Operator overloads are not implemented. They will be defined but never called.");

procBlock = new DMASTProcBlockInner(loc, procStatements.ToArray(), procBlock.SetStatements);
List<DMASTProcStatement> procStatements = procBlock.Statements.ToList();
Location tokenLoc = procBlock.Location;
//add ". = src" as the first expression in the operator
DMASTProcStatementExpression assignEqSrc = new DMASTProcStatementExpression(tokenLoc, new DMASTAssign(tokenLoc,new DMASTCallableSelf(tokenLoc), new DMASTIdentifier(tokenLoc, "src")));
procStatements.Insert(0, assignEqSrc);

}
statement = new DMASTProcDefinition(loc, _currentPath, parameters.ToArray(), procBlock);
procBlock = new DMASTProcBlockInner(loc, procStatements.ToArray(), procBlock.SetStatements);
}

//Object definition
if (statement == null) {
DMASTBlockInner? block = Block();
return new DMASTProcDefinition(loc, _currentPath, parameters.ToArray(), procBlock);
}

if (block != null) {
DMCompiler.VerbosePrint($"Parsed object {_currentPath}");
statement = new DMASTObjectDefinition(loc, _currentPath, block);
}
}
//Object definition
if (Block() is { } block) {
DMCompiler.VerbosePrint($"Parsed object {_currentPath}");
return new DMASTObjectDefinition(loc, _currentPath, block);
}

//Var definition(s)
if (statement == null && _currentPath.FindElement("var") != -1) {
DreamPath varPath = _currentPath;
List<DMASTObjectVarDefinition> varDefinitions = new();
//Var definition(s)
if (_currentPath.FindElement("var") != -1) {
DreamPath varPath = _currentPath;
List<DMASTObjectVarDefinition> varDefinitions = new();

while (true) {
Whitespace();
while (true) {
Whitespace();

DMASTExpression? value = PathArray(ref varPath);
DMASTExpression? value = PathArray(ref varPath);

if (Check(TokenType.DM_Equals)) {
if (value != null) Warning("List doubly initialized");
if (Check(TokenType.DM_Equals)) {
if (value != null) Warning("List doubly initialized");

Whitespace();
value = Expression();
RequireExpression(ref value);
} else if (value == null) {
value = new DMASTConstantNull(loc);
}
Whitespace();
value = Expression();
RequireExpression(ref value);
} else if (value == null) {
value = new DMASTConstantNull(loc);
}

var valType = AsTypes() ?? DMValueType.Anything;
var varDef = new DMASTObjectVarDefinition(loc, varPath, value, valType);
var valType = AsTypes() ?? DMValueType.Anything;
var varDef = new DMASTObjectVarDefinition(loc, varPath, value, valType);

varDefinitions.Add(varDef);
if (Check(TokenType.DM_Comma)) {
Whitespace();
DMASTPath? newVarPath = Path();

if (newVarPath == null) {
Emit(WarningCode.InvalidVarDefinition, "Expected a var definition");
break;
} else if (newVarPath.Path.Elements.Length > 1) { // TODO: This is valid DM
Emit(WarningCode.BadToken, newVarPath.Location, "Invalid var name");
break;
}
varDefinitions.Add(varDef);
if (Check(TokenType.DM_Comma)) {
Whitespace();
DMASTPath? newVarPath = Path();

varPath = _currentPath.AddToPath("../" + newVarPath.Path.PathString);
} else {
if (newVarPath == null) {
Emit(WarningCode.InvalidVarDefinition, "Expected a var definition");
break;
} else if (newVarPath.Path.Elements.Length > 1) { // TODO: This is valid DM
Emit(WarningCode.BadToken, newVarPath.Location, "Invalid var name");
break;
}
}

if (varDefinitions.Count == 1) {
statement = varDefinitions[0];
varPath = _currentPath.AddToPath("../" + newVarPath.Path.PathString);
} else {
statement = new DMASTMultipleObjectVarDefinitions(loc, varDefinitions.ToArray());
break;
}
}

//Var override
if (statement == null && Check(TokenType.DM_Equals)) {
Whitespace();
DMASTExpression? value = Expression();
RequireExpression(ref value);

statement = new DMASTObjectVarOverride(loc, _currentPath, value);
}

//Empty object definition
if (statement == null) {
DMCompiler.VerbosePrint($"Parsed object {_currentPath}");
statement = new DMASTObjectDefinition(loc, _currentPath, null);
}
return (varDefinitions.Count == 1)
? varDefinitions[0]
: new DMASTMultipleObjectVarDefinitions(loc, varDefinitions.ToArray());
}

if (requireDelimiter && !PeekDelimiter() && Current().Type != TokenType.DM_Dedent && Current().Type != TokenType.DM_RightCurlyBracket && Current().Type != TokenType.EndOfFile) {
Emit(WarningCode.BadToken, "Expected end of object statement");
}
//Var override
if (Check(TokenType.DM_Equals)) {
Whitespace();
DMASTExpression? value = Expression();
RequireExpression(ref value);

return statement;
} finally {
_currentPath = oldPath;
return new DMASTObjectVarOverride(loc, _currentPath, value);
}
//no return here because this is technically unreachable

//Empty object definition
DMCompiler.VerbosePrint($"Parsed object {_currentPath}");
return new DMASTObjectDefinition(loc, _currentPath, null);
}

/// <summary>
Expand Down
8 changes: 2 additions & 6 deletions DMCompiler/Compiler/DMM/DMMParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public DreamMapJson ParseMap() {
MapObjectJson mapObject = new MapObjectJson(typeId);

if (Check(TokenType.DM_LeftCurlyBracket)) {
DMASTStatement? statement = Statement(requireDelimiter: false);
DMASTStatement? statement = Statement();

while (statement != null) {
if (statement is not DMASTObjectVarOverride varOverride) {
Expand All @@ -81,11 +81,7 @@ public DreamMapJson ParseMap() {
DMCompiler.ForcedWarning(statement.Location, $"Duplicate var override '{varOverride.VarName}' in DMM on type {objectType.Path}");
}

if (Check(TokenType.DM_Semicolon)) {
statement = Statement(requireDelimiter: false);
} else {
statement = null;
}
statement = Check(TokenType.DM_Semicolon) ? Statement() : null;
}

Consume(TokenType.DM_RightCurlyBracket, "Expected '}'");
Expand Down

0 comments on commit 0c9def4

Please sign in to comment.