txlyre 2 weeks ago
parent
commit
16f2890b2b
1 changed files with 44 additions and 2 deletions
  1. 44 2
      qic.c

+ 44 - 2
qic.c

@@ -1097,6 +1097,9 @@ struct _node_t {
     N_UNARY_PLUS,
     N_UNARY_PLUS,
     N_BNOT,
     N_BNOT,
 
 
+    N_REFERENCE,
+    N_DEREFERENCE,
+
     N_LITERAL,
     N_LITERAL,
     N_LIST,
     N_LIST,
     N_LISTGEN,
     N_LISTGEN,
@@ -1566,7 +1569,11 @@ char *unescape(char *s);
 node_t *parse_primary(list_t *tokens, size_t *pos) {
 node_t *parse_primary(list_t *tokens, size_t *pos) {
   if (MATCH(MVAR))
   if (MATCH(MVAR))
     return NODET(MVAR, tokens->data[(*pos) - 1]);
     return NODET(MVAR, tokens->data[(*pos) - 1]);
-  else if (MATCH(CATCH)) {
+  else if (AT(AND) && ATP(NAME, 1)) {
+    MATCH(AND);
+
+    return NODET(REFERENCE, tokens->data[(*pos)++]);
+  } else if (MATCH(CATCH)) {
     node_t *a = parse_expr(tokens, pos);
     node_t *a = parse_expr(tokens, pos);
 
 
     return NODE1(CATCH, a);
     return NODE1(CATCH, a);
@@ -1909,6 +1916,10 @@ node_t *parse_unary(list_t *tokens, size_t *pos) {
     node_t *a = parse_unary(tokens, pos);
     node_t *a = parse_unary(tokens, pos);
 
 
     return NODE1(BNOT, a);
     return NODE1(BNOT, a);
+  } else if (MATCH(RAISE)) {
+    node_t *a = parse_unary(tokens, pos);
+
+    return NODE1(DEREFERENCE, a);
   } else if (MATCH(PLUSPLUS)) {
   } else if (MATCH(PLUSPLUS)) {
     node_t *a = parse_postfix(tokens, pos);
     node_t *a = parse_postfix(tokens, pos);
 
 
@@ -2129,10 +2140,16 @@ node_t *parse_bitand(list_t *tokens, size_t *pos) {
 node_t *parse_bitxor(list_t *tokens, size_t *pos) {
 node_t *parse_bitxor(list_t *tokens, size_t *pos) {
   node_t *a = parse_bitand(tokens, pos);
   node_t *a = parse_bitand(tokens, pos);
 
 
+  if (CLIFF)
+    return a;
+
   while (MATCH(RAISE)) {
   while (MATCH(RAISE)) {
     node_t *b = parse_bitand(tokens, pos);
     node_t *b = parse_bitand(tokens, pos);
 
 
     a = NODE2(XOR, a, b);
     a = NODE2(XOR, a, b);
+
+    if (CLIFF)
+      break;
   }
   }
 
 
   return a;
   return a;
@@ -2422,12 +2439,20 @@ node_t *parse_func(list_t *tokens, size_t *pos, int is_expr) {
     captured = table_new();
     captured = table_new();
 
 
     do {
     do {
+      int is_ref = 0;
+
+      if (MATCH(AND))
+        is_ref = 1;
+
       if (!AT(NAME))
       if (!AT(NAME))
         PARSE_ERROR("expected identifier");
         PARSE_ERROR("expected identifier");
 
 
       token_t *name = tokens->data[(*pos)++];
       token_t *name = tokens->data[(*pos)++];
 
 
-      table_set(captured, name->text, NODET(LITERAL, name));
+      if (is_ref)
+        table_set(captured, name->text, NODET(REFERENCE, name));
+      else
+        table_set(captured, name->text, NODET(LITERAL, name));
     } while (MATCH(COMMA));
     } while (MATCH(COMMA));
 
 
     EXPECT(RPAR, ")");
     EXPECT(RPAR, ")");
@@ -3274,6 +3299,12 @@ node_t *parse(char *source) {
       buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text);    \
       buffer_fmt(buf, ", qi_make_string(state, \"%s\"), ", (lhs)->t->text);    \
       rhs;                                                                     \
       rhs;                                                                     \
       buffer_fmt(buf, ")");                                                    \
       buffer_fmt(buf, ")");                                                    \
+    } else if ((lhs)->tag == N_DEREFERENCE) {                                  \
+      buffer_fmt(buf, "qi_set_ref(state, " #prefix ", ");                      \
+      compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, (lhs)->a);           \
+      buffer_fmt(buf, ", ");                                                   \
+      rhs;                                                                     \
+      buffer_fmt(buf, ")");                                                    \
     } else                                                                     \
     } else                                                                     \
       COMPILE_ERROR("illegal assignment left-hand side");                      \
       COMPILE_ERROR("illegal assignment left-hand side");                      \
   }
   }
@@ -6760,9 +6791,20 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab,
     UNOP("bnot");
     UNOP("bnot");
     break;
     break;
 
 
+  case N_REFERENCE:
+    EMIT("qi_make_ref(state, \"%s\")", node->t->text);
+    break;
+
+  case N_DEREFERENCE:
+    EMIT("qi_deref(state, ");
+    compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
+    EMIT(")");
+    break;
+
   case N_MACRO_CALL:
   case N_MACRO_CALL:
     compile_macro_call(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, 1);
     compile_macro_call(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node, 1);
     break;
     break;
+
   case N_MVAR:
   case N_MVAR:
     COMPILE_ERROR("macro variable outside of a macro");
     COMPILE_ERROR("macro variable outside of a macro");