The software you are developing for CSE 450 is focused on compilation, but the core ideas behind interpreting a source program remains identical -- you still have to lex and parse the input, do semantic checking on it, convert it to an Abstract Syntax tree. But instead of converting the tree to an Intermediate (Bad) Code and then to Ugly Code, the other option is to just execute it directly.
For this honors project, you will modify your compiler (likely your Project 5 solution) to be an interpreter. This interpreter should be able to handle all of the features that you implemented in projects 1 through 5. With one exception, none of the test cases use the random command.
The honors project is a Mimir project with the same name.
Your project.py file must have a function called "generate_output_from_string" which takes a good code string and returns the output from running it.
In order to receive Honors Credit, you must pass every test in Project Honors. There is no partial credit.
I recommend that you implement this option by creating an interpret() method to parallel your generate_ic() / generate_bad_code() functions throughout the abstract syntax tree node implementations. Note that interpret() will still return a tableEntry, but it does not need to have access to the ic_instructions since it won't use it.
This project should include very few changes to your lexer and parser. Most of the changes will be in how you traverse the AST and how the symbol table is implemented.
One of the biggest differences between your interpreter and your compiler is how the symbol table is structured. In a compiler, the table will reference a register location for the virtual machine. An interpreter reads and executes the source directly, which means it will need to keep track of and store variables' values.
To be more specific, the table is a dictionary, so it consists of a string "key", and a value. The type of the value for an interpreter can be one of the 4 types (val, char, array(val), array(char)).
For the purposes of this project, the type of a variable will not change after it is declared. At this point, your compiler probably keeps track of types already. This means you can check the type of a variable.
Note, once you set the type of your variable it is fixed, and your interpreter should still throw errors for mismatched types. This form of type system is known as static typing. It is more common in compiled languages. C/C++, Java, and Go are examples of this.