Skip to content

Commit

Permalink
Merge branch 'master' into winclone-child-elements
Browse files Browse the repository at this point in the history
  • Loading branch information
amylizzle authored Sep 21, 2023
2 parents d4fb501 + 90fce27 commit e3c21a7
Show file tree
Hide file tree
Showing 41 changed files with 715 additions and 244 deletions.
39 changes: 39 additions & 0 deletions Content.Tests/DMProject/Tests/Builtins/text2num.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// NaN != NaN in BYOND
#define isnan(x) ( (x) != (x) )

/proc/RunTest()
ASSERT(text2num(null) == null)
ASSERT(text2num("") == null)
ASSERT(text2num(".") == null)
ASSERT(text2num("-") == null)
ASSERT(text2num("+") == null)

ASSERT(text2num("12") == 12)
ASSERT(text2num("+12") == 12)
ASSERT(text2num("-12") == -12)
ASSERT(text2num("0") == 0)
ASSERT(text2num("1.0") == 1)
ASSERT(text2num("1.2344") == 1.2344)
ASSERT(text2num("0.0") == 0)
ASSERT(text2num(".4") == 0.4)

ASSERT(text2num("Z", 36) == 35)
ASSERT(text2num("A", 16) == 10)
ASSERT(text2num("z", 36) == 35)
ASSERT(text2num("a", 16) == 10)

ASSERT(text2num("F.A", 16) == 15.625)
ASSERT(text2num("f.a", 16) == 15.625)
ASSERT(text2num("F.A", 15) == null)
ASSERT(text2num("Z.0", 36) == 35)

ASSERT(text2num("F..A", 16) == 15)
ASSERT(text2num("4 2") == 4)

ASSERT(text2num("0xA") == 10)
ASSERT(text2num("0xA", 16) == 10)
ASSERT(text2num("0xA", 15) == 0)
ASSERT(text2num("0xA", 36) == 1198)

ASSERT(isnan(text2num("nan")))
ASSERT(isnan(text2num(" -nansomething")))
7 changes: 7 additions & 0 deletions Content.Tests/DMProject/Tests/Math/trig.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/proc/RunTest()
ASSERT(arctan(0) == 0)
ASSERT(arctan(1) == 45)
ASSERT(arctan(sqrt(3)) == 60)
ASSERT(round(arctan(3, 4)) == round(53.1301)) //that float precision tho
ASSERT(arctan(-1, 1) == 135)
ASSERT(arctan(0, -5) == -90)
39 changes: 39 additions & 0 deletions Content.Tests/DMProject/Tests/Text/StringInterpolation9.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/datum/thing
var/name = "thing"

/datum/Thing
var/name = "Thing"

/datum/proper_thing
var/name = "\proper thing"

/datum/plural_things
var/name = "things"
var/gender = PLURAL

/proc/RunTest()
// Lowercase \a on datums
ASSERT("\a [new /datum/thing]" == "a thing")
ASSERT("\a [new /datum/Thing]" == "Thing")
ASSERT("\a [new /datum/proper_thing]" == "thing")
ASSERT("\a [new /datum/plural_things]" == "some things")

// Uppercase \A on datums
ASSERT("\A [new /datum/thing]" == "A thing")
ASSERT("\A [new /datum/Thing]" == "Thing")
ASSERT("\A [new /datum/proper_thing]" == "thing")
ASSERT("\A [new /datum/plural_things]" == "Some things")

// Lowercase \a on strings
ASSERT("\a ["thing"]" == "a thing")
ASSERT("\a ["Thing"]" == "Thing")
ASSERT("\a ["\proper thing"]" == "thing")

// Uppercase \A on strings
ASSERT("\A ["thing"]" == "A thing")
ASSERT("\A ["Thing"]" == "Thing")
ASSERT("\A ["\proper thing"]" == "thing")

