Read my book

I wrote books about Webpack and React. Check them out!

Monday, December 7, 2009

Placidity - Part 3, Variables II

So far our interactive interpreter handles simple math expressions and variables. After last post I realised it would be useful to have a way to print stored variables and to remove them. To make our interpreter easier for the user it would be useful to provide "help" command as well. I will implement those features in this blog post. So let's get to work.

Printing Variables

It's probably nice enough if we provide "variables" command that then outputs all stored variables in a form such as this:

Stored variables:
a=14
b=-4
animal='boar'

In addition it would be nice to allow the user to use "vars" alias just to avoid some typing and add some niftiniess to the system for power users. Let's add tests for these cases:

test_interpreter.py:


And here's the implementation:

interpreter.py:


The new tests forced me to change parameters passed to eval as it polluted the contents of self.vars. Later command matching probably goes into a class of its own but the current implementation is just fine for now. We can always refactor the structure later. Let's take a look at removing variables next.

Removing Variables

Removing variables should be straight forward. I would expect it to work in following way:

>>> a = 12
>>> vars
Stored variables:
a=12
>>> clean
>>> vars
No stored variables

Obviously if there are no stored variables, clean should do nothing. Let's write tests based on these observations:

test_interpreter.py:


Here are the relevant bits of my implementation:

interpreter.py:


So it's just one more check to the interpret method. The method looks like it could use some refactoring. Let's abstract the commands a bit. Here's my refactored code as whole:

interpreter.py:


commands.py:


Note that I separated commands to a module of their own just for the sake of clarity. The interpret method is still not perfect as the exception handling looks a bit crufty but that's for some later refactoring effort. Let's see if our refactoring efforts help in the implementation of the "help" command next.

Implementation of Help Command

As before let's define how "help" should work. Here's a sample snippet of expected behavior:

>>> help
clean - Cleans up stored variables
variables, vars - Shows stored variables
>>> help clean
Cleans up stored variables

Okay, so we have two distinct cases to test for. Let's implement the tests:

tests_interpreter.py:


And here's the implementation. Thanks to the refactored command architecture, we won't have to pollute the interpreter directly anymore.

commands.py:


Summary

Whew. Now it's possible to view the stored variables, remove them ("clean" command) and to see some rudimentary help on demand. There are still lots of issues to solve, though.

For instance if you look at the way "help" command is tested, you can see it's somewhat tightly coupled with the other commands. So should we need to add more functionality to the system, we would have to alter the test. This definitely is not a good thing.

Furthermore it might make sense to separate the command tests into a module of their own. Also it would be possible to decompose the current commands module even further and treat each command as a plugin. Let's take a look at this in the next part of the series. You may find the source code of this part of the series here.