Browse Source

Sol Part 63: DO YOU THINK THIS IS A GAME?

Version bump to 0.3a4!
master
Graham Northup 5 years ago
parent
commit
0822b69fb2
Signed by: grissess GPG Key ID: 5D000E6F539376FB
  1. 1
      .gitignore
  2. 43
      Makefile
  3. 5
      RECIPES
  4. 65
      builtins.c
  5. 323
      lex.yy.c
  6. 14651
      parser.output
  7. 1404
      parser.tab.c
  8. 119
      parser.tab.h
  9. 59
      parser.y
  10. 671
      programs/chip8.sol
  11. 12
      programs/interp.sol
  12. 15
      runtime.c
  13. 4
      ser.c
  14. 16
      sol.h
  15. 6
      solrun.c
  16. 54
      state.c
  17. 28
      tests/lang_elseif.sol
  18. 2
      tokenizer.lex

1
.gitignore

@ -14,3 +14,4 @@ _build
doxyxml
valgrind.log
*_INFO
prof

43
Makefile

@ -1,6 +1,6 @@
CFLAGS= -g $(BUILD_DEFINES)
LDFLAGS= -lfl -lm -ldl -lreadline
OBJ= lex.yy.o parser.tab.o dsl/seq.o dsl/list.o dsl/array.o dsl/generic.o astprint.o runtime.o gc.o object.o state.o builtins.o solrun.o ser.o sol_help.o
override CFLAGS:= -g $(BUILD_DEFINES) $(CFLAGS)
override LDFLAGS:= -lfl -lm -ldl -lreadline $(LDFLAGS)
OBJ= lex.yy.o parser.tab.o dsl/seq.o dsl/list.o dsl/array.o dsl/generic.o astprint.o runtime.o gc.o object.o state.o builtins.o solrun.o ser.o
ifndef CC
CC:= gcc
@ -18,12 +18,22 @@ ifndef DESTDIR
DESTDIR:= /usr/local/
endif
ifdef NO_HELP
override CFLAGS+= -DNO_HELP
else
OBJ+= sol_help.o
endif
ifndef STDOUT_FILENAME
STDOUT_FILENAME:=/dev/fd/1
endif
include VERSION_INFO
include ARCH_INFO
BUILD_DEFINES:= -DSOL_BUILD_HOST="\"$(shell uname -n)\"" -DSOL_BUILD_KERNEL="\"$(shell uname -s)\"" -DSOL_BUILD_ARCH="\"$(shell uname -m)\"" -DSOL_BUILD_REV="\"$(shell git rev-parse --short HEAD)$(shell git diff-index --quiet HEAD || echo '-dirty')\""
SOL_VER:=$(MAJOR).$(MINOR)$(RELEASE)$(PATCH)
SOL_VER:=$(MAJOR).$(MINOR)$(RELEASE)$(PATCH)$(SUFFIX)
LINKED_VERS:=sol sol$(MAJOR) sol$(MAJOR).$(MINOR)
.PHONY: install install_bin install_bindir install_lib install_libdir uninstall uninstall_bin uninstall_lib all test clean docs
@ -66,7 +76,30 @@ test_%: tests/%.sol
./sol r $?
testcomp_%: tests/%.sol
./sol rc $? /dev/fd/1 | ./sol C
./sol rc $? $(STDOUT_FILENAME) | ./sol C
profile: all prof profile-boot $(sort $(patsubst tests/%.sol,profile_%,$(wildcard tests/*.sol))) profilecomp-boot $(sort $(patsubst tests/%.sol,profilecomp_%,$(wildcard tests/*.sol)))
prof:
mkdir prof
profile-boot: programs/test.sol
LLVM_PROFILE_FILE=prof/boot.prof ./sol r $?
profile_%: tests/%.sol
LLVM_PROFILE_FILE=prof/sol.$(basename $(notdir $?)).prof ./sol r $?
profilecomp-boot: programs/test.sol
LLVM_PROFILE_FILE=prof/bootcomp.comp.prof ./sol rc $? $(STDOUT_FILENAME) | LLVM_PROFILE_FILE=prof/bootcomp.run.prof ./sol C
profilecomp_%: tests/%.sol
LLVM_PROFILE_FILE=prof/solcomp.$(basename $(notdir $?)).comp.prof ./sol rc $? $(STDOUT_FILENAME) | LLVM_PROFILE_FILE=prof/solcomp.$(basename $(notdir $?)).run.prof ./sol C
prof/sol.html: profile
llvm-profdata merge -sparse prof/*.prof -o prof/sol.prof.merged
llvm-cov show -instr-profile prof/sol.prof.merged ./sol -format=html > $@
all-profile: prof/sol.html
dsl:
git submodule init && git submodule sync && git submodule update

5
RECIPES

@ -0,0 +1,5 @@
WASM/asm.js:
make CC=emcc CFLAGS=-DNO_READLINE NO_HELP=1
clang for profiling:
make CC=clang CFLAGS="-fprofile-instr-generate -fcoverage-mapping"

65
builtins.c

@ -4,8 +4,12 @@
#include <math.h>
#include <stdint.h>
#include <dlfcn.h>
#ifndef NO_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#include <termios.h>
#include <sys/ioctl.h>
#include "ast.h"
#include "dsl/dsl.h"
@ -484,6 +488,7 @@ sol_object_t *sol_f_debug_scopes(sol_state_t *state, sol_object_t *args) {
return sol_incref(state->scopes);
}
#ifndef NO_READLINE
sol_object_t *sol_f_readline_readline(sol_state_t *state, sol_object_t *args) {
sol_object_t *obj, *objstr, *res;
char *line;
@ -512,6 +517,7 @@ sol_object_t *sol_f_readline_add_history(sol_state_t *state, sol_object_t *args)
sol_obj_free(line);
return sol_incref(state->None);
}
#endif
void _sol_freef_seq_iter(void *iter, size_t sz) {
dsl_free_seq_iter((dsl_seq_iter *) iter);
@ -1290,6 +1296,30 @@ sol_object_t *sol_f_list_filter(sol_state_t *state, sol_object_t *args) {
return list;
}
sol_object_t *sol_f_list_reduce(sol_state_t *state, sol_object_t *args) {
sol_object_t *list = sol_list_get_index(state, args, 0), *func = sol_list_get_index(state, args, 1);
sol_object_t *val = sol_list_get_index(state, args, 2), *newval;
sol_object_t *fargs = sol_new_list(state), *item;
int idx = 0, len = sol_list_len(state, list);
sol_list_insert(state, fargs, 0, func);
sol_list_insert(state, fargs, 1, state->None);
sol_list_insert(state, fargs, 2, state->None);
while(idx < len) {
item = sol_list_get_index(state, list, idx);
sol_list_set_index(state, fargs, 1, val);
sol_list_set_index(state, fargs, 2, item);
sol_obj_free(item);
newval = CALL_METHOD(state, func, call, fargs);
sol_obj_free(val);
val = newval;
idx++;
}
sol_obj_free(list);
sol_obj_free(func);
sol_obj_free(fargs);
return val;
}
sol_object_t *sol_f_map_add(sol_state_t *state, sol_object_t *args) {
sol_object_t *a = sol_list_get_index(state, args, 0), *b = sol_list_get_index(state, args, 1), *map;
if(!sol_is_map(b)) {
@ -1592,7 +1622,13 @@ sol_object_t *sol_f_func_tostring(sol_state_t *state, sol_object_t *args) {
sol_object_t *sol_f_cfunc_call(sol_state_t *state, sol_object_t *args) {
sol_object_t *func = sol_list_get_index(state, args, 0), *fargs = sol_list_sublist(state, args, 1);
sol_object_t *res = func->cfunc(state, fargs);
sol_object_t *res = NULL, *tmp = NULL;
sol_list_insert(state, state->fnstack, 0, func);
res = func->cfunc(state, fargs);
tmp = sol_list_remove(state, state->fnstack, 0);
if(tmp != func) {
printf("ERROR: Function stack imbalance\n");
}
sol_obj_free(func);
sol_obj_free(fargs);
return res;
@ -2642,7 +2678,7 @@ sol_object_t *sol_f_stream_write(sol_state_t *state, sol_object_t *args) {
return sol_new_int(state, sz);
}
sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
sol_object_t *sol_f_stream_read_buffer(sol_state_t *state, sol_object_t *args) {
sol_object_t *stream = sol_list_get_index(state, args, 0), *amt = sol_list_get_index(state, args, 1), *iamt, *res;
char *s = NULL, *p;
size_t count = 0, max = 0, pos, end;
@ -2660,22 +2696,21 @@ sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
sol_obj_free(amt);
return sol_set_error_string(state, "IO read error");
}
s[end - pos] = '\0';
count = end - pos;
} else if(sol_string_eq(state, amt, "LINE")) {
s = malloc(STDIO_CHUNK_SIZE * sizeof(char));
sol_stream_fgets(state, stream, s, STDIO_CHUNK_SIZE);
count = strlen(s);
}
} else {
iamt = sol_cast_int(state, amt);
s = malloc((iamt->ival + 1) * sizeof(char));
count = sol_stream_fread(state, stream, s, sizeof(char), iamt->ival);
s[count] = '\0';
sol_obj_free(iamt);
}
if(s) {
//printf("IO: Read result: %s\n", s);
res = sol_new_string(state, s);
free(s);
res = sol_new_buffer(state, s, count, OWN_FREE, NULL, NULL);
} else {
//printf("IO: No read result!\n");
res = sol_incref(state->None);
@ -2685,6 +2720,13 @@ sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
return res;
}
sol_object_t *sol_f_stream_read(sol_state_t *state, sol_object_t *args) {
sol_object_t *buf = sol_f_stream_read_buffer(state, args);
sol_object_t *str = sol_new_string(state, buf->buffer);
sol_obj_free(buf);
return str;
}
sol_object_t *sol_f_stream_seek(sol_state_t *state, sol_object_t *args) {
sol_object_t *stream = sol_list_get_index(state, args, 0), *offset = sol_list_get_index(state, args, 1), *whence = sol_list_get_index(state, args, 2);
sol_object_t *ioffset = sol_cast_int(state, offset), *iwhence = sol_cast_int(state, whence);
@ -2715,6 +2757,17 @@ sol_object_t *sol_f_stream_eof(sol_state_t *state, sol_object_t *args) {
return res;
}
sol_object_t *sol_f_stream_ioctl(sol_state_t *state, sol_object_t *args) {
sol_object_t *stream = sol_list_get_index(state, args, 0), *buf = sol_list_get_index(state, args, 2);
sol_object_t *req = sol_list_get_index(state, args, 1), *ireq = sol_cast_int(state, req);
sol_object_t *res = sol_new_int(state, ioctl(fileno(stream->stream), (unsigned long) ireq->ival, buf->buffer));
sol_obj_free(stream);
sol_obj_free(buf);
sol_obj_free(req);
sol_obj_free(ireq);
return res;
}
static char *sol_FileModes[] = {
NULL,
"r",

323
lex.yy.c

@ -431,8 +431,8 @@ static void yynoreturn yy_fatal_error ( const char* msg );
(yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
#define YY_NUM_RULES 73
#define YY_END_OF_BUFFER 74
#define YY_NUM_RULES 74
#define YY_END_OF_BUFFER 75
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@ -440,25 +440,25 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static const flex_int16_t yy_accept[152] =
static const flex_int16_t yy_accept[154] =
{ 0,
0, 0, 74, 73, 72, 34, 73, 68, 23, 26,
73, 62, 63, 21, 19, 67, 20, 64, 22, 2,
65, 66, 51, 40, 52, 70, 70, 70, 70, 59,
60, 28, 70, 70, 70, 70, 70, 70, 70, 70,
70, 70, 70, 70, 70, 70, 57, 27, 58, 29,
72, 61, 72, 0, 50, 0, 3, 30, 46, 0,
4, 25, 43, 41, 0, 42, 44, 1, 2, 56,
53, 49, 54, 55, 70, 70, 70, 70, 48, 70,
70, 70, 11, 70, 70, 70, 70, 70, 5, 10,
70, 70, 70, 33, 70, 70, 70, 70, 47, 32,
72, 61, 69, 45, 0, 71, 1, 70, 70, 70,
31, 70, 70, 70, 17, 70, 9, 70, 70, 24,
35, 70, 70, 70, 70, 70, 18, 37, 70, 70,
7, 70, 12, 70, 70, 6, 36, 70, 39, 15,
70, 38, 70, 70, 8, 70, 13, 14, 70, 16,
0
0, 0, 75, 74, 73, 35, 74, 69, 24, 27,
74, 63, 64, 22, 20, 68, 21, 65, 23, 2,
66, 67, 52, 41, 53, 71, 71, 71, 71, 60,
61, 29, 71, 71, 71, 71, 71, 71, 71, 71,
71, 71, 71, 71, 71, 71, 58, 28, 59, 30,
73, 62, 73, 0, 51, 0, 3, 31, 47, 0,
4, 26, 44, 42, 0, 43, 45, 1, 2, 57,
54, 50, 55, 56, 71, 71, 71, 71, 49, 71,
71, 71, 12, 71, 71, 71, 71, 71, 5, 11,
71, 71, 71, 34, 71, 71, 71, 71, 48, 33,
73, 62, 70, 46, 0, 72, 1, 71, 71, 71,
32, 71, 71, 71, 18, 71, 10, 71, 71, 25,
36, 71, 71, 71, 71, 71, 19, 38, 71, 71,
7, 71, 13, 71, 71, 6, 37, 71, 40, 16,
71, 71, 39, 71, 71, 9, 71, 8, 14, 15,
71, 17, 0
} ;
static const YY_CHAR yy_ec[256] =
@ -503,49 +503,49 @@ static const YY_CHAR yy_meta[53] =
1, 1
} ;
static const flex_int16_t yy_base[156] =
static const flex_int16_t yy_base[158] =
{ 0,
0, 51, 169, 170, 52, 52, 163, 170, 170, 49,
158, 170, 170, 46, 144, 170, 44, 170, 143, 44,
170, 170, 42, 142, 47, 0, 132, 119, 117, 170,
170, 138, 117, 114, 114, 113, 25, 41, 37, 124,
111, 110, 108, 116, 38, 113, 170, 54, 170, 170,
75, 170, 78, 145, 170, 143, 170, 170, 170, 138,
170, 124, 170, 170, 142, 170, 170, 126, 71, 170,
170, 170, 170, 170, 0, 103, 100, 94, 170, 106,
104, 96, 0, 92, 102, 95, 90, 91, 0, 0,
91, 97, 84, 0, 83, 93, 80, 88, 170, 170,
88, 170, 170, 170, 122, 170, 106, 78, 87, 86,
0, 89, 73, 83, 0, 72, 0, 83, 83, 0,
0, 67, 71, 77, 71, 68, 0, 0, 63, 63,
0, 65, 0, 65, 53, 0, 0, 61, 0, 0,
53, 0, 63, 51, 0, 45, 0, 0, 51, 0,
170, 104, 106, 81, 108
0, 51, 171, 172, 52, 52, 165, 172, 172, 49,
160, 172, 172, 46, 146, 172, 44, 172, 145, 44,
172, 172, 42, 144, 47, 0, 134, 121, 119, 172,
172, 140, 119, 116, 116, 115, 25, 41, 37, 126,
113, 112, 110, 118, 38, 115, 172, 54, 172, 172,
75, 172, 78, 147, 172, 145, 172, 172, 172, 140,
172, 126, 172, 172, 144, 172, 172, 128, 71, 172,
172, 172, 172, 172, 0, 105, 102, 96, 172, 108,
106, 98, 0, 94, 104, 97, 92, 93, 0, 0,
93, 99, 86, 0, 85, 95, 82, 90, 172, 172,
88, 172, 172, 172, 124, 172, 108, 80, 89, 88,
0, 91, 75, 85, 0, 74, 0, 85, 85, 0,
0, 69, 73, 79, 73, 77, 0, 0, 72, 65,
64, 66, 0, 66, 55, 0, 0, 62, 0, 0,
54, 59, 0, 63, 51, 0, 45, 0, 0, 0,
51, 0, 172, 104, 106, 81, 108
} ;
static const flex_int16_t yy_def[156] =
static const flex_int16_t yy_def[158] =
{ 0,
151, 1, 151, 151, 151, 151, 152, 151, 151, 151,
153, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 154, 154, 154, 154, 151,
151, 151, 154, 154, 154, 154, 154, 154, 154, 154,
154, 154, 154, 154, 154, 154, 151, 151, 151, 151,
151, 151, 151, 151, 151, 152, 151, 151, 151, 153,
151, 151, 151, 151, 155, 151, 151, 151, 151, 151,
151, 151, 151, 151, 154, 154, 154, 154, 151, 154,
154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
154, 154, 154, 154, 154, 154, 154, 154, 151, 151,
151, 151, 151, 151, 155, 151, 151, 154, 154, 154,
154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
0, 151, 151, 151, 151
153, 1, 153, 153, 153, 153, 154, 153, 153, 153,
155, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 156, 156, 156, 156, 153,
153, 153, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 153, 153, 153, 153,
153, 153, 153, 153, 153, 154, 153, 153, 153, 155,
153, 153, 153, 153, 157, 153, 153, 153, 153, 153,
153, 153, 153, 153, 156, 156, 156, 156, 153, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 153, 153,
153, 153, 153, 153, 157, 153, 153, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
156, 156, 0, 153, 153, 153, 153
} ;
static const flex_int16_t yy_nxt[223] =
static const flex_int16_t yy_nxt[225] =
{ 0,
4, 5, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
@ -555,26 +555,26 @@ static const flex_int16_t yy_nxt[223] =
49, 50, 51, 53, 53, 54, 58, 62, 65, 68,
52, 69, 70, 71, 84, 66, 85, 63, 73, 74,
59, 86, 89, 55, 96, 99, 101, 53, 90, 53,
53, 97, 75, 87, 102, 150, 68, 88, 69, 101,
53, 149, 148, 147, 146, 145, 144, 102, 143, 142,
141, 140, 139, 100, 56, 56, 60, 60, 105, 105,
138, 137, 136, 135, 134, 133, 132, 131, 130, 129,
128, 127, 126, 107, 106, 125, 124, 123, 122, 121,
120, 119, 118, 117, 116, 115, 114, 113, 112, 111,
110, 109, 108, 107, 106, 104, 61, 57, 103, 98,
95, 94, 93, 92, 91, 83, 82, 81, 80, 79,
78, 77, 76, 72, 67, 64, 61, 57, 151, 3,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151
53, 97, 75, 87, 102, 152, 68, 88, 69, 101,
53, 151, 150, 149, 148, 147, 146, 102, 145, 144,
143, 142, 141, 100, 56, 56, 60, 60, 105, 105,
140, 139, 138, 137, 136, 135, 134, 133, 132, 131,
130, 129, 128, 127, 126, 107, 106, 125, 124, 123,
122, 121, 120, 119, 118, 117, 116, 115, 114, 113,
112, 111, 110, 109, 108, 107, 106, 104, 61, 57,
103, 98, 95, 94, 93, 92, 91, 83, 82, 81,
80, 79, 78, 77, 76, 72, 67, 64, 61, 57,
153, 3, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153
} ;
static const flex_int16_t yy_chk[223] =
static const flex_int16_t yy_chk[225] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -584,23 +584,23 @@ static const flex_int16_t yy_chk[223] =
1, 1, 2, 5, 5, 6, 10, 14, 17, 20,
2, 20, 23, 23, 37, 17, 37, 14, 25, 25,
10, 38, 39, 6, 45, 48, 51, 51, 39, 53,
53, 45, 154, 38, 51, 149, 69, 38, 69, 101,
101, 146, 144, 143, 141, 138, 135, 101, 134, 132,
130, 129, 126, 48, 152, 152, 153, 153, 155, 155,
125, 124, 123, 122, 119, 118, 116, 114, 113, 112,
110, 109, 108, 107, 105, 98, 97, 96, 95, 93,
92, 91, 88, 87, 86, 85, 84, 82, 81, 80,
78, 77, 76, 68, 65, 62, 60, 56, 54, 46,
44, 43, 42, 41, 40, 36, 35, 34, 33, 32,
29, 28, 27, 24, 19, 15, 11, 7, 3, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151, 151, 151, 151, 151, 151, 151, 151, 151,
151, 151
53, 45, 156, 38, 51, 151, 69, 38, 69, 101,
101, 147, 145, 144, 142, 141, 138, 101, 135, 134,
132, 131, 130, 48, 154, 154, 155, 155, 157, 157,
129, 126, 125, 124, 123, 122, 119, 118, 116, 114,
113, 112, 110, 109, 108, 107, 105, 98, 97, 96,
95, 93, 92, 91, 88, 87, 86, 85, 84, 82,
81, 80, 78, 77, 76, 68, 65, 62, 60, 56,
54, 46, 44, 43, 42, 41, 40, 36, 35, 34,
33, 32, 29, 28, 27, 24, 19, 15, 11, 7,
3, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153, 153, 153, 153, 153, 153, 153,
153, 153, 153, 153
} ;
static yy_state_type yy_last_accepting_state;
@ -962,13 +962,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 152 )
if ( yy_current_state >= 154 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 170 );
while ( yy_base[yy_current_state] != 172 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@ -1032,82 +1032,82 @@ YY_RULE_SETUP
case 8:
YY_RULE_SETUP
#line 101 "tokenizer.lex"
{ return WHILE; }
{ return ELSEIF; }
YY_BREAK
case 9:
YY_RULE_SETUP
#line 103 "tokenizer.lex"
{ return FOR; }
{ return WHILE; }
YY_BREAK
case 10:
YY_RULE_SETUP
#line 105 "tokenizer.lex"
{ return IN; }
{ return FOR; }
YY_BREAK
case 11:
YY_RULE_SETUP
#line 107 "tokenizer.lex"
{ return DO; }
{ return IN; }
YY_BREAK
case 12:
YY_RULE_SETUP
#line 109 "tokenizer.lex"
{ return FUNC; }
{ return DO; }
YY_BREAK
case 13:
YY_RULE_SETUP
#line 111 "tokenizer.lex"
{ return LAMBDA; }
{ return FUNC; }
YY_BREAK
case 14:
YY_RULE_SETUP
#line 113 "tokenizer.lex"
{ return RETURN; }
{ return LAMBDA; }
YY_BREAK
case 15:
YY_RULE_SETUP
#line 115 "tokenizer.lex"
{ return BREAK; }
{ return RETURN; }
YY_BREAK
case 16:
YY_RULE_SETUP
#line 117 "tokenizer.lex"
{ return CONTINUE; }
{ return BREAK; }
YY_BREAK
case 17:
YY_RULE_SETUP
#line 119 "tokenizer.lex"
{ return END; }
{ return CONTINUE; }
YY_BREAK
case 18:
YY_RULE_SETUP
#line 121 "tokenizer.lex"
{ return NONE; }
{ return END; }
YY_BREAK
case 19:
YY_RULE_SETUP
#line 123 "tokenizer.lex"
{ return PLUS; }
{ return NONE; }
YY_BREAK
case 20:
YY_RULE_SETUP
#line 125 "tokenizer.lex"
{ return MINUS; }
{ return PLUS; }
YY_BREAK
case 21:
YY_RULE_SETUP
#line 127 "tokenizer.lex"
{ return STAR; }
{ return MINUS; }
YY_BREAK
case 22:
YY_RULE_SETUP
#line 129 "tokenizer.lex"
{ return SLASH; }
{ return STAR; }
YY_BREAK
case 23:
YY_RULE_SETUP
#line 131 "tokenizer.lex"
{ return PERCENT; }
{ return SLASH; }
YY_BREAK
case 24:
YY_RULE_SETUP
@ -1117,32 +1117,32 @@ YY_RULE_SETUP
case 25:
YY_RULE_SETUP
#line 135 "tokenizer.lex"
{ return DSTAR; }
{ return PERCENT; }
YY_BREAK
case 26:
YY_RULE_SETUP
#line 137 "tokenizer.lex"
{ return BAND; }
{ return DSTAR; }
YY_BREAK
case 27:
YY_RULE_SETUP
#line 139 "tokenizer.lex"
{ return BOR; }
{ return BAND; }
YY_BREAK
case 28:
YY_RULE_SETUP
#line 141 "tokenizer.lex"
{ return BXOR; }
{ return BOR; }
YY_BREAK
case 29:
YY_RULE_SETUP
#line 143 "tokenizer.lex"
{ return BNOT; }
{ return BXOR; }
YY_BREAK
case 30:
YY_RULE_SETUP
#line 145 "tokenizer.lex"
{ return LAND; }
{ return BNOT; }
YY_BREAK
case 31:
YY_RULE_SETUP
@ -1152,7 +1152,7 @@ YY_RULE_SETUP
case 32:
YY_RULE_SETUP
#line 149 "tokenizer.lex"
{ return LOR; }
{ return LAND; }
YY_BREAK
case 33:
YY_RULE_SETUP
@ -1162,7 +1162,7 @@ YY_RULE_SETUP
case 34:
YY_RULE_SETUP
#line 153 "tokenizer.lex"
{ return LNOT; }
{ return LOR; }
YY_BREAK
case 35:
YY_RULE_SETUP
@ -1172,7 +1172,7 @@ YY_RULE_SETUP
case 36:
YY_RULE_SETUP
#line 157 "tokenizer.lex"
{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 1; return INT; }
{ return LNOT; }
YY_BREAK
case 37:
YY_RULE_SETUP
@ -1182,7 +1182,7 @@ YY_RULE_SETUP
case 38:
YY_RULE_SETUP
#line 161 "tokenizer.lex"
{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 0; return INT; }
{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 1; return INT; }
YY_BREAK
case 39:
YY_RULE_SETUP
@ -1192,176 +1192,181 @@ YY_RULE_SETUP
case 40:
YY_RULE_SETUP
#line 165 "tokenizer.lex"
{ return ASSIGN; }
{ *yylval = malloc(sizeof(long)); *((long *) *yylval) = 0; return INT; }
YY_BREAK
case 41:
YY_RULE_SETUP
#line 167 "tokenizer.lex"
{ return ASSIGNPLUS; }
{ return ASSIGN; }
YY_BREAK
case 42:
YY_RULE_SETUP
#line 169 "tokenizer.lex"
{ return ASSIGNMINUS; }
{ return ASSIGNPLUS; }
YY_BREAK
case 43:
YY_RULE_SETUP
#line 171 "tokenizer.lex"
{ return ASSIGNSTAR; }
{ return ASSIGNMINUS; }
YY_BREAK
case 44:
YY_RULE_SETUP
#line 173 "tokenizer.lex"
{ return ASSIGNSLASH; }
{ return ASSIGNSTAR; }
YY_BREAK
case 45:
YY_RULE_SETUP
#line 175 "tokenizer.lex"
{ return ASSIGNDSTAR; }
{ return ASSIGNSLASH; }
YY_BREAK
case 46:
YY_RULE_SETUP
#line 177 "tokenizer.lex"
{ return ASSIGNBAND; }
{ return ASSIGNDSTAR; }
YY_BREAK
case 47:
YY_RULE_SETUP
#line 179 "tokenizer.lex"
{ return ASSIGNBOR; }
{ return ASSIGNBAND; }
YY_BREAK
case 48:
YY_RULE_SETUP
#line 181 "tokenizer.lex"
{ return ASSIGNBXOR; }
{ return ASSIGNBOR; }
YY_BREAK
case 49:
YY_RULE_SETUP
#line 183 "tokenizer.lex"
{ return EQUAL; }
{ return ASSIGNBXOR; }
YY_BREAK
case 50:
YY_RULE_SETUP
#line 185 "tokenizer.lex"
{ return NEQUAL; }
{ return EQUAL; }
YY_BREAK
case 51:
YY_RULE_SETUP
#line 187 "tokenizer.lex"
{ return LESS; }
{ return NEQUAL; }
YY_BREAK
case 52:
YY_RULE_SETUP
#line 189 "tokenizer.lex"
{ return GREATER; }
{ return LESS; }
YY_BREAK
case 53:
YY_RULE_SETUP
#line 191 "tokenizer.lex"
{ return LESSEQ; }
{ return GREATER; }
YY_BREAK
case 54:
YY_RULE_SETUP
#line 193 "tokenizer.lex"
{ return GREATEREQ; }
{ return LESSEQ; }
YY_BREAK
case 55:
YY_RULE_SETUP
#line 195 "tokenizer.lex"
{ return RSHIFT; }
{ return GREATEREQ; }
YY_BREAK
case 56:
YY_RULE_SETUP
#line 197 "tokenizer.lex"
{ return LSHIFT; }
{ return RSHIFT; }
YY_BREAK
case 57:
YY_RULE_SETUP
#line 199 "tokenizer.lex"
{ return LBRACE; }
{ return LSHIFT; }
YY_BREAK
case 58:
YY_RULE_SETUP
#line 201 "tokenizer.lex"
{ return RBRACE; }
{ return LBRACE; }
YY_BREAK
case 59:
YY_RULE_SETUP
#line 203 "tokenizer.lex"
{ return LBRACKET; }
{ return RBRACE; }
YY_BREAK
case 60:
YY_RULE_SETUP
#line 205 "tokenizer.lex"
{ return RBRACKET; }
{ return LBRACKET; }
YY_BREAK
case 61:
YY_RULE_SETUP
#line 207 "tokenizer.lex"
{ return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
{ return RBRACKET; }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 209 "tokenizer.lex"
{ return LPAREN; }
{ return BLPAREN; } /* "Breaking" paren, not allowed to introduce a call_expr */
YY_BREAK
case 63:
YY_RULE_SETUP
#line 211 "tokenizer.lex"
{ return RPAREN; }
{ return LPAREN; }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 213 "tokenizer.lex"
{ return DOT; }
{ return RPAREN; }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 215 "tokenizer.lex"
{ return COLON; }
{ return DOT; }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 217 "tokenizer.lex"
{ return SEMICOLON; }
{ return COLON; }
YY_BREAK
case 67:
YY_RULE_SETUP
#line 219 "tokenizer.lex"
{ return COMMA; }
{ return SEMICOLON; }
YY_BREAK
case 68:
YY_RULE_SETUP
#line 221 "tokenizer.lex"
{ return POUND; }
{ return COMMA; }
YY_BREAK
case 69:
YY_RULE_SETUP
#line 223 "tokenizer.lex"
{ return TBANG; }
{ return POUND; }
YY_BREAK
case 70:
YY_RULE_SETUP
#line 225 "tokenizer.lex"
{ *yylval = (void *) strdup(yytext); return IDENT; }
{ return TBANG; }
YY_BREAK
case 71:
/* rule 71 can match eol */
YY_RULE_SETUP
#line 227 "tokenizer.lex"
/* Skip comments */
{ *yylval = (void *) strdup(yytext); return IDENT; }
YY_BREAK
case 72:
/* rule 72 can match eol */
YY_RULE_SETUP
#line 229 "tokenizer.lex"
/* Skip whitespace */
/* Skip comments */
YY_BREAK
case 73:
/* rule 73 can match eol */
YY_RULE_SETUP
#line 231 "tokenizer.lex"
/* Skip whitespace */
YY_BREAK
case 74:
YY_RULE_SETUP
#line 233 "tokenizer.lex"
ECHO;
YY_BREAK
#line 1364 "lex.yy.c"
#line 1369 "lex.yy.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
@ -1655,7 +1660,7 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 152 )
if ( yy_current_state >= 154 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@ -1683,11 +1688,11 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 152 )
if ( yy_current_state >= 154 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
yy_is_jam = (yy_current_state == 151);
yy_is_jam = (yy_current_state == 153);
return yy_is_jam ? 0 : yy_current_state;
}
@ -2365,7 +2370,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
#line 231 "tokenizer.lex"
#line 233 "tokenizer.lex"
int yywrap(void) {

14651
parser.output
File diff suppressed because it is too large
View File

1404
parser.tab.c
File diff suppressed because it is too large
View File

119
parser.tab.h

@ -47,65 +47,66 @@ extern int yydebug;
{
IF = 258,
THEN = 259,
ELSE = 260,
WHILE = 261,
FOR = 262,
IN = 263,
DO = 264,
FUNC = 265,
LAMBDA = 266,
RETURN = 267,
BREAK = 268,
CONTINUE = 269,
END = 270,
NONE = 271,
IDENT = 272,
INT = 273,
FLOAT = 274,
STRING = 275,
PLUS = 276,
MINUS = 277,
STAR = 278,
SLASH = 279,
PERCENT = 280,
DSTAR = 281,
BAND = 282,
BOR = 283,
BXOR = 284,
BNOT = 285,
LAND = 286,
LOR = 287,
LNOT = 288,
ASSIGN = 289,
ASSIGNPLUS = 290,
ASSIGNMINUS = 291,
ASSIGNSTAR = 292,
ASSIGNSLASH = 293,
ASSIGNDSTAR = 294,
ASSIGNBAND = 295,
ASSIGNBOR = 296,
ASSIGNBXOR = 297,
EQUAL = 298,
NEQUAL = 299,
LESS = 300,
GREATER = 301,
LESSEQ = 302,
GREATEREQ = 303,
RSHIFT = 304,
LSHIFT = 305,
LBRACE = 306,
RBRACE = 307,
BLPAREN = 308,
LPAREN = 309,
RPAREN = 310,
LBRACKET = 311,
RBRACKET = 312,
DOT = 313,
COLON = 314,
SEMICOLON = 315,
COMMA = 316,
POUND = 317,
TBANG = 318
ELSEIF = 260,
ELSE = 261,
WHILE = 262,
FOR = 263,
IN = 264,
DO = 265,
FUNC = 266,
LAMBDA = 267,
RETURN = 268,
BREAK = 269,
CONTINUE = 270,
END = 271,
NONE = 272,
IDENT = 273,
INT = 274,
FLOAT = 275,
STRING = 276,
PLUS = 277,
MINUS = 278,
STAR = 279,
SLASH = 280,
PERCENT = 281,
DSTAR = 282,
BAND = 283,
BOR = 284,
BXOR = 285,
BNOT = 286,
LAND = 287,
LOR = 288,
LNOT = 289,
ASSIGN = 290,
ASSIGNPLUS = 291,
ASSIGNMINUS = 292,
ASSIGNSTAR = 293,
ASSIGNSLASH = 294,
ASSIGNDSTAR = 295,
ASSIGNBAND = 296,
ASSIGNBOR = 297,
ASSIGNBXOR = 298,
EQUAL = 299,
NEQUAL = 300,
LESS = 301,
GREATER = 302,
LESSEQ = 303,
GREATEREQ = 304,
RSHIFT = 305,
LSHIFT = 306,
LBRACE = 307,
RBRACE = 308,
BLPAREN = 309,
LPAREN = 310,
RPAREN = 311,
LBRACKET = 312,
RBRACKET = 313,
DOT = 314,
COLON = 315,
SEMICOLON = 316,
COMMA = 317,
POUND = 318,
TBANG = 319
};
#endif

59
parser.y

@ -5,13 +5,23 @@
#include <string.h>
#define YYSTYPE void *
#define YYLTYPE loc_t
/* Hacks */
#define first_line line
#define last_line line
#define first_column col
#define last_column col
int yylex(YYSTYPE *, loc_t *);
void yyerror(loc_t *, stmt_node **, char *);
%}
%define lr.type ielr
%define api.pure full
%token IF THEN ELSE
%token IF THEN ELSEIF ELSE
%token WHILE FOR IN DO
%token FUNC LAMBDA RETURN BREAK CONTINUE
%token END NONE
@ -71,21 +81,13 @@ expr:
;
control_expr:
IF expr THEN stmt_list END {
$$ = NEW_EX();
AS_EX($$)->type = EX_IFELSE;
AS_EX($$)->ifelse = NEW(ifelse_node);
AS_EX($$)->ifelse->cond = $2;
AS_EX($$)->ifelse->iftrue = $4;
AS_EX($$)->ifelse->iffalse = NULL;
}
| IF expr THEN stmt_list ELSE stmt_list END {
IF expr THEN stmt_list if_termin {
$$ = NEW_EX();
AS_EX($$)->type = EX_IFELSE;
AS_EX($$)->ifelse = NEW(ifelse_node);
AS_EX($$)->ifelse->cond = $2;
AS_EX($$)->ifelse->iftrue = $4;
AS_EX($$)->ifelse->iffalse = $6;
AS_EX($$)->ifelse->iffalse = $5;
}
| WHILE expr DO stmt_list END {
$$ = NEW_EX();
@ -105,6 +107,23 @@ control_expr:
| assign_expr { $$ = $1; }
;
if_termin:
ELSEIF expr THEN stmt_list if_termin {
$$ = NEW_ST();
AS_ST($$)->type = ST_EXPR;
AS_ST($$)->expr = NEW_EX();
AS_ST($$)->expr->type = EX_IFELSE;
AS_ST($$)->expr->ifelse = NEW(ifelse_node);
AS_ST($$)->expr->ifelse->cond = $2;
AS_ST($$)->expr->ifelse->iftrue = $4;
AS_ST($$)->expr->ifelse->iffalse = $5;
}
| ELSE stmt_list END {
$$ = $2;
}
| END { $$ = NULL; }
;
assign_expr:
IDENT ASSIGN expr { $$ = NEW_EX(); AS_EX($$)->type = EX_ASSIGN; AS_EX($$)->assign = NEW(assign_node); AS_EX($$)->assign->ident = $1; AS_EX($$)->assign->value = $3; }
| IDENT ASSIGNPLUS expr {
@ -165,7 +184,7 @@ assign_expr:
}
| ex_index_expr ASSIGN expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -178,7 +197,7 @@ assign_expr:
}
| ex_index_expr ASSIGNPLUS expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -191,7 +210,7 @@ assign_expr:
}
| ex_index_expr ASSIGNMINUS expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -204,7 +223,7 @@ assign_expr:
}
| ex_index_expr ASSIGNSTAR expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -217,7 +236,7 @@ assign_expr:
}
| ex_index_expr ASSIGNSLASH expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -230,7 +249,7 @@ assign_expr:
}
| ex_index_expr ASSIGNDSTAR expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -243,7 +262,7 @@ assign_expr:
}
| ex_index_expr ASSIGNBAND expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -256,7 +275,7 @@ assign_expr:
}
| ex_index_expr ASSIGNBOR expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();
@ -269,7 +288,7 @@ assign_expr:
}
| ex_index_expr ASSIGNBXOR expr {
if(AS_EX($1)->type != EX_INDEX) {
yyerror("Assigning to non-indexing expression");
yyerror(&@$, NULL, "Assigning to non-indexing expression");
YYABORT;
}
$$ = NEW_EX();

671
programs/chip8.sol

@ -0,0 +1,671 @@
chr2hex_t = {}
hex2chr_t = {}
for i in range(10) do
c = chr(ord('0') + i)
chr2hex_t[c] = i
hex2chr_t[i] = c
end
for i in [10, 11, 12, 13, 14, 15] do
c = chr(ord('A') + i - 10)
chr2hex_t[c] = i
hex2chr_t[i] = c
end
func new_reg()
return {
V = [0] * 16,
I = 0,
IP = 512,
ST = 0,
DT = 0,
}
end
func new_mem()
return [
240, 144, 144, 144, 240, -- 0
32, 96, 32, 32, 112, -- 1
240, 16, 240, 128, 240, -- 2
240, 16, 240, 16, 240, -- 3
144, 144, 240, 16, 16, -- 4
240, 128, 240, 16, 240, -- 5
240, 128, 240, 144, 240, -- 6
240, 16, 32, 64, 64, -- 7
240, 144, 240, 144, 240, -- 8
240, 144, 240, 16, 240, -- 9
240, 144, 240, 144, 144, -- A
224, 144, 224, 144, 224, -- B
240, 128, 128, 128, 240, -- C
224, 144, 144, 144, 224, -- D
240, 128, 240, 128, 240, -- E
240, 128, 240, 128, 128, -- F
] + [0] * 4016
end
func mem_int(mem, i, bytes)
r = 0
while (bytes > 0) && (i < 4096) do
r = (r << 8) | mem[i]
i += 1
bytes -= 1
end
return r
end
func load_buffer(mem, addr, s)
if None == addr then addr = 512 end
idx = 0
while (idx < s:size()) && (addr < 4096) do
mem[addr] = s:get(buffer.type.byte, idx)
addr += 1
idx += 1
end
end
func load_stream(mem, addr, str)
load_buffer(mem, addr, str:read_buffer(io.ALL))
end
func get_bit(v, i)
return (v >> i) & 1
end
func new_disp(w, h)
if w == None then w = 64 end
if h == None then h = 32 end
return {
fb = [0] * (64 * 32),
w = w,
h = h,
}
end
func disp_blit(b, x, y, v)
idx = y * (b.w) + x
changed = 0
for bit in range(8) do
if (idx >= 0) && (idx < (b.w) * (b.h)) then
oldb = b.fb[idx]
b.fb[idx] ^= if v & 128 then 1 else 0 end
changed = changed || ((!oldb) && (b.fb[idx]))
idx += 1
v = v << 1
end
end
return changed
end
func print_sprite(m, i, n)
if None == n then n = 15 end
fake_fb = new_disp(8, n)
for idx in range(n) do
disp_blit(fake_fb, 0, idx, m[i + idx])
end
print(disp_render(fake_fb))
end
NL = chr(10)
CSI = chr(27) + '['
func clear_screen()
io.stdout:write(CSI+'H'+CSI+'2J')
end
func disp_render(d)
s = ''
for row in range(d.h) do
s = s + disp_render_row(d, row) + NL
end
return s
end
func disp_render_row(d, r)
t = ''
for col in range(d.w) do
idx = r * (d.w) + col
if d.fb[idx] then
t += '*'
else
t += ' '
end
end
return t
end
func unused_syscall(state, n)
state:log("unknown syscall " + tostring(n))
end
func clear_disp(state, n)
state.disp = new_disp()
end
func ret(state, n)
state:jump(state:pop())
end
func new_sys()
sys = [unused_syscall] * 4096
sys[224] = clear_disp
sys[238] = ret
return sys
end
func new_state()
return {
reg = new_reg(),
mem = new_mem(),
disp = new_disp(),
sys = new_sys(),
jumped = false,
trace = false,
jump = func(self, ip)
self.reg.IP = ip
self.jumped = true
end,
skip = func(self)
self.reg.IP += 2
end,
stack = [],
push = func(self, v)
self.stack:insert(#(self.stack), v)
if (#self.stack) > 16 then
self:log("stack overflow: " + tostring(self.stack))
end
end,
pop = func(self)
if (#self.stack) == 0 then
self:log("stack underflow")
return 0
end
return self.stack:remove((#self.stack) - 1)
end,
keys = [0] * 16,
buffer = [],
log = func(self, msg)
self.buffer:insert(#(self.buffer), msg)
end,
breaks = [],
-- wchan = None
}
end
func new_insn(n)
return {
nib = [(n >> 12) & 15, (n >> 8) & 15, (n >> 4) & 15, n & 15],
byte = {high = (n >> 8) & 255, low = n & 255},
addr = n & 4095,
n = n,
}
end
func rand(n=0)
n = ((n * 17) + 1569752) % 3707765549
n = (n << 1) | (((n >> 3) & 1) ^ ((n >> 6) & 1))
n = (n << 1) | (((n >> 8) & 1) ^ ((n >> 5) & 1))
n = ((n * 7) + 67293512) % 3747882443
n = (n << 1) | (((n >> 7) & 1) ^ ((n >> 2) & 1))
n = (n << 1) | (((n >> 4) & 1) ^ ((n >> 3) & 1))
return n
end
func seed(n)
rand.closure.n = n
end
func bad_op(state, ins)
state:log("bad insn: " + tostring(ins.n) + " " + tostring(ins.nib))
end
insns = {
[0] = func insn0(state, ins)
state.sys[ins.addr](state, ins.addr)
end,
[1] = func insn1(state, ins)
state:jump(ins.addr)
end,
[2] = func insn2(state, ins)
state:push(state.reg.IP + 2)
state:jump(ins.addr)
end,
[3] = func insn3(state, ins)
if state.reg.V[ins.nib[1]] == ins.byte.low then
state:skip()
end
end,
[4] = func insn4(state, ins)
if state.reg.V[ins.nib[1]] != ins.byte.low then
state:skip(</