// Invalid \a
ASSERT("\a [123]" == "")
ASSERT("\A [123]" == "")
20 changes: 20 additions & 0 deletions Content.Tests/DMProject/Tests/Text/findlasttext.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/proc/RunTest()
ASSERT(findlasttext("abcdefg", "f", 0, -1) == 0)
ASSERT(findlasttext("abcdefg", "f", 0, -2) == 6)
ASSERT(findlasttext("abcdefg", "f", 6) == 6)
ASSERT(findlasttext("abcdefg", "f", 5) == 0)
ASSERT(findlasttext("abcdefg", "bc", 2) == 2)
ASSERT(findlasttext("abcdefg", "ab", 10) == 1)
ASSERT(findlasttext("abcdefg", "f", 5) == 0)
ASSERT(findlasttext("Banana", "na", -3) == 3)
ASSERT(findlasttext("Banana", "na", -5) == 0)
ASSERT(findlasttext("Banana", "na", 0) == 5)
ASSERT(findlasttext("Banana", "na", 3) == 3)
ASSERT(findlasttext("Banana", "na", 2) == 0)
ASSERT(findlasttext("Banana", "na", 5) == 5)
ASSERT(findlasttext("Banana", "na", 50) == 5)
ASSERT(findlasttext("Banana", "na", -50) == 0)
ASSERT(findlasttext("abcdefg", "f", 6, -50) == 6)
ASSERT(findlasttext("abcdefg", "f", 6, 50) == 0)


27 changes: 27 additions & 0 deletions DMCompiler/Compiler/DM/DMAST.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenDreamShared.Compiler;
using OpenDreamShared.Dream;
using OpenDreamShared.Dream.Procs;
Expand Down Expand Up @@ -190,6 +191,10 @@ public void VisitList(DMASTList list) {
throw new NotImplementedException();
}

public void VisitDimensionalList(DMASTDimensionalList list) {
throw new NotImplementedException();
}

public void VisitNewList(DMASTNewList newList) {
throw new NotImplementedException();
}
Expand Down Expand Up @@ -1294,6 +1299,28 @@ public DMASTList(Location location, DMASTCallParameter[] values) : base(location
public override void Visit(DMASTVisitor visitor) {
visitor.VisitList(this);
}

public bool AllValuesConstant() {
return Values.All(value => value is {
Key: DMASTExpressionConstant,
Value: DMASTExpressionConstant
});
}
}

/// <summary>
/// Represents the value of a var defined as <code>var/list/L[1][2][3]</code>
/// </summary>
public sealed class DMASTDimensionalList : DMASTExpression {
public readonly List<DMASTExpression> Sizes;

public DMASTDimensionalList(Location location, List<DMASTExpression> sizes) : base(location) {
Sizes = sizes;
}

public override void Visit(DMASTVisitor visitor) {
visitor.VisitDimensionalList(this);
}
}

