
Base For Evaluable Objects
All objects in the lisp language can be evaluated with the eval function.
The classes that represent them are all derived from Evaluable, and must
implement the eval method, which varies with the object.
Literal atoms just return themselves; lists evaluate as function calls;
identifiers evaluate by looking themselves up in the context. None of
which is in this file.
//*****************************************************************************
//*** Evaluable abstract class.
//***
//*** All the object visible to the interpreted program are Evaluable,
//*** though sometimes evaluating them will yield an error. They also
//*** have car() and cdr() methods, like pairs, though they should not
//*** be called. It's convenient to have them here just to reduce the
//*** number of casts needed to get anything done. (There's already a lot.)
//*****************************************************************************
#include <string>
using namespace std;
#include <stdlib.h>
#include "context.h"
#ifndef _evaluable_h_
#define _evaluable_h_
/* These are objects on which the eval() method works. These are exposed to
the interpreted code. */
class Evaluable: public RefCtObj {
public:
// These can be evaluated, they all have a name, and they can all
// be printed.
virtual Ptr<Evaluable> eval(Ptr<Context>) = 0;
virtual string name() = 0;
virtual void print(ostream &) = 0;
// Some objects can be applied (to). But not
// unless they really are . . .
virtual bool applyable() { return false; }
// Nice to be able to find these, too.
virtual bool closure() { return false; }
// These really don't belong here in the heirarchy, but it makes
// life *much* easier to be not constantly casting stuff.
virtual Ptr<Evaluable> car() {
cerr << "*** Internal error: car() on non-list object. ***";
abort();
}
virtual Ptr<Evaluable> cdr() {
cerr << "*** Internal error: cdr() on non-list object. ***";
abort();
}
};
#endif