Skip to content

Commit

Permalink
Add SetValue to the IL instruction set.
Browse files Browse the repository at this point in the history
  • Loading branch information
atrexus committed Mar 30, 2024
1 parent 7428a56 commit 4206be7
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 7 deletions.
6 changes: 1 addition & 5 deletions src/Unluau.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ internal class Program
{
static void Main(string[] args)
{
using var stream = File.OpenRead("./test/IfElse.luau");
using var stream = File.OpenRead("./test/SetTables.luau");
var chunk = LuauChunk.Create(stream);

Console.WriteLine(chunk.ToString());

var program = chunk.Lift();

using var output = Console.OpenStandardOutput();
program.Visit(new OutputVisitor(output));

Console.WriteLine('\n');

program.Visit(new ValueVisitor());
program.Visit(new OutputVisitor(output));
Expand Down
Binary file added src/Unluau.CLI/test/AnimationClipEditor.luac
Binary file not shown.
Binary file added src/Unluau.CLI/test/SetTables.luau
Binary file not shown.
44 changes: 43 additions & 1 deletion src/Unluau/Chunk/Luau/Function.cs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ public Closure Lift()
var context = GetClosureContext();
var stack = new Stack();

// Now we load the parameters to this closure onto the stack.
foreach (var variable in context.Parameters)
stack.Set(variable.Slot, variable);

var body = LiftBasicBlock(stack, 0);

return new(context, body);
Expand Down Expand Up @@ -371,6 +375,10 @@ OpCode.LOADKX or
_ => throw new NotSupportedException()
};

// Skip the AUX instruction for the following operation codes
if (instruction.Code == OpCode.GETIMPORT)
pc++;

// Here we check to see if the slot we are loading our value into is initialized or not. If it has, then we
// check to see if this value has been set within the current block. If not then we reset it, otherwise we
// just update it.
Expand Down Expand Up @@ -478,6 +486,38 @@ OpCode.LOADKX or
block.Statements.Add(getIndex);
break;
}
case OpCode.SETTABLEKS:
case OpCode.SETTABLE:
case OpCode.SETTABLEN:
{
// This is our indexable value. In Luau its always a table.
var table = new Reference(context, stack.Get(instruction.B)!);

// Gets the value for the index.
var indexValue = instruction.Code switch
{
OpCode.SETTABLE => new Reference(context, stack.Get(instruction.C)!),

// The SETTABLEN instruction contains a value (byte) from 1 to 256. Because the C operand can only hold
// a value as large as 255, we need to add 1 to it.
OpCode.SETTABLEN => new BasicValue<int>(context, instruction.C + 1),

// The SETTABLEKS instruction contains a constant in the auxiliary instruction. We group them here for
// simplicity.
OpCode.SETTABLEKS => ConstantToBasicValue(context, Constants[Instructions[++pc].Value]),

// We know this won't ever happen, but the C# compiler will cry if I don't add this.
_ => throw new NotSupportedException()
};

var index = new Index(context, table, indexValue);

// Now we get the value of the set instruction (what we are setting the index to).
var value = new Reference(context, stack.Get(instruction.A)!);

block.Statements.Add(new SetIndex(context, index, value));
break;
}
case OpCode.MOVE:
{
var rb = stack.Get(instruction.B)!;
Expand Down Expand Up @@ -536,6 +576,8 @@ OpCode.LOADKX or
}
case OpCode.SETLIST:
{
// This instruction doesn't generate any IL instructions. Instead it initializes a table as an array,
// and assigns all of its values to it.
var table = (Table)stack.Get(instruction.A)!.Value;

for (int i = 0; i < instruction.C - 1; ++i)
Expand Down Expand Up @@ -563,7 +605,7 @@ OpCode.LOADKX or
var values = new BasicValue[valueCount];

for (int i = 0; i < valueCount; ++i)
values[i] = stack.Get(instruction.A + i)!.Value;
values[i] = new Reference(context, stack.Get(instruction.A + i)!);

// Note: We always add a return statement, even if this is the block of the main closure. Whether or not to
// display the `return` of the main block is configurable in the AST builder.
Expand Down
36 changes: 36 additions & 0 deletions src/Unluau/IL/Statements/Instructions/SetIndex.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Unluau.IL.Values;

namespace Unluau.IL.Statements.Instructions
{
/// <summary>
/// Assigns a value to an index.
/// </summary>
/// <param name="context">Information about the instruction.</param>
/// <param name="index">The index.</param>
/// <param name="value">The value to assign.</param>
public class SetIndex(Context context, Values.Index index, BasicValue value) : Instruction(context)
{
/// <summary>
/// The index we are setting.
/// </summary>
public Values.Index Index { get; set; } = index;

/// <summary>
/// The value we are assigning to the index.
/// </summary>
public BasicValue Value { get; set; } = value;

/// <summary>
/// Implements the recursive visitor pattern.
/// </summary>
/// <param name="visitor">The visitor.</param>
public override void Visit(Visitor visitor)
{
if (visitor.Visit(this))
{
Index.Visit(visitor);
Value.Visit(visitor);
}
}
}
}
1 change: 1 addition & 0 deletions src/Unluau/IL/Visitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class Visitor
public virtual bool Visit(GetIndexSelf node) => Visit(node as Instruction);
public virtual bool Visit(Move node) => Visit(node as Instruction);
public virtual bool Visit(Return node) => Visit(node as Instruction);
public virtual bool Visit(SetIndex node) => Visit(node as Instruction);

// Blocks
public virtual bool Visit(IfBlock node) => Visit(node as BasicBlock);
Expand Down
7 changes: 7 additions & 0 deletions src/Unluau/IL/Visitors/OutputVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ public override bool Visit(Return node)
return false;
}

public override bool Visit(SetIndex node)
{
Writer.Write(Format(node.Context, "SetIndex", node.Index.ToString(), node.Value.ToString()));

return false;
}

public override bool Visit(BasicBlock node)
{
Writer.WriteLine(Format(node.Context, "BasicBlock {"));
Expand Down
14 changes: 13 additions & 1 deletion src/Unluau/IL/Visitors/ValueVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,26 @@ public override bool Visit(NotTest node)
return true;
}

public override bool Visit(GetIndexSelf node)
public override bool Visit(GetIndex node)
{
if (!TryDelete(node, node.Slot))
node.Index = ResolveIndex(node.Index);

return true;
}

public override bool Visit(GetIndexSelf node)
{
return Visit(node as GetIndex);
}

public override bool Visit(SetIndex node)
{
node.Index = ResolveIndex(node.Index);

return true;
}

public override bool Visit(LoadValue node)
{
TryDelete(node, node.Slot);
Expand Down

0 comments on commit 4206be7

Please sign in to comment.