Skip to content

Commit

Permalink
Merge branch 'master' into tracy
Browse files Browse the repository at this point in the history
  • Loading branch information
amylizzle authored Dec 18, 2024
2 parents f03a935 + 64c5684 commit b2c5dbb
Show file tree
Hide file tree
Showing 29 changed files with 334 additions and 88 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ name: Lint
on:
pull_request:
branches: [master]
types: [opened, synchronize, reopened, ready_for_review]

jobs:
lint:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest

steps:
Expand Down
6 changes: 0 additions & 6 deletions Content.Tests/DMProject/Broken Tests/Procs/Arglist/initial.dm

This file was deleted.

7 changes: 5 additions & 2 deletions Content.Tests/DMProject/Tests/Builtins/__IMPLIED_TYPE__.dm
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@


/datum/test/var/bar = "foobar"
/datum/test
/proc/RunTest()
var/datum/test/D = __IMPLIED_TYPE__
ASSERT(D.bar == "foobar")
ASSERT(D == /datum/test)
D = ArgumentTest(__IMPLIED_TYPE__)

/proc/ArgumentTest(some_argument)
ASSERT(some_argument == /datum/test)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUNTIME ERROR

/proc/ListNullArg2(a[5][3])
ASSERT(a[1].len == 3)
ASSERT(a[1].len == 3) // a should be null

/proc/RunTest()
ListNullArg2()
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUNTIME ERROR

/proc/ListNullArg1(a[5])
ASSERT(a.len == 5)
ASSERT(a.len == 5) // a should be null

/proc/RunTest()
ListNullArg1()
6 changes: 6 additions & 0 deletions Content.Tests/DMProject/Tests/Procs/Arglist/initial.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

/proc/_initial(...)
ASSERT(initial(arglist(args))[1] == "foo")

/proc/RunTest()
_initial("foo")
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// COMPILE ERROR
// COMPILE ERROR OD0501

/datum
var/const/idx = 0
Expand Down
18 changes: 18 additions & 0 deletions Content.Tests/DMProject/Tests/Statements/For/reuse_decl_const2.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// COMPILE ERROR OD0501

/datum
var/const/idx = 0
var/c = 0
proc/do_loop()
for (idx in list(1,2,3))
c += idx

/proc/RunTest()
var/datum/d = new
d.do_loop()

var/const/idx = 0
var/c = 0
for (idx in list(1,2,3))
c += idx

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// COMPILE ERROR OD3205
#pragma ExtraToken error

/proc/RunTest()
if(1).
ASSERT(TRUE)
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@
ASSERT(TRUE)
else
ASSERT(FALSE)
for(var/i in 1 to 1):
ASSERT(TRUE)
for(var/i in 1 to 1).
ASSERT(TRUE)
2 changes: 2 additions & 0 deletions DMCompiler/Bytecode/DreamProcOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ public enum DreamProcOpcode : byte {
ReturnReferenceValue = 0x97,
[OpcodeMetadata(0, OpcodeArgType.Float)]
ReturnFloat = 0x98,
[OpcodeMetadata(1, OpcodeArgType.Reference, OpcodeArgType.String)]
IndexRefWithString = 0x99,
}
// ReSharper restore MissingBlankLines

