]> git.mxchange.org Git - simgear.git/blob - simgear/nasal/nasal.h
cppbind::Ghost: improve compiler error message for wrong usage.
[simgear.git] / simgear / nasal / nasal.h
1 #ifndef _NASAL_H
2 #define _NASAL_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #include "naref.h"
8
9 #if __GNUC__ > 2
10 /* This marks the function as having no side effects and depending on
11  * nothing but its arguments, which allows the optimizer to avoid
12  * duplicate calls to naNil(). */
13 #define GCC_PURE __attribute__((__pure__))
14 #else
15 #define GCC_PURE
16 #endif
17
18 typedef struct Context* naContext;
19
20 // The function signature for an extension function:
21 typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args);
22
23 // The function signature for an extension function with userdata passed back:
24 typedef naRef (*naCFunctionU)
25               (naContext ctx, naRef me, int argc, naRef* args, void* user_data);
26
27 // All Nasal code runs under the watch of a naContext:
28 naContext naNewContext();
29 void naFreeContext(naContext c);
30
31 // Use this when making a call to a new context "underneath" a
32 // preexisting context on the same stack.  It allows stack walking to
33 // see through the boundary, and eliminates the need to release the
34 // mod lock (i.e. must be called with the mod lock held!)
35 naContext naSubContext(naContext super);
36
37 // The naContext supports a user data pointer that can be used to
38 // store data specific to an naCall invocation without exposing it to
39 // Nasal as a ghost.  FIXME: this API is semi-dangerous, there is no
40 // provision for sharing it, nor for validating the source or type of
41 // the pointer returned.
42 void naSetUserData(naContext c, void* p);
43 void* naGetUserData(naContext c) GCC_PURE;
44
45 // run GC now (may block)
46 void naGC();
47
48 // "Save" this object in the context, preventing it (and objects
49 // referenced by it) from being garbage collected.
50 // TODO do we need a context? It is not used anyhow...
51 void naSave(naContext ctx, naRef obj);
52
53 // "Save" this object and get a key which allows do mark the object as free
54 // later on (with naGCFree).
55 int naGCSave(naRef obj);
56
57 // Release an object previously passed to naGCSave to allow it being cleaned up
58 // by the garbage collector.
59 void naGCRelease(int key);
60
61 // Drop all saved references
62 void naClearSaved();
63
64 // Similar, but the object is automatically released when the
65 // context next runs native bytecode.  Useful for saving off C-space
66 // temporaries to protect them before passing back into a naCall.
67 void naTempSave(naContext c, naRef r);
68
69 // Parse a buffer in memory into a code object.  The srcFile parameter
70 // is a Nasal string representing the "file" from which the code is
71 // read.  The "first line" is typically 1, but is settable for
72 // situations where the Nasal code is embedded in another context with
73 // its own numbering convetions.  If an error occurs, returns nil and
74 // sets the errLine pointer to point to the line at fault.  The string
75 // representation of the error can be retrieved with naGetError() on
76 // the context.
77 naRef naParseCode(naContext c, naRef srcFile, int firstLine,
78                   char* buf, int len, int* errLine);
79
80 // Binds a bare code object (as returned from naParseCode) with a
81 // closure object (a hash) to act as the outer scope / namespace.
82 naRef naBindFunction(naContext ctx, naRef code, naRef closure);
83
84 // Similar, but it binds to the current context's closure (i.e. the
85 // namespace at the top of the current call stack).
86 naRef naBindToContext(naContext ctx, naRef code);
87
88 // Call a code or function object with the specified arguments "on"
89 // the specified object and using the specified hash for the local
90 // variables.  Passing a null args array skips the parameter variables
91 // (e.g. "arg") assignments; to get a zero-length arg instead, pass in
92 // argc==0 and a non-null args vector.  The obj or locals parameters
93 // may be nil.  Will attempt to acquire the mod lock, so call
94 // naModUnlock() first if the lock is already held.
95 naRef naCall(naContext ctx, naRef func, int argc, naRef* args,
96              naRef obj, naRef locals);
97
98 // As naCall(), but continues execution at the operation after a
99 // previous die() call or runtime error.  Useful to do "yield"
100 // semantics, leaving the context in a condition where it can be
101 // restarted from C code.  Cannot be used currently to restart a
102 // failed operation.  Will attempt to acquire the mod lock, so call
103 // naModUnlock() first if the lock is already held.
104 naRef naContinue(naContext ctx);
105
106 // Does a naCall() in a given context.  Wrapped here to make lock
107 // tracking easier.  Extension functions are called with the lock, but
108 // we have to release it before making a new naCall().  So rather than
109 // drop the lock in every extension function that might call back into
110 // Nasal, we keep a stack depth counter here and only unlock/lock
111 // around the naCall if it isn't the first one.
112 naRef naCallMethodCtx( naContext ctx,
113                        naRef code,
114                        naRef self,
115                        int argc,
116                        naRef* args,
117                        naRef locals );
118
119 // Same as naCallMethodCtx but creates (and afterwards destroyes) a new context
120 naRef naCallMethod(naRef code, naRef self, int argc, naRef* args, naRef locals);
121
122 typedef void (*naErrorHandler)(naContext);
123
124 // Register a handler to be called if an error is raised during the execution of
125 // naCallMethodCtx or naCallMethod.
126 naErrorHandler naSetErrorHandler(naErrorHandler cb);
127
128 // Throw an error from the current call stack.  This function makes a
129 // longjmp call to a handler in naCall() and DOES NOT RETURN.  It is
130 // intended for use in library code that cannot otherwise report an
131 // error via the return value, and MUST be used carefully.  If in
132 // doubt, return naNil() as your error condition.  Works like
133 // printf().
134 void naRuntimeError(naContext c, const char* fmt, ...);
135
136 // "Re-throws" a runtime error caught from the subcontext.  Acts as a
137 // naRuntimeError() called on the parent context.  Does not return.
138 void naRethrowError(naContext subc);
139
140 // Retrieve the specified member from the object, respecting the
141 // "parents" array as for "object.field".  Returns zero for missing
142 // fields.
143 int naMember_get(naContext c, naRef obj, naRef field, naRef* out);
144 int naMember_cget(naContext c, naRef obj, const char* field, naRef* out);
145
146 // Returns a hash containing functions from the Nasal standard library
147 // Useful for passing as a namespace to an initial function call
148 naRef naInit_std(naContext c);
149
150 // Ditto, for other core libraries
151 naRef naInit_math(naContext c);
152 naRef naInit_bits(naContext c);
153 naRef naInit_io(naContext c);
154 naRef naInit_regex(naContext c);
155 naRef naInit_unix(naContext c);
156 naRef naInit_thread(naContext c);
157 naRef naInit_utf8(naContext c);
158 naRef naInit_sqlite(naContext c);
159 naRef naInit_readline(naContext c);
160 naRef naInit_gtk(naContext ctx);
161 naRef naInit_cairo(naContext ctx);
162
163 // Returns a hash which can be used to add methods callable on strings
164 naRef naInit_string(naContext c);
165
166 // Context stack inspection, frame zero is the "top"
167 int naStackDepth(naContext ctx);
168 int naGetLine(naContext ctx, int frame);
169 naRef naGetSourceFile(naContext ctx, int frame);
170 char* naGetError(naContext ctx);
171
172 // Type predicates
173 int naIsNil(naRef r) GCC_PURE;
174 int naIsNum(naRef r) GCC_PURE;
175 int naIsString(naRef r) GCC_PURE;
176 int naIsScalar(naRef r) GCC_PURE;
177 int naIsVector(naRef r) GCC_PURE;
178 int naIsHash(naRef r) GCC_PURE;
179 int naIsCode(naRef r) GCC_PURE;
180 int naIsFunc(naRef r) GCC_PURE;
181 int naIsCCode(naRef r) GCC_PURE;
182
183 // Object equality (check for same instance, aka. pointer equality)
184 int naIsIdentical(naRef l, naRef r) GCC_PURE;
185
186 // Allocators/generators:
187 naRef naNil() GCC_PURE;
188 naRef naNum(double num) GCC_PURE;
189 naRef naNewString(naContext c);
190 naRef naNewVector(naContext c);
191 naRef naNewHash(naContext c);
192 naRef naNewFunc(naContext c, naRef code);
193
194 /**
195  * Register extension function
196  *
197  * @param fptr      Pointer to C-function
198  * @param user_data Optional user data passed back on calling the function
199  * @param destroy   Optional callback called if function gets freed by garbage
200  *                  collector to free user data if required.
201  */
202 naRef naNewCCode(naContext c, naCFunction fptr);
203 naRef naNewCCodeU(naContext c, naCFunctionU fptr, void* user_data);
204 naRef naNewCCodeUD(naContext c, naCFunctionU fptr, void* user_data,
205                                                    void (*destroy)(void*));
206
207 // Some useful conversion/comparison routines
208 int naEqual(naRef a, naRef b) GCC_PURE;
209 int naStrEqual(naRef a, naRef b) GCC_PURE;
210 int naTrue(naRef b) GCC_PURE;
211 naRef naNumValue(naRef n) GCC_PURE;
212 naRef naStringValue(naContext c, naRef n);
213
214 // String utilities:
215 int naStr_len(naRef s) GCC_PURE;
216 char* naStr_data(naRef s) GCC_PURE;
217 naRef naStr_fromdata(naRef dst, const char* data, int len);
218 naRef naStr_concat(naRef dest, naRef s1, naRef s2);
219 naRef naStr_substr(naRef dest, naRef str, int start, int len);
220 naRef naInternSymbol(naRef sym);
221 naRef getStringMethods(naContext c);
222
223 // Vector utilities:
224 int naVec_size(naRef v);
225 naRef naVec_get(naRef v, int i);
226 void naVec_set(naRef vec, int i, naRef o);
227 int naVec_append(naRef vec, naRef o);
228 void naVec_setsize(naContext c, naRef vec, int sz);
229
230 /**
231  * Remove and retrieve the first element of the vector.
232  *
233  * This operation reduces the size of the vector by one and moves all elements
234  * by one towards the begin of the vector.
235  *
236  * @return The element removed from the begin
237  */
238 naRef naVec_removefirst(naRef vec);
239
240 /**
241  * Remove and retrieve the last element of the vector.
242  *
243  * This operation reduces the size of the vector by one.
244  *
245  * @return The element removed from the end
246  */
247 naRef naVec_removelast(naRef vec);
248
249 // Hash utilities:
250 int naHash_size(naRef h);
251 int naHash_get(naRef hash, naRef key, naRef* out);
252 naRef naHash_cget(naRef hash, char* key);
253 void naHash_set(naRef hash, naRef key, naRef val);
254 void naHash_cset(naRef hash, char* key, naRef val);
255 void naHash_delete(naRef hash, naRef key);
256 /**
257  * Store the keys in ::hash into the vector at ::dst
258  *
259  * @see ::naNewVector
260  */
261 void naHash_keys(naRef dst, naRef hash);
262
263 // Ghost utilities:
264 typedef struct naGhostType {
265     void(*destroy)(void*);
266     const char* name;
267     const char*(*get_member)(naContext c, void*, naRef key, naRef* out);
268     void(*set_member)(naContext c, void*, naRef key, naRef val);
269 } naGhostType;
270
271 /**
272  * Create a ghost for an object without any attributes. If ::t contains pointers
273  * to get_member or set_member function they will be ignored.
274  */
275 naRef        naNewGhost(naContext c, naGhostType* t, void* ghost);
276 /**
277  * Create a ghost for an object. This version uses the get_member and set_member
278  * function pointers in ::t upon trying to get or set a member respectively from
279  * Nasal.
280  */
281 naRef        naNewGhost2(naContext c, naGhostType* t, void* ghost);
282 naGhostType* naGhost_type(naRef ghost);
283 void*        naGhost_ptr(naRef ghost);
284 int          naIsGhost(naRef r);
285
286 // Acquires a "modification lock" on a context, allowing the C code to
287 // modify Nasal data without fear that such data may be "lost" by the
288 // garbage collector (nasal data on the C stack is not examined in
289 // GC!).  This disallows garbage collection until the current thread
290 // can be blocked.  The lock should be acquired whenever nasal objects
291 // are being modified.  It need not be acquired when only read access
292 // is needed, PRESUMING that the Nasal data being read is findable by
293 // the collector (via naSave, for example) and that another Nasal
294 // thread cannot or will not delete the reference to the data.  It
295 // MUST NOT be acquired by naCFunction's, as those are called with the
296 // lock already held; acquiring two locks for the same thread will
297 // cause a deadlock when the GC is invoked.  It should be UNLOCKED by
298 // naCFunction's when they are about to do any long term non-nasal
299 // processing and/or blocking I/O.  Note that naModLock() may need to
300 // block to allow garbage collection to occur, and that garbage
301 // collection by other threads may be blocked until naModUnlock() is
302 // called.  It must also be UNLOCKED by threads that hold a lock
303 // already before making a naCall() or naContinue() call -- these
304 // functions will attempt to acquire the lock again.
305 void naModLock();
306 void naModUnlock();
307
308 // Library utilities.  Generate namespaces and add symbols.
309 typedef struct { char* name; naCFunction func; } naCFuncItem;
310 naRef naGenLib(naContext c, naCFuncItem *funcs);
311 void naAddSym(naContext c, naRef ns, char *sym, naRef val);
312
313 #ifdef __cplusplus
314 } // extern "C"
315 #endif
316 #endif // _NASAL_H