txlyre 1 month ago
parent
commit
88d9b57bde
1 changed files with 57 additions and 9 deletions
  1. 57 9
      qic.c

+ 57 - 9
qic.c

@@ -300,6 +300,7 @@ typedef struct {
     T_REQUIRE,
     T_TRY,
     T_CATCH,
+    T_FINALLY,
     T_THROW,
     T_GOTO,
     T_CLASS,
@@ -634,6 +635,8 @@ token_t *next_token(char *source, size_t *pos) {
       return TK(TRY);
     else if (strcmp(name, "catch") == 0)
       return TK(CATCH);
+    else if (strcmp(name, "finally") == 0)
+      return TK(FINALLY);
     else if (strcmp(name, "throw") == 0)
       return TK(THROW);
     else if (strcmp(name, "goto") == 0)
@@ -1042,6 +1045,20 @@ node_t *node3(int tag, node_t *a, node_t *b, node_t *c) {
 
 #define NODE3(n, a, b, c) (node_pos(node3(N_##n, (a), (b), (c)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
+node_t *node3t(int tag, node_t *a, node_t *b, node_t *c, token_t *t) {
+  node_t *node = malloc(sizeof(node_t));
+
+  node->tag = tag;
+  node->a = a;
+  node->b = b;
+  node->c = c;
+  node->t = t;
+
+  return node;
+}
+
+#define NODE3t(n, a, b, c, d) (node_pos(node3t(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 *node4(int tag, node_t *a, node_t *b, node_t *c, node_t *d) {
   node_t *node = malloc(sizeof(node_t));
 
@@ -2038,8 +2055,12 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
     }
 
     node_t *b = BLOCK();
+    node_t *c = NULL;
 
-    return NODE2t(TRY, a, b, t);
+    if (MATCH(FINALLY))
+      c = BLOCK();
+
+    return NODE3t(TRY, a, b, c, t);
   } else if (MATCH(THROW)) {
     node_t *a = NULL;
 
@@ -2417,7 +2438,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
     });
   }
 
-  compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
+  compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
 
   CTXPOP();
   CTXPOP();
@@ -4044,12 +4065,11 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
 
       LBPUSH();
       CTXPUSH("gap");
-      compile_node(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->a);
+      compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
       CTXPOP();
       LBPOP();
 
-      buffer_fmt(tbuf, "\n");
-      buffer_fmt(tbuf, "}\n");
+      buffer_fmt(tbuf, "\n}\n");
 
       buffer_appendb(gbuf, tbuf);
 
@@ -4081,14 +4101,42 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
 
     case N_TRY:
       EMIT("qi_try(state, {\n");
-      compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
+      LBPUSH();
+      CTXPUSH("gap");
+      CTXPUSH("trap");
+      compile_node(gbuf, buf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
+      CTXPOP();
+      CTXPOP();
+      LBPOP();
       EMIT("}, {\n");
       if (node->t)
         EMIT("qi_decl(state, \"%s\", trap->value);\n", node->t->text);
-      CTXPUSH("trap");
-      compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->b);
+      LBPUSH();
+      CTXPUSH("gap");
+      compile_node(gbuf, buf, ctx, table_new(), stack_new(), stack_new(), lbl, node->b);
       CTXPOP();
-      EMIT("}, NULL);\n");
+      LBPOP();
+
+      if (node->c) {
+        NEWGID();
+
+        buffer_t *tbuf = buffer_new();
+
+        buffer_fmt(tbuf, "void __finally%d(qi_state_t *state) {\n", gid);
+        LBPUSH();
+        CTXPUSH("gap");
+        compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->c);
+        CTXPOP();
+        LBPOP();
+
+        buffer_fmt(tbuf, "\n}\n");
+
+        buffer_appendb(gbuf, tbuf);
+
+        EMIT("}, __finally%d);\n", gid);
+      } else {
+        EMIT("}, NULL);\n");
+      }
       break;
 
     case N_THROW: