FixScript

C API

Prerequisites

The C implementation is currently written for targets where int is 4 bytes and short is 2 bytes. This is true for the usual 32/64 bit targets but may not be true in embedded targets and modifications would be needed.

The code also uses the indirect goto feature of GCC and Clang for increasing the performance. However it contains a fallback that uses switches with some performance degradation and noticeable increase in object size. This doesn't apply when JIT is available for given platform and is not disabled.

Temporary roots

To avoid premature garbage collection of temporary values in C code all created arrays, strings, etc. are added into list of temporary roots. This list is cleared only on explicit garbage collection, when calling script function or returning from the handler of a native function.

Types

typedef struct Heap Heap;
The heap contains all the data structures of the scripts as well as the compiled scripts themselves.
typedef struct Script Script;
Reference to specific script. This is to allow to query functions defined in that script. The scripts are owned by Heap and must not be mixed up between heaps or freed manually.
typedef struct { int value; int is_array; } Value;
Value struct contains the integer value and an indication if it's an array reference or a float value. It's preferred to use this type as an opaque value and always use the functions for handling the simple values.
Internal details: The distinction between array reference and floats is made based on the unsigned value, if it's outside the range 1..0x7FFFFF (meaning the exponent is present or the number is negative or zero) then it's outside of valid array references and it's a float value. Note that denormalized numbers are flushed to zero and thus don't collide with array references (the exponent would be stored as 0 in such case). The is_array is either 0 or 1, this allows to directly compare the struct for equivalence. This struct is always passed by value. You can test validity of any reference by comparing value to zero (all references are non-zero).
typedef struct SharedArrayHandle SharedArrayHandle;
Used for referencing shared arrays outside a heap.
typedef void (*HandleFreeFunc)(void *p);
Used for freeing the native handle. Called during garbage collection, it is advised to not trigger garbage collection in the function (directly or indirectly), however there is a safeguard preventing a recursive GC. Should GC occur again the heap will get larger instead (and there is a possibility of getting spurious out of memory errors if the heap was already big enough, also it can overinflate the heap without the ability to shrink because of fragmentation).
typedef void *(*HandleFunc)(Heap *heap, int op, void *p1, void *p2);
Used for handling the native value handle. The operation can be one of the following:
HANDLE_OP_FREE
free the value handle p1 (called during garbage collection, see the note on HandleFreeFunc type)
HANDLE_OP_COPY
create a copy of the value handle p1 or return NULL if copies are not supported (the destination heap pointer is in p2), this operation must be thread-safe as the copying can occur in multiple threads concurrently
HANDLE_OP_COMPARE
compare the value handles p1 and p2, result is negative (if less), zero (if equal) or positive (if greater), the result needs to be casted to intptr_t and then to void *
note: the second pointer can be from a handle in a different heap
HANDLE_OP_HASH
return hash of the value handle p1 casted to void * (only low 32 bits are used)
HANDLE_OP_TO_STRING
return newly allocated string representation of the value handle p1 (return NULL for default string representation)
HANDLE_OP_MARK_REFS
called during GC to mark references (using the fixscript_mark_ref function) held on the native side (p1 points to handle)
HANDLE_OP_COPY_REFS
called during deep cloning to copy references (using the fixscript_copy_ref function) held on the native side (p1 points to handle and p2 to copy context), this operation must be thread-safe as the copying can occur in multiple threads concurrently
note: in some circumstances it won't be called for a deep copy (eg. in case of an error during cloning), handle such cases gracefully
typedef Script *(*LoadScriptFunc)(Heap *heap, const char *fname, Value *error, void *data);
Used for providing a callback to load other scripts when using the import or the use statement.
typedef Value (*NativeFunc)(Heap *heap, Value *error, int num_params, Value *params, void *data);
Used for providing native functions. Use error to return second return value (usually used for errors, initialized to zero).

Error codes

Note: Error constants are negative values (success code is zero).

