Permalink
Browse files

all: add grouped eval

  • Loading branch information...
hellerve committed Nov 19, 2018
1 parent f29d163 commit 0e448179847b36bf1b25ea5134e3aba63169a45b
Showing with 108 additions and 33 deletions.
  1. +1 −1 Makefile
  2. +16 −13 src/debug.c
  3. +17 −7 src/eval.c
  4. +70 −12 src/parser.c
  5. +4 −0 src/parser.h
@@ -4,7 +4,7 @@ PREFIX=/usr/local/bin/
SOURCES=$(wildcard src/*.c)
MAIN=main.c
override CFLAGS+=-std=c11 -O2 -Wno-gnu
DEVFLAGS=-Werror -Wall -g -fPIC -DNDEBUG -Wfloat-equal -Wundef -Wwrite-strings -Wuninitialized -pedantic
DEVFLAGS=-Werror -Wall -g -fPIC -DNDEBUG -Wfloat-equal -Wundef -Wwrite-strings -Wuninitialized -pedantic -fsanitize=address -O0

all: main.c
mkdir -p $(BUILDDIR)
@@ -3,25 +3,28 @@
#include "debug.h"

void print_bytecode(bytecode* code) {
#define print(i, s, ind) (printf("%4d: %*s%s\n", i, ind, "", s))
#define print_arg(i, s, a, ind) (printf("%4d: %*s%s %d\n", i, ind, "", s, a))
#define print(s) (printf("%4d: %*s%s\n", i, indent, "", s))
#define print_arg(s) (printf("%4d: %*s%s %d\n", i, indent, "", s, c.arg))
int i = 0;
int indent = 0;
while(1) {
bytecode c = code[i++];
switch (c.code) {
case INC: print(i, "inc", indent); break;
case DEC: print(i, "dec", indent); break;
case FWD: print(i, "fwd", indent); break;
case BCK: print(i, "bck", indent); break;
case PRN: print(i, "prn", indent); break;
case ZERO: print(i, "zero", indent); break;
case READ: print(i, "read", indent); break;
case STARTL: print_arg(i, "start loop", c.arg, indent); indent += 2; break;
case ENDL: indent -= 2; print_arg(i, "end loop", c.arg, indent); break;
case INC: print_arg("inc"); break;
case DEC: print_arg("dec"); break;
case FWD: print_arg("fwd"); break;
case BCK: print_arg("bck"); break;
case PRN: print("prn"); break;
case ZERO: print("zero"); break;
case READ: print("read"); break;
case STARTL: print_arg("start loop"); indent += 2; break;
case ENDL: indent -= 2; print_arg("end loop"); break;

case SEND: print_arg(i, "send", c.arg, indent); break;
case RECV: print(i, "receive", indent); break;
case SEND: print_arg("send"); break;
case RECV: print("receive"); break;

case MOVE_PTR: print_arg("move ptr"); break;
case MOVE_DATA: print_arg("move data"); break;

case HALT: return;
}
@@ -30,23 +30,24 @@ void* eval(void* arg) {
bytecode c;
static void* dispatch_table[] = {
&&do_zero, &&do_inc, &&do_dec, &&do_fwd, &&do_bck, &&do_prn, &&do_read,
&&do_startl, &&do_endl, &&do_send, &&do_recv, &&do_halt
&&do_startl, &&do_endl, &&do_send, &&do_recv, &&do_move_ptr, &&do_move_data,
&&do_halt
};

for (int idx = 0; idx < TAPE_LEN; idx++) t[idx] = 0;

DISPATCH();
do_zero: t[h] = 0; DISPATCH();
do_inc: t[h]++; DISPATCH();
do_dec: t[h]--; DISPATCH();
do_inc: t[h]+=c.arg; DISPATCH();
do_dec: t[h]-=c.arg; DISPATCH();
#ifdef NO_WRAP
do_fwd: h++; DISPATCH();
do_bck: h--; DISPATCH();
do_fwd: h += c.arg; DISPATCH();
do_bck: h -= c.arg; DISPATCH();
#else
// modulo would be prettier here, but slows the code down by A LOT; somehow
// the C compilers can’t optimize uncoditional modulos here
do_fwd: h = h == TAPE_LEN-1 ? 0 : h+1; DISPATCH();
do_bck: h = h == 0 ? TAPE_LEN-1 : h-1; DISPATCH();
do_fwd: h += c.arg; if (h >= TAPE_LEN-1) h %=TAPE_LEN; DISPATCH();
do_bck: h -= c.arg; if (h < 0) h %= TAPE_LEN; DISPATCH();
#endif
do_prn: printf("%c", t[h]); DISPATCH();
do_read: scanf("%c", (char*)&t[h]); DISPATCH();
@@ -84,6 +85,15 @@ do_endl: if(t[h]) i = c.arg; DISPATCH();
}
DISPATCH();

do_move_ptr: while (t[h]) h+=c.arg; DISPATCH();

do_move_data:
if (t[h]) {
t[h+c.arg] += t[h];
t[h] = 0;
}
DISPATCH();

do_halt:
return NULL;
#undef DISPATCH
@@ -6,6 +6,7 @@
int getmatchbck(char* str, char* end) {
int last_depth[256];
int cur_depth = 0;
int dup = 0;
char* start = str;

for (int i = 0; i < 256; i++) last_depth[i] = 0;
@@ -14,11 +15,20 @@ int getmatchbck(char* str, char* end) {
while (str++ < end) {
switch(*str) {
case '[':
last_depth[cur_depth++] = str-start;
last_depth[cur_depth++] = str-start-dup;
break;
case ']':
cur_depth--;
break;
case '>':
case '<':
case '+':
case '-': {
char c = *str;
while (*(++str)==c) dup++;
str--;
break;
}
}
}

@@ -27,7 +37,7 @@ int getmatchbck(char* str, char* end) {
return last_depth[cur_depth];
}

int getmatchfwd(char* str, char* begin) {
int getmatchfwd(char* str, char* begin, int dup) {
int cur_depth = 1;

while (cur_depth) {
@@ -38,12 +48,21 @@ int getmatchfwd(char* str, char* begin) {
case ']':
cur_depth--;
break;
case '>':
case '<':
case '+':
case '-': {
char c = *str;
while (*(++str)==c) dup++;
str--;
break;
}
case '\0': return -1;
}
str++;
}

return str-begin;
return str-begin-dup;
}

char* remove_comments(char* inpt) {
@@ -75,8 +94,6 @@ char* remove_comments(char* inpt) {
return inpt;
}

#include <stdio.h>

char* optimize_zero(char* inpt) {
char* str = inpt;
int ln = strlen(inpt);
@@ -92,12 +109,47 @@ char* optimize_zero(char* inpt) {
return inpt;
}

#include <stdio.h>

int optimize_loop(bytecode* s, int begin, int end) {
if (begin < 30) printf("eeeeeend: %d %d\n", begin, end);
bytecode rep = s[begin];
if (end-begin == 2 && (rep.code == FWD || rep.code == BCK)) {
// [>] || [<] == MOVE_PTR
int narg = rep.code == FWD ? rep.arg : -rep.arg;
s[begin-1] = (bytecode){.code=MOVE_PTR, .arg=narg};
return 2;
} else if (end-begin == 5 && rep.code == DEC && s[begin+3].code == INC &&
rep.arg == s[begin+3].arg == 1) {
// [->+<] || [-<+>] == MOVE_DATA
if (s[begin+2].code == FWD && s[begin+4].code == BCK &&
s[begin+2].arg == s[begin+4].arg) {
s[begin+1] = (bytecode){.code=MOVE_DATA, .arg=s[begin+2].arg};
s[begin+2] = (bytecode){.code=ENDL, .arg=begin};
s = realloc(s, begin+3);
return 3;
} else if (s[begin+2].code == BCK && s[begin+4].code == FWD &&
s[begin+2].arg == s[begin+4].arg) {
s[begin+1] = (bytecode){.code=MOVE_DATA, .arg=-s[begin+2].arg};
s[begin+2] = (bytecode){.code=ENDL, .arg=begin};
return 3;
}
}
return 0;
}

actors* parse(char* inpt) {
#define build_op(c, a) {\
res = realloc(res, sizeof(bytecode)*(++idx));\
res[idx-1] = (bytecode){.code=c, .arg=a};\
}
#define build_cumulative_op(c) {\
if (idx > 0 && res[idx-1].code == c) { res[idx-1].arg++; dup++; }\
else build_op(c, 1);\
}
int idx = 0;
int dup = 0;
int elided = 0;
char* str = inpt;
actors* ac = malloc(sizeof(actors));
ac->num = 0;
@@ -108,15 +160,15 @@ actors* parse(char* inpt) {

while (*inpt != '\0') {
switch (*inpt) {
case '+': build_op(INC, 0); break;
case '-': build_op(DEC, 0); break;
case '>': build_op(FWD, 0); break;
case '<': build_op(BCK, 0); break;
case '+': build_cumulative_op(INC); break;
case '-': build_cumulative_op(DEC); break;
case '>': build_cumulative_op(FWD); break;
case '<': build_cumulative_op(BCK); break;
case '.': build_op(PRN, 0); break;
case ',': build_op(READ, 0); break;
case '0': build_op(ZERO, 0); break;
case '0': build_cumulative_op(ZERO); break;
case '[': {
int matching_end = getmatchfwd(inpt+1, str);
int matching_end = getmatchfwd(inpt+1, str, dup);
if (matching_end < 0) {
free_actors(ac);
free(res);
@@ -134,7 +186,12 @@ actors* parse(char* inpt) {
return NULL;
}

build_op(ENDL, matching_begin+1);
build_op(ENDL, matching_begin+1-elided);
//int removed = optimize_loop(res, matching_begin+1, idx+elided);
//idx -= removed;
//dup += removed;
//elided += removed;
//res = realloc(res, sizeof(bytecode)*idx);
break;
}

@@ -166,6 +223,7 @@ actors* parse(char* inpt) {

return ac;
#undef build_op
#undef build_cumulative_op
}

void free_actors(actors* ac) {
@@ -14,6 +14,10 @@ enum BYTECODES {

SEND,
RECV,

MOVE_PTR,
MOVE_DATA,

HALT,
};

0 comments on commit 0e44817

Please sign in to comment.