|
@@ -766,6 +766,7 @@ struct _node_t {
|
|
|
|
|
|
N_LITERAL,
|
|
|
N_LIST,
|
|
|
+ N_LISTGEN,
|
|
|
N_TUPLE,
|
|
|
N_NILTUPLE,
|
|
|
N_TABLE,
|
|
@@ -847,6 +848,8 @@ struct _node_t {
|
|
|
|
|
|
N_LOGOR,
|
|
|
N_LOGAND,
|
|
|
+
|
|
|
+ N_BUFFER
|
|
|
} tag;
|
|
|
|
|
|
struct _node_t *a;
|
|
@@ -862,6 +865,8 @@ struct _node_t {
|
|
|
token_t *t;
|
|
|
token_t *t2;
|
|
|
|
|
|
+ buffer_t *buf;
|
|
|
+
|
|
|
size_t fi;
|
|
|
size_t pos;
|
|
|
};
|
|
@@ -1043,6 +1048,15 @@ node_t *nodef(int tag, token_t *name, table_t *params, table_t *captured, node_t
|
|
|
|
|
|
#define NODEF(n, a, b, c, d) (node_pos(nodef(N_##n, (a), (b), (c), (d)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
|
|
|
|
|
|
+node_t *nodeb(buffer_t *buf) {
|
|
|
+ node_t *node = malloc(sizeof(node_t));
|
|
|
+
|
|
|
+ node->tag = N_BUFFER;
|
|
|
+ node->buf = buf;
|
|
|
+
|
|
|
+ return node;
|
|
|
+}
|
|
|
+
|
|
|
#define LABELLOOP(n)\
|
|
|
node_t *ln = (n);\
|
|
|
ln->t2 = label;
|
|
@@ -1102,8 +1116,40 @@ node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
|
} else if (MATCH(LSB)) {
|
|
|
list_t *a = parse_sequence(tokens, pos, T_RSB);
|
|
|
|
|
|
+ node_t *loop = NULL;
|
|
|
+
|
|
|
+ if (MATCH(FOR)) {
|
|
|
+ if (MATCH(LSB)) {
|
|
|
+ list_t *l = list_new();
|
|
|
+
|
|
|
+ do {
|
|
|
+ if(!AT(NAME))
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
+
|
|
|
+ list_push(l, ((token_t *)tokens->data[(*pos)++])->text);
|
|
|
+ } while (MATCH(COMMA));
|
|
|
+
|
|
|
+ EXPECT(RSB, "]");
|
|
|
+ EXPECT(OF, "of");
|
|
|
+
|
|
|
+ loop = NODE2l(FOROFUNPACK, parse_expr(tokens, pos), NODEL(LIST, a), l);
|
|
|
+ } else {
|
|
|
+ if(!AT(NAME))
|
|
|
+ PARSE_ERROR("expected identifier");
|
|
|
+
|
|
|
+ token_t *t = tokens->data[(*pos)++];
|
|
|
+
|
|
|
+ EXPECT(OF, "of");
|
|
|
+
|
|
|
+ loop = NODE2t(FOROF, parse_expr(tokens, pos), NODEL(LIST, a), t);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
EXPECT(RSB, "]");
|
|
|
|
|
|
+ if (loop)
|
|
|
+ return NODE1(LISTGEN, loop);
|
|
|
+
|
|
|
return NODEL(LIST, a);
|
|
|
} else if (MATCH(LCB)) {
|
|
|
table_t *table = table_new();
|
|
@@ -2449,7 +2495,7 @@ const char *STD[][2] = {
|
|
|
"func head(l): return l[0]\n"
|
|
|
"func tail(l): return slice(l, 1)\n"
|
|
|
"func die(msg, c=1) {\n"
|
|
|
- " println(msg)\n"
|
|
|
+ " fputs(STDERR, str(msg) + \"\\n\")\n"
|
|
|
" exit(c)\n"
|
|
|
"}\n"
|
|
|
"func min(x, y): x < y? x: y\n"
|
|
@@ -3360,6 +3406,33 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
EMIT(")");
|
|
|
break;
|
|
|
|
|
|
+ case N_LISTGEN: {
|
|
|
+ NEWGID();
|
|
|
+
|
|
|
+ buffer_t *tbuf = buffer_new();
|
|
|
+
|
|
|
+ buffer_fmt(tbuf, "qi_value_t *__listgen%d(qi_state_t *state) {\n", gid);
|
|
|
+ buffer_fmt(tbuf, "qi_list_t *list = qi_list_make();\n");
|
|
|
+
|
|
|
+ buffer_t *bbuf = buffer_new();
|
|
|
+
|
|
|
+ for (size_t i = 0; i < node->a->b->l->length; i++) {
|
|
|
+ buffer_fmt(bbuf, "qi_list_push(list, ");
|
|
|
+ compile_node(gbuf, bbuf, ctx, ltab, lstk, sstk, lbl, node->a->b->l->data[i]);
|
|
|
+ buffer_fmt(bbuf, ");\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ node->a->b = nodeb(bbuf);
|
|
|
+
|
|
|
+ compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
|
|
|
+
|
|
|
+ buffer_fmt(tbuf, "return qi_make_list(state, list);\n}\n");
|
|
|
+
|
|
|
+ buffer_appendb(gbuf, tbuf);
|
|
|
+
|
|
|
+ EMIT("__listgen%d(state)", gid);
|
|
|
+ } break;
|
|
|
+
|
|
|
case N_TUPLE:
|
|
|
EMIT("qi_make_tuple(state, ");
|
|
|
compile_list(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l);
|
|
@@ -3950,6 +4023,8 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
case N_INLINE: EMIT("%s;", unescape(node->t->text)); break;
|
|
|
case N_HEADER: buffer_fmt(HBUF, "%s\n", unescape(node->t->text)); break;
|
|
|
|
|
|
+ case N_BUFFER: buffer_appendb(buf, node->buf); break;
|
|
|
+
|
|
|
default:
|
|
|
COMPILE_ERROR("not yet implemented");
|
|
|
}
|