Grades and deadlines
-
Initial deadline: 23:59 on Tuesday 02 December
-
How to submit: Turn in your completed
lab5.1.ymlfile, along with everything in thesrc/mainfolder of your maven project.You must submit via the command line in order to preserve the folder structure. Use either of these two commands to do it:
club -csi413 -plab5.1 -f lab5.1.yml src/mainor
submit -c=si413 -p=lab5.1 lab5.1.yml src/main(you can download the club tool here)
If you used an AI tool to help with this lab (you should use Gemini), turn in a file
aichat.mdas well. Remember the course guidelines for the use of generative AI on labs. -
Grading:
In this lab you will complete ONE OF the following tasks:
- Add support for two built-in functions to your Lab 4.2 interpreter
- Add support for numbers to one of the Lab 4.2 starter langauges.
If your submission meets the requirements for your chosen task, you will receive 5 points towards your total lab grade.
-
Collaboration
You are free to discuss the lab with classmates (without looking at Java code), diagram out your solution, etc., as long as that collaboration is clearly documented in your YAML file.
After you have already written something, and it doesn’t work, you may also get debugging help from someone working on a different language than you, provided this help is clearly documented. Help never includes sharing any working code with a classmate.
-
Resubmissions:
We will follow the same resubmission policy for all labs this semester:
def points_earned(deadline, max_points, previous_submission=None): while current_time() < deadline: wait() submission = get_from_submit_system() if meets_all_requirements(submission): return max_points elif significant_progress(previous_submission, submission): return points_earned(deadline + one_week, max_points, submission) else: return 0
Two Options
You have two options for how you will complete this lab:
-
You will add built-in functions to your own working interpreter from last lab.
This option will be better for you if you enjoyed that lab on functions, and want a higher intellectual/conceptual challenge but much less actual coding work to do.
-
You will add numbers to one of the three starter languages from last lab. You don’t actually have to have a working solution to that lab to complete this one, because we will not test whether function calls work.
This option will be better for you if you feel a little less confident on the previous lab, want a good review where you touch on all of the pieces of the interpreter we’ve seen this semester, and want to do a little more actual coding work to get it done.
Of course, it would be great if you want to take both options in a single interpreter! But we will only assign credit based on whichever option you indicate in the yaml file.
Option A: Builtins
(Skip down to Option B and ignore this section if you are taking that option.)
Getting started (files for option A)
Start by cloning the git repo corresponding to the language you used for the previous lab, by running one of these three commands:
# for EasyAs
git clone https://github.com/si413usna/startlab.git -b lab5.1-a-easyas lab5.1
# for Simple
git clone https://github.com/si413usna/startlab.git -b lab5.1-a-simple lab5.1
# for ddcw
git clone https://github.com/si413usna/startlab.git -b lab5.1-a-ddcw lab5.1
Go into the new directory and copy your entire src/ folder from your
working solution to Lab 4.2. That will be your starting point for this
lab.
In the new directory, you will find a new program in your language,
called read_plus. Your goal will be to implement built-in functions
for the read and plus functions so that this program (or any other
program like it) works in your interpreter.
What is a built-in function?
A built-in function in a programming language is something which looks syntactically like any other regular function call, but which is pre-defined when any program in that language starts. Typically, these built-in functions might be used to do common tasks, or to access special capabilities that otherwise wouldn’t be available to the programmer.
Most programming languages include a lot of built-in functions. In
Python these include things like print(), abs(), and open().
It’s important to distinguish these from keywords, which are also kind
of “built-in” to the language, but do not behave like regular functions
and in fact have a special role in the token spec and grammar. Things
like if, while, else are examples of keywords in Python.
By contrast, from the programmer’s perspective built-in functions are exactly like any other function, just that the programmer didn’t have to define them.
Behind the scenes, when a user calls a built-in function, that should trigger some special interpreter code (i.e., code that you write in Java), to do whatever the function is supposed to do.
The built-in functions you need to write
We are asking you to write two built-in functions and add them to your interpreter in your language. Here are equivalent definitions of these functions in Python, so that it’s clear what they are supposed to do:
# Takes a string for a file name, then reads and returns the entire
# file contents as a single string
def read(fname):
with open(fname) as fin:
return fin.read()
# Takes two strings which hold digit characters representing two
# then adds those numbers and returns the sum as another string.
def plus(num1, num2):
return str(int(num1) + int(num2))
Hints on how to get built-ins working
Most importantly, you should not need to change your token spec, grammar, or AST generation at all in order to get built-in functions to work. If you find yourself editing those files, take a step back and consider whether you really want/need to!
In my sample solutions, I just created one new file that I called
Builtins.java, and then added a few new lines of code to
Interpreter.java. (Of course, you might structure your solution in a
different way, and that is totally OK as long as it works!)
To get these two built-in functions to work, somewhere you have to have your code in Java to do the thing that each built-in does (reading a file or adding two string-represented integers). That is actually the easy part; I’m sure you could write those few lines of Java in your sleep by now!
The tricky part is figuring out how to connect these methods/classes, with the running interpreter. Precisely how you do this will depend on how you got function calls working in the previous lab. Now you need to mimic what a function definition would do, except you are going to kind of hard-code these two function definitions into the global frame, in Java, before the interpreter ever starts executing the user code. You might need to create a special closure object, create a new binding somewhere, etc. – you figure out the details!
Just like with the last lab, I recommend starting with something easy (like a test builtin that takes no arguments and has no return value), then working your way up by adding arguments/parameters first, then return values, until a “fully powered” built-in function works correctly.
Testing and submitting your work
The included read_plus program in your language, can be used to test
your code. Of course you will need to make some test file(s) in your
directory in order to test it out! I also recommend you make some
smaller, simpler testing programs as you develop and debug your
interpreter.
Submit your interpreter in the usual way, after completing the yml
file:
club -csi413 -plab5.1 -f lab5.1.yml src/mainsubmit -c=si413 -p=lab5.1 lab5.1.yml src/main
Option B: Numbers
(Go back up to Option A and ignore this section if you are taking that option.)
Getting started (files for option B)
Start by cloning the git repo corresponding to the language you used for the previous lab, by running one of these three commands:
# for EasyAs
git clone https://github.com/si413usna/startlab.git -b lab5.1-b-easyas lab5.1
# for Simple
git clone https://github.com/si413usna/startlab.git -b lab5.1-b-simple lab5.1
# for ddcw
git clone https://github.com/si413usna/startlab.git -b lab5.1-b-ddcw lab5.1
The new directory has identical starter code to Lab 4.2.
You do not need to implement functions for this lab, just numbers with
variables, loops, and if statements.
(If you have a working solution to that lab and want to start with your
own code instead, then just replace the src/ directory with your working one
from Lab 4.2.)
Adding numbers to your language
For this option, you need to change your language and the interpreter to support numbers. Specifically, you need to support:
- Integer literals
- Printing numbers
- Reading numbers from the command line
- Saving numbers as variables
- Converting a number to a string
- Adding, multiplying, or subtracting two numbers
- Less-than comparison of two numbers
Importantly, your changes must be backwards-compatible with the existing language, meaning that the programs we previously wrote in your language, without numbers should still work.
Here is a Python program (to estimate the square root of a given integer) that demonstrates the new features you need to add to your language and interpreter:
print("Enter a number")
target = int(input())
if target < 1:
print("Too small")
target = 1234
cur = 1
while cur*cur < target:
cur = cur + 1
prev = cur - 1
if target - prev*prev < cur*cur - target:
sqrt = prev
else:
sqrt = cur
print("Square root of " + str(target) + " is close to " + str(sqrt))
Hints on adding numbers
In order to add support for numbers, you will need to:
-
Add some new tokens to
tokenSpec.txt. At the very least you will need a new token type for integer literals, and you may need to add more new tokens for some of the operators as well. -
Add new grammar rules to
ParseRules.g4for the new kinds of statements and expressions you need to support numbers and the required operations -
Modify
Value.javaso that it supports an additional type (numbers/integers) besides strings and booleans -
Add new AST node definitions in
Expr.javaandStmt.javato support the new kinds of expressions and statements in your language -
Write new visit methods in
ASTGen.javato handle each of the new grammar rules you added, and create AST nodes from the parse tree nodes
Nothing you are being asked to do for this option is really “new”, in the sense that we have done all these things in previous interpreter labs in the semester. Essentially you have to do a little bit of what you did in all the previous interpreter labs, which hopefully can be a nice review of all the steps and pieces of your interpreter.
Testing and submitting your work
You need to write a program equivalent to the Python square root program above, in your language. Your program should really be line-by-line equivalent to this one, demonstrating the new number features in your language and how you chose to make them.
Submit your interpreter in the usual way, after completing the yml
file:
club -csi413 -plab5.1 -f lab5.1.yml src/mainsubmit -c=si413 -p=lab5.1 lab5.1.yml src/main