Skip to content

Commit

Permalink
Merge branch 'master' into icon_blend_additions3
Browse files Browse the repository at this point in the history
# Conflicts:
#	OpenDreamRuntime/DreamManager.cs
#	OpenDreamRuntime/Objects/DreamIcon.cs
#	OpenDreamRuntime/Objects/DreamList.cs
#	OpenDreamRuntime/Objects/DreamObjectDefinition.cs
#	OpenDreamRuntime/Objects/DreamObjectTree.cs
#	OpenDreamRuntime/Procs/DMProc.cs
  • Loading branch information
wixoaGit committed Dec 15, 2022
2 parents 7640e98 + 1f9d661 commit 3ccabd5
Show file tree
Hide file tree
Showing 39 changed files with 1,076 additions and 307 deletions.
11 changes: 7 additions & 4 deletions DMCompiler/DM/DMObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DMObject {

public List<DMASTObjectVarOverride>? danglingOverrides = null; // Overrides waiting for the LateVarDef event to happen
private bool _isSubscribedToVarDef = false;

public DMObject(int id, DreamPath path, DMObject parent) {
Id = id;
Path = path;
Expand Down Expand Up @@ -90,7 +90,7 @@ public void WaitForLateVarDefinition(DMASTObjectVarOverride varOverride)
}
}

///<remarks>
///<remarks>
/// Note that this DOES NOT query our <see cref= "GlobalVariables" />. <br/>
/// <see langword="TODO:"/> Make this (and other things) match the nomenclature of <see cref="HasLocalVariable"/>
/// </remarks>
Expand Down Expand Up @@ -179,15 +179,18 @@ public DMVariable GetGlobalVariable(string name) {
}

