ref: 0318f82986c6c2522a232f8b248017e8a5dc533d
parent: a1ecc5c8c33a2fb69047602eb03410bc61adbabb
author: Rewbert <krookr@chalmers.se>
date: Wed Sep 20 10:08:24 EDT 2023
i broke it, the evaluator reaches ERR valio tag 17
--- /dev/null
+++ b/Main.hs
@@ -1,0 +1,9 @@
+module Main (main) where
+
+import Prelude
+
+y :: Double
+y = -1.37
+
+main :: IO ()
+main = putStrLn $ showDouble y
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@
@mkdir -p bin
$(GCC) -Wall -O3 src/runtime/eval.c -o $(EVAL)
-$(BIN)/$(MHS): src/*.hs src/*/*.hs $(TOOLS)/convertX.sh
+$(BIN)/$(MHS): src/*.hs src/*/*.hs lib/Primitives.hs $(TOOLS)/convertX.sh
$(GHCE) -isrc -Wall -O src/MicroHs/Main.hs -main-is MicroHs.Main -o $(BIN)/$(MHS)
$(BIN)/boot$(MHS): $(ALLSRC) $(TOOLS)/convertY.sh
--- a/TODO
+++ b/TODO
@@ -25,6 +25,6 @@
- maybe?
- could be used instead of derived when all is derived
* use pointer stack during GC instead of recursion.
-* add Double primitive type
+ROBERT * add Double primitive type
* implement Data.Integer
* add pretty printing library
--- /dev/null
+++ b/lib/Data/Double.hs
@@ -1,0 +1,49 @@
+-- Copyright 2023 Lennart Augustsson
+-- See LICENSE file for full license.
+module Data.Double(module Data.Double) where
+import Primitives
+import Data.Bool_Type
+
+--Yinfixl 6 +,-
+--Yinfixl 7 *
+
+-- Arithmetic
+(+) :: Double -> Double -> Double
+(+) = primDoubleAdd
+(-) :: Double -> Double -> Double
+(-) = primDoubleSub
+(*) :: Double -> Double -> Double
+(*) = primDoubleMul
+
+negate :: Double -> Double
+negate x = 0.0 - x
+
+--------------------------------
+
+--Yinfix 4 ==,/=,<,<=,>,>=
+
+-- Comparison
+(==) :: Double -> Double -> Bool
+(==) = primDoubleEQ
+(/=) :: Double -> Double -> Bool
+(/=) = primDoubleNE
+
+(<) :: Double -> Double -> Bool
+(<) = primDoubleLT
+(<=) :: Double -> Double -> Bool
+(<=) = primDoubleLE
+(>) :: Double -> Double -> Bool
+(>) = primDoubleGT
+(>=) :: Double -> Double -> Bool
+(>=) = primDoubleGE
+
+eqDouble :: Double -> Double -> Bool
+eqDouble = (==)
+
+ltDouble :: Double -> Double -> Bool
+ltDouble = (<)
+
+showDouble :: Double -> String
+showDouble = primDoubleShow
+
+--------------------------------
--- a/lib/Prelude.hs
+++ b/lib/Prelude.hs
@@ -7,6 +7,7 @@
module Data.Either,
module Data.Function,
module Data.Int,
+ module Data.Double,
module Data.List,
module Data.Maybe,
module Data.Tuple,
@@ -19,6 +20,7 @@
import Data.Either
import Data.Function
import Data.Int
+import Data.Double
import Data.List
import Data.Maybe
import Data.Tuple
--- a/lib/Primitives.hs
+++ b/lib/Primitives.hs
@@ -16,6 +16,27 @@
primIntSubR :: Int -> Int -> Int
primIntSubR = primitive "subtract"
+primDoubleAdd :: Double -> Double -> Double
+primDoubleAdd = primitive "fadd"
+primDoubleSub :: Double -> Double -> Double
+primDoubleSub = primitive "fsub"
+primDoubleMul :: Double -> Double -> Double
+primDoubleMul = primitive "fmul"
+primDoubleEQ :: Double -> Double -> Bool
+primDoubleEQ = primitive "feq"
+primDoubleNE :: Double -> Double -> Bool
+primDoubleNE = primitive "fne"
+primDoubleLT :: Double -> Double -> Bool
+primDoubleLT = primitive "flt"
+primDoubleLE :: Double -> Double -> Bool
+primDoubleLE = primitive "fle"
+primDoubleGT :: Double -> Double -> Bool
+primDoubleGT = primitive "fgt"
+primDoubleGE :: Double -> Double -> Bool
+primDoubleGE = primitive "fge"
+primDoubleShow :: Double -> String
+primDoubleShow = primitive "fshow"
+
primWordAdd :: Word -> Word -> Word
primWordAdd = primitive "+"
primWordSub :: Word -> Word -> Word
--- a/lib/Text/String.hs
+++ b/lib/Text/String.hs
@@ -5,6 +5,7 @@
import Data.Char
import Data.Either
import Data.Int
+import qualified Data.Double as DD
import Data.List
import Data.Maybe
import Data.Tuple
--- a/src/Compat.hs
+++ b/src/Compat.hs
@@ -30,8 +30,14 @@
readInt :: String -> Int
readInt = read
+readDouble :: String -> Double
+readDouble = read
+
showInt :: Int -> String
showInt = show
+
+showDouble :: Double -> String
+showDouble = show
showChar :: Char -> String
showChar = show
--- a/src/MicroHs/Expr.hs
+++ b/src/MicroHs/Expr.hs
@@ -107,7 +107,7 @@
eqCon (ConLit l) (ConLit k) = eqLit l k
eqCon _ _ = False
-data Lit = LInt Int | LChar Char | LStr String | LPrim String
+data Lit = LInt Int | LDouble Double | LChar Char | LStr String | LPrim String
--Xderiving (Show, Eq)
eqLit :: Lit -> Lit -> Bool
@@ -358,6 +358,9 @@
showLit l =
case l of
LInt i -> showInt i
+ LDouble d -> case showDouble d of
+ '-':xs -> '-':'f':xs
+ xs -> 'f':xs
LChar c -> showChar c
LStr s -> showString s
LPrim s -> '$':s
--- a/src/MicroHs/Lex.hs
+++ b/src/MicroHs/Lex.hs
@@ -14,6 +14,7 @@
| TString Loc String
| TChar Loc Char
| TInt Loc Int
+ | TDouble Loc Double
| TSpec Loc Char
| TError Loc String
| TBrace Loc
@@ -25,6 +26,7 @@
showToken (TString _ s) = showString s
showToken (TChar _ c) = showChar c
showToken (TInt _ i) = showInt i
+showToken (TDouble _ d) = showDouble d
showToken (TSpec _ c) = [c]
showToken (TError _ s) = "ERROR " ++ s
showToken (TBrace _) = "TBrace"
@@ -72,6 +74,7 @@
--take 10 .
lex (mkLoc 1 1)
+-- | Take a location and string and produce a list of tokens
lex :: Loc -> String -> [Token]
lex loc (' ':cs) = lex (addCol loc 1) cs lex loc ('\n':cs) = tIndent (lex (incrLine loc) cs)@@ -89,10 +92,14 @@
lex loc cs@(d:_) | isUpper d = upperIdent loc loc [] cs
lex loc ('-':d:cs) | isDigit d =case span isDigit cs of
- (ds, rs) -> TInt loc (readInt ('-':d:ds)) : lex (addCol loc $ 2 + length ds) rs+ (ds, rs) | null rs || not (eqChar (head rs) '.') -> TInt loc (readInt ('-':d:ds)) : lex (addCol loc $ 2 + length ds) rs+ | otherwise -> case span isDigit (tail rs) of
+ (ns, rs') -> TDouble loc (readDouble ('-':d:ds ++ '.':ns)) : lex (addCol loc $ 3 + length ds + length ns) rs'lex loc (d:cs) | isDigit d =
case span isDigit cs of
- (ds, rs) -> TInt loc (readInt (d:ds)) : lex (addCol loc $ 1 + length ds) rs
+ (ds, rs) | null rs || not (eqChar (head rs) '.') -> TInt loc (readInt (d:ds)) : lex (addCol loc $ 1 + length ds) rs
+ | otherwise -> case span isDigit (tail rs) of
+ (ns, rs') -> TDouble loc (readDouble (d:ds ++ '.':ns)) : lex (addCol loc $ 2 + length ds + length ns) rs'
lex loc (d:cs) | isOperChar d =
case span isOperChar cs of
(ds, rs) -> TIdent loc [] (d:ds) : lex (addCol loc $ 1 + length ds) rs
@@ -122,6 +129,9 @@
skipLine loc (_:cs) = skipLine loc cs
skipLine _ [] = []
+-- | Takes a list of tokens and produces a list of tokens. If the first token in
+-- the input list is a TIndent, the input is returned unaltered. Otherwise, a
+-- TIndent is prepended to the input list
tIndent :: [Token] -> [Token]
tIndent ts@(TIndent _ : _) = ts
tIndent ts = TIndent (tokensLoc ts) : ts
@@ -178,6 +188,7 @@
tokensLoc (TString loc _ :_) = loc
tokensLoc (TChar loc _ :_) = loc
tokensLoc (TInt loc _ :_) = loc
+tokensLoc (TDouble loc _ : _) = loc
tokensLoc (TSpec loc _ :_) = loc
tokensLoc (TError loc _ :_) = loc
tokensLoc (TBrace loc :_) = loc
@@ -184,6 +195,7 @@
tokensLoc (TIndent loc :_) = loc
tokensLoc [] = mkLoc 0 1
+-- | This appears to be the magical layout resolver, I wondered where it was...
layout :: [Int] -> [Token] -> [Token]
layout mms@(m : ms) tts@(TIndent x : ts) | n == m = TSpec (tokensLoc ts) ';' : layout mms ts
| n < m = TSpec (tokensLoc ts) '}' : layout ms tts where {n = getCol x}--- a/src/MicroHs/Parse.hs
+++ b/src/MicroHs/Parse.hs
@@ -194,6 +194,7 @@
is (TString (l, c) s) = Just (ELit (SLoc fn l c) (LStr s))
is (TChar (l, c) a) = Just (ELit (SLoc fn l c) (LChar a))
is (TInt (l, c) i) = Just (ELit (SLoc fn l c) (LInt i))
+ is (TDouble (l, c) d) = Just (ELit (SLoc fn l c) (LDouble d))
is _ = Nothing
satisfyM "literal" is
--- a/src/MicroHs/TypeCheck.hs
+++ b/src/MicroHs/TypeCheck.hs
@@ -273,6 +273,7 @@
[(mkIdent "IO", [entry "Primitives.IO" kTypeTypeS]),
(mkIdent "->", [entry "Primitives.->" kTypeTypeTypeS]),
(mkIdent "Int", [entry "Primitives.Int" kTypeS]),
+ (mkIdent "Double", [entry "Primitives.Double" kTypeS]),
(mkIdent "Word", [entry "Primitives.Word" kTypeS]),
(mkIdent "Char", [entry "Primitives.Char" kTypeS]),
(mkIdent "Handle", [entry "Primitives.Handle" kTypeS]),
@@ -850,6 +851,7 @@
let { lit t = T.do { munify loc mt t; T.return (ELit loc l, t) } } incase l of
LInt _ -> lit (tConI "Primitives.Int")
+ LDouble _ -> lit (tConI "Primitives.Double")
LChar _ -> lit (tConI "Primitives.Char")
LStr _ -> lit (tApps (mkIdent "Data.List.[]") [tConI "Primitives.Char"])
LPrim _ -> T.do
--- a/src/PrimTable.hs
+++ b/src/PrimTable.hs
@@ -30,6 +30,9 @@
, arith "quot" quot
, arith "rem" rem
, arith "subtract" subtract
+ , farith "fadd" (+)
+ , farith "fsub" (-)
+ , farith "fmul" (*)
, cmp "==" (==)
, cmp "/=" (/=)
, cmp "<" (<)
@@ -52,6 +55,8 @@
comb n f = (n, unsafeCoerce f)
arith :: String -> (Int -> Int -> Int) -> (String, Any)
arith = comb
+ farith :: String -> (Double -> Double -> Double) -> (String, Any)
+ farith = comb
cmp :: String -> (Int -> Int -> Bool) -> (String, Any)
cmp n f = comb n (\ x y -> if f x y then cTrue else cFalse)
cTrue _x y = y
--- a/src/Text/ParserComb.hs
+++ b/src/Text/ParserComb.hs
@@ -49,6 +49,7 @@
data Res s t a = Many [(a, ([t], s))] (LastFail t)
--deriving (Show)
+-- |
data Prsr s t a = P (([t], s) -> Res s t a)
--instance Show (Prsr s t a) where show _ = "<<Prsr>>"
--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -82,9 +82,11 @@
#define ERR(s) do { fprintf(stderr, "ERR: %s\n", s); exit(1); } while(0)-enum node_tag { T_FREE, T_IND, T_AP, T_INT, T_HDL, T_S, T_K, T_I, T_B, T_C,+enum node_tag { T_FREE, T_IND, T_AP, T_INT, T_DOUBLE, T_HDL, T_S, T_K, T_I, T_B, T_C,T_A, T_Y, T_SS, T_BB, T_CC, T_P, T_O, T_T, T_BK, T_ADD, T_SUB, T_MUL,
T_QUOT, T_REM, T_SUBR, T_UQUOT, T_UREM,
+ T_FADD, T_FSUB, T_FMUL,
+ T_FEQ, T_FNE, T_FLT, T_FLE, T_FGT, T_FGE, T_FSHOW,
T_EQ, T_NE, T_LT, T_LE, T_GT, T_GE, T_ULT, T_ULE, T_UGT, T_UGE,
T_ERROR, T_SEQ,
T_IO_BIND, T_IO_THEN, T_IO_RETURN, T_IO_GETCHAR, T_IO_PUTCHAR,
@@ -120,7 +122,9 @@
#define GETTAG(p) (p)->tag
#define SETTAG(p, t) do { (p)->tag = (t); } while(0)#define GETVALUE(p) (p)->u.value
+#define GETDOUBLEVALUE(p,d) do { memcpy(&d, &((p)->u.value), 8); } while(0)#define SETVALUE(p,v) (p)->u.value = v
+#define SETDOUBLEVALUE(p,v) do { memcpy(&((p)->u.value), &v, 8); } while(0)#define FUN(p) (p)->u.s.fun
#define ARG(p) (p)->u.s.arg
#define NEXT(p) FUN(p)
@@ -151,7 +155,9 @@
#define GETTAG(p) ((p)->ufun.uutag & 1 ? (int)((p)->ufun.uutag >> 1) : T_AP)
#define SETTAG(p,t) do { if (t != T_AP) (p)->ufun.uutag = ((t) << 1) + 1; } while(0)#define GETVALUE(p) (p)->uarg.uuvalue
+#define GETDOUBLEVALUE(p, d) do { memcpy(&d, &((p)->uarg.uuvalue), 8); } while(0)#define SETVALUE(p,v) (p)->uarg.uuvalue = v
+#define SETDOUBLEVALUE(p,v) do { memcpy(&((p)->uarg.uuvalue), &v, 8); } while(0)#define FUN(p) (p)->ufun.uufun
#define ARG(p) (p)->uarg.uuarg
#define STR(p) (p)->uarg.uustring
@@ -362,6 +368,16 @@
{ "uquot", T_UQUOT }, { "urem", T_UREM }, { "subtract", T_SUBR },+ { "fadd" , T_FADD},+ { "fsub" , T_FSUB},+ { "fmul" , T_FMUL},+ {"feq", T_FEQ},+ {"fne", T_FNE},+ {"flt", T_FLT},+ {"fle", T_FLE},+ {"fgt", T_FGT},+ {"fge", T_FGE},+ {"fshow", T_FSHOW}, { "==", T_EQ }, { "/=", T_NE }, { "<", T_LT },@@ -628,6 +644,42 @@
return i;
}
+double
+parse_double(BFILE *f)
+{+ // apparently longest float, when rendered, takes up 24 characters
+ // I expect Lennart will hate this...
+ char floatstr[24];
+ int i = 0;
+ for(;;) {+ int c = getb(f);
+// printf("%d\n", c);+ if (c < '0' || c > '9') {+ ungetb(c, f);
+ break;
+ }
+ floatstr[i++] = c;
+ }
+ int c = getb(f);
+ if(c != '.') {+ ERR("can not parse double");+ }
+ floatstr[i++] = '.';
+
+ for(;;) {+ int c = getb(f);
+ if(c < '0' || c > '9') {+ ungetb(c, f);
+ break;
+ }
+ floatstr[i++] = c;
+ }
+
+ floatstr[i++] = '\0';
+ double d = strtod(floatstr, NULL);
+ return d;
+}
+
NODEPTR
mkStrNode(const char *str)
{@@ -637,6 +689,7 @@
}
NODEPTR mkInt(int64_t i);
+NODEPTR mkDouble(double d);
/* Table of labelled nodes for sharing during parsing. */
struct shared_entry {@@ -673,6 +726,7 @@
NODEPTR *nodep;
int64_t l;
value_t i;
+ double d;
value_t neg;
int c;
char buf[80]; /* store names of primitives. */
@@ -686,6 +740,9 @@
FUN(r) = parse(f);
if (!gobble(f, ' ')) ERR("parse ' '");ARG(r) = parse(f);
+ c = getb(f);
+// printf("got %c\n", c);+ ungetb(c, f);
if (!gobble(f, ')')) ERR("parse ')'");return r;
case '-':
@@ -693,9 +750,21 @@
if ('0' <= c && c <= '9') {neg = -1;
goto number;
+ } else if (c == 'f') {+ neg = -1;
+ goto flabel; // this stuff is cursed, I am not as much of a hacker as Lennart
} else { ERR("got -");}
+ case 'f':
+ flabel:
+ c = getb(f);
+ if('0' <= c && c <= '9') {+ neg = 1;
+ goto floatingnumber;
+ } else {+ ERR("got f");+ }
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
/* integer [0-9]+*/
neg = 1;
@@ -703,8 +772,17 @@
ungetb(c, f);
i = neg * parse_int(f);
r = mkInt(i);
+// printf("%ld\n", i);return r;
+ floatingnumber:
+ ungetb(c, f);
+ d = neg * parse_double(f);
+ r = mkDouble(d);
+// printf("%f\n", d);+ return r;
+ /* somewhere here, add case for doubles */
case '$':
+// printf("$\n");/* A primitive, keep getting char's until end */
for (int j = 0;;) {c = getb(f);
@@ -715,6 +793,7 @@
}
buf[j++] = c;
}
+// printf("%s\n", buf);/* Look up the primop and use the preallocated node. */
for (int j = 0; j < sizeof primops / sizeof primops[0]; j++) { if (strcmp(primops[j].name, buf) == 0) {@@ -938,6 +1017,11 @@
fputc(')', f);break;
case T_INT: fprintf(f, "%"PRIu64, GETVALUE(n)); break;
+ case T_DOUBLE:
+ double d;
+ GETDOUBLEVALUE(n, d);
+ fprintf(f, "%f", d);
+ break;
case T_STR:
{const char *p = STR(n);
@@ -983,6 +1067,16 @@
case T_UQUOT: fprintf(f, "$uquot"); break;
case T_UREM: fprintf(f, "$urem"); break;
case T_SUBR: fprintf(f, "$subtract"); break;
+ case T_FADD: fprintf(f, "$fadd"); break;
+ case T_FSUB: fprintf(f, "$fsub"); break;
+ case T_FMUL: fprintf(f, "$fmul"); break;
+ case T_FEQ: fprintf(f, "$feq"); break;
+ case T_FNE: fprintf(f, "$fne"); break;
+ case T_FLT: fprintf(f, "$flt"); break;
+ case T_FLE: fprintf(f, "$fle"); break;
+ case T_FGT: fprintf(f, "$fgt"); break;
+ case T_FGE: fprintf(f, "$fge"); break;
+ case T_FSHOW: fprintf(f, "$fshow"); break;
case T_EQ: fprintf(f, "$=="); break;
case T_NE: fprintf(f, "$/="); break;
case T_LT: fprintf(f, "$<"); break;
@@ -1056,6 +1150,15 @@
return n;
}
+NODEPTR
+mkDouble(double d)
+{+ NODEPTR n;
+ n = alloc_node(T_DOUBLE);
+ SETDOUBLEVALUE(n, d);
+ return n;
+}
+
static inline NODEPTR
mkNil(void)
{@@ -1114,6 +1217,18 @@
return n;
}
+static inline NODEPTR
+evald(NODEPTR n)
+{+ PUSH(n);
+ eval(n);
+ n = TOP(0);
+ POP(1);
+ while (GETTAG(n) == T_IND)
+ n = INDIR(n);
+ return n;
+}
+
/* Follow indirections */
static inline NODEPTR
indir(NODEPTR n)
@@ -1137,6 +1252,22 @@
return GETVALUE(n);
}
+/* Evaluate to a Double */
+static inline double
+evaldouble(NODEPTR n)
+{+ n = evald(n);
+ #if SANITY
+ if (GETTAG(n) != T_DOUBLE) {+ fprintf(stderr, "bad tag %d\n", GETTAG(n));
+ ERR("evaldouble");+ }
+ #endif
+ double d;
+ GETDOUBLEVALUE(n, d);
+ return d;
+}
+
/* Evaluate to a T_HDL */
FILE *
evalhandleN(NODEPTR n)
@@ -1205,7 +1336,9 @@
int64_t stk = stack_ptr;
NODEPTR x, y, z, w;
value_t xi, yi;
+ double xd, yd;
value_t r;
+ double rd;
FILE *hdl;
char *msg;
int64_t l;
@@ -1234,14 +1367,20 @@
/* Alloc a possible GC action, e, between setting x and popping */
#define CHKARGEV1(e) do { CHECK(1); x = ARG(TOP(0)); e; POP(1); n = TOP(-1); } while(0)-#define SETINT(n,r) do { SETTAG((n), T_INT); SETVALUE((n), (r)); } while(0)-#define OPINT2(e) do { CHECK(2); xi = evalint(ARG(TOP(0))); yi = evalint(ARG(TOP(1))); e; POP(2); n = TOP(-1); } while(0);-#define ARITHBIN(op) do { OPINT2(r = xi op yi); SETINT(n, r); RET; } while(0)-#define ARITHBINU(op) do { OPINT2(r = (int64_t)((uint64_t)xi op (uint64_t)yi)); SETINT(n, r); RET; } while(0)-#define CMP(op) do { OPINT2(r = xi op yi); GOIND(r ? comTrue : combFalse); } while(0)-#define CMPU(op) do { OPINT2(r = (uint64_t)xi op (uint64_t)yi); GOIND(r ? comTrue : combFalse); } while(0)+#define SETINT(n,r) do { SETTAG((n), T_INT); SETVALUE((n), (r)); } while(0)+#define SETSTRING(n,r) do { SETTAG((n), T_STR); SETVALUE((n), (r)); } while(0)+#define SETDOUBLE(n,d) do { SETTAG((n), T_DOUBLE); SETDOUBLEVALUE((n), (d)); } while(0)+#define OPINT2(e) do { CHECK(2); xi = evalint(ARG(TOP(0))); yi = evalint(ARG(TOP(1))); e; POP(2); n = TOP(-1); } while(0);+#define OPDOUBLE2(e) do { CHECK(2); xd = evaldouble(ARG(TOP(0))); yd = evaldouble(ARG(TOP(1))); e; POP(2); n = TOP(-1); } while(0);+#define ARITHBIN(op) do { OPINT2(r = xi op yi); SETINT(n, r); RET; } while(0)+#define ARITHBINU(op) do { OPINT2(r = (int64_t)((uint64_t)xi op (uint64_t)yi)); SETINT(n, r); RET; } while(0)+#define FARITHBIN(op) do { OPDOUBLE2(rd = xd op yd); SETDOUBLE(n, rd); RET; } while(0) // TODO FIXME+#define CMP(op) do { OPINT2(r = xi op yi); GOIND(r ? comTrue : combFalse); } while(0)+#define CMPF(op) do { OPDOUBLE2(r = xd op yd); GOIND(r ? comTrue : combFalse); } while(0)+#define CMPU(op) do { OPINT2(r = (uint64_t)xi op (uint64_t)yi); GOIND(r ? comTrue : combFalse); } while(0) for(;;) {+ printf("eval %d\n", GETTAG(n));num_reductions++;
#if FASTTAGS
l = LABEL(n);
@@ -1268,6 +1407,7 @@
case T_STR: GCCHECK(strNodes(strlen(STR(n)))); GOIND(mkStringC(STR(n)));
case T_INT: RET;
+ case T_DOUBLE: RET;
case T_HDL: RET;
case T_S: GCCHECK(2); CHKARG3; GOAP(new_ap(x, z), new_ap(y, z)); /* S x y z = x z (y z) */
@@ -1291,6 +1431,37 @@
case T_QUOT: ARITHBIN(/);
case T_REM: ARITHBIN(%);
case T_SUBR: OPINT2(r = yi - xi); SETINT(n, r); RET;
+ case T_FADD: FARITHBIN(+);
+ case T_FSUB: FARITHBIN(-);
+ case T_FMUL: FARITHBIN(*);
+ case T_FEQ: CMPF(==);
+ case T_FNE: CMPF(!=);
+ case T_FLT: CMPF(<);
+ case T_FLE: CMPF(<=);
+ case T_FGT: CMPF(>);
+ case T_FGE: CMPF(>=);
+ case T_FSHOW:
+ // check that the double exists
+ CHECK(1);
+
+ // evaluate it, I have verified that it is properly evaluated
+ xd = evaldouble(ARG(TOP(0)));
+
+ // turn it into a string, which I have also verified does what it is supposed to
+ char str[25];
+ memset(str, 0, 25);
+ snprintf(str, 25, "%f", xd);
+ NODEPTR s = mkStringC(str);
+
+ // remove the double from the stack
+ POP(1);
+ n = TOP(-1);
+
+ // make the node point to the new string
+ SETIND(n,s);
+
+ // return
+ RET;
case T_UQUOT: ARITHBINU(/);
case T_UREM: ARITHBINU(%);
@@ -1355,6 +1526,7 @@
n = evali(n);
PUSH(n);
for(;;) {+ printf("evalio %d\n", GETTAG(n));num_reductions++;
switch (GETTAG(n)) {case T_IND:
--
⑨