|
@@ -1,3 +1,4 @@
|
|
|
+#include <time.h>
|
|
|
#include <ctype.h>
|
|
|
#include <stdio.h>
|
|
|
#include <stdarg.h>
|
|
@@ -7,6 +8,7 @@
|
|
|
#define QIC_VERSION "qic v01 " __DATE__
|
|
|
|
|
|
size_t GID = 0;
|
|
|
+char *PREFIX = NULL;
|
|
|
|
|
|
typedef struct {
|
|
|
void **data;
|
|
@@ -67,24 +69,24 @@ typedef struct {
|
|
|
size_t *data;
|
|
|
|
|
|
size_t length;
|
|
|
-} stack_t;
|
|
|
+} int_stack_t;
|
|
|
|
|
|
-stack_t *stack_new(void) {
|
|
|
- stack_t *stack = malloc(sizeof(list_t));
|
|
|
+int_stack_t *stack_new(void) {
|
|
|
+ int_stack_t *stack = malloc(sizeof(list_t));
|
|
|
stack->data = NULL;
|
|
|
stack->length = 0;
|
|
|
|
|
|
return stack;
|
|
|
}
|
|
|
|
|
|
-void stack_push(stack_t *l, size_t v) {
|
|
|
+void stack_push(int_stack_t *l, size_t v) {
|
|
|
size_t i = l->length++;
|
|
|
|
|
|
l->data = realloc(l->data, l->length * sizeof(size_t));
|
|
|
l->data[i] = v;
|
|
|
}
|
|
|
|
|
|
-size_t stack_pop(stack_t *l) {
|
|
|
+size_t stack_pop(int_stack_t *l) {
|
|
|
if (!l->length)
|
|
|
return 0;
|
|
|
|
|
@@ -2382,18 +2384,18 @@ node_t *parse(char *source) {
|
|
|
}
|
|
|
#define COMPILE_ERROR(fmt, ...) { format_error(GETFNAME(node->fi), GETSRC(node->fi), node->pos, fmt, ##__VA_ARGS__); exit(1); }
|
|
|
|
|
|
-void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node);
|
|
|
+void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, node_t *node);
|
|
|
|
|
|
char *tempvar() {
|
|
|
NEWGID();
|
|
|
|
|
|
- char *s = malloc(sizeof(char) * 64);
|
|
|
- snprintf(s, 64, "__temp%zu", gid);
|
|
|
+ char *s = malloc(sizeof(char) * (64 + strlen(PREFIX)));
|
|
|
+ snprintf(s, 64 + strlen(PREFIX), "__%s%zu", PREFIX, gid);
|
|
|
|
|
|
return s;
|
|
|
}
|
|
|
|
|
|
-void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, list_t *seq) {
|
|
|
+void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, list_t *seq) {
|
|
|
if (!seq || seq->length < 1) {
|
|
|
EMIT("NULL");
|
|
|
|
|
@@ -2411,7 +2413,7 @@ void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
NEWGID();
|
|
|
|
|
|
- buffer_fmt(tbuf, "inline static qi_list_t *__list%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "inline static qi_list_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
if (has_star)
|
|
|
buffer_fmt(tbuf, "qi_list_t *list = qi_list_make();\n");
|
|
|
else
|
|
@@ -2449,10 +2451,10 @@ void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__list%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
}
|
|
|
|
|
|
-void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, table_t *table) {
|
|
|
+void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, table_t *table) {
|
|
|
if (!table || table->used < 1) {
|
|
|
EMIT("NULL");
|
|
|
|
|
@@ -2463,7 +2465,7 @@ void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, st
|
|
|
|
|
|
NEWGID();
|
|
|
|
|
|
- buffer_fmt(tbuf, "inline static qi_table_t *__table%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "inline static qi_table_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
buffer_fmt(tbuf, "qi_table_t *table = qi_table_make();\n");
|
|
|
|
|
|
table_iterate(table, {
|
|
@@ -2479,7 +2481,7 @@ void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, st
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__table%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
}
|
|
|
|
|
|
#define CTXPUSH(s) list_push(ctx, (s))
|
|
@@ -2565,14 +2567,14 @@ void emit_debug(buffer_t *buf, node_t *node) {
|
|
|
buffer_fmt(buf, "state->_debug_data = __debugData[%d];\n", insert_debug(node));
|
|
|
}
|
|
|
|
|
|
-void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node, char *name) {
|
|
|
+void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, node_t *node, char *name) {
|
|
|
NEWGID();
|
|
|
|
|
|
char *funname = name? name: node->t? node->t->text: "<anon>";
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "qi_value_t *__func%d(qi_state_t *state, qi_size_t pargc, qi_list_t *pargs) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *__%s%d(qi_state_t *state, qi_size_t pargc, qi_list_t *pargs) {\n", PREFIX, gid);
|
|
|
|
|
|
LBPUSH();
|
|
|
CTXPUSH("gap");
|
|
@@ -2618,7 +2620,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "qi_make_function(state, \"%s\", %d, __func%d, ", funname, !node->h? 0: (node->h->used - optargc), gid);
|
|
|
+ buffer_fmt(tbuf, "qi_make_function(state, \"%s\", %d, __%s%d, ", funname, !node->h? 0: (node->h->used - optargc), PREFIX, gid);
|
|
|
compile_table(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->h2);
|
|
|
buffer_fmt(tbuf, ")");
|
|
|
|
|
@@ -2654,7 +2656,7 @@ node_t *const_get(char *name) {
|
|
|
return val;
|
|
|
}
|
|
|
|
|
|
-void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, list_t *block) {
|
|
|
+void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, list_t *block) {
|
|
|
for (size_t i = 0; i < block->length; i++) {
|
|
|
node_t *node = block->data[i];
|
|
|
|
|
@@ -2678,7 +2680,7 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, st
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "qi_value_t *__class%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
buffer_fmt(tbuf, "qi_list_t *supers = qi_list_make_n(%d);\n", !supers? 0: supers->length);
|
|
|
|
|
|
if (supers)
|
|
@@ -2727,7 +2729,7 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, st
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("qi_set(state, false, \"%s\", __class%d(state));", name, gid);
|
|
|
+ EMIT("qi_set(state, false, \"%s\", __%s%d(state));", name, PREFIX, gid);
|
|
|
} else if (node->tag == N_LABEL) {
|
|
|
char *label = node->t->text;
|
|
|
|
|
@@ -2757,522 +2759,6 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, st
|
|
|
}
|
|
|
|
|
|
const char *STD[][2] = {
|
|
|
- {"std",
|
|
|
- "func head(l): return l[0]\n"
|
|
|
- "func tail(l): return slice(l, 1)\n"
|
|
|
- "func min(x, y): x < y? x: y\n"
|
|
|
- "func max(x, y): x > y? x: y\n"
|
|
|
- "func reverse(x) {\n"
|
|
|
- " if type(x) !in (\"list\", \"string\", \"bytes\")\n"
|
|
|
- " throw \"expected first argument to be: list, string or bytes, but got: \" + type(x)\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var i = len(x)-1; i >= 0; i--\n"
|
|
|
- " list_push(r, x[i])\n"
|
|
|
- " if type(x) == \"string\"\n"
|
|
|
- " return list_join(r)\n"
|
|
|
- " elif type(x) == \"bytes\"\n"
|
|
|
- " return bytes(r)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.reverse\", reverse)\n"
|
|
|
- "set_pseudomethod(\"string.reverse\", reverse)\n"
|
|
|
- "set_pseudomethod(\"bytes.reverse\", reverse)\n"
|
|
|
- "func range(f) {\n"
|
|
|
- " var t, s\n"
|
|
|
- " if len(arguments) >= 3 {\n"
|
|
|
- " t = arguments[1]\n"
|
|
|
- " s = arguments[2]\n"
|
|
|
- " } elif len(arguments) >= 2 {\n"
|
|
|
- " t = arguments[1]\n"
|
|
|
- " s = 1\n"
|
|
|
- " } else {\n"
|
|
|
- " t = f\n"
|
|
|
- " f = 0\n"
|
|
|
- " s = 1\n"
|
|
|
- " }\n"
|
|
|
- " if type(f) != \"number\"\n"
|
|
|
- " throw \"expected first argument to be: number, but got: \" + type(f)\n"
|
|
|
- " if type(t) != \"number\"\n"
|
|
|
- " throw \"expected second argument to be: number, but got: \" + type(t)\n"
|
|
|
- " if type(s) != \"number\"\n"
|
|
|
- " throw \"expected third argument to be: number, but got: \" + type(s)\n"
|
|
|
- " if f > t\n"
|
|
|
- " return reverse(range(t, f, s))\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var i = f; i < t; i += s\n"
|
|
|
- " list_push(r, i)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "const SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2\n"
|
|
|
- "func frewind(file)\n"
|
|
|
- " return file.rewind()\n"
|
|
|
- "func file_read(filename) {\n"
|
|
|
- " let file = fopen(filename, \"r\")\n"
|
|
|
- " defer fclose(file)\n"
|
|
|
- " return str(fread(file, -1))\n"
|
|
|
- "}\n"
|
|
|
- "func file_write(filename, data) {\n"
|
|
|
- " let file = fopen(filename, \"w\")\n"
|
|
|
- " defer fclose(file)\n"
|
|
|
- " fwrite(file, bytes(data))\n"
|
|
|
- "}\n"
|
|
|
- "func is_defined(name) {\n"
|
|
|
- " if type(name) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(name)\n"
|
|
|
- " inline `bool b = qi_find(state, qi_get(state, \"name\")->value.string) != NULL`\n"
|
|
|
- " inline `return qi_make_boolean(state, b)`\n"
|
|
|
- "}\n"
|
|
|
- "func list_remove(l, x, first=false) {\n"
|
|
|
- " if type(l) != \"list\"\n"
|
|
|
- " throw \"expected first argument to be: list, but got: \" + type(l)\n"
|
|
|
- " repeat:\n"
|
|
|
- " for var i = 0; i < len(l); i++\n"
|
|
|
- " if l[i] == x {\n"
|
|
|
- " list_delete(l, i)\n"
|
|
|
- " if first\n"
|
|
|
- " break\n"
|
|
|
- " goto repeat\n"
|
|
|
- " }\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.remove\", list_remove)\n"
|
|
|
- "func list_join(l) {\n"
|
|
|
- " if type(l) != \"list\"\n"
|
|
|
- " throw \"expected first argument to be: list, but got: \" + type(l)\n"
|
|
|
- " var r = \"\"\n"
|
|
|
- " var s\n"
|
|
|
- " if len(arguments) == 1\n"
|
|
|
- " s = \"\"\n"
|
|
|
- " else\n"
|
|
|
- " s = arguments[1]\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(s)\n"
|
|
|
- " var first = true\n"
|
|
|
- " for var x of l {\n"
|
|
|
- " if type(x) != \"string\"\n"
|
|
|
- " throw \"expected sequence item to be: string, but got: \" + type(x)\n"
|
|
|
- " if s != \"\" && !first\n"
|
|
|
- " r += s\n"
|
|
|
- " r += x\n"
|
|
|
- " first = false\n"
|
|
|
- " }\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.join\", list_join)\n"
|
|
|
- "func list_pop_at(l, i) {\n"
|
|
|
- " if type(l) != \"list\"\n"
|
|
|
- " throw \"expected first argument to be: list, but got: \" + type(l)\n"
|
|
|
- " if type(i) != \"number\"\n"
|
|
|
- " throw \"expected second argument to be: number, but got: \" + type(i)\n"
|
|
|
- " var x = l[i]\n"
|
|
|
- " list_delete(l, i)\n"
|
|
|
- " return x\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.popAt\", list_pop_at)\n"
|
|
|
- "func list_sort(l, cmp=func (x, y): x > y) {\n"
|
|
|
- " if type(l) != \"list\"\n"
|
|
|
- " throw \"expected first argument to be: list, but got: \" + type(l)\n"
|
|
|
- " if type(cmp) != \"function\"\n"
|
|
|
- " throw \"expected second argument to be: function, but got: \" + type(cmp)\n"
|
|
|
- " if len(l) == 0\n"
|
|
|
- " return l\n"
|
|
|
- " var z = len(l)\n"
|
|
|
- " for var i = 0; i < z - 1; i++\n"
|
|
|
- " for var j = 0; j < z - 1 - i; j++\n"
|
|
|
- " if cmp(l[j], l[j+1]) {\n"
|
|
|
- " let tmp = l[j]\n"
|
|
|
- " l[j] = l[j+1]\n"
|
|
|
- " l[j+1] = tmp\n"
|
|
|
- " }\n"
|
|
|
- " return l\n"
|
|
|
- "}\n"
|
|
|
- "func list_sorted(l, cmp=func (x, y): x > y) {\n"
|
|
|
- " l = list_copy(l)\n"
|
|
|
- " return list_sort(l, cmp)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.sort\", list_sort)\n"
|
|
|
- "set_pseudomethod(\"list.sorted\", list_sorted)\n"
|
|
|
- "func list_shift(l) {\n"
|
|
|
- " if type(l) != \"list\"\n"
|
|
|
- " throw \"expected first argument to be: list, but got: \" + type(l)\n"
|
|
|
- " if is_empty(l)\n"
|
|
|
- " throw \"shift from empty list\"\n"
|
|
|
- " var a = l[0]\n"
|
|
|
- " list_delete(l, 0)\n"
|
|
|
- " return a\n"
|
|
|
- "}\n"
|
|
|
- "func list_unshift(l, x) {\n"
|
|
|
- " list_insert(l, 0, x)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.shift\", list_shift)\n"
|
|
|
- "set_pseudomethod(\"list.unshift\", list_unshift)\n"
|
|
|
- "func slice(l) {\n"
|
|
|
- " if type(l) !in (\"list\", \"string\", \"bytes\")\n"
|
|
|
- " throw \"expected first argument to be: list, string or bytes, but got: \" + type(l)\n"
|
|
|
- " var r = []\n"
|
|
|
- " if len(arguments) == 2 {\n"
|
|
|
- " var f = arguments[1]\n"
|
|
|
- " if type(f) != \"number\"\n"
|
|
|
- " throw \"expected second argument to be: number, but got: \" + type(f)\n"
|
|
|
- " for var i = f; i < len(l); i++\n"
|
|
|
- " list_push(r, l[i])\n"
|
|
|
- " } elif len(arguments) == 3 {\n"
|
|
|
- " var f = arguments[1], t = arguments[2]\n"
|
|
|
- " if type(f) != \"number\"\n"
|
|
|
- " throw \"expected second argument to be: number, but got: \" + type(f)\n"
|
|
|
- " if type(t) != \"number\"\n"
|
|
|
- " throw \"expected third argument to be: number, but got: \" + type(t)\n"
|
|
|
- " for var i = f; i < len(l) && i <= t; i++\n"
|
|
|
- " list_push(r, l[i])\n"
|
|
|
- " }\n"
|
|
|
- " if type(l) == \"string\"\n"
|
|
|
- " return list_join(r)\n"
|
|
|
- " elif type(l) == \"bytes\"\n"
|
|
|
- " return bytes(r)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.slice\", slice)\n"
|
|
|
- "set_pseudomethod(\"string.slice\", slice)\n"
|
|
|
- "set_pseudomethod(\"bytes.slice\", slice)\n"
|
|
|
- "let __slice = slice;\n"
|
|
|
- "func str_startswith(s, p) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if len(s) < len(p)\n"
|
|
|
- " return false\n"
|
|
|
- " return slice(s, 0, len(p)-1) == p\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.startsWith\", str_startswith)\n"
|
|
|
- "func str_endswith(s, p) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if len(s) < len(p)\n"
|
|
|
- " return false\n"
|
|
|
- " return slice(s, len(s) - len(p)) == p\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.endsWith\", str_endswith)\n"
|
|
|
- "func str_split(s) {\n"
|
|
|
- " if len(arguments) == 1 || arguments[1] == \"\"\n"
|
|
|
- " return list(s)\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be:!string, but got: \" + type(s)\n"
|
|
|
- " var r = []\n"
|
|
|
- " var d = arguments[1]\n"
|
|
|
- " if type(d) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(s)\n"
|
|
|
- " var t = \"\"\n"
|
|
|
- " for var i = 0; i < len(s); i++ {\n"
|
|
|
- " if slice(s, i, i+len(d)-1) == d {\n"
|
|
|
- " list_push(r, t)\n"
|
|
|
- " t = \"\"\n"
|
|
|
- " i += len(d)-1\n"
|
|
|
- " continue\n"
|
|
|
- " }\n"
|
|
|
- " t += s[i]\n"
|
|
|
- " }\n"
|
|
|
- " if t != \"\"\n"
|
|
|
- " list_push(r, t)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.split\", str_split)\n"
|
|
|
- "func str_replace(s, w, b) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if type(w) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(w)\n"
|
|
|
- " if type(b) != \"string\"\n"
|
|
|
- " throw \"expected third argument to be: string, but got: \" + type(b)\n"
|
|
|
- " var r = \"\"\n"
|
|
|
- " for var i = 0; i < len(s); i++ {\n"
|
|
|
- " if slice(s, i, i+len(w)-1) == w {\n"
|
|
|
- " r += b\n"
|
|
|
- " i += len(w)-1\n"
|
|
|
- " continue\n"
|
|
|
- " }\n"
|
|
|
- " r += s[i]\n"
|
|
|
- " }\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.replace\", str_replace)\n"
|
|
|
- "func table_keys(t) {\n"
|
|
|
- " if type(t) != \"table\"\n"
|
|
|
- " throw \"expected first argument to be: table, but got: \" + type(t)\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var k of t\n"
|
|
|
- " list_push(r, k)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"table.keys\", table_keys)\n"
|
|
|
- "func table_values(t) {\n"
|
|
|
- " if type(t) != \"table\"\n"
|
|
|
- " throw \"expected first argument to be: table, but got: \" + type(t)\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var k of t\n"
|
|
|
- " list_push(r, t[k])\n" " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"table.values\", table_values)\n"
|
|
|
- "func reduce(f, xs) {\n"
|
|
|
- " if type(f) != \"function\"\n"
|
|
|
- " throw \"expected first argument to be: function, but got: \" + type(f)\n"
|
|
|
- " if type(xs) !in (\"list\", \"tuple\", \"string\", \"bytes\")\n"
|
|
|
- " throw \"expected second argument to be: list, tuple, string or bytes, but got: \" + type(xs)\n"
|
|
|
- " if len(xs) == 0\n"
|
|
|
- " throw \"cannot reduce empty list\"\n"
|
|
|
- " r = xs[0]\n"
|
|
|
- " for var x of slice(xs, 1)\n"
|
|
|
- " r = f(r, x)\n"
|
|
|
- " if type(xs) == \"tuple\"\n"
|
|
|
- " return tuple(r)\n"
|
|
|
- " elif type(xs) == \"string\"\n"
|
|
|
- " return list_join(r)\n"
|
|
|
- " elif type(xs) == \"bytes\"\n"
|
|
|
- " return bytes(r)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.reduce\", func (xs, f): reduce(f, xs))\n"
|
|
|
- "set_pseudomethod(\"tuple.reduce\", func (xs, f): reduce(f, xs))\n"
|
|
|
- "set_pseudomethod(\"string.reduce\", func (xs, f): reduce(f, xs))\n"
|
|
|
- "set_pseudomethod(\"bytes.reduce\", func (xs, f): reduce(f, xs))\n"
|
|
|
- "func sum(xs)\n"
|
|
|
- " return reduce(func (x, y): x + y, xs)\n"
|
|
|
- "set_pseudomethod(\"list.sum\", sum)\n"
|
|
|
- "set_pseudomethod(\"tuple.sum\", sum)\n"
|
|
|
- "func product(xs)\n"
|
|
|
- " return reduce(func (x, y): x * y, xs)\n"
|
|
|
- "set_pseudomethod(\"list.product\", product)\n"
|
|
|
- "set_pseudomethod(\"tuple.product\", product)\n"
|
|
|
- "func map(f, xs) {\n"
|
|
|
- " if type(f) != \"function\"\n"
|
|
|
- " throw \"expected first argument to be: function, but got: \" + type(f)\n"
|
|
|
- " if type(xs) !in (\"list\", \"tuple\", \"string\", \"bytes\")\n"
|
|
|
- " throw \"expected second argument to be: list, tuple, string or bytes, but got: \" + type(xs)\n"
|
|
|
- " if len(xs) == 0\n"
|
|
|
- " return xs\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var x of xs\n"
|
|
|
- " list_push(r, f(x))\n"
|
|
|
- " if type(xs) == \"tuple\"\n"
|
|
|
- " return tuple(r)\n"
|
|
|
- " elif type(xs) == \"string\"\n"
|
|
|
- " return list_join(r)\n"
|
|
|
- " elif type(xs) == \"bytes\"\n"
|
|
|
- " return bytes(r)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.map\", func (xs, f): map(f, xs))\n"
|
|
|
- "set_pseudomethod(\"tuple.map\", func (xs, f): map(f, xs))\n"
|
|
|
- "set_pseudomethod(\"string.map\", func (xs, f): map(f, xs))\n"
|
|
|
- "set_pseudomethod(\"bytes.map\", func (xs, f): map(f, xs))\n"
|
|
|
- "func filter(f, xs) {\n"
|
|
|
- " if type(f) != \"function\"\n"
|
|
|
- " throw \"expected first argument to be: function, but got: \" + type(f)\n"
|
|
|
- " if type(xs) !in (\"list\", \"tuple\", \"string\", \"bytes\")\n"
|
|
|
- " throw \"expected second argument to be: list, tuple, string or bytes, but got: \" + type(xs)\n"
|
|
|
- " if len(xs) == 0\n"
|
|
|
- " return xs\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var x of xs\n"
|
|
|
- " if f(x)\n"
|
|
|
- " list_push(r, x)\n"
|
|
|
- " if type(xs) == \"tuple\"\n"
|
|
|
- " return tuple(r)\n"
|
|
|
- " elif type(xs) == \"string\"\n"
|
|
|
- " return list_join(r)\n"
|
|
|
- " elif type(xs) == \"bytes\"\n"
|
|
|
- " return bytes(r)\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"list.filter\", func (xs, f): filter(f, xs))\n"
|
|
|
- "set_pseudomethod(\"tuple.filter\", func (xs, f): filter(f, xs))\n"
|
|
|
- "set_pseudomethod(\"string.filter\", func (xs, f): filter(f, xs))\n"
|
|
|
- "set_pseudomethod(\"bytes.filter\", func (xs, f): filter(f, xs))\n"
|
|
|
- "func str_index(s, w) {\n"
|
|
|
- " if s == \"\" || w == \"\"\n"
|
|
|
- " return -1\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if type(w) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(w)\n"
|
|
|
- " for var i = 0; i < len(s); i++\n"
|
|
|
- " if len(w) == 1 && s[i] == w\n"
|
|
|
- " return i\n"
|
|
|
- " elif slice(s, i, i+len(w)-1) == w\n"
|
|
|
- " return i\n"
|
|
|
- " return -1\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.index\", str_index)\n"
|
|
|
- "func str_lstrip(s, cs=\" \\t\\n\\r\\x0b\\x0c\") {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if type(cs) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(cs)\n"
|
|
|
- " if s == \"\"\n"
|
|
|
- " return s\n"
|
|
|
- " for var i = 0; s[i] in cs && i < len(s); i++\n"
|
|
|
- " pass\n"
|
|
|
- " return slice(s, i)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.lstrip\", str_lstrip)\n"
|
|
|
- "func str_rstrip(s, cs=\" \\t\\n\\r\\x0b\\x0c\") {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if type(cs) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(cs)\n"
|
|
|
- " if s == \"\"\n"
|
|
|
- " return s\n"
|
|
|
- " for var k = 0, i = len(s)-1; s[i] in cs && i >= 0; k++\n"
|
|
|
- " i--\n"
|
|
|
- " return slice(s, 0, len(s)-k-1)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.rstrip\", str_rstrip)\n"
|
|
|
- "func str_strip(s, cs=\" \\t\\n\\r\\x0b\\x0c\") {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if type(cs) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(cs)\n"
|
|
|
- " return str_lstrip(str_rstrip(s, cs), cs)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.strip\", str_strip)\n"
|
|
|
- "func table_get(t, k, d=nil) {\n"
|
|
|
- " if type(t) != \"table\"\n"
|
|
|
- " throw \"expected first argument to be: table, but got: \" + type(t)\n"
|
|
|
- " if type(k) != \"string\"\n"
|
|
|
- " throw \"expected second argument to be: string, but got: \" + type(k)\n"
|
|
|
- " if k !in t\n"
|
|
|
- " return d\n"
|
|
|
- " return t[k]\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"table.get\", table_get)\n"
|
|
|
- "func zip() {\n"
|
|
|
- " if !arguments\n"
|
|
|
- " return []\n"
|
|
|
- " var l = map(len, arguments)\n"
|
|
|
- " l = reduce(min, l)\n"
|
|
|
- " var r = []\n"
|
|
|
- " for var i = 0; i < l; i++ {\n"
|
|
|
- " var t = []\n"
|
|
|
- " for var xs of arguments\n"
|
|
|
- " list_push(t, xs[i])\n"
|
|
|
- " list_push(r, t)\n"
|
|
|
- " }\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "func enumerate(l)\n"
|
|
|
- " if type(l) == \"table\"\n"
|
|
|
- " return zip(table_keys(l), table_values(l))\n"
|
|
|
- " else\n"
|
|
|
- " return zip(range(len(l)), l)\n"
|
|
|
- "func str_toupper(s) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(c)\n"
|
|
|
- " return map(func (c): c >= 'a' && c <= 'z'? chr(ord(c) - 32): c, s)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.toupper\", str_toupper)\n"
|
|
|
- "func str_tolower(s) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(c)\n"
|
|
|
- " return map(func (c): c >= 'A' && c <= 'Z'? chr(ord(c) + 32): c, s)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.tolower\", str_tolower)\n"
|
|
|
- "func Object(t, p=nil): return p !is nil? set_meta_table(p, get_meta_table(p) + t): set_meta_table({}, t)\n"
|
|
|
- "func is_object(o): return has_meta_table(o)\n"
|
|
|
- "func __class_wrapper(n, p, t, mt, st): return Object(st + {\n"
|
|
|
- " t: t,\n"
|
|
|
- " mt: mt,\n"
|
|
|
- " super: [],\n"
|
|
|
- " __type: func (this) use (n): return n,\n"
|
|
|
- " __str: func (this) use (n): return \"<class \" + n + \">\",\n"
|
|
|
- " __call: func (this, pargs) use (p) {\n"
|
|
|
- " var t = {}\n"
|
|
|
- " var mt = {}\n"
|
|
|
- " for var other of p {\n"
|
|
|
- " t += other.t\n"
|
|
|
- " mt += other.mt\n"
|
|
|
- " list_push(this.super, other)\n"
|
|
|
- " }\n"
|
|
|
- " if len(this.super) == 1\n"
|
|
|
- " this.super = this.super[0]\n"
|
|
|
- " t += this.t\n"
|
|
|
- " mt += this.mt\n"
|
|
|
- " t.super = this.super\n"
|
|
|
- " obj = set_meta_table(t, mt)\n"
|
|
|
- " if \"constructor\" in mt\n"
|
|
|
- " func_call(mt.constructor, [obj] + pargs)\n"
|
|
|
- " return obj\n"
|
|
|
- " }\n"
|
|
|
- "})\n"
|
|
|
- "func format(s) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " var r = \"\"\n"
|
|
|
- " var n = 1\n"
|
|
|
- " for var i = 0; i < len(s); i++\n"
|
|
|
- " switch s[i] {\n"
|
|
|
- " case '_'\n"
|
|
|
- " if i+1 < len(s) && s[i+1] == '_' {\n"
|
|
|
- " r += '_'\n"
|
|
|
- " i++\n"
|
|
|
- " continue\n"
|
|
|
- " }\n"
|
|
|
- " r += repr(arguments[n++])\n"
|
|
|
- " break\n"
|
|
|
- " default\n"
|
|
|
- " r += s[i]\n"
|
|
|
- " }\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.format\", format)\n"
|
|
|
- "func formatl(s, l) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " if type(l) != \"list\"\n"
|
|
|
- " throw \"expected second argument to be: list, but got: \" + type(l)\n"
|
|
|
- " return func_call(str_format, [s] + l)\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.formatl\", formatl)\n"
|
|
|
- "func formatd(s, t) {\n"
|
|
|
- " if type(s) != \"string\"\n"
|
|
|
- " throw \"expected first argument to be: string, but got: \" + type(s)\n"
|
|
|
- " var r = \"\"\n"
|
|
|
- " var n = 1\n"
|
|
|
- " for var i = 0; i < len(s); i++\n"
|
|
|
- " switch s[i] {\n"
|
|
|
- " case '{'\n"
|
|
|
- " if i+1 < len(s) && s[i+1] == '{' {\n"
|
|
|
- " r += '{'\n"
|
|
|
- " i++\n"
|
|
|
- " continue\n"
|
|
|
- " }\n"
|
|
|
- " var k = ''\n"
|
|
|
- " i++\n"
|
|
|
- " for i < len(s) && s[i] != '}'\n"
|
|
|
- " k += s[i++]\n"
|
|
|
- " if i >= len(s) || s[i] != '}'\n"
|
|
|
- " throw \"unmatched { in format specifier\"\n"
|
|
|
- " if !k\n"
|
|
|
- " throw \"empty format key\"\n"
|
|
|
- " r += repr(t[k])\n"
|
|
|
- " break\n"
|
|
|
- " default\n"
|
|
|
- " r += s[i]\n"
|
|
|
- " }\n"
|
|
|
- " return r\n"
|
|
|
- "}\n"
|
|
|
- "set_pseudomethod(\"string.formatd\", formatd)\n"
|
|
|
- "func getch() return chr(fgetc(STDIN))\n"
|
|
|
- "func putch(c) fputc(STDOUT, c)\n"
|
|
|
- "func getline()\n"
|
|
|
- " return fgets(STDIN, 256)\n"
|
|
|
- "func input() {\n"
|
|
|
- " if len(arguments) > 0\n"
|
|
|
- " func_call(print, arguments)\n"
|
|
|
- " return str_rstrip(getline(), \"\\n\\r\")\n"
|
|
|
- "}\n"
|
|
|
- "func open(path, mode=\"r\"): fopen(path, mode)\n"
|
|
|
- "func assert(cond, msg=\"assertion failed\")\n"
|
|
|
- " if !cond\n"
|
|
|
- " throw msg\n"
|
|
|
- },
|
|
|
-
|
|
|
{"utf8",
|
|
|
"func utf8_chrlen(s) {\n"
|
|
|
" s = bytes(s)\n"
|
|
@@ -3603,9 +3089,9 @@ char *unescape(char *s) {
|
|
|
return buffer_read(buf);
|
|
|
}
|
|
|
|
|
|
-void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl);
|
|
|
+void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl);
|
|
|
|
|
|
-int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, char *path) {
|
|
|
+int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, char *path) {
|
|
|
char *source = NULL;
|
|
|
|
|
|
for (size_t i = 0; STD[i][0]; i++) {
|
|
@@ -3655,7 +3141,7 @@ int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stac
|
|
|
|
|
|
buffer_t *HBUF;
|
|
|
|
|
|
-void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node) {
|
|
|
+void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl, node_t *node) {
|
|
|
switch (node->tag) {
|
|
|
case N_TOPLEVEL: case N_PROGRAM:
|
|
|
compile_block(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l);
|
|
@@ -3790,7 +3276,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
NEWGID();
|
|
|
|
|
|
- buffer_fmt(tbuf, "inline static qi_value_t *__fstring%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "inline static qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
buffer_fmt(tbuf, "qi_value_t *str = state->empty_string;\n");
|
|
|
|
|
|
for (size_t i = 0; i < parts->length; i++) {
|
|
@@ -3813,7 +3299,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__fstring%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
} break;
|
|
|
|
|
|
case T_NAME: {
|
|
@@ -3842,7 +3328,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "inline static qi_value_t *__listgen%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "inline static qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
buffer_fmt(tbuf, "qi_list_t *list = qi_list_make();\n");
|
|
|
|
|
|
buffer_t *bbuf = buffer_new();
|
|
@@ -3871,7 +3357,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__listgen%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
} break;
|
|
|
|
|
|
case N_TUPLE:
|
|
@@ -3924,7 +3410,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "inline static qi_value_t *__slice%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "inline static qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
|
|
|
if (node->b && node->c) {
|
|
|
buffer_fmt(tbuf, "qi_list_t *pargs = qi_list_make_n(3);\n");
|
|
@@ -3966,7 +3452,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__slice%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
} break;
|
|
|
|
|
|
case N_ASSIGN:
|
|
@@ -3978,7 +3464,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "inline static qi_value_t *__assign%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "inline static qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
|
|
|
char *varname = tempvar();
|
|
|
|
|
@@ -3995,7 +3481,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__assign%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
|
|
|
break;
|
|
|
} else if (node->a->tag == N_TUPLE) {
|
|
@@ -4009,7 +3495,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "qi_value_t *__assign%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *__%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
|
|
|
list_t *vals = list_new();
|
|
|
for (size_t i = 0; i < node->b->l->length; i++) {
|
|
@@ -4033,7 +3519,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("__assign%d(state)", gid);
|
|
|
+ EMIT("__%s%d(state)", PREFIX, gid);
|
|
|
|
|
|
break;
|
|
|
}
|
|
@@ -4106,7 +3592,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
if (table_get(ltab, node->t2->text))
|
|
|
COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
|
|
|
|
- stack_t *pair = stack_new();
|
|
|
+ int_stack_t *pair = stack_new();
|
|
|
|
|
|
stack_push(pair, 1);
|
|
|
stack_push(pair, gid);
|
|
@@ -4163,7 +3649,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
if (table_get(ltab, node->t2->text))
|
|
|
COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
|
|
|
|
- stack_t *pair = stack_new();
|
|
|
+ int_stack_t *pair = stack_new();
|
|
|
|
|
|
stack_push(pair, 0);
|
|
|
stack_push(pair, gid);
|
|
@@ -4211,7 +3697,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
if (table_get(ltab, node->t2->text))
|
|
|
COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
|
|
|
|
- stack_t *pair = stack_new();
|
|
|
+ int_stack_t *pair = stack_new();
|
|
|
|
|
|
stack_push(pair, 0);
|
|
|
stack_push(pair, gid);
|
|
@@ -4267,7 +3753,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
} else {
|
|
|
char *label = node->t->text;
|
|
|
|
|
|
- stack_t *pair = table_get(ltab, label);
|
|
|
+ int_stack_t *pair = table_get(ltab, label);
|
|
|
|
|
|
if (!pair)
|
|
|
COMPILE_ERROR("undefined loop label: '%s'", label);
|
|
@@ -4296,7 +3782,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
} else {
|
|
|
char *label = node->t->text;
|
|
|
|
|
|
- stack_t *pair = table_get(ltab, label);
|
|
|
+ int_stack_t *pair = table_get(ltab, label);
|
|
|
|
|
|
if (pair->data[1])
|
|
|
COMPILE_ERROR("continue on a switch loop label: '%s'", label);
|
|
@@ -4318,7 +3804,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "void __defer%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "void __%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
|
|
|
LBPUSH();
|
|
|
CTXPUSH("gap");
|
|
@@ -4332,7 +3818,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("qi_add_defer(state, -1, __defer%d);", gid);
|
|
|
+ EMIT("qi_add_defer(state, -1, __%s%d);", PREFIX, gid);
|
|
|
} break;
|
|
|
|
|
|
case N_RETURN:
|
|
@@ -4396,7 +3882,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
- buffer_fmt(tbuf, "void __finally%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "void __%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
|
LBPUSH();
|
|
|
CTXPUSH("gap");
|
|
|
compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->c);
|
|
@@ -4407,7 +3893,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
|
|
|
|
- EMIT("}, __finally%d);\n", gid);
|
|
|
+ EMIT("}, __%s%d);\n", PREFIX, gid);
|
|
|
} else {
|
|
|
EMIT("}, NULL);\n");
|
|
|
}
|
|
@@ -4593,7 +4079,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl) {
|
|
|
+void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, int_stack_t *lstk, int_stack_t *sstk, list_t *lbl) {
|
|
|
node_t *n = parse(source);
|
|
|
|
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
|
|
@@ -4615,8 +4101,8 @@ char *escape(char *s) {
|
|
|
char *compile(char *source, list_t *required) {
|
|
|
list_t *ctx = list_new();
|
|
|
table_t *ltab = table_new();
|
|
|
- stack_t *lstk = stack_new();
|
|
|
- stack_t *sstk = stack_new();
|
|
|
+ int_stack_t *lstk = stack_new();
|
|
|
+ int_stack_t *sstk = stack_new();
|
|
|
list_t *lbl = list_new();
|
|
|
LBPUSH();
|
|
|
|
|
@@ -4726,7 +4212,15 @@ int main(int argc, char **argv) {
|
|
|
DEBUG = 1;
|
|
|
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--stdin") == 0)
|
|
|
readstdin = 1;
|
|
|
- else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) {
|
|
|
+ else if (strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--prefix") == 0) {
|
|
|
+ if (i+1 >= argc) {
|
|
|
+ fprintf(stderr, "fatal: missing argument after '-p/--prefix' parameter\n");
|
|
|
+
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ PREFIX = argv[++i];
|
|
|
+ } else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) {
|
|
|
if (i+1 >= argc) {
|
|
|
fprintf(stderr, "fatal: missing argument after '-o/--output' parameter\n");
|
|
|
|
|
@@ -4740,7 +4234,7 @@ int main(int argc, char **argv) {
|
|
|
fprintf(stderr, "-h --help\tprint this message and exit\n");
|
|
|
fprintf(stderr, "-d --debug\tenable debug mode\n");
|
|
|
fprintf(stderr, "-s --stdin\tread stdin as input\n");
|
|
|
- fprintf(stderr, "-o --outout path\toutput generated C code to 'path'\n");
|
|
|
+ fprintf(stderr, "-o --output\toutput generated C code to the specified file\n");
|
|
|
|
|
|
return 0;
|
|
|
} else {
|
|
@@ -4761,6 +4255,18 @@ int main(int argc, char **argv) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (!PREFIX) {
|
|
|
+ const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
+
|
|
|
+ srand(time(NULL));
|
|
|
+
|
|
|
+ PREFIX = malloc(sizeof(char) * 9);
|
|
|
+ PREFIX[8] = 0;
|
|
|
+
|
|
|
+ for (size_t i = 0; i < 8; i++)
|
|
|
+ PREFIX[i] = chars[(size_t)((double) rand() / RAND_MAX * (sizeof(chars) - 1))];
|
|
|
+ }
|
|
|
+
|
|
|
if (readstdin || !main)
|
|
|
out = compile_file("<stdin>", stdin, required);
|
|
|
else {
|
|
@@ -4778,7 +4284,7 @@ int main(int argc, char **argv) {
|
|
|
fclose(fd);
|
|
|
}
|
|
|
|
|
|
- if (outf) {
|
|
|
+ if (outf && strcmp(outf, "-") != 0) {
|
|
|
FILE *fd = fopen(outf, "wb");
|
|
|
if (!fd) {
|
|
|
fprintf(stderr, "fatal: unable to open output file: '%s'\n", outf);
|