Pinion is an open source scripting language for Unity, created by Kasper the main person guiding me at LuGus Studios where I did my internship. This scripting language is used in their projects like Liftoff and Midnight Protocol to give users (in Midnight Protocol) or companies like NASA, for which they did Liftoff Offworld, the possibility to make their own exercises to train drone pilots.
At the start of this assignment I was given this code snippet (below text) and told that when running this code, instead of filling the array with the checkpoint + number. The array would be empty except for the first index which would have checkpoint13.

So I started going through the code trying to figure out how the compiler did variable assignment and if it was a compiler or runtime error. Because of the complexity I had to manually go through step for step while writing down which functions got called so that I would have a map of how the compiler worked. After some time I figured out that the = assignment operator didn’t have support for arrays so it would just treat it like a normal variable and assign to the first position.
To solve this when you are making an assignement with the = operator I write and extra index to the stack. If it is an array that is the index at which to write but if it is not it is 0. This means that you will always have a extra integer on the stack even when it is not an array. This was the cleanest way I found since at runtime we do not keep track if it is an array or not. The code below is the assignment that is run at runtime.
public static void AssignVariable(PinionContainer container, int variable, int newValue)
{
// write value at the location of the variable + the index of the array (if it is not an array that will be 0)
container.IntRegister.WriteValue((ushort)(container.AdvanceToNextInstruction() + container.IntRegister.ReadValue(container.AdvanceToNextInstruction())), newValue);
}
This code is the code run at compile time
private static void AssignVariableCompileHandler(IList<CompilerArgument> providedArguments, IList<ushort> instructionCodes, System.Action<string> compileErrorHandler)
{
// Compiler should already have ensured signature match at this point.
// We can be reasonably sure there are exactly two arguments of the right type.
CompilerArgument targetVariable = providedArguments[0];
// Disallow using assign operator with anything but variables. To do otherwise is pointless anyway.
if (targetVariable.argumentSource != CompilerArgument.ArgSource.Variable)
{
compileErrorHandler(messageAssignVariableOnly);
return;
}
ushort readIndex = 0;
if (targetVariable.variablePointer.IsArray)
{
// Look for the last instruction code that indicates read int
// This one should be the index of the array where we should be writing to.
ushort instructionCode = PinionAPI.GetInternalInstructionByID(PinionAPIInternalIDs.ReadInt).instructionCode;
for (int index = instructionCodes.Count -1; index >= 0; index--)
{
if (instructionCodes[index] == instructionCode)
{
readIndex = instructionCodes[index + 1];
break;
}
}
}
// add the location of the array and the location of the index of the array (if it is not an array that will be 0) to the instruction code
instructionCodes.Add((ushort)(targetVariable.variablePointer.GetIndexInRegister()));
instructionCodes.Add(readIndex);
}
