txlyre 1 dia atrás
pai
commit
04a7733a2e
1 arquivos alterados com 76 adições e 1 exclusões
  1. 76 1
      qic.c

+ 76 - 1
qic.c

@@ -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");
   }