|
@@ -571,6 +571,10 @@ token_t *next_token(char *source, size_t *pos) {
|
|
|
return TK(COMMA);
|
|
|
else if (source[*pos] == '.' && ++(*pos))
|
|
|
return TK(DOT);
|
|
|
+ else if (source[*pos] == '<' && ++(*pos))
|
|
|
+ return TK(LT);
|
|
|
+ else if (source[*pos] == '>' && ++(*pos))
|
|
|
+ return TK(GT);
|
|
|
|
|
|
LEX_ERROR("unexpected input")
|
|
|
}
|
|
@@ -625,6 +629,8 @@ struct _node_t {
|
|
|
N_ASSIGN_ADD,
|
|
|
|
|
|
N_EQUALS,
|
|
|
+ N_LT,
|
|
|
+ N_GT,
|
|
|
|
|
|
N_INC,
|
|
|
N_DEC,
|
|
@@ -1019,6 +1025,24 @@ node_t *parse_shift(list_t *tokens, size_t *pos) {
|
|
|
node_t *parse_relation(list_t *tokens, size_t *pos) {
|
|
|
node_t *a = parse_shift(tokens, pos);
|
|
|
|
|
|
+ do {
|
|
|
+ if (MATCH(LT)) {
|
|
|
+ node_t *b = parse_shift(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(LT, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ } else if (MATCH(GT)) {
|
|
|
+ node_t *b = parse_shift(tokens, pos);
|
|
|
+
|
|
|
+ a = NODE2(GT, a, b);
|
|
|
+
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ } while (1);
|
|
|
+
|
|
|
return a;
|
|
|
}
|
|
|
|
|
@@ -1447,7 +1471,24 @@ int in_context(list_t *ctx, char *s) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+size_t scopes_count(list_t *ctx) {
|
|
|
+ if (!ctx->length)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ size_t k = 0;
|
|
|
+
|
|
|
+ for (ssize_t i = ctx->length - 1; i >= 0; i--) {
|
|
|
+ if (strcmp(ctx->data[i], "gap") == 0)
|
|
|
+ break;
|
|
|
+ else if (strcmp(ctx->data[i], "scope") == 0)
|
|
|
+ k++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return k;
|
|
|
+}
|
|
|
+
|
|
|
#define INCTX(s) (in_context(ctx, (s)))
|
|
|
+#define SCOPESK (scopes_count(ctx))
|
|
|
|
|
|
#define LPUSH(i) stack_push(lstk, (i))
|
|
|
#define LPOP() stack_pop(lstk)
|
|
@@ -1474,11 +1515,11 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
if (pair->data[1]) {
|
|
|
optargc++;
|
|
|
|
|
|
- buffer_fmt(tbuf, "qi_set(state, false, false, \"%s\", pargc >= %d? qi_list_index(pargs, %d): ", entry.key, argc+1, argc);
|
|
|
+ buffer_fmt(tbuf, "qi_set(state, false, \"%s\", pargc >= %d? qi_list_index(pargs, %d): ", entry.key, argc+1, argc);
|
|
|
compile_node(gbuf, tbuf, ctx, lstk, pair->data[1]);
|
|
|
buffer_fmt(tbuf, ");\n");
|
|
|
} else
|
|
|
- buffer_fmt(tbuf, "qi_set(state, false, false, \"%s\", qi_list_index(pargs, %d));\n", entry.key, argc);
|
|
|
+ buffer_fmt(tbuf, "qi_set(state, false, \"%s\", qi_list_index(pargs, %d));\n", entry.key, argc);
|
|
|
|
|
|
argc++;
|
|
|
});
|
|
@@ -1506,7 +1547,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- EMIT("qi_set(state, false, false, \"%s\", ", node->t->text);
|
|
|
+ EMIT("qi_set(state, false, \"%s\", ", node->t->text);
|
|
|
buffer_appendb(buf, tbuf);
|
|
|
EMIT(");");
|
|
|
}
|
|
@@ -1552,9 +1593,11 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
break;
|
|
|
|
|
|
case N_BLOCK:
|
|
|
+ CTXPUSH("scope");
|
|
|
EMIT("qi_new_scope(state);\n");
|
|
|
compile_block(gbuf, buf, ctx, lstk, node->l);
|
|
|
EMIT("qi_old_scope(state);");
|
|
|
+ CTXPOP();
|
|
|
break;
|
|
|
|
|
|
case N_LITERAL:
|
|
@@ -1639,15 +1682,19 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
case N_IF:
|
|
|
EMIT("if (_qi_truthy(state, ");
|
|
|
compile_node(gbuf, buf, ctx, lstk, node->a);
|
|
|
- EMIT(") {\n");
|
|
|
- EMIT("qi_new_subscope(state);\n");
|
|
|
+ EMIT(")) {\n");
|
|
|
+ CTXPUSH("scope");
|
|
|
+ EMIT("qi_new_scope(state);\n");
|
|
|
compile_node(gbuf, buf, ctx, lstk, node->b);
|
|
|
EMIT("qi_old_scope(state);\n");
|
|
|
+ CTXPOP();
|
|
|
if (node->c) {
|
|
|
EMIT("} else {\n");
|
|
|
- EMIT("qi_new_subscope(state);\n");
|
|
|
+ CTXPUSH("scope");
|
|
|
+ EMIT("qi_new_scope(state);\n");
|
|
|
compile_node(gbuf, buf, ctx, lstk, node->c);
|
|
|
EMIT("qi_old_scope(state);\n");
|
|
|
+ CTXPOP();
|
|
|
}
|
|
|
EMIT("}");
|
|
|
break;
|
|
@@ -1655,7 +1702,8 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
case N_FOR: {
|
|
|
NEWGID();
|
|
|
|
|
|
- EMIT("qi_new_subscope(state);\n");
|
|
|
+ CTXPUSH("scope");
|
|
|
+ EMIT("qi_new_scope(state);\n");
|
|
|
|
|
|
if (!node->a) {
|
|
|
EMIT("for (;;) {\n");
|
|
@@ -1686,6 +1734,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
EMIT("__break%d:;\n", gid);
|
|
|
|
|
|
EMIT("qi_old_scope(state);\n");
|
|
|
+ CTXPOP();
|
|
|
} break;
|
|
|
|
|
|
case N_BREAK:
|
|
@@ -1725,6 +1774,9 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
if (!INCTX("func"))
|
|
|
COMPILE_ERROR("return outside of a function");
|
|
|
|
|
|
+ for (size_t i = 0; i < SCOPESK; i++)
|
|
|
+ EMIT("qi_old_scope(state);\n");
|
|
|
+
|
|
|
EMIT("return ");
|
|
|
|
|
|
if (node->a)
|
|
@@ -1754,6 +1806,14 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
|
|
|
BINOP("equals");
|
|
|
break;
|
|
|
|
|
|
+ case N_LT:
|
|
|
+ BINOP("lt");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case N_GT:
|
|
|
+ BINOP("gt");
|
|
|
+ break;
|
|
|
+
|
|
|
case N_ADD:
|
|
|
BINOP("add");
|
|
|
break;
|