txlyre 1 день назад
Родитель
Сommit
b1cdbcf41b
1 измененных файлов с 56 добавлено и 2 удалено
  1. 56 2
      qic.c

+ 56 - 2
qic.c

@@ -281,6 +281,7 @@ typedef struct {
     T_VAR,
     T_LET,
     T_CONST,
+    T_UNPACK,
     T_IF,
     T_ELSE,
     T_ELIF,
@@ -582,6 +583,8 @@ token_t *next_token(char *source, size_t *pos) {
       return TK(LET);
     else if (strcmp(name, "const") == 0)
       return TK(CONST);
+    else if (strcmp(name, "unpack") == 0)
+      return TK(UNPACK);
     else if (strcmp(name, "if") == 0)
       return TK(IF);
     else if (strcmp(name, "else") == 0)
@@ -808,6 +811,9 @@ struct _node_t {
 
     N_VAR,
     N_LET,
+    N_VARUNPACK,
+    N_LETUNPACK,
+    N_UNPACK,
     N_CONST,
     N_IF,
     N_SWITCH,
@@ -1566,6 +1572,31 @@ node_t *parse_var(list_t *tokens, size_t *pos, int is_let) {
   return NODEH(VAR, h);
 }
 
+node_t *parse_unpack(list_t *tokens, size_t *pos, int tag) {
+  EXPECT(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(ASSIGN, "=");
+
+  node_t *a = parse_expr(tokens, pos);
+
+  if (tag == N_VARUNPACK)
+    return NODE1l(VARUNPACK, a, l);
+  else if (tag == N_LETUNPACK)
+    return NODE1l(LETUNPACK, a, l);
+
+  return NODE1l(UNPACK, a, l);
+}
+
 node_t *parse_func(list_t *tokens, size_t *pos, int is_expr) {
   token_t *name = NULL;
 
@@ -1666,10 +1697,18 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
     EXPECT(RCB, "}");
 
     return NODEL(BLOCK, stmts);
-  } else if (MATCH(VAR))
+  } else if (MATCH(VAR)) {
+    if (AT(LPAR))
+      return parse_unpack(tokens, pos, N_VARUNPACK);
+
     return parse_var(tokens, pos, 0);
-  else if (MATCH(LET))
+  } else if (MATCH(LET)) {
+    if (AT(LPAR))
+      return parse_unpack(tokens, pos, N_LETUNPACK);
+
     return parse_var(tokens, pos, 1);
+  } else if (MATCH(UNPACK))
+    return parse_unpack(tokens, pos, N_UNPACK);
   else if (MATCH(CONST)) {
     table_t *h = table_new();
 
@@ -2646,6 +2685,21 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, lis
       });
     break;
 
+    case N_UNPACK: case N_VARUNPACK: case N_LETUNPACK: {
+      NEWGID();
+
+      EMIT("qi_value_t *__temp%d = ", gid);
+      compile_node(gbuf, buf, ctx, lstk, lbl, node->a);
+      EMIT(";\n");
+
+      for (size_t i = 0; i < node->l->length; i++)
+        if (node->tag == N_UNPACK) {
+          EMIT("qi_set(state, false, \"%s\", qi_index(state, __temp%d, qi_make_number(state, %d)));\n", node->l->data[i], gid, i);
+        } else {
+          EMIT("%s(state, \"%s\", qi_index(state, __temp%d, qi_make_number(state, %d)));\n", node->tag == N_VARUNPACK? "qi_decl": "qi_decl_const", node->l->data[i], gid, i);
+        }
+    } break;
+
     case N_CONST:break;
 
     case N_IF: