|
@@ -703,8 +703,8 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
|
|
|
return t;
|
|
return t;
|
|
} else if (source[*pos] == 'u' &&
|
|
} else if (source[*pos] == 'u' &&
|
|
- (source[(*pos) + 1] == '"' || source[(*pos) + 1] == '\'' ||
|
|
|
|
- source[(*pos) + 1] == '`')) {
|
|
|
|
|
|
+ (source[(*pos) + 1] == '"' || source[(*pos) + 1] == '\'' ||
|
|
|
|
+ source[(*pos) + 1] == '`')) {
|
|
(*pos)++;
|
|
(*pos)++;
|
|
|
|
|
|
token_t *t = tokenize_string(source, pos);
|
|
token_t *t = tokenize_string(source, pos);
|
|
@@ -1583,7 +1583,9 @@ node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
EXPECT(RCB, "}");
|
|
EXPECT(RCB, "}");
|
|
|
|
|
|
return NODEH(TABLE, table);
|
|
return NODEH(TABLE, table);
|
|
- } else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) || MATCH(USTRING) || MATCH(NAME) || MATCH(TRUE) || MATCH(FALSE) || MATCH(NIL))
|
|
|
|
|
|
+ } else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) ||
|
|
|
|
+ MATCH(USTRING) || MATCH(NAME) || MATCH(TRUE) || MATCH(FALSE) ||
|
|
|
|
+ MATCH(NIL))
|
|
return NODET(LITERAL, tokens->data[(*pos) - 1]);
|
|
return NODET(LITERAL, tokens->data[(*pos) - 1]);
|
|
|
|
|
|
if (MATCH(RPAR)) {
|
|
if (MATCH(RPAR)) {
|
|
@@ -2593,32 +2595,32 @@ node_t *_parse_stmt(list_t *tokens, size_t *pos, int allow_comma) {
|
|
|
|
|
|
if (!CLIFF && !AT(EOF) && !AT(SEMI)) {
|
|
if (!CLIFF && !AT(EOF) && !AT(SEMI)) {
|
|
EXPECT(LCB, "{");
|
|
EXPECT(LCB, "{");
|
|
-
|
|
|
|
|
|
+
|
|
for (;;) {
|
|
for (;;) {
|
|
int is_out = 0;
|
|
int is_out = 0;
|
|
int is_static = 0;
|
|
int is_static = 0;
|
|
-
|
|
|
|
|
|
+
|
|
if (AT(RCB))
|
|
if (AT(RCB))
|
|
break;
|
|
break;
|
|
-
|
|
|
|
|
|
+
|
|
if (MATCH(LET))
|
|
if (MATCH(LET))
|
|
is_out = 1;
|
|
is_out = 1;
|
|
else if (MATCH(CONST))
|
|
else if (MATCH(CONST))
|
|
is_static = 1;
|
|
is_static = 1;
|
|
-
|
|
|
|
|
|
+
|
|
if (!AT(NAME))
|
|
if (!AT(NAME))
|
|
PARSE_ERROR("expected identifier");
|
|
PARSE_ERROR("expected identifier");
|
|
-
|
|
|
|
|
|
+
|
|
list_t *triple = list_new();
|
|
list_t *triple = list_new();
|
|
-
|
|
|
|
|
|
+
|
|
token_t *t = tokens->data[(*pos)++];
|
|
token_t *t = tokens->data[(*pos)++];
|
|
list_push(triple, t);
|
|
list_push(triple, t);
|
|
-
|
|
|
|
|
|
+
|
|
int *flagp = malloc_checked(sizeof(int));
|
|
int *flagp = malloc_checked(sizeof(int));
|
|
int flag = is_static ? 2 : is_out ? 1 : 0;
|
|
int flag = is_static ? 2 : is_out ? 1 : 0;
|
|
-
|
|
|
|
|
|
+
|
|
memcpy(flagp, &flag, sizeof(int));
|
|
memcpy(flagp, &flag, sizeof(int));
|
|
-
|
|
|
|
|
|
+
|
|
if (MATCH(ASSIGN)) {
|
|
if (MATCH(ASSIGN)) {
|
|
list_push(triple, flagp);
|
|
list_push(triple, flagp);
|
|
list_push(triple, parse_expr(tokens, pos));
|
|
list_push(triple, parse_expr(tokens, pos));
|
|
@@ -2626,10 +2628,10 @@ node_t *_parse_stmt(list_t *tokens, size_t *pos, int allow_comma) {
|
|
list_push(triple, flagp);
|
|
list_push(triple, flagp);
|
|
list_push(triple, parse_func(tokens, pos, 1));
|
|
list_push(triple, parse_func(tokens, pos, 1));
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
list_push(triples, triple);
|
|
list_push(triples, triple);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
EXPECT(RCB, "}");
|
|
EXPECT(RCB, "}");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2663,7 +2665,8 @@ node_t *_parse_stmt(list_t *tokens, size_t *pos, int allow_comma) {
|
|
return NODET(INLINE, t);
|
|
return NODET(INLINE, t);
|
|
}
|
|
}
|
|
|
|
|
|
- return NODE1(EXPRSTMT, allow_comma? parse_comma_expr(tokens, pos): parse_expr(tokens, pos));
|
|
|
|
|
|
+ return NODE1(EXPRSTMT, allow_comma ? parse_comma_expr(tokens, pos)
|
|
|
|
+ : parse_expr(tokens, pos));
|
|
}
|
|
}
|
|
|
|
|
|
#define ATM(t) \
|
|
#define ATM(t) \
|
|
@@ -3041,14 +3044,14 @@ node_t *parse(char *source) {
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a); \
|
|
EMIT(")"); \
|
|
EMIT(")"); \
|
|
}
|
|
}
|
|
-#define ASSIGNIN(buf, lhs, rhs, prefix) \
|
|
|
|
|
|
+#define ASSIGNIN(buf, lhs, rhs, prefix) \
|
|
{ \
|
|
{ \
|
|
if ((lhs)->tag == N_LITERAL && (lhs)->t->tag == T_NAME) { \
|
|
if ((lhs)->tag == N_LITERAL && (lhs)->t->tag == T_NAME) { \
|
|
- buffer_fmt(buf, "qi_set(state, " #prefix ", \"%s\", ", (lhs)->t->text); \
|
|
|
|
|
|
+ buffer_fmt(buf, "qi_set(state, " #prefix ", \"%s\", ", (lhs)->t->text); \
|
|
rhs; \
|
|
rhs; \
|
|
buffer_fmt(buf, ")"); \
|
|
buffer_fmt(buf, ")"); \
|
|
} else if ((lhs)->tag == N_INDEX) { \
|
|
} else if ((lhs)->tag == N_INDEX) { \
|
|
- buffer_fmt(buf, "qi_index_set(state, " #prefix ", "); \
|
|
|
|
|
|
+ buffer_fmt(buf, "qi_index_set(state, " #prefix ", "); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a); \
|
|
buffer_fmt(buf, ", "); \
|
|
buffer_fmt(buf, ", "); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->b); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->b); \
|
|
@@ -3056,7 +3059,7 @@ node_t *parse(char *source) {
|
|
rhs; \
|
|
rhs; \
|
|
buffer_fmt(buf, ")"); \
|
|
buffer_fmt(buf, ")"); \
|
|
} else if ((lhs)->tag == N_MEMBER) { \
|
|
} else if ((lhs)->tag == N_MEMBER) { \
|
|
- buffer_fmt(buf, "qi_index_set(state, " #prefix ", "); \
|
|
|
|
|
|
+ buffer_fmt(buf, "qi_index_set(state, " #prefix ", "); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a); \
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a); \
|
|
buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text); \
|
|
buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text); \
|
|
rhs; \
|
|
rhs; \
|
|
@@ -3075,15 +3078,18 @@ node_t *parse(char *source) {
|
|
EMIT(")"); \
|
|
EMIT(")"); \
|
|
}); \
|
|
}); \
|
|
}
|
|
}
|
|
-#define COMPASSIGNP(lhs, s, rhs) \
|
|
|
|
|
|
+#define COMPASSIGNP(lhs, s, rhs) \
|
|
{ \
|
|
{ \
|
|
- ASSIGNIN(buf, node->a, { \
|
|
|
|
- EMIT("qi_%s(state, ", s); \
|
|
|
|
- compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)); \
|
|
|
|
- EMIT(", "); \
|
|
|
|
- rhs; \
|
|
|
|
- EMIT(")"); \
|
|
|
|
- }, true); \
|
|
|
|
|
|
+ ASSIGNIN( \
|
|
|
|
+ buf, node->a, \
|
|
|
|
+ { \
|
|
|
|
+ EMIT("qi_%s(state, ", s); \
|
|
|
|
+ compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)); \
|
|
|
|
+ EMIT(", "); \
|
|
|
|
+ rhs; \
|
|
|
|
+ EMIT(")"); \
|
|
|
|
+ }, \
|
|
|
|
+ true); \
|
|
}
|
|
}
|
|
#define COMPILE_ERROR(fmt, ...) \
|
|
#define COMPILE_ERROR(fmt, ...) \
|
|
{ \
|
|
{ \
|
|
@@ -3098,8 +3104,7 @@ node_t *parse(char *source) {
|
|
}
|
|
}
|
|
|
|
|
|
void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- node_t *node);
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, node_t *node);
|
|
|
|
|
|
char *tempvar() {
|
|
char *tempvar() {
|
|
NEWGID();
|
|
NEWGID();
|
|
@@ -3111,8 +3116,7 @@ char *tempvar() {
|
|
}
|
|
}
|
|
|
|
|
|
void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- list_t *seq) {
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, list_t *seq) {
|
|
if (!seq || seq->length < 1) {
|
|
if (!seq || seq->length < 1) {
|
|
EMIT("NULL");
|
|
EMIT("NULL");
|
|
|
|
|
|
@@ -3179,8 +3183,7 @@ void compile_list(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
}
|
|
}
|
|
|
|
|
|
void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
void compile_table(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- table_t *table) {
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, table_t *table) {
|
|
if (!table || table->used < 1) {
|
|
if (!table || table->used < 1) {
|
|
EMIT("NULL");
|
|
EMIT("NULL");
|
|
|
|
|
|
@@ -3218,7 +3221,7 @@ int in_context(list_t *ctx, char *s) {
|
|
if (!ctx->length)
|
|
if (!ctx->length)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- for (ssize_t i = ctx->length - 1; i >= 0; i--)
|
|
|
|
|
|
+ for (ssize_t i = ctx->length - 1; i >= 0; i--)
|
|
if (strcmp(ctx->data[i], "gap") == 0)
|
|
if (strcmp(ctx->data[i], "gap") == 0)
|
|
break;
|
|
break;
|
|
else if (strcmp(ctx->data[i], s) == 0)
|
|
else if (strcmp(ctx->data[i], s) == 0)
|
|
@@ -3261,21 +3264,23 @@ list_t *CONSTANTS;
|
|
#define SCOPESK (count_ctxs(ctx, "scope"))
|
|
#define SCOPESK (count_ctxs(ctx, "scope"))
|
|
#define TRAPSK (count_ctxs(ctx, "trap"))
|
|
#define TRAPSK (count_ctxs(ctx, "trap"))
|
|
|
|
|
|
-#define LPUSH(i) {\
|
|
|
|
- int_stack_t *pair = stack_new();\
|
|
|
|
- stack_push(pair, (i));\
|
|
|
|
- stack_push(pair, scope_index(ctx));\
|
|
|
|
- list_push(lstk, pair);\
|
|
|
|
-}
|
|
|
|
|
|
+#define LPUSH(i) \
|
|
|
|
+ { \
|
|
|
|
+ int_stack_t *pair = stack_new(); \
|
|
|
|
+ stack_push(pair, (i)); \
|
|
|
|
+ stack_push(pair, scope_index(ctx)); \
|
|
|
|
+ list_push(lstk, pair); \
|
|
|
|
+ }
|
|
#define LPOP() list_pop(lstk)
|
|
#define LPOP() list_pop(lstk)
|
|
#define LID (((int_stack_t *)lstk->data[lstk->length - 1])->data[0])
|
|
#define LID (((int_stack_t *)lstk->data[lstk->length - 1])->data[0])
|
|
|
|
|
|
-#define SPUSH(i) {\
|
|
|
|
- int_stack_t *pair = stack_new();\
|
|
|
|
- stack_push(pair, (i));\
|
|
|
|
- stack_push(pair, scope_index(ctx));\
|
|
|
|
- list_push(sstk, pair);\
|
|
|
|
-}
|
|
|
|
|
|
+#define SPUSH(i) \
|
|
|
|
+ { \
|
|
|
|
+ int_stack_t *pair = stack_new(); \
|
|
|
|
+ stack_push(pair, (i)); \
|
|
|
|
+ stack_push(pair, scope_index(ctx)); \
|
|
|
|
+ list_push(sstk, pair); \
|
|
|
|
+ }
|
|
#define SPOP() list_pop(sstk)
|
|
#define SPOP() list_pop(sstk)
|
|
#define SID (sstk->data[sstk->length - 1]->data[0])
|
|
#define SID (sstk->data[sstk->length - 1]->data[0])
|
|
|
|
|
|
@@ -3303,8 +3308,8 @@ void emit_debug(buffer_t *buf, node_t *node) {
|
|
}
|
|
}
|
|
|
|
|
|
void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- node_t *node, char *name) {
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, node_t *node,
|
|
|
|
+ char *name) {
|
|
NEWGID();
|
|
NEWGID();
|
|
|
|
|
|
char *funname = name ? name : node->t ? node->t->text : "<anon>";
|
|
char *funname = name ? name : node->t ? node->t->text : "<anon>";
|
|
@@ -3434,8 +3439,7 @@ size_t scope_index(list_t *ctx) {
|
|
}
|
|
}
|
|
|
|
|
|
void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- list_t *block) {
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, list_t *block) {
|
|
for (size_t i = 0; i < block->length; i++) {
|
|
for (size_t i = 0; i < block->length; i++) {
|
|
node_t *node = block->data[i];
|
|
node_t *node = block->data[i];
|
|
|
|
|
|
@@ -3558,196 +3562,195 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
|
|
|
const char *STD[][2] = {
|
|
const char *STD[][2] = {
|
|
{"json",
|
|
{"json",
|
|
- "require \"string\"\n"
|
|
|
|
- "class JSONError(Error)\n"
|
|
|
|
- "func json_tokenize(s) {\n"
|
|
|
|
- " let toks = []\n"
|
|
|
|
- " for var i = 0; i < len(s); i++ {\n"
|
|
|
|
- " if isws(s[i])\n"
|
|
|
|
- " continue\n"
|
|
|
|
- " if s[i] in \"[]{}:,\"\n"
|
|
|
|
- " toks.push((s[i], nil))\n"
|
|
|
|
- " elif isalpha(s[i]) {\n"
|
|
|
|
- " var text = \"\"\n"
|
|
|
|
- " for i < len(s) && isalpha(s[i])\n"
|
|
|
|
- " text += s[i++]\n"
|
|
|
|
- " i--\n"
|
|
|
|
- " toks.push((\"name\", text))\n"
|
|
|
|
- " } elif s[i] == '-' || isdigit(s[i]) {\n"
|
|
|
|
- " var text = \"\"\n"
|
|
|
|
- " if s[i] == '-'\n"
|
|
|
|
- " text += s[i++]\n"
|
|
|
|
- " if i >= len(s) || !isdigit(s[i])\n"
|
|
|
|
- " throw JSONError(f\"${i}: malformed number literal\")\n"
|
|
|
|
- " for i < len(s) && isdigit(s[i]) {\n"
|
|
|
|
- " text += s[i++]\n"
|
|
|
|
- " if i < len(s) && s[i] == \".\" && \".\" !in text\n"
|
|
|
|
- " text += s[i++]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " i--\n"
|
|
|
|
- " toks.push((\"number\", text))\n"
|
|
|
|
- " } elif s[i] == '\"' {\n"
|
|
|
|
- " var text = \"\"\n"
|
|
|
|
- " i++\n"
|
|
|
|
- " for i < len(s) && s[i] != '\"' {\n"
|
|
|
|
- " var c = s[i++]\n"
|
|
|
|
- " if c == `\\` {\n"
|
|
|
|
- " if i >= len(s)\n"
|
|
|
|
- " throw JSONError(f\"#${i}: unterminated string literal\")\n"
|
|
|
|
- " switch s[i] {\n"
|
|
|
|
- " case \"n\":\n"
|
|
|
|
- " c = \"\\n\"\n"
|
|
|
|
- " break\n"
|
|
|
|
- " case \"r\":\n"
|
|
|
|
- " c = \"\\r\"\n"
|
|
|
|
- " break\n"
|
|
|
|
- " case \"t\":\n"
|
|
|
|
- " c = \"\\t\"\n"
|
|
|
|
- " break\n"
|
|
|
|
- " }\n"
|
|
|
|
- " i++\n"
|
|
|
|
- " }\n"
|
|
|
|
- " text += c\n"
|
|
|
|
- " }\n"
|
|
|
|
- " if i >= len(s) || s[i] != '\"'\n"
|
|
|
|
- " throw JSONError(f\"#${i}: unterminated string literal\")\n"
|
|
|
|
- " toks.push((\"string\", text))\n"
|
|
|
|
- " } else\n"
|
|
|
|
- " throw JSONError(f\"#${i}: unknown input\")\n"
|
|
|
|
- " }\n"
|
|
|
|
- " return toks\n"
|
|
|
|
- "}\n"
|
|
|
|
- "func json_parse(toks) {\n"
|
|
|
|
- " func parse_array(toks) {\n"
|
|
|
|
- " let r = []\n"
|
|
|
|
- " if toks && toks[0][0] == ']'\n"
|
|
|
|
- " return r, toks[1:]\n"
|
|
|
|
- " for {\n"
|
|
|
|
- " var e\n"
|
|
|
|
- " [e, toks] = parse_expression(toks)\n"
|
|
|
|
- " r.push(e)\n"
|
|
|
|
- " if !toks || toks[0][0] != ','\n"
|
|
|
|
- " break\n"
|
|
|
|
- " if toks[0][0] == \",\"\n"
|
|
|
|
- " toks = toks[1:]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " if !toks || toks[0][0] != ']'\n"
|
|
|
|
- " throw JSONError(\"missing ]\")\n"
|
|
|
|
- " return r, toks[1:]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " func parse_object(toks) {\n"
|
|
|
|
- " let r = {}\n"
|
|
|
|
- " for {\n"
|
|
|
|
- " var k, e\n"
|
|
|
|
- " if !toks || toks[0][0] != \"string\"\n"
|
|
|
|
- " throw JSONError(\"expected string\")\n"
|
|
|
|
- " k = toks[0][1]\n"
|
|
|
|
- " toks = toks[1:]\n"
|
|
|
|
- " if !toks || toks[0][0] != \":\"\n"
|
|
|
|
- " throw JSONError(\"expected :\")\n"
|
|
|
|
- " toks = toks[1:]\n"
|
|
|
|
- " [e, toks] = parse_expression(toks)\n"
|
|
|
|
- " r[k] = e\n"
|
|
|
|
- " if !toks || toks[0][0] != \",\"\n"
|
|
|
|
- " break\n"
|
|
|
|
- " if toks[0][0] == \",\"\n"
|
|
|
|
- " toks = toks[1:]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " if !toks || toks[0][0] != \"}\"\n"
|
|
|
|
- " throw JSONError(\"missing }\")\n"
|
|
|
|
- " return r, toks[1:]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " func parse_expression(toks) {\n"
|
|
|
|
- " if toks\n"
|
|
|
|
- " switch toks[0][0] {\n"
|
|
|
|
- " case \"{\":\n"
|
|
|
|
- " return parse_object(toks[1:])\n"
|
|
|
|
- " case \"[\":\n"
|
|
|
|
- " return parse_array(toks[1:])\n"
|
|
|
|
- " case \"name\":\n"
|
|
|
|
- " switch toks[0][1] {\n"
|
|
|
|
- " case \"true\":\n"
|
|
|
|
- " return true, toks[1:]\n"
|
|
|
|
- " case \"false\":\n"
|
|
|
|
- " return false, toks[1:]\n"
|
|
|
|
- " case \"null\":\n"
|
|
|
|
- " return nil, toks[1:]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " throw JSONError(f\"illegal name: ${toks[0][1]}\")\n"
|
|
|
|
- " case \"number\":\n"
|
|
|
|
- " return num(toks[0][1]), toks[1:]\n"
|
|
|
|
- " case \"string\":\n"
|
|
|
|
- " return toks[0][1], toks[1:]\n"
|
|
|
|
- " }\n"
|
|
|
|
- " throw JSONError(\"expected expression\")\n"
|
|
|
|
- " }\n"
|
|
|
|
- " if !toks\n"
|
|
|
|
- " throw JSONError(\"empty document\")\n"
|
|
|
|
- " if toks[0][0] !in \"{[\"\n"
|
|
|
|
- " throw JSONError(\"expected { or [\")\n"
|
|
|
|
- " let [r, unconsumed] = parse_expression(toks)\n"
|
|
|
|
- " if unconsumed\n"
|
|
|
|
- " throw JSONError(\"unconsumed input\")\n"
|
|
|
|
- " return r\n"
|
|
|
|
- "}\n"
|
|
|
|
- "func json_read(s)\n"
|
|
|
|
- " return json_parse(json_tokenize(s))\n"
|
|
|
|
- "func json_dump(d) {\n"
|
|
|
|
- " func escape(s) {\n"
|
|
|
|
- " var r = \"\"\n"
|
|
|
|
- " \n"
|
|
|
|
- " for var c of s {\n"
|
|
|
|
- " if c == `\\`\n"
|
|
|
|
- " r += `\\\\`\n"
|
|
|
|
- " elif c == '\"'\n"
|
|
|
|
- " r += `\\\"`\n"
|
|
|
|
- " elif c == \"\\n\"\n"
|
|
|
|
- " r += `\\n`\n"
|
|
|
|
- " elif c == \"\\r\"\n"
|
|
|
|
- " r += `\\r`\n"
|
|
|
|
- " elif c == \"\\t\"\n"
|
|
|
|
- " r += `\\t`\n"
|
|
|
|
- " else r += c\n"
|
|
|
|
- " }\n"
|
|
|
|
- " return r\n"
|
|
|
|
- " }\n"
|
|
|
|
- " switch type(d) {\n"
|
|
|
|
- " case \"nil\":\n"
|
|
|
|
- " return \"null\"\n"
|
|
|
|
- " case \"bool\":\n"
|
|
|
|
- " return d? \"true\": \"false\"\n"
|
|
|
|
- " case \"number\":\n"
|
|
|
|
- " return str(d)\n"
|
|
|
|
- " case \"string\":\n"
|
|
|
|
- " return \"\\\"\" + escape(d) + \"\\\"\"\n"
|
|
|
|
- " case \"list\":\n"
|
|
|
|
- " var f = true\n"
|
|
|
|
- " var buf = \"[\"\n"
|
|
|
|
- " for var el of d {\n"
|
|
|
|
- " if f\n"
|
|
|
|
- " f = false\n"
|
|
|
|
- " else\n"
|
|
|
|
- " buf += \", \"\n"
|
|
|
|
- " buf += json_dump(el) \n"
|
|
|
|
- " }\n"
|
|
|
|
- " buf += \"]\"\n"
|
|
|
|
- " return buf\n"
|
|
|
|
- " case \"table\":\n"
|
|
|
|
- " var f = true\n"
|
|
|
|
- " var buf = \"{\"\n"
|
|
|
|
- " for var [k, v] of enumerate(d) {\n"
|
|
|
|
- " if f\n"
|
|
|
|
- " f = false\n"
|
|
|
|
- " else\n"
|
|
|
|
- " buf += \", \"\n"
|
|
|
|
- " buf += f`\"${escape(k)}\": ${json_dump(v)}`\n"
|
|
|
|
- " }\n"
|
|
|
|
- " buf += \"}\"\n"
|
|
|
|
- " return buf\n"
|
|
|
|
- " }\n"
|
|
|
|
- " throw JSONError(f\"cannot serialize ${type(d)} into a JSON\")\n"
|
|
|
|
- "}\n"
|
|
|
|
- },
|
|
|
|
|
|
+ "require \"string\"\n"
|
|
|
|
+ "class JSONError(Error)\n"
|
|
|
|
+ "func json_tokenize(s) {\n"
|
|
|
|
+ " let toks = []\n"
|
|
|
|
+ " for var i = 0; i < len(s); i++ {\n"
|
|
|
|
+ " if isws(s[i])\n"
|
|
|
|
+ " continue\n"
|
|
|
|
+ " if s[i] in \"[]{}:,\"\n"
|
|
|
|
+ " toks.push((s[i], nil))\n"
|
|
|
|
+ " elif isalpha(s[i]) {\n"
|
|
|
|
+ " var text = \"\"\n"
|
|
|
|
+ " for i < len(s) && isalpha(s[i])\n"
|
|
|
|
+ " text += s[i++]\n"
|
|
|
|
+ " i--\n"
|
|
|
|
+ " toks.push((\"name\", text))\n"
|
|
|
|
+ " } elif s[i] == '-' || isdigit(s[i]) {\n"
|
|
|
|
+ " var text = \"\"\n"
|
|
|
|
+ " if s[i] == '-'\n"
|
|
|
|
+ " text += s[i++]\n"
|
|
|
|
+ " if i >= len(s) || !isdigit(s[i])\n"
|
|
|
|
+ " throw JSONError(f\"${i}: malformed number literal\")\n"
|
|
|
|
+ " for i < len(s) && isdigit(s[i]) {\n"
|
|
|
|
+ " text += s[i++]\n"
|
|
|
|
+ " if i < len(s) && s[i] == \".\" && \".\" !in text\n"
|
|
|
|
+ " text += s[i++]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " i--\n"
|
|
|
|
+ " toks.push((\"number\", text))\n"
|
|
|
|
+ " } elif s[i] == '\"' {\n"
|
|
|
|
+ " var text = \"\"\n"
|
|
|
|
+ " i++\n"
|
|
|
|
+ " for i < len(s) && s[i] != '\"' {\n"
|
|
|
|
+ " var c = s[i++]\n"
|
|
|
|
+ " if c == `\\` {\n"
|
|
|
|
+ " if i >= len(s)\n"
|
|
|
|
+ " throw JSONError(f\"#${i}: unterminated string literal\")\n"
|
|
|
|
+ " switch s[i] {\n"
|
|
|
|
+ " case \"n\":\n"
|
|
|
|
+ " c = \"\\n\"\n"
|
|
|
|
+ " break\n"
|
|
|
|
+ " case \"r\":\n"
|
|
|
|
+ " c = \"\\r\"\n"
|
|
|
|
+ " break\n"
|
|
|
|
+ " case \"t\":\n"
|
|
|
|
+ " c = \"\\t\"\n"
|
|
|
|
+ " break\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " i++\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " text += c\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " if i >= len(s) || s[i] != '\"'\n"
|
|
|
|
+ " throw JSONError(f\"#${i}: unterminated string literal\")\n"
|
|
|
|
+ " toks.push((\"string\", text))\n"
|
|
|
|
+ " } else\n"
|
|
|
|
+ " throw JSONError(f\"#${i}: unknown input\")\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " return toks\n"
|
|
|
|
+ "}\n"
|
|
|
|
+ "func json_parse(toks) {\n"
|
|
|
|
+ " func parse_array(toks) {\n"
|
|
|
|
+ " let r = []\n"
|
|
|
|
+ " if toks && toks[0][0] == ']'\n"
|
|
|
|
+ " return r, toks[1:]\n"
|
|
|
|
+ " for {\n"
|
|
|
|
+ " var e\n"
|
|
|
|
+ " [e, toks] = parse_expression(toks)\n"
|
|
|
|
+ " r.push(e)\n"
|
|
|
|
+ " if !toks || toks[0][0] != ','\n"
|
|
|
|
+ " break\n"
|
|
|
|
+ " if toks[0][0] == \",\"\n"
|
|
|
|
+ " toks = toks[1:]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " if !toks || toks[0][0] != ']'\n"
|
|
|
|
+ " throw JSONError(\"missing ]\")\n"
|
|
|
|
+ " return r, toks[1:]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " func parse_object(toks) {\n"
|
|
|
|
+ " let r = {}\n"
|
|
|
|
+ " for {\n"
|
|
|
|
+ " var k, e\n"
|
|
|
|
+ " if !toks || toks[0][0] != \"string\"\n"
|
|
|
|
+ " throw JSONError(\"expected string\")\n"
|
|
|
|
+ " k = toks[0][1]\n"
|
|
|
|
+ " toks = toks[1:]\n"
|
|
|
|
+ " if !toks || toks[0][0] != \":\"\n"
|
|
|
|
+ " throw JSONError(\"expected :\")\n"
|
|
|
|
+ " toks = toks[1:]\n"
|
|
|
|
+ " [e, toks] = parse_expression(toks)\n"
|
|
|
|
+ " r[k] = e\n"
|
|
|
|
+ " if !toks || toks[0][0] != \",\"\n"
|
|
|
|
+ " break\n"
|
|
|
|
+ " if toks[0][0] == \",\"\n"
|
|
|
|
+ " toks = toks[1:]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " if !toks || toks[0][0] != \"}\"\n"
|
|
|
|
+ " throw JSONError(\"missing }\")\n"
|
|
|
|
+ " return r, toks[1:]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " func parse_expression(toks) {\n"
|
|
|
|
+ " if toks\n"
|
|
|
|
+ " switch toks[0][0] {\n"
|
|
|
|
+ " case \"{\":\n"
|
|
|
|
+ " return parse_object(toks[1:])\n"
|
|
|
|
+ " case \"[\":\n"
|
|
|
|
+ " return parse_array(toks[1:])\n"
|
|
|
|
+ " case \"name\":\n"
|
|
|
|
+ " switch toks[0][1] {\n"
|
|
|
|
+ " case \"true\":\n"
|
|
|
|
+ " return true, toks[1:]\n"
|
|
|
|
+ " case \"false\":\n"
|
|
|
|
+ " return false, toks[1:]\n"
|
|
|
|
+ " case \"null\":\n"
|
|
|
|
+ " return nil, toks[1:]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " throw JSONError(f\"illegal name: ${toks[0][1]}\")\n"
|
|
|
|
+ " case \"number\":\n"
|
|
|
|
+ " return num(toks[0][1]), toks[1:]\n"
|
|
|
|
+ " case \"string\":\n"
|
|
|
|
+ " return toks[0][1], toks[1:]\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " throw JSONError(\"expected expression\")\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " if !toks\n"
|
|
|
|
+ " throw JSONError(\"empty document\")\n"
|
|
|
|
+ " if toks[0][0] !in \"{[\"\n"
|
|
|
|
+ " throw JSONError(\"expected { or [\")\n"
|
|
|
|
+ " let [r, unconsumed] = parse_expression(toks)\n"
|
|
|
|
+ " if unconsumed\n"
|
|
|
|
+ " throw JSONError(\"unconsumed input\")\n"
|
|
|
|
+ " return r\n"
|
|
|
|
+ "}\n"
|
|
|
|
+ "func json_read(s)\n"
|
|
|
|
+ " return json_parse(json_tokenize(s))\n"
|
|
|
|
+ "func json_dump(d) {\n"
|
|
|
|
+ " func escape(s) {\n"
|
|
|
|
+ " var r = \"\"\n"
|
|
|
|
+ " \n"
|
|
|
|
+ " for var c of s {\n"
|
|
|
|
+ " if c == `\\`\n"
|
|
|
|
+ " r += `\\\\`\n"
|
|
|
|
+ " elif c == '\"'\n"
|
|
|
|
+ " r += `\\\"`\n"
|
|
|
|
+ " elif c == \"\\n\"\n"
|
|
|
|
+ " r += `\\n`\n"
|
|
|
|
+ " elif c == \"\\r\"\n"
|
|
|
|
+ " r += `\\r`\n"
|
|
|
|
+ " elif c == \"\\t\"\n"
|
|
|
|
+ " r += `\\t`\n"
|
|
|
|
+ " else r += c\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " return r\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " switch type(d) {\n"
|
|
|
|
+ " case \"nil\":\n"
|
|
|
|
+ " return \"null\"\n"
|
|
|
|
+ " case \"bool\":\n"
|
|
|
|
+ " return d? \"true\": \"false\"\n"
|
|
|
|
+ " case \"number\":\n"
|
|
|
|
+ " return str(d)\n"
|
|
|
|
+ " case \"string\":\n"
|
|
|
|
+ " return \"\\\"\" + escape(d) + \"\\\"\"\n"
|
|
|
|
+ " case \"list\":\n"
|
|
|
|
+ " var f = true\n"
|
|
|
|
+ " var buf = \"[\"\n"
|
|
|
|
+ " for var el of d {\n"
|
|
|
|
+ " if f\n"
|
|
|
|
+ " f = false\n"
|
|
|
|
+ " else\n"
|
|
|
|
+ " buf += \", \"\n"
|
|
|
|
+ " buf += json_dump(el) \n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " buf += \"]\"\n"
|
|
|
|
+ " return buf\n"
|
|
|
|
+ " case \"table\":\n"
|
|
|
|
+ " var f = true\n"
|
|
|
|
+ " var buf = \"{\"\n"
|
|
|
|
+ " for var [k, v] of enumerate(d) {\n"
|
|
|
|
+ " if f\n"
|
|
|
|
+ " f = false\n"
|
|
|
|
+ " else\n"
|
|
|
|
+ " buf += \", \"\n"
|
|
|
|
+ " buf += f`\"${escape(k)}\": ${json_dump(v)}`\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " buf += \"}\"\n"
|
|
|
|
+ " return buf\n"
|
|
|
|
+ " }\n"
|
|
|
|
+ " throw JSONError(f\"cannot serialize ${type(d)} into a JSON\")\n"
|
|
|
|
+ "}\n"},
|
|
|
|
|
|
{"utf8", "func utf8_chrlen(s) {\n"
|
|
{"utf8", "func utf8_chrlen(s) {\n"
|
|
" s = bytes(s)\n"
|
|
" s = bytes(s)\n"
|
|
@@ -3785,7 +3788,8 @@ const char *STD[][2] = {
|
|
"class ustr {\n"
|
|
"class ustr {\n"
|
|
" _ucs = nil\n"
|
|
" _ucs = nil\n"
|
|
" constructor (this, s=\"\") {\n"
|
|
" constructor (this, s=\"\") {\n"
|
|
- " if type(s) == \"list\" && all(map(func (x): type(x) == \"number\", s)) {\n"
|
|
|
|
|
|
+ " if type(s) == \"list\" && all(map(func (x): type(x) == "
|
|
|
|
+ "\"number\", s)) {\n"
|
|
" this._ucs = s\n"
|
|
" this._ucs = s\n"
|
|
" return\n"
|
|
" return\n"
|
|
" }\n"
|
|
" }\n"
|
|
@@ -4145,12 +4149,10 @@ char *unescape(char *s) {
|
|
}
|
|
}
|
|
|
|
|
|
void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
- table_t *ltab, list_t *lstk, list_t *sstk,
|
|
|
|
- list_t *lbl);
|
|
|
|
|
|
+ table_t *ltab, list_t *lstk, list_t *sstk, list_t *lbl);
|
|
|
|
|
|
int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
int require_once(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- char *path) {
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, char *path) {
|
|
char *source = NULL;
|
|
char *source = NULL;
|
|
|
|
|
|
for (size_t i = 0; STD[i][0]; i++) {
|
|
for (size_t i = 0; STD[i][0]; i++) {
|
|
@@ -4390,13 +4392,15 @@ node_t *mexpr_eval(node_t *n) {
|
|
return mexpr_eval(n->c);
|
|
return mexpr_eval(n->c);
|
|
}
|
|
}
|
|
|
|
|
|
- case N_TUPLE: case N_LIST: {
|
|
|
|
|
|
+ case N_TUPLE:
|
|
|
|
+ case N_LIST: {
|
|
list_t *l = list_new();
|
|
list_t *l = list_new();
|
|
|
|
|
|
for (size_t i = 0; i < n->l->length; i++) {
|
|
for (size_t i = 0; i < n->l->length; i++) {
|
|
node_t *a = mexpr_eval(n->l->data[i]);
|
|
node_t *a = mexpr_eval(n->l->data[i]);
|
|
|
|
|
|
- if (!IS_EXPR(a)) return NULL;
|
|
|
|
|
|
+ if (!IS_EXPR(a))
|
|
|
|
+ return NULL;
|
|
|
|
|
|
list_push(l, a);
|
|
list_push(l, a);
|
|
}
|
|
}
|
|
@@ -4896,7 +4900,8 @@ node_t *_expand_mvars(node_t *node, int expr, mvar_expand_err_t *err) {
|
|
|
|
|
|
return node;
|
|
return node;
|
|
} else if (node->tag == N_PROGRAM || node->tag == N_BLOCK ||
|
|
} else if (node->tag == N_PROGRAM || node->tag == N_BLOCK ||
|
|
- node->tag == N_LIST || node->tag == N_TUPLE || node->tag == N_COMMA) {
|
|
|
|
|
|
+ node->tag == N_LIST || node->tag == N_TUPLE ||
|
|
|
|
+ node->tag == N_COMMA) {
|
|
node = node_copy(node);
|
|
node = node_copy(node);
|
|
node->l = list_copy(node->l);
|
|
node->l = list_copy(node->l);
|
|
|
|
|
|
@@ -4958,7 +4963,8 @@ node_t *_expand_mvars(node_t *node, int expr, mvar_expand_err_t *err) {
|
|
}
|
|
}
|
|
|
|
|
|
return node;
|
|
return node;
|
|
- } else if (node->tag == N_INC || node->tag == N_DEC || node->tag == N_PINC || node->tag == N_PDEC) {
|
|
|
|
|
|
+ } else if (node->tag == N_INC || node->tag == N_DEC || node->tag == N_PINC ||
|
|
|
|
+ node->tag == N_PDEC) {
|
|
node = node_copy(node);
|
|
node = node_copy(node);
|
|
|
|
|
|
node->a = _expand_mvars(node->a, 1, err);
|
|
node->a = _expand_mvars(node->a, 1, err);
|
|
@@ -5003,8 +5009,8 @@ node_t *expand_mvars(node_t *node, node_t *_node, int expr) {
|
|
}
|
|
}
|
|
|
|
|
|
void compile_macro_call(buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
void compile_macro_call(buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
- table_t *ltab, list_t *lstk, list_t *sstk,
|
|
|
|
- list_t *lbl, node_t *node, int expr) {
|
|
|
|
|
|
+ table_t *ltab, list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
+ node_t *node, int expr) {
|
|
size_t argc = node->l->length;
|
|
size_t argc = node->l->length;
|
|
char *name = node->t->text;
|
|
char *name = node->t->text;
|
|
|
|
|
|
@@ -5060,8 +5066,7 @@ void compile_macro_call(buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
}
|
|
}
|
|
|
|
|
|
void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
- list_t *lstk, list_t *sstk, list_t *lbl,
|
|
|
|
- node_t *node) {
|
|
|
|
|
|
+ list_t *lstk, list_t *sstk, list_t *lbl, node_t *node) {
|
|
switch (node->tag) {
|
|
switch (node->tag) {
|
|
case N_TOPLEVEL:
|
|
case N_TOPLEVEL:
|
|
case N_PROGRAM:
|
|
case N_PROGRAM:
|
|
@@ -5238,8 +5243,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
EMIT("__%s%d(state)", PREFIX, gid);
|
|
EMIT("__%s%d(state)", PREFIX, gid);
|
|
} break;
|
|
} break;
|
|
|
|
|
|
- case T_USTRING:
|
|
|
|
- EMIT("qi_call(state, qi_get(state, \"ustr\"), qi_list_push(qi_list_make(), qi_make_string(state, \"%s\")))", node->t->text);
|
|
|
|
|
|
+ case T_USTRING:
|
|
|
|
+ EMIT("qi_call(state, qi_get(state, \"ustr\"), "
|
|
|
|
+ "qi_list_push(qi_list_make(), qi_make_string(state, \"%s\")))",
|
|
|
|
+ node->t->text);
|
|
break;
|
|
break;
|
|
|
|
|
|
case T_NAME: {
|
|
case T_NAME: {
|
|
@@ -5252,9 +5259,15 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
EMIT("qi_get(state, \"%s\")", name);
|
|
EMIT("qi_get(state, \"%s\")", name);
|
|
} break;
|
|
} break;
|
|
|
|
|
|
- case T_TRUE: EMIT("state->_true"); break;
|
|
|
|
- case T_FALSE: EMIT("state->_false"); break;
|
|
|
|
- case T_NIL: EMIT("state->nil"); break;
|
|
|
|
|
|
+ case T_TRUE:
|
|
|
|
+ EMIT("state->_true");
|
|
|
|
+ break;
|
|
|
|
+ case T_FALSE:
|
|
|
|
+ EMIT("state->_false");
|
|
|
|
+ break;
|
|
|
|
+ case T_NIL:
|
|
|
|
+ EMIT("state->nil");
|
|
|
|
+ break;
|
|
|
|
|
|
default:
|
|
default:
|
|
COMPILE_ERROR("not yet implemented");
|
|
COMPILE_ERROR("not yet implemented");
|
|
@@ -5441,7 +5454,8 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
ASSIGNIN(tbuf, (node_t *)node->a->l->data[i],
|
|
ASSIGNIN(tbuf, (node_t *)node->a->l->data[i],
|
|
buffer_fmt(tbuf,
|
|
buffer_fmt(tbuf,
|
|
"qi_index(state, %s, qi_make_number(state, %d))",
|
|
"qi_index(state, %s, qi_make_number(state, %d))",
|
|
- varname, i), false);
|
|
|
|
|
|
+ varname, i),
|
|
|
|
+ false);
|
|
buffer_fmt(tbuf, ";\n");
|
|
buffer_fmt(tbuf, ";\n");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -5697,7 +5711,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
|
|
|
CTXPUSH("scope");
|
|
CTXPUSH("scope");
|
|
EMIT("qi_new_scope(state);\n");
|
|
EMIT("qi_new_scope(state);\n");
|
|
-
|
|
|
|
|
|
+
|
|
if (node->t2) {
|
|
if (node->t2) {
|
|
if (table_get(ltab, node->t2->text))
|
|
if (table_get(ltab, node->t2->text))
|
|
COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
COMPILE_ERROR("redeclaration of loop label: '%s'", node->t2->text);
|
|
@@ -5884,7 +5898,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
pair = lstk->data[lstk->length - 1];
|
|
pair = lstk->data[lstk->length - 1];
|
|
gid = pair->data[0];
|
|
gid = pair->data[0];
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
size_t scopes_k = count_scopes(ctx, pair->data[1]);
|
|
size_t scopes_k = count_scopes(ctx, pair->data[1]);
|
|
|
|
|
|
for (size_t i = 0; i < scopes_k; i++) {
|
|
for (size_t i = 0; i < scopes_k; i++) {
|
|
@@ -5892,7 +5906,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
}
|
|
}
|
|
|
|
|
|
EMIT("goto __break%d;", gid);
|
|
EMIT("goto __break%d;", gid);
|
|
- } break;
|
|
|
|
|
|
+ } break;
|
|
|
|
|
|
case N_CONTINUE: {
|
|
case N_CONTINUE: {
|
|
if (!INCTX("for"))
|
|
if (!INCTX("for"))
|
|
@@ -5935,10 +5949,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
|
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
int_stack_t *pair = lstk->data[lstk->length - 1];
|
|
int_stack_t *pair = lstk->data[lstk->length - 1];
|
|
size_t gid = pair->data[0];
|
|
size_t gid = pair->data[0];
|
|
-
|
|
|
|
|
|
+
|
|
size_t scopes_k = count_scopes(ctx, pair->data[1]);
|
|
size_t scopes_k = count_scopes(ctx, pair->data[1]);
|
|
|
|
|
|
for (size_t i = 0; i < scopes_k; i++) {
|
|
for (size_t i = 0; i < scopes_k; i++) {
|
|
@@ -5946,7 +5960,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
}
|
|
}
|
|
|
|
|
|
EMIT("goto __continue%d;", gid);
|
|
EMIT("goto __continue%d;", gid);
|
|
- } break;
|
|
|
|
|
|
+ } break;
|
|
|
|
|
|
case N_DEFER: {
|
|
case N_DEFER: {
|
|
NEWGID();
|
|
NEWGID();
|
|
@@ -5986,15 +6000,15 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(";\n");
|
|
EMIT(";\n");
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
for (size_t i = 0; i < SCOPESK; i++)
|
|
for (size_t i = 0; i < SCOPESK; i++)
|
|
EMIT("qi_old_scope(state);\n");
|
|
EMIT("qi_old_scope(state);\n");
|
|
|
|
|
|
for (size_t i = 0; i < TRAPSK; i++)
|
|
for (size_t i = 0; i < TRAPSK; i++)
|
|
EMIT("qi_unset_trap(state, trap);\n");
|
|
EMIT("qi_unset_trap(state, trap);\n");
|
|
|
|
|
|
- EMIT("return %s;", varname? varname: "state->nil");
|
|
|
|
- } break;
|
|
|
|
|
|
+ EMIT("return %s;", varname ? varname : "state->nil");
|
|
|
|
+ } break;
|
|
|
|
|
|
case N_FUNCDEF:
|
|
case N_FUNCDEF:
|
|
break;
|
|
break;
|
|
@@ -6027,7 +6041,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
buffer_t *tbuf = buffer_new();
|
|
buffer_fmt(tbuf, "void __%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
buffer_fmt(tbuf, "void __%s%d(qi_state_t *state) {\n", PREFIX, gid);
|
|
- buffer_fmt(tbuf, "qi_call(state, qi_index(state, %s, qi_make_string(state, \"__leave\")), qi_list_push(qi_list_make(), %s));\n", varname, varname);
|
|
|
|
|
|
+ buffer_fmt(tbuf,
|
|
|
|
+ "qi_call(state, qi_index(state, %s, qi_make_string(state, "
|
|
|
|
+ "\"__leave\")), qi_list_push(qi_list_make(), %s));\n",
|
|
|
|
+ varname, varname);
|
|
buffer_fmt(tbuf, "}\n");
|
|
buffer_fmt(tbuf, "}\n");
|
|
|
|
|
|
buffer_appendb(gbuf, tbuf);
|
|
buffer_appendb(gbuf, tbuf);
|
|
@@ -6036,8 +6053,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
EMIT(";\n");
|
|
EMIT(";\n");
|
|
|
|
|
|
- EMIT("qi_call(state, qi_index(state, %s, qi_make_string(state, \"__enter\")), qi_list_push(qi_list_make(), %s));\n", varname, varname);
|
|
|
|
-
|
|
|
|
|
|
+ EMIT("qi_call(state, qi_index(state, %s, qi_make_string(state, "
|
|
|
|
+ "\"__enter\")), qi_list_push(qi_list_make(), %s));\n",
|
|
|
|
+ varname, varname);
|
|
|
|
+
|
|
CTXPUSH("scope");
|
|
CTXPUSH("scope");
|
|
EMIT("qi_new_scope(state);\n");
|
|
EMIT("qi_new_scope(state);\n");
|
|
|
|
|
|
@@ -6046,10 +6065,10 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
EMIT("qi_decl(state, \"%s\", %s);\n", node->t->text, varname);
|
|
EMIT("qi_decl(state, \"%s\", %s);\n", node->t->text, varname);
|
|
|
|
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
|
|
-
|
|
|
|
|
|
+
|
|
CTXPOP();
|
|
CTXPOP();
|
|
EMIT("qi_old_scope(state);\n");
|
|
EMIT("qi_old_scope(state);\n");
|
|
- } break;
|
|
|
|
|
|
+ } break;
|
|
|
|
|
|
case N_TRY:
|
|
case N_TRY:
|
|
EMIT("qi_try(state, {\n");
|
|
EMIT("qi_try(state, {\n");
|
|
@@ -6309,8 +6328,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
|
|
}
|
|
}
|
|
|
|
|
|
void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx,
|
|
- table_t *ltab, list_t *lstk, list_t *sstk,
|
|
|
|
- list_t *lbl) {
|
|
|
|
|
|
+ table_t *ltab, list_t *lstk, list_t *sstk, list_t *lbl) {
|
|
node_t *n = parse(source);
|
|
node_t *n = parse(source);
|
|
if (NEEDS_UTF8 && !is_required("utf8")) {
|
|
if (NEEDS_UTF8 && !is_required("utf8")) {
|
|
NEEDS_UTF8 = 0;
|
|
NEEDS_UTF8 = 0;
|