X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=src%2Fread.c;h=0f6a63d840108567ed2180c37dbe70afca1b5df0;hb=e3dcc1d3966fb95a5a232daa193c6b5d89a06b7e;hp=57dd81f511d8f3538e73ee7efed7bd1bd7945029;hpb=8d55156675587a770c5654362bcbd3d2a98e4aa9;p=muddle-interpreter.git diff --git a/src/read.c b/src/read.c index 57dd81f..0f6a63d 100644 --- a/src/read.c +++ b/src/read.c @@ -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 @@ -18,6 +18,7 @@ License along with this file. If not, see #include "read.h" #include "object.h" +#include "oblist.h" #include #include @@ -113,6 +114,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 +207,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 +235,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 +250,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 = oblist_find_or_insert (root, p, n); + 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; }