aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-05 19:49:31 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-05 19:49:31 +0800
commita6574b0025b68eb28a8c7d679ca6783132ad013d (patch)
tree09f8e9976e209c9e7bf48556e8d90f211c1b3464
parent5dba94ed1eec7a808cab022a23480b4d39518307 (diff)
complex, real, rational, integral number support
-rw-r--r--builtin.cpp425
-rw-r--r--builtin.h151
-rw-r--r--consts.cpp5
-rw-r--r--consts.h5
-rw-r--r--eval.cpp3
-rw-r--r--exc.cpp12
-rw-r--r--exc.h11
-rw-r--r--model.cpp16
-rw-r--r--model.h43
-rw-r--r--parser.cpp23
-rw-r--r--parser.h2
11 files changed, 526 insertions, 170 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 79ecdfb..6c58d96 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -1,46 +1,356 @@
#include "exc.h"
#include "consts.h"
#include "builtin.h"
+#include "model.h"
+#include "exc.h"
#include <cstdio>
#include <sstream>
+#include <cctype>
+#include <cstdlib>
using std::stringstream;
extern EmptyList *empty_list;
+static const int NUM_LVL_COMP = 0;
+static const int NUM_LVL_REAL = 1;
+static const int NUM_LVL_RAT = 2;
+static const int NUM_LVL_INT = 3;
-BoolObj::BoolObj(bool _val) : EvalObj(), val(_val) {}
-
-bool BoolObj::is_true() { return val; }
-
-string BoolObj::ext_repr() { return string(val ? "#t" : "#f"); }
-
-#ifdef DEBUG
-string BoolObj::_debug_repr() { return ext_repr(); }
-#endif
-
-IntObj::IntObj(int _val) : NumberObj(), val(_val) {}
-string IntObj::ext_repr() {
+string double_to_str(double val, bool force_sign = false) {
stringstream ss;
+ if (force_sign) ss << std::showpos;
ss << val;
return ss.str();
}
-#ifdef DEBUG
-string IntObj::_debug_repr() { return ext_repr(); }
-#endif
-
-FloatObj::FloatObj(double _val) : NumberObj(), val(_val) {}
-
-string FloatObj::ext_repr() {
+string int_to_str(int val) {
stringstream ss;
ss << val;
return ss.str();
}
-#ifdef DEBUG
-string FloatObj::_debug_repr() { return ext_repr(); }
-#endif
+double str_to_double(string repr, bool &flag) {
+ const char *nptr = repr.c_str();
+ char *endptr;
+ double val = strtod(nptr, &endptr);
+ if (endptr != nptr + repr.length())
+ {
+ flag = false;
+ return 0;
+ }
+ flag = true;
+ return val;
+}
+
+int gcd(int a, int b) {
+ int t;
+ while (b) t = b, b = a % b, a = t;
+ return a;
+}
+
+
+InexactNumObj::InexactNumObj(NumLvl level) : NumObj(level, false) {}
+
+CompNumObj::CompNumObj(double _real, double _imag) :
+ InexactNumObj(NUM_LVL_COMP), real(_real), imag(_imag) {}
+
+CompNumObj *CompNumObj::from_string(string repr) {
+ // spos: the position of the last sign
+ // ipos: the position of i
+ int spos = -1, ipos = -1,
+ len = repr.length();
+ bool sign;
+ for (int i = 0; i < len; i++)
+ if (repr[i] == '+' || repr[i] == '-')
+ {
+ spos = i;
+ sign = repr[i] == '-';
+ }
+ else if (repr[i] == 'i' || repr[i] == 'I')
+ ipos = i;
+
+ if (spos == -1 || ipos == -1 || !(spos < ipos))
+ return NULL;
+
+ bool flag;
+ double real = 0, imag = 1;
+ if (spos > 0)
+ {
+ real = str_to_double(repr.substr(0, spos), flag);
+ if (!flag) return NULL;
+ }
+ if (ipos > spos + 1)
+ {
+ imag = str_to_double(repr.substr(spos + 1, ipos - spos - 1), flag);
+ if (!flag) return NULL;
+ }
+ if (sign) imag = -imag;
+ return new CompNumObj(real, imag);
+}
+
+CompNumObj *CompNumObj::convert(NumObj *obj) {
+ switch (obj->level)
+ {
+ case NUM_LVL_COMP :
+ return static_cast<CompNumObj*>(obj); break;
+ case NUM_LVL_REAL :
+ return new CompNumObj(static_cast<RealNumObj*>(obj)->real, 0);
+ break;
+ case NUM_LVL_RAT :
+ {
+ RatNumObj *rat = static_cast<RatNumObj*>(obj);
+ return new CompNumObj(rat->a / double(rat->b), 0);
+ break;
+ }
+ case NUM_LVL_INT :
+ return new CompNumObj(static_cast<IntNumObj*>(obj)->val, 0);
+ }
+ throw NormalError(INT_ERR);
+}
+
+#define A (real)
+#define B (imag)
+#define C (r->real)
+#define D (r->imag)
+
+NumObj *CompNumObj::plus(NumObj *_r) {
+ CompNumObj *r = CompNumObj::convert(_r);
+ return new CompNumObj(A + C, B + D);
+}
+
+NumObj *CompNumObj::minus(NumObj *_r) {
+ CompNumObj *r = CompNumObj::convert(_r);
+ return new CompNumObj(A - C, B - D);
+}
+
+NumObj *CompNumObj::multi(NumObj *_r) {
+ CompNumObj *r = CompNumObj::convert(_r);
+ return new CompNumObj(A * C - B * D,
+ B * C + A * D);
+}
+
+NumObj *CompNumObj::div(NumObj *_r) {
+ CompNumObj *r = CompNumObj::convert(_r);
+ double f = 1.0 / (C * C + D * D);
+ return new CompNumObj((A * C + B * D) * f,
+ (B * C - A * D) * f);
+}
+
+BoolObj *CompNumObj::eq(NumObj *_r) {
+ CompNumObj *r = CompNumObj::convert(_r);
+ return new BoolObj(A == C && B == D); // TODO: more proper judgement
+}
+
+string CompNumObj::ext_repr() {
+ return double_to_str(real) + double_to_str(imag, true) + "i";
+}
+
+#undef A
+#undef B
+#undef C
+#undef D
+
+RealNumObj::RealNumObj(double _real) : InexactNumObj(NUM_LVL_REAL), real(_real) {}
+
+RealNumObj *RealNumObj::from_string(string repr) {
+ bool flag;
+ double real = str_to_double(repr, flag);
+ if (!flag) return NULL;
+ return new RealNumObj(real);
+}
+
+RealNumObj *RealNumObj::convert(NumObj *obj) {
+ switch (obj->level)
+ {
+ case NUM_LVL_REAL:
+ return static_cast<RealNumObj*>(obj); break;
+ case NUM_LVL_RAT:
+ {
+ RatNumObj *rat = static_cast<RatNumObj*>(obj);
+ return new RealNumObj(rat->a / double(rat->b));
+ break;
+ }
+ case NUM_LVL_INT:
+ return new RealNumObj(static_cast<IntNumObj*>(obj)->val);
+ }
+ throw NormalError(INT_ERR);
+}
+
+NumObj *RealNumObj::plus(NumObj *_r) {
+ return new RealNumObj(real + RealNumObj::convert(_r)->real);
+}
+
+NumObj *RealNumObj::minus(NumObj *_r) {
+ return new RealNumObj(real - RealNumObj::convert(_r)->real);
+}
+
+NumObj *RealNumObj::multi(NumObj *_r) {
+ return new RealNumObj(real * RealNumObj::convert(_r)->real);
+}
+
+NumObj *RealNumObj::div(NumObj *_r) {
+ return new RealNumObj(real / RealNumObj::convert(_r)->real);
+}
+
+BoolObj *RealNumObj::eq(NumObj *_r) {
+ return new BoolObj(real == RealNumObj::convert(_r)->real);
+}
+
+BoolObj *RealNumObj::lt(NumObj *_r) {
+ return new BoolObj(real < RealNumObj::convert(_r)->real);
+}
+
+BoolObj *RealNumObj::gt(NumObj *_r) {
+ return new BoolObj(real > RealNumObj::convert(_r)->real);
+}
+
+string RealNumObj::ext_repr() {
+ return double_to_str(real);
+}
+
+ExactNumObj::ExactNumObj(NumLvl level) : NumObj(level, false) {}
+
+RatNumObj::RatNumObj(int _a, int _b) :
+ ExactNumObj(NUM_LVL_RAT), a(_a), b(_b) {
+ int g = gcd(a, b);
+ a /= g;
+ b /= g;
+}
+
+RatNumObj *RatNumObj::from_string(string repr) {
+ int a, b;
+ if (sscanf(repr.c_str(), "%d/%d", &a, &b) != 2)
+ return NULL;
+ return new RatNumObj(a, b);
+}
+
+RatNumObj *RatNumObj::convert(NumObj *obj) {
+ switch (obj->level)
+ {
+ case NUM_LVL_RAT:
+ return static_cast<RatNumObj*>(obj); break;
+ case NUM_LVL_INT:
+ return new RatNumObj(static_cast<IntNumObj*>(obj)->val, 1);
+ }
+ throw NormalError(INT_ERR);
+}
+
+#define A (a)
+#define B (b)
+#define C (r->a)
+#define D (r->b)
+
+NumObj *RatNumObj::plus(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ int na = A * D + B * C, nb = B * D;
+ int g = gcd(na, nb);
+ na /= g;
+ nb /= g;
+ return new RatNumObj(na, nb);
+}
+
+NumObj *RatNumObj::minus(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ int na = A * D - B * C, nb = B * D;
+ int g = gcd(na, nb);
+ na /= g;
+ nb /= g;
+ return new RatNumObj(na, nb);
+}
+
+NumObj *RatNumObj::multi(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ int na = A * C, nb = B * D;
+ int g = gcd(na, nb);
+ na /= g;
+ nb /= g;
+ return new RatNumObj(na, nb);
+}
+
+NumObj *RatNumObj::div(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ int na = A * D, nb = B * C;
+ int g = gcd(na, nb);
+ na /= g;
+ nb /= g;
+ return new RatNumObj(na, nb);
+}
+
+BoolObj *RatNumObj::lt(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ return new BoolObj(A * D < C * B);
+}
+
+BoolObj *RatNumObj::gt(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ return new BoolObj(A * D > C * B);
+}
+
+BoolObj *RatNumObj::eq(NumObj *_r) {
+ RatNumObj *r = RatNumObj::convert(_r);
+ return new BoolObj(A * D == C * B);
+}
+
+string RatNumObj::ext_repr() {
+ return int_to_str(A) + "/" + int_to_str(B);
+}
+
+IntNumObj::IntNumObj(int _val) : ExactNumObj(NUM_LVL_INT), val(_val) {}
+
+IntNumObj *IntNumObj::from_string(string repr) {
+ int val = 0;
+ for (int i = 0; i < repr.length(); i++)
+ {
+ if (!('0' <= repr[i] && repr[i] <= '9'))
+ return NULL;
+ val = val * 10 + repr[i] - '0';
+ }
+ return new IntNumObj(val);
+}
+
+IntNumObj *IntNumObj::convert(NumObj *obj) {
+ switch (obj->level)
+ {
+ case NUM_LVL_INT :
+ return static_cast<IntNumObj*>(obj);
+ default:
+ throw NormalError(INT_ERR);
+ }
+}
+
+NumObj *IntNumObj::plus(NumObj *_r) {
+
+ return new IntNumObj(val + IntNumObj::convert(_r)->val);
+}
+
+NumObj *IntNumObj::minus(NumObj *_r) {
+ return new IntNumObj(val - IntNumObj::convert(_r)->val);
+}
+
+NumObj *IntNumObj::multi(NumObj *_r) {
+ return new IntNumObj(val * IntNumObj::convert(_r)->val);
+}
+
+NumObj *IntNumObj::div(NumObj *_r) {
+ return new IntNumObj(val / IntNumObj::convert(_r)->val);
+}
+
+BoolObj *IntNumObj::lt(NumObj *_r) {
+ return new BoolObj(val < IntNumObj::convert(_r)->val);
+}
+
+BoolObj *IntNumObj::gt(NumObj *_r) {
+ return new BoolObj(val > IntNumObj::convert(_r)->val);
+}
+
+BoolObj *IntNumObj::eq(NumObj *_r) {
+ return new BoolObj(val == IntNumObj::convert(_r)->val);
+}
+
+string IntNumObj::ext_repr() {
+ return int_to_str(val);
+}
SpecialOptIf::SpecialOptIf() : SpecialOptObj() {}
@@ -113,10 +423,6 @@ Cons *SpecialOptIf::call(ArgList *args, Environment * &envt,
string SpecialOptIf::ext_repr() { return string("#<Builtin Macro: if>"); }
-#ifdef DEBUG
-string SpecialOptIf::_debug_repr() { return ext_repr(); }
-#endif
-
SpecialOptLambda::SpecialOptLambda() : SpecialOptObj() {}
#define FILL_MARKS(pc, flag) \
for (Cons *ptr = TO_CONS(pc->cdr); \
@@ -155,10 +461,6 @@ Cons *SpecialOptLambda::call(ArgList *args, Environment * &envt,
string SpecialOptLambda::ext_repr() { return string("#<Builtin Macro: lambda>"); }
-#ifdef DEBUG
-string SpecialOptLambda::_debug_repr() { return ext_repr(); }
-#endif
-
SpecialOptDefine::SpecialOptDefine() : SpecialOptObj() {}
void SpecialOptDefine::prepare(Cons *pc) {
@@ -224,10 +526,6 @@ Cons *SpecialOptDefine::call(ArgList *args, Environment * &envt,
string SpecialOptDefine::ext_repr() { return string("#<Builtin Macro: define>"); }
-#ifdef DEBUG
-string SpecialOptDefine::_debug_repr() { return ext_repr(); }
-#endif
-
void SpecialOptSet::prepare(Cons *pc) {
pc = TO_CONS(pc->cdr);
if (pc == empty_list)
@@ -263,10 +561,6 @@ SpecialOptSet::SpecialOptSet() {}
string SpecialOptSet::ext_repr() { return string("#<Builtin Macro: set!>"); }
-#ifdef DEBUG
-string SpecialOptSet::_debug_repr() { return ext_repr(); }
-#endif
-
EvalObj *builtin_cons(ArgList *args) {
if (args == empty_list ||
args->cdr == empty_list ||
@@ -301,52 +595,21 @@ EvalObj *builtin_list(ArgList *args) {
}
EvalObj *builtin_plus(ArgList *args) {
- // TODO: type conversion and proper arithmetic
- int res = 0;
- for (Cons *ptr = args; ptr != empty_list; ptr = TO_CONS(ptr->cdr))
- res += dynamic_cast<IntObj*>(ptr->car)->val;
- return new IntObj(res);
-}
-
-EvalObj *builtin_minus(ArgList *args) {
- // TODO: type conversion and proper arithmetic
- int res = dynamic_cast<IntObj*>(args->car)->val;
- for (Cons *ptr = TO_CONS(args->cdr);
- ptr != empty_list; ptr = TO_CONS(ptr->cdr))
- res -= dynamic_cast<IntObj*>(ptr->car)->val;
- return new IntObj(res);
-}
-
-EvalObj *builtin_times(ArgList *args) {
- // TODO: type conversion and proper arithmetic
- int res = 1;
+ NumObj *res = new IntNumObj(0), *opr; // the most accurate type
for (Cons *ptr = args; ptr != empty_list; ptr = TO_CONS(ptr->cdr))
- res *= dynamic_cast<IntObj*>(ptr->car)->val;
- return new IntObj(res);
-}
-
-EvalObj *builtin_div(ArgList *args) {
- // TODO: type conversion and proper arithmetic
- int res = dynamic_cast<IntObj*>(args->car)->val;
- for (Cons *ptr = TO_CONS(args->cdr); ptr != empty_list; ptr = TO_CONS(ptr->cdr))
- res /= dynamic_cast<IntObj*>(ptr->car)->val;
- return new IntObj(res);
-}
-
-EvalObj *builtin_lt(ArgList *args) {
- return new BoolObj(dynamic_cast<IntObj*>(args->car)->val <
- dynamic_cast<IntObj*>(TO_CONS(args->cdr)->car)->val);
-}
-
-EvalObj *builtin_gt(ArgList *args) {
- return new BoolObj(dynamic_cast<IntObj*>(args->car)->val >
- dynamic_cast<IntObj*>(TO_CONS(args->cdr)->car)->val);
+ {
+ if (!ptr->car->is_num_obj()) // not a number
+ throw TokenError(ptr->car->ext_repr(), RUN_ERR_WRONG_TYPE);
+ opr = static_cast<NumObj*>(ptr->car);
+ if (res->level < opr->level)
+ // upper type conversion
+ res = res->plus(opr);
+ else
+ res = opr->plus(res);
+ }
+ return res;
}
-EvalObj *builtin_arithmetic_eq(ArgList *args) {
- return new BoolObj(dynamic_cast<IntObj*>(args->car)->val ==
- dynamic_cast<IntObj*>(TO_CONS(args->cdr)->car)->val);
-}
EvalObj *builtin_display(ArgList *args) {
printf("%s\n", args->car->ext_repr().c_str());
diff --git a/builtin.h b/builtin.h
index 997c0c6..b12e110 100644
--- a/builtin.h
+++ b/builtin.h
@@ -6,46 +6,122 @@
using std::string;
-/** @class BoolObj
- * Booleans
+
+
+/** @class InexactNumObj
+ * Inexact number implementation (using doubles)
*/
-class BoolObj: public EvalObj {
+class InexactNumObj: public NumObj {
public:
- bool val; /**< true for \#t, false for \#f */
- BoolObj(bool); /**< Converts a C bool value to a BoolObj*/
- bool is_true(); /**< Override EvalObj `is_true()` */
-#ifdef DEBUG
- string _debug_repr();
-#endif
+ InexactNumObj(NumLvl level);
+};
+
+/** @class CompNumObj
+ * Complex numbers
+ */
+class CompNumObj: public InexactNumObj {
+ public:
+ double real, imag;
+
+ /** Construct a complex number */
+ CompNumObj(double _real, double _imag);
+ /** Try to construct an RealNumObj object
+ * @return NULL if failed
+ */
+ static CompNumObj *from_string(string repr);
+ /** Convert to a complex number from other numeric types */
+ static CompNumObj *convert(NumObj* obj);
+
+ NumObj *plus(NumObj *r);
+ NumObj *minus(NumObj *r);
+ NumObj *multi(NumObj *r);
+ NumObj *div(NumObj *r);
+ BoolObj *eq(NumObj *r);
string ext_repr();
};
-/** @class IntObj
- * A simple implementation of integers
- * Will be removed in the future
+/** @class RealNumObj
+ * Real numbers
*/
-class IntObj: public NumberObj {
+class RealNumObj: public InexactNumObj {
public:
- int val; /**< Numeric value */
- /** Converts a C integer value to a FloatObj */
- IntObj(int);
-#ifdef DEBUG
- string _debug_repr();
-#endif
+ double real;
+ /** Construct a real number */
+ RealNumObj(double _real);
+ /** Try to construct an RealNumObj object
+ * @return NULL if failed
+ */
+ static RealNumObj *from_string(string repr);
+ /** Convert to a real number from other numeric types */
+ static RealNumObj *convert(NumObj* obj);
+
+ NumObj *plus(NumObj *r);
+ NumObj *minus(NumObj *r);
+ NumObj *multi(NumObj *r);
+ NumObj *div(NumObj *r);
+ BoolObj *lt(NumObj *r);
+ BoolObj *gt(NumObj *r);
+ BoolObj *eq(NumObj *r);
string ext_repr();
+
};
-/** @class FloatObj
- * Floating point numbers
+
+/** @class ExactNumObj
+ * Exact number implementation (using gmp)
*/
-class FloatObj: public NumberObj {
+class ExactNumObj: public NumObj {
public:
- double val; /**< Numeric value */
- /** Converts a C double value to a FloatObj */
- FloatObj(double);
-#ifdef DEBUG
- string _debug_repr();
-#endif
+ ExactNumObj(NumLvl level);
+};
+
+/** @class RatNumObj
+ * Rational numbers
+ */
+class RatNumObj: public ExactNumObj {
+ public:
+ int a, b;
+ /** Construct a rational number */
+ RatNumObj(int _a, int _b);
+ /** Try to construct an RealNumObj object
+ * @return NULL if failed
+ */
+ static RatNumObj *from_string(string repr);
+ /** Convert to a Rational number from other numeric types */
+ static RatNumObj *convert(NumObj* obj);
+
+ NumObj *plus(NumObj *r);
+ NumObj *minus(NumObj *r);
+ NumObj *multi(NumObj *r);
+ NumObj *div(NumObj *r);
+ BoolObj *lt(NumObj *r);
+ BoolObj *gt(NumObj *r);
+ BoolObj *eq(NumObj *r);
+ string ext_repr();
+};
+
+/** @class IntNumObj
+ * Integers
+ */
+class IntNumObj: public ExactNumObj {
+ public:
+ int val;
+ /** Construct a integer */
+ IntNumObj(int _val);
+ /** Try to construct an IntNumObj object
+ * @return NULL if failed
+ */
+ static IntNumObj *from_string(string repr);
+ /** Convert to a integer from other numeric types */
+ static IntNumObj *convert(NumObj* obj);
+
+ NumObj *plus(NumObj *r);
+ NumObj *minus(NumObj *r);
+ NumObj *multi(NumObj *r);
+ NumObj *div(NumObj *r);
+ BoolObj *lt(NumObj *r);
+ BoolObj *gt(NumObj *r);
+ BoolObj *eq(NumObj *r);
string ext_repr();
};
@@ -73,9 +149,6 @@ class SpecialOptIf: public SpecialOptObj {
void prepare(Cons *pc);
Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
-#ifdef DEBUG
- string _debug_repr();
-#endif
string ext_repr();
};
@@ -89,9 +162,6 @@ class SpecialOptLambda: public SpecialOptObj {
Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
-#ifdef DEBUG
- string _debug_repr();
-#endif
string ext_repr();
};
@@ -104,9 +174,6 @@ class SpecialOptDefine: public SpecialOptObj {
void prepare(Cons *pc);
Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
-#ifdef DEBUG
- string _debug_repr();
-#endif
string ext_repr();
};
@@ -119,19 +186,11 @@ class SpecialOptSet: public SpecialOptObj {
void prepare(Cons *pc);
Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
-#ifdef DEBUG
- string _debug_repr();
-#endif
string ext_repr();
};
EvalObj *builtin_plus(ArgList *);
-EvalObj *builtin_minus(ArgList *);
-EvalObj *builtin_times(ArgList *);
-EvalObj *builtin_div(ArgList *);
-EvalObj *builtin_lt(ArgList *);
-EvalObj *builtin_gt(ArgList *);
-EvalObj *builtin_arithmetic_eq(ArgList *);
+
EvalObj *builtin_display(ArgList *);
EvalObj *builtin_cons(ArgList *);
EvalObj *builtin_car(ArgList *);
diff --git a/consts.cpp b/consts.cpp
index ec3ed01..e41c981 100644
--- a/consts.cpp
+++ b/consts.cpp
@@ -1,6 +1,6 @@
#include "consts.h"
-const char *SYN_ERR_MSG[] = {
+const char *ERR_MSG[] = {
"\"%s\" is not an valid identifier",
"Cannot apply the operation \"%s\"",
"Unbound variable: \"%s\"",
@@ -9,5 +9,6 @@ const char *SYN_ERR_MSG[] = {
"Wrong number of arguments to procedure (%s)",
"Illegal empty combination ()",
"Unexpected \")\"",
- "Wrong type (expecting %s)"
+ "Wrong type (expecting %s)",
+ "Internal Error !!! File a bug please!"
};
diff --git a/consts.h b/consts.h
index 5991317..e88cd31 100644
--- a/consts.h
+++ b/consts.h
@@ -10,9 +10,10 @@ enum ErrCode {
RUN_ERR_WRONG_NUM_OF_ARGS,
SYN_ERR_EMPTY_COMB,
READ_ERR_UNEXPECTED_RIGHT_BRACKET,
- RUN_ERR_WRONG_TYPE
+ RUN_ERR_WRONG_TYPE,
+ INT_ERR
};
-extern const char *SYN_ERR_MSG[];
+extern const char *ERR_MSG[];
#endif
diff --git a/eval.cpp b/eval.cpp
index 56bd06c..d6aee3b 100644
--- a/eval.cpp
+++ b/eval.cpp
@@ -14,12 +14,13 @@ void Evaluator::add_builtin_routines() {
envt->add_binding(new SymObj(name), rout)
ADD_ENTRY("+", new BuiltinProcObj(builtin_plus, "+"));
- ADD_ENTRY("-", new BuiltinProcObj(builtin_minus, "-"));
+/* ADD_ENTRY("-", new BuiltinProcObj(builtin_minus, "-"));
ADD_ENTRY("*", new BuiltinProcObj(builtin_times, "*"));
ADD_ENTRY("/", new BuiltinProcObj(builtin_div, "/"));
ADD_ENTRY(">", new BuiltinProcObj(builtin_gt, ">"));
ADD_ENTRY("<", new BuiltinProcObj(builtin_lt, "<"));
ADD_ENTRY("=", new BuiltinProcObj(builtin_arithmetic_eq, "="));
+ */
ADD_ENTRY("display", new BuiltinProcObj(builtin_display, "display"));
ADD_ENTRY("cons", new BuiltinProcObj(builtin_cons, "cons"));
ADD_ENTRY("car", new BuiltinProcObj(builtin_car, "car"));
diff --git a/exc.cpp b/exc.cpp
index 648326e..167bf92 100644
--- a/exc.cpp
+++ b/exc.cpp
@@ -1,16 +1,16 @@
#include "exc.h"
#include <cstdio>
-SyntaxError::SyntaxError(ErrCode _code) : code(_code) {}
+GeneralError::GeneralError(ErrCode _code) : code(_code) {}
-string SyntaxError::get_msg() { return this->msg; }
+string GeneralError::get_msg() { return this->msg; }
-TokenError::TokenError(string token, ErrCode code) : SyntaxError(code) {
+TokenError::TokenError(string token, ErrCode code) : GeneralError(code) {
static char buffer[1024]; // should be enough
- sprintf(buffer, SYN_ERR_MSG[code], token.c_str());
+ sprintf(buffer, ERR_MSG[code], token.c_str());
msg = buffer;
}
-NormalError::NormalError(ErrCode code) : SyntaxError(code) {
- msg = SYN_ERR_MSG[code];
+NormalError::NormalError(ErrCode code) : GeneralError(code) {
+ msg = ERR_MSG[code];
}
diff --git a/exc.h b/exc.h
index 7a6879d..dc380d3 100644
--- a/exc.h
+++ b/exc.h
@@ -10,26 +10,21 @@ using std::string;
* The top-level exception
*/
class GeneralError {
- public:
- virtual string get_msg() = 0; /**< Extract error message */
-};
-
-class SyntaxError : public GeneralError {
protected:
string msg; /**< Error mesg */
ErrCode code; /**< Error code */
public:
- SyntaxError(ErrCode code); /**< Construct an SyntaxError */
+ GeneralError(ErrCode code); /**< Construct a General Error */
string get_msg(); /**< Get the error message */
};
-class TokenError : public SyntaxError {
+class TokenError : public GeneralError {
public:
TokenError(string token, ErrCode code); /**< Construct an TokenError */
};
-class NormalError : public SyntaxError {
+class NormalError : public GeneralError {
public:
NormalError(ErrCode code);
};
diff --git a/model.cpp b/model.cpp
index 83d5b79..34ea645 100644
--- a/model.cpp
+++ b/model.cpp
@@ -39,7 +39,14 @@ bool EvalObj::is_cons_obj() {
return otype & CLS_CONS_OBJ;
}
+bool EvalObj::is_num_obj() {
+ return otype & CLS_NUM_OBJ;
+}
+
#ifdef DEBUG
+string EvalObj::_debug_repr() {
+ return ext_repr();
+}
void EvalObj::_debug_print() {
printf("mem: 0x%llX\n%s\n\n", (unsigned long long)this,
_debug_repr().c_str());
@@ -143,7 +150,14 @@ string ProcObj::_debug_repr() { return ext_repr(); }
SpecialOptObj::SpecialOptObj() : OptObj() {}
-NumberObj::NumberObj() : EvalObj() {}
+BoolObj::BoolObj(bool _val) : EvalObj(), val(_val) {}
+
+bool BoolObj::is_true() { return val; }
+
+string BoolObj::ext_repr() { return string(val ? "#t" : "#f"); }
+
+NumObj::NumObj(NumLvl _level, bool _exactness) :
+ EvalObj(CLS_SIM_OBJ | CLS_NUM_OBJ), level(_level), exactness(_exactness) {}
BuiltinProcObj::BuiltinProcObj(BuiltinProc f, string _name) :
OptObj(), handler(f), name(_name) {}
diff --git a/model.h b/model.h
index a98a475..9795934 100644
--- a/model.h
+++ b/model.h
@@ -9,7 +9,9 @@ using std::list;
using std::string;
using std::map;
-typedef unsigned char ClassType; // that range is enough
+// the range of unsigned char is enough for these types
+typedef unsigned char ClassType;
+typedef unsigned char NumLvl;
static const int CLS_RET_ADDR = 1 << 0;
static const int CLS_EVAL_OBJ = 1 << 1;
@@ -18,6 +20,8 @@ static const int CLS_SIM_OBJ = 1 << 0;
static const int CLS_CONS_OBJ = 1 << 1;
static const int CLS_SYM_OBJ = 1 << 2;
static const int CLS_OPT_OBJ = 1 << 3;
+static const int CLS_NUM_OBJ = 1 << 4;
+
#define TO_CONS(ptr) \
(static_cast<Cons*>(ptr))
@@ -81,12 +85,15 @@ class EvalObj : public FrameObj {
bool is_opt_obj();
/** Check if the object is a Cons */
bool is_cons_obj();
+ /** Check if the object is a number */
+ bool is_num_obj();
virtual void prepare(Cons *pc);
/** Any EvalObj has its external representation */
virtual string ext_repr() = 0;
/** Always true for all EvalObjs except BoolObj */
virtual bool is_true();
#ifdef DEBUG
+ virtual string _debug_repr();
virtual void _debug_print();
#endif
};
@@ -243,13 +250,41 @@ class BuiltinProcObj: public OptObj {
string ext_repr();
};
-/** @class NumberObj
+/** @class BoolObj
+ * Booleans
+ */
+class BoolObj: public EvalObj {
+ public:
+ bool val; /**< true for \#t, false for \#f */
+ BoolObj(bool); /**< Converts a C bool value to a BoolObj*/
+ bool is_true(); /**< Override EvalObj `is_true()` */
+ string ext_repr();
+};
+
+/** @class NumObj
* The top level abstract of numbers
*/
-class NumberObj: public EvalObj {
+class NumObj: public EvalObj {
+ protected:
+ /** True if the number is of exact value */
+ bool exactness;
public:
- NumberObj();
+ /** The level of the specific number. The smaller the level
+ * is, the more generic that number is.
+ */
+ NumLvl level;
+
+ /**
+ * Construct a general Numeric object
+ */
+ NumObj(NumLvl level, bool _exactness);
+ bool is_exact();
+ virtual NumObj *plus(NumObj *r) = 0;
+ virtual NumObj *minus(NumObj *r) = 0;
+ virtual NumObj *multi(NumObj *r) = 0;
+ virtual NumObj *div(NumObj *r) = 0;
+ virtual BoolObj *eq(NumObj *r) = 0;
};
typedef map<string, EvalObj*> Str2EvalObj;
diff --git a/parser.cpp b/parser.cpp
index f4de5a2..499b832 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -64,28 +64,17 @@ bool Tokenizor::get_token(string &ret) {
}
ASTGenerator::ASTGenerator() {}
-EvalObj *ASTGenerator::to_float(const string &str) {
- stringstream ss(str);
- double val;
- ss >> val;
- if (ss.fail() || !ss.eof()) return NULL;
- return new FloatObj(val);
-}
-
-EvalObj *ASTGenerator::to_int(const string &str) {
- stringstream ss(str);
- int val;
- ss >> val;
- if (ss.fail() || !ss.eof()) return NULL;
- return new IntObj(val);
-}
EvalObj *ASTGenerator::to_obj(const string &str) {
EvalObj *res = NULL;
- if ((res = ASTGenerator::to_int(str)))
+ if ((res = IntNumObj::from_string(str)))
+ return res;
+ if ((res = RatNumObj::from_string(str)))
+ return res;
+ if ((res = RealNumObj::from_string(str)))
return res;
- if ((res = ASTGenerator::to_float(str)))
+ if ((res = CompNumObj::from_string(str)))
return res;
return new SymObj(str);
}
diff --git a/parser.h b/parser.h
index 5c427ee..fa00ccc 100644
--- a/parser.h
+++ b/parser.h
@@ -34,8 +34,6 @@ class Tokenizor {
*/
class ASTGenerator {
private:
- static EvalObj* to_float(const string &);
- static EvalObj* to_int(const string &);
/** Convert the string to an internal object */
static EvalObj* to_obj(const string &);
public: