Skip to content

Commit

Permalink
Parse proc return types (OpenDreamProject#1696)
Browse files Browse the repository at this point in the history
Co-authored-by: ike709 <[email protected]>
  • Loading branch information
ike709 and ike709 authored Mar 4, 2024
1 parent 1ba83c6 commit cc50ab6
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 28 deletions.
6 changes: 6 additions & 0 deletions Content.Tests/DMProject/Tests/Procs/return_type.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Just testing that this parses
/proc/foo() as /list
return list("a","b","c")

/proc/RunTest()
ASSERT(foo()[2] == "b")
69 changes: 43 additions & 26 deletions DMCompiler/Compiler/DM/DMParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ public DMASTFile File() {
ConsumeRightParenthesis();
Whitespace();

// Proc return type
// TODO: Currently we parse it but don't do anything with this information
AsTypes(out _, true);

DMASTProcBlockInner? procBlock = ProcBlock();
if (procBlock is null) {
DMASTProcStatement? procStatement = ProcStatement();
Expand Down Expand Up @@ -289,7 +293,7 @@ public DMASTFile File() {

value ??= new DMASTConstantNull(loc);

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

varDefinitions.Add(varDef);
Expand Down Expand Up @@ -858,7 +862,7 @@ public DMASTFile File() {
if (value == null) Error("Expected an expression");
}

AsTypes();
AsTypes(out _);

varDeclarations.Add(new DMASTProcStatementVarDeclaration(loc, varPath, value));
if (allowMultiple && Check(TokenType.DM_Comma)) {
Expand Down Expand Up @@ -1161,7 +1165,7 @@ private DMASTProcStatementSet[] ProcSetEnd(bool allowMultiple) {

_allowVarDeclExpression = true;
DMASTExpression? expr1 = Expression();
DMValueType? dmTypes = AsTypes();
DMValueType? dmTypes = AsTypes(out _);
Whitespace();
_allowVarDeclExpression = false;
if (expr1 == null) {
Expand Down Expand Up @@ -1697,7 +1701,7 @@ public List<DMASTDefinitionParameter> DefinitionParameters(out bool wasIndetermi
value = Expression();
}

var type = AsTypes();
var type = AsTypes(out _);
Whitespace();

if (Check(TokenType.DM_In)) {
Expand Down Expand Up @@ -2427,7 +2431,7 @@ private void BracketWhitespace() {
return new DMASTProb(identifier.Location, callParameters[0].Value);
case "input": {
Whitespace();
DMValueType? types = AsTypes();
DMValueType? types = AsTypes(out _);
Whitespace();
DMASTExpression? list = null;

Expand Down Expand Up @@ -2597,7 +2601,8 @@ private void BracketWhitespace() {
return expression;
}

private DMValueType? AsTypes() {
private DMValueType? AsTypes(out DMASTPath? path, bool allowPath = false) {
path = null;
if (Check(TokenType.DM_As)) {
DMValueType type = DMValueType.Anything;

Expand All @@ -2614,27 +2619,39 @@ private void BracketWhitespace() {
if (closed) break;
}

Consume(new TokenType[] { TokenType.DM_Identifier, TokenType.DM_Null }, "Expected value type");
switch (typeToken.Text) {
case "anything": type |= DMValueType.Anything; break;
case "null": type |= DMValueType.Null; break;
case "text": type |= DMValueType.Text; break;
case "obj": type |= DMValueType.Obj; break;
case "mob": type |= DMValueType.Mob; break;
case "turf": type |= DMValueType.Turf; break;
case "num": type |= DMValueType.Num; break;
case "message": type |= DMValueType.Message; break;
case "area": type |= DMValueType.Area; break;
case "color": type |= DMValueType.Color; break;
case "file": type |= DMValueType.File; break;
case "command_text": type |= DMValueType.CommandText; break;
case "sound": type |= DMValueType.Sound; break;
case "icon": type |= DMValueType.Icon; break;
case "opendream_unimplemented": type |= DMValueType.Unimplemented; break;
case "opendream_compiletimereadonly": type |= DMValueType.CompiletimeReadonly; break;
default: Error("Invalid value type '" + typeToken.Text + "'"); break;
}

if (!Check(new TokenType[] { TokenType.DM_Identifier, TokenType.DM_Null })) {
// Proc return types
path = Path();
if (allowPath) {
if (path is null) {
DMCompiler.Emit(WarningCode.BadToken, typeToken.Location, "Expected value type or path");
}
type |= DMValueType.Path;
} else {
DMCompiler.Emit(WarningCode.BadToken, typeToken.Location, "Expected value type");
}
} else {
switch (typeToken.Text) {
case "anything": type |= DMValueType.Anything; break;
case "null": type |= DMValueType.Null; break;
case "text": type |= DMValueType.Text; break;
case "obj": type |= DMValueType.Obj; break;
case "mob": type |= DMValueType.Mob; break;
case "turf": type |= DMValueType.Turf; break;
case "num": type |= DMValueType.Num; break;
case "message": type |= DMValueType.Message; break;
case "area": type |= DMValueType.Area; break;
case "color": type |= DMValueType.Color; break;
case "file": type |= DMValueType.File; break;
case "command_text": type |= DMValueType.CommandText; break;
case "sound": type |= DMValueType.Sound; break;
case "icon": type |= DMValueType.Icon; break;
case "opendream_unimplemented": type |= DMValueType.Unimplemented; break;
case "opendream_compiletimereadonly": type |= DMValueType.CompiletimeReadonly; break;
default: Error("Invalid value type '" + typeToken.Text + "'"); break;
}
}
Whitespace();
} while (Check(TokenType.DM_Bar));

Expand Down
5 changes: 3 additions & 2 deletions DMCompiler/DM/DMValueType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public enum DMValueType {
CommandText = 0x400,
Sound = 0x800,
Icon = 0x1000,
Path = 0x2000, // For proc return types

//Byond here be dragons
Unimplemented = 0x2000, // Marks that a method or property is not implemented. Throws a compiler warning if accessed.
CompiletimeReadonly = 0x4000, // Marks that a property can only ever be read from, never written to. This is a const-ier version of const, for certain standard values like list.type
Unimplemented = 0x4000, // Marks that a method or property is not implemented. Throws a compiler warning if accessed.
CompiletimeReadonly = 0x8000, // Marks that a property can only ever be read from, never written to. This is a const-ier version of const, for certain standard values like list.type
}

0 comments on commit cc50ab6

Please sign in to comment.