Milestone 4: Variables and Flow
In this fourth milestone, you'll add variables, conditional statements, and for-each loops to your spreadsheet. These features will build on your previous work in the lexer, parser, and model classes. You'll need to expand your environment abstraction and expression hierarchy from milestone 1. You'll be adding new structures to the spreadsheet grammar, which means you'll be extending the lexer and parser from milestone 2. If your model and view are cleanly separated, you shouldn't need to make many changes to your user interface from milestone 3.
Let's examine each of these new features in detail.
Variables
Programmers use variables to attach meaningful names to data. Many spreadsheets don't support this humane practice. One just puts a value in a cell and refers to that cell by its column and row. Your spreadsheet is for humans, so we need a way to name things. Variable declarations appear in in a cell's formula, which means we need a way to sequence together statements. Extend your spreadsheet so users can write formulas like this:
proportion = #[2, 4] + 1
amount = sum([5, 8], [9, 8])
proportion * amount
You'll need to expand your lexer, parser, and model classes to support variable declarations and the other statements described later. In particular, you will need to make these three changes:
-
Add a block abstraction to your expression hierarchy. It is a sequence of statements. Have its
visit
method inEvaluator
evaluate this sequence and return the value produced by the final statement. Add a rule to your grammar for matching blocks. Have the parser's top rule parse a block instead of just a single expression. -
Add an assignment abstraction, in which the variable is treated as an lvalue. Have its
visit
method inEvaluator
evaluate the right-hand side to a primitive and store the binding in a key-value store maintained inRuntime
. -
Add a variable reference abstraction, in which the variable is treated as an rvalue. Have its
visit
method look up and return the associated primitive value stored inRuntime
. Raise an error if the variable is undefined.
Variables should be local to a cell's formula. No other cells can access them. That means each cell should be executed with a new and independent instance of Runtime
. As the program runs, there will be a single grid but many Runtime
instances.
Conditional Statements
Add support for conditional statements so that users can write code like this:
if #[2, 1] > #[2, 0]
1
else
0
end
Make a conditional abstraction in your model classes that stores the condition and two blocks. It evaluates the condition and chooses which block to evaluate. The value returned by the conditional is the value returned by the block that gets executed. For simplicity, assume that every conditional has both a then and else block.
For-each Loops
Add support for for-each loops so that users can write code like this:
count = 0
for value in [4, 0]..[4, 3]
if value > 0.0
count = count + 1
end
end
Make a for-each abstraction in your model classes that stores the name of the iterator, the starting cell address, the ending cell address, and the block. It iterates through the two-dimensional window of cells and assigns each cell's value to a local variable with the given name. The block is evaluated for each cell in the given window. The value returned by the block on the final iteration is the value returned by the larger loop.
Submission
To submit your milestone, follow the instructions. In particular, do these three things:
- Submit your project to the official GitHub repository that your instructor made for you.
- Record a 3–5 minute screencast of you walking through your code and commenting on it. Do not exceed 5 minutes. Your instructor has many videos to watch. Post it to Canvas Studio according to the instructions.
- Complete the ready date submission form on Canvas.
In your video, demonstrate entering assignments, if statements, and for-each loops using the Curses interface that you built for milestone 3.
Don't comment on or show every single line of code in your video. Select a few representative snippets. Do comment on programming language ideas that interest you or challenged you.