Expand Down
1 change: 1 addition & 0 deletions DMCompiler/Compiler/CompilerError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public enum WarningCode {
AssignmentInConditional = 3202,
PickWeightedSyntax = 3203,
AmbiguousInOrder = 3204,
ExtraToken = 3205,
RuntimeSearchOperator = 3300,

// 4000 - 4999 are reserved for runtime configuration. (TODO: Runtime doesn't know about configs yet!)
Expand Down
42 changes: 39 additions & 3 deletions DMCompiler/Compiler/DM/DMParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,8 +1125,10 @@ private DMASTProcStatementIf If() {

BracketWhitespace();
ConsumeRightParenthesis();
Whitespace();
Check(TokenType.DM_Colon);
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

Whitespace();

DMASTProcStatement? procStatement = ProcStatement();
Expand Down Expand Up @@ -1165,6 +1167,10 @@ private DMASTProcStatement For() {
Whitespace();

if (Check(TokenType.DM_RightParenthesis)) {
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementInfLoop(loc, GetForBody(loc));
}

Expand All @@ -1185,6 +1191,10 @@ private DMASTProcStatement For() {
if (expr1 is DMASTAssign assign) {
ExpressionTo(out var endRange, out var step);
Consume(TokenType.DM_RightParenthesis, "Expected ')' in for after to expression");
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, new DMASTExpressionInRange(loc, assign.LHS, assign.RHS, endRange, step), null, null, dmTypes, GetForBody(loc));
} else {
Emit(WarningCode.BadExpression, "Expected = before to in for");
Expand All @@ -1197,15 +1207,27 @@ private DMASTProcStatement For() {
DMASTExpression? listExpr = Expression();
Whitespace();
Consume(TokenType.DM_RightParenthesis, "Expected ')' in for after expression 2");
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, new DMASTExpressionIn(loc, expr1, listExpr), null, null, dmTypes, GetForBody(loc));
}

if (!Check(ForSeparatorTypes)) {
Consume(TokenType.DM_RightParenthesis, "Expected ')' in for after expression 1");
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, expr1, null, null, dmTypes, GetForBody(loc));
}

if (Check(TokenType.DM_RightParenthesis)) {
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, expr1, null, null, dmTypes, GetForBody(loc));
}

Expand All @@ -1221,10 +1243,18 @@ private DMASTProcStatement For() {

if (!Check(ForSeparatorTypes)) {
Consume(TokenType.DM_RightParenthesis, "Expected ')' in for after expression 2");
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, expr1, expr2, null, dmTypes, GetForBody(loc));
}

if (Check(TokenType.DM_RightParenthesis)) {
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, expr1, expr2, null, dmTypes, GetForBody(loc));
}

Expand All @@ -1239,6 +1269,10 @@ private DMASTProcStatement For() {
}

Consume(TokenType.DM_RightParenthesis, "Expected ')' in for after expression 3");
if (Check(TokenType.DM_Colon) || Check(TokenType.DM_Period)) {
Emit(WarningCode.ExtraToken, loc, "Extra token at end of proc statement");
}

return new DMASTProcStatementFor(loc, expr1, expr2, expr3, dmTypes, GetForBody(loc));

