Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into appearanceRefCounts
Browse files Browse the repository at this point in the history
  • Loading branch information
amylizzle committed Nov 28, 2024
2 parents 2a11400 + 12b9f6e commit f69f4be
Show file tree
Hide file tree
Showing 83 changed files with 4,240 additions and 3,693 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/compiler-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Compile /tg/station Master
run: main\bin\DMCompiler\DMCompiler.exe tg\tgstation.dme --suppress-unimplemented
- name: Disassemble /tg/station Master
run: main\bin\DMDisassembler\DMDisassembler.exe tg\tgstation.json crash-on-error
run: main\bin\DMDisassembler\DMDisassembler.exe tg\tgstation.json crash-on-test
- name: Checkout Goonstation Master
uses: actions/checkout@v2
with:
Expand Down
2 changes: 2 additions & 0 deletions Content.IntegrationTests/Content.IntegrationTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<LangVersion>12</LangVersion>
<NoWarn>NU1507</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<RootNamespace>Content.IntegrationTests</RootNamespace>
<AssemblyName>Content.IntegrationTests</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NUnit" />
Expand Down
3 changes: 2 additions & 1 deletion Content.IntegrationTests/SetupCompileDM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public sealed class SetupCompileDm {

[OneTimeSetUp]
public void Compile() {
bool successfulCompile = DMCompiler.DMCompiler.Compile(new() {
DMCompiler.DMCompiler compiler = new();
bool successfulCompile = compiler.Compile(new() {
Files = new() { DmEnvironment }
});

Expand Down
2 changes: 2 additions & 0 deletions Content.Tests/Content.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<Nullable>enable</Nullable>
<NoWarn>NU1507</NoWarn>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<RootNamespace>Content.Tests</RootNamespace>
<AssemblyName>Content.Tests</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NUnit" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

/proc/RunTest()
ASSERT(isnum(world.opendream_topic_port))
3 changes: 3 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/world_system_type.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

/proc/RunTest()
ASSERT(istext(world.system_type) && length(world.system_type))
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// COMPILE ERROR OD3300
#pragma RuntimeSearchOperator error
/datum/proc/foo()
return

/proc/RunTest()
var/datum/D = new
D:foo()
8 changes: 8 additions & 0 deletions Content.Tests/DMProject/Tests/Tree/upward_search_path3.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

//# issue 617

/datum/foo
/datum/bar/var/meep = .foo
/proc/RunTest()
var/datum/bar/D = new
ASSERT(D.meep == /datum/foo)
53 changes: 27 additions & 26 deletions Content.Tests/DMTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@ public enum DMTestFlags {

[OneTimeSetUp]
public void OneTimeSetup() {
var dmCompiler = new DMCompiler.DMCompiler();
IoCManager.InjectDependencies(this);
_taskManager.Initialize();
Compile(InitializeEnvironment);
Compile(dmCompiler, InitializeEnvironment);
_dreamMan.PreInitialize(Path.ChangeExtension(InitializeEnvironment, "json"));
_dreamMan.OnException += OnException;
}

private static string? Compile(string sourceFile) {
bool successfulCompile = DMCompiler.DMCompiler.Compile(new() {
Files = new() { sourceFile }
private string? Compile(DMCompiler.DMCompiler compiler, string sourceFile) {
bool successfulCompile = compiler.Compile(new() {
Files = [sourceFile]
});

return successfulCompile ? Path.ChangeExtension(sourceFile, "json") : null;
Expand All @@ -64,10 +65,11 @@ public void TestFiles(string sourceFile, DMTestFlags testFlags, int errorCode) {
string initialDirectory = Directory.GetCurrentDirectory();
TestContext.WriteLine($"--- TEST {sourceFile} | Flags: {testFlags}");
try {
string? compiledFile = Compile(Path.Join(initialDirectory, TestsDirectory, sourceFile));
var dmCompiler = new DMCompiler.DMCompiler();
var compiledFile = Compile(dmCompiler, Path.Join(initialDirectory, TestsDirectory, sourceFile));
if (testFlags.HasFlag(DMTestFlags.CompileError)) {
Assert.That(errorCode == -1, Is.False, "Expected an error code");
Assert.That(DMCompiler.DMCompiler.UniqueEmissions.Contains((WarningCode)errorCode), Is.True, $"Expected error code \"{errorCode}\" was not found");
Assert.That(dmCompiler.UniqueEmissions.Contains((WarningCode)errorCode), Is.True, $"Expected error code \"{errorCode}\" was not found");
Assert.That(compiledFile, Is.Null, "Expected an error during DM compilation");

Cleanup(compiledFile);
Expand Down Expand Up @@ -167,29 +169,28 @@ private static DMTestFlags GetDMTestFlags(string sourceFile, out int errorCode)
DMTestFlags testFlags = DMTestFlags.NoError;
errorCode = -1; // If it's null GetTests() fusses about a NRE

using (StreamReader reader = new StreamReader(sourceFile)) {
string? firstLine = reader.ReadLine();
if (firstLine == null)
return testFlags;
if (firstLine.Contains("IGNORE", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.Ignore;
if (firstLine.Contains("COMPILE ERROR", StringComparison.InvariantCulture)) {
testFlags |= DMTestFlags.CompileError;

Match match = ErrorCodeRegex().Match(firstLine); // "OD" followed by exactly 4 numbers
if (match.Success) {
errorCode = int.Parse(match.Groups[1].Value);
}
using StreamReader reader = new StreamReader(sourceFile);
string? firstLine = reader.ReadLine();
if (firstLine == null)
return testFlags;
if (firstLine.Contains("IGNORE", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.Ignore;
if (firstLine.Contains("COMPILE ERROR", StringComparison.InvariantCulture)) {
testFlags |= DMTestFlags.CompileError;

Match match = ErrorCodeRegex().Match(firstLine); // "OD" followed by exactly 4 numbers
if (match.Success) {
errorCode = int.Parse(match.Groups[1].Value);
}

if (firstLine.Contains("RUNTIME ERROR", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.RuntimeError;
if (firstLine.Contains("RETURN TRUE", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.ReturnTrue;
if (firstLine.Contains("NO RETURN", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.NoReturn;
}

if (firstLine.Contains("RUNTIME ERROR", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.RuntimeError;
if (firstLine.Contains("RETURN TRUE", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.ReturnTrue;
if (firstLine.Contains("NO RETURN", StringComparison.InvariantCulture))
testFlags |= DMTestFlags.NoReturn;

return testFlags;
}

Expand Down
2 changes: 2 additions & 0 deletions DMCompiler/Bytecode/DMReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public struct DMReference {
public static readonly DMReference Self = new() { RefType = Type.Self };
public static readonly DMReference Usr = new() { RefType = Type.Usr };
public static readonly DMReference Args = new() { RefType = Type.Args };
public static readonly DMReference World = new() { RefType = Type.World };
public static readonly DMReference SuperProc = new() { RefType = Type.SuperProc };
public static readonly DMReference ListIndex = new() { RefType = Type.ListIndex };
public static readonly DMReference Invalid = new() { RefType = Type.Invalid };
Expand All @@ -16,6 +17,7 @@ public enum Type : byte {
Self,
Usr,
Args,
World,
SuperProc,
ListIndex,
Argument,
Expand Down
3 changes: 2 additions & 1 deletion DMCompiler/Bytecode/DreamProcOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ public enum DreamProcOpcode : byte {
CreateObject = 0x2E,
[OpcodeMetadata(-1, OpcodeArgType.Label)]
BooleanOr = 0x2F, // Shrinks the stack by 1 or 0. Assume 1.
//0x30
[OpcodeMetadata(0, OpcodeArgType.ListSize)]
CreateMultidimensionalList = 0x30,
[OpcodeMetadata(-1)]
CompareGreaterThanOrEqual = 0x31,
[OpcodeMetadata(-1, OpcodeArgType.Label)]
Expand Down
11 changes: 3 additions & 8 deletions DMCompiler/Compiler/CompilerError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public enum WarningCode {
PointlessScopeOperator = 2209,
PointlessPositionalArgument = 2210,
ProcArgumentGlobal = 2211, // Prepending "/" on a proc arg (e.g. "/proc/example(/var/foo)" makes the arg a global var. Ref https://www.byond.com/forum/post/2830750
AmbiguousVarStatic = 2212, // Referencing a static variable when an instance variable with the same name exists
MalformedRange = 2300,
InvalidRange = 2301,
InvalidSetStatement = 2302,
Expand All @@ -72,7 +73,8 @@ public enum WarningCode {
SuspiciousSwitchCase = 3201, // "else if" cases are actually valid DM, they just spontaneously end the switch context and begin an if-else ladder within the else case of the switch
AssignmentInConditional = 3202,
PickWeightedSyntax = 3203,
AmbiguousInOrder = 3204
AmbiguousInOrder = 3204,
RuntimeSearchOperator = 3300,

// 4000 - 4999 are reserved for runtime configuration. (TODO: Runtime doesn't know about configs yet!)
}
Expand Down Expand Up @@ -116,10 +118,3 @@ public CompilerEmission(ErrorLevel level, WarningCode code, Location? location,
_ => "",
};
}

// TODO: Find a nicer way to do this
public sealed class UnknownIdentifierException(Location location, string identifier)
: Exception($"Unknown identifier \"{identifier}\" - This message should not be seen") {
public readonly Location Location = location;
public readonly string Identifier = identifier;
}
7 changes: 7 additions & 0 deletions DMCompiler/Compiler/DM/AST/DMAST.Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ public virtual IEnumerable<DMASTExpression> Leaves() {
public virtual DMASTExpression GetUnwrapped() {
return this;
}

public override string ToStringNoLocation() {
var leaves = Leaves().ToList();
if (leaves.Count == 0)
return $"{GetType().Name}";
return $"{GetType().Name}({string.Join(", ", Leaves().Select(l => l.ToString(Location)))})";
}
}

/// <summary>
Expand Down
3 changes: 0 additions & 3 deletions DMCompiler/Compiler/DM/AST/DMAST.ObjectStatements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ public sealed class DMASTObjectVarDefinition(

public bool IsStatic => _varDecl.IsStatic;

// TODO: Standardize our phrasing in the codebase. Are we calling these Statics or Globals?
public bool IsGlobal => _varDecl.IsStatic;

public bool IsConst => _varDecl.IsConst;
public bool IsTmp => _varDecl.IsTmp;

Expand Down
14 changes: 14 additions & 0 deletions DMCompiler/Compiler/DM/AST/DMAST.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ namespace DMCompiler.Compiler.DM.AST;

public abstract class DMASTNode(Location location) {
public readonly Location Location = location;

public override string ToString() {
return $"{ToString(null)}";
}

public string ToString(Location? loc) {
if (loc is not null && Location.SourceFile == loc.Value.SourceFile && Location.Line == loc.Value.Line)
return ToStringNoLocation();
return $"{ToStringNoLocation()} [{Location}]";
}

public virtual string ToStringNoLocation() {
return GetType().Name;
}
}

public sealed class DMASTFile(Location location, DMASTBlockInner blockInner) : DMASTNode(location) {
Expand Down
31 changes: 15 additions & 16 deletions DMCompiler/Compiler/DM/DMLexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace DMCompiler.Compiler.DM;

public sealed class DMLexer : TokenLexer {
internal sealed class DMLexer : TokenLexer {
public static readonly List<string> ValidEscapeSequences = [
"icon",
"Roman", "roman",
Expand Down Expand Up @@ -68,7 +68,7 @@ public sealed class DMLexer : TokenLexer {
private readonly Stack<int> _indentationStack = new(new[] { 0 });

/// <param name="source">The enumerable list of tokens output by <see cref="DMPreprocessor.DMPreprocessorLexer"/>.</param>
public DMLexer(string sourceName, IEnumerable<Token> source) : base(sourceName, source) { }
internal DMLexer(string sourceName, IEnumerable<Token> source) : base(sourceName, source) { }

protected override Token ParseNextToken() {
Token token;
Expand Down Expand Up @@ -114,6 +114,7 @@ protected override Token ParseNextToken() {
token = preprocToken;
}
} else {
var firstTokenLocation = CurrentLocation;
switch (preprocToken.Type) {
case TokenType.DM_Preproc_Whitespace: Advance(); token = CreateToken(TokenType.DM_Whitespace, preprocToken.Text); break;
case TokenType.DM_Preproc_Punctuator_LeftParenthesis: BracketNesting++; Advance(); token = CreateToken(TokenType.DM_LeftParenthesis, preprocToken.Text); break;
Expand All @@ -125,19 +126,19 @@ protected override Token ParseNextToken() {
case TokenType.DM_Preproc_Punctuator_Question:
switch (Advance().Type) {
case TokenType.DM_Preproc_Punctuator_Period:
token = CreateToken(TokenType.DM_QuestionPeriod, "?.");
Advance();
token = CreateToken(TokenType.DM_QuestionPeriod, "?.", firstTokenLocation);
break;

case TokenType.DM_Preproc_Punctuator_Colon:
token = CreateToken(TokenType.DM_QuestionColon, "?:");
Advance();
token = CreateToken(TokenType.DM_QuestionColon, "?:", firstTokenLocation);
break;

case TokenType.DM_Preproc_Punctuator_LeftBracket:
token = CreateToken(TokenType.DM_QuestionLeftBracket, "?[");
BracketNesting++;
Advance();
token = CreateToken(TokenType.DM_QuestionLeftBracket, "?[", firstTokenLocation);
BracketNesting++;
break;

default:
Expand All @@ -149,11 +150,10 @@ protected override Token ParseNextToken() {
switch (Advance().Type) {
case TokenType.DM_Preproc_Punctuator_Period:
if (Advance().Type == TokenType.DM_Preproc_Punctuator_Period) {
token = CreateToken(TokenType.DM_IndeterminateArgs, "...");

Advance();
token = CreateToken(TokenType.DM_IndeterminateArgs, "...", firstTokenLocation);
} else {
token = CreateToken(TokenType.DM_SuperProc, "..");
token = CreateToken(TokenType.DM_SuperProc, "..", firstTokenLocation);
}

break;
Expand Down Expand Up @@ -231,6 +231,7 @@ protected override Token ParseNextToken() {
break;
}
case TokenType.DM_Preproc_ConstantString: {
Advance();
string tokenText = preprocToken.Text;
switch (preprocToken.Text[0]) {
case '"':
Expand All @@ -239,21 +240,19 @@ protected override Token ParseNextToken() {
case '@': token = CreateToken(TokenType.DM_RawString, tokenText, preprocToken.Value); break;
default: token = CreateToken(TokenType.Error, tokenText, "Invalid string"); break;
}

Advance();
break;
}
case TokenType.DM_Preproc_StringBegin:
token = CreateToken(TokenType.DM_StringBegin, preprocToken.Text, preprocToken.Value);
Advance();
token = CreateToken(TokenType.DM_StringBegin, preprocToken.Text, preprocToken.Value);
break;
case TokenType.DM_Preproc_StringMiddle:
token = CreateToken(TokenType.DM_StringMiddle, preprocToken.Text, preprocToken.Value);
Advance();
token = CreateToken(TokenType.DM_StringMiddle, preprocToken.Text, preprocToken.Value);
break;
case TokenType.DM_Preproc_StringEnd:
token = CreateToken(TokenType.DM_StringEnd, preprocToken.Text, preprocToken.Value);
Advance();
token = CreateToken(TokenType.DM_StringEnd, preprocToken.Text, preprocToken.Value);
break;
case TokenType.DM_Preproc_Identifier: {
TokenTextBuilder.Clear();
Expand All @@ -267,7 +266,7 @@ protected override Token ParseNextToken() {
var identifierText = TokenTextBuilder.ToString();
var tokenType = Keywords.GetValueOrDefault(identifierText, TokenType.DM_Identifier);

token = CreateToken(tokenType, identifierText);
token = CreateToken(tokenType, identifierText, firstTokenLocation);
break;
}
case TokenType.DM_Preproc_Number: {
Expand All @@ -290,7 +289,7 @@ protected override Token ParseNextToken() {

break;
}
case TokenType.EndOfFile: token = preprocToken; Advance(); break;
case TokenType.EndOfFile: Advance(); token = preprocToken; break;
default: token = CreateToken(TokenType.Error, preprocToken.Text, "Invalid token"); break;
}
}
Expand Down
Loading

0 comments on commit f69f4be

Please sign in to comment.