A minimalistic programming language written in C89.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

387 lignes
12 KiB

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