|
|
@ -1,27 +1,54 @@ |
|
|
|
#pragma once |
|
|
|
#include "stddef.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; |
|
|
@ -30,12 +57,17 @@ struct fn { |
|
|
|
|
|
|
|
struct context; |
|
|
|
|
|
|
|
/** |
|
|
|
* Represents natively defined words within ink |
|
|
|
*/ |
|
|
|
struct native_fn { |
|
|
|
char *name; |
|
|
|
|
|
|
|
void (*value)(struct context *); |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Represents the narrow execution context of a single thread of execution within ink. |
|
|
|
*/ |
|
|
|
struct ink_routine { |
|
|
|
int panic; |
|
|
|
|
|
|
@ -46,24 +78,31 @@ struct ink_routine { |
|
|
|
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; |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* Represents a complete execution context for the ink interpreter |
|
|
|
*/ |
|
|
|
struct context { |
|
|
|
int panic; |
|
|
|
|
|
|
|
|
|
|
|
void *(*malloc)(size_t); |
|
|
|
|
|
|
|
void *(*realloc)(void *, size_t); |
|
|
|
|
|
|
|
void (*free)(void *); |
|
|
|
|
|
|
|
int (*putchar)(int); |
|
|
|
|
|
|
|
struct ink_routine *routines; |
|
|
|
int routines_capacity; |
|
|
|
int routines_top; |
|
|
|
|
|
|
|
/** |
|
|
|
* Contains the id of the routine that is currently being manipulated |
|
|
|
*/ |
|
|
|
int routine_current; |
|
|
|
|
|
|
|
struct native_fn *native_words; |
|
|
@ -79,25 +118,117 @@ struct context { |
|
|
|
int lex_reserved_words_top; |
|
|
|
|
|
|
|
unsigned int steps; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 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)(size_t), void *(*realloc)(void *, size_t), void(*free)(void *), int(*putchar)(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(); |
|
|
|
#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 |
|
|
|
*/ |
|
|
|
void ink_compile(struct context *pContext, 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); |
|
|
|
|
|
|
|
#ifdef __cplusplus |
|
|
|