// Object Class Definitions. // // File: object.h // Author: course // Version: 1 // Defines a LISP "object", which is the base class of // all LISP objects, e.g. symbols, fixnums, conses, etc. #ifndef OBJECT_H #define OBJECT_H #include "basic.h" #include "const.h" // Classes defined elsewhere. // class object_type; // // A C++ object that describes a LISP object type. // E.g. // extern object_type * SYMBOL_TYPE; // extern object_type * CONS_TYPE; // extern object_type * FIXNUM_TYPE; // // are C++ objects that contain information, such as // used and free lists for allocators, that describe // the LISP types SYMBOL, CONS, and FIXNUM. // // See type_of below. // Object Class Hierarchy: // // -------------------------------------- // Base | object | // Class: | | // | virtual functions: | // | print | // | scavenge | // -------------------------------------- // | | | | | // Derived | | | | | // Classes: symbol fixnum cons function ... // Note on Access (public, private, protected, friend); // // The access granting features of C++ are sometimes // inadequate to the correct writing of a program. This // is a common problem with existing languages, // including also Ada. // // Our policy is to write the program correctly first, // and then use C++ access granting features to express // access control as well as possible, without // destroying the correctness or readability of the // program. // // For example, friends should be thought of as member // functions with alternative syntax. The fact that // they also get access to private members is secondary. // Thus below we declare the >> operator to be a friend // because it is logically a member of the object type, // even though it in fact does not need access to // private members of object. // // As a second example, we write the definition of the // object class below in the order we think the reader // will find best. Public stuff is first, because this // is the user's view of the class. Then we switch // back and forth between private and protected as // needed. // // Lastly, sometimes the access granting system of C++ // is too complex to manage succinctly for a given // piece of data, so in that case we declare it public // while commenting that it really should be protected. // Note on Strict Typing: // // Generally we do not use casts such as // (cons *) my_object // that violate strong typing, except via inline // functions whose names begin with the word // "unchecked", which warns the programmer to be extra // careful. // object ------ Base class for all LISP objects. // class object { public: // Get the type of the object. Returns one of // SYMBOL_TYPE, CONS_TYPE, FIXNUM_TYPE, etc. // friend object_type * type_of (object * ob); // Print an object. // friend ostream& operator << (ostream& s, object * ob); // Read an object. Returns ob == NULL if end of // file encountered. Defined in parser.cc. // friend istream& operator >> (istream& s, object * & ob); private: // Virtuals to be implemented by subclasses. virtual ostream& print (ostream& s) = 0; // Print object. Does the work for <<. virtual void scavenge() = 0; // Scavenge object during garbage collection. // Called by: friend void gc_mark (object * ob); // Data. public: // Data used by too much code to get access // exactly right easily. Should be more // protected. object_type * type; // Type of the object. bool marked; // Used by garbage // collector; true if // object marked. object * link; // Used to chain together // objects of the same type // on used or free list; // NULL if end of chain. // Used by object allocators // (e.g. // make_symbol) and // garbage collector. protected: // Functions called by derived class object // allocators (e.g. make_symbol) to initialize the // above data components. // Initialize object with a given type. // void init_object (object_type * ty); // Create object without initializing memory. You // must apply init above separately. // object () {} }; inline object_type * type_of (object * ob) { return ob->type; } inline ostream& operator << (ostream& s, object * ob) { return ob->print (s); } inline void object::init_object (object_type * ty) { type = ty; marked = false; link = NULL; } // Announce an error that an object does not have a // given type. May be called with NULL object. // (Defined in obtype, but prototyped here so // obtype.h is not generally needed.) // void type_error (object * ob, object_type * ty); #endif // OBJECT_H