Browse Source

Added more internals and control flow

main
Ludovic 'Archivist' Lagouardette 7 months ago
parent
commit
3014191951
6 changed files with 295 additions and 34 deletions
  1. +2
    -1
      ink.h
  2. +270
    -31
      lib.c
  3. +5
    -0
      main.c
  4. +14
    -1
      test/test01.nk
  5. +3
    -1
      test/test02.nk
  6. +1
    -0
      test/test03.nk

+ 2
- 1
ink.h View File

@ -33,6 +33,7 @@ struct context {
void*(*malloc)(size_t);
void*(*realloc)(void*, size_t);
void(*free)(void*);
int(*putchar)(int);
struct elem* stack;
int capacity;
@ -58,7 +59,7 @@ struct context {
void ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*));
void ink_push(struct context* ctx, struct elem value);
void ink_push_fn(struct context* ctx, struct stack_frame value);
struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*));
struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int));
struct context* ink_make_default_context();
int ink_step(struct context *pContext);
void ink_run(struct context *pContext, char* buffer);

+ 270
- 31
lib.c View File

@ -1,7 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef NOSTDLIB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#endif
#include "ink.h"
#define INK_RESERVED (-1)
@ -14,6 +17,7 @@
#define _KEYWORD_INK_FUNCTION "fn"
#define _KEYWORD_INK_DO "do"
#define _KEYWORD_INK_END "end"
#define _KEYWORD_INK_RETURN "return"
struct label {
int active;
@ -21,6 +25,79 @@ struct label {
char* name;
};
#ifdef NOSTDLIB
static size_t strlen(const char* c) {
size_t j = 0;
while(*(c++)) {
j++;
}
return j;
}
static void* memcpy(void* _dest, const void* _src, size_t sz) {
char* dest = _dest;
const char* src = _src;
while(sz--) {
*(dest++) = *(src++);
}
return dest;
}
static int strcmp(const char* dest, const char* src) {
while(*dest != 0 && *src != 0) {
if(*(dest++) != *(src++)) {
return 1;
}
}
return 0;
}
static void* memmove(void* _dest, const void* _src, size_t sz) {
char* dest = _dest;
const char* src = _src;
if (src < dest) {
src += sz;
dest += sz;
while (sz-- > 0) {
*--dest = *--src;
}
} else {
while (sz-- > 0) {
*dest++ = *src++;
}
}
return dest;
}
static void* memset(void* _dest, int src, size_t sz) {
char* dest = _dest;
while(sz--) {
*(dest++) = src++;
}
return dest;
}
static int isspace(int d) {
return d == ' ' || d == '\t' || d == '\n';
}
static int isdigit(int d) {
return '0' <= d && d <= '9';
}
static int atoi(const char* c) {
int ret = 0;
while(*c) {
ret *= 10;
ret += *c - '0';
++c;
}
return ret;
}
#endif
void ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
if(ctx->native_words == NULL) {
ctx->native_words = ctx->malloc(sizeof(struct native_fn) * 8);
@ -67,7 +144,7 @@ static int ink_add_indigenous(struct context* ctx, const char* name, struct elem
for(i = 0; i < ctx->words_top; ++i) {
if(strcmp(name, ctx->words[i].name) == 0) {
ctx->free(ctx->words[i].things);
ctx->words[i].things = malloc(sizeof(struct elem) * count);
ctx->words[i].things = ctx->malloc(sizeof(struct elem) * count);
memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
ctx->words[i].size = count;
return i;
@ -80,7 +157,7 @@ static int ink_add_indigenous(struct context* ctx, const char* name, struct elem
}
memcpy(copy, name, len);
copy[len] = 0;
ctx->words[ctx->words_top].things = malloc(sizeof(struct elem) * count);
ctx->words[ctx->words_top].things = ctx->malloc(sizeof(struct elem) * count);
memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
ctx->words[ctx->words_top].size = count;
ctx->words[ctx->words_top].name = copy;
@ -110,7 +187,7 @@ static int ink_add_lex_string(struct context* ctx, const char* name) {
}
int len = strlen(name);
i = ctx->lex_reserved_words_top;
ctx->lex_reserved_words[i] = malloc(len+1);
ctx->lex_reserved_words[i] = ctx->malloc(len+1);
memcpy(ctx->lex_reserved_words[i], name, len);
ctx->lex_reserved_words[i][len] = 0;
ctx->lex_reserved_words_top++;
@ -167,11 +244,12 @@ static void ink_pop(struct context* ctx) {
ctx->top--;
}
struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*)) {
struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int)) {
struct context* ctx = (struct context*)malloc(sizeof(struct context));
ctx->malloc = malloc;
ctx->realloc = realloc;
ctx->free = free;
ctx->putchar = putchar;
ctx->panic = 0;
ctx->stack = NULL;
ctx->capacity = 0;
@ -191,17 +269,55 @@ struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*,
return ctx;
}
/**
* Allocates a string that contains the integer
* @param _ context (used to allocate)
* @param cpy the value
* @return the allocated string, needs to be freed by ctx->free
*/
static char* ink_itoa(struct context* _, int cpy) {
char* n = _->malloc(16);
n[15] = 0;
char* it = n+15;
do {
it--;
*it = (cpy % 10) + '0';
cpy = cpy / 10;
} while(cpy);
memmove(n, it, 16 - (it-n));
return n;
}
static void print_stacktrace(struct context* _) {
int i = 0;
for(; i < _->function_stack_top; ++i) {
struct elem thing = _->function_stack[i].executing;
switch(thing.type) {
case INK_NATIVE_FUNCTION:
printf("%s\n", _->native_words[thing.value].name);
case INK_NATIVE_FUNCTION: {
char *n = _->native_words[thing.value].name;
while (*n) {
_->putchar(*n);
++n;
}
_->putchar(10);
break;
case INK_FUNCTION:
printf("%s:%d\n", _->words[thing.value].name, _->function_stack[i].index);
}
case INK_FUNCTION:{
char *n = _->native_words[thing.value].name;
while (*n) {
_->putchar(*n);
++n;
}
_->putchar(':');
n = ink_itoa(_, _->function_stack[i].index);
while (*n) {
_->putchar(*n);
++n;
}
_->free(n);
_->putchar(10);
break;
}
default:
break;
}
@ -223,6 +339,92 @@ static void add_int(struct context* ctx) {
ctx->stack[ctx->top-1].value = a.value + b.value;
}
static void dupe_elem(struct context* ctx) {
if(ctx->top < 1) {
ctx->panic = 1;
return;
}
struct elem a = ctx->stack[ctx->top-1];
ink_push(ctx, a);
}
static void drop_elem(struct context* ctx) {
if(ctx->top < 1) {
ctx->panic = 1;
return;
}
ink_pop(ctx);
}
static void pluck_elem(struct context* ctx) {
if(ctx->top < 1) {
ctx->panic = 1;
return;
}
struct elem a = ctx->stack[ctx->top-1];
if(a.type != INK_INTEGER) {
ctx->panic = 1;
return;
}
int position = ctx->top - (a.value + 1);
if(position >= ctx->top || position < 0) {
ctx->panic = 1;
return;
}
ink_pop(ctx);
ink_push(ctx, ctx->stack[position]);
}
static void swap_elem(struct context* ctx) {
if(ctx->top < 2) {
ctx->panic = 1;
return;
}
struct elem a = ctx->stack[ctx->top-1];
struct elem b = ctx->stack[ctx->top-2];
ctx->stack[ctx->top-2] = a;
ctx->stack[ctx->top-1] = b;
}
static void return_if(struct context* ctx) {
if(ctx->top < 1) {
ctx->panic = 1;
return;
}
struct elem a = ctx->stack[ctx->top-1];
if(a.type != INK_INTEGER) {
ctx->panic = 1;
return;
}
if(a.value) {
ink_pop_fn(ctx);
ink_pop_fn(ctx);
}
ink_pop(ctx);
return;
}
static void jump_if(struct context* ctx) {
if(ctx->top < 1) {
ctx->panic = 1;
return;
}
struct elem a = ctx->stack[ctx->top-1];
if(a.type != INK_INTEGER) {
ctx->panic = 1;
return;
}
ink_pop(ctx);
if(a.value) {
ink_pop_fn(ctx);
a = ctx->stack[ctx->top-1];
ctx->function_stack[ctx->function_stack_top - 1].index += a.value - 3;
ink_pop(ctx);
//printf("\t*%d\n", ctx->function_stack[ctx->function_stack_top - 1].index);
}
return;
}
static void print_int(struct context* ctx) {
if(ctx->top < 1 || ctx->stack[ctx->top-1].type != INK_INTEGER) {
ctx->panic = 1;
@ -230,7 +432,13 @@ static void print_int(struct context* ctx) {
}
struct elem a = ctx->stack[ctx->top-1];
ink_pop(ctx);
printf("%d", a.value);
char* n = ink_itoa(ctx, a.value);
char* str = n;
while (*str) {
ctx->putchar(*str);
++str;
}
ctx->free(n);
}
static void print_as_utf8(struct context* ctx) {
@ -240,19 +448,19 @@ static void print_as_utf8(struct context* ctx) {
}
struct elem a = ctx->stack[ctx->top-1];
if(a.value <= 0x7F) {
putc(a.value, stdout);
ctx->putchar(a.value);
} else if(a.value <= 0x7FF) {
putc(((a.value & 0xFC0) >> 6) | 192, stdout);
putc((a.value & 0x3F) | 128, stdout);
ctx->putchar(((a.value & 0xFC0) >> 6) | 192);
ctx->putchar((a.value & 0x3F) | 128);
} else if(a.value <= 0xFFFF) {
putc(((a.value & 0x3F000) >> 12) | 224, stdout);
putc(((a.value & 0xFC0) >> 6) | 128, stdout);
putc((a.value & 0x3F) | 128, stdout);
ctx->putchar(((a.value & 0x3F000) >> 12) | 224);
ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
ctx->putchar((a.value & 0x3F) | 128);
} else if(a.value <= 0x10FFFF) {
putc(((a.value & 0x3C0000) >> 18) | 240, stdout);
putc(((a.value & 0x3F000) >> 12) | 128, stdout);
putc(((a.value & 0xFC0) >> 6) | 128, stdout);
putc((a.value & 0x3F) | 128, stdout);
ctx->putchar(((a.value & 0x3C0000) >> 18) | 240);
ctx->putchar(((a.value & 0x3F000) >> 12) | 128);
ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
ctx->putchar((a.value & 0x3F) | 128);
} else {
ctx->panic = 1;
return;
@ -260,14 +468,22 @@ static void print_as_utf8(struct context* ctx) {
ink_pop(ctx);
}
#ifndef NOSTDLIB
struct context* ink_make_default_context() {
struct context* ctx = ink_make_context(malloc, realloc, free);
struct context* ctx = ink_make_context(malloc, realloc, free, putchar);
ink_add_native(ctx, "trace", print_stacktrace);
ink_add_native(ctx, "print_int", print_int);
ink_add_native(ctx, "print_utf8", print_as_utf8);
ink_add_native(ctx, "+", add_int);
ink_add_native(ctx, "swap", swap_elem);
ink_add_native(ctx, "dup", dupe_elem);
ink_add_native(ctx, "drop", drop_elem);
ink_add_native(ctx, "pluck", pluck_elem);
ink_add_native(ctx, "return_if", return_if);
ink_add_native(ctx, "jump_if", jump_if);
return ctx;
}
#endif
static void ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) {
int i;
@ -297,6 +513,13 @@ static void ink_consume_one(int* end, struct context* pContext, char** buffer, c
ink_push(pContext, value);
done = 1;
}
if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) {
struct elem value;
value.value = 0;
value.type = INK_RETURN;
ink_push(pContext, value);
done = 1;
}
if (!done) {
for (i = 0; i < pContext->words_top; ++i) {
if (strcmp(r, pContext->words[i].name) == 0) {
@ -375,17 +598,26 @@ static int lblcmp(const char* label, const char* other, size_t label_sz) {
return 0;
}
/**
*
* @param pContext
* @param executable_buffer
* @param executable_buffer_top
* @internal Loop from hell
*/
static void ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
int i;
struct label labels[128];
struct elem function_buffer[256];
#define LABEL_BUFFER 128
#define FUNCTION_BUFFER 256
struct label labels[LABEL_BUFFER];
struct elem function_buffer[FUNCTION_BUFFER];
int function_buffer_top = 0;
int function_name = -1;
#define MODE_EXECUTABLE 0
#define MODE_FUNCTION 1
#define MODE_DO 2
int mode = 0;
memset(labels, 0, sizeof(struct label)*mi">128);
memset(labels, 0, sizeof(struct label)*n">LABEL_BUFFER);
for(i = 0; i < pContext->top; ++i) {
struct elem current = pContext->stack[i];
switch (mode) {
@ -427,7 +659,7 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer,
struct elem pt = function_buffer[j];
if(pt.type == INK_LABEL) {
int k;
for(k = 0; k < mi">128; k++) {
for(k = 0; k < n">LABEL_BUFFER; k++) {
if(labels[k].active) {
if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
labels[k].dest = j;
@ -451,7 +683,7 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer,
if(pt.type == INK_RESERVED) {
const char* str = pContext->lex_reserved_words[pt.value];
int k;
for(k = 0; k < mi">128; k++) {
for(k = 0; k < n">LABEL_BUFFER; k++) {
if(labels[k].active) {
const char* lbl = labels[k].name;
int label_sz = strlen(lbl);
@ -481,12 +713,14 @@ static void ink_parse(struct context* pContext, struct elem* executable_buffer,
#undef MODE_EXECUTABLE
#undef MODE_FUNCTION
#undef MODE_DO
#undef LABEL_BUFFER
#undef FUNCTION_BUFFER
}
int ink_step(struct context *pContext) {
if(pContext->function_stack_top == 0) return 0;
if(pContext->panic) {
perror("PANIC!!!\n");
return -1;
}
struct stack_frame* top = &pContext->function_stack[pContext->function_stack_top-1];
@ -511,8 +745,13 @@ int ink_step(struct context *pContext) {
if(top->index >= pContext->words[top->executing.value].size) {
ink_pop_fn(pContext);
} else {
struct elem next = pContext->words[top->executing.value].things[top->index];
if(next.type == INK_RETURN) {
ink_pop_fn(pContext);
return 1;
}
struct stack_frame frame;
frame.executing = pContext->words[top->executing.value].things[top->index];
frame.executing = next;
frame.index = 0;
ink_push_fn(pContext, frame);
top->index++;

+ 5
- 0
main.c View File

@ -13,6 +13,11 @@ int main(int argc, char** argv) {
}
read_buffer[cnt] = 0;
ink_run(ctx, read_buffer);
if(ctx->panic) {
perror("Panicked !!");
}
fclose(file);
}

+ 14
- 1
test/test01.nk View File

@ -1,3 +1,16 @@
fn potato do
label: trace trace label print_int 10 print_utf8 endfn print_int 10 print_utf8 endfn:
trace return
end
fn print_n_utf8_impl do
start:
-1 + swap print_utf8
dup start swap jump_if
end
fn potato2 do
start:
-1 + dup
65 print_utf8 10 print_utf8
start swap jump_if
end

+ 3
- 1
test/test02.nk View File

@ -1 +1,3 @@
potato potato
fn print_n_utf8 do
print_n_utf8_impl drop
end

+ 1
- 0
test/test03.nk View File

@ -0,0 +1 @@
100 108 114 111 119 32 111 108 108 101 72 11 print_n_utf8

Loading…
Cancel
Save