Define UVECTOR and ATOM
[muddle-interpreter.git] / src / read.c
index 57dd81f511d8f3538e73ee7efed7bd1bd7945029..b8570f3778f09fa13f134a1a2af088d00e1cce9e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2017 Keziah Wesley
+Copyright (C) 2017-2018 Keziah Wesley
 
 You can redistribute and/or modify this file under the terms of the
 GNU Affero General Public License as published by the Free Software
@@ -113,6 +113,66 @@ static uint32_t obj_get_fix32(const object *o) {
 }
 */
 
+static int
+read_num (const char *p, reader_stack * st)
+{
+  int i = 0;
+  // Use an unsigned intermediate to simplify overflow checks.
+  uint64_t x = 0;
+  // Disallow "number" composed of ancillary number components only.
+  bool gotdigits = false;
+  // Skip for now, later we'll check again to potentially negate.
+  if (p[0] == '-')
+    i++;
+  // TODO: asterisk-deliminated *octal*
+  // TODO: other bases?
+  for (; p[i]; i++)
+    {
+      if (p[i] >= '0' && p[i] <= '9')
+       {
+         if (x * 10 + (p[i] - '0') < x)
+           goto read_float;
+         x = x * 10 + (p[i] - '0');
+         gotdigits = true;
+         continue;
+       }
+
+      // TODO: decimal points, exponent notation
+      // NB. a terminal decimal denotes a FIX
+      // NB. exponent notation doesn't necessarily indicate a float
+
+      // TODO: distinguish 'delimiter' characters that terminate
+      // number from 'identifier' chars that cause parsing to fail
+      // (and potentially be parsed as an atom)
+      break;
+    }
+  if (!gotdigits)
+    return 0;
+  if (p[0] != '-')
+    {
+      if (x <= INT32_MAX)
+       (--(st->pos))->fix32 = new_fix32 ((int32_t) x);
+      else if (x <= INT64_MAX)
+       (--(st->pos))->fix64 = new_fix64 (x);
+      else
+       goto read_float;
+    }
+  else
+    {
+      if (-x >= (uint64_t) INT32_MIN)
+       (--(st->pos))->fix32 = new_fix32 (0 - (int32_t) x);
+      else if (-x >= (uint64_t) INT64_MIN)
+       (--(st->pos))->fix64 = new_fix64 (0 - (int64_t) x);
+      else
+       goto read_float;
+    }
+  st->framelen++;
+  return i;
+read_float:
+  assert (0 && "unimplemented: promote num to float");
+  return i;
+}
+
 // stack[0..len]: objs in current list
 // stack[len]: parent len
 const char *
@@ -146,7 +206,10 @@ read_token (const char *p, reader_stack * st)
          }
        *--(st->pos) = (object)
        {
-       .fix32.type = type,.fix32.rest = 0,.fix32.val = st->framelen,};
+         .fix32.type = type,.fix32.rest = 0,.fix32.val = (fix32_val)
+         {
+         .n = st->framelen}
+       ,};
        st->framelen = 0;
        break;
       }
@@ -171,11 +234,10 @@ read_token (const char *p, reader_stack * st)
        // pop frame, push new LIST
        st->pos += st->framelen;
        assert (st->pos->type == type);
-       st->framelen = st->pos->fix32.val + 1;
+       st->framelen = st->pos->fix32.val.n + 1;
        // overwrite the frame marker with the collection it became
-       st->pos->list = (list_object)
-       {
-       .type = type,.rest = 0,.head = o};
+       st->pos->list = new_list (o);
+       st->pos->list.type = type;
        break;
       }
     case ']':
@@ -187,21 +249,27 @@ read_token (const char *p, reader_stack * st)
        uint32_t len = st->framelen;
        st->pos += st->framelen;
        assert (st->pos->type == EVALTYPE_VECTOR);
-       st->framelen = st->pos->fix32.val + 1;
+       st->framelen = st->pos->fix32.val.n + 1;
        st->pos->vector = new_vector (h, len);
        break;
       }
-    case '4':
+    default:
       {
-       p++;
-       // push fix obj, extending frame
-       (--(st->pos))->fix64 = new_fix64 (4);
-       st->framelen++;
-       break;
+       int n = read_num (p, st);
+       if (n)
+         return p + n;
+
+       n = count_pname (p);
+       if (n > 0)
+         {
+           (--(st->pos))->atom = new_atom (0);
+           st->framelen++;
+           return p + n;
+         }
+
+       fprintf (stderr, "read unimplemented for char: '%c'\n", *p);
+       assert (0 && "read unimplemented for char");
       }
-    default:
-      fprintf (stderr, "read unimplemented for char: '%c'\n", *p);
-      assert (0 && "read unimplemented for char");
     }
   return p;
 }