txlyre 21 godzin temu
rodzic
commit
e2c714c060
1 zmienionych plików z 52 dodań i 3 usunięć
  1. 52 3
      qic.c

+ 52 - 3
qic.c

@@ -820,6 +820,8 @@ struct _node_t {
     N_FOR,
     N_FOROF,
     N_FOROFVAR,
+    N_FOROFUNPACK,
+    N_FOROFVARUNPACK,
     N_BREAK,
     N_CONTINUE,
     N_FUNCDEF,
@@ -1787,6 +1789,25 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
     node_t *c = NULL;
 
     if (!AT(LCB) && !AT(COLON) && !CLIFF) {
+      if (MATCH(LPAR)) {
+        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(RPAR, ")");
+        EXPECT(OF, "of");
+
+        a = parse_expr(tokens, pos);
+        b = BLOCK();
+
+        return NODE2l(FOROFUNPACK, a, b, l);
+      }
+
       if (AT(NAME) && ATP(OF, 1)) {
         token_t *t = tokens->data[(*pos)++];
 
@@ -1799,6 +1820,25 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
       }
 
       if (MATCH(VAR)) {
+        if (MATCH(LPAR)) {
+          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(RPAR, ")");
+          EXPECT(OF, "of");
+
+          a = parse_expr(tokens, pos);
+          b = BLOCK();
+
+          return NODE2l(FOROFVARUNPACK, a, b, l);
+        }
+
         if (AT(NAME) && ATP(OF, 1)) {
           token_t *t = tokens->data[(*pos)++];
 
@@ -2793,7 +2833,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
       EMIT("__break%d:;\n", gid);
       } break;
 
-    case N_FOROF: case N_FOROFVAR: {
+    case N_FOROF: case N_FOROFVAR: case N_FOROFUNPACK: case N_FOROFVARUNPACK: {
       NEWGID();
       char *varname = tempvar();
 
@@ -2801,11 +2841,20 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
       compile_node(gbuf, buf, ctx, lstk, lbl, node->a);
       EMIT(");\n");
 
-      if (node->tag == N_FOROFVAR)
+      if (node->tag == N_FOROFVAR) {
         EMIT("qi_decl(state, \"%s\", state->nil);\n", node->t->text);
+      } else if (node->tag == N_FOROFVARUNPACK) {
+        for (size_t i = 0; i < node->l->length; i++)
+          EMIT("qi_decl(state, \"%s\", state->nil);\n", node->l->data[i]);
+      }
 
       EMIT("for (qi_size_t length = _qi_length(state, %s), i = 0; i < length; i++) {\n", varname);
-      EMIT("qi_set(state, false, \"%s\", qi_index(state, %s, qi_make_number(state, i)));\n", node->t->text, varname);
+
+      if (node->tag == N_FOROFUNPACK || node->tag == N_FOROFVARUNPACK) {
+        for (size_t i = 0; i < node->l->length; i++)
+          EMIT("qi_set(state, false, \"%s\", qi_index(state, qi_index(state, %s, qi_make_number(state, i)), qi_make_number(state, %d)));\n", node->l->data[i], varname, i);
+      } else 
+        EMIT("qi_set(state, false, \"%s\", qi_index(state, %s, qi_make_number(state, i)));\n", node->t->text, varname);
 
       LPUSH(gid);
       CTXPUSH("for");