txlyre 2 gün önce
ebeveyn
işleme
5ea5ad09c0
1 değiştirilmiş dosya ile 105 ekleme ve 16 silme
  1. 105 16
      qic.c

+ 105 - 16
qic.c

@@ -416,18 +416,18 @@ int is_required(char *path) {
 }
 
 char *traverse(char *source, size_t pos, size_t *line, size_t *col) {
-  *line = 1;
-  *col = 1;
+  if (line) *line = 1;
+  if (col) *col = 1;
 
   size_t p = 0;
 
   for (size_t i = 0; i < pos; i++) {
      if (source[i] == '\n') {
-       (*line)++;
-       (*col) = 1;
+       if (line) (*line)++;
+       if (col) (*col) = 1;
 
        p = i+1;
-     } else (*col)++;
+     } else if (col) (*col)++;
   }
 
   return &source[p];
@@ -812,6 +812,10 @@ list_t *tokenize(char *source) {
   return toks;
 }
 
+int DEBUG = 0;
+list_t *DEBUGDATA;
+list_t *FUNCNAMES;
+
 struct _node_t {
   enum {
     N_TOPLEVEL,
@@ -2493,9 +2497,30 @@ list_t *CONSTANTS;
 #define LBPUSH() list_push(lbl, table_new())
 #define LBPOP() list_pop(lbl)
 
+size_t insert_debug(node_t *node) {
+  size_t line;
+  (void)traverse(GETSRC(node->fi), node->pos, &line, NULL);
+
+  buffer_t *tbuf = buffer_new();
+  buffer_fmt(tbuf, "File \"%s\", line %d", GETFNAME(node->fi), line);
+
+  if (FUNCNAMES->length)
+    buffer_fmt(tbuf, ", in %s", list_index(FUNCNAMES, -1));
+
+  list_push(DEBUGDATA, buffer_read(tbuf));
+
+  return DEBUGDATA->length - 1;
+}
+
+void emit_debug(buffer_t *buf, node_t *node) {
+  buffer_fmt(buf, "state->_debug_data = __debugData[%d];\n", insert_debug(node)); 
+}
+
 void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, stack_t *lstk, stack_t *sstk, list_t *lbl, node_t *node, char *name) {
   NEWGID();
 
+  char *funname = name? name: node->t? node->t->text: "<anon>";
+
   buffer_t *tbuf = buffer_new();
 
   buffer_fmt(tbuf, "qi_value_t *__func%d(qi_state_t *state, qi_size_t pargc, qi_list_t *pargs) {\n", gid);
@@ -2504,6 +2529,9 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
   CTXPUSH("gap");
   CTXPUSH("func");
   list_push(CONSTANTS, table_new());
+  list_push(FUNCNAMES, funname);
+
+  if (DEBUG) emit_debug(tbuf, node);
 
   size_t optargc = 0;
 
@@ -2528,6 +2556,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
 
   compile_node(gbuf, tbuf, ctx, table_new(), stack_new(), stack_new(), lbl, node->a);
 
+  list_pop(FUNCNAMES);
   list_pop(CONSTANTS);
   CTXPOP();
   CTXPOP();
@@ -2540,7 +2569,7 @@ void compile_func(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
 
   tbuf = buffer_new();
 
-  buffer_fmt(tbuf, "qi_make_function(state, \"%s\", %d, __func%d, ", name? name: node->t? node->t->text: "<anon>", !node->h? 0: (node->h->used - optargc), gid);
+  buffer_fmt(tbuf, "qi_make_function(state, \"%s\", %d, __func%d, ", funname, !node->h? 0: (node->h->used - optargc), gid);
   compile_table(gbuf, tbuf, ctx, ltab, lstk, sstk, lbl, node->h2);
   buffer_fmt(tbuf, ")");
 
@@ -2670,6 +2699,8 @@ void compile_block(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, st
     if (n->tag == N_CONST || n->tag == N_FUNCDEF || n->tag == N_CLASS || n->tag == N_PASS)
       continue;
 
+    if (DEBUG) emit_debug(buf, n);
+
     compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
 
     EMIT("\n");
@@ -3809,10 +3840,19 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
       break;
 
     case N_CALL:
-      EMIT("qi_call(state, ");
+      if (DEBUG) {
+        EMIT("qi_call_debug(state, ");
+      } else {
+        EMIT("qi_call(state, ");
+      }
+
       compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->a);
       EMIT(", ");
       compile_list(gbuf, buf, ctx, ltab, lstk, sstk, lbl, node->l);
+
+      if (DEBUG)
+        buffer_fmt(buf, ", __debugData[%d]", insert_debug(node)); 
+
       EMIT(")");
       break;
 
@@ -4505,6 +4545,19 @@ void compile_into(char *source, buffer_t *gbuf, buffer_t *buf, list_t *ctx, tabl
   compile_node(gbuf, buf, ctx, ltab, lstk, sstk, lbl, n);
 }
 
+char *escape(char *s) {
+  buffer_t *buf = buffer_new();
+
+  while (*s) {
+    if (*s == '\\' || *s == '"')     
+      buffer_append(buf, '\\');
+
+    buffer_append(buf, *s++);
+  }
+
+  return buffer_read(buf);
+}
+
 char *compile(char *source, list_t *required) {
   list_t *ctx = list_new();
   table_t *ltab = table_new();
@@ -4531,13 +4584,28 @@ char *compile(char *source, list_t *required) {
   buffer_t *rbuf = buffer_new();
 
   buffer_appends(rbuf, "#include <qirt.h>\n");
+
+  if (DEBUG && DEBUGDATA->length) {
+    buffer_fmt(rbuf, "static const char *__debugData[%d] = {\n", DEBUGDATA->length);
+
+    for (size_t i = 0; i < DEBUGDATA->length; i++)
+      buffer_fmt(rbuf, "\"%s\",\n", escape(DEBUGDATA->data[i]));
+
+    buffer_fmt(rbuf, "};\n");
+  }
+
   buffer_appendb(rbuf, HBUF);
 
   buffer_appendb(rbuf, gbuf);
 
   buffer_appends(rbuf, "int main(int argc, char **argv) {\n");
   buffer_appends(rbuf, "qi_state_t *state;\n");
-  buffer_appends(rbuf, "qi_state_init(&state);\n");
+
+  if (DEBUG)
+    buffer_appends(rbuf, "qi_state_init_debug(&state);\n");
+  else
+    buffer_appends(rbuf, "qi_state_init(&state);\n");
+
   buffer_appends(rbuf, "qi_list_t *args = qi_list_make();\n");
   buffer_appends(rbuf, "for (int i = 0; i < argc; i++)\n");
   buffer_appends(rbuf, "  qi_list_push(args, qi_make_string(state, argv[i]));\n");
@@ -4579,6 +4647,9 @@ char *compile_file(char *filename, FILE *fd, list_t *required) {
 }
 
 int main(int argc, char **argv) {
+  DEBUGDATA = list_new();
+  FUNCNAMES = list_new();
+
   FILES = list_new();
   REQUIRED = list_new();
 
@@ -4590,19 +4661,37 @@ int main(int argc, char **argv) {
   genmathlib();
 
   char *out;
+  char *main = NULL;
+  list_t *required = NULL;
+  int readstdin = 0;
+
+  for (size_t i = 1; i < argc; i++) {
+    if (*argv[i] == '-') {
+      if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0)
+        DEBUG = 1;
+      else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--stdin") == 0)
+        readstdin = 1;
+      else {
+        fprintf(stderr, "fatal: unknown commandline argument: '%s'\n", argv[i]);
 
-  if (argc < 2)
-    out = compile_file("<stdin>", stdin, NULL);
-  else {
-    char *main = argv[1];
-    list_t *required = NULL;
+        return 1;
+      }
 
-    if (argc > 2)
-      required = list_new();
+      continue;
+    }
+
+    if (!readstdin && !main) main = argv[i];
+    else {
+      if (!required)
+        required = list_new();
 
-    for (size_t i = 2; i < argc; i++)
       list_push(required, argv[i]);
+    }
+  }
 
+  if (readstdin || !main)
+    out = compile_file("<stdin>", stdin, required);
+  else {
     FILE *fd = fopen(main, "rb");
     if (!fd) {
       fprintf(stderr, "fatal: unable to open file: '%s'\n", main);