Logic in Cecil

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

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

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 Cecil style in your implementation.  You should use type declarations for method and field arguments and results, and you should be able to successfully typecheck your implementation.  Several features of Cecil 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 "type tests".  Here are some suggestions: