From c1b0946ccc99116a3ac993bda979ce5a07d0097c Mon Sep 17 00:00:00 2001 From: R-unic Date: Mon, 20 Jan 2025 18:07:44 -0500 Subject: [PATCH] docs: document all OpCodes --- Heir/CodeGeneration/BytecodeDeserializer.cs | 1 - Heir/CodeGeneration/OpCode.cs | 94 ++++++++++++++++++++- Test.heir | 9 +- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/Heir/CodeGeneration/BytecodeDeserializer.cs b/Heir/CodeGeneration/BytecodeDeserializer.cs index 0caf6dd..d0848aa 100644 --- a/Heir/CodeGeneration/BytecodeDeserializer.cs +++ b/Heir/CodeGeneration/BytecodeDeserializer.cs @@ -48,7 +48,6 @@ public static Bytecode Deserialize(Stream stream) case OperandType.StringList: { var length = reader.ReadInt32(); - var list = new List(); for (var i = 0; i < length; i++) list.Add((string)DeserializeOperand(reader)!); diff --git a/Heir/CodeGeneration/OpCode.cs b/Heir/CodeGeneration/OpCode.cs index 06d00d6..732a61e 100644 --- a/Heir/CodeGeneration/OpCode.cs +++ b/Heir/CodeGeneration/OpCode.cs @@ -2,50 +2,138 @@ public enum OpCode : byte { + /// Creates a new scope BEGINSCOPE, + /// Ends the current scope and returns to the enclosing scope ENDSCOPE, + /// Pushes the given value onto the stack + /// The value to push onto the stack PUSH, + /// Pushes an onto the stack + /// A of bytecode keys & bytecode values PUSHOBJECT, + /// Pushes none (null) onto the stack PUSHNONE, + /// Pops the last value off of the stack POP, - JMP, // jump to the instruction at the provided offset - JZ, // jump if value on stack is false or 0 - JNZ, // jump if value on stack is true or 1 + /// Jump ahead by the given offset + /// The amount of instructions to jump ahead + JMP, + /// Jump ahead by the given offset if the last value on the stack is false or 0 + /// The amount of instructions to jump ahead + JZ, + /// Jump ahead by the given offset if the last value on the stack is true or 1 + /// The amount of instructions to jump ahead + JNZ, + /// Swaps the positions of the last 2 elements on the stack SWAP, + /// Pushes the last element in the stack onto the stack again DUP, + /// + /// Stores a variable in the current scope using the last two frames of the stack. + /// Of those last two frames, the first is the value and the second is the name. + /// + /// Whether to push the value of the stored variable onto the stack (false by default) + /// + /// This example is produced when executing let abc = 5;: + /// + /// PUSH abc + /// PUSH 5 + /// STORE + /// STORE, + /// + /// Loads a variable from the current scope using the last frame in the stack. + /// The frame it uses is the name of the variable to load. + /// LOAD, + /// + /// If the call stack is not empty, returns to the last . + /// Otherwise, it advances. + /// RETURN, + /// Pushes a onto the stack + /// The body of the function as bytecode PROC, + /// Calls the last frame in the stack (assuming it's a ) + /// + /// A tuple; the first item being the amount of argument instructions that come after this instruction, + /// and the second item being a list of all parameter names on the callee. + /// + /// + /// This example is produced when executing fn double(x: int) -> x * 2; double(8);: + /// + /// PUSH double + /// + /// PROC (bytecode) + /// BEGINSCOPE + /// PUSH x + /// LOAD + /// PUSH 2 + /// MUL + /// RETURN + /// ENDSCOPE + /// + /// STORE False + /// PUSH double + /// LOAD + /// CALL (1, ["x"]) + /// PUSH 8 + /// EXIT + /// CALL, + /// Indexes the second to last frame in the stack using the last frame in the stack (assuming it's a of objects) INDEX, + /// Concatenates the last two frames in the stack together (assuming they're s) CONCAT, + /// Adds the last two frames in the stack together (assuming they're numbers) ADD, + /// Subtracts the last two frames in the stack (assuming they're numbers) SUB, + /// Multiplies the last two frames in the stack (assuming they're numbers) MUL, + /// Divides the last two frames in the stack (assuming they're numbers) DIV, + /// Divides then floors (integer division) the last two frames in the stack (assuming they're numbers) IDIV, + /// Raises the last frame in the stack to the second to last frame in the stack's power (assuming they're numbers) POW, + /// Calculates the modulus of the last two frames in the stack (assuming they're numbers) MOD, + /// Negates the last frame in the stack (assuming it's a number) UNM, + /// Calculates binary not on the last frame in the stack (assuming it's an ) BNOT, + /// Calculates binary and on the last two frames in the stack (assuming they're s) BAND, + /// Calculates binary or on the last two frames in the stack (assuming they're s) BOR, + /// Calculates binary exclusive or on the last two frames in the stack (assuming they're s) BXOR, + /// Calculates bit shift left on the last two frames in the stack (assuming they're s) BSHL, + /// Calculates bit shift right on the last two frames in the stack (assuming they're s) BSHR, + /// Calculates logical and on the last two frames in the stack (assuming they're s) AND, + /// Calculates logical or on the last two frames in the stack (assuming they're s) OR, + /// Calculates logical not on the last frame in the stack (assuming it's a ) NOT, + /// Calculates less than (LT) on the last two frames in the stack (assuming they're numbers) LT, + /// Calculates less than or equal to (LTE) on the last two frames in the stack (assuming they're numbers) LTE, + /// Calculates equality of the last two frames in the stack EQ, + /// No operation, blank instruction NOOP, + /// Signal to the that the program has completed. EXIT } \ No newline at end of file diff --git a/Test.heir b/Test.heir index c355b0f..a58cc6e 100644 --- a/Test.heir +++ b/Test.heir @@ -1,7 +1,2 @@ -fn fib(n: int): int { - if n <= 1 return n; - return fib(n - 1) + fib(n - 2); -} - -let r = fib(20); -print(r); \ No newline at end of file +fn double(x: int) -> x * 2; +double(8); \ No newline at end of file