txlyre 1 mês atrás
pai
commit
4a4d3a6214
1 arquivos alterados com 66 adições e 2 exclusões
  1. 66 2
      qic.c

+ 66 - 2
qic.c

@@ -289,6 +289,7 @@ typedef struct {
     T_USE,
     T_RETURN,
     T_DEFER,
+    T_REQUIRE,
 
     T_LPAR,
     T_RPAR,
@@ -367,6 +368,17 @@ void consume_ignored(char *source, size_t *pos) {
 
 list_t *FILES;
 
+int is_required(char *path) {
+  for (size_t i = 0; i < FILES->length; i++) {
+    list_t *pair = FILES->data[i];
+
+    if (strcmp(pair->data[0], path) == 0)
+      return 1;
+  }
+
+  return 0;
+}
+
 void traverse(char *source, size_t pos, size_t *line, size_t *col) {
   *line = 1;
   *col = 1;
@@ -525,6 +537,8 @@ token_t *next_token(char *source, size_t *pos) {
       return TK(DEFER);
     else if (strcmp(name, "pass") == 0)
       return TK(PASS);
+    else if (strcmp(name, "require") == 0)
+      return TK(REQUIRE);
 
     return token(T_NAME, name);
   } else if (strncmp(&source[*pos], "==", 2) == 0 && ++(*pos) && ++(*pos))
@@ -644,6 +658,7 @@ struct _node_t {
     N_RETURN,
     N_DEFER,
     N_PASS,
+    N_REQUIRE,
 
     N_IFEXPR,
     N_FUNCEXPR,
@@ -1329,6 +1344,14 @@ 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");
+
+    token_t *path = tokens->data[(*pos)++];
+
+    return NODET(REQUIRE, path);
+  }
 
   node_t *n = parse_expr(tokens, pos);
 
@@ -1580,6 +1603,8 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, li
   }
 }
 
+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) {
   switch (node->tag) {
     case N_PROGRAM:
@@ -1781,6 +1806,7 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
 
       if (node->a)
         compile_node(gbuf, buf, ctx, lstk, node->a);
+      else EMIT("state->nil");
 
       EMIT(";");
       break;
@@ -1788,6 +1814,40 @@ 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_REQUIRE: {
+      char *path = node->t->text;
+
+      if (is_required(path))
+        break;
+
+      FILE *fd = fopen(path, "rb");
+      if (!fd)
+        COMPILE_ERROR("failed to open: `%s'", path);
+
+      buffer_t *fbuf = buffer_new();
+
+      for (;;) {
+        char line[512];
+
+        if (!fgets(line, sizeof(line), fd))
+          break;
+
+        buffer_appends(fbuf, line);
+      }
+
+      char *source = buffer_read(fbuf);
+
+      list_t *pair = list_new();
+      list_push(pair, path);
+      list_push(pair, source);
+
+      list_push(FILES, pair);
+
+      compile_into(source, gbuf, buf, ctx, lstk);
+
+      list_pop(FILES);
+      } break;
+
     case N_IFEXPR:
       EMIT("(_qi_truthy(state, ");
       compile_node(gbuf, buf, ctx, lstk, node->a);
@@ -1839,9 +1899,13 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk, nod
   }
 }
 
-char *compile(char *source) {
+void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, stack_t *lstk) {
   node_t *n = parse(source);
 
+  compile_node(gbuf, buf, ctx, lstk, n);
+}
+
+char *compile(char *source) {
   list_t *ctx = list_new();
   stack_t *lstk = stack_new();
   
@@ -1851,7 +1915,7 @@ char *compile(char *source) {
 
   buffer_t *buf = buffer_new();
 
-  compile_node(gbuf, buf, ctx, lstk, n);
+  compile_into(source, gbuf, buf, ctx, lstk);
 
   buffer_t *rbuf = buffer_new();