txlyre vor 1 Monat
Ursprung
Commit
c415b28d94
1 geänderte Dateien mit 171 neuen und 34 gelöschten Zeilen
  1. 171 34
      qic.c

+ 171 - 34
qic.c

@@ -290,6 +290,9 @@ typedef struct {
     T_RETURN,
     T_DEFER,
     T_REQUIRE,
+    T_TRY,
+    T_CATCH,
+    T_THROW,
 
     T_LPAR,
     T_RPAR,
@@ -305,6 +308,7 @@ typedef struct {
     T_STARSTAR,
     T_PLUSPLUS,
     T_MINUSMINUS,
+    T_SLASHSLASH,
 
     T_PLUS,
     T_MINUS,
@@ -537,6 +541,12 @@ token_t *next_token(char *source, size_t *pos) {
       return TK(PASS);
     else if (strcmp(name, "require") == 0)
       return TK(REQUIRE);
+    else if (strcmp(name, "try") == 0)
+      return TK(TRY);
+    else if (strcmp(name, "catch") == 0)
+      return TK(CATCH);
+    else if (strcmp(name, "throw") == 0)
+      return TK(THROW);
 
     return token(T_NAME, name);
   } else if (strncmp(&source[*pos], "==", 2) == 0 && ++(*pos) && ++(*pos))
@@ -551,6 +561,10 @@ token_t *next_token(char *source, size_t *pos) {
     return TK(PLUSPLUS);
   else if (strncmp(&source[*pos], "--", 2) == 0 && ++(*pos) && ++(*pos))
     return TK(MINUSMINUS);
+  else if (strncmp(&source[*pos], "//", 2) == 0 && ++(*pos) && ++(*pos))
+    return TK(SLASHSLASH);
+  else if (strncmp(&source[*pos], "**", 2) == 0 && ++(*pos) && ++(*pos))
+    return TK(STARSTAR);
   else if (source[*pos] == '(' && ++(*pos))
     return TK(LPAR);
   else if (source[*pos] == ')' && ++(*pos))
@@ -604,10 +618,10 @@ list_t *tokenize(char *source) {
     tok->fi = FILES->length-1;
     tok->pos = tok_pos;
 
+    list_push(toks, tok);
+
     if (tok->tag == T_EOF)
       break;
-
-    list_push(toks, tok);
   } while (1);
 
   return toks;
@@ -636,6 +650,8 @@ struct _node_t {
     N_SUB,
     N_MUL,
     N_DIV,
+    N_IDIV,
+    N_POW,
 
     N_ASSIGN,
     N_ASSIGN_ADD,
@@ -657,6 +673,8 @@ struct _node_t {
     N_DEFER,
     N_PASS,
     N_REQUIRE,
+    N_TRY,
+    N_THROW,
 
     N_IFEXPR,
     N_FUNCEXPR,
@@ -698,7 +716,7 @@ node_t *nodet(int tag, token_t *t) {
   return node;
 }
 
-#define NODET(n, a) (node_pos(nodet(N_##n, (a)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODET(n, a) (node_pos(nodet(N_##n, (a)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *nodel(int tag, list_t *l) {
   node_t *node = malloc(sizeof(node_t));
@@ -709,7 +727,7 @@ node_t *nodel(int tag, list_t *l) {
   return node;
 }
 
-#define NODEL(n, a) (node_pos(nodel(N_##n, (a)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODEL(n, a) (node_pos(nodel(N_##n, (a)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *nodeh(int tag, table_t *h) {
   node_t *node = malloc(sizeof(node_t));
@@ -720,7 +738,7 @@ node_t *nodeh(int tag, table_t *h) {
   return node;
 }
 
-#define NODEH(n, a) (node_pos(nodeh(N_##n, (a)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODEH(n, a) (node_pos(nodeh(N_##n, (a)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *node0(int tag) {
   node_t *node = malloc(sizeof(node_t));
@@ -730,7 +748,7 @@ node_t *node0(int tag) {
   return node;
 }
 
-#define NODE0(n) (node_pos(node0(N_##n), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODE0(n) (node_pos(node0(N_##n), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *node1(int tag, node_t *a) {
   node_t *node = malloc(sizeof(node_t));
@@ -741,7 +759,7 @@ node_t *node1(int tag, node_t *a) {
   return node;
 }
 
-#define NODE1(n, a) (node_pos(node1(N_##n, (a)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODE1(n, a) (node_pos(node1(N_##n, (a)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *node1l(int tag, node_t *a, list_t *l) {
   node_t *node = malloc(sizeof(node_t));
@@ -753,7 +771,7 @@ node_t *node1l(int tag, node_t *a, list_t *l) {
   return node;
 }
 
-#define NODE1l(n, a, l) (node_pos(node1l(N_##n, (a), (l)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODE1l(n, a, l) (node_pos(node1l(N_##n, (a), (l)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *node1t(int tag, node_t *a, token_t *t) {
   node_t *node = malloc(sizeof(node_t));
@@ -765,7 +783,7 @@ node_t *node1t(int tag, node_t *a, token_t *t) {
   return node;
 }
 
-#define NODE1t(n, a, t) (node_pos(node1t(N_##n, (a), (t)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODE1t(n, a, t) (node_pos(node1t(N_##n, (a), (t)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
 
 node_t *node2(int tag, node_t *a, node_t *b) {
   node_t *node = malloc(sizeof(node_t));
@@ -777,7 +795,20 @@ node_t *node2(int tag, node_t *a, node_t *b) {
   return node;
 }
 
-#define NODE2(n, a, b) (node_pos(node2(N_##n, (a), (b)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODE2(n, a, b) (node_pos(node2(N_##n, (a), (b)), ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->fi, ((token_t *)tokens->data[(*pos)>0?(*pos)-1:(*pos)])->pos))
+
+node_t *node2t(int tag, node_t *a, node_t *b, token_t *t) {
+  node_t *node = malloc(sizeof(node_t));
+
+  node->tag = tag;
+  node->a = a;
+  node->b = b;
+  node->t = t;
+
+  return node;
+}
+
+#define NODE2t(n, a, b, c) (node_pos(node2t(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 *node3(int tag, node_t *a, node_t *b, node_t *c) {
   node_t *node = malloc(sizeof(node_t));
@@ -790,7 +821,7 @@ node_t *node3(int tag, node_t *a, node_t *b, node_t *c) {
   return node;
 }
 
-#define NODE3(n, a, b, c) (node_pos(node3(N_##n, (a), (b), (c)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#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 *node4(int tag, node_t *a, node_t *b, node_t *c, node_t *d) {
   node_t *node = malloc(sizeof(node_t));
@@ -804,7 +835,7 @@ node_t *node4(int tag, node_t *a, node_t *b, node_t *c, node_t *d) {
   return node;
 }
 
-#define NODE4(n, a, b, c, d) (node_pos(node4(N_##n, (a), (b), (c), (d)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#define NODE4(n, a, b, c, d) (node_pos(node4(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 *nodef(int tag, token_t *name, table_t *params, table_t *captured, node_t *body) {
   node_t *node = malloc(sizeof(node_t));
@@ -818,7 +849,7 @@ node_t *nodef(int tag, token_t *name, table_t *params, table_t *captured, node_t
   return node;
 }
 
-#define NODEF(n, a, b, c, d) (node_pos(nodef(N_##n, (a), (b), (c), (d)), ((token_t *)tokens->data[(*pos)-1])->fi, ((token_t *)tokens->data[(*pos)-1])->pos))
+#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))
 
 #define AT(tk) (*pos < tokens->length && ((token_t *)tokens->data[*pos])->tag == T_##tk)
 #define MATCH(tk) (AT(tk) && ++(*pos))
@@ -978,6 +1009,18 @@ node_t *parse_unary(list_t *tokens, size_t *pos) {
 node_t *parse_pow(list_t *tokens, size_t *pos) {
   node_t *a = parse_unary(tokens, pos);
 
+  do {
+    if (MATCH(STARSTAR)) {
+      node_t *b = parse_unary(tokens, pos);
+
+      a = NODE2(POW, a, b);
+
+      continue;
+    }
+
+    break;
+  } while (1);
+
   return a;
 }
 
@@ -996,6 +1039,12 @@ node_t *parse_mul(list_t *tokens, size_t *pos) {
 
       a = NODE2(DIV, a, b);
 
+      continue;
+    } else if (MATCH(SLASHSLASH)) {
+      node_t *b = parse_pow(tokens, pos);
+
+      a = NODE2(IDIV, a, b);
+
       continue;
     }
 
@@ -1342,13 +1391,29 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
 
     return NODE1(DEFER, a);
   } else if (MATCH(PASS)) return NODE0(PASS);
-  else if (MATCH(REQUIRE)) {
-    if (!AT(STRING))
-      PARSE_ERROR("expected string");
+  else if (MATCH(TRY)) {
+    node_t *a = BLOCK();
+    token_t *t = NULL;
+
+    EXPECT(CATCH, "catch");
 
-    token_t *path = tokens->data[(*pos)++];
+    if (!AT(COLON) && !AT(LCB)) {
+      if (!AT(NAME))
+        PARSE_ERROR("expected identifier");
+
+      t = tokens->data[(*pos)++];
+    }
+
+    node_t *b = BLOCK();
+
+    return NODE2t(TRY, a, b, t);
+  } else if (MATCH(THROW)) {
+    node_t *a = NULL;
+
+    if (!CLIFF)
+      a = parse_expr(tokens, pos);
 
-    return NODET(REQUIRE, path);
+    return NODE1(THROW, a);
   }
 
   node_t *n = parse_expr(tokens, pos);
@@ -1357,10 +1422,27 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
 }
 
 node_t *parse_program(list_t *tokens, size_t *pos) {
+  if (AT(EOF))
+    PARSE_ERROR("empty program");
+
   list_t *stmts = list_new();
 
-  while (*pos < tokens->length) {
-    node_t *n = parse_stmt(tokens, pos);
+  int flag = 0;
+
+  while (!AT(EOF) && *pos < tokens->length) {
+    node_t *n;
+
+    if (MATCH(REQUIRE)) {
+      if (flag)
+        PARSE_ERROR("misplaced require statement")
+
+      if (!AT(STRING))
+        PARSE_ERROR("expected string");
+
+      token_t *path = tokens->data[(*pos)++];
+
+      n = NODET(REQUIRE, path);
+    } else { n = parse_stmt(tokens, pos); flag = 1; }
 
     MATCH(SEMI);
 
@@ -1492,7 +1574,7 @@ int in_context(list_t *ctx, char *s) {
   return 0;
 }
 
-size_t scopes_count(list_t *ctx) {
+size_t count_ctxs(list_t *ctx, char *s) {
   if (!ctx->length)
     return 0;
 
@@ -1501,7 +1583,7 @@ size_t scopes_count(list_t *ctx) {
   for (ssize_t i = ctx->length - 1; i >= 0; i--) {
     if (strcmp(ctx->data[i], "gap") == 0)
       break;
-    else if (strcmp(ctx->data[i], "scope") == 0)
+    else if (strcmp(ctx->data[i], s) == 0)
       k++;
   }
 
@@ -1509,7 +1591,8 @@ size_t scopes_count(list_t *ctx) {
 }
 
 #define INCTX(s) (in_context(ctx, (s)))
-#define SCOPESK (scopes_count(ctx))
+#define SCOPESK (count_ctxs(ctx, "scope"))
+#define TRAPSK (count_ctxs(ctx, "trap"))
 
 #define LPUSH(i) stack_push(lstk, (i))
 #define LPOP() stack_pop(lstk)
@@ -1601,6 +1684,11 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, li
   }
 }
 
+#define STD_SIZE 1
+const char *STD[STD_SIZE][2] = {
+  {"std", "func head(l): return l[0]"},
+};
+
 void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctk, stack_t *lstk);
 
 void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, node_t *node) {
@@ -1800,6 +1888,9 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
       for (size_t i = 0; i < SCOPESK; i++)
         EMIT("qi_old_scope(state);\n");
 
+      for (size_t i = 0; i < TRAPSK; i++)
+        EMIT("qi_unset_trap(state, trap);\n");
+
       EMIT("return ");
 
       if (node->a)
@@ -1812,28 +1903,66 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
     case N_FUNCDEF: break;
     case N_PASS: break;
 
+    case N_TRY:
+      CTXPUSH("scope");
+      EMIT("qi_new_scope(state);\n");
+      EMIT("qi_try(state, {\n");
+      compile_node(gbuf, buf, ctx, lstk, node->a);
+      EMIT("}, {\n");
+      if (node->t)
+        EMIT("qi_decl(state, \"%s\", trap->value);\n", node->t->text);
+      CTXPUSH("trap");
+      compile_node(gbuf, buf, ctx, lstk, node->b);
+      CTXPOP();
+      EMIT("}, NULL);\n");
+      EMIT("qi_new_scope(state);");
+      CTXPOP();
+      break;
+
+    case N_THROW:
+      EMIT("qi_throw(state, ");
+      if (node->a)
+        compile_node(gbuf, buf, ctx, lstk, node->a);
+      else {
+        EMIT("state->nil");
+      }
+      EMIT(");");
+      break;
+
     case N_REQUIRE: {
+      char *source = NULL;
+
       char *path = node->t->text;
+      for (size_t i = 0; i < STD_SIZE; i++) {
+        if (strcmp(path, STD[i][0]) == 0) {
+          source = (char *)STD[i][1];
+
+          break;
+        }
+      }
 
       if (is_required(path))
         break;
 
-      FILE *fd = fopen(path, "rb");
-      if (!fd)
-        COMPILE_ERROR("failed to open: `%s'", path);
+      if (!source) {
+        FILE *fd = fopen(path, "rb");
+        if (!fd)
+          COMPILE_ERROR("failed to open: `%s'", path);
 
-      buffer_t *fbuf = buffer_new();
+        buffer_t *fbuf = buffer_new();
 
-      for (;;) {
-        char line[512];
+        for (;;) {
+          char line[512];
 
-        if (!fgets(line, sizeof(line), fd))
-          break;
+          if (!fgets(line, sizeof(line), fd))
+            break;
 
-        buffer_appends(fbuf, line);
-      }
+          buffer_appends(fbuf, line);
+        }
 
-      char *source = buffer_read(fbuf);
+        source = buffer_read(fbuf);
+        path = realpath(path, NULL);
+      }
 
       list_t *pair = list_new();
       list_push(pair, path);
@@ -1889,6 +2018,14 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
       BINOP("div");
       break;
 
+    case N_IDIV:
+      BINOP("idiv");
+      break;
+
+    case N_POW:
+      BINOP("pow");
+      break;
+
     case N_NEGATE:
       UNOP("negate");
       break;