# `ink` `ink` is a minimalistic interpreted programming language, tentatively implemented exclusively in C89. It features coroutines and can currently only manipulate integers. Part of the code may not be compliant with C89 and I will try to fix that in time. It is fully self-contained and doesn't rely on a working standard library beyond the following: - `malloc` - `realloc` - `free` - `putchar` To make the library not use the standard library, build it with `NOSTDLIB` defined as a preprocessor directive. All of these functions need to work for `ink` to work. It is easy to add new functions to the interpreter. I added a garbage collector to handle cleaning dynamically allocated resources. It is possible to segregate unsafe allocations (allocations that should be hidden from the interpreter) by setting the `inner_` versions of the library functions to different allocation functions. ## Limits - Token size is limited to 127 bytes (see `ink_lex`) - Values and indices are limited to the platform size of `int` - Main function has a size limit of 256 tokens (see `ink_compile`) - Functions have a size limit of 256 tokens (see `ink_parse`) - Functions have a count limit 128 labels (see `ink_parse`) - Only non-main functions can use labels ## Examples ### Hello World ``` [ 72 101 108 108 111 32 87 111 114 108 100 10 ] array.print_utf8 ``` ### Clone array ```asm # Clones an array, creating a new array # # @param array The array to clone into a new array # @return a new array that contains the same elements as the source array # # array -> new_array fn array.clone do array.new 2 pluck array.size 0 # array new_array end it 2 pluck 2 pluck == end_loop jump_if # array new_array end it loop: dup 5 pluck # array new_array end it it array array.index 4 pluck # array new_array end it v new_array array.push # array new_array end it 1 + 2 pluck 2 pluck > loop jump_if end_loop: drop drop swap drop # new_array end ``` ### `+%` encryption Encrypts a string with `(v + add_key) % modulo_key`. It modifies the array that was passed in. ```asm # Encrypts things by doing `(v + add_key) % modulo_key` # # @param array An array of ints representing a string # @param add_key Should be lower than the add key # @param modulo_key Should ke higher than all the codepoints of the array # # array add_key modulo_key fn encrypt do 3 pluck array.size # array add_key modulo_key index loop: 1 - dup 5 pluck # array add_key modulo_key index index array array.index # array add_key modulo_key index v 4 pluck + # array add_key modulo_key index (v + add_key) 3 pluck % # array add_key modulo_key index ((v + add_key) % modulo_key) 2 pluck # array add_key modulo_key index ((v + add_key) % modulo_key) index 6 pluck # array add_key modulo_key index ((v + add_key) % modulo_key) index array array.set # array add_key modulo_key index dup 0 != loop jump_if drop drop drop drop end # Prints a string as an array of ints # # @param array An array of ints representing a string # # array fn string.dump do dup array.size 0 # array end it 91 print_utf8 32 print_utf8 loop: dup # array end it it 4 pluck # array end it it array array.index print_int 32 print_utf8 1 + # array end it 2 pluck 2 pluck > loop jump_if # array end it 93 print_utf8 end ``` ```asm [ 72 101 108 108 111 32 87 111 114 108 100 10 ] dup 32 128 encrypt string.dump ```