|
|
- #pragma once
- #include "stddef.h"
- #include "stdint.h"
-
-
- /**
- * Represents the natively defined type of integers
- */
- #define INK_INTEGER 0
-
- /**
- * Represents the natively defined type of natively defined functions
- */
- #define INK_NATIVE_FUNCTION 1
-
- /**
- * Represents the natively defined type of functions defined from within ink
- */
- #define INK_FUNCTION 2
-
- /**
- * Represents the special coroutine state that means that it was disposed of and is ready for reuse
- */
- #define INK_ROUTINE_CAN_REUSE 32
-
- /**
- * Represents the special coroutine state that means that it was terminated without errors
- */
- #define INK_ROUTINE_SUCCESS 1
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /**
- * Represents arbitrary values within ink
- */
- struct elem {
- int type;
- int value;
- };
-
- /**
- * Represents a stack-frame within the execution context
- */
- struct stack_frame {
- struct elem executing;
- int index;
- };
-
- /**
- * Represents a function within ink, defined in ink, using the homoiconic representation of ink
- */
- struct fn {
- char *name;
- struct elem *things;
- int size;
- };
-
- struct context;
-
- /**
- * Represents natively defined words within ink
- */
- struct native_fn {
- char *name;
- void (*value)(struct context *);
- };
-
- struct parse_error {
- int is_set;
- const char* error_message;
- size_t offset;
- };
-
- struct runtime_error {
- int is_set;
- const char* error_message;
- };
-
- /**
- * Represents the narrow execution context of a single thread of execution within ink.
- */
- struct ink_routine {
- int panic;
-
- struct parse_error parse_error;
- struct runtime_error runtime_error;
-
- struct elem *stack;
- int capacity;
- int top;
-
- struct stack_frame *function_stack;
- int function_stack_capacity;
- int function_stack_top;
-
- /**
- * This user data can be set to any value convenient for the user to track a state local to the routine that is executing
- */
- void *routine_userdata;
- };
-
- /**
- * Contains a list of element on which garbage collection is to not be performed
- */
- struct ink_collection_list {
- struct elem* elements;
- int count;
- };
-
- /**
- * Contains the data and metadata of an embedded element including the pointer to the element
- */
- struct element_slab {
- void* data;
- int is_protected;
- int uses;
- int in_use;
- };
-
- /**
- * Contains all the data for every element of any type and its garbage collection information.
- */
- struct ink_type {
- const char* name; /**< The name of the type */
- int element_size; /**< The size of individual elements of the type, 0 for int adjacent, negative for unmanaged size */
- struct element_slab* elements; /**< The elements that are still live */
- int elements_top; /**< The top of the elements list */
- int elements_capacity; /**< The allocated capacity of the elements list */
- void (*collect)(struct context*,void*); /**< The "destructor" of the object */
- struct ink_collection_list (*gc)(struct context*,void*); /**< A function that returns an in-interpreter allocated list of elem references within the object */
- };
-
- /**
- * Represents a complete execution context for the ink interpreter
- */
- struct context {
- int panic;
-
- void *(*inner_malloc)(struct context*,size_t);
- void *(*inner_realloc)(struct context*,void *, size_t);
- void (*inner_free)(struct context*,void *);
-
- void *(*malloc)(struct context*,size_t);
- void *(*realloc)(struct context*,void *, size_t);
- void (*free)(struct context*,void *);
- int (*putchar)(struct context*,int);
-
- struct ink_routine *routines;
- int routines_capacity;
- int routines_top;
-
- struct ink_type *types;
- int types_capacity;
- int types_top;
-
- /**
- * Contains the id of the routine that is currently being manipulated
- */
- int routine_current;
-
- struct native_fn *native_words;
- int native_words_capacity;
- int native_words_top;
-
- struct fn *words;
- int words_capacity;
- int words_top;
-
- char **lex_reserved_words;
- int lex_reserved_words_capacity;
- int lex_reserved_words_top;
-
- unsigned int steps;
- unsigned int collections;
-
- /**
- * Can be set to any data that is convenient to the user to track and use within natively defined functions
- */
- void *persistent_userdata;
- };
-
- /**
- * Creates a routine to execute within the context
- * @param ctx The context in which to create the routine
- * @warning Does not set the `routine_current` of the context to the newly created routine
- * @return either a negative error value or the id of the created routine
- */
- int ink_make_routine(struct context *ctx);
-
- /**
- * Cleans the targeted routine id data from the context
- * @param ctx The context to operate in
- * @param routine The id of the routine to destroy
- * @return 0 if nothing could or needed to be performed, 1 otherwise
- */
- int ink_kill_routine(struct context *ctx, int routine);
-
- /**
- * Declares and defines a native function within the context
- * @param ctx The context tpo operate in
- * @param name The name to give to the newly declared word
- * @param value A pointer to a valid word-function
- * @return a negative value in case of error, 0 otherwise
- */
- int ink_add_native(struct context *ctx, const char *name, void(*value)(struct context *));
-
- /**
- * Pushes a value on the current routine's value stack
- * @param ctx The context to manipulate
- * @param value The value to push
- * @return 0 on success, a negative value on failure
- */
- int ink_push(struct context *ctx, struct elem value);
-
- /**
- * Pushes a function on the execution stack of the current routine of the context
- * @param ctx The context to operate in
- * @param value the function that will be pushed. in the state one wants it to run from
- * @return 0 on success, a negative value on failure
- */
- int ink_push_fn(struct context *ctx, struct stack_frame value);
-
- /**
- * Create a context to execute routines
- * @param malloc the memory allocation function, with a signature similar to the standard malloc
- * @param realloc the memory allocation function, with a signature similar to the standard realloc
- * @param free the memory allocation function, with a signature similar to the standard free
- * @param putchar a function to print to the output character by character
- * @return a pointer to a context allocated within the malloc function itself.
- */
- struct context* ink_make_context(void*(*malloc)(struct context*, size_t), void*(*realloc)(struct context*, void*, size_t), void(*free)(struct context*, void*), int(*putchar)(struct context*, int));
-
- /**
- * Create a context to execute routines in-place
- * @param location a pointer to where the context should be built, userdata can be set in advance
- * @param malloc the memory allocation function, with a signature similar to the standard malloc
- * @param realloc the memory allocation function, with a signature similar to the standard realloc
- * @param free the memory allocation function, with a signature similar to the standard free
- * @param putchar a function to print to the output character by character
- * @return a pointer to a context allocated within the malloc function itself.
- */
- void ink_make_context_inplace(struct context* location, void*(*malloc)(struct context*, size_t), void*(*realloc)(struct context*, void*, size_t), void(*free)(struct context*, void*), int(*putchar)(struct context*, int));
-
- #ifndef NOSTDLIB
- /**
- * Creates a context that includes the standard library of ink, as well as uses the C standard library to operate
- * @return a pointer to a context allocated with malloc and with predefined functions added
- */
- struct context* ink_make_default_context(void);
- #endif
-
- /**
- * Steps the current routine by one execution step
- * @param pContext The context of the routine to advance
- * @return A negative value in case of error, 0 if execution is finished, a positive value if more steps are required to execute
- */
- int ink_step(struct context *pContext);
-
- /**
- * Examine the context to see if any routines can execute
- * @param pContext the context
- * @return 0 if no coroutines are available, 1 otherwise
- */
- int ink_can_run(struct context *pContext);
-
- /**
- * Step every routine that can be executed.
- * @param pContext The context, the `routine_current` value may be modified.
- * @return 0
- */
- int ink_step_everyone(struct context *pContext);
-
- /**
- * Compiles the code and starts a main routine to execute it
- * @param pContext The context to execute the code in
- * @param buffer The buffer that contains the source as a NULL terminated string
- * @return the routine that was created when compiling the code or -1 in case an error occured
- */
- int ink_compile(struct context *pContext, const char *buffer);
-
- /**
- * Includes the standard library in the specified context
- * @param ctx The context
- * @return 0
- */
- int ink_std_library(struct context *ctx);
-
- /**
- * Removes the top element of the function stack of the current routine of the specified context
- * @param ctx the context
- */
- void ink_pop_fn(struct context *ctx);
-
- /**
- * Removes the top element of the stack of the current routine of the specified context
- * @param ctx the context
- */
- void ink_pop(struct context *ctx);
-
- /**
- * Declares a new type that can be stored within the interpreter
- * @param ctx The context in which to add the file
- * @param type_name The name of the type we want to add
- * @param size The size in bytes of the type to add, size of 0 mean no size, in which case the type is adjacent to C int, negative size means that the memory is not managed by the interpreter.
- * @param collect A "destructor" function for the data
- * @param gc A function that returns a list (allocated with the `inner_malloc`) of all the elements this element holds references to
- * @return if positive, a new type id, if negative an error value
- * @internal user defined type ids minimal value is 15, we keep the first 16 types as reserved, just like negative type ids
- */
- int ink_new_type(
- struct context* ctx,
- const char* type_name,
- int size,
- void (*collect)(struct context*,void*),
- struct ink_collection_list (*gc)(struct context*,void*)
- );
-
- /**
- *
- * @param ctx The context of the interpreter
- * @param ref The in-interpreter reference
- * @return A pointer to the created value or NULL if it can't be found or has a size of 0
- */
- void* ink_get_value(struct context* ctx, struct elem ref);
-
- /**
- * Builds a native type from the provided memory by copying it using memcpy
- * @param ctx The context in which we operate
- * @param type_id The type_id to use
- * @param ptr The pointer from which to copy
- * @return The in-interpreter reference of the newly created element
- */
- struct elem ink_make_native(struct context* ctx, int type_id, void* ptr);
-
- /**
- * Builds a transparent type from the provided pointer
- * @param ctx The context in which we operate
- * @param type_id The type_id to use
- * @param ptr The pointer
- * @return The in-interpreter reference of the newly created element
- */
- struct elem ink_make_transparent(struct context* ctx, int type_id, void* ptr);
-
- /**
- * Launch the mark and sweep garbage collection
- * @param ctx The context to clean
- */
- void ink_gc(struct context* ctx);
-
- /**
- * Cleans up coroutine stacks before reuse
- * @param ctx
- */
- void ink_clean_routines(struct context* ctx);
-
- /**
- * Obtains the type id from the declared name of the type
- * @param ctx The context where we want to detect the type
- * @param name The name of the type
- * @return the type id if it exists, -1 otherwise
- */
- int get_type_by_name(struct context* ctx, const char* name);
-
- /**
- * The internal representation of arrays in ink
- */
- struct ink_array {
- int top;
- int capacity;
- struct elem* elements;
- uint16_t flags;
- };
-
- /**
- * Pushes a value in an array. in case of failure, panics the routine
- *
- * @param ctx the working context
- * @param currentRoutine the routine that will panic
- * @param ary the array to be incremented
- * @param value the value to push
- */
- void array_push(struct context* ctx, struct ink_routine* currentRoutine, struct ink_array* ary, struct elem value);
-
- #ifdef __cplusplus
- };
- #endif
|