1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-24 06:03:17 +00:00

Make coloring changes to the repl

This commit is contained in:
bakpakin 2017-07-02 20:51:52 -04:00
parent bfadf6ff12
commit 0cf278994d
7 changed files with 149 additions and 140 deletions

View File

@ -30,6 +30,12 @@ static int client_strequal(const char *a, const char *b) {
return *a == *b;
}
static int client_strequal_witharg(const char *a, const char *b) {
while (*b)
if (*a++ != *b++) return 0;
return *a == '=';
}
#define GST_CLIENT_HELP 1
#define GST_CLIENT_VERBOSE 2
#define GST_CLIENT_VERSION 4
@ -37,6 +43,14 @@ static int client_strequal(const char *a, const char *b) {
#define GST_CLIENT_NOCOLOR 16
#define GST_CLIENT_UNKNOWN 32
static void printf_flags(int64_t flags, const char *col, const char *fmt, const char *arg) {
if (!(flags & GST_CLIENT_NOCOLOR))
printf("\x1B[%sm", col);
printf(fmt, arg);
if (!(flags & GST_CLIENT_NOCOLOR))
printf("\x1B[0m");
}
/* Simple read line functionality */
static char *gst_getline() {
char *line = malloc(100);
@ -68,7 +82,7 @@ static char *gst_getline() {
}
/* Compile and run an ast */
static int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
static int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last, int64_t flags) {
GstCompiler c;
GstValue func;
/* Try to compile generated AST */
@ -77,15 +91,15 @@ static int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
func = gst_wrap_function(gst_compiler_compile(&c, ast));
/* Check for compilation errors */
if (c.error.type != GST_NIL) {
printf("Compiler error: %s\n", (const char *)gst_to_string(vm, c.error));
printf_flags(flags, "31", "compiler error: %s\n", (const char *)gst_to_string(vm, c.error));
return 1;
}
/* Execute function */
if (gst_run(vm, func)) {
if (vm->crash) {
printf("VM crash: %s\n", vm->crash);
printf_flags(flags, "31", "vm crash: %s\n", vm->crash);
} else {
printf("VM error: %s\n", (const char *)gst_to_string(vm, vm->ret));
printf_flags(flags, "31", "vm error: %s\n", (const char *)gst_to_string(vm, vm->ret));
}
return 1;
}
@ -93,7 +107,7 @@ static int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) {
}
/* Parse a file and execute it */
static int debug_run(Gst *vm, FILE *in) {
static int debug_run(Gst *vm, FILE *in, int64_t flags) {
char buffer[2048] = {0};
const char *reader = buffer;
GstParser p;
@ -105,7 +119,7 @@ static int debug_run(Gst *vm, FILE *in) {
if (!fgets(buffer, sizeof(buffer), in)) {
/* Check that parser is complete */
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
printf("Unexpected end of source\n");
printf_flags(flags, "31", "parse error: unexpected end of source%s\n", "");
return 1;
}
/* Otherwise we finished the file with no problems*/
@ -117,15 +131,15 @@ static int debug_run(Gst *vm, FILE *in) {
}
/* Check if file read in correctly */
if (p.error) {
printf("Parse error: %s\n", p.error);
printf_flags(flags, "31", "parse error: %s\n", p.error);
break;
}
/* Check that parser is complete */
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
printf("Unexpected end of source\n");
printf_flags(flags, "31", "parse error: unexpected end of source%s\n", "");
break;
}
if (debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret)) {
if (debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret, flags)) {
break;
}
}
@ -144,11 +158,7 @@ static int debug_repl(Gst *vm, uint64_t flags) {
if (p.status == GST_PARSER_ERROR || p.status == GST_PARSER_FULL)
break;
if (!reader || *reader == '\0') {
if (flags & GST_CLIENT_NOCOLOR) {
printf(">>> ");
} else {
printf("\x1B[33m>>>\x1B[0m ");
}
printf_flags(flags, "33", "> %s", "");
if (buffer)
free(buffer);
buffer = gst_getline();
@ -160,21 +170,17 @@ static int debug_repl(Gst *vm, uint64_t flags) {
}
/* Check if file read in correctly */
if (p.error) {
printf("Parse error: %s\n", p.error);
printf_flags(flags, "31", "parse error: %s\n", p.error);
buffer = reader = NULL;
continue;
}
/* Check that parser is complete */
if (p.status != GST_PARSER_FULL && p.status != GST_PARSER_ROOT) {
printf("Unexpected end of source\n");
printf_flags(flags, "31", "parse error: unexpected end of source%s\n", "");
continue;
}
if (!debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret)) {
if (flags & GST_CLIENT_NOCOLOR) {
printf("%s\n", gst_description(vm, vm->ret));
} else {
printf("\x1B[36m%s\x1B[0m\n", gst_description(vm, vm->ret));
}
if (!debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret, flags)) {
printf_flags(flags, "36", "%s\n", (const char *) gst_description(vm, vm->ret));
}
}
}
@ -184,6 +190,7 @@ int main(int argc, const char **argv) {
int status = -1;
int i;
int fileRead = 0;
uint32_t memoryInterval = 4096;
uint64_t flags = 0;
/* Read the arguments. Ignore files. */
@ -203,6 +210,20 @@ int main(int argc, const char **argv) {
flags |= GST_CLIENT_REPL;
} else if (client_strequal(arg + 2, "nocolor")) {
flags |= GST_CLIENT_NOCOLOR;
} else if (client_strequal_witharg(arg + 2, "memchunk")) {
int64_t val = memoryInterval;
const uint8_t *end = (const uint8_t *)(arg + 2);
while (*end) ++end;
int status = gst_read_integer((const uint8_t *)arg + 11, end, &val);
if (status) {
if (val > 0xFFFFFFFF) {
memoryInterval = 0xFFFFFFFF;
} else if (val < 0) {
memoryInterval = 0;
} else {
memoryInterval = val;
}
}
} else {
flags |= GST_CLIENT_UNKNOWN;
}
@ -240,11 +261,14 @@ int main(int argc, const char **argv) {
printf( "Usage:\n"
"%s -opts --fullopt1 --fullopt2 file1 file2...\n"
"\n"
" -h --help : Shows this information.\n"
" -V --verbose : Show more output.\n"
" -r --repl : Launch a repl after all files are processed.\n"
" -c --nocolor : Don't use VT100 color codes in the repl.\n"
" -v --version : Print the version number and exit.\n\n",
" -h --help : Shows this information.\n"
" -V --verbose : Show more output.\n"
" -r --repl : Launch a repl after all files are processed.\n"
" -c --nocolor : Don't use VT100 color codes in the repl.\n"
" -v --version : Print the version number and exit.\n"
" --memchunk=[int] : Set the amount of memory to allocate before\n"
" forcing a collection in bytes. Max is 2^32-1,\n"
" min is 0.\n\n",
argv[0]);
return 0;
}
@ -255,6 +279,7 @@ int main(int argc, const char **argv) {
/* Set up VM */
gst_init(&vm);
vm.memoryInterval = memoryInterval;
gst_stl_load(&vm);
/* Read the arguments. Only process files. */
@ -264,7 +289,7 @@ int main(int argc, const char **argv) {
FILE *f;
f = fopen(arg, "rb");
fileRead = 1;
status = debug_run(&vm, f);
status = debug_run(&vm, f, flags);
}
}

View File

@ -22,7 +22,7 @@
#include <gst/gst.h>
static const char UNEXPECTED_CLOSING_DELIM[] = "Unexpected closing delimiter";
static const char UNEXPECTED_CLOSING_DELIM[] = "unexpected closing delimiter";
/* Handle error in parsing */
#define p_error(p, e) ((p)->error = (e), (p)->status = GST_PARSER_ERROR)
@ -125,86 +125,6 @@ static int is_symbol_char(uint8_t c) {
return 0;
}
/* Get an integer power of 10 */
static double exp10(int power) {
if (power == 0) return 1;
if (power > 0) {
double result = 10;
int currentPower = 1;
while (currentPower * 2 <= power) {
result = result * result;
currentPower *= 2;
}
return result * exp10(power - currentPower);
} else {
return 1 / exp10(-power);
}
}
/* Read a real from a string. Returns if successfuly
* parsed a real from the enitre input string.
* If returned 1, output is int ret.*/
static int read_real(const uint8_t *string, const uint8_t *end, double *ret, int forceInt) {
int sign = 1, x = 0;
double accum = 0, exp = 1, place = 1;
/* Check the sign */
if (*string == '-') {
sign = -1;
++string;
} else if (*string == '+') {
++string;
}
if (string >= end) return 0;
while (string < end) {
if (*string == '.' && !forceInt) {
place = 0.1;
} else if (!forceInt && (*string == 'e' || *string == 'E')) {
/* Read the exponent */
++string;
if (string >= end) return 0;
if (!read_real(string, end, &exp, 1))
return 0;
exp = exp10(exp);
break;
} else {
x = *string;
if (x < '0' || x > '9') return 0;
x -= '0';
if (place < 1) {
accum += x * place;
place *= 0.1;
} else {
accum *= 10;
accum += x;
}
}
++string;
}
*ret = accum * sign * exp;
return 1;
}
static int read_integer(const uint8_t *string, const uint8_t *end, int64_t *ret) {
int sign = 1, x = 0;
int64_t accum = 0;
if (*string == '-') {
sign = -1;
++string;
} else if (*string == '+') {
++string;
}
if (string >= end) return 0;
while (string < end) {
x = *string;
if (x < '0' || x > '9') return 0;
x -= '0';
accum = accum * 10 + x;
++string;
}
*ret = accum * sign;
return 1;
}
/* Checks if a string slice is equal to a string constant */
static int check_str_const(const char *ref, const uint8_t *start, const uint8_t *end) {
while (*ref && start < end) {
@ -222,10 +142,10 @@ static GstValue build_token(GstParser *p, GstBuffer *buf) {
GstInteger integer;
uint8_t *data = buf->data;
uint8_t *back = data + buf->count;
if (read_integer(data, back, &integer)) {
if (gst_read_integer(data, back, &integer)) {
x.type = GST_INTEGER;
x.data.integer = integer;
} else if (read_real(data, back, &real, 0)) {
} else if (gst_read_real(data, back, &real, 0)) {
x.type = GST_REAL;
x.data.real = real;
} else if (check_str_const("nil", data, back)) {

View File

@ -85,6 +85,95 @@ void *gst_check_userdata(Gst *vm, uint32_t i, const GstUserType *type) {
return x.data.pointer;
}
/****/
/* Parsing utils */
/****/
/* Get an integer power of 10 */
static double exp10(int power) {
if (power == 0) return 1;
if (power > 0) {
double result = 10;
int currentPower = 1;
while (currentPower * 2 <= power) {
result = result * result;
currentPower *= 2;
}
return result * exp10(power - currentPower);
} else {
return 1 / exp10(-power);
}
}
int gst_read_integer(const uint8_t *string, const uint8_t *end, int64_t *ret) {
int sign = 1, x = 0;
int64_t accum = 0;
if (*string == '-') {
sign = -1;
++string;
} else if (*string == '+') {
++string;
}
if (string >= end) return 0;
while (string < end) {
x = *string;
if (x < '0' || x > '9') return 0;
x -= '0';
accum = accum * 10 + x;
++string;
}
*ret = accum * sign;
return 1;
}
/* Read a real from a string. Returns if successfuly
* parsed a real from the enitre input string.
* If returned 1, output is int ret.*/
int gst_read_real(const uint8_t *string, const uint8_t *end, double *ret, int forceInt) {
int sign = 1, x = 0;
double accum = 0, exp = 1, place = 1;
/* Check the sign */
if (*string == '-') {
sign = -1;
++string;
} else if (*string == '+') {
++string;
}
if (string >= end) return 0;
while (string < end) {
if (*string == '.' && !forceInt) {
place = 0.1;
} else if (!forceInt && (*string == 'e' || *string == 'E')) {
/* Read the exponent */
++string;
if (string >= end) return 0;
if (!gst_read_real(string, end, &exp, 1))
return 0;
exp = exp10(exp);
break;
} else {
x = *string;
if (x < '0' || x > '9') return 0;
x -= '0';
if (place < 1) {
accum += x * place;
place *= 0.1;
} else {
accum *= 10;
accum += x;
}
}
++string;
}
*ret = accum * sign * exp;
return 1;
}
/****/
/* Module utils */
/****/
static void gst_cmodule_register(Gst *vm, const char *name, const GstModuleItem *mod) {
uint32_t startLength;
GstBuffer *buffer = gst_buffer(vm, 10);

View File

@ -499,7 +499,7 @@ void gst_init(Gst *vm) {
vm->nextCollection = 0;
/* Setting memoryInterval to zero forces
* a collection pretty much every cycle, which is
* obviously horrible for performance, but helps ensure
* horrible for performance, but helps ensure
* there are no memory bugs during dev */
vm->memoryInterval = 0;
vm->black = 0;

View File

@ -654,6 +654,8 @@ int gst_hashtable_view(GstValue tab, const GstValue **data, uint32_t *cap);
#define GST_ENV_METADATA 1
#define GST_ENV_VARS 2
int gst_read_real(const uint8_t *string, const uint8_t *end, double *ret, int forceInt);
int gst_read_integer(const uint8_t *string, const uint8_t *end, int64_t *ret);
GstReal gst_integer_to_real(GstInteger x);
GstInteger gst_real_to_integer(GstReal x);
GstInteger gst_startrange(GstInteger raw, uint32_t len);

View File

@ -8,4 +8,4 @@
(var i 0)
(while (< i 1000)
(print i)
(varset i (+ i 1)))
(varset! i (+ i 1)))

View File

@ -1,27 +0,0 @@
(namespace-set! "gst.repl")
"Read a line"
(export! "readline" (fn []
(: b (buffer))
(read stdin 1 b)
(while (not (= (get "\n" 0) (get b (- (length b) 1))))
(read stdin 1 b)
)
(string b)
))
"Create a parser"
(export! "p" (parser))
"Run a simple repl."
(while 1
(write stdout ">> ")
(: t (thread (fn [line]
(: ret 1)
(while line
(: line (parse-charseq p line))
(if (parse-hasvalue p)
(: ret ((compile (parse-consume p))))))
ret)))
(: res (tran t (readline)))
(if (= (status t) "dead") (print (debugp res)) (print "Error: " (debugp res))))