diff --git a/DMCompiler/Bytecode/DreamProcOpcode.cs b/DMCompiler/Bytecode/DreamProcOpcode.cs index 53ec087bba..17c8a7a973 100644 --- a/DMCompiler/Bytecode/DreamProcOpcode.cs +++ b/DMCompiler/Bytecode/DreamProcOpcode.cs @@ -131,10 +131,10 @@ public enum DreamProcOpcode : byte { Sin = 0x79, Cos = 0x7A, Tan = 0x7B, - Arcsin = 0x7C, - Arccos = 0x7D, - Arctan = 0x7E, - Arctan2 = 0x7F, + ArcSin = 0x7C, + ArcCos = 0x7D, + ArcTan = 0x7E, + ArcTan2 = 0x7F, Sqrt = 0x80, Log = 0x81, LogE = 0x82, diff --git a/DMCompiler/DM/DMProc.cs b/DMCompiler/DM/DMProc.cs index 5c4a58f996..8ba88da617 100644 --- a/DMCompiler/DM/DMProc.cs +++ b/DMCompiler/DM/DMProc.cs @@ -957,21 +957,21 @@ public void Tan() { WriteOpcode(DreamProcOpcode.Tan); } - public void Arcsin() { - WriteOpcode(DreamProcOpcode.Arcsin); + public void ArcSin() { + WriteOpcode(DreamProcOpcode.ArcSin); } - public void Arccos() { - WriteOpcode(DreamProcOpcode.Arccos); + public void ArcCos() { + WriteOpcode(DreamProcOpcode.ArcCos); } - public void Arctan() { - WriteOpcode(DreamProcOpcode.Arctan); + public void ArcTan() { + WriteOpcode(DreamProcOpcode.ArcTan); } - public void Arctan2() { + public void ArcTan2() { ShrinkStack(1); - WriteOpcode(DreamProcOpcode.Arctan2); + WriteOpcode(DreamProcOpcode.ArcTan2); } public void Sqrt() { diff --git a/DMCompiler/DM/Expressions/Builtins.cs b/DMCompiler/DM/Expressions/Builtins.cs index 280dd67e09..ab46a0fc31 100644 --- a/DMCompiler/DM/Expressions/Builtins.cs +++ b/DMCompiler/DM/Expressions/Builtins.cs @@ -3,6 +3,7 @@ using OpenDreamShared.Dream; using OpenDreamShared.Json; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using DMCompiler.Bytecode; namespace DMCompiler.DM.Expressions { @@ -644,20 +645,26 @@ public override void EmitPushValue(DMObject dmObject, DMProc proc) { } } - class Sin : DMExpression { - DMExpression _expr; + internal class Sin : DMExpression { + private readonly DMExpression _expr; public Sin(Location location, DMExpression expr) : base(location) { _expr = expr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Sin(); + if (constant is not Number {Value: var x}) { + x = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, sin(0) will always be 0"); + } + + constant = new Number(Location, SharedOperations.Sin(x)); return true; } @@ -667,20 +674,26 @@ public override void EmitPushValue(DMObject dmObject, DMProc proc) { } } - class Cos : DMExpression { - DMExpression _expr; + internal class Cos : DMExpression { + private readonly DMExpression _expr; public Cos(Location location, DMExpression expr) : base(location) { _expr = expr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Cos(); + if (constant is not Number {Value: var x}) { + x = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, cos(0) will always be 1"); + } + + constant = new Number(Location, SharedOperations.Cos(x)); return true; } @@ -690,20 +703,26 @@ public override void EmitPushValue(DMObject dmObject, DMProc proc) { } } - class Tan : DMExpression { - DMExpression _expr; + internal class Tan : DMExpression { + private readonly DMExpression _expr; public Tan(Location location, DMExpression expr) : base(location) { _expr = expr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Tan(); + if (constant is not Number {Value: var x}) { + x = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, tan(0) will always be 0"); + } + + constant = new Number(Location, SharedOperations.Tan(x)); return true; } @@ -713,115 +732,164 @@ public override void EmitPushValue(DMObject dmObject, DMProc proc) { } } - class Arcsin : DMExpression { - DMExpression _expr; + internal class ArcSin : DMExpression { + private readonly DMExpression _expr; - public Arcsin(Location location, DMExpression expr) : base(location) { + public ArcSin(Location location, DMExpression expr) : base(location) { _expr = expr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Arcsin(); + if (constant is not Number {Value: var x}) { + x = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, arcsin(0) will always be 0"); + } + + if (x is < -1 or > 1) { + DMCompiler.Emit(WarningCode.BadArgument, _expr.Location, $"Invalid value {x}, must be >= -1 and <= 1"); + x = 0; + } + + constant = new Number(Location, SharedOperations.ArcSin(x)); return true; } public override void EmitPushValue(DMObject dmObject, DMProc proc) { _expr.EmitPushValue(dmObject, proc); - proc.Arcsin(); + proc.ArcSin(); } } - class Arccos : DMExpression { - DMExpression _expr; + internal class ArcCos : DMExpression { + private readonly DMExpression _expr; - public Arccos(Location location, DMExpression expr) : base(location) { + public ArcCos(Location location, DMExpression expr) : base(location) { _expr = expr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Arccos(); + if (constant is not Number {Value: var x}) { + x = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, arccos(0) will always be 1"); + } + + if (x is < -1 or > 1) { + DMCompiler.Emit(WarningCode.BadArgument, _expr.Location, $"Invalid value {x}, must be >= -1 and <= 1"); + x = 0; + } + + constant = new Number(Location, SharedOperations.ArcCos(x)); return true; } public override void EmitPushValue(DMObject dmObject, DMProc proc) { _expr.EmitPushValue(dmObject, proc); - proc.Arccos(); + proc.ArcCos(); } } - class Arctan : DMExpression { - DMExpression _expr; + internal class ArcTan : DMExpression { + private readonly DMExpression _expr; - public Arctan(Location location, DMExpression expr) : base(location) { + public ArcTan(Location location, DMExpression expr) : base(location) { _expr = expr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Arctan(); + if (constant is not Number {Value: var a}) { + a = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, arctan(0) will always be 0"); + } + + constant = new Number(Location, SharedOperations.ArcTan(a)); return true; } public override void EmitPushValue(DMObject dmObject, DMProc proc) { _expr.EmitPushValue(dmObject, proc); - proc.Arctan(); + proc.ArcTan(); } } - class Arctan2 : DMExpression { - DMExpression _xexpr; - DMExpression _yexpr; + internal class ArcTan2 : DMExpression { + private readonly DMExpression _xExpr; + private readonly DMExpression _yExpr; - public Arctan2(Location location, DMExpression xexpr, DMExpression yexpr) : base(location) { - _xexpr = xexpr; - _yexpr = yexpr; + public ArcTan2(Location location, DMExpression xExpr, DMExpression yExpr) : base(location) { + _xExpr = xExpr; + _yExpr = yExpr; } - - public override bool TryAsConstant(out Constant constant) { - if (!_xexpr.TryAsConstant(out Constant xconst) || !_yexpr.TryAsConstant(out Constant yconst)) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { + if (!_xExpr.TryAsConstant(out var xConst) || !_yExpr.TryAsConstant(out var yConst)) { constant = null; return false; } - constant = xconst.Arctan2(yconst); + if (xConst is not Number {Value: var x}) { + x = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _xExpr.Location, "Invalid x value treated as 0"); + } + + if (yConst is not Number {Value: var y}) { + y = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _xExpr.Location, "Invalid y value treated as 0"); + } + + constant = new Number(Location, SharedOperations.ArcTan(x, y)); return true; } public override void EmitPushValue(DMObject dmObject, DMProc proc) { - _xexpr.EmitPushValue(dmObject, proc); - _yexpr.EmitPushValue(dmObject, proc); - proc.Arctan2(); + _xExpr.EmitPushValue(dmObject, proc); + _yExpr.EmitPushValue(dmObject, proc); + proc.ArcTan2(); } } - class Sqrt : DMExpression { - DMExpression _expr; + internal class Sqrt : DMExpression { + private readonly DMExpression _expr; public Sqrt(Location location, DMExpression expr) : base(location) { _expr = expr; } - public override bool TryAsConstant(out Constant constant) { + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Sqrt(); + if (constant is not Number {Value: var a}) { + a = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, sqrt(0) will always be 0"); + } + + if (a < 0) { + DMCompiler.Emit(WarningCode.BadArgument, _expr.Location, + $"Cannot get the square root of a negative number ({a})"); + } + + constant = new Number(Location, SharedOperations.Sqrt(a)); return true; } @@ -831,32 +899,44 @@ public override void EmitPushValue(DMObject dmObject, DMProc proc) { } } - class Log : DMExpression { - DMExpression _expr; - DMExpression? _baseExpr; + internal class Log : DMExpression { + private readonly DMExpression _expr; + private readonly DMExpression? _baseExpr; public Log(Location location, DMExpression expr, DMExpression? baseExpr) : base(location) { _expr = expr; _baseExpr = baseExpr; } - - public override bool TryAsConstant(out Constant constant) { + + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } + if (constant is not Number {Value: var value} || value <= 0) { + value = 1; + DMCompiler.Emit(WarningCode.BadArgument, _expr.Location, + "Invalid value, must be a number greater than 0"); + } + if (_baseExpr == null) { - constant = constant.Log(null); + constant = new Number(Location, SharedOperations.Log(value)); return true; } - if (!_baseExpr.TryAsConstant(out Constant baseConstant)) { + if (!_baseExpr.TryAsConstant(out var baseConstant)) { constant = null; return false; } - constant = constant.Log(baseConstant); + if (baseConstant is not Number {Value: var baseValue} || baseValue <= 0) { + baseValue = 10; + DMCompiler.Emit(WarningCode.BadArgument, _baseExpr.Location, + "Invalid base, must be a number greater than 0"); + } + + constant = new Number(Location, SharedOperations.Log(value, baseValue)); return true; } @@ -871,20 +951,26 @@ public override void EmitPushValue(DMObject dmObject, DMProc proc) { } } - class Abs : DMExpression { - DMExpression _expr; + internal class Abs : DMExpression { + private readonly DMExpression _expr; public Abs(Location location, DMExpression expr) : base(location) { _expr = expr; } - public override bool TryAsConstant(out Constant constant) { + public override bool TryAsConstant([NotNullWhen(true)] out Constant? constant) { if (!_expr.TryAsConstant(out constant)) { constant = null; return false; } - constant = constant.Abs(); + if (constant is not Number {Value: var a}) { + a = 0; + DMCompiler.Emit(WarningCode.FallbackBuiltinArgument, _expr.Location, + "Invalid value treated as 0, abs(0) will always be 0"); + } + + constant = new Number(Location, SharedOperations.Abs(a)); return true; } diff --git a/DMCompiler/DM/Expressions/Constant.cs b/DMCompiler/DM/Expressions/Constant.cs index f7d00a87ae..c8391830aa 100644 --- a/DMCompiler/DM/Expressions/Constant.cs +++ b/DMCompiler/DM/Expressions/Constant.cs @@ -97,49 +97,6 @@ public virtual Constant LessThan(Constant rhs) { public virtual Constant LessThanOrEqual(Constant rhs) { throw new CompileErrorException(Location, $"const operation \"{this} <= {rhs}\" is invalid"); } - - public virtual Constant Sin() { - throw new CompileErrorException(Location, $"const operation \"sin({this})\" is invalid"); - } - - public virtual Constant Cos() { - throw new CompileErrorException(Location, $"const operation \"cos({this})\" is invalid"); - } - - public virtual Constant Tan() { - throw new CompileErrorException(Location, $"const operation \"tan({this})\" is invalid"); - } - - public virtual Constant Arcsin() { - throw new CompileErrorException(Location, $"const operation \"arcsin({this})\" is invalid"); - } - - public virtual Constant Arccos() { - throw new CompileErrorException(Location, $"const operation \"arccos({this})\" is invalid"); - } - - public virtual Constant Arctan() { - throw new CompileErrorException(Location, $"const operation \"arctan({this})\" is invalid"); - } - - public virtual Constant Arctan2(Constant yConst) { - throw new CompileErrorException(Location, $"const operation \"arctan({this}, {yConst})\" is invalid"); - } - - public virtual Constant Sqrt() { - throw new CompileErrorException(Location, $"const operation \"sqrt({this})\" is invalid"); - } - - public virtual Constant Log(Constant? baseVal) { - if (baseVal == null) { - throw new CompileErrorException(Location, $"const operation \"log({this})\" is invalid"); - } - throw new CompileErrorException(Location, $"const operation \"log({baseVal}, {this})\" is invalid"); - } - - public virtual Constant Abs() { - throw new CompileErrorException(Location, $"const operation \"abs({this})\" is invalid"); - } #endregion } @@ -359,70 +316,6 @@ public override Constant LessThanOrEqual(Constant rhs) { } return new Number(Location, (Value <= rhsNum.Value) ? 1 : 0); } - - public override Constant Sin() { - return new Number(Location, MathF.Sin(Value / 180 * MathF.PI)); - } - - public override Constant Cos() { - return new Number(Location, MathF.Cos(Value / 180 * MathF.PI)); - } - - public override Constant Tan() { - return new Number(Location, MathF.Tan(Value / 180 * MathF.PI)); - } - - public override Constant Arcsin() { - if (Value < -1 || Value > 1) { - throw new CompileErrorException(Location, $"const operation \"arcsin({this})\" is invalid (out of range)"); - } - return new Number(Location, MathF.Asin(Value) / MathF.PI * 180); - } - - public override Constant Arccos() { - if (Value < -1 || Value > 1) { - throw new CompileErrorException(Location, $"const operation \"arccos({this})\" is invalid (out of range)"); - } - return new Number(Location, MathF.Acos(Value) / MathF.PI * 180); - } - - public override Constant Arctan() { - return new Number(Location, MathF.Atan(Value) / MathF.PI * 180); - } - - public override Constant Arctan2(Constant yConst) { - if (yConst is not Number yNum) { - throw new CompileErrorException(Location, $"const operation \"arctan2({this}, {yConst})\" is invalid"); - } - return new Number(Location, MathF.Atan2(yNum.Value, Value) / MathF.PI * 180); - } - - public override Constant Sqrt() { - if (Value < 0) { - throw new CompileErrorException(Location, $"const operation \"sqrt({this})\" is invalid (negative)"); - } - return new Number(Location, MathF.Sqrt(Value)); - } - - public override Constant Log(Constant? baseVal) { - if (Value <= 0) { - throw new CompileErrorException(Location, $"const operation \"log({this})\" is invalid (non-positive)"); - } - if (baseVal == null) { - return new Number(Location, MathF.Log(Value)); - } - if (baseVal is not Number baseNum) { - throw new CompileErrorException(Location, $"const operation \"log({this}, {baseVal})\" is invalid"); - } - if (baseNum.Value <= 0) { - throw new CompileErrorException(Location, $"const operation \"log({this}, {baseVal})\" is invalid (non-positive base)"); - } - return new Number(Location, MathF.Log(Value, baseNum.Value)); - } - - public override Constant Abs() { - return new Number(Location, MathF.Abs(Value)); - } } // "abc" diff --git a/DMCompiler/DM/Visitors/DMVisitorExpression.cs b/DMCompiler/DM/Visitors/DMVisitorExpression.cs index 9d711dc4c3..8acb35a0dc 100644 --- a/DMCompiler/DM/Visitors/DMVisitorExpression.cs +++ b/DMCompiler/DM/Visitors/DMVisitorExpression.cs @@ -996,23 +996,23 @@ public void VisitTan(DMASTTan tan) { public void VisitArcsin(DMASTArcsin arcsin) { var expr = DMExpression.Create(_dmObject, _proc, arcsin.Expression, _inferredPath); - Result = new Expressions.Arcsin(arcsin.Location, expr); + Result = new Expressions.ArcSin(arcsin.Location, expr); } public void VisitArccos(DMASTArccos arccos) { var expr = DMExpression.Create(_dmObject, _proc, arccos.Expression, _inferredPath); - Result = new Expressions.Arccos(arccos.Location, expr); + Result = new Expressions.ArcCos(arccos.Location, expr); } public void VisitArctan(DMASTArctan arctan) { var expr = DMExpression.Create(_dmObject, _proc, arctan.Expression, _inferredPath); - Result = new Expressions.Arctan(arctan.Location, expr); + Result = new Expressions.ArcTan(arctan.Location, expr); } public void VisitArctan2(DMASTArctan2 arctan2) { var xexpr = DMExpression.Create(_dmObject, _proc, arctan2.XExpression, _inferredPath); var yexpr = DMExpression.Create(_dmObject, _proc, arctan2.YExpression, _inferredPath); - Result = new Expressions.Arctan2(arctan2.Location, xexpr, yexpr); + Result = new Expressions.ArcTan2(arctan2.Location, xexpr, yexpr); } public void VisitSqrt(DMASTSqrt sqrt) { diff --git a/DMCompiler/DMStandard/DefaultPragmaConfig.dm b/DMCompiler/DMStandard/DefaultPragmaConfig.dm index 7526cc2396..2c71d6c4e4 100644 --- a/DMCompiler/DMStandard/DefaultPragmaConfig.dm +++ b/DMCompiler/DMStandard/DefaultPragmaConfig.dm @@ -19,6 +19,7 @@ #pragma PointlessParentCall warning #pragma PointlessBuiltinCall warning #pragma SuspiciousMatrixCall warning +#pragma FallbackBuiltinArgument warning #pragma MalformedRange warning #pragma InvalidRange error #pragma InvalidSetStatement error diff --git a/DMCompiler/SharedOperations.cs b/DMCompiler/SharedOperations.cs new file mode 100644 index 0000000000..a29482757c --- /dev/null +++ b/DMCompiler/SharedOperations.cs @@ -0,0 +1,65 @@ +using System; +using System.Runtime.CompilerServices; + +namespace DMCompiler; + +/// +/// A class containing operations used by both the compiler and the server. +/// Helps make sure things like sin() and cos() give the same result on both. +/// +public static class SharedOperations { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sin(float x) { + return MathF.Sin(x / 180 * MathF.PI); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Cos(float x) { + return MathF.Cos(x / 180 * MathF.PI); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Tan(float x) { + return MathF.Tan(x / 180 * MathF.PI); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ArcSin(float x) { + return MathF.Asin(x) / MathF.PI * 180; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ArcCos(float x) { + return MathF.Acos(x) / MathF.PI * 180; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ArcTan(float a) { + return MathF.Atan(a) / MathF.PI * 180; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float ArcTan(float x, float y) { + return MathF.Atan2(y, x) / MathF.PI * 180; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sqrt(float a) { + return MathF.Sqrt(a); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Log(float y) { + return MathF.Log(y); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Log(float y, float baseValue) { + return MathF.Log(y, baseValue); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Abs(float a) { + return MathF.Abs(a); + } +} diff --git a/OpenDream.sln.DotSettings b/OpenDream.sln.DotSettings index 06cd921c58..b9158a88ff 100644 --- a/OpenDream.sln.DotSettings +++ b/OpenDream.sln.DotSettings @@ -9,6 +9,9 @@ RHS UI True + True + True + True True True True diff --git a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs index 4bd131d69a..da20d51b32 100644 --- a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs +++ b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using DMCompiler; using DMCompiler.Bytecode; using OpenDreamRuntime.Objects; using OpenDreamRuntime.Objects.Types; @@ -1619,82 +1620,92 @@ public static ProcStatus EndTry(DMProcState state) { } public static ProcStatus Sin(DMProcState state) { - DreamValue value = state.Pop(); + float x = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Sin(x); - state.Push(new DreamValue(MathF.Sin(value.UnsafeGetValueAsFloat() / 180 * MathF.PI))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } public static ProcStatus Cos(DMProcState state) { - DreamValue value = state.Pop(); + float x = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Cos(x); - state.Push(new DreamValue(MathF.Cos(value.UnsafeGetValueAsFloat() / 180 * MathF.PI))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } public static ProcStatus Tan(DMProcState state) { - DreamValue value = state.Pop(); + float x = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Tan(x); - state.Push(new DreamValue(MathF.Tan(value.UnsafeGetValueAsFloat() / 180 * MathF.PI))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } - public static ProcStatus Arcsin(DMProcState state) { - DreamValue value = state.Pop(); + public static ProcStatus ArcSin(DMProcState state) { + float x = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.ArcSin(x); - state.Push(new DreamValue(MathF.Asin(value.UnsafeGetValueAsFloat()) / MathF.PI * 180)); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } - public static ProcStatus Arccos(DMProcState state) { - DreamValue value = state.Pop(); + public static ProcStatus ArcCos(DMProcState state) { + float x = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.ArcCos(x); - state.Push(new DreamValue(MathF.Acos(value.UnsafeGetValueAsFloat()) / MathF.PI * 180)); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } - public static ProcStatus Arctan(DMProcState state) { - DreamValue value = state.Pop(); + public static ProcStatus ArcTan(DMProcState state) { + float a = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.ArcTan(a); - state.Push(new DreamValue(MathF.Atan(value.UnsafeGetValueAsFloat()) / MathF.PI * 180)); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } - public static ProcStatus Arctan2(DMProcState state) { - DreamValue y = state.Pop(); - DreamValue x = state.Pop(); - var yValue = y.UnsafeGetValueAsFloat(); + public static ProcStatus ArcTan2(DMProcState state) { + float y = state.Pop().UnsafeGetValueAsFloat(); + float x = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.ArcTan(x, y); - state.Push(new DreamValue(MathF.Atan2(yValue, x.UnsafeGetValueAsFloat()) / MathF.PI * 180)); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } public static ProcStatus Sqrt(DMProcState state) { - DreamValue value = state.Pop(); + float a = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Sqrt(a); - state.Push(new DreamValue(MathF.Sqrt(value.UnsafeGetValueAsFloat()))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } public static ProcStatus Log(DMProcState state) { - DreamValue baseValue = state.Pop(); - DreamValue value = state.Pop(); + float baseValue = state.Pop().UnsafeGetValueAsFloat(); + float value = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Log(value, baseValue); - state.Push(new DreamValue(MathF.Log(value.UnsafeGetValueAsFloat(), baseValue.UnsafeGetValueAsFloat()))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } public static ProcStatus LogE(DMProcState state) { - DreamValue value = state.Pop(); + float y = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Log(y); - state.Push(new DreamValue(MathF.Log(value.UnsafeGetValueAsFloat()))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } public static ProcStatus Abs(DMProcState state) { - DreamValue value = state.Pop(); + float a = state.Pop().UnsafeGetValueAsFloat(); + float result = SharedOperations.Abs(a); - state.Push(new DreamValue(MathF.Abs(value.UnsafeGetValueAsFloat()))); + state.Push(new DreamValue(result)); return ProcStatus.Continue; } diff --git a/OpenDreamRuntime/Procs/DMProc.cs b/OpenDreamRuntime/Procs/DMProc.cs index 37be0c73c8..ca8d51a094 100644 --- a/OpenDreamRuntime/Procs/DMProc.cs +++ b/OpenDreamRuntime/Procs/DMProc.cs @@ -288,10 +288,10 @@ public sealed class DMProcState : ProcState { {DreamProcOpcode.Sin, DMOpcodeHandlers.Sin}, {DreamProcOpcode.Cos, DMOpcodeHandlers.Cos}, {DreamProcOpcode.Tan, DMOpcodeHandlers.Tan}, - {DreamProcOpcode.Arcsin, DMOpcodeHandlers.Arcsin}, - {DreamProcOpcode.Arccos, DMOpcodeHandlers.Arccos}, - {DreamProcOpcode.Arctan, DMOpcodeHandlers.Arctan}, - {DreamProcOpcode.Arctan2, DMOpcodeHandlers.Arctan2}, + {DreamProcOpcode.ArcSin, DMOpcodeHandlers.ArcSin}, + {DreamProcOpcode.ArcCos, DMOpcodeHandlers.ArcCos}, + {DreamProcOpcode.ArcTan, DMOpcodeHandlers.ArcTan}, + {DreamProcOpcode.ArcTan2, DMOpcodeHandlers.ArcTan2}, {DreamProcOpcode.Sqrt, DMOpcodeHandlers.Sqrt}, {DreamProcOpcode.Log, DMOpcodeHandlers.Log}, {DreamProcOpcode.LogE, DMOpcodeHandlers.LogE}, diff --git a/OpenDreamShared/Compiler/CompilerError.cs b/OpenDreamShared/Compiler/CompilerError.cs index a6bb60e0e8..0c468ffd54 100644 --- a/OpenDreamShared/Compiler/CompilerError.cs +++ b/OpenDreamShared/Compiler/CompilerError.cs @@ -44,6 +44,7 @@ public enum WarningCode { PointlessParentCall = 2205, PointlessBuiltinCall = 2206, // For pointless calls to issaved() or initial() SuspiciousMatrixCall = 2207, // Calling matrix() with seemingly the wrong arguments + FallbackBuiltinArgument = 2208, // A builtin (sin(), cos(), etc) with an invalid/fallback argument MalformedRange = 2300, InvalidRange = 2301, InvalidSetStatement = 2302,