Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement as syntax for multiple base types (mob|obj|turf) #1917

3 changes: 2 additions & 1 deletion DMCompiler/Bytecode/DreamProcOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ public enum DreamProcOpcode : byte {
CreateFilteredListEnumerator = 0x41,
[OpcodeMetadata(-1)]
Power = 0x42,
//0x43,
[OpcodeMetadata(-1, OpcodeArgType.EnumeratorId, OpcodeArgType.FilterId)]
CreateFilteredBaseTypesListEnumerator = 0x43,
//0x44
[OpcodeMetadata(-3, OpcodeArgType.TypeId)]
Prompt = 0x45,
Expand Down
6 changes: 4 additions & 2 deletions DMCompiler/DM/Builders/DMProcBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -612,8 +612,10 @@ public void ProcessStatementForList(DMExpression list, DMExpression outputVar, D
implicitTypeCheck = dmTypes.Value.TypePath;
} else if (!dmTypes.Value.IsAnything) {
// "as anything" performs no check. Other values are unimplemented.
DMCompiler.UnimplementedWarning(outputVar.Location,
$"As type {dmTypes} in for loops is unimplemented. No type check will be performed.");
byte typeId = (byte) dmTypes.Value.Type;
proc.CreateFilteredBaseTypesListEnumerator(typeId, dmTypes.Value.Type);
// DMCompiler.UnimplementedWarning(outputVar.Location,
// $"As type {dmTypes} in for loops is unimplemented. No type check will be performed.");
}

list.EmitPushValue(dmObject, proc);
Expand Down
10 changes: 10 additions & 0 deletions DMCompiler/DM/DMProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,12 @@ public void CreateFilteredListEnumerator(int filterTypeId, DreamPath filterType)
WriteFilterID(filterTypeId, filterType);
}

public void CreateFilteredBaseTypesListEnumerator(byte filterTypeId, DMValueType filterType) {
WriteOpcode(DreamProcOpcode.CreateFilteredBaseTypesListEnumerator);
WriteEnumeratorId(_enumeratorIdCounter++);
WriteFilterTypeID(filterTypeId, filterType);
}

public void CreateTypeEnumerator() {
WriteOpcode(DreamProcOpcode.CreateTypeEnumerator);
WriteEnumeratorId(_enumeratorIdCounter++);
Expand Down Expand Up @@ -1115,6 +1121,10 @@ private void WriteFilterID(int filterId, DreamPath filter) {
AnnotatedBytecode.WriteFilterId(filterId, filter, _writerLocation);
}

private void WriteFilterTypeID(byte filterId, DMValueType filter) {
AnnotatedBytecode.WriteFilterTypeId(filterId, filter, _writerLocation);
}

private void WriteStackDelta(int delta) {
AnnotatedBytecode.WriteStackDelta(delta, _writerLocation);
}
Expand Down
19 changes: 19 additions & 0 deletions DMCompiler/Optimizer/AnnotatedByteCodeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ public void WriteFilterId(int filterTypeId, DreamPath filterPath, Location locat
_annotatedBytecode[^1].AddArg(new AnnotatedBytecodeFilter(filterTypeId, filterPath, location));
}

/// <summary>
/// Write a filter. Filters are stored as reference IDs in the raw bytecode, which refer
/// to a string in the string table containing the datum path of the filter.
/// </summary>
/// <param name="filterPaths">The datum paths of the filter</param>
/// <param name="location">The location of the filter in the source code</param>
///
public void WriteFilterTypeId(byte filterTypeId, DMValueType filterPaths, Location location) {
_location = location;

if (_requiredArgs.Count == 0 || _requiredArgs.Peek() != OpcodeArgType.FilterId) {
DMCompiler.ForcedError(location, "Expected filter argument");
}

_requiredArgs.Pop();

_annotatedBytecode[^1].AddArg(new AnnotatedBytecodeTypeFilter(filterTypeId, filterPaths, location));
}

/// <summary>
/// Write a list size, restricted to non-negative integers
/// </summary>
Expand Down
29 changes: 29 additions & 0 deletions DMCompiler/Optimizer/AnnotatedBytecode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,35 @@ public Location GetLocation() {
}
}

