]> git.mxchange.org Git - simgear.git/blob - simgear/nasal/nasal.h
Olaf Flebbe:
[simgear.git] / simgear / nasal / nasal.h
1 #ifndef _NASAL_H
2 #define _NASAL_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #ifndef BYTE_ORDER
8
9 # if (BSD >= 199103)
10 #  include <machine/endian.h>
11 # elif defined(__CYGWIN__) || defined(__MINGW32__)
12 #  include <sys/param.h>
13 # elif defined(linux)
14 #  include <endian.h>
15 # else
16 #  ifndef LITTLE_ENDIAN
17 #   define LITTLE_ENDIAN   1234    /* LSB first: i386, vax */
18 #  endif
19 #  ifndef BIG_ENDIAN
20 #   define BIG_ENDIAN      4321    /* MSB first: 68000, ibm, net */
21 #  endif
22
23 #  if defined(ultrix) || defined(__alpha__) || defined(__alpha) ||  \
24       defined(__i386__) || defined(__i486__) || defined(_X86_) ||   \
25       defined(sun386)
26 #   define BYTE_ORDER LITTLE_ENDIAN
27 #  else
28 #   define BYTE_ORDER BIG_ENDIAN
29 #  endif
30 # endif /* BSD */
31 #endif /* BYTE_ORDER */
32
33 #if BYTE_ORDER == BIG_ENDIAN
34 # include <limits.h>
35 # if (LONG_MAX == 2147483647)
36 #  define NASAL_BIG_ENDIAN_32_BIT 1
37 # endif
38 #endif
39
40 // This is a nasal "reference".  They are always copied by value, and
41 // contain either a pointer to a garbage-collectable nasal object
42 // (string, vector, hash) or a floating point number.  Keeping the
43 // number here is an optimization to prevent the generation of
44 // zillions of tiny "number" object that have to be collected.  Note
45 // sneaky hack: on little endian systems, placing reftag after ptr and
46 // putting 1's in the top 13 (except the sign bit) bits makes the
47 // double value a NaN, and thus unmistakable (no actual number can
48 // appear as a reference, and vice versa).  Swap the structure order
49 // on 32 bit big-endian systems.  On 64 bit sytems of either
50 // endianness, reftag and the double won't be coincident anyway.
51 #define NASAL_REFTAG 0x7ff56789 // == 2,146,789,257 decimal
52 typedef union {
53     double num;
54     struct {
55 #ifdef NASAL_BIG_ENDIAN_32_BIT
56         int reftag; // Big-endian systems need this here!
57 #endif
58         union {
59             struct naObj* obj;
60             struct naStr* str;
61             struct naVec* vec;
62             struct naHash* hash;
63             struct naCode* code;
64             struct naFunc* func;
65             struct naCCode* ccode;
66             struct naGhost* ghost;
67         } ptr;
68 #ifndef NASAL_BIG_ENDIAN_32_BIT
69         int reftag; // Little-endian and 64 bit systems need this here!
70 #endif
71     } ref;
72 } naRef;
73
74 typedef struct Context* naContext;
75     
76 // The function signature for an extension function:
77 typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args);
78
79 // All Nasal code runs under the watch of a naContext:
80 naContext naNewContext();
81 void naFreeContext(naContext c);
82
83 // Save this object in the context, preventing it (and objects
84 // referenced by it) from being garbage collected.
85 void naSave(naContext ctx, naRef obj);
86
87 // Similar, but the object is automatically released when the
88 // context next runs native bytecode.  Useful for saving off C-space
89 // temporaries to protect them before passing back into a naCall.
90 void naTempSave(naContext c, naRef r);
91
92 // Parse a buffer in memory into a code object.
93 naRef naParseCode(naContext c, naRef srcFile, int firstLine,
94                   char* buf, int len, int* errLine);
95
96 // Binds a bare code object (as returned from naParseCode) with a
97 // closure object (a hash) to act as the outer scope / namespace.
98 // FIXME: this API is weak.  It should expose the recursive nature of
99 // closures, and allow for extracting the closure and namespace
100 // information from function objects.
101 naRef naBindFunction(naContext ctx, naRef code, naRef closure);
102
103 // Similar, but it binds to the current context's closure (i.e. the
104 // namespace at the top of the current call stack).
105 naRef naBindToContext(naContext ctx, naRef code);
106
107 // Call a code or function object with the specifed arguments "on" the
108 // specified object and using the specified hash for the local
109 // variables.  Any of args, obj or locals may be nil.
110 naRef naCall(naContext ctx, naRef func, int argc, naRef* args, naRef obj, naRef locals);
111
112 // Throw an error from the current call stack.  This function makes a
113 // longjmp call to a handler in naCall() and DOES NOT RETURN.  It is
114 // intended for use in library code that cannot otherwise report an
115 // error via the return value, and MUST be used carefully.  If in
116 // doubt, return naNil() as your error condition.
117 void naRuntimeError(naContext ctx, char* msg);
118
119 // Call a method on an object (NOTE: func is a function binding, *not*
120 // a code object as returned from naParseCode).
121 naRef naMethod(naContext ctx, naRef func, naRef object);
122
123 // Returns a hash containing functions from the Nasal standard library
124 // Useful for passing as a namespace to an initial function call
125 naRef naStdLib(naContext c);
126
127 // Ditto, for other core libraries
128 naRef naMathLib(naContext c);
129 naRef naBitsLib(naContext c);
130 naRef naIOLib(naContext c);
131 naRef naRegexLib(naContext c);
132 naRef naUnixLib(naContext c);
133
134 // Current line number & error message
135 int naStackDepth(naContext ctx);
136 int naGetLine(naContext ctx, int frame);
137 naRef naGetSourceFile(naContext ctx, int frame);
138 char* naGetError(naContext ctx);
139
140 // Type predicates
141 int naIsNil(naRef r);
142 int naIsNum(naRef r);
143 int naIsString(naRef r);
144 int naIsScalar(naRef r);
145 int naIsVector(naRef r);
146 int naIsHash(naRef r);
147 int naIsCode(naRef r);
148 int naIsFunc(naRef r);
149 int naIsCCode(naRef r);
150
151 // Allocators/generators:
152 naRef naNil();
153 naRef naNum(double num);
154 naRef naNewString(naContext c);
155 naRef naNewVector(naContext c);
156 naRef naNewHash(naContext c);
157 naRef naNewFunc(naContext c, naRef code);
158 naRef naNewCCode(naContext c, naCFunction fptr);
159
160 // Some useful conversion/comparison routines
161 int naEqual(naRef a, naRef b);
162 int naStrEqual(naRef a, naRef b);
163 int naTrue(naRef b);
164 naRef naNumValue(naRef n);
165 naRef naStringValue(naContext c, naRef n);
166
167 // String utilities:
168 int naStr_len(naRef s);
169 char* naStr_data(naRef s);
170 naRef naStr_fromdata(naRef dst, char* data, int len);
171 naRef naStr_concat(naRef dest, naRef s1, naRef s2);
172 naRef naStr_substr(naRef dest, naRef str, int start, int len);
173 naRef naInternSymbol(naRef sym);
174
175 // Vector utilities:
176 int naVec_size(naRef v);
177 naRef naVec_get(naRef v, int i);
178 void naVec_set(naRef vec, int i, naRef o);
179 int naVec_append(naRef vec, naRef o);
180 naRef naVec_removelast(naRef vec);
181 void naVec_setsize(naRef vec, int sz);
182
183 // Hash utilities:
184 int naHash_size(naRef h);
185 int naHash_get(naRef hash, naRef key, naRef* out);
186 naRef naHash_cget(naRef hash, char* key);
187 void naHash_set(naRef hash, naRef key, naRef val);
188 void naHash_cset(naRef hash, char* key, naRef val);
189 void naHash_delete(naRef hash, naRef key);
190 void naHash_keys(naRef dst, naRef hash);
191
192 // Ghost utilities:
193 typedef struct naGhostType {
194     void (*destroy)(void* ghost);
195 } naGhostType;
196 naRef        naNewGhost(naContext c, naGhostType* t, void* ghost);
197 naGhostType* naGhost_type(naRef ghost);
198 void*        naGhost_ptr(naRef ghost);
199 int          naIsGhost(naRef r);
200
201 // Acquires a "modification lock" on a context, allowing the C code to
202 // modify Nasal data without fear that such data may be "lost" by the
203 // garbage collector (the C stack is not examined in GC!).  This
204 // disallows garbage collection until the current thread can be
205 // blocked.  The lock should be acquired whenever modifications to
206 // Nasal objects are made.  It need not be acquired when only read
207 // access is needed.  It MUST NOT be acquired by naCFunction's, as
208 // those are called with the lock already held; acquiring two locks
209 // for the same thread will cause a deadlock when the GC is invoked.
210 // It should be UNLOCKED by naCFunction's when they are about to do
211 // any long term non-nasal processing and/or blocking I/O.
212 void naModLock();
213 void naModUnlock();
214
215 #ifdef __cplusplus
216 } // extern "C"
217 #endif
218 #endif // _NASAL_H