public sealed class DMASTAddText : DMASTExpression {
Expand Down
28 changes: 20 additions & 8 deletions DMCompiler/Compiler/DM/DMParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ public DMASTFile File() {
while (true) {
Whitespace();

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

if (Check(TokenType.DM_Equals)) {
if (value != null) Warning("List doubly initialized");
Expand Down Expand Up @@ -410,7 +410,7 @@ public DMASTFile File() {
}
}

public DMASTExpression? PathArray(ref DreamPath path) {
public DMASTDimensionalList? PathArray(ref DreamPath path) {
if (Current().Type == TokenType.DM_LeftBracket || Current().Type == TokenType.DM_DoubleSquareBracket) {
var loc = Current().Location;

Expand All @@ -421,7 +421,7 @@ public DMASTFile File() {
path = new DreamPath("/" + String.Join("/", elements));
}

List<DMASTCallParameter> sizes = new(2); // Most common is 1D or 2D lists
List<DMASTExpression> sizes = new(2); // Most common is 1D or 2D lists

while (true) {
if(Check(TokenType.DM_DoubleSquareBracket))
Expand All @@ -430,18 +430,17 @@ public DMASTFile File() {
Whitespace();
var size = Expression();
if (size is not null) {
sizes.Add(new DMASTCallParameter(size.Location, size));
sizes.Add(size);
}

ConsumeRightBracket();
Whitespace();
}
else
} else
break;
}

if (sizes.Count > 0) {
return new DMASTNewPath(loc, new DMASTPath(loc, DreamPath.List), sizes.ToArray());
return new DMASTDimensionalList(loc, sizes);
}
}

Expand Down Expand Up @@ -637,7 +636,20 @@ public DMASTFile File() {
if (expression != null) {
switch (expression) {
case DMASTIdentifier identifier:
Check(TokenType.DM_Colon);
// This could be a sleep without parentheses
if (!Check(TokenType.DM_Colon) && !leadingColon && identifier.Identifier == "sleep") {
var procIdentifier = new DMASTCallableProcIdentifier(expression.Location, "sleep");
var sleepTime = Expression();
if (sleepTime == null) // The argument is optional
sleepTime = new DMASTConstantNull(Location.Internal);

// TODO: Make sleep an opcode
expression = new DMASTProcCall(expression.Location, procIdentifier,
new[] { new DMASTCallParameter(sleepTime.Location, sleepTime) });
break;
}

// But it was a label
return Label(identifier);
case DMASTRightShift rightShift:
// A right shift on its own becomes a special "input" statement
Expand Down
28 changes: 10 additions & 18 deletions DMCompiler/DM/DMObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal static class DMObjectTree {
public static DMObject Root => GetDMObject(DreamPath.Root)!;

private static readonly Dictionary<string, int> StringToStringId = new();
private static readonly Dictionary<DreamPath, List<(int GlobalId, DMExpression Value)>> _globalInitAssigns = new();
private static readonly List<(int GlobalId, DMExpression Value)> _globalInitAssigns = new();

private static Dictionary<DreamPath, int> _pathToTypeId = new();
private static int _dmObjectIdCounter = 0;
Expand Down Expand Up @@ -182,29 +182,21 @@ public static void AddGlobalProc(string name, int id) {
GlobalProcs[name] = id; // Said in this way so it clobbers previous definitions of this global proc (the ..() stuff doesn't work with glob procs)
}

public static void AddGlobalInitAssign(DMObject owningType, int globalId, DMExpression value) {
if (!_globalInitAssigns.TryGetValue(owningType.Path, out var list)) {
list = new List<(int GlobalId, DMExpression Value)>();

_globalInitAssigns.Add(owningType.Path, list);
}

list.Add( (globalId, value) );
public static void AddGlobalInitAssign(int globalId, DMExpression value) {
_globalInitAssigns.Add( (globalId, value) );
}

public static void CreateGlobalInitProc() {
if (_globalInitAssigns.Count == 0) return;

foreach (var globals in _globalInitAssigns.Values) {
foreach (var assign in globals) {
try {
GlobalInitProc.DebugSource(assign.Value.Location);
foreach (var assign in _globalInitAssigns) {
try {
GlobalInitProc.DebugSource(assign.Value.Location);

assign.Value.EmitPushValue(Root, GlobalInitProc);
GlobalInitProc.Assign(DMReference.CreateGlobal(assign.GlobalId));
} catch (CompileErrorException e) {
DMCompiler.Emit(e.Error);
}
assign.Value.EmitPushValue(Root, GlobalInitProc);
GlobalInitProc.Assign(DMReference.CreateGlobal(assign.GlobalId));
} catch (CompileErrorException e) {
DMCompiler.Emit(e.Error);
}
}

Expand Down
5 changes: 0 additions & 5 deletions DMCompiler/DM/Expressions/Binary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,6 @@ public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) {
return true;
}

if (RHS.TryAsConstant(out var rhs)) {
constant = rhs;
return true;
}

constant = null;
return false;
}
Expand Down
25 changes: 25 additions & 0 deletions DMCompiler/DM/Expressions/Builtins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,31 @@ public override bool TryAsJsonRepresentation(out object? json) {
}
}

// Value of var/list/L[1][2][3]
internal sealed class DimensionalList : DMExpression {
private readonly DMExpression[] _sizes;

public DimensionalList(Location location, DMExpression[] sizes) : base(location) {
_sizes = sizes;
}

public override void EmitPushValue(DMObject dmObject, DMProc proc) {
// This basically emits new /list(1, 2, 3)

if (!DMObjectTree.TryGetTypeId(DreamPath.List, out var listTypeId)) {
DMCompiler.Emit(WarningCode.ItemDoesntExist, Location, "Could not get type ID of /list");
return;
}

foreach (var size in _sizes) {
size.EmitPushValue(dmObject, proc);
}

proc.PushType(listTypeId);
proc.CreateObject(DMCallArgumentsType.FromStack, _sizes.Length);
}
}

// newlist(...)
sealed class NewList : DMExpression {
private readonly DMExpression[] _parameters;
Expand Down
Loading

0 comments on commit e3c21a7

Please sign in to comment.