diff --git a/src/Unluau.CLI/Program.cs b/src/Unluau.CLI/Program.cs index fbd5140..d91bbaf 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/input.txt"); + using var stream = File.OpenRead("./test/Unary.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 b51fa9f..0825571 100644 --- a/src/Unluau/Chunk/Luau/Function.cs +++ b/src/Unluau/Chunk/Luau/Function.cs @@ -526,6 +526,35 @@ OpCode.LOADKX or block.Statements.Add(new Move(context, ra, rb)); break; } + case OpCode.CONCAT: + { + var values = new Reference[instruction.C - instruction.B + 1]; + + for ( var i = instruction.B; i < instruction.C + 1; ++i ) + { + values[i - instruction.B] = new Reference(context, stack.Get(i)!); + } + + stack.Set(instruction.A, new Concat(context, values)); + + break; + } + case OpCode.LENGTH: + case OpCode.MINUS: + case OpCode.NOT: + { + var type = instruction.Code switch + { + OpCode.LENGTH => UnaryType.Length, + OpCode.MINUS => UnaryType.Minus, + OpCode.NOT => UnaryType.Not, + _ => throw new NotSupportedException() + }; + + stack.Set(instruction.A, new Unary(context, type, new Reference(context, stack.Get(instruction.B)!))); + + break; + } case OpCode.JUMPIFEQ: case OpCode.JUMPIFLE: case OpCode.JUMPIFLT: diff --git a/src/Unluau/IL/Values/Concat.cs b/src/Unluau/IL/Values/Concat.cs new file mode 100644 index 0000000..5051875 --- /dev/null +++ b/src/Unluau/IL/Values/Concat.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Unluau.Utils; + +namespace Unluau.IL.Values +{ + /// + /// Concatenates values in registers. + /// + /// Information about the location. + /// The registers that are concatenated together. + public class Concat(Context context, BasicValue[] registers) : BasicValue(context) + { + /// + /// The registers that are concatenated together. + /// + public BasicValue[] Registers { get; set; } = registers; + + /// + /// Implements the visitor. + /// + /// The visitor. + public override void Visit(Visitor visitor) + { + if (visitor.Visit(this)) + { + foreach (var reg in Registers) + { + reg.Visit(visitor); + } + } + } + + /// + /// Converts the current to a string. + /// + /// String representation. + public override string ToString() => $"Concat({TypeExtensions.ToString(Registers)})"; + } +} diff --git a/src/Unluau/IL/Values/Unary.cs b/src/Unluau/IL/Values/Unary.cs new file mode 100644 index 0000000..56263a9 --- /dev/null +++ b/src/Unluau/IL/Values/Unary.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Unluau.Utils; + +namespace Unluau.IL.Values +{ + public enum UnaryType + { + Not, + Minus, + Length + } + + /// + /// Applies unary operation to a register. + /// + /// Information about the location. + /// The type of unary operation. + /// The register that the unary operation is applied to. + public class Unary(Context context, UnaryType type, BasicValue value) : BasicValue(context) + { + /// + /// The type of unary operation. + /// + public UnaryType Type { get; set; } = type; + + /// + /// The register that the unary operation is applied to. + /// + public BasicValue Value { get; set; } = value; + + /// + /// Implements the visitor. + /// + /// The visitor. + public override void Visit(Visitor visitor) + { + if (visitor.Visit(this)) + { + Value.Visit(visitor); + } + } + + /// + /// Converts the current to a string. + /// + /// String representation. + public override string ToString() => $"{Enum.GetName(typeof(UnaryType), Type)}({TypeExtensions.ToString(Value)})"; + } +} diff --git a/src/Unluau/IL/Visitors/ValueVisitor.cs b/src/Unluau/IL/Visitors/ValueVisitor.cs index 4a8c953..9b39100 100644 --- a/src/Unluau/IL/Visitors/ValueVisitor.cs +++ b/src/Unluau/IL/Visitors/ValueVisitor.cs @@ -167,6 +167,12 @@ private static BasicValue ResolveValue(BasicValue value) if (value is Table table) ResolveTable(table); + if (value is Concat concat) + concat.Registers = ResolveValueList(concat.Registers); + + if (value is Unary unary) + unary.Value = ResolveValue(unary.Value); + return value; }