internal sealed class AnnotatedBytecodeTypeFilter : IAnnotatedBytecode {
public DMValueType FilterPath;

public int FilterTypeId;
public Location Location;

public AnnotatedBytecodeTypeFilter(int filterTypeId, DMValueType filterPath, Location location) {
FilterTypeId = filterTypeId;
FilterPath = filterPath;
Location = location;
}

public void AddArg(IAnnotatedBytecode arg) {
DMCompiler.ForcedError(Location, "Cannot add args to a filter");
}

public void SetLocation(IAnnotatedBytecode loc) {
Location = loc.GetLocation();
}

public void SetLocation(Location loc) {
Location = loc;
}

public Location GetLocation() {
return Location;
}
}

internal sealed class AnnotatedBytecodeReference : IAnnotatedBytecode {
public int Index;
public Location Location;
Expand Down
10 changes: 10 additions & 0 deletions OpenDreamRuntime/Procs/DMOpcodeHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ public static ProcStatus CreateFilteredListEnumerator(DMProcState state) {
return ProcStatus.Continue;
}

public static ProcStatus CreateFilteredBaseTypesListEnumerator(DMProcState state) { // this is also plagarized from the above. make sure thats ok? and remove this comment
var enumeratorId = state.ReadInt();
var filterTypeId = state.ReadInt();
var filterType = state.Proc.ObjectTree.GetTreeEntry(filterTypeId); // this REALLY probably has to change. seems to be a path rn
var enumerator = GetContentsEnumerator(state.Proc.ObjectTree, state.Proc.AtomManager, state.Pop(), filterType);

state.Enumerators[enumeratorId] = enumerator;
return ProcStatus.Continue;
}

public static ProcStatus CreateTypeEnumerator(DMProcState state) {
var enumeratorId = state.ReadInt();
var typeValue = state.Pop();
Expand Down
1 change: 1 addition & 0 deletions OpenDreamRuntime/Procs/DMProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ public sealed class DMProcState : ProcState {
{DreamProcOpcode.OutputControl, DMOpcodeHandlers.OutputControl},
{DreamProcOpcode.BitShiftRight, DMOpcodeHandlers.BitShiftRight},
{DreamProcOpcode.CreateFilteredListEnumerator, DMOpcodeHandlers.CreateFilteredListEnumerator},
{DreamProcOpcode.CreateFilteredBaseTypesListEnumerator, DMOpcodeHandlers.CreateFilteredBaseTypesListEnumerator},
{DreamProcOpcode.Power, DMOpcodeHandlers.Power},
{DreamProcOpcode.Prompt, DMOpcodeHandlers.Prompt},
{DreamProcOpcode.Ftp, DMOpcodeHandlers.Ftp},
Expand Down
7 changes: 7 additions & 0 deletions OpenDreamRuntime/Procs/ProcDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public ITuple DecodeInstruction() {
return (opcode, ReadInt(), ReadReference(), ReadInt());

case DreamProcOpcode.CreateFilteredListEnumerator:
case DreamProcOpcode.CreateFilteredBaseTypesListEnumerator:
case DreamProcOpcode.EnumerateNoAssign:
return (opcode, ReadInt(), ReadInt());

Expand Down Expand Up @@ -289,6 +290,12 @@ or DreamProcOpcode.JumpIfTrueReference
text.Append(getTypePath(type));
break;

case (DreamProcOpcode.CreateFilteredBaseTypesListEnumerator, int enumeratorId, int type):
text.Append(enumeratorId);
text.Append(' ');
text.Append(getTypePath(type)); // TODO: maybe make sure this works / leave as thing for reviewer to talk abt
break;

case (DreamProcOpcode.CreateListNRefs
or DreamProcOpcode.PushNRefs, DMReference[] refs): {
foreach (var reference in refs) {
Expand Down