summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--arith.c20
-rw-r--r--parser.l14
-rw-r--r--stream.c53
4 files changed, 71 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index 2fe03180..160c1eb5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2012-03-21 Kaz Kylheku <kaz@kylheku.com>
+ * arith.c (neg): Floating-point support.
+
+ * parser.l: FLO and FLODOT cases had to be reordered because
+ the lex trailing context counts as part of the match length,
+ causing 3.0 to be matched as three characters with 0 as
+ the trailing context. The cases are split up to eliminate
+ a flex warning.
+
+ * stream.c (vformat): Support bignum in floating point
+ conversion. Bugfixes: floating point conversion was
+ accessing obj->fl.n instead of using n.
+ Changed some if/else ladders to switches.
+
+2012-03-21 Kaz Kylheku <kaz@kylheku.com>
+
* arith.c (plus): Minor code simplification.
(minus): Floating point support.
diff --git a/arith.c b/arith.c
index f2f033ea..838d39dd 100644
--- a/arith.c
+++ b/arith.c
@@ -490,13 +490,19 @@ tail:
val neg(val anum)
{
- if (bignump(anum)) {
- val n = make_bignum();
- mp_neg(mp(anum), mp(n));
- return n;
- } else {
- cnum n = c_num(anum);
- return num(-n);
+ switch (type(anum)) {
+ case BGNUM:
+ {
+ val n = make_bignum();
+ mp_neg(mp(anum), mp(n));
+ return n;
+ }
+ case FLNUM:
+ return flo(-c_flo(anum));
+ case NUM:
+ return num(-c_num(anum));
+ default:
+ uw_throwf(error_s, lit("neg: ~s is not a number"), anum, nao);
}
}
diff --git a/parser.l b/parser.l
index 449cc148..7e07f79f 100644
--- a/parser.l
+++ b/parser.l
@@ -194,8 +194,18 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}
return NUMBER;
}
-<SPECIAL,NESTED,BRACED>{FLODOT}/[^.] |
-<SPECIAL,NESTED,BRACED>{FLO} {
+<SPECIAL,NESTED,BRACED>{FLO} {
+ val str = string_own(utf8_dup_from(yytext));
+
+ if (yy_top_state() == INITIAL
+ || yy_top_state() == QSILIT)
+ yy_pop_state();
+
+ yylval.val = flo_str(str);
+ return NUMBER;
+}
+
+<SPECIAL,NESTED,BRACED>{FLODOT}/[^.] {
val str = string_own(utf8_dup_from(yytext));
if (yy_top_state() == INITIAL
diff --git a/stream.c b/stream.c
index f9b1eb25..6110e1d6 100644
--- a/stream.c
+++ b/stream.c
@@ -1122,18 +1122,21 @@ val vformat(val stream, val fmtstr, va_list vl)
{
double n;
- if (bignump(obj))
- uw_throwf(error_s, lit("format: ~s: bignum to float "
- "conversion unsupported\n"), obj, nao);
-
- if (fixnump(obj))
+ switch (type(obj)) {
+ case BGNUM:
+ obj = flo_int(obj);
+ /* fallthrough */
+ case FLNUM:
+ n = c_flo(obj);
+ break;
+ case NUM:
n = (double) c_num(obj);
- else if (floatp(obj))
- n = obj->fl.n;
- else
+ break;
+ default:
uw_throwf(error_s, lit("format: ~~~a conversion requires "
"numeric arg: ~s given\n"),
chr(ch), obj, nao);
+ }
/* guard against num_buf overflow */
if (precision > 128)
@@ -1141,9 +1144,9 @@ val vformat(val stream, val fmtstr, va_list vl)
num(precision), nao);
if (ch == 'e')
- sprintf(num_buf, "%.*e", precision, obj->fl.n);
+ sprintf(num_buf, "%.*e", precision, n);
else
- sprintf(num_buf, "%.*f", precision, obj->fl.n);
+ sprintf(num_buf, "%.*f", precision, n);
precision = 0;
goto output_num;
}
@@ -1151,17 +1154,20 @@ val vformat(val stream, val fmtstr, va_list vl)
obj = va_arg(vl, val);
if (obj == nao)
goto premature;
- if (fixnump(obj)) {
+ switch (type(obj)) {
+ case NUM:
value = c_num(obj);
sprintf(num_buf, num_fmt->dec, value);
goto output_num;
- } else if (bignump(obj)) {
- int nchars = mp_radix_size(mp(obj), 10);
- if (nchars >= (int) sizeof (num_buf))
- pnum = (char *) chk_malloc(nchars + 1);
- mp_toradix(mp(obj), (unsigned char *) pnum, 10);
+ case BGNUM:
+ {
+ int nchars = mp_radix_size(mp(obj), 10);
+ if (nchars >= (int) sizeof (num_buf))
+ pnum = (char *) chk_malloc(nchars + 1);
+ mp_toradix(mp(obj), (unsigned char *) pnum, 10);
+ }
goto output_num;
- } else if (floatp(obj)) {
+ case FLNUM:
sprintf(num_buf, "%g", obj->fl.n);
if (!precision) {
@@ -1180,11 +1186,14 @@ val vformat(val stream, val fmtstr, va_list vl)
precision = 0;
}
goto output_num;
- } else if (width != 0) {
- val str = format(nil, ch == 'a' ? lit("~a") : lit("~s"), obj, nao);
- if (!vformat_str(stream, str, width, left, precision))
- return nil;
- continue;
+ default:
+ if (width != 0) {
+ val str = format(nil, ch == 'a' ? lit("~a") : lit("~s"),
+ obj, nao);
+ if (!vformat_str(stream, str, width, left, precision))
+ return nil;
+ continue;
+ }
}
if (ch == 'a')
obj_pprint(obj, stream);