diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | arith.c | 20 | ||||
-rw-r--r-- | parser.l | 14 | ||||
-rw-r--r-- | stream.c | 53 |
4 files changed, 71 insertions, 31 deletions
@@ -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. @@ -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); } } @@ -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 @@ -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); |