Calculator REPL Part 4: Support bools

This is the fourth installment in my discussion of building a calculator REPL in Rust. (For convenience, here are part 1 part 2 and part 3 .) I’ve decided that I like this project a lot, and that I’m going to gradually start trying to make it into a fully-featured Scheme interpreter. (It already has way too many parentheses, after all.)

The first thing I want to do in expanding beyond a calculator REPL is have two data types. Before I just had ints; now I’m going to add bools.

First, I had to make it so that my operand type tokens can represent more than integers. To accomplish this, I added another enum, called Type, to use inside operands. The integer 3 used to be parsed as Token::Operand(3), but now it’s parsed as Token::Operand(Type::Integer(3)), which leaves room for me to parse things as Token::Operand(Type::Bool(true)). This is the sort of change that the rust compiler really helps with: Once I added this enum, I went through and mechanically cleaned up compiler errors. When I was done, I had working but unused implementation of boolean types. Even though it’s just me on this project, I’m trying to be sure that master never fails to build or has regressions, so I opened a PR to add bools.

Now that my interpreter can represent boolean values, we need to be able to do something with them. To start with, I’m just adding and and or. This change will effectively give me two different languages in that can’t talk to each other: A language that and do and and or operations with bools, and a language that can do arithmetic operations with integers. At some point we’ll need to write operations that can handle bools and integers, but for now, getting the bools working will be a good start.

My file is getting too big, and doing too many things, so I want to break my interpreter out into sub modules. At least for now, I’m grouping these sub modules by the type of thing they do: I’ll have a main interpreter module, which will call out to different reducers, so I can have integer reducers, boolean reducers, etc. This PR adds boolean reducers and calls them from the interpreter. The or reducer and the and reducer are the same except that the or reducers uses any and the and reducer uses all:

pub fn reduce_or(stack: &mut Vec<Token>) -> Result<Token, RuntimeError> {
// would return Err if the vector were not entirely
// made of Token::Operand(Type::Bool), since we can't reduce with `or`
// other values
let bool_result = unwrap_boolean_tokens(stack);
if let Ok(bool_vec) = bool_result {
bool_vec.iter().any(|b| *b) // and reducer has "all" here
} else {
Err(RuntimeError{ })

view raw

hosted with ❤ by GitHub

Next time, we’ll add comparison reducers, so that we can start using ints and bools in the same expression. Till then, happy learning!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s