diff --git a/README.md b/README.md index 7d0c706..2b175b1 100644 --- a/README.md +++ b/README.md @@ -26,4 +26,106 @@ It is possible to segregate unsafe allocations (allocations that should be hidde - 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 \ No newline at end of file +- 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 +``` diff --git a/lib.c b/lib.c index 49a2289..cfd8542 100644 --- a/lib.c +++ b/lib.c @@ -461,9 +461,16 @@ static int ink_lex(struct context *pContext, char* buffer) { int end; int err; end = 0; - +restart_after_comment: while(*buffer != 0) { if(isspace(*buffer)) { + if(end == 1 && r[0] == '#') { + while(*buffer != '\n' && *buffer != 0) { + ++buffer; + } + end = 0; + goto restart_after_comment; + } err = ink_consume_one(&end, pContext, &buffer, r); if(err < 0) { pContext->panic = 1; @@ -1084,7 +1091,7 @@ static void print_stacktrace(struct context* _) { break; } case INK_FUNCTION:{ - n = _->native_words[thing.value].name; + n = _->words[thing.value].name; while (*n) { _->putchar(*n); ++n; @@ -1095,7 +1102,6 @@ static void print_stacktrace(struct context* _) { _->putchar(*n); ++n; } - _->free(n); _->putchar(10); break; } @@ -1197,7 +1203,7 @@ static void is_equal(struct context* ctx) { ink_pop(ctx); ret.type = INK_INTEGER; ret.value = a.value == b.value && a.type == b.type; - + ink_push(ctx, ret); } static void is_different(struct context* ctx) { @@ -1216,7 +1222,7 @@ static void is_different(struct context* ctx) { ink_pop(ctx); ret.type = INK_INTEGER; ret.value = !(a.value == b.value && a.type == b.type); - + ink_push(ctx, ret); } #ifndef NOEXTRAARITHMETIC @@ -1404,24 +1410,26 @@ static void return_if(struct context* ctx) { static void jump_if(struct context* ctx) { struct ink_routine* currentRoutine; - struct elem a; + struct elem label; + struct elem condition; currentRoutine = ctx->routines + ctx->routine_current; - if(currentRoutine->top < 1) { + if(currentRoutine->top < 2) { ctx->panic = -1; return; } - a = currentRoutine->stack[currentRoutine->top-1]; - if(a.type != INK_INTEGER) { + label = currentRoutine->stack[currentRoutine->top-1]; + condition = currentRoutine->stack[currentRoutine->top-2]; + if(label.type != INK_INTEGER || condition.type != INK_INTEGER) { ctx->panic = -1; return; } ink_pop(ctx); - if(a.value) { - ink_pop_fn(ctx); - a = currentRoutine->stack[currentRoutine->top-1]; - currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += a.value - 3; - } ink_pop(ctx); + ink_pop_fn(ctx); + if(condition.value) { + currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += label.value - 2; + } + return; } @@ -1681,6 +1689,42 @@ static void index_array(struct context* ctx) { ink_push(ctx, ary->elements[idx.value]); } +static void set_array(struct context* ctx) { + int tid; + struct ink_routine *currentRoutine; + struct elem a; + struct ink_array *ary; + struct elem idx; + struct elem value; + + tid = get_type_by_name(ctx, "array"); + currentRoutine = ctx->routines + ctx->routine_current; + if (currentRoutine->top < 3 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) { + currentRoutine->panic = -1; + return; + } + a = currentRoutine->stack[currentRoutine->top - 1]; + ary = ink_get_value(ctx, a); + if (ary == NULL) { + currentRoutine->panic = -1; + return; + } + + idx = currentRoutine->stack[currentRoutine->top - 2]; + value = currentRoutine->stack[currentRoutine->top - 3]; + + if(ary->top <= idx.value) { + currentRoutine->panic = -1; + return; + } + ink_pop(ctx); + ink_pop(ctx); + ink_pop(ctx); + + ary->elements[idx.value] = value; + +} + static void get_size_array(struct context* ctx) { int tid; struct ink_routine *currentRoutine; @@ -1799,6 +1843,7 @@ int ink_std_library(struct context* ctx) { v += ink_add_native(ctx, "array.new", new_array); v += ink_add_native(ctx, "array.push", push_array); v += ink_add_native(ctx, "array.index", index_array); + v += ink_add_native(ctx, "array.set", set_array); v += ink_add_native(ctx, "array.size", get_size_array); v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints); v += ink_add_native(ctx, "stack.to_array", arrayify_stack); diff --git a/main.c b/main.c index cbe4d79..76ae18a 100644 --- a/main.c +++ b/main.c @@ -1,15 +1,22 @@ #include "ink.h" #include +#include int main(int argc, char** argv) { char read_buffer[2048]; - struct context* ctx = ink_make_default_context(); - char** end_argv = argv + argc; + clock_t begin, end; + double time_spent; + struct context* ctx; + char** end_argv; + ctx = ink_make_default_context(); + end_argv = argv + argc; for(argv+=1; argv != end_argv; argv++) { - FILE* file = fopen(*argv, "r"); - size_t cnt = fread(read_buffer, 1, 2047, file); + FILE* file; + size_t cnt; + file = fopen(*argv, "r"); + cnt = fread(read_buffer, 1, 2047, file); if(cnt == 0) { - + fprintf(stderr, "Can't read file !! -> %s\n", *argv); } read_buffer[cnt] = 0; ink_compile(ctx, read_buffer); @@ -21,10 +28,13 @@ int main(int argc, char** argv) { fclose(file); } + begin = clock(); while(ink_can_run(ctx)) { ink_step_everyone(ctx); } ink_gc(ctx); - printf("\nExecuted in %u steps\nCollected %u times\n", ctx->steps, ctx->collections); + end = clock(); + time_spent = ctx->steps/((double)(end - begin) / CLOCKS_PER_SEC); + printf("\nExecuted in %u steps\nCollected %u times\nExecution freq: %uHz\n", ctx->steps, ctx->collections, (unsigned int)time_spent); return ctx->panic; } \ No newline at end of file diff --git a/test/test01.nk b/test/test01.nk index 41cf486..f7889c6 100644 --- a/test/test01.nk +++ b/test/test01.nk @@ -18,4 +18,57 @@ fn potato3 do -1 + dup 66 print_utf8 10 print_utf8 start swap jump_if +end + +# 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 + drop drop drop end \ No newline at end of file diff --git a/test/test02.nk b/test/test02.nk index 3fc8712..4045d79 100644 --- a/test/test02.nk +++ b/test/test02.nk @@ -1,3 +1,27 @@ fn print_n_utf8 do print_n_utf8_impl drop end + +# 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 == l 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 + l: drop drop swap drop + # new_array +end diff --git a/test/test03.nk b/test/test03.nk index c850e4b..e69de29 100644 --- a/test/test03.nk +++ b/test/test03.nk @@ -1,9 +0,0 @@ -4 potato2 - -fn u do - -loop: - 65 print_int -loop 1 jump_if - -end \ No newline at end of file diff --git a/test/test04.nk b/test/test04.nk index 79f5b5e..e69de29 100644 --- a/test/test04.nk +++ b/test/test04.nk @@ -1 +0,0 @@ -4 potato3 diff --git a/test/test06.nk b/test/test06.nk index 5b74eee..7624c4c 100644 --- a/test/test06.nk +++ b/test/test06.nk @@ -1 +1,59 @@ -[ 72 101 108 108 111 32 87 111 114 108 100 10 ] array.print_utf8 \ No newline at end of file +# This says Hello World + +[ 72 101 108 108 111 32 87 111 114 108 100 10 ] + +# This prints the array above + +array.print_utf8 + +[ 72 101 108 108 111 32 87 111 114 108 100 10 ] +# original +dup array.clone dup +# original cloned cloned +32 128 encrypt +# original cloned +string.dump +10 print_utf8 +string.dump + +# We encrypt 6 times in a row +[ 84 104 105 115 32 105 115 32 97 110 32 101 120 97 109 112 108 101 32 111 102 32 116 101 120 116 32 116 111 32 98 101 32 101 110 99 114 121 112 116 101 100 32 116 119 105 99 101 46 ] +dup array.clone +dup +33 128 encrypt +dup +57 128 encrypt +dup +91 128 encrypt +dup +33 128 encrypt +dup +57 128 encrypt +dup +91 128 encrypt + +# Print encrypted +dup +10 print_utf8 +string.dump + +# We decrypt in reverse order with a key that is the modular inverse of the original (adjacent to subtraction) +dup +128 91 - 128 encrypt +dup +128 57 - 128 encrypt +dup +128 33 - 128 encrypt +dup +128 91 - 128 encrypt +dup +128 57 - 128 encrypt +dup +128 33 - 128 encrypt + +# Print encrypted then decrypted +10 print_utf8 +string.dump +# Print never encrypted +10 print_utf8 +string.dump