Logic in Diesel

For this part of the homework, to gain practice programming in Diesel and using Vortex, you will develop an implementation of propositional logic formulae (i.e., boolean expressions) in Diesel.  Your implementation should exploit a number of Diesel language features, as well as including some interesting algorithms and representation choices.

The logic.diesel file is a starter file defining the interface to Formula objects; you should flesh it out with a real implementation.  The logic-tests.diesel file contains an initial set of tests for your implementation; sample output of running logic-tests.diesel on my sample solution is here. You should also add your own tests to logic-tests.diesel.

API

There are several different kinds of logic formulae that can be constructed:

All of these expressions yield an object of type Formula (or some subtype of Formula).

The following operations are defined on Formula objects (in addition to the formula "constructors" above):

Optionally, there is an additional operation available for formulae:

Canonical Representation

Formulae must be represented internally in canonical form.

Implementation Notes

You should use good Diesel style in your implementation.  You should use type declarations for function, method, and field arguments and results, and you should be able to successfully typecheck your implementation.  Several features of Diesel will be helpful, including multimethods and easy support for one-of-a-kind objects.  Explicit tests like if should be used rarely, if at all; method dispatching should take care of any "instanceof tests".  Here are some suggestions: