txlyre 2 өдөр өмнө
parent
commit
105ad4b889
1 өөрчлөгдсөн 124 нэмэгдсэн , 54 устгасан
  1. 124 54
      qic.c

+ 124 - 54
qic.c

@@ -692,7 +692,7 @@ token_t *next_token(char *source, size_t *pos) {
     (*pos)++;
 
     buffer_t *name = buffer_new();
-    if (source[*pos] == '$' || source[*pos] == '{' || source[*pos] == ':')
+    if (source[*pos] == '$' || source[*pos] == '{' || source[*pos] == ':' || source[*pos] == '*')
       buffer_append(name, source[(*pos)++]);
     else {
       if (!source[*pos] || !isalpha(source[*pos]))
@@ -1267,6 +1267,7 @@ node_t *nodeb(buffer_t *buf) {
 typedef struct {
   list_t *params;
   list_t *body;
+  int variable;
 } macro_t;
 
 table_t *MACROS;
@@ -2410,7 +2411,9 @@ node_t *parse_stmt(list_t *tokens, size_t *pos) {
 node_t *parse_mexpr(list_t *tokens, size_t *pos);
 
 node_t *parse_mprimary(list_t *tokens, size_t *pos) {
-  if (MATCH(LPAR)) {
+  if (MATCH(STAR))
+    return NODET(LITERAL, token(T_NAME, strdup("*")));
+  else if (MATCH(LPAR)) {
     node_t *a = parse_mexpr(tokens, pos);
 
     EXPECT(RPAR, ")");
@@ -2452,6 +2455,12 @@ node_t *parse_mprimary(list_t *tokens, size_t *pos) {
 }
 
 node_t *parse_mexpr(list_t *tokens, size_t *pos) {
+  if (MATCH(MINUS)) {
+    node_t *a = parse_mexpr(tokens, pos);
+
+    return NODE1(NEGATE, a);
+  }
+
   node_t *a = parse_mprimary(tokens, pos);
 
   do {
@@ -2616,15 +2625,20 @@ node_t *parse_program(list_t *tokens, size_t *pos) {
 
       EXPECT(LPAR, "(");
 
+      int variable = 0;
       list_t *params = list_new();
 
-      if (!AT(RPAR))
-        do {
-          if(!AT(NAME))
-            PARSE_ERROR("expected identifier");
+      if (!AT(RPAR)) {
+        if (MATCH(STAR))
+          variable = 1;
+        else
+          do {
+            if(!AT(NAME))
+              PARSE_ERROR("expected identifier");
 
-          list_push(params, tokens->data[(*pos)++]);
-        } while (MATCH(COMMA));
+            list_push(params, tokens->data[(*pos)++]);
+          } while (MATCH(COMMA));
+      }
 
       EXPECT(RPAR, ")");
 
@@ -2654,7 +2668,8 @@ node_t *parse_program(list_t *tokens, size_t *pos) {
       macro_t *m = malloc_checked(sizeof(macro_t));
       m->params = params;
       m->body = body;
-      
+      m->variable = variable;
+
       list_push(ms, m);
     } else { n = parse_stmt(tokens, pos); flag = 1; }
 
@@ -3470,6 +3485,53 @@ buffer_t *HBUF;
 list_t *MVARS;
 node_t *YES;
 
+#define IS_NUMBER(n) ((n) && (n)->tag == N_LITERAL && (n)->t->tag == T_NUMBER)
+#define TO_DOUBLE(n) (strtod((n)->t->text, NULL))
+
+node_t *make_number(double v) {
+  char buf[64];
+  snprintf(buf, sizeof(buf), "%g", v);
+
+  return nodet(N_LITERAL, token(T_NUMBER, strdup(buf)));
+}
+
+node_t *mexpr_negate(node_t *a) {
+  if (!IS_NUMBER(a))
+    return NULL;
+
+  return make_number(-TO_DOUBLE(a));
+}
+
+node_t *mexpr_add(node_t *a, node_t *b) {
+  if (!IS_NUMBER(a))
+    return NULL;
+
+  if (!IS_NUMBER(b))
+    return NULL;
+
+  return make_number(TO_DOUBLE(a) + TO_DOUBLE(b));
+}
+
+node_t *mexpr_sub(node_t *a, node_t *b) {
+  if (!IS_NUMBER(a))
+    return NULL;
+
+  if (!IS_NUMBER(b))
+    return NULL;
+
+  return make_number(TO_DOUBLE(a) - TO_DOUBLE(b));
+}
+
+node_t *mexpr_mul(node_t *a, node_t *b) {
+  if (!IS_NUMBER(a))
+    return NULL;
+
+  if (!IS_NUMBER(b))
+    return NULL;
+
+  return make_number(TO_DOUBLE(a) * TO_DOUBLE(b));
+}
+
 node_t *mf_isExpr(list_t *t) {
   if (t->length != 1)
     return NULL;
@@ -3500,57 +3562,52 @@ node_t *mf_newList(list_t *t) {
   return nodel(N_LIST, t);
 }
 
-struct {
-  char *name;
-  node_t *(*handler)(list_t *);
-} METAFUNCS[] = {
-  { "isExpr", mf_isExpr },
-  { "isList", mf_isList },
-
-  { "newList", mf_newList },
-
-  { NULL, NULL }
-};
+node_t *mf_len(list_t *t) {
+  if (t->length != 1)
+    return NULL;
 
-#define IS_NUMBER(n) ((n) && (n)->tag == N_LITERAL && (n)->t->tag == T_NUMBER)
-#define TO_DOUBLE(n) (strtod((n)->t->text, NULL))
+  node_t *a = t->data[0];
+  if (!a)
+    return NULL;
 
-node_t *make_number(double v) {
-  char buf[64];
-  snprintf(buf, sizeof(buf), "%g", v);
+  if (a->tag == N_LIST)
+    return make_number(a->l->length);
 
-  return nodet(N_LITERAL, token(T_NUMBER, strdup(buf)));
+  return NULL;
 }
 
-node_t *mexpr_add(node_t *a, node_t *b) {
-  if (!IS_NUMBER(a))
+node_t *mf_nth(list_t *t) {
+  if (t->length != 2)
     return NULL;
 
-  if (!IS_NUMBER(b))
-    return NULL;
-
-  return make_number(TO_DOUBLE(a) + TO_DOUBLE(b));
-}
-
-node_t *mexpr_sub(node_t *a, node_t *b) {
-  if (!IS_NUMBER(a))
+  node_t *a = t->data[0];
+  if (!a)
     return NULL;
 
+  node_t *b = t->data[1];
   if (!IS_NUMBER(b))
     return NULL;
 
-  return make_number(TO_DOUBLE(a) - TO_DOUBLE(b));
+  if (a->tag == N_LIST)
+    return list_index(a->l, TO_DOUBLE(b));
+
+  return NULL;
 }
 
-node_t *mexpr_mul(node_t *a, node_t *b) {
-  if (!IS_NUMBER(a))
-    return NULL;
+struct {
+  char *name;
+  node_t *(*handler)(list_t *);
+} METAFUNCS[] = {
+  { "isExpr", mf_isExpr },
+  { "isList", mf_isList },
 
-  if (!IS_NUMBER(b))
-    return NULL;
+  { "newList", mf_newList },
 
-  return make_number(TO_DOUBLE(a) * TO_DOUBLE(b));
-}
+  { "len", mf_len },
+  { "nth", mf_nth },
+
+  { NULL, NULL }
+};
 
 macro_t *find_macro(char *name, size_t argc, int *res) {
   list_t *ms = table_get(MACROS, name);
@@ -3562,12 +3619,15 @@ macro_t *find_macro(char *name, size_t argc, int *res) {
   }
 
   macro_t *m = NULL;
-  for (ssize_t i = ms->length - 1; i >= 0; i--)
-    if (((macro_t *)ms->data[i])->params->length == argc) {
-      m = ms->data[i];
+  for (size_t i = 0; i < ms->length; i++) {
+    macro_t *t = ms->data[i];
+
+    if (t->variable || t->params->length == argc) {
+      m = t;
 
       break;
     }
+  }
 
   if (!m) {
     if (res) *res = 2;
@@ -3641,33 +3701,39 @@ node_t *run_mexpr(node_t *node) {
       if (run_mexpr(node->a) && run_mexpr(node->b))
         return YES;
 
+    case N_NEGATE: {
+      node_t *a = run_mexpr(node->a);
+
+      return mexpr_negate(a);
+    } 
+
     case N_ADD: {
       node_t *a = run_mexpr(node->a);
       node_t *b = run_mexpr(node->b);
 
       return mexpr_add(a, b);
-    } break;
+    }
 
     case N_SUB: {
       node_t *a = run_mexpr(node->a);
       node_t *b = run_mexpr(node->b);
 
       return mexpr_sub(a, b);
-    } break;
+    }
 
     case N_MUL: {
       node_t *a = run_mexpr(node->a);
       node_t *b = run_mexpr(node->b);
 
       return mexpr_mul(a, b);
-    } break;
+    }
 
     case N_EQUALS: {
       node_t *a = run_mexpr(node->a);
       node_t *b = run_mexpr(node->b);
 
       return mexpr_equals(a, b)? YES: NULL;
-    } break;
+    }
 
     default:
       COMPILE_ERROR("not yet implemented");
@@ -3716,9 +3782,13 @@ node_t *run_mnode(node_t *node) {
 
 node_t *run_macro(macro_t *macro, list_t *args) {
   table_t *mvars = list_index(MVARS, -1);
-  for (size_t i = 0; i < args->length; i++)
-    table_set(mvars, ((token_t *)macro->params->data[i])->text, args->data[i]);
-  
+
+  if (macro->variable)
+    table_set(mvars, "*", nodel(N_LIST, args));
+  else 
+    for (size_t i = 0; i < args->length; i++)
+      table_set(mvars, ((token_t *)macro->params->data[i])->text, args->data[i]);
+
   node_t *r = NULL;
 
   for (size_t i = 0; i < macro->body->length; i++) {