From 39ab9aabfed5c17f5e19a43fd29a16b6fb77f2e0 Mon Sep 17 00:00:00 2001
From: atrexus <110138304+atrexus@users.noreply.github.com>
Date: Thu, 8 Feb 2024 18:48:36 -0500
Subject: [PATCH] added condition testing ;P
---
src/Unluau.CLI/Program.cs | 2 +-
src/Unluau/Chunk/Luau/Function.cs | 23 ++++++++++++++---
src/Unluau/IL/Values/Conditions/Test.cs | 33 +++++++++++++++++++++++++
src/Unluau/IL/Visitor.cs | 1 +
src/Unluau/IL/Visitors/OutputVisitor.cs | 15 +++--------
src/Unluau/IL/Visitors/ValueVisitor.cs | 7 ++++++
6 files changed, 65 insertions(+), 16 deletions(-)
create mode 100644 src/Unluau/IL/Values/Conditions/Test.cs
diff --git a/src/Unluau.CLI/Program.cs b/src/Unluau.CLI/Program.cs
index c4067d1..f327b52 100644
--- a/src/Unluau.CLI/Program.cs
+++ b/src/Unluau.CLI/Program.cs
@@ -7,7 +7,7 @@ internal class Program
{
static void Main(string[] args)
{
- using var stream = File.OpenRead("./test/Conditions.luau");
+ using var stream = File.OpenRead("./test/RegisterTest.luau");
var chunk = LuauChunk.Create(stream);
Console.WriteLine(chunk.ToString());
diff --git a/src/Unluau/Chunk/Luau/Function.cs b/src/Unluau/Chunk/Luau/Function.cs
index 18e4ee2..ab202a3 100644
--- a/src/Unluau/Chunk/Luau/Function.cs
+++ b/src/Unluau/Chunk/Luau/Function.cs
@@ -486,21 +486,36 @@ OpCode.LOADKX or
case OpCode.JUMPIFNOTEQ:
case OpCode.JUMPIFNOTLE:
case OpCode.JUMPIFNOTLT:
+ case OpCode.JUMPIFNOT:
{
+ // Save the original pc value so that we can conserve the jump offset.
+ var ogPc = pc;
+
var left = new Reference(context, stack.Get(instruction.A)!);
- var right = new Reference(context, stack.Get(Instructions[++pc].Value)!);
+
+ var right = instruction.Code switch
+ {
+ // These operations just test a value and have one operand.
+ OpCode.JUMPIF or OpCode.JUMPIFNOT => null,
+
+ _ => new Reference(context, stack.Get(Instructions[++pc].Value)!)
+ };
// Build the condition based on the current operation code.
- var condition = instruction.Code switch
+ BasicCondition condition = instruction.Code switch
{
- OpCode.JUMPIFNOTEQ => new Equals(context, left, right),
+ // Performs a jump if values are not equal to each other.
+ OpCode.JUMPIFNOTEQ => new Equals(context, left, right!),
+
+ // Jumps if the register is nil or false.
+ OpCode.JUMPIFNOT => new Test(context, left),
// This should never happen, but just in case.
_ => throw new NotImplementedException()
};
// Now we lift the body of the block.
- var body = LiftBasicBlock(stack, ++pc, pc + instruction.D - 1);
+ var body = LiftBasicBlock(stack, ++pc, pc + instruction.D - (pc - ogPc - 1));
block.Statements.Add(new IfBlock(body.Context, condition, body.Statements));
break;
diff --git a/src/Unluau/IL/Values/Conditions/Test.cs b/src/Unluau/IL/Values/Conditions/Test.cs
new file mode 100644
index 0000000..438e078
--- /dev/null
+++ b/src/Unluau/IL/Values/Conditions/Test.cs
@@ -0,0 +1,33 @@
+namespace Unluau.IL.Values.Conditions
+{
+ ///
+ /// Condition that checks if the basic value is valid (not null or true boolean).
+ ///
+ ///
+ ///
+ public class Test(Context context, BasicValue basicValue) : BasicCondition(context)
+ {
+ ///
+ /// The value to check.
+ ///
+ public BasicValue Value { get; set; } = basicValue;
+
+ ///
+ /// Returns a string representation of the current value.
+ ///
+ /// String representation.
+ public override string? ToString() => $"Test({Value})";
+
+ ///
+ /// Implements the visitor.
+ ///
+ /// The visitor.
+ public override void Visit(Visitor visitor)
+ {
+ if (visitor.Visit(this))
+ {
+ Value.Visit(visitor);
+ }
+ }
+ }
+}
diff --git a/src/Unluau/IL/Visitor.cs b/src/Unluau/IL/Visitor.cs
index 3df7a40..5ec70e7 100644
--- a/src/Unluau/IL/Visitor.cs
+++ b/src/Unluau/IL/Visitor.cs
@@ -41,5 +41,6 @@ public class Visitor
// Conditions
public virtual bool Visit(Equals node) => Visit(node as BasicCondition);
+ public virtual bool Visit(Test node) => Visit(node as BasicCondition);
}
}
diff --git a/src/Unluau/IL/Visitors/OutputVisitor.cs b/src/Unluau/IL/Visitors/OutputVisitor.cs
index 3b8ce2c..d02d4db 100644
--- a/src/Unluau/IL/Visitors/OutputVisitor.cs
+++ b/src/Unluau/IL/Visitors/OutputVisitor.cs
@@ -93,16 +93,9 @@ public override bool Visit(BasicBlock node)
return false;
}
- public override bool Visit(Equals node)
- {
- Writer.Write($"{node.Left} == {node.Right}");
- return false;
- }
-
public override bool Visit(IfBlock node)
{
- Writer.Write(Format(node.Context, "IfBlock "));
- node.Condition.Visit(this);
+ Writer.Write(Format(node.Context, $"IfBlock {node.Condition}"));
Writer.WriteLine(" {");
Indent++;
@@ -113,7 +106,7 @@ public override bool Visit(IfBlock node)
return false;
}
- private string Format(Context context, string op, string? a, string? b, string? c)
+ private static string Format(Context context, string op, string? a, string? b, string? c)
{
StringBuilder stringBuilder = new();
@@ -122,10 +115,10 @@ private string Format(Context context, string op, string? a, string? b, string?
return stringBuilder.ToString();
}
- private string Format(Context context, string op, string? a, string? b)
+ private static string Format(Context context, string op, string? a, string? b)
=> Format(context, op, a, b, " ");
- private string Format(Context context, string op)
+ private static string Format(Context context, string op)
{
StringBuilder stringBuilder = new();
diff --git a/src/Unluau/IL/Visitors/ValueVisitor.cs b/src/Unluau/IL/Visitors/ValueVisitor.cs
index b0a07ae..26856ca 100644
--- a/src/Unluau/IL/Visitors/ValueVisitor.cs
+++ b/src/Unluau/IL/Visitors/ValueVisitor.cs
@@ -62,6 +62,13 @@ public override bool Visit(Equals node)
return true;
}
+ public override bool Visit(Test node)
+ {
+ node.Value = ResolveValue(node.Value);
+
+ return true;
+ }
+
public override bool Visit(GetIndexSelf node)
{
if (!TryDelete(node, node.Slot))