commit 6ff4c2c0398e451e68875fd71705a07f351bb289
parent fe7d2fd10e29b176370e9a9ebc066d4365ca1c1e
Author: Ed van Bruggen <edvb@uw.edu>
Date: Sun, 28 Oct 2018 23:52:58 -0700
Add floating point type
Diffstat:
4 files changed, 59 insertions(+), 17 deletions(-)
diff --git a/t/simple/frac.expect b/t/simple/frac.expect
@@ -6,6 +6,4 @@
1/2
1192/3619
-1/2
--1/2
-2
-2
diff --git a/t/simple/frac.tsp b/t/simple/frac.tsp
@@ -6,6 +6,4 @@
4/8
02384/7238
-1/2
-1/-2
-6/3
--6/-3
diff --git a/tisp.c b/tisp.c
@@ -54,6 +54,7 @@ type_str(Type t)
switch (t) {
case NIL: return "nil";
case INTEGER: return "integer";
+ case DOUBLE: return "double";
case RATIONAL: return "rational";
case STRING: return "string";
case SYMBOL: return "symbol";
@@ -144,6 +145,10 @@ vals_eq(Val a, Val b)
if (a->v.i != b->v.i)
return 0;
break;
+ case DOUBLE:
+ if (a->v.d != b->v.d)
+ return 0;
+ break;
case RATIONAL:
if (a->v.r.num != b->v.r.num || a->v.r.den != b->v.r.den)
return 0;
@@ -294,6 +299,15 @@ mk_int(int i)
}
Val
+mk_dub(double d)
+{
+ Val ret = emalloc(sizeof(struct Val));
+ ret->t = DOUBLE;
+ ret->v.d = d;
+ return ret;
+}
+
+Val
mk_rat(int num, int den)
{
if (den == 0)
@@ -371,28 +385,47 @@ mk_list(Env env, int n, Val *a)
}
static int
-read_int(Str str) {
- int ret, sign = 1;
+read_sign(Str str)
+{
switch (*str->d) {
- case '-':
- sign = -1;
- case '+':
- str->d++;
- break;
+ case '-': ++str->d; return -1;
+ case '+': ++str->d; return 1;
+ default: return 1;
}
+}
+
+static int
+read_int(Str str)
+{
+ int ret;
for (ret = 0; isdigit(*str->d); str->d++)
ret = ret * 10 + *str->d - '0';
- return sign * ret;
+ return ret;
}
Val
read_num(Str str)
{
+ int sign = read_sign(str);
int num = read_int(str);
- if (*str->d != '/')
- return mk_int(num);
- str->d++;
- return mk_rat(num, read_int(str));
+ Str s;
+ switch (*str->d) {
+ case '/':
+ str->d++;
+ return mk_rat(sign * num, read_int(str));
+ case '.':
+ s = emalloc(sizeof(str));
+ s->d = ++str->d;
+ double d = (double) read_int(s);
+ int size = s->d - str->d;
+ str->d = s->d;
+ free(s);
+ while (size--)
+ d /= 10.0;
+ return mk_dub(sign * (num+d));
+ default:
+ return mk_int(sign * num);
+ }
}
static Val
@@ -441,13 +474,20 @@ read_list(Env env, Str str)
return b;
}
+static int
+isnum(char *str)
+{
+ return isdigit(*str) || (*str == '.' && isdigit(str[1])) ||
+ ((*str == '-' || *str == '+') && (isdigit(str[1]) || str[1] == '.'));
+}
+
Val
tisp_read(Env env, Str str)
{
skip_ws(str);
if (strlen(str->d) == 0)
return env->nil;
- if (isdigit(*str->d) || ((*str->d == '-' || *str->d == '+') && isdigit(str->d[1])))
+ if (isnum(str->d))
return read_num(str);
if (*str->d == '"')
return read_str(str);
@@ -487,6 +527,7 @@ tisp_eval(Env env, Val v)
switch (v->t) {
case NIL:
case INTEGER:
+ case DOUBLE:
case RATIONAL:
case STRING:
return v;
@@ -526,6 +567,9 @@ tisp_print(Val v)
case INTEGER:
printf("%d", v->v.i);
break;
+ case DOUBLE:
+ printf("%f", v->v.d);
+ break;
case RATIONAL:
printf("%d/%d", v->v.r.num, v->v.r.den);
break;
diff --git a/tisp.h b/tisp.h
@@ -71,6 +71,7 @@ typedef enum {
NIL,
INTEGER,
RATIONAL,
+ DOUBLE,
STRING,
SYMBOL,
PRIMITIVE,
@@ -83,6 +84,7 @@ struct Val {
union {
int i;
Ratio r;
+ double d;
char *s;
Prim pr;
Func f;