public void CreateInitializationProc() {
if (InitializationProcExpressions.Count > 0 && InitializationProc == null)
{
if (InitializationProcExpressions.Count > 0 && InitializationProc == null) {
var init = DMObjectTree.CreateDMProc(this, null);
InitializationProc = init.Id;
init.PushArguments(0);
init.Call(DMReference.SuperProc);

foreach (DMExpression expression in InitializationProcExpressions) {
try {
if (expression.Location.Line is int line) {
init.DebugSource(expression.Location.SourceFile);
init.DebugLine(line);
}
expression.EmitPushValue(this, init);
} catch (CompileErrorException e) {
DMCompiler.Emit(e.Error);
Expand Down
4 changes: 4 additions & 0 deletions DMCompiler/DM/DMObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ public static void CreateGlobalInitProc() {
foreach (var globals in _globalInitAssigns.Values) {
foreach (var assign in globals) {
try {
if (assign.Value.Location.Line is int line) {
GlobalInitProc.DebugSource(assign.Value.Location.SourceFile);
GlobalInitProc.DebugLine(line);
}
assign.Value.EmitPushValue(root, GlobalInitProc);
GlobalInitProc.Assign(DMReference.CreateGlobal(assign.GlobalId));
} catch (CompileErrorException e) {
Expand Down
24 changes: 19 additions & 5 deletions DMCompiler/DM/DMProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public DMProcScope(DMProcScope parentScope) {
public List<DMValueType> ParameterTypes = new();
public Location Location = Location.Unknown;
public ProcAttributes Attributes;
public string Name { get => _astDefinition?.Name; }
public string Name { get => _astDefinition?.Name ?? "<init>"; }
public int Id;
public Dictionary<string, int> GlobalVariables = new();

Expand All @@ -65,12 +65,23 @@ public DMProcScope(DMProcScope parentScope) {
[CanBeNull] private Stack<string> _loopStack = null;
private Stack<DMProcScope> _scopes = new();
private Dictionary<string, LocalVariable> _parameters = new();
private int _localVariableIdCounter = 0;
private int _labelIdCounter = 0;
private int _maxStackSize = 0;
private int _currentStackSize = 0;
private bool _negativeStackSizeError = false;

private List<LocalVariableJson> _localVariableNames = new();
private int _localVariableIdCounter = 0;
private int AllocLocalVariable(string name) {
_localVariableNames.Add(new LocalVariableJson { Offset = (int)Bytecode.Position, Add = name });
return _localVariableIdCounter++;
}
private void DeallocLocalVariables(int amount) {
if (amount > 0) {
_localVariableNames.Add(new LocalVariableJson { Offset = (int)Bytecode.Position, Remove = amount });
_localVariableIdCounter -= amount;
}
}

public DMProc(int id, DMObject dmObject, [CanBeNull] DMASTProcDefinition astDefinition)
{
Expand Down Expand Up @@ -136,6 +147,9 @@ public ProcDefinitionJson GetJsonRepresentation() {
});
}
}
if (_localVariableNames.Count > 0) {
procDefinition.Locals = _localVariableNames;
}

return procDefinition;
}
Expand Down Expand Up @@ -214,15 +228,15 @@ public bool TryAddLocalVariable(string name, DreamPath? type) {
if (_parameters.ContainsKey(name)) //Parameters and local vars cannot share a name
return false;

int localVarId = _localVariableIdCounter++;
int localVarId = AllocLocalVariable(name);
return _scopes.Peek().LocalVariables.TryAdd(name, new LocalVariable(localVarId, false, type));
}

public bool TryAddLocalConstVariable(string name, DreamPath? type, Expressions.Constant value) {
if (_parameters.ContainsKey(name)) //Parameters and local vars cannot share a name
return false;

int localVarId = _localVariableIdCounter++;
int localVarId = AllocLocalVariable(name);
return _scopes.Peek().LocalVariables.TryAdd(name, new LocalConstVariable(localVarId, type, value));
}

Expand Down Expand Up @@ -544,7 +558,7 @@ public void StartScope() {

public void EndScope() {
DMProcScope destroyedScope = _scopes.Pop();
_localVariableIdCounter -= destroyedScope.LocalVariables.Count;
DeallocLocalVariables(destroyedScope.LocalVariables.Count);
}

public void Jump(string label) {
Expand Down
10 changes: 6 additions & 4 deletions DMCompiler/DM/Visitors/DMObjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,10 @@ private static void ProcessProcDefinition(DMASTProcDefinition procDefinition, DM
}

if (procDefinition.IsVerb && (dmObject.IsSubtypeOf(DreamPath.Atom) || dmObject.IsSubtypeOf(DreamPath.Client)) && !DMCompiler.Settings.NoStandard) {
Expressions.Field field = new Expressions.Field(Location.Unknown, dmObject.GetVariable("verbs"));
var initLoc = procDefinition.Location;
Expressions.Field field = new Expressions.Field(initLoc, dmObject.GetVariable("verbs"));
DreamPath procPath = new DreamPath(".proc/" + procName);
Expressions.Append append = new Expressions.Append(Location.Unknown, field, new Expressions.Path(Location.Unknown, procPath));
Expressions.Append append = new Expressions.Append(initLoc, field, new Expressions.Path(initLoc, procPath));

dmObject.InitializationProcExpressions.Add(append);
}
Expand Down Expand Up @@ -377,8 +378,9 @@ private static void EmitInitializationAssign(DMObject currentObject, DMVariable

DMObjectTree.AddGlobalInitAssign(currentObject, globalId.Value, expression);
} else {
Expressions.Field field = new Expressions.Field(Location.Unknown, variable);
Expressions.Assignment assign = new Expressions.Assignment(Location.Unknown, field, expression);
var initLoc = expression.Location;
Expressions.Field field = new Expressions.Field(initLoc, variable);
Expressions.Assignment assign = new Expressions.Assignment(initLoc, field, expression);

currentObject.InitializationProcExpressions.Add(assign);
}
Expand Down
7 changes: 4 additions & 3 deletions DMCompiler/DMCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,8 @@ DMPreprocessor build() {

if (Settings.DumpPreprocessor) {
//Preprocessing is done twice because the output is used up when dumping it
DMPreprocessor dumpPreproc = build();

StringBuilder result = new();
foreach (Token t in dumpPreproc) {
foreach (Token t in build()) {
result.Append(t.Text);
}

Expand Down Expand Up @@ -283,12 +281,15 @@ private static string SaveJson(List<DreamMapJson> maps, string interfaceFile, st
if (DMObjectTree.Globals.Count > 0) {
GlobalListJson globalListJson = new GlobalListJson();
globalListJson.GlobalCount = DMObjectTree.Globals.Count;
globalListJson.Names = new List<string>(globalListJson.GlobalCount);

// Approximate capacity (4/285 in tgstation, ~3%)
globalListJson.Globals = new Dictionary<int, object>((int) (DMObjectTree.Globals.Count * 0.03));

for (int i = 0; i < DMObjectTree.Globals.Count; i++) {
DMVariable global = DMObjectTree.Globals[i];
globalListJson.Names.Add(global.Name);

if (!global.TryAsJsonRepresentation(out var globalJson))
ForcedError(global.Value.Location, $"Failed to serialize global {global.Name}");

Expand Down
2 changes: 1 addition & 1 deletion OpenDreamRuntime/AtomManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public IconAppearance CreateAppearanceFromDefinition(DreamObjectDefinition def)
}
}

internal interface IAtomManager {
public interface IAtomManager {
public Dictionary<DreamList, DreamObject> OverlaysListToAtom { get; }
public Dictionary<DreamList, DreamObject> UnderlaysListToAtom { get; }

Expand Down
15 changes: 9 additions & 6 deletions OpenDreamRuntime/DreamManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using OpenDreamRuntime.Objects;
using OpenDreamRuntime.Objects.MetaObjects;
using OpenDreamRuntime.Procs;
using OpenDreamRuntime.Procs.DebugAdapter;
using OpenDreamRuntime.Procs.Native;
using OpenDreamRuntime.Resources;
using OpenDreamShared;
Expand All @@ -20,15 +21,19 @@ partial class DreamManager : IDreamManager {
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IDreamMapManager _dreamMapManager = default!;
[Dependency] private readonly IDreamDebugManager _dreamDebugManager = default!;
[Dependency] private readonly IProcScheduler _procScheduler = default!;
[Dependency] private readonly DreamResourceManager _dreamResourceManager = default!;
[Dependency] private readonly ITaskManager _taskManager = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IDreamObjectTree _objectTree = default!;

public DreamObject WorldInstance { get; private set; }
public Exception? LastDMException { get; set; }

// Global state that may not really (really really) belong here
public List<DreamValue> Globals { get; set; } = new();
public IReadOnlyList<string> GlobalNames { get; private set; } = new List<string>();
public DreamList WorldContentsList { get; private set; }
public Dictionary<DreamObject, DreamList> AreaContents { get; set; } = new();
public Dictionary<DreamObject, int> ReferenceIDs { get; set; } = new();
Expand All @@ -48,20 +53,17 @@ public void PreInitialize(string jsonPath) {
_dreamResourceManager.Initialize();

if (!LoadJson(jsonPath)) {
IoCManager.Resolve<ITaskManager>().RunOnMainThread(() => { IoCManager.Resolve<IBaseServer>().Shutdown("Error while loading the compiled json. The opendream.json_path CVar may be empty, or points to a file that doesn't exist"); });
_taskManager.RunOnMainThread(() => { IoCManager.Resolve<IBaseServer>().Shutdown("Error while loading the compiled json. The opendream.json_path CVar may be empty, or points to a file that doesn't exist"); });
}
}

public void StartWorld() {
// It is now OK to call user code, like /New procs.
Initialized = true;
InitializedTick = IoCManager.Resolve<IGameTiming>().CurTick;
InitializedTick = _gameTiming.CurTick;

// Call global <init> with waitfor=FALSE
if (_compiledJson.GlobalInitProc is ProcDefinitionJson initProcDef) {
var globalInitProc = new DMProc(DreamPath.Root, "(global init)", null, null, null, initProcDef.Bytecode, initProcDef.MaxStackSize, initProcDef.Attributes, initProcDef.VerbName, initProcDef.VerbCategory, initProcDef.VerbDesc, initProcDef.Invisibility, _objectTree, _dreamResourceManager);
globalInitProc.Spawn(WorldInstance, new DreamProcArguments());
}
_objectTree.GlobalInitProc?.Spawn(WorldInstance, new());

// Call New() on all /area and /turf that exist, each with waitfor=FALSE separately. If <global init> created any /area, call New a SECOND TIME
// new() up /objs and /mobs from compiled-in maps [order: (1,1) then (2,1) then (1,2) then (2,2)]
Expand Down Expand Up @@ -116,6 +118,7 @@ public bool LoadJson(string? jsonPath) {
if (_compiledJson.Globals is GlobalListJson jsonGlobals) {
Globals.Clear();
Globals.EnsureCapacity(jsonGlobals.GlobalCount);
GlobalNames = jsonGlobals.Names;

for (int i = 0; i < jsonGlobals.GlobalCount; i++) {
object globalValue = jsonGlobals.Globals.GetValueOrDefault(i, null);
Expand Down
27 changes: 17 additions & 10 deletions OpenDreamRuntime/DreamThread.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public abstract class DreamProc {
public string Name { get; }

// This is currently publicly settable because the loading code doesn't know what our super is until after we are instantiated
public DreamProc SuperProc { set; get; }
public DreamProc? SuperProc { set; get; }

public ProcAttributes Attributes { get; }

Expand All @@ -31,7 +31,7 @@ public abstract class DreamProc {
public string? VerbDesc { get; }
public sbyte? Invisibility { get; }

protected DreamProc(DreamPath owningType, string name, DreamProc superProc, ProcAttributes attributes, List<String>? argumentNames, List<DMValueType>? argumentTypes, string? verbName, string? verbCategory, string? verbDesc, sbyte? invisibility) {
protected DreamProc(DreamPath owningType, string name, DreamProc? superProc, ProcAttributes attributes, List<String>? argumentNames, List<DMValueType>? argumentTypes, string? verbName, string? verbCategory, string? verbDesc, sbyte? invisibility) {
OwningType = owningType;
Name = name;
SuperProc = superProc;
Expand Down Expand Up @@ -124,6 +124,12 @@ public ProcStatus Resume() {
public virtual void ReturnedInto(DreamValue value) {}

public virtual void Cancel() {}

public override string ToString() {
var sb = new StringBuilder();
AppendStackFrame(sb);
return sb.ToString();
}
}

public sealed class DreamThread {
Expand All @@ -149,7 +155,7 @@ public DreamThread(string name) {
Name = name;
}

public static DreamValue Run(DreamProc proc, DreamObject src, DreamObject usr, DreamProcArguments? arguments) {
public static DreamValue Run(DreamProc proc, DreamObject src, DreamObject? usr, DreamProcArguments? arguments) {
var context = new DreamThread(proc.ToString());
var state = proc.CreateState(context, src, usr, arguments ?? new DreamProcArguments(null));
context.PushProcState(state);
Expand Down Expand Up @@ -250,17 +256,17 @@ public ProcStatus HandleDefer() {

// `WaitFor = true` frames
while (_current is not null && _current.WaitFor) {
var frame = _current;
newStackReversed.Push(_current);
PopProcState();
newStackReversed.Push(frame);
}

// `WaitFor = false` frame
if(_current == null) throw new InvalidOperationException();
var threadName = _current.ToString();
newStackReversed.Push(_current);
PopProcState();

DreamThread newThread = new DreamThread("defer " + Name);
DreamThread newThread = new DreamThread(threadName);
foreach (var frame in newStackReversed) {
frame.Thread = newThread;
newThread.PushProcState(frame);
Expand Down Expand Up @@ -309,10 +315,6 @@ public void HandleException(Exception exception)
{
_current?.Cancel();

if (_current is DMProcState state) {
state.ReturnPools();
}

var dreamMan = IoCManager.Resolve<IDreamManager>();
dreamMan.LastDMException = exception;

Expand All @@ -330,6 +332,11 @@ public void HandleException(Exception exception)
dreamMan.WriteWorldLog(builder.ToString(), LogLevel.Error);

IoCManager.Resolve<Procs.DebugAdapter.IDreamDebugManager>()?.HandleException(this, exception);

// Only return pools after giving the debugger a chance to inspect them.
if (_current is DMProcState state) {
state.ReturnPools();
}
}

public IEnumerable<ProcState> InspectStack() {
Expand Down
9 changes: 3 additions & 6 deletions OpenDreamRuntime/DreamValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,13 @@ public DreamValue(object value) {
}

public override string ToString() {
string strValue;
if (Value == null) {
strValue = "null";
return "null";
} else if (Type == DreamValueType.String) {
strValue = $"\"{Value}\"";
return $"\"{Value}\"";
} else {
strValue = Value.ToString() ?? "<ToString() = null>";
return Value.ToString() ?? "<ToString() = null>";
}

return "DreamValue(" + Type + ", " + strValue + ")";
}

[Obsolete("Deprecated. Use TryGetValueAsString() or MustGetValueAsString() instead.")]
Expand Down
3 changes: 1 addition & 2 deletions OpenDreamRuntime/EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ protected override void Dispose(bool disposing) {
public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) {
if (level == ModUpdateLevel.PostEngine) {
_commandSystem.RunRepeatingCommands();
if (!_debugManager.Stopped)
_dreamManager.Update();
_dreamManager.Update();
_debugManager.Update();
}
}
Expand Down
3 changes: 2 additions & 1 deletion OpenDreamRuntime/IDreamManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public interface IDreamManager {
/// </summary>
public Exception? LastDMException { get; set; }

public List<DreamValue> Globals { get; set; }
public List<DreamValue> Globals { get; }
public IReadOnlyList<string> GlobalNames { get; }
public DreamList WorldContentsList { get; }
public Dictionary<DreamObject, DreamList> AreaContents { get; set; }
public Dictionary<DreamObject, int> ReferenceIDs { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions OpenDreamRuntime/Objects/DreamIcon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,10 @@ public sealed class DreamIconOperationBlendImage : DreamIconOperationBlend {
private readonly ParsedDMIDescription _blendingDescription;

public DreamIconOperationBlendImage(BlendType type, int xOffset, int yOffset, DreamValue blending) : base(type, xOffset, yOffset) {
//TODO: Find a way to get rid of this!
var objectTree = IoCManager.Resolve<IDreamObjectTree>();
var resourceManager = IoCManager.Resolve<DreamResourceManager>();

(var blendingResource, _blendingDescription) = DreamMetaObjectIcon.GetIconResourceAndDescription(objectTree, resourceManager, blending);
_blending = resourceManager.LoadImage(blendingResource);
}
Expand Down
Loading

0 comments on commit 3ccabd5

Please sign in to comment.