Grades and deadlines

Two Parts - Both Optional

This lab has two parts. But both parts are independent, and you can complete them in either order, or only do one.

Getting started (for both parts)

Start by cloning the git repo corresponding to the language you used for the previous lab, by running one of these three commands:

# for Hibana
git clone https://github.com/si413usna/startlab.git -b lab5.1-hibana lab5.1

# for DIGEST
git clone https://github.com/si413usna/startlab.git -b lab5.1-digest lab5.1

# for void
git clone https://github.com/si413usna/startlab.git -b lab5.1-void lab5.1

You should see just a few files there:

Part A: Builtins

(Skip down to Part B and ignore this section if you are starting with that part.)

Files for Part A

Clone the git repo using the instructions above.

Notice there is no src/ directory here. That’s because the first thing you need to do is to 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.

Built-ins are also different from library functions, which are typically written in the target language itself and #included or imported directly.

By contrast, built-ins work like this:

In other words, a built-in looks like any other function in your language, but the code to actually run it will be written (for you) in Java, the language of the interpreter itself.

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 numbers
# then adds those numbers and returns the sum as another string.
def plus(num1, num2):
    return str(int(num1) + int(num2))

Note on error handling

Yes, you should do proper error handling in your builtin functions. Remember there is an Errors.error("message here") function that’s already provided for you in the Errors.java class. For both read and plus, you should catch potential run-time errors (like specifying a filename that doesn’t exist, or entering non-numerical strings) and print a sensible error message rather than crashing your interpreter with a stack trace.

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 RunState.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 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.

Complete the yml file and submit using the commands at the top of this page.

Part B: Numbers

Files for part B

Clone the git repo using the instructions above.

If you completed part A, you’re ready to go.

Otherwise, if you completed lab 4.2, copy your src/ directory from that lab into your directory for this lab.

Otherwise — if you are starting here and didn’t complete lab 4.2 — then run the provided ./get_src.sh script to download the starter code from lab 4.2.

Either way, you should be starting with an interpreter for your language that does everything from the unit 3 labs (at least): strings, booleans, variables, if statements, and while loops.

Adding numbers to your language

For this part, you need to change your language and the interpreter to support numbers. Specifically, you need to support:

(Notice, division and mod are not included! Just the things on this list.)

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.

(And if you complete part A, those built-in functions should still work as described there — the built-in plus function should still operate on strings, not actual numbers.)

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))

You need to fill in the empty file sqrt_prog with code in your language which will do the equivalent to the code above.

Hints on adding numbers

In order to add support for numbers, you will need to:

Nothing you are being asked to do for this part 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 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 that one, demonstrating the new number features in your language and how you chose to make them.

I also strongly recommend that you write some smaller, simpler programs to test each feature as you develop it. Like maybe start with a program that just prints an integer literal like 42 and try to get that working, then add the ability to add numbers, test it, etc. etc.

Once it works, complete the yml file and submit using the commands at the top of this page.