X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Fnasal.h;h=8b6b2c92866e5825dede03f9ba8c7fa9e34b41fe;hb=27a91062bda197ff0e5c3d95f43a2f89c353fdc5;hp=1b8184bcbeb7f50d4e95d2227f19e838c6fa9908;hpb=de6003367d006218782d64b5c0da4d8c8ea8ede0;p=simgear.git diff --git a/simgear/nasal/nasal.h b/simgear/nasal/nasal.h index 1b8184bc..8b6b2c92 100644 --- a/simgear/nasal/nasal.h +++ b/simgear/nasal/nasal.h @@ -16,10 +16,14 @@ extern "C" { #endif typedef struct Context* naContext; - + // The function signature for an extension function: typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args); +// The function signature for an extension function with userdata passed back: +typedef naRef (*naCFunctionU) + (naContext ctx, naRef me, int argc, naRef* args, void* user_data); + // All Nasal code runs under the watch of a naContext: naContext naNewContext(); void naFreeContext(naContext c); @@ -38,10 +42,25 @@ naContext naSubContext(naContext super); void naSetUserData(naContext c, void* p); void* naGetUserData(naContext c) GCC_PURE; +// run GC now (may block) +void naGC(); + // "Save" this object in the context, preventing it (and objects // referenced by it) from being garbage collected. +// TODO do we need a context? It is not used anyhow... void naSave(naContext ctx, naRef obj); +// "Save" this object and get a key which allows do mark the object as free +// later on (with naGCFree). +int naGCSave(naRef obj); + +// Release an object previously passed to naGCSave to allow it being cleaned up +// by the garbage collector. +void naGCRelease(int key); + +// Drop all saved references +void naClearSaved(); + // Similar, but the object is automatically released when the // context next runs native bytecode. Useful for saving off C-space // temporaries to protect them before passing back into a naCall. @@ -84,6 +103,28 @@ naRef naCall(naContext ctx, naRef func, int argc, naRef* args, // naModUnlock() first if the lock is already held. naRef naContinue(naContext ctx); +// Does a naCall() in a given context. Wrapped here to make lock +// tracking easier. Extension functions are called with the lock, but +// we have to release it before making a new naCall(). So rather than +// drop the lock in every extension function that might call back into +// Nasal, we keep a stack depth counter here and only unlock/lock +// around the naCall if it isn't the first one. +naRef naCallMethodCtx( naContext ctx, + naRef code, + naRef self, + int argc, + naRef* args, + naRef locals ); + +// Same as naCallMethodCtx but creates (and afterwards destroyes) a new context +naRef naCallMethod(naRef code, naRef self, int argc, naRef* args, naRef locals); + +typedef void (*naErrorHandler)(naContext); + +// Register a handler to be called if an error is raised during the execution of +// naCallMethodCtx or naCallMethod. +naErrorHandler naSetErrorHandler(naErrorHandler cb); + // Throw an error from the current call stack. This function makes a // longjmp call to a handler in naCall() and DOES NOT RETURN. It is // intended for use in library code that cannot otherwise report an @@ -99,8 +140,8 @@ void naRethrowError(naContext subc); // Retrieve the specified member from the object, respecting the // "parents" array as for "object.field". Returns zero for missing // fields. -int naMember_get(naRef obj, naRef field, naRef* out); -int naMember_cget(naRef obj, const char* field, naRef* out); +int naMember_get(naContext c, naRef obj, naRef field, naRef* out); +int naMember_cget(naContext c, naRef obj, const char* field, naRef* out); // Returns a hash containing functions from the Nasal standard library // Useful for passing as a namespace to an initial function call @@ -119,6 +160,9 @@ naRef naInit_readline(naContext c); naRef naInit_gtk(naContext ctx); naRef naInit_cairo(naContext ctx); +// Returns a hash which can be used to add methods callable on strings +naRef naInit_string(naContext c); + // Context stack inspection, frame zero is the "top" int naStackDepth(naContext ctx); int naGetLine(naContext ctx, int frame); @@ -136,6 +180,9 @@ int naIsCode(naRef r) GCC_PURE; int naIsFunc(naRef r) GCC_PURE; int naIsCCode(naRef r) GCC_PURE; +// Object equality (check for same instance, aka. pointer equality) +int naIsIdentical(naRef l, naRef r) GCC_PURE; + // Allocators/generators: naRef naNil() GCC_PURE; naRef naNum(double num) GCC_PURE; @@ -143,7 +190,19 @@ naRef naNewString(naContext c); naRef naNewVector(naContext c); naRef naNewHash(naContext c); naRef naNewFunc(naContext c, naRef code); + +/** + * Register extension function + * + * @param fptr Pointer to C-function + * @param user_data Optional user data passed back on calling the function + * @param destroy Optional callback called if function gets freed by garbage + * collector to free user data if required. + */ naRef naNewCCode(naContext c, naCFunction fptr); +naRef naNewCCodeU(naContext c, naCFunctionU fptr, void* user_data); +naRef naNewCCodeUD(naContext c, naCFunctionU fptr, void* user_data, + void (*destroy)(void*)); // Some useful conversion/comparison routines int naEqual(naRef a, naRef b) GCC_PURE; @@ -153,20 +212,39 @@ naRef naNumValue(naRef n) GCC_PURE; naRef naStringValue(naContext c, naRef n); // String utilities: -int naStr_len(naRef s); -char* naStr_data(naRef s); -naRef naStr_fromdata(naRef dst, char* data, int len); +int naStr_len(naRef s) GCC_PURE; +char* naStr_data(naRef s) GCC_PURE; +naRef naStr_fromdata(naRef dst, const char* data, int len); naRef naStr_concat(naRef dest, naRef s1, naRef s2); naRef naStr_substr(naRef dest, naRef str, int start, int len); naRef naInternSymbol(naRef sym); +naRef getStringMethods(naContext c); // Vector utilities: int naVec_size(naRef v); naRef naVec_get(naRef v, int i); void naVec_set(naRef vec, int i, naRef o); int naVec_append(naRef vec, naRef o); +void naVec_setsize(naContext c, naRef vec, int sz); + +/** + * Remove and retrieve the first element of the vector. + * + * This operation reduces the size of the vector by one and moves all elements + * by one towards the begin of the vector. + * + * @return The element removed from the begin + */ +naRef naVec_removefirst(naRef vec); + +/** + * Remove and retrieve the last element of the vector. + * + * This operation reduces the size of the vector by one. + * + * @return The element removed from the end + */ naRef naVec_removelast(naRef vec); -void naVec_setsize(naRef vec, int sz); // Hash utilities: int naHash_size(naRef h); @@ -175,30 +253,58 @@ naRef naHash_cget(naRef hash, char* key); void naHash_set(naRef hash, naRef key, naRef val); void naHash_cset(naRef hash, char* key, naRef val); void naHash_delete(naRef hash, naRef key); +/** + * Store the keys in ::hash into the vector at ::dst + * + * @see ::naNewVector + */ void naHash_keys(naRef dst, naRef hash); // Ghost utilities: typedef struct naGhostType { - void (*destroy)(void* ghost); + void(*destroy)(void*); const char* name; + const char*(*get_member)(naContext c, void*, naRef key, naRef* out); + void(*set_member)(naContext c, void*, naRef key, naRef val); } naGhostType; + +/** + * Create a ghost for an object without any attributes. If ::t contains pointers + * to get_member or set_member function they will be ignored. + */ naRef naNewGhost(naContext c, naGhostType* t, void* ghost); +/** + * Create a ghost for an object. This version uses the get_member and set_member + * function pointers in ::t upon trying to get or set a member respectively from + * Nasal. + */ +naRef naNewGhost2(naContext c, naGhostType* t, void* ghost); naGhostType* naGhost_type(naRef ghost); void* naGhost_ptr(naRef ghost); +/** + * Attach a nasal object to the given ghost. Binds the lifetime of @a data to + * the lifetime of the @a ghost. + */ +void naGhost_setData(naRef ghost, naRef data); +/** + * Retrieve the object attached to the @a ghost, previously set with + * naGhost_setData(). + */ +naRef naGhost_data(naRef ghost); int naIsGhost(naRef r); // Acquires a "modification lock" on a context, allowing the C code to // modify Nasal data without fear that such data may be "lost" by the -// garbage collector (nasal data the C stack is not examined in GC!). -// This disallows garbage collection until the current thread can be -// blocked. The lock should be acquired whenever nasal objects are -// being modified. It need not be acquired when only read access is -// needed, PRESUMING that the Nasal data being read is findable by the -// collector (via naSave, for example) and that another Nasal thread -// cannot or will not delete the reference to the data. It MUST NOT -// be acquired by naCFunction's, as those are called with the lock -// already held; acquiring two locks for the same thread will cause a -// deadlock when the GC is invoked. It should be UNLOCKED by +// garbage collector (nasal data on the C stack is not examined in +// GC!). This disallows garbage collection until the current thread +// can be blocked. The lock should be acquired whenever nasal objects +// are being modified. It need not be acquired when only read access +// is needed, PRESUMING that the Nasal data being read is findable by +// the collector (via naSave, for example) and that another Nasal +// thread cannot or will not delete the reference to the data. It +// MUST NOT be acquired by naCFunction's, as those are called with the +// lock already held; acquiring two locks for the same thread will +// cause a deadlock when the GC is invoked. It should be UNLOCKED by // naCFunction's when they are about to do any long term non-nasal // processing and/or blocking I/O. Note that naModLock() may need to // block to allow garbage collection to occur, and that garbage