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))