read: implement basic decimal FIXes
[muddle-interpreter.git] / src / read.c
index 57dd81f511d8f3538e73ee7efed7bd1bd7945029..68efbf3eef5c2c5434c4550a23f692f464508976 100644 (file)
@@ -113,10 +113,70 @@ 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 *
-read_token (const char *p, reader_stack * st)
+read_token (const char *p, reader_stack *st)
 {
   p += count_whitespace (p);
   switch (p[0])
@@ -191,17 +251,17 @@ read_token (const char *p, reader_stack * st)
        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;
+
+       // TODO: try read pname
+
+       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;
 }