A minimalistic programming language written in C89.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 rivejä
10 KiB

6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
6 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
5 kuukautta sitten
  1. #pragma once
  2. #include "stddef.h"
  3. /**
  4. * Represents the natively defined type of integers
  5. */
  6. #define INK_INTEGER 0
  7. /**
  8. * Represents the natively defined type of natively defined functions
  9. */
  10. #define INK_NATIVE_FUNCTION 1
  11. /**
  12. * Represents the natively defined type of functions defined from within ink
  13. */
  14. #define INK_FUNCTION 2
  15. /**
  16. * Represents the special coroutine state that means that it was disposed of and is ready for reuse
  17. */
  18. #define INK_ROUTINE_CAN_REUSE 32
  19. /**
  20. * Represents the special coroutine state that means that it was terminated without errors
  21. */
  22. #define INK_ROUTINE_SUCCESS 1
  23. #ifdef __cplusplus
  24. extern "C" {
  25. #endif
  26. /**
  27. * Represents arbitrary values within ink
  28. */
  29. struct elem {
  30. int type;
  31. int value;
  32. };
  33. /**
  34. * Represents a stack-frame within the execution context
  35. */
  36. struct stack_frame {
  37. struct elem executing;
  38. int index;
  39. };
  40. /**
  41. * Represents a function within ink, defined in ink, using the homoiconic representation of ink
  42. */
  43. struct fn {
  44. char *name;
  45. struct elem *things;
  46. int size;
  47. };
  48. struct context;
  49. /**
  50. * Represents natively defined words within ink
  51. */
  52. struct native_fn {
  53. char *name;
  54. void (*value)(struct context *);
  55. };
  56. /**
  57. * Represents the narrow execution context of a single thread of execution within ink.
  58. */
  59. struct ink_routine {
  60. int panic;
  61. struct elem *stack;
  62. int capacity;
  63. int top;
  64. struct stack_frame *function_stack;
  65. int function_stack_capacity;
  66. int function_stack_top;
  67. /**
  68. * This user data can be set to any value convenient for the user to track a state local to the routine that is executing
  69. */
  70. void *routine_userdata;
  71. };
  72. /**
  73. * Contains a list of element on which garbage collection is to not be performed
  74. */
  75. struct ink_collection_list {
  76. struct elem* elements;
  77. int count;
  78. };
  79. /**
  80. * Contains the data and metadata of an embedded element including the pointer to the element
  81. */
  82. struct element_slab {
  83. void* data;
  84. int uses;
  85. int in_use;
  86. };
  87. /**
  88. * Contains all the data for every element of any type and its garbage collection information.
  89. */
  90. struct ink_type {
  91. const char* name; /**< The name of the type */
  92. int element_size; /**< The size of individual elements of the type, 0 for int adjacent, negative for unmanaged size */
  93. struct element_slab* elements; /**< The elements that are still live */
  94. int elements_top; /**< The top of the elements list */
  95. int elements_capacity; /**< The allocated capacity of the elements list */
  96. void (*collect)(struct context*,void*); /**< The "destructor" of the object */
  97. struct ink_collection_list (*gc)(struct context*,void*); /**< A function that returns an in-interpreter allocated list of elem references within the object */
  98. };
  99. /**
  100. * Represents a complete execution context for the ink interpreter
  101. */
  102. struct context {
  103. int panic;
  104. void *(*inner_malloc)(size_t);
  105. void *(*inner_realloc)(void *, size_t);
  106. void (*inner_free)(void *);
  107. void *(*malloc)(size_t);
  108. void *(*realloc)(void *, size_t);
  109. void (*free)(void *);
  110. int (*putchar)(int);
  111. struct ink_routine *routines;
  112. int routines_capacity;
  113. int routines_top;
  114. struct ink_type *types;
  115. int types_capacity;
  116. int types_top;
  117. /**
  118. * Contains the id of the routine that is currently being manipulated
  119. */
  120. int routine_current;
  121. struct native_fn *native_words;
  122. int native_words_capacity;
  123. int native_words_top;
  124. struct fn *words;
  125. int words_capacity;
  126. int words_top;
  127. char **lex_reserved_words;
  128. int lex_reserved_words_capacity;
  129. int lex_reserved_words_top;
  130. unsigned int steps;
  131. unsigned int collections;
  132. /**
  133. * Can be set to any data that is convenient to the user to track and use within natively defined functions
  134. */
  135. void *persistent_userdata;
  136. };
  137. /**
  138. * Creates a routine to execute within the context
  139. * @param ctx The context in which to create the routine
  140. * @warning Does not set the `routine_current` of the context to the newly created routine
  141. * @return either a negative error value or the id of the created routine
  142. */
  143. int ink_make_routine(struct context *ctx);
  144. /**
  145. * Cleans the targeted routine id data from the context
  146. * @param ctx The context to operate in
  147. * @param routine The id of the routine to destroy
  148. * @return 0 if nothing could or needed to be performed, 1 otherwise
  149. */
  150. int ink_kill_routine(struct context *ctx, int routine);
  151. /**
  152. * Declares and defines a native function within the context
  153. * @param ctx The context tpo operate in
  154. * @param name The name to give to the newly declared word
  155. * @param value A pointer to a valid word-function
  156. * @return a negative value in case of error, 0 otherwise
  157. */
  158. int ink_add_native(struct context *ctx, const char *name, void(*value)(struct context *));
  159. /**
  160. * Pushes a value on the current routine's value stack
  161. * @param ctx The context to manipulate
  162. * @param value The value to push
  163. * @return 0 on success, a negative value on failure
  164. */
  165. int ink_push(struct context *ctx, struct elem value);
  166. /**
  167. * Pushes a function on the execution stack of the current routine of the context
  168. * @param ctx The context to operate in
  169. * @param value the function that will be pushed. in the state one wants it to run from
  170. * @return 0 on success, a negative value on failure
  171. */
  172. int ink_push_fn(struct context *ctx, struct stack_frame value);
  173. /**
  174. * Create a context to execute routines
  175. * @param malloc the memory allocation function, with a signature similar to the standard malloc
  176. * @param realloc the memory allocation function, with a signature similar to the standard realloc
  177. * @param free the memory allocation function, with a signature similar to the standard free
  178. * @param putchar a function to print to the output character by character
  179. * @return a pointer to a context allocated within the malloc function itself.
  180. */
  181. struct context* ink_make_context(void *(*malloc)(size_t), void *(*realloc)(void *, size_t), void(*free)(void *), int(*putchar)(int));
  182. #ifndef NOSTDLIB
  183. /**
  184. * Creates a context that includes the standard library of ink, as well as uses the C standard library to operate
  185. * @return a pointer to a context allocated with malloc and with predefined functions added
  186. */
  187. struct context* ink_make_default_context(void);
  188. #endif
  189. /**
  190. * Steps the current routine by one execution step
  191. * @param pContext The context of the routine to advance
  192. * @return A negative value in case of error, 0 if execution is finished, a positive value if more steps are required to execute
  193. */
  194. int ink_step(struct context *pContext);
  195. /**
  196. * Examine the context to see if any routines can execute
  197. * @param pContext the context
  198. * @return 0 if no coroutines are available, 1 otherwise
  199. */
  200. int ink_can_run(struct context *pContext);
  201. /**
  202. * Step every routine that can be executed.
  203. * @param pContext The context, the `routine_current` value may be modified.
  204. * @return 0
  205. */
  206. int ink_step_everyone(struct context *pContext);
  207. /**
  208. * Compiles the code and starts a main routine to execute it
  209. * @param pContext The context to execute the code in
  210. * @param buffer The buffer that contains the source as a NULL terminated string
  211. */
  212. void ink_compile(struct context *pContext, const char *buffer);
  213. /**
  214. * Includes the standard library in the specified context
  215. * @param ctx The context
  216. * @return 0
  217. */
  218. int ink_std_library(struct context *ctx);
  219. /**
  220. * Removes the top element of the function stack of the current routine of the specified context
  221. * @param ctx the context
  222. */
  223. void ink_pop_fn(struct context *ctx);
  224. /**
  225. * Removes the top element of the stack of the current routine of the specified context
  226. * @param ctx the context
  227. */
  228. void ink_pop(struct context *ctx);
  229. /**
  230. * Declares a new type that can be stored within the interpreter
  231. * @param ctx The context in which to add the file
  232. * @param type_name The name of the type we want to add
  233. * @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.
  234. * @param collect A "destructor" function for the data
  235. * @param gc A function that returns a list (allocated with the `inner_malloc`) of all the elements this element holds references to
  236. * @return if positive, a new type id, if negative an error value
  237. * @internal user defined type ids minimal value is 15, we keep the first 16 types as reserved, just like negative type ids
  238. */
  239. int ink_new_type(
  240. struct context* ctx,
  241. const char* type_name,
  242. int size,
  243. void (*collect)(struct context*,void*),
  244. struct ink_collection_list (*gc)(struct context*,void*)
  245. );
  246. /**
  247. *
  248. * @param ctx The context of the interpreter
  249. * @param ref The in-interpreter reference
  250. * @return A pointer to the created value or NULL if it can't be found or has a size of 0
  251. */
  252. void* ink_get_value(struct context* ctx, struct elem ref);
  253. /**
  254. * Builds a native type from the provided memory by copying it using memcpy
  255. * @param ctx The context in which we operate
  256. * @param type_id The type_id to use
  257. * @param ptr The pointer from which to copy
  258. * @return The in-interpreter reference of the newly created element
  259. */
  260. struct elem ink_make_native(struct context* ctx, int type_id, void* ptr);
  261. /**
  262. * Builds a transparent type from the provided pointer
  263. * @param ctx The context in which we operate
  264. * @param type_id The type_id to use
  265. * @param ptr The pointer
  266. * @return The in-interpreter reference of the newly created element
  267. */
  268. struct elem ink_make_transparent(struct context* ctx, int type_id, void* ptr);
  269. /**
  270. * Launch the mark and sweep garbage collection
  271. * @param ctx The context to clean
  272. */
  273. void ink_gc(struct context* ctx);
  274. /**
  275. * Obtains the type id from the declared name of the type
  276. * @param ctx The context where we want to detect the type
  277. * @param name The name of the type
  278. * @return the type id if it exists, -1 otherwise
  279. */
  280. int get_type_by_name(struct context* ctx, const char* name);
  281. /**
  282. * The internal representation of arrays in ink
  283. */
  284. struct ink_array {
  285. int top;
  286. int capacity;
  287. struct elem* elements;
  288. };
  289. /**
  290. * Pushes a value in an array. in case of failure, panics the routine
  291. *
  292. * @param ctx the working context
  293. * @param currentRoutine the routine that will panic
  294. * @param ary the array to be incremented
  295. * @param value the value to push
  296. */
  297. void array_push(struct context* ctx, struct ink_routine* currentRoutine, struct ink_array* ary, struct elem value);
  298. #ifdef __cplusplus
  299. };
  300. #endif