FIXSCRIPT_SUCCESS
No error occurred.
FIXSCRIPT_ERR_INVALID_ACCESS
The value is an invalid reference.
FIXSCRIPT_ERR_INVALID_BYTE_ARRAY
The value is invalid byte array (contains values outside the range of byte or contains non-integer values).
FIXSCRIPT_ERR_INVALID_SHORT_ARRAY
The value is invalid short array (contains values outside the range of short or contains non-integer values).
FIXSCRIPT_ERR_INVALID_NULL_STRING
The string contains zero character (reported only when the string is retrieved without getting the length and thus relying on the zero character termination).
FIXSCRIPT_ERR_CONST_WRITE
The value is a constant string and can't be modified.
FIXSCRIPT_ERR_OUT_OF_BOUNDS
The index or range is out of the bounds.
FIXSCRIPT_ERR_OUT_OF_MEMORY
Tried to allocate more memory than available or an integer overflow occurred during computation of how much to allocate.
FIXSCRIPT_ERR_INVALID_SHARED_ARRAY_OPERATION
Tried to change length or element size on a shared array, or put a reference or native handle to such array.
FIXSCRIPT_ERR_KEY_NOT_FOUND
The requested key isn't present in the hash table.
FIXSCRIPT_ERR_RECURSION_LIMIT
The recursion limit was exceeded.
FIXSCRIPT_ERR_UNSERIALIZABLE_REF
An unserializable reference occurred (for example native handle).
FIXSCRIPT_ERR_BAD_FORMAT
Bad format or data too short (when unserializing).
FIXSCRIPT_ERR_FUNC_REF_LOAD_ERROR
Script load error during resolving of function reference (typically native function not defined or script wasn't loaded when resolving within already loaded code only).
FIXSCRIPT_ERR_NESTED_WEAKREF
Nested weak references are not allowed (referencing directly another weak reference or having a key as a weak reference).

Functions

Simple values handling

Note: these functions are all inlined.

Value fixscript_int(int value);
Makes a 32-bit integer value.
Value fixscript_float(float value);
Makes a 32-bit float value. The denormals are flushed to zero.
int fixscript_is_int(Value value);
Returns whether the value is a 32-bit integer.
int fixscript_is_float(Value value);
Returns whether the value is a 32-bit float.
int fixscript_get_int(Value value);
Returns the integer representation of the value. If the value is a float or an array reference it will return the bitwise representation.
float fixscript_get_float(Value value);
Returns the float representation of the value. Gives incorrect values if the value wasn't a float.

Heap management

Heap *fixscript_create_heap();
Creates a new heap, this contains the whole context of script execution. You can use only different heaps in different threads concurrently.
void fixscript_free_heap(Heap *heap);
Frees all the resources for given heap.
void fixscript_collect_heap(Heap *heap);
Runs garbage collection for given heap. It also clears the temporary roots, you need to store references directly in the heap or increase their external reference count to persist them.
long long fixscript_heap_size(Heap *heap);
Traverses the heap to obtain the overall size of the heap in bytes. This includes overheads from reserved memory for array growths and struct paddings, but doesn't include overhead of the underlying malloc implementation.
void fixscript_adjust_heap_size(Heap *heap, long long relative_change);
Adjusts tracked memory footprint of the heap. This is used for making sure the garbage collection knows about externally allocated memory (eg. when using native handles).
void fixscript_set_max_stack_size(Heap *heap, int size);
Sets the maximum stack size in number of stack entries (each taking 5 bytes and currently each up to 32 bytes for native JIT stack).
int fixscript_get_max_stack_size(Heap *heap);
Returns the stack size limit.
int fixscript_get_stack_size(Heap *heap);
Returns the current stack size.
void fixscript_ref(Heap *heap, Value value);
Increases the number of external references, preventing the value from being garbage collected. There is an internal limit that once reached will prevent decreasing of the counter to prevent releasing the value while still potentially being held.
Note: Beware of reference cycles that will result into inability to reclaim memory. Often this is when the native handle needs to hold into some heap data which contains reference back to the native handle, creating a cycle. This is best solved by using a value handle and using the HANDLE_OP_MARK_REFS operation to mark any such references. Alternativelly you can use weak references on the native side (simply by not using fixscript_ref) and wrapping the native handle into an object (containing array of references that need to be retained) and referencing to that object instead of the handle.
void fixscript_unref(Heap *heap, Value value);
Decreases the number of external references, once at zero the value can be garbage collected.
void fixscript_set_protected(Heap *heap, Value value, int is_protected);
Sets the protected status of given reference. This is used in native libraries that want to protect internal data structures to not be directly exposed to the scripts by other native libraries that create arbitrary references from just the integer portion and pass them to the scripts.
int fixscript_is_protected(Heap *heap, Value value);
Returns whether the given reference is protected and shouldn't be exposed to the script.
void fixscript_register_cleanup(Heap *heap, HandleFreeFunc free_func, void *data);
Registers a cleanup function that will be called when the heap is freed.
void fixscript_register_heap_key(volatile int *key);
Registers a heap key if it's not registered already, this is done atomically. This is a global operation, and should be used for static initialization only.
int fixscript_set_heap_data(Heap *heap, int key, void *data, HandleFreeFunc free_func);
Sets per-heap value with given key, freeing the previous value if present.
void *fixscript_get_heap_data(Heap *heap, int key);
Returns per-heap value for given key.

Execution time limit

void fixscript_set_time_limit(Heap *heap, int limit);
Sets a time limit in milliseconds for execution of the scripts. The time limit starts counting after calling of this function. This function must be called before any scripts are loaded as they need to be instrumented with the time checks. To disable the time limit, pass -1 as a limit (avoid passing 0 as that would remove instrumentation for newly compiled scripts).
int fixscript_get_remaining_time(Heap *heap);
Returns the remaining time in milliseconds (capped to 0) for execution of the scripts. Returns -1 when the time limit is not set. The 0 is also returned when the heap is stopped asynchronously from another thread.
void fixscript_stop_execution(Heap *heap);
Stops the running script asynchronously from another thread. The heap must be using the time limit feature (use -1 for no actual time limit). To be able to run code again the time limit must be set again (it will reset the stop execution flag).

Reference handling in value handles

void fixscript_mark_ref(Heap *heap, Value value);
Marks a reference held on the native side. Call this only during the HANDLE_OP_MARK_REFS operation of the value handles.
Value fixscript_copy_ref(void *ctx, Value value);
Creates a copy of the reference, using the copy context that is available during HANDLE_OP_COPY_REFS operation of the value handles.

Array access

Value fixscript_create_array(Heap *heap, int len);
Creates a new array of given length. The reference is added into temporary roots to prevent it from premature deallocation.
Value fixscript_create_byte_array(Heap *heap, const char *buf, int len);
Creates a new byte array with given content. The reference is added into temporary roots to prevent it from premature deallocation.
int fixscript_set_array_length(Heap *heap, Value arr_val, int len);
Sets length of given array, expanding the capacity when needed. If the length is bigger than currently is the space is filled with zeros. Does nothing in case the array reference is invalid. Returns error code.
int fixscript_get_array_length(Heap *heap, Value arr_val, int *len);
Returns length of the array or hash in the output parameter. Returns error code.
int fixscript_get_array_element_size(Heap *heap, Value arr_val, int *elem_size);
Returns the current element size (1, 2 or 4 bytes) of the array in the output parameter. Returns error code.
int fixscript_is_array(Heap *heap, Value arr_val);
Returns whether the given value is valid reference to an array.
int fixscript_set_array_elem(Heap *heap, Value arr_val, int idx, Value value);
Sets value in the array at given index. Returns error code.
int fixscript_get_array_elem(Heap *heap, Value arr_val, int idx, Value *value);
Retrieves value in the array at given index. Returns error code.
int fixscript_append_array_elem(Heap *heap, Value arr_val, Value value);
Appends value in to the array. Returns error code.
int fixscript_get_array_range(Heap *heap, Value arr_val, int off, int len, Value *values);
Retrieves values from the array in specified range. Returns error code.
int fixscript_set_array_range(Heap *heap, Value arr_val, int off, int len, Value *values);
Stores values to the array in specified range. Returns error code.
int fixscript_get_array_bytes(Heap *heap, Value arr_val, int off, int len, char *bytes);
Retrieves byte values from the array in specified range. Returns error code.
int fixscript_set_array_bytes(Heap *heap, Value arr_val, int off, int len, char *bytes);
Stores byte values to the array in specified range. Returns error code.
int fixscript_has_array_references(Heap *heap, Value arr_val, int off, int len, int float_as_ref, int *result);
Checks the array for contained references. You can specify if you want to treat floats as references (faster) or not. The result is passed in an output parameter. Returns error code.
int fixscript_copy_array(Heap *heap, Value dest, int dest_off, Value src, int src_off, int count);
Copies given amount of values between different arrays or within the same array. Returns error code.
int fixscript_lock_array(Heap *heap, Value arr_val, int off, int len, void **data, int elem_size, int access);
Obtains direct pointer access to an array when possible or allocates a temporary buffer and optionally copies the data to it from the array. You must unlock the array by calling fixscript_unlock_array with the same parameters (length can be made smaller). There must be no other access to the array while being locked. The reference is added into temporary roots to prevent it from premature deallocation. The access can be one of ACCESS_READ_ONLY, ACCESS_WRITE_ONLY or ACCESS_READ_WRITE.
void fixscript_unlock_array(Heap *heap, Value arr_val, int off, int len, void **data, int elem_size, int access);
Finishes direct pointer access to an array or optionally copies the data from the temporary buffer back into the array and frees the temporary buffer if used. All the parameters must be the same as when called the fixscript_lock_array function. It is however permitted to shorten the length to avoid unnecessary copying of data. In write mode the values in the range are converted to integers only, making any references invalid.

Shared arrays

Value fixscript_create_shared_array(Heap *heap, int len, int elem_size);
Creates a new shared array. The reference is added into temporary roots to prevent it from premature deallocation.
Value fixscript_create_or_get_shared_array(Heap *heap, int type, void *ptr, int len, int elem_size, HandleFreeFunc free_func, void *data, int *created);
Creates a new shared array with user provided pointer or gets an existing instance. The type allows to specify what kind of handle type it is (use a non-negative integer or pass a negative number when not used). The pointer must be aligned to element size. The reference is added into temporary roots to prevent it from premature deallocation. Optionally you can retrieve whether the shared array was created or an existing instance was returned instead.
Note: The shared arrays are matched based on type, pointer, length, element size and data, therefore if any of these are unique (eg. resulting from a new allocation), the array is always created as new and there is no need to check for creation status.
void fixscript_ref_shared_array(SharedArrayHandle *sah);
Increases the number of references, preventing the shared array from being freed prematurely. There is an internal limit that once reached will prevent decreasing of the counter to prevent freeing the array while still potentially being held.
void fixscript_unref_shared_array(SharedArrayHandle *sah);
Decreases the number of references, once at zero the shared array is freed.
int fixscript_get_shared_array_reference_count(SharedArrayHandle *sah);
Returns the value of reference counter for given shared array.
SharedArrayHandle *fixscript_get_shared_array_handle(Heap *heap, Value arr_val, int expected_type, int *actual_type);
Obtains direct reference to shared array for usage outside of the heap. You can restrict obtaining for given handle type only (pass a negative value to allow any type of shared array). Returns NULL on error (invalid value or different type).
void *fixscript_get_shared_array_handle_data(SharedArrayHandle *sah, int *len, int *elem_size, void **data, int expected_type, int *actual_type);
Returns information about a shared array. You can restrict checking for given handle type (pass a negative value to disable the check). All output parameters are optional. Returns NULL on error (different type).
Value fixscript_get_shared_array_value(Heap *heap, SharedArrayHandle *sah);
Creates or returns an existing reference to given shared array.
Value fixscript_get_shared_array(Heap *heap, int type, void *ptr, int len, int elem_size, void *data);
Returns an existing reference to a shared array, returns null in case the reference is not present.
void *fixscript_get_shared_array_data(Heap *heap, Value arr_val, int *len, int *elem_size, void **data, int expected_type, int *actual_type);
Returns information about a shared array. You can restrict checking for given handle type (pass a negative value to disable the check). All output parameters are optional. Returns NULL on error (invalid value or different type).
int fixscript_is_shared_array(Heap *heap, Value arr_val);
Returns whether the given value is a valid reference to a shared array.

String access

Value fixscript_create_string(Heap *heap, const char *s, int len);
Creates a new string from UTF-8 encoded characters of given length. Any incorrectly encoded character is replaced by the replacement character (U+FFFD). If the length is negative the length is computed automatically. The reference is added into temporary roots to prevent it from premature deallocation.
Value fixscript_create_string_utf16(Heap *heap, const unsigned short *s, int len);
A variant of fixscript_create_string that uses UTF-16 encoded characters. Any invalid surrogate pair encoding is replaced by the replacement character (U+FFFD).
int fixscript_get_string(Heap *heap, Value str_val, int str_off, int str_len, char **str, int *len_out);
Returns the string contents as UTF-8 encoded characters (pass negative value for length to use the whole string). Any invalid character (outside of the valid range or within the surrogate pairs range) is replaced by the replacement character (U+FFFD). The string is always zero-terminated and you can optionally obtain the string length. The string must be deallocated by the caller using the free function. If the output length is not obtained and the string contains zero character it returns an error instead of returning shortened string. Returns error code.
int fixscript_get_string_utf16(Heap *heap, Value str_val, int str_off, int str_len, unsigned short **str, int *len_out);
A variant of fixscript_get_string that uses UTF-16 encoded characters.
int fixscript_is_string(Heap *heap, Value str_val);
Returns whether the given value is a valid reference to a string.
int fixscript_get_const_string(Heap *heap, Value str_val, int off, int len, Value *ret);
Returns a constant string (can't be modified) for the given string. You can either specify a portion of the original string or specify negative length to consider the whole string, in such case the same string is returned if it is already a constant. Returns error code. There is always only a single instance for each unique constant string.
int fixscript_get_const_string_between(Heap *dest, Heap *src, Value str_val, int off, int len, Value *ret);
A variant that allows to use a different heap for the source string.
int fixscript_is_const_string(Heap *heap, Value str_val);
Returns whether the given value is a valid reference to a constant string.

Hash access

Value fixscript_create_hash(Heap *heap);
Creates a new hash. The reference is added into temporary roots to prevent it from premature deallocation.
int fixscript_is_hash(Heap *heap, Value hash_val);
Returns whether the given value is valid reference to a hash.
int fixscript_set_hash_elem(Heap *heap, Value hash_val, Value key_val, Value value_val);
Sets value in the hash for given key. Returns error code.
int fixscript_get_hash_elem(Heap *heap, Value hash_val, Value key_val, Value *value_val);
Retrieves value in the hash for given key. Returns error code.
int fixscript_get_hash_elem_between(Heap *heap, Value hash_val, Heap *key_heap, Value key_val, Value *value_val);
Retrieves value in the hash for given key (the key can be from a different heap). Returns error code.
int fixscript_remove_hash_elem(Heap *heap, Value hash_val, Value key_val, Value *value_val);
Removes entry for given key. Returns error code.
int fixscript_clear_hash(Heap *heap, Value hash_val);
Clears all entries in the hash. Returns error code.
int fixscript_iter_hash(Heap *heap, Value hash_val, Value *key_val, Value *value_val, int *pos);
Retrieves the next key and value from the hash. The iteration position must be initialized to zero before retrieving first entry. Returns non-zero if entry was retrieved or zero when there are no more entries present.

Native handles

Value fixscript_create_handle(Heap *heap, int type, void *handle, HandleFreeFunc free_func);
Creates a new native handle. The type must not be negative. free_func is optional.
Value fixscript_create_value_handle(Heap *heap, int type, void *handle, HandleFunc handle_func);
Creates a new native value handle (supports comparing by value and cloning). The type must not be negative.
void *fixscript_get_handle(Heap *heap, Value handle_val, int expected_type, int *actual_type);
Obtains native handle with given type (or negative value to disable the check), optionally you can get the type (set to -1 in case the handle is invalid). Returns NULL on error (invalid value or different type).
void fixscript_register_handle_types(volatile int *offset, int count);
Registers given number of native handle types if it's not registered already, this is done atomically. This is a global operation, and should be used for static initialization only. The counts are counted from INT_MAX and allocated by decrementing.
int fixscript_is_handle(Heap *heap, Value handle_val);
Returns whether the given value is a valid reference to a handle.

Weak references

int fixscript_create_weak_ref(Heap *heap, Value value, Value *container, Value *key, Value *weak_ref);
Creates a new weak reference (or already existing instance). Optionally you can pass a container (hash table or array) for automatic action to occur once the target object is garbage collected. In case of hash tables either the weak reference or provided key is removed. For arrays either the weak reference or provided key is appended to it. Be sure to periodically empty the array to prevent memory leaks.
Note: weak references can't reference directly other weak references (including the key).
int fixscript_get_weak_ref(Heap *heap, Value weak_ref, Value *value);
Obtains the reference value for given weak reference.
int fixscript_is_weak_ref(Heap *heap, Value weak_ref);
Returns whether the given value is a weak reference.

Error handling

const char *fixscript_get_error_msg(int error_code);
Returns error message as a constant string, returns NULL for success or unknown error codes.
Value fixscript_create_error(Heap *heap, Value msg);
Creates error value (with the same format as the builtin error function) with given value for message.
Value fixscript_create_error_string(Heap *heap, const char *s);
Creates error value (with the same format as the builtin error function) with given error message.
Value fixscript_error(Heap *heap, Value *error, int code);
Creates error value (with the same format as the builtin error function) with error message that corresponds to given error code. For convenience it returns zero and stores the error into the provided parameter.
const char *fixscript_get_compiler_error(Heap *heap, Value error);
Returns a string representation of a compiler error. It also handles simplifying of syntax errors produced by token processors. The returned string is allocated internally and the previous pointer is freed for each invocation of this function.

Value inspection

int fixscript_dump_value(Heap *heap, Value value, int newlines);
Pretty prints the given value to standard error stream (stderr).
int fixscript_to_string(Heap *heap, Value value, int newlines, char **str, int *len);
Pretty prints the given value to newly allocated UTF-8 string (zero-terminated if length is not obtained). Returns error code.

Cloning & serialization

int fixscript_compare(Heap *heap, Value value1, Value value2);
Compares the values, returns a non-zero value when they are equal. There is currently a maximum recursion limit of 50, more nested values will simply return as not equal.
int fixscript_compare_between(Heap *heap1, Value value1, Heap *heap2, Value value2);
A variant that allows to use a different heap for each value.
int fixscript_clone(Heap *heap, Value value, int deep, Value *clone);
Clones given value. Returns error code.
int fixscript_clone_between(Heap *dest, Heap *src, Value value, Value *clone, LoadScriptFunc load_func, void *load_data, Value *error);
Clones given value between different (or same) heaps. The optional load function is to load the scripts for cloned function references, otherwise the references will be unresolved until cloned again with the load function provided. You can pass the fixscript_resolve_existing function to allow references to be resolved in already loaded code without loading any other code. Returns error code. You can optionally obtain more precise error value when script load fails (if resolving is used). The error is stored in the destination heap, if no such detailed error is produced use the standard error codes. It is permitted to clone to multiple threads concurrently as long as the source heap is not used for anything else.
int fixscript_serialize(Heap *heap, Value *buf_val, Value value);
Serializes given value to byte array value (created when not provided).
int fixscript_unserialize(Heap *heap, Value buf_val, int *off, int len, Value *value);
Unserializes value from given byte array value. The provided offset is adjusted with the resulting position after the operation. If the length is passed as negative it will allow extra data after the serialized data (possibily another serialized data).
int fixscript_serialize_to_array(Heap *heap, char **buf, int *len_out, Value value);
Serializes given value to native byte array. If length is not obtained the serialized form is prepended by the size of the serialized data.
int fixscript_unserialize_from_array(Heap *heap, const char *buf, int *off_out, int len, Value *value);
Unserializes value from given native byte array. If length is negative it is read from the beginning of the serialized data (must be outputed in that form). Optionally you can retrieve offset after the serialized data, in that case it will allow extra data after the serialized data (possibly another serialized data).

Script loading & running

Script *fixscript_load(Heap *heap, const char *src, const char *fname, Value *error, LoadScriptFunc load_func, void *load_data);
Loads given script source under provided file name. On error it returns NULL and the error value is outputed (optional). Passing of load_func is optional (import and use statements will not work in such case). You can use fixscript_resolve_existing function to allow loading of already compiled scripts.
Script *fixscript_load_file(Heap *heap, const char *name, Value *error, const char *dirname);
A variant of fixscript_load that loads scripts from file system.
Script *fixscript_load_embed(Heap *heap, const char *name, Value *error, const char * const * const embed_files);
A variant of fixscript_load that loads scripts from embedded static array as produced by the fixembed tool.
Script *fixscript_reload(Heap *heap, const char *src, const char *fname, Value *error, LoadScriptFunc load_func, void *load_data);
Reloads given script. The newly loaded version of the script replaces existing functions so new calls will go to the updated script. On error it returns NULL and the error value is outputed (optional). Passing of load_func is optional (import and use statements will not work in such case). You can use fixscript_resolve_existing function to allow loading of already compiled scripts.
Script *fixscript_resolve_existing(Heap *heap, const char *name, Value *error, void *data);
Script loading function that returns an error when trying to load a new script. Used for enabling function reference resolving within already loaded scripts when cloning between heaps or just to allow to use the previously compiled scripts only.
Script *fixscript_get(Heap *heap, const char *fname);
Returns script for given file name (or NULL if not found).
char *fixscript_get_script_name(Heap *heap, Script *script);
Returns newly allocated script name for given script (or NULL if no script is provided).
Value fixscript_get_function(Heap *heap, Script *script, const char *func_name);
Returns function handle for function with given name (must provide parameter count as part of the name). Returns zero in case the script is not provided.
int fixscript_get_function_list(Heap *heap, Script *script, char ***functions_out, int *count_out);
Obtains a list of functions in given script as two output parameters. Returns an error code. The individual strings and the list must be freed using the free function.
int fixscript_get_function_name(Heap *heap, Value func_val, char **script_name_out, char **func_name_out, int *num_params_out);
Obtains script name, function name and number of parameters for given function value (all obtained values are optional). Returns error code.
int fixscript_is_func_ref(Heap *heap, Value func_ref);
Returns whether the given value is a function reference.
Value fixscript_run(Heap *heap, Script *script, const char *func_name, Value *error, ...);
Runs function with given name (including parameter count in the name) and (optionally) obtains the error value.
Value fixscript_run_args(Heap *heap, Script *script, const char *func_name, Value *error, Value *args);
A variant of fixscript_run with arguments passed as an array.
Value fixscript_call(Heap *heap, Value func, int num_params, Value *error, ...);
Calls function using given function value and (optionally) obtains the error value.
Value fixscript_call_args(Heap *heap, Value func, int num_params, Value *error, Value *args);
A variant of fixscript_call with arguments passed as an array.
void fixscript_register_native_func(Heap *heap, const char *name, NativeFunc func, void *data);
Registers (or replaces) native function with given name.
NativeFunc fixscript_get_native_func(Heap *heap, const char *name, void **data);
Returns registered native function and the associated data (optional).

Bytecode & heap inspection

char *fixscript_dump_code(Heap *heap, Script *script, const char *func_name);
Returns newly allocated string representation of bytecode for given function (or all functions if not provided).
char *fixscript_dump_heap(Heap *heap);
Returns newly allocated string representation of heap values.

Optional asynchronous mode

There is an optional support for asynchronous mode that allows to have suspendable native functions and automatic suspension after processing of a number of instructions (for emulation of threads). The result is that the FixScript code is synchronous and the asynchronicity needs to be dealt with in native functions only.

This needs to be enabled by the FIXSCRIPT_ASYNC define. When compiling for the WebAssembly target it is automatically enabled. Use the FIXSCRIPT_NO_ASYNC define to disable it.

Currently enabling this mode disables the JIT compiler. There is no plan to add support for JIT in this mode except for platforms that require it for operation (WebAssembly only). Any other native platform is always able to manipulate the native stack therefore there is no need for this mode. However it might be simpler in some cases (and to be platform independent) to use this mode instead.

Types

typedef void (*ContinuationFunc)(void *data);
A general continuation function.
typedef void (*ContinuationResultFunc)(Heap *heap, Value result, Value error, void *data);
A continuation function that receives result from an asynchronous call.
typedef void (*ContinuationSuspendFunc)(ContinuationFunc resume_func, void *resume_data, void *data);
A continuation function that receives another continuation function for resuming the original processing.

Functions

void fixscript_set_auto_suspend_handler(Heap *heap, int num_instructions, ContinuationSuspendFunc func, void *data);
Sets the handler for automatic suspension after processing a number of instructions. The handler can cancel the suspension by calling the resume function immediately. It reuses the execution time limit feature which is automatically enabled for all heaps in asynchronous mode. Pass NULL as function to disable it.
Note: automatic suspension is disabled in token processors.
void fixscript_get_auto_suspend_handler(Heap *heap, int *num_instructions, ContinuationSuspendFunc *func, void **data);
Returns the handler for automatic suspension. All output parameters are optional.
void fixscript_suspend(Heap *heap, ContinuationResultFunc *func, void **data);
Suspends the native function. Returns the continuation function that needs to be called with the result. After calling this function the native function handler should just return. It is a fatal non-recoverable error to call this function when the FixScript code isn't called using the asynchronous variants of the call functions. Use the fixscript_in_async_call to check for this condition.
void fixscript_suspend_void(Heap *heap, ContinuationFunc *func, void **data);
An alternative variant of suspending for native functions that return no value. Uses a simpler continuation function type.
void fixscript_run_async(Heap *heap, Script *script, const char *func_name, Value *args, ContinuationResultFunc cont_func, void *cont_data);
Runs asynchronously function with given name (including parameter count in the name). After calling this function you should just return, leaving further processing to the provided continuation function.
void fixscript_call_async(Heap *heap, Value func, int num_params, Value *args, ContinuationResultFunc cont_func, void *cont_data);
A variant for asynchronous calling using a function reference.
void fixscript_allow_sync_call(Heap *heap);
This function must be called right before the normal (synchronous) call functions (fixscript_run and fixscript_call) to allow to run in synchronous mode from an asynchronous call. This is for special needs where you can't support asynchronous mode (for example when calling functions from native handles). The auto suspending is also automatically disabled in this mode.
int fixscript_in_async_call(Heap *heap);
Returns whether the heap is currently in asynchronous call.