Skip to content

Commit

Permalink
Improve proc call return value checking
Browse files Browse the repository at this point in the history
  • Loading branch information
out-of-phaze committed Oct 31, 2024
1 parent 8f12971 commit 7939a42
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 7 deletions.
9 changes: 7 additions & 2 deletions DMCompiler/DM/Builders/DMExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ private static DMExpression BuildIdentifier(DMASTIdentifier identifier, DMObject
if (CurrentScopeMode == ScopeMode.Normal) {
var localVar = proc?.GetLocalVariable(name);
if (localVar != null)
return new Local(identifier.Location, localVar, localVar.ExplicitValueType);
return new Local(identifier.Location, localVar, proc!, localVar.ExplicitValueType);

var field = dmObject?.GetVariable(name);
if (field != null) {
Expand Down Expand Up @@ -526,7 +526,7 @@ private static DMExpression BuildCallableProcIdentifier(DMASTCallableProcIdentif
if (CurrentScopeMode is ScopeMode.Static or ScopeMode.FirstPassStatic)
return new GlobalProc(procIdentifier.Location, procIdentifier.Identifier);
if (dmObject.HasProc(procIdentifier.Identifier))
return new Proc(procIdentifier.Location, procIdentifier.Identifier);
return new Proc(procIdentifier.Location, procIdentifier.Identifier, dmObject);
if (DMObjectTree.TryGetGlobalProc(procIdentifier.Identifier, out _))
return new GlobalProc(procIdentifier.Location, procIdentifier.Identifier);

Expand Down Expand Up @@ -781,6 +781,11 @@ private static DMExpression BuildDereference(DMASTDereference deref, DMObject dm

var returnTypes = fromObject.GetProcReturnTypes(field) ?? DMValueType.Anything;
nextPath = returnTypes.HasPath ? returnTypes.TypePath : returnTypes.AsPath();
if (!returnTypes.HasPath & nextPath.HasValue) {
var thePath = nextPath!.Value;
thePath.Type = DreamPath.PathType.UpwardSearch;
nextPath = thePath;
}
}

operation = new Dereference.CallOperation {
Expand Down
2 changes: 1 addition & 1 deletion DMCompiler/DM/Expressions/LValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public override DMReference EmitReference(DMObject dmObject, DMProc proc, string
}

// Identifier of local variable
internal sealed class Local(Location location, DMProc.LocalVariable localVar, DMComplexValueType? valType) : LValue(location, localVar.Type) {
internal sealed class Local(Location location, DMProc.LocalVariable localVar, DMProc proc, DMComplexValueType? valType) : LValue(location, localVar.Type) {
public DMProc.LocalVariable LocalVar { get; } = localVar;
public override DMComplexValueType ValType {
get {
Expand Down
26 changes: 22 additions & 4 deletions DMCompiler/DM/Expressions/Procs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
namespace DMCompiler.DM.Expressions;

// x() (only the identifier)
internal sealed class Proc(Location location, string identifier) : DMExpression(location) {
internal sealed class Proc(Location location, string identifier, DMObject theObject) : DMExpression(location) {
public DMObject dmObject => theObject;
public string Identifier => identifier;
public override DMComplexValueType ValType => GetReturnType(theObject);
public override void EmitPushValue(DMObject dmObject, DMProc proc) {
DMCompiler.Emit(WarningCode.BadExpression, Location, "attempt to use proc as value");
proc.Error();
Expand Down Expand Up @@ -39,6 +42,7 @@ public DMComplexValueType GetReturnType(DMObject dmObject) {
/// </remarks>
internal sealed class GlobalProc(Location location, string name) : DMExpression(location) {
public override DMComplexValueType ValType => GetProc().ReturnTypes;
public string Identifier => name;

public override string ToString() {
return $"{name}()";
Expand Down Expand Up @@ -68,7 +72,7 @@ public DMProc GetProc() {
/// This is an LValue _and_ a proc!
/// </summary>
internal sealed class ProcSelf(Location location, DreamPath? path, DMProc proc) : LValue(location, path) {
public override DMComplexValueType ValType => proc.ReturnTypes;
public override DMComplexValueType ValType => proc.RawReturnTypes;

public override DMReference EmitReference(DMObject dmObject, DMProc proc, string endLabel, ShortCircuitMode shortCircuitMode = ShortCircuitMode.KeepNull) {
return DMReference.Self;
Expand All @@ -77,7 +81,7 @@ public override DMReference EmitReference(DMObject dmObject, DMProc proc, string

// ..
internal sealed class ProcSuper(Location location, DMObject _dmObject, DMProc _proc) : DMExpression(location) {
public override DMComplexValueType ValType => _dmObject.GetProcReturnTypes(_proc.Name) ?? DMValueType.Anything;
public override DMComplexValueType ValType => _dmObject.GetProcReturnTypes(_proc.Name) ?? DMValueType.Anything; // TODO: could this just be _proc.ReturnTypes?

public override void EmitPushValue(DMObject dmObject, DMProc proc) {
DMCompiler.Emit(WarningCode.InvalidReference, Location, $"Attempt to use proc \"..\" as value");
Expand All @@ -100,7 +104,21 @@ public override DMReference EmitReference(DMObject dmObject, DMProc proc, string
internal sealed class ProcCall(Location location, DMExpression target, ArgumentList arguments, DMComplexValueType valType)
: DMExpression(location) {
public override bool PathIsFuzzy => Path == null;
public override DMComplexValueType ValType => valType.IsAnything ? target.ValType : valType;
public override DMComplexValueType ValType {
get {
if (!valType.IsAnything)
return valType;
switch (target) {
case Proc procTarget:
return procTarget.dmObject.GetProcReturnTypes(procTarget.Identifier) ?? DMValueType.Anything;
case GlobalProc procTarget:
if(DMObjectTree.TryGetGlobalProc(procTarget.Identifier, out var globalProc))
return globalProc.RawReturnTypes ?? DMValueType.Anything;
return DMValueType.Anything;
}
return target.ValType;
}
}

public (DMObject? ProcOwner, DMProc? Proc) GetTargetProc(DMObject dmObject) {
return target switch {
Expand Down

0 comments on commit 7939a42

Please sign in to comment.