The Monty project is an interpreter for Monty ByteCodes files. Monty 0.98 is a scripting language that is first compiled into Monty byte codes, similar to Python. The interpreter relies on a unique stack data structure with specific instructions to manipulate it. The project involves implementing various opcodes to perform stack operations.
The project uses two main data structures, defined in the header file:
typedef struct stack_s
{
int n;
struct stack_s *prev;
struct stack_s *next;
} stack_t;
typedef struct instruction_s
{
char *opcode;
void (*f)(stack_t **stack, unsigned int line_number);
} instruction_t;
The code is compiled using the following command:
gcc -Wall -Werror -Wextra -pedantic -std=c89 *.c -o monty
All output is printed on stdout
, and any error messages are printed on stderr
.
Monty byte code files have the .m
extension. Each file contains instructions, with one instruction per line. The interpreter executes the byte codes line by line and stops if an error occurs or when the entire file is executed.
./monty file
- If no file or more than one argument is provided, it prints:
USAGE: monty file
and exits withEXIT_FAILURE
. - If it can't open the file, it prints:
Error: Can't open file <file>
and exits withEXIT_FAILURE
. - If an invalid instruction is encountered, it prints:
L<line_number>: unknown instruction <opcode>
and exits withEXIT_FAILURE
. - If
malloc
fails, it prints:Error: malloc failed
and exits withEXIT_FAILURE
.
The push
opcode pushes an element onto the stack. Usage: push <int>
. If the argument is not an integer or not provided, it prints an error message.
The pall
opcode prints all values on the stack. If the stack is empty, it doesn't print anything.
The pint
opcode prints the value at the top of the stack. If the stack is empty, it prints an error message.
The pop
opcode removes the top element of the stack. If the stack is empty, it prints an error message.
The swap
opcode swaps the top two elements of the stack. If the stack contains less than two elements, it prints an error message.
The add
opcode adds the top two elements of the stack. If the stack contains less than two elements, it prints an error message.
The nop
opcode does nothing.
The sub
opcode subtracts the top element of the stack from the second top element. If the stack contains less than two elements, it prints an error message.
The div
opcode divides the second top element of the stack by the top element. If the stack contains less than two elements or the top element is 0, it prints an error message.
The mul
opcode multiplies the second top element of the stack with the top element. If the stack contains less than two elements, it prints an error message.
The mod
opcode computes the remainder of the division of the second top element by the top element. If the stack contains less than two elements or the top element is 0, it prints an error message.
Comments in Monty start with #
and are ignored by the interpreter.
The pchar
opcode prints the character at the top of the stack. If the value is not in the ASCII table or the stack is empty, it prints an error message.
The pstr
opcode prints the string starting at the top of the stack. It stops when the stack is empty, the value is 0, or the value is not in the ASCII table.
The rotl
opcode rotates the stack to the top. The top element becomes the last one, and the second top element becomes the first one.
The rotr
opcode rotates the stack to the bottom. The last element becomes the top element.
The stack
opcode sets the data format to a stack (LIFO), and queue
sets it to a queue (FIFO). When switching modes, the top and front of the stack are adjusted accordingly.
A Brainf*ck script that prints "School" followed by a new line.
Reads two digits from stdin, adds them, and prints the result.
Reads two digits from stdin, multiplies them, and prints the result.
Reads two digits from stdin, multiplies them, and prints the result followed by a new line.