DMASTProcBlockInner GetForBody(Location forLocation) {
Expand Down Expand Up @@ -1690,7 +1724,9 @@ private List<DMASTDefinitionParameter> DefinitionParameters(out bool wasIndeterm
var loc = Current().Location;
Whitespace();

DMASTExpression? value = PathArray(ref path.Path);
PathArray(ref path.Path);

DMASTExpression? value = null;
DMASTExpression? possibleValues = null;

if (Check(TokenType.DM_DoubleSquareBracketEquals)) {
Expand Down
36 changes: 18 additions & 18 deletions DMCompiler/DM/Builders/DMExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ private DMExpression BuildExpression(DMASTExpression expression, DreamPath? infe
case DMASTDereference deref: result = BuildDereference(deref, inferredPath); break;
case DMASTLocate locate: result = BuildLocate(locate, inferredPath); break;
case DMASTImplicitIsType implicitIsType: result = BuildImplicitIsType(implicitIsType, inferredPath); break;
case DMASTList list: result = BuildList(list); break;
case DMASTList list: result = BuildList(list, inferredPath); break;
case DMASTDimensionalList dimensionalList: result = BuildDimensionalList(dimensionalList, inferredPath); break;
case DMASTNewList newList: result = BuildNewList(newList, inferredPath); break;
case DMASTAddText addText: result = BuildAddText(addText, inferredPath); break;
case DMASTInput input: result = BuildInput(input); break;
case DMASTPick pick: result = BuildPick(pick); break;
case DMASTInput input: result = BuildInput(input, inferredPath); break;
case DMASTPick pick: result = BuildPick(pick, inferredPath); break;
case DMASTLog log: result = BuildLog(log, inferredPath); break;
case DMASTCall call: result = BuildCall(call, inferredPath); break;
case DMASTExpressionWrapped wrapped: result = BuildExpression(wrapped.Value, inferredPath); break;
Expand Down Expand Up @@ -327,10 +327,10 @@ private DMExpression BuildExpression(DMASTExpression expression, DreamPath? infe
break;
case DMASTGradient gradient:
result = new Gradient(gradient.Location,
BuildArgumentList(gradient.Location, gradient.Parameters));
BuildArgumentList(gradient.Location, gradient.Parameters, inferredPath));
break;
case DMASTRgb rgb:
result = new Rgb(rgb.Location, BuildArgumentList(rgb.Location, rgb.Parameters));
result = new Rgb(rgb.Location, BuildArgumentList(rgb.Location, rgb.Parameters, inferredPath));
break;
case DMASTLocateCoordinates locateCoordinates:
result = new LocateCoordinates(locateCoordinates.Location,
Expand Down Expand Up @@ -435,7 +435,7 @@ private DMExpression BuildExpression(DMASTExpression expression, DreamPath? infe
case DMASTVarDeclExpression varDeclExpr:
var declIdentifier = new DMASTIdentifier(expression.Location, varDeclExpr.DeclPath.Path.LastElement);

result = BuildIdentifier(declIdentifier);
result = BuildIdentifier(declIdentifier, inferredPath);
break;
case DMASTVoid:
result = BadExpression(WarningCode.BadExpression, expression.Location, "Attempt to use a void expression");
Expand Down Expand Up @@ -751,7 +751,7 @@ private DMExpression BuildProcCall(DMASTProcCall procCall, DreamPath? inferredPa
}

var target = BuildExpression((DMASTExpression)procCall.Callable, inferredPath);
var args = BuildArgumentList(procCall.Location, procCall.Parameters);
var args = BuildArgumentList(procCall.Location, procCall.Parameters, inferredPath);
if (target is Proc targetProc) { // GlobalProc handles returnType itself
var returnType = targetProc.GetReturnType(ctx.Type);

Expand Down Expand Up @@ -885,7 +885,7 @@ private DMExpression BuildDereference(DMASTDereference deref, DreamPath? inferre
return UnknownReference(callOperation.Location,
$"Could not find a global proc named \"{callOperation.Identifier}\"");

var argumentList = BuildArgumentList(deref.Expression.Location, callOperation.Parameters);
var argumentList = BuildArgumentList(deref.Expression.Location, callOperation.Parameters, inferredPath);

var globalProcExpr = new GlobalProc(expr.Location, globalProc);
expr = new ProcCall(expr.Location, globalProcExpr, argumentList, DMValueType.Anything);
Expand Down Expand Up @@ -1023,7 +1023,7 @@ private DMExpression BuildDereference(DMASTDereference deref, DreamPath? inferre

case DMASTDereference.CallOperation callOperation: {
var field = callOperation.Identifier;
var argumentList = BuildArgumentList(deref.Expression.Location, callOperation.Parameters);
var argumentList = BuildArgumentList(deref.Expression.Location, callOperation.Parameters, inferredPath);

if (!callOperation.NoSearch && !pathIsFuzzy) {
if (prevPath == null) {
Expand Down Expand Up @@ -1081,16 +1081,16 @@ private DMExpression BuildImplicitIsType(DMASTImplicitIsType isType, DreamPath?
return new IsTypeInferred(isType.Location, expr, expr.Path.Value);
}

private DMExpression BuildList(DMASTList list) {
private DMExpression BuildList(DMASTList list, DreamPath? inferredPath) {
(DMExpression? Key, DMExpression Value)[] values = [];

if (list.Values != null) {
values = new (DMExpression?, DMExpression)[list.Values.Length];

for (int i = 0; i < list.Values.Length; i++) {
DMASTCallParameter value = list.Values[i];
DMExpression? key = (value.Key != null) ? BuildExpression(value.Key) : null;
DMExpression listValue = BuildExpression(value.Value);
DMExpression? key = (value.Key != null) ? BuildExpression(value.Key, inferredPath) : null;
DMExpression listValue = BuildExpression(value.Value, inferredPath);

values[i] = (key, listValue);
}
Expand Down Expand Up @@ -1151,7 +1151,7 @@ private DMExpression BuildAddText(DMASTAddText addText, DreamPath? inferredPath)
return new AddText(addText.Location, expArr);
}

private DMExpression BuildInput(DMASTInput input) {
private DMExpression BuildInput(DMASTInput input, DreamPath? inferredPath) {
DMExpression[] arguments = new DMExpression[input.Parameters.Length];
for (int i = 0; i < input.Parameters.Length; i++) {
DMASTCallParameter parameter = input.Parameters[i];
Expand All @@ -1161,12 +1161,12 @@ private DMExpression BuildInput(DMASTInput input) {
"input() does not take named arguments");
}

arguments[i] = BuildExpression(parameter.Value);
arguments[i] = BuildExpression(parameter.Value, inferredPath);
}

DMExpression? list = null;
if (input.List != null) {
list = BuildExpression(input.List);
list = BuildExpression(input.List, inferredPath);

DMValueType objectTypes = DMValueType.Null |DMValueType.Obj | DMValueType.Mob | DMValueType.Turf |
DMValueType.Area;
Expand All @@ -1188,13 +1188,13 @@ private DMExpression BuildInput(DMASTInput input) {
return new Input(input.Location, arguments, input.Types.Value, list);
}

private DMExpression BuildPick(DMASTPick pick) {
private DMExpression BuildPick(DMASTPick pick, DreamPath? inferredPath) {
Pick.PickValue[] pickValues = new Pick.PickValue[pick.Values.Length];

for (int i = 0; i < pickValues.Length; i++) {
DMASTPick.PickValue pickValue = pick.Values[i];
DMExpression? weight = (pickValue.Weight != null) ? BuildExpression(pickValue.Weight) : null;
DMExpression value = BuildExpression(pickValue.Value);
DMExpression? weight = (pickValue.Weight != null) ? BuildExpression(pickValue.Weight, inferredPath) : null;
DMExpression value = BuildExpression(pickValue.Value, inferredPath);

if (weight is Prob prob) // pick(prob(50);x, prob(200);y) format
weight = prob.P;
Expand Down
9 changes: 8 additions & 1 deletion DMCompiler/DM/Builders/DMProcBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,10 @@ public void ProcessStatementFor(DMASTProcStatementFor statementFor) {

var outputVar = _exprBuilder.Create(outputExpr);

if (outputVar is Local { LocalVar: DMProc.LocalConstVariable } or Field { IsConst: true }) {
compiler.Emit(WarningCode.WriteToConstant, outputExpr.Location, "Cannot change constant value");
}

var start = _exprBuilder.Create(exprRange.StartRange);
var end = _exprBuilder.Create(exprRange.EndRange);
var step = exprRange.Step != null
Expand Down Expand Up @@ -520,7 +524,10 @@ public void ProcessStatementFor(DMASTProcStatementFor statementFor) {

if (outputVar is Local outputLocal) {
outputLocal.LocalVar.ExplicitValueType = statementFor.DMTypes;
}
if(outputLocal.LocalVar is DMProc.LocalConstVariable)
compiler.Emit(WarningCode.WriteToConstant, outputExpr.Location, "Cannot change constant value");
} else if (outputVar is Field { IsConst: true })
compiler.Emit(WarningCode.WriteToConstant, outputExpr.Location, "Cannot change constant value");

ProcessStatementForList(list, outputVar, statementFor.DMTypes, statementFor.Body);
break;
Expand Down
11 changes: 9 additions & 2 deletions DMCompiler/DM/DMCodeTree.Vars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,16 @@ private bool AlreadyExists(DMCompiler compiler, DMObject dmObject) {
$"Duplicate definition of static var \"{VarName}\"");
return true;
} else if (dmObject.HasLocalVariable(VarName)) {
if (!varDef.Location.InDMStandard) // Duplicate instance vars are not an error in DMStandard
compiler.Emit(WarningCode.InvalidVarDefinition, varDef.Location,
if (!varDef.Location.InDMStandard) { // Duplicate instance vars are not an error in DMStandard
var variable = dmObject.GetVariable(VarName);
if(variable!.Value is not null)
compiler.Emit(WarningCode.InvalidVarDefinition, varDef.Location,
$"Duplicate definition of var \"{VarName}\". Previous definition at {variable.Value.Location}");
else
compiler.Emit(WarningCode.InvalidVarDefinition, varDef.Location,
$"Duplicate definition of var \"{VarName}\"");
}

return true;
} else if (IsStatic && VarName == "vars" && dmObject == compiler.DMObjectTree.Root) {
compiler.Emit(WarningCode.InvalidVarDefinition, varDef.Location, "Duplicate definition of global.vars");
Expand Down
3 changes: 1 addition & 2 deletions DMCompiler/DM/DMProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,9 @@ public void ValidateReturnType(DMExpression expr) {
}

public ProcDefinitionJson GetJsonRepresentation() {
var optimizer = new BytecodeOptimizer();
var serializer = new AnnotatedBytecodeSerializer(_compiler);

optimizer.Optimize(_compiler, AnnotatedBytecode.GetAnnotatedBytecode());
_compiler.BytecodeOptimizer.Optimize(AnnotatedBytecode.GetAnnotatedBytecode());

List<ProcArgumentJson>? arguments = null;
if (_parameters.Count > 0) {
Expand Down
Loading

0 comments on commit b2c5dbb

Please sign in to comment.