jpayne@69: /* jpayne@69: * tclOOInt.h -- jpayne@69: * jpayne@69: * This file contains the structure definitions and some of the function jpayne@69: * declarations for the object-system (NB: not Tcl_Obj, but ::oo). jpayne@69: * jpayne@69: * Copyright (c) 2006-2012 by Donal K. Fellows jpayne@69: * jpayne@69: * See the file "license.terms" for information on usage and redistribution of jpayne@69: * this file, and for a DISCLAIMER OF ALL WARRANTIES. jpayne@69: */ jpayne@69: jpayne@69: #ifndef TCL_OO_INTERNAL_H jpayne@69: #define TCL_OO_INTERNAL_H 1 jpayne@69: jpayne@69: #include "tclInt.h" jpayne@69: #include "tclOO.h" jpayne@69: jpayne@69: /* jpayne@69: * Hack to make things work with Objective C. Note that ObjC isn't really jpayne@69: * supported, but we don't want to to be actively hostile to it. [Bug 2163447] jpayne@69: */ jpayne@69: jpayne@69: #ifdef __OBJC__ jpayne@69: #define Class TclOOClass jpayne@69: #define Object TclOOObject jpayne@69: #endif /* __OBJC__ */ jpayne@69: jpayne@69: /* jpayne@69: * Forward declarations. jpayne@69: */ jpayne@69: jpayne@69: struct CallChain; jpayne@69: struct Class; jpayne@69: struct Foundation; jpayne@69: struct Object; jpayne@69: jpayne@69: /* jpayne@69: * The data that needs to be stored per method. This record is used to collect jpayne@69: * information about all sorts of methods, including forwards, constructors jpayne@69: * and destructors. jpayne@69: */ jpayne@69: jpayne@69: typedef struct Method { jpayne@69: const Tcl_MethodType *typePtr; jpayne@69: /* The type of method. If NULL, this is a jpayne@69: * special flag record which is just used for jpayne@69: * the setting of the flags field. */ jpayne@69: int refCount; jpayne@69: void *clientData; /* Type-specific data. */ jpayne@69: Tcl_Obj *namePtr; /* Name of the method. */ jpayne@69: struct Object *declaringObjectPtr; jpayne@69: /* The object that declares this method, or jpayne@69: * NULL if it was declared by a class. */ jpayne@69: struct Class *declaringClassPtr; jpayne@69: /* The class that declares this method, or jpayne@69: * NULL if it was declared directly on an jpayne@69: * object. */ jpayne@69: int flags; /* Assorted flags. Includes whether this jpayne@69: * method is public/exported or not. */ jpayne@69: } Method; jpayne@69: jpayne@69: /* jpayne@69: * Pre- and post-call callbacks, to allow procedure-like methods to be fine jpayne@69: * tuned in their behaviour. jpayne@69: */ jpayne@69: jpayne@69: typedef int (TclOO_PreCallProc)(void *clientData, Tcl_Interp *interp, jpayne@69: Tcl_ObjectContext context, Tcl_CallFrame *framePtr, int *isFinished); jpayne@69: typedef int (TclOO_PostCallProc)(void *clientData, Tcl_Interp *interp, jpayne@69: Tcl_ObjectContext context, Tcl_Namespace *namespacePtr, int result); jpayne@69: typedef void (TclOO_PmCDDeleteProc)(void *clientData); jpayne@69: typedef void *(TclOO_PmCDCloneProc)(void *clientData); jpayne@69: jpayne@69: /* jpayne@69: * Procedure-like methods have the following extra information. jpayne@69: */ jpayne@69: jpayne@69: typedef struct ProcedureMethod { jpayne@69: int version; /* Version of this structure. Currently must jpayne@69: * be 0. */ jpayne@69: Proc *procPtr; /* Core of the implementation of the method; jpayne@69: * includes the argument definition and the jpayne@69: * body bytecodes. */ jpayne@69: int flags; /* Flags to control features. */ jpayne@69: int refCount; jpayne@69: void *clientData; jpayne@69: TclOO_PmCDDeleteProc *deleteClientdataProc; jpayne@69: TclOO_PmCDCloneProc *cloneClientdataProc; jpayne@69: ProcErrorProc *errProc; /* Replacement error handler. */ jpayne@69: TclOO_PreCallProc *preCallProc; jpayne@69: /* Callback to allow for additional setup jpayne@69: * before the method executes. */ jpayne@69: TclOO_PostCallProc *postCallProc; jpayne@69: /* Callback to allow for additional cleanup jpayne@69: * after the method executes. */ jpayne@69: GetFrameInfoValueProc *gfivProc; jpayne@69: /* Callback to allow for fine tuning of how jpayne@69: * the method reports itself. */ jpayne@69: } ProcedureMethod; jpayne@69: jpayne@69: #define TCLOO_PROCEDURE_METHOD_VERSION 0 jpayne@69: jpayne@69: /* jpayne@69: * Flags for use in a ProcedureMethod. jpayne@69: * jpayne@69: * When the USE_DECLARER_NS flag is set, the method will use the namespace of jpayne@69: * the object or class that declared it (or the clone of it, if it was from jpayne@69: * such that the implementation of the method came to the particular use) jpayne@69: * instead of the namespace of the object on which the method was invoked. jpayne@69: * This flag must be distinct from all others that are associated with jpayne@69: * methods. jpayne@69: */ jpayne@69: jpayne@69: #define USE_DECLARER_NS 0x80 jpayne@69: jpayne@69: /* jpayne@69: * Forwarded methods have the following extra information. jpayne@69: */ jpayne@69: jpayne@69: typedef struct ForwardMethod { jpayne@69: Tcl_Obj *prefixObj; /* The list of values to use to replace the jpayne@69: * object and method name with. Will be a jpayne@69: * non-empty list. */ jpayne@69: } ForwardMethod; jpayne@69: jpayne@69: /* jpayne@69: * Helper definitions that declare a "list" array. The two varieties are jpayne@69: * either optimized for simplicity (in the case that the whole array is jpayne@69: * typically assigned at once) or efficiency (in the case that the array is jpayne@69: * expected to be expanded over time). These lists are designed to be iterated jpayne@69: * over with the help of the FOREACH macro (see later in this file). jpayne@69: * jpayne@69: * The "num" field always counts the number of listType_t elements used in the jpayne@69: * "list" field. When a "size" field exists, it describes how many elements jpayne@69: * are present in the list; when absent, exactly "num" elements are present. jpayne@69: */ jpayne@69: jpayne@69: #define LIST_STATIC(listType_t) \ jpayne@69: struct { int num; listType_t *list; } jpayne@69: #define LIST_DYNAMIC(listType_t) \ jpayne@69: struct { int num, size; listType_t *list; } jpayne@69: jpayne@69: /* jpayne@69: * Now, the definition of what an object actually is. jpayne@69: */ jpayne@69: jpayne@69: typedef struct Object { jpayne@69: struct Foundation *fPtr; /* The basis for the object system. Putting jpayne@69: * this here allows the avoidance of quite a jpayne@69: * lot of hash lookups on the critical path jpayne@69: * for object invocation and creation. */ jpayne@69: Tcl_Namespace *namespacePtr;/* This object's namespace. */ jpayne@69: Tcl_Command command; /* Reference to this object's public jpayne@69: * command. */ jpayne@69: Tcl_Command myCommand; /* Reference to this object's internal jpayne@69: * command. */ jpayne@69: struct Class *selfCls; /* This object's class. */ jpayne@69: Tcl_HashTable *methodsPtr; /* Object-local Tcl_Obj (method name) to jpayne@69: * Method* mapping. */ jpayne@69: LIST_STATIC(struct Class *) mixins; jpayne@69: /* Classes mixed into this object. */ jpayne@69: LIST_STATIC(Tcl_Obj *) filters; jpayne@69: /* List of filter names. */ jpayne@69: struct Class *classPtr; /* This is non-NULL for all classes, and NULL jpayne@69: * for everything else. It points to the class jpayne@69: * structure. */ jpayne@69: int refCount; /* Number of strong references to this object. jpayne@69: * Note that there may be many more weak jpayne@69: * references; this mechanism exists to jpayne@69: * avoid Tcl_Preserve. */ jpayne@69: int flags; jpayne@69: int creationEpoch; /* Unique value to make comparisons of objects jpayne@69: * easier. */ jpayne@69: int epoch; /* Per-object epoch, incremented when the way jpayne@69: * an object should resolve call chains is jpayne@69: * changed. */ jpayne@69: Tcl_HashTable *metadataPtr; /* Mapping from pointers to metadata type to jpayne@69: * the ClientData values that are the values jpayne@69: * of each piece of attached metadata. This jpayne@69: * field starts out as NULL and is only jpayne@69: * allocated if metadata is attached. */ jpayne@69: Tcl_Obj *cachedNameObj; /* Cache of the name of the object. */ jpayne@69: Tcl_HashTable *chainCache; /* Place to keep unused contexts. This table jpayne@69: * is indexed by method name as Tcl_Obj. */ jpayne@69: Tcl_ObjectMapMethodNameProc *mapMethodNameProc; jpayne@69: /* Function to allow remapping of method jpayne@69: * names. For itcl-ng. */ jpayne@69: LIST_STATIC(Tcl_Obj *) variables; jpayne@69: } Object; jpayne@69: jpayne@69: #define OBJECT_DESTRUCTING 1 /* Indicates that an object is being or has jpayne@69: * been destroyed */ jpayne@69: #define DESTRUCTOR_CALLED 2 /* Indicates that evaluation of destructor script for the jpayne@69: object has began */ jpayne@69: #define OO_UNUSED_4 4 /* No longer used. */ jpayne@69: #define ROOT_OBJECT 0x1000 /* Flag to say that this object is the root of jpayne@69: * the class hierarchy and should be treated jpayne@69: * specially during teardown. */ jpayne@69: #define FILTER_HANDLING 0x2000 /* Flag set when the object is processing a jpayne@69: * filter; when set, filters are *not* jpayne@69: * processed on the object, preventing nasty jpayne@69: * recursive filtering problems. */ jpayne@69: #define USE_CLASS_CACHE 0x4000 /* Flag set to say that the object is a pure jpayne@69: * instance of the class, and has had nothing jpayne@69: * added that changes the dispatch chain (i.e. jpayne@69: * no methods, mixins, or filters. */ jpayne@69: #define ROOT_CLASS 0x8000 /* Flag to say that this object is the root jpayne@69: * class of classes, and should be treated jpayne@69: * specially during teardown (and in a few jpayne@69: * other spots). */ jpayne@69: #define FORCE_UNKNOWN 0x10000 /* States that we are *really* looking up the jpayne@69: * unknown method handler at that point. */ jpayne@69: #define DONT_DELETE 0x20000 /* Inhibit deletion of this object. */ jpayne@69: jpayne@69: /* jpayne@69: * And the definition of a class. Note that every class also has an associated jpayne@69: * object, through which it is manipulated. jpayne@69: */ jpayne@69: jpayne@69: typedef struct Class { jpayne@69: Object *thisPtr; /* Reference to the object associated with jpayne@69: * this class. */ jpayne@69: int flags; /* Assorted flags. */ jpayne@69: LIST_STATIC(struct Class *) superclasses; jpayne@69: /* List of superclasses, used for generation jpayne@69: * of method call chains. */ jpayne@69: LIST_DYNAMIC(struct Class *) subclasses; jpayne@69: /* List of subclasses, used to ensure deletion jpayne@69: * of dependent entities happens properly when jpayne@69: * the class itself is deleted. */ jpayne@69: LIST_DYNAMIC(Object *) instances; jpayne@69: /* List of instances, used to ensure deletion jpayne@69: * of dependent entities happens properly when jpayne@69: * the class itself is deleted. */ jpayne@69: LIST_STATIC(Tcl_Obj *) filters; jpayne@69: /* List of filter names, used for generation jpayne@69: * of method call chains. */ jpayne@69: LIST_STATIC(struct Class *) mixins; jpayne@69: /* List of mixin classes, used for generation jpayne@69: * of method call chains. */ jpayne@69: LIST_DYNAMIC(struct Class *) mixinSubs; jpayne@69: /* List of classes that this class is mixed jpayne@69: * into, used to ensure deletion of dependent jpayne@69: * entities happens properly when the class jpayne@69: * itself is deleted. */ jpayne@69: Tcl_HashTable classMethods; /* Hash table of all methods. Hash maps from jpayne@69: * the (Tcl_Obj*) method name to the (Method*) jpayne@69: * method record. */ jpayne@69: Method *constructorPtr; /* Method record of the class constructor (if jpayne@69: * any). */ jpayne@69: Method *destructorPtr; /* Method record of the class destructor (if jpayne@69: * any). */ jpayne@69: Tcl_HashTable *metadataPtr; /* Mapping from pointers to metadata type to jpayne@69: * the ClientData values that are the values jpayne@69: * of each piece of attached metadata. This jpayne@69: * field starts out as NULL and is only jpayne@69: * allocated if metadata is attached. */ jpayne@69: struct CallChain *constructorChainPtr; jpayne@69: struct CallChain *destructorChainPtr; jpayne@69: Tcl_HashTable *classChainCache; jpayne@69: /* Places where call chains are stored. For jpayne@69: * constructors, the class chain is always jpayne@69: * used. For destructors and ordinary methods, jpayne@69: * the class chain is only used when the jpayne@69: * object doesn't override with its own mixins jpayne@69: * (and filters and method implementations for jpayne@69: * when getting method chains). */ jpayne@69: LIST_STATIC(Tcl_Obj *) variables; jpayne@69: } Class; jpayne@69: jpayne@69: /* jpayne@69: * The foundation of the object system within an interpreter contains jpayne@69: * references to the key classes and namespaces, together with a few other jpayne@69: * useful bits and pieces. Probably ought to eventually go in the Interp jpayne@69: * structure itself. jpayne@69: */ jpayne@69: jpayne@69: typedef struct ThreadLocalData { jpayne@69: int nsCount; /* Epoch counter is used for keeping jpayne@69: * the values used in Tcl_Obj internal jpayne@69: * representations sane. Must be thread-local jpayne@69: * because Tcl_Objs can cross interpreter jpayne@69: * boundaries within a thread (objects don't jpayne@69: * generally cross threads). */ jpayne@69: } ThreadLocalData; jpayne@69: jpayne@69: typedef struct Foundation { jpayne@69: Tcl_Interp *interp; jpayne@69: Class *objectCls; /* The root of the object system. */ jpayne@69: Class *classCls; /* The class of all classes. */ jpayne@69: Tcl_Namespace *ooNs; /* ::oo namespace. */ jpayne@69: Tcl_Namespace *defineNs; /* Namespace containing special commands for jpayne@69: * manipulating objects and classes. The jpayne@69: * "oo::define" command acts as a special kind jpayne@69: * of ensemble for this namespace. */ jpayne@69: Tcl_Namespace *objdefNs; /* Namespace containing special commands for jpayne@69: * manipulating objects and classes. The jpayne@69: * "oo::objdefine" command acts as a special jpayne@69: * kind of ensemble for this namespace. */ jpayne@69: Tcl_Namespace *helpersNs; /* Namespace containing the commands that are jpayne@69: * only valid when executing inside a jpayne@69: * procedural method. */ jpayne@69: int epoch; /* Used to invalidate method chains when the jpayne@69: * class structure changes. */ jpayne@69: ThreadLocalData *tsdPtr; /* Counter so we can allocate a unique jpayne@69: * namespace to each object. */ jpayne@69: Tcl_Obj *unknownMethodNameObj; jpayne@69: /* Shared object containing the name of the jpayne@69: * unknown method handler method. */ jpayne@69: Tcl_Obj *constructorName; /* Shared object containing the "name" of a jpayne@69: * constructor. */ jpayne@69: Tcl_Obj *destructorName; /* Shared object containing the "name" of a jpayne@69: * destructor. */ jpayne@69: Tcl_Obj *clonedName; /* Shared object containing the name of a jpayne@69: * "" pseudo-constructor. */ jpayne@69: Tcl_Obj *defineName; /* Fully qualified name of oo::define. */ jpayne@69: } Foundation; jpayne@69: jpayne@69: /* jpayne@69: * A call context structure is built when a method is called. It contains the jpayne@69: * chain of method implementations that are to be invoked by a particular jpayne@69: * call, and the process of calling walks the chain, with the [next] command jpayne@69: * proceeding to the next entry in the chain. jpayne@69: */ jpayne@69: jpayne@69: #define CALL_CHAIN_STATIC_SIZE 4 jpayne@69: jpayne@69: struct MInvoke { jpayne@69: Method *mPtr; /* Reference to the method implementation jpayne@69: * record. */ jpayne@69: int isFilter; /* Whether this is a filter invocation. */ jpayne@69: Class *filterDeclarer; /* What class decided to add the filter; if jpayne@69: * NULL, it was added by the object. */ jpayne@69: }; jpayne@69: jpayne@69: typedef struct CallChain { jpayne@69: int objectCreationEpoch; /* The object's creation epoch. Note that the jpayne@69: * object reference is not stored in the call jpayne@69: * chain; it is in the call context. */ jpayne@69: int objectEpoch; /* Local (object structure) epoch counter jpayne@69: * snapshot. */ jpayne@69: int epoch; /* Global (class structure) epoch counter jpayne@69: * snapshot. */ jpayne@69: int flags; /* Assorted flags, see below. */ jpayne@69: int refCount; /* Reference count. */ jpayne@69: int numChain; /* Size of the call chain. */ jpayne@69: struct MInvoke *chain; /* Array of call chain entries. May point to jpayne@69: * staticChain if the number of entries is jpayne@69: * small. */ jpayne@69: struct MInvoke staticChain[CALL_CHAIN_STATIC_SIZE]; jpayne@69: } CallChain; jpayne@69: jpayne@69: typedef struct CallContext { jpayne@69: Object *oPtr; /* The object associated with this call. */ jpayne@69: int index; /* Index into the call chain of the currently jpayne@69: * executing method implementation. */ jpayne@69: int skip; /* Current number of arguments to skip; can jpayne@69: * vary depending on whether it is a direct jpayne@69: * method call or a continuation via the jpayne@69: * [next] command. */ jpayne@69: CallChain *callPtr; /* The actual call chain. */ jpayne@69: } CallContext; jpayne@69: jpayne@69: /* jpayne@69: * Bits for the 'flags' field of the call chain. jpayne@69: */ jpayne@69: jpayne@69: #define PUBLIC_METHOD 0x01 /* This is a public (exported) method. */ jpayne@69: #define PRIVATE_METHOD 0x02 /* This is a private (class's direct instances jpayne@69: * only) method. Supports itcl. */ jpayne@69: #define OO_UNKNOWN_METHOD 0x04 /* This is an unknown method. */ jpayne@69: #define CONSTRUCTOR 0x08 /* This is a constructor. */ jpayne@69: #define DESTRUCTOR 0x10 /* This is a destructor. */ jpayne@69: jpayne@69: /* jpayne@69: * Structure containing definition information about basic class methods. jpayne@69: */ jpayne@69: jpayne@69: typedef struct { jpayne@69: const char *name; /* Name of the method in question. */ jpayne@69: int isPublic; /* Whether the method is public by default. */ jpayne@69: Tcl_MethodType definition; /* How to call the method. */ jpayne@69: } DeclaredClassMethod; jpayne@69: jpayne@69: /* jpayne@69: *---------------------------------------------------------------- jpayne@69: * Commands relating to OO support. jpayne@69: *---------------------------------------------------------------- jpayne@69: */ jpayne@69: jpayne@69: MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); jpayne@69: MODULE_SCOPE int TclOODefineObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOOObjDefObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineConstructorObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineDeleteMethodObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineDestructorObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineExportObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineForwardObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineMethodObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineRenameMethodObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineUnexportObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineClassObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOODefineSelfObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOOUnknownDefinition(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOOCopyObjectCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOONextObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOONextToObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOOSelfObjCmd(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const *objv); jpayne@69: jpayne@69: /* jpayne@69: * Method implementations (in tclOOBasic.c). jpayne@69: */ jpayne@69: jpayne@69: MODULE_SCOPE int TclOO_Class_Constructor(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Class_Create(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Class_CreateNs(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Class_New(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Object_Destroy(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Object_Eval(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Object_LinkVar(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Object_Unknown(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: MODULE_SCOPE int TclOO_Object_VarName(void *clientData, jpayne@69: Tcl_Interp *interp, Tcl_ObjectContext context, jpayne@69: int objc, Tcl_Obj *const *objv); jpayne@69: jpayne@69: /* jpayne@69: * Private definitions, some of which perhaps ought to be exposed properly or jpayne@69: * maybe just put in the internal stubs table. jpayne@69: */ jpayne@69: jpayne@69: MODULE_SCOPE void TclOOAddToInstances(Object *oPtr, Class *clsPtr); jpayne@69: MODULE_SCOPE void TclOOAddToMixinSubs(Class *subPtr, Class *mixinPtr); jpayne@69: MODULE_SCOPE void TclOOAddToSubclasses(Class *subPtr, Class *superPtr); jpayne@69: MODULE_SCOPE Class * TclOOAllocClass(Tcl_Interp *interp, jpayne@69: Object *useThisObj); jpayne@69: MODULE_SCOPE int TclNRNewObjectInstance(Tcl_Interp *interp, jpayne@69: Tcl_Class cls, const char *nameStr, jpayne@69: const char *nsNameStr, int objc, jpayne@69: Tcl_Obj *const *objv, int skip, jpayne@69: Tcl_Object *objectPtr); jpayne@69: MODULE_SCOPE Object * TclNewObjectInstanceCommon(Tcl_Interp *interp, jpayne@69: Class *classPtr, jpayne@69: const char *nameStr, jpayne@69: const char *nsNameStr); jpayne@69: MODULE_SCOPE int TclOODecrRefCount(Object *oPtr); jpayne@69: MODULE_SCOPE int TclOOObjectDestroyed(Object *oPtr); jpayne@69: MODULE_SCOPE int TclOODefineSlots(Foundation *fPtr); jpayne@69: MODULE_SCOPE void TclOODeleteChain(CallChain *callPtr); jpayne@69: MODULE_SCOPE void TclOODeleteChainCache(Tcl_HashTable *tablePtr); jpayne@69: MODULE_SCOPE void TclOODeleteContext(CallContext *contextPtr); jpayne@69: MODULE_SCOPE void TclOODeleteDescendants(Tcl_Interp *interp, jpayne@69: Object *oPtr); jpayne@69: MODULE_SCOPE void TclOODelMethodRef(Method *method); jpayne@69: MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr, jpayne@69: Tcl_Obj *methodNameObj, int flags, jpayne@69: Tcl_Obj *cacheInThisObj); jpayne@69: MODULE_SCOPE CallChain *TclOOGetStereotypeCallChain(Class *clsPtr, jpayne@69: Tcl_Obj *methodNameObj, int flags); jpayne@69: MODULE_SCOPE Foundation *TclOOGetFoundation(Tcl_Interp *interp); jpayne@69: MODULE_SCOPE Tcl_Obj * TclOOGetFwdFromMethod(Method *mPtr); jpayne@69: MODULE_SCOPE Proc * TclOOGetProcFromMethod(Method *mPtr); jpayne@69: MODULE_SCOPE Tcl_Obj * TclOOGetMethodBody(Method *mPtr); jpayne@69: MODULE_SCOPE int TclOOGetSortedClassMethodList(Class *clsPtr, jpayne@69: int flags, const char ***stringsPtr); jpayne@69: MODULE_SCOPE int TclOOGetSortedMethodList(Object *oPtr, int flags, jpayne@69: const char ***stringsPtr); jpayne@69: MODULE_SCOPE int TclOOInit(Tcl_Interp *interp); jpayne@69: MODULE_SCOPE void TclOOInitInfo(Tcl_Interp *interp); jpayne@69: MODULE_SCOPE int TclOOInvokeContext(void *clientData, jpayne@69: Tcl_Interp *interp, int objc, jpayne@69: Tcl_Obj *const objv[]); jpayne@69: MODULE_SCOPE int TclNRObjectContextInvokeNext(Tcl_Interp *interp, jpayne@69: Tcl_ObjectContext context, int objc, jpayne@69: Tcl_Obj *const *objv, int skip); jpayne@69: MODULE_SCOPE void TclOONewBasicMethod(Tcl_Interp *interp, Class *clsPtr, jpayne@69: const DeclaredClassMethod *dcm); jpayne@69: MODULE_SCOPE Tcl_Obj * TclOOObjectName(Tcl_Interp *interp, Object *oPtr); jpayne@69: MODULE_SCOPE void TclOOReleaseClassContents(Tcl_Interp *interp, jpayne@69: Object *oPtr); jpayne@69: MODULE_SCOPE int TclOORemoveFromInstances(Object *oPtr, Class *clsPtr); jpayne@69: MODULE_SCOPE int TclOORemoveFromMixins(Class *mixinPtr, Object *oPtr); jpayne@69: MODULE_SCOPE int TclOORemoveFromMixinSubs(Class *subPtr, jpayne@69: Class *mixinPtr); jpayne@69: MODULE_SCOPE int TclOORemoveFromSubclasses(Class *subPtr, jpayne@69: Class *superPtr); jpayne@69: MODULE_SCOPE Tcl_Obj * TclOORenderCallChain(Tcl_Interp *interp, jpayne@69: CallChain *callPtr); jpayne@69: MODULE_SCOPE void TclOOStashContext(Tcl_Obj *objPtr, jpayne@69: CallContext *contextPtr); jpayne@69: MODULE_SCOPE void TclOOSetupVariableResolver(Tcl_Namespace *nsPtr); jpayne@69: jpayne@69: /* jpayne@69: * Include all the private API, generated from tclOO.decls. jpayne@69: */ jpayne@69: jpayne@69: #include "tclOOIntDecls.h" jpayne@69: jpayne@69: /* jpayne@69: * Alternatives to Tcl_Preserve/Tcl_EventuallyFree/Tcl_Release. jpayne@69: */ jpayne@69: jpayne@69: #define AddRef(ptr) ((ptr)->refCount++) jpayne@69: jpayne@69: /* jpayne@69: * A convenience macro for iterating through the lists used in the internal jpayne@69: * memory management of objects. jpayne@69: * REQUIRES DECLARATION: int i; jpayne@69: */ jpayne@69: jpayne@69: #define FOREACH(var,ary) \ jpayne@69: for(i=0 ; i<(ary).num; i++) if ((ary).list[i] == NULL) { \ jpayne@69: continue; \ jpayne@69: } else if ((var) = (ary).list[i], 1) jpayne@69: jpayne@69: /* jpayne@69: * Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS jpayne@69: * sets up the declarations needed for the main macro, FOREACH_HASH, which jpayne@69: * does the actual iteration. FOREACH_HASH_VALUE is a restricted version that jpayne@69: * only iterates over values. jpayne@69: */ jpayne@69: jpayne@69: #define FOREACH_HASH_DECLS \ jpayne@69: Tcl_HashEntry *hPtr;Tcl_HashSearch search jpayne@69: #define FOREACH_HASH(key,val,tablePtr) \ jpayne@69: for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \ jpayne@69: ((key)=(void *)Tcl_GetHashKey((tablePtr),hPtr),\ jpayne@69: (val)=Tcl_GetHashValue(hPtr),1):0; hPtr=Tcl_NextHashEntry(&search)) jpayne@69: #define FOREACH_HASH_VALUE(val,tablePtr) \ jpayne@69: for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \ jpayne@69: ((val)=Tcl_GetHashValue(hPtr),1):0;hPtr=Tcl_NextHashEntry(&search)) jpayne@69: jpayne@69: /* jpayne@69: * Convenience macro for duplicating a list. Needs no external declaration, jpayne@69: * but all arguments are used multiple times and so must have no side effects. jpayne@69: */ jpayne@69: jpayne@69: #undef DUPLICATE /* prevent possible conflict with definition in WINAPI nb30.h */ jpayne@69: #define DUPLICATE(target,source,type) \ jpayne@69: do { \ jpayne@69: size_t len = sizeof(type) * ((target).num=(source).num);\ jpayne@69: if (len != 0) { \ jpayne@69: memcpy(((target).list=(type*)ckalloc(len)), (source).list, len); \ jpayne@69: } else { \ jpayne@69: (target).list = NULL; \ jpayne@69: } \ jpayne@69: } while(0) jpayne@69: jpayne@69: #endif /* TCL_OO_INTERNAL_H */ jpayne@69: jpayne@69: /* jpayne@69: * Local Variables: jpayne@69: * mode: c jpayne@69: * c-basic-offset: 4 jpayne@69: * fill-column: 78 jpayne@69: * End: jpayne@69: */