1 module wren;
2 
3 extern (C):
4 
5 // The Wren semantic version number components.
6 enum WREN_VERSION_MAJOR = 0;
7 enum WREN_VERSION_MINOR = 4;
8 enum WREN_VERSION_PATCH = 0;
9 
10 // A human-friendly string representation of the version.
11 enum WREN_VERSION_STRING = "0.4.0";
12 
13 // A monotonically increasing numeric representation of the version number. Use
14 // this if you want to do range checks over versions.
15 enum WREN_VERSION_NUMBER = WREN_VERSION_MAJOR * 1000000 + WREN_VERSION_MINOR * 1000 + WREN_VERSION_PATCH;
16 
17 //WREN_API
18 
19 // A single virtual machine for executing Wren code.
20 //
21 // Wren has no global state, so all state stored by a running interpreter lives
22 // here.
23 struct WrenVM;
24 
25 // A handle to a Wren object.
26 //
27 // This lets code outside of the VM hold a persistent reference to an object.
28 // After a handle is acquired, and until it is released, this ensures the
29 // garbage collector will not reclaim the object it references.
30 struct WrenHandle;
31 
32 // A generic allocation function that handles all explicit memory management
33 // used by Wren. It's used like so:
34 //
35 // - To allocate new memory, [memory] is NULL and [newSize] is the desired
36 //   size. It should return the allocated memory or NULL on failure.
37 //
38 // - To attempt to grow an existing allocation, [memory] is the memory, and
39 //   [newSize] is the desired size. It should return [memory] if it was able to
40 //   grow it in place, or a new pointer if it had to move it.
41 //
42 // - To shrink memory, [memory] and [newSize] are the same as above but it will
43 //   always return [memory].
44 //
45 // - To free memory, [memory] will be the memory to free and [newSize] will be
46 //   zero. It should return NULL.
47 alias WrenReallocateFn = void* function (void* memory, size_t newSize, void* userData);
48 
49 // A function callable from Wren code, but implemented in C.
50 alias WrenForeignMethodFn = void function (WrenVM* vm);
51 
52 // A finalizer function for freeing resources owned by an instance of a foreign
53 // class. Unlike most foreign methods, finalizers do not have access to the VM
54 // and should not interact with it since it's in the middle of a garbage
55 // collection.
56 alias WrenFinalizerFn = void function (void* data);
57 
58 // Gives the host a chance to canonicalize the imported module name,
59 // potentially taking into account the (previously resolved) name of the module
60 // that contains the import. Typically, this is used to implement relative
61 // imports.
62 alias WrenResolveModuleFn = const(char)* function (
63     WrenVM* vm,
64     const(char)* importer,
65     const(char)* name);
66 
67 // Forward declare
68 
69 // Called after loadModuleFn is called for module [name]. The original returned result
70 // is handed back to you in this callback, so that you can free memory if appropriate.
71 alias WrenLoadModuleCompleteFn = void function (WrenVM* vm, const(char)* name, WrenLoadModuleResult result);
72 
73 // The result of a loadModuleFn call. 
74 // [source] is the source code for the module, or NULL if the module is not found.
75 // [onComplete] an optional callback that will be called once Wren is done with the result.
76 struct WrenLoadModuleResult
77 {
78     const(char)* source;
79     WrenLoadModuleCompleteFn onComplete;
80     void* userData;
81 }
82 
83 // Loads and returns the source code for the module [name].
84 alias WrenLoadModuleFn = WrenLoadModuleResult function (WrenVM* vm, const(char)* name);
85 
86 // Returns a pointer to a foreign method on [className] in [module] with
87 // [signature].
88 alias WrenBindForeignMethodFn = void function (WrenVM* vm, const(char)* module_, const(char)* className, bool isStatic, const(char)* signature) function (
89     WrenVM* vm,
90     const(char)* module_,
91     const(char)* className,
92     bool isStatic,
93     const(char)* signature);
94 
95 // Displays a string of text to the user.
96 alias WrenWriteFn = void function (WrenVM* vm, const(char)* text);
97 
98 enum WrenErrorType
99 {
100     // A syntax or resolution error detected at compile time.
101     WREN_ERROR_COMPILE = 0,
102 
103     // The error message for a runtime error.
104     WREN_ERROR_RUNTIME = 1,
105 
106     // One entry of a runtime error's stack trace.
107     WREN_ERROR_STACK_TRACE = 2
108 }
109 
110 // Reports an error to the user.
111 //
112 // An error detected during compile time is reported by calling this once with
113 // [type] `WREN_ERROR_COMPILE`, the resolved name of the [module] and [line]
114 // where the error occurs, and the compiler's error [message].
115 //
116 // A runtime error is reported by calling this once with [type]
117 // `WREN_ERROR_RUNTIME`, no [module] or [line], and the runtime error's
118 // [message]. After that, a series of [type] `WREN_ERROR_STACK_TRACE` calls are
119 // made for each line in the stack trace. Each of those has the resolved
120 // [module] and [line] where the method or function is defined and [message] is
121 // the name of the method or function.
122 alias WrenErrorFn = void function (
123     WrenVM* vm,
124     WrenErrorType type,
125     const(char)* module_,
126     int line,
127     const(char)* message);
128 
129 struct WrenForeignClassMethods
130 {
131     // The callback invoked when the foreign object is created.
132     //
133     // This must be provided. Inside the body of this, it must call
134     // [wrenSetSlotNewForeign()] exactly once.
135     WrenForeignMethodFn allocate;
136 
137     // The callback invoked when the garbage collector is about to collect a
138     // foreign object's memory.
139     //
140     // This may be `NULL` if the foreign class does not need to finalize.
141     WrenFinalizerFn finalize;
142 }
143 
144 // Returns a pair of pointers to the foreign methods used to allocate and
145 // finalize the data for instances of [className] in resolved [module].
146 alias WrenBindForeignClassFn = WrenForeignClassMethods function (
147     WrenVM* vm,
148     const(char)* module_,
149     const(char)* className);
150 
151 struct WrenConfiguration
152 {
153     // The callback Wren will use to allocate, reallocate, and deallocate memory.
154     //
155     // If `NULL`, defaults to a built-in function that uses `realloc` and `free`.
156     WrenReallocateFn reallocateFn;
157 
158     // The callback Wren uses to resolve a module name.
159     //
160     // Some host applications may wish to support "relative" imports, where the
161     // meaning of an import string depends on the module that contains it. To
162     // support that without baking any policy into Wren itself, the VM gives the
163     // host a chance to resolve an import string.
164     //
165     // Before an import is loaded, it calls this, passing in the name of the
166     // module that contains the import and the import string. The host app can
167     // look at both of those and produce a new "canonical" string that uniquely
168     // identifies the module. This string is then used as the name of the module
169     // going forward. It is what is passed to [loadModuleFn], how duplicate
170     // imports of the same module are detected, and how the module is reported in
171     // stack traces.
172     //
173     // If you leave this function NULL, then the original import string is
174     // treated as the resolved string.
175     //
176     // If an import cannot be resolved by the embedder, it should return NULL and
177     // Wren will report that as a runtime error.
178     //
179     // Wren will take ownership of the string you return and free it for you, so
180     // it should be allocated using the same allocation function you provide
181     // above.
182     WrenResolveModuleFn resolveModuleFn;
183 
184     // The callback Wren uses to load a module.
185     //
186     // Since Wren does not talk directly to the file system, it relies on the
187     // embedder to physically locate and read the source code for a module. The
188     // first time an import appears, Wren will call this and pass in the name of
189     // the module being imported. The method will return a result, which contains
190     // the source code for that module. Memory for the source is owned by the 
191     // host application, and can be freed using the onComplete callback.
192     //
193     // This will only be called once for any given module name. Wren caches the
194     // result internally so subsequent imports of the same module will use the
195     // previous source and not call this.
196     //
197     // If a module with the given name could not be found by the embedder, it
198     // should return NULL and Wren will report that as a runtime error.
199     WrenLoadModuleFn loadModuleFn;
200 
201     // The callback Wren uses to find a foreign method and bind it to a class.
202     //
203     // When a foreign method is declared in a class, this will be called with the
204     // foreign method's module, class, and signature when the class body is
205     // executed. It should return a pointer to the foreign function that will be
206     // bound to that method.
207     //
208     // If the foreign function could not be found, this should return NULL and
209     // Wren will report it as runtime error.
210     WrenBindForeignMethodFn bindForeignMethodFn;
211 
212     // The callback Wren uses to find a foreign class and get its foreign methods.
213     //
214     // When a foreign class is declared, this will be called with the class's
215     // module and name when the class body is executed. It should return the
216     // foreign functions uses to allocate and (optionally) finalize the bytes
217     // stored in the foreign object when an instance is created.
218     WrenBindForeignClassFn bindForeignClassFn;
219 
220     // The callback Wren uses to display text when `System.print()` or the other
221     // related functions are called.
222     //
223     // If this is `NULL`, Wren discards any printed text.
224     WrenWriteFn writeFn;
225 
226     // The callback Wren uses to report errors.
227     //
228     // When an error occurs, this will be called with the module name, line
229     // number, and an error message. If this is `NULL`, Wren doesn't report any
230     // errors.
231     WrenErrorFn errorFn;
232 
233     // The number of bytes Wren will allocate before triggering the first garbage
234     // collection.
235     //
236     // If zero, defaults to 10MB.
237     size_t initialHeapSize;
238 
239     // After a collection occurs, the threshold for the next collection is
240     // determined based on the number of bytes remaining in use. This allows Wren
241     // to shrink its memory usage automatically after reclaiming a large amount
242     // of memory.
243     //
244     // This can be used to ensure that the heap does not get too small, which can
245     // in turn lead to a large number of collections afterwards as the heap grows
246     // back to a usable size.
247     //
248     // If zero, defaults to 1MB.
249     size_t minHeapSize;
250 
251     // Wren will resize the heap automatically as the number of bytes
252     // remaining in use after a collection changes. This number determines the
253     // amount of additional memory Wren will use after a collection, as a
254     // percentage of the current heap size.
255     //
256     // For example, say that this is 50. After a garbage collection, when there
257     // are 400 bytes of memory still in use, the next collection will be triggered
258     // after a total of 600 bytes are allocated (including the 400 already in
259     // use.)
260     //
261     // Setting this to a smaller number wastes less memory, but triggers more
262     // frequent garbage collections.
263     //
264     // If zero, defaults to 50.
265     int heapGrowthPercent;
266 
267     // User-defined data associated with the VM.
268     void* userData;
269 }
270 
271 enum WrenInterpretResult
272 {
273     WREN_RESULT_SUCCESS = 0,
274     WREN_RESULT_COMPILE_ERROR = 1,
275     WREN_RESULT_RUNTIME_ERROR = 2
276 }
277 
278 // The type of an object stored in a slot.
279 //
280 // This is not necessarily the object's *class*, but instead its low level
281 // representation type.
282 enum WrenType
283 {
284     WREN_TYPE_BOOL = 0,
285     WREN_TYPE_NUM = 1,
286     WREN_TYPE_FOREIGN = 2,
287     WREN_TYPE_LIST = 3,
288     WREN_TYPE_MAP = 4,
289     WREN_TYPE_NULL = 5,
290     WREN_TYPE_STRING = 6,
291 
292     // The object is of a type that isn't accessible by the C API.
293     WREN_TYPE_UNKNOWN = 7
294 }
295 
296 // Get the current wren version number.
297 //
298 // Can be used to range checks over versions.
299 int wrenGetVersionNumber ();
300 
301 // Initializes [configuration] with all of its default values.
302 //
303 // Call this before setting the particular fields you care about.
304 void wrenInitConfiguration (WrenConfiguration* configuration);
305 
306 // Creates a new Wren virtual machine using the given [configuration]. Wren
307 // will copy the configuration data, so the argument passed to this can be
308 // freed after calling this. If [configuration] is `NULL`, uses a default
309 // configuration.
310 WrenVM* wrenNewVM (WrenConfiguration* configuration);
311 
312 // Disposes of all resources is use by [vm], which was previously created by a
313 // call to [wrenNewVM].
314 void wrenFreeVM (WrenVM* vm);
315 
316 // Immediately run the garbage collector to free unused memory.
317 void wrenCollectGarbage (WrenVM* vm);
318 
319 // Runs [source], a string of Wren source code in a new fiber in [vm] in the
320 // context of resolved [module].
321 WrenInterpretResult wrenInterpret (
322     WrenVM* vm,
323     const(char)* module_,
324     const(char)* source);
325 
326 // Creates a handle that can be used to invoke a method with [signature] on
327 // using a receiver and arguments that are set up on the stack.
328 //
329 // This handle can be used repeatedly to directly invoke that method from C
330 // code using [wrenCall].
331 //
332 // When you are done with this handle, it must be released using
333 // [wrenReleaseHandle].
334 WrenHandle* wrenMakeCallHandle (WrenVM* vm, const(char)* signature);
335 
336 // Calls [method], using the receiver and arguments previously set up on the
337 // stack.
338 //
339 // [method] must have been created by a call to [wrenMakeCallHandle]. The
340 // arguments to the method must be already on the stack. The receiver should be
341 // in slot 0 with the remaining arguments following it, in order. It is an
342 // error if the number of arguments provided does not match the method's
343 // signature.
344 //
345 // After this returns, you can access the return value from slot 0 on the stack.
346 WrenInterpretResult wrenCall (WrenVM* vm, WrenHandle* method);
347 
348 // Releases the reference stored in [handle]. After calling this, [handle] can
349 // no longer be used.
350 void wrenReleaseHandle (WrenVM* vm, WrenHandle* handle);
351 
352 // The following functions are intended to be called from foreign methods or
353 // finalizers. The interface Wren provides to a foreign method is like a
354 // register machine: you are given a numbered array of slots that values can be
355 // read from and written to. Values always live in a slot (unless explicitly
356 // captured using wrenGetSlotHandle(), which ensures the garbage collector can
357 // find them.
358 //
359 // When your foreign function is called, you are given one slot for the receiver
360 // and each argument to the method. The receiver is in slot 0 and the arguments
361 // are in increasingly numbered slots after that. You are free to read and
362 // write to those slots as you want. If you want more slots to use as scratch
363 // space, you can call wrenEnsureSlots() to add more.
364 //
365 // When your function returns, every slot except slot zero is discarded and the
366 // value in slot zero is used as the return value of the method. If you don't
367 // store a return value in that slot yourself, it will retain its previous
368 // value, the receiver.
369 //
370 // While Wren is dynamically typed, C is not. This means the C interface has to
371 // support the various types of primitive values a Wren variable can hold: bool,
372 // double, string, etc. If we supported this for every operation in the C API,
373 // there would be a combinatorial explosion of functions, like "get a
374 // double-valued element from a list", "insert a string key and double value
375 // into a map", etc.
376 //
377 // To avoid that, the only way to convert to and from a raw C value is by going
378 // into and out of a slot. All other functions work with values already in a
379 // slot. So, to add an element to a list, you put the list in one slot, and the
380 // element in another. Then there is a single API function wrenInsertInList()
381 // that takes the element out of that slot and puts it into the list.
382 //
383 // The goal of this API is to be easy to use while not compromising performance.
384 // The latter means it does not do type or bounds checking at runtime except
385 // using assertions which are generally removed from release builds. C is an
386 // unsafe language, so it's up to you to be careful to use it correctly. In
387 // return, you get a very fast FFI.
388 
389 // Returns the number of slots available to the current foreign method.
390 int wrenGetSlotCount (WrenVM* vm);
391 
392 // Ensures that the foreign method stack has at least [numSlots] available for
393 // use, growing the stack if needed.
394 //
395 // Does not shrink the stack if it has more than enough slots.
396 //
397 // It is an error to call this from a finalizer.
398 void wrenEnsureSlots (WrenVM* vm, int numSlots);
399 
400 // Gets the type of the object in [slot].
401 WrenType wrenGetSlotType (WrenVM* vm, int slot);
402 
403 // Reads a boolean value from [slot].
404 //
405 // It is an error to call this if the slot does not contain a boolean value.
406 bool wrenGetSlotBool (WrenVM* vm, int slot);
407 
408 // Reads a byte array from [slot].
409 //
410 // The memory for the returned string is owned by Wren. You can inspect it
411 // while in your foreign method, but cannot keep a pointer to it after the
412 // function returns, since the garbage collector may reclaim it.
413 //
414 // Returns a pointer to the first byte of the array and fill [length] with the
415 // number of bytes in the array.
416 //
417 // It is an error to call this if the slot does not contain a string.
418 const(char)* wrenGetSlotBytes (WrenVM* vm, int slot, int* length);
419 
420 // Reads a number from [slot].
421 //
422 // It is an error to call this if the slot does not contain a number.
423 double wrenGetSlotDouble (WrenVM* vm, int slot);
424 
425 // Reads a foreign object from [slot] and returns a pointer to the foreign data
426 // stored with it.
427 //
428 // It is an error to call this if the slot does not contain an instance of a
429 // foreign class.
430 void* wrenGetSlotForeign (WrenVM* vm, int slot);
431 
432 // Reads a string from [slot].
433 //
434 // The memory for the returned string is owned by Wren. You can inspect it
435 // while in your foreign method, but cannot keep a pointer to it after the
436 // function returns, since the garbage collector may reclaim it.
437 //
438 // It is an error to call this if the slot does not contain a string.
439 const(char)* wrenGetSlotString (WrenVM* vm, int slot);
440 
441 // Creates a handle for the value stored in [slot].
442 //
443 // This will prevent the object that is referred to from being garbage collected
444 // until the handle is released by calling [wrenReleaseHandle()].
445 WrenHandle* wrenGetSlotHandle (WrenVM* vm, int slot);
446 
447 // Stores the boolean [value] in [slot].
448 void wrenSetSlotBool (WrenVM* vm, int slot, bool value);
449 
450 // Stores the array [length] of [bytes] in [slot].
451 //
452 // The bytes are copied to a new string within Wren's heap, so you can free
453 // memory used by them after this is called.
454 void wrenSetSlotBytes (WrenVM* vm, int slot, const(char)* bytes, size_t length);
455 
456 // Stores the numeric [value] in [slot].
457 void wrenSetSlotDouble (WrenVM* vm, int slot, double value);
458 
459 // Creates a new instance of the foreign class stored in [classSlot] with [size]
460 // bytes of raw storage and places the resulting object in [slot].
461 //
462 // This does not invoke the foreign class's constructor on the new instance. If
463 // you need that to happen, call the constructor from Wren, which will then
464 // call the allocator foreign method. In there, call this to create the object
465 // and then the constructor will be invoked when the allocator returns.
466 //
467 // Returns a pointer to the foreign object's data.
468 void* wrenSetSlotNewForeign (WrenVM* vm, int slot, int classSlot, size_t size);
469 
470 // Stores a new empty list in [slot].
471 void wrenSetSlotNewList (WrenVM* vm, int slot);
472 
473 // Stores a new empty map in [slot].
474 void wrenSetSlotNewMap (WrenVM* vm, int slot);
475 
476 // Stores null in [slot].
477 void wrenSetSlotNull (WrenVM* vm, int slot);
478 
479 // Stores the string [text] in [slot].
480 //
481 // The [text] is copied to a new string within Wren's heap, so you can free
482 // memory used by it after this is called. The length is calculated using
483 // [strlen()]. If the string may contain any null bytes in the middle, then you
484 // should use [wrenSetSlotBytes()] instead.
485 void wrenSetSlotString (WrenVM* vm, int slot, const(char)* text);
486 
487 // Stores the value captured in [handle] in [slot].
488 //
489 // This does not release the handle for the value.
490 void wrenSetSlotHandle (WrenVM* vm, int slot, WrenHandle* handle);
491 
492 // Returns the number of elements in the list stored in [slot].
493 int wrenGetListCount (WrenVM* vm, int slot);
494 
495 // Reads element [index] from the list in [listSlot] and stores it in
496 // [elementSlot].
497 void wrenGetListElement (WrenVM* vm, int listSlot, int index, int elementSlot);
498 
499 // Sets the value stored at [index] in the list at [listSlot], 
500 // to the value from [elementSlot]. 
501 void wrenSetListElement (WrenVM* vm, int listSlot, int index, int elementSlot);
502 
503 // Takes the value stored at [elementSlot] and inserts it into the list stored
504 // at [listSlot] at [index].
505 //
506 // As in Wren, negative indexes can be used to insert from the end. To append
507 // an element, use `-1` for the index.
508 void wrenInsertInList (WrenVM* vm, int listSlot, int index, int elementSlot);
509 
510 // Returns the number of entries in the map stored in [slot].
511 int wrenGetMapCount (WrenVM* vm, int slot);
512 
513 // Returns true if the key in [keySlot] is found in the map placed in [mapSlot].
514 bool wrenGetMapContainsKey (WrenVM* vm, int mapSlot, int keySlot);
515 
516 // Retrieves a value with the key in [keySlot] from the map in [mapSlot] and
517 // stores it in [valueSlot].
518 void wrenGetMapValue (WrenVM* vm, int mapSlot, int keySlot, int valueSlot);
519 
520 // Takes the value stored at [valueSlot] and inserts it into the map stored
521 // at [mapSlot] with key [keySlot].
522 void wrenSetMapValue (WrenVM* vm, int mapSlot, int keySlot, int valueSlot);
523 
524 // Removes a value from the map in [mapSlot], with the key from [keySlot],
525 // and place it in [removedValueSlot]. If not found, [removedValueSlot] is
526 // set to null, the same behaviour as the Wren Map API.
527 void wrenRemoveMapValue (
528     WrenVM* vm,
529     int mapSlot,
530     int keySlot,
531     int removedValueSlot);
532 
533 // Looks up the top level variable with [name] in resolved [module] and stores
534 // it in [slot].
535 void wrenGetVariable (
536     WrenVM* vm,
537     const(char)* module_,
538     const(char)* name,
539     int slot);
540 
541 // Looks up the top level variable with [name] in resolved [module], 
542 // returns false if not found. The module must be imported at the time, 
543 // use wrenHasModule to ensure that before calling.
544 bool wrenHasVariable (WrenVM* vm, const(char)* module_, const(char)* name);
545 
546 // Returns true if [module] has been imported/resolved before, false if not.
547 bool wrenHasModule (WrenVM* vm, const(char)* module_);
548 
549 // Sets the current fiber to be aborted, and uses the value in [slot] as the
550 // runtime error object.
551 void wrenAbortFiber (WrenVM* vm, int slot);
552 
553 // Returns the user data associated with the WrenVM.
554 void* wrenGetUserData (WrenVM* vm);
555 
556 // Sets user data associated with the WrenVM.
557 void wrenSetUserData (WrenVM* vm, void* userData);
558