aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Chevalier <[email protected]>2011-03-24 17:12:24 -0700
committerTim Chevalier <[email protected]>2011-03-25 11:20:30 -0700
commita47cd50dfb9b8d88abea0baf4122e454d82e09e9 (patch)
tree0a6d53f38d5ef5fc32d4cb78ec125606cd2b328e
parentrustc: Store cached crate metadata in the session (diff)
downloadrust-a47cd50dfb9b8d88abea0baf4122e454d82e09e9.tar.xz
rust-a47cd50dfb9b8d88abea0baf4122e454d82e09e9.zip
Parse FP literals without coercing to int. This allows parsing 64-bit
floats. However, if someone writes a literal that can't be represented precisely in 64 bits, the front-end will accept it while the back-end will (presumably) complain.
-rw-r--r--Makefile.in6
-rw-r--r--src/comp/front/lexer.rs95
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/run-pass/floatlits.rs8
4 files changed, 71 insertions, 39 deletions
diff --git a/Makefile.in b/Makefile.in
index e2cf9f34..fd8d8b52 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -572,7 +572,8 @@ docsnap: doc/rust.pdf
FLOAT_XFAILS := $(S)src/test/run-pass/float.rs \
$(S)src/test/run-pass/float2.rs \
- $(S)src/test/run-pass/float-signature.rs
+ $(S)src/test/run-pass/float-signature.rs \
+ $(S)src/test/run-pass/floatlits.rs
# Temporarily xfail tests broken by the nominal-tags change.
@@ -641,8 +642,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
writing-through-read-alias.rs) \
$(S)src/test/bench/shootout/nbody.rs
-TEST_XFAILS_STAGE0 := $(FLOAT_XFAILS) \
- $(addprefix $(S)src/test/run-pass/, \
+TEST_XFAILS_STAGE0 := $(addprefix $(S)src/test/run-pass/, \
acyclic-unwind.rs \
alt-pattern-drop.rs \
alt-type-simple.rs \
diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs
index 791276a7..6975d9c5 100644
--- a/src/comp/front/lexer.rs
+++ b/src/comp/front/lexer.rs
@@ -318,47 +318,65 @@ impure fn consume_block_comment(reader rdr) {
be consume_any_whitespace(rdr);
}
-impure fn scan_dec_digits(reader rdr) -> int {
-
- auto c = rdr.curr();
+fn digits_to_string(str s) -> int {
let int accum_int = 0;
+ let int i = 0;
- while (is_dec_digit(c) || c == '_') {
- if (c != '_') {
- accum_int *= 10;
- accum_int += dec_digit_val(c);
- }
- rdr.bump();
- c = rdr.curr();
+ for (u8 c in s) {
+ accum_int *= 10;
+ accum_int += dec_digit_val(c as char);
}
ret accum_int;
}
-impure fn scan_exponent(reader rdr) -> option.t[int] {
+impure fn scan_exponent(reader rdr) -> option.t[str] {
auto c = rdr.curr();
- auto sign = 1;
+ auto res = "";
if (c == 'e' || c == 'E') {
+ res += _str.from_bytes(vec(c as u8));
rdr.bump();
c = rdr.curr();
- if (c == '-') {
- sign = -1;
- rdr.bump();
- } else if (c == '+') {
+ if (c == '-' || c == '+') {
+ res += _str.from_bytes(vec(c as u8));
rdr.bump();
}
auto exponent = scan_dec_digits(rdr);
- ret(some(sign * exponent));
+ if (_str.byte_len(exponent) > 0u) {
+ ret(some(res + exponent));
+ }
+ else {
+ log ("scan_exponent: bad fp literal");
+ fail;
+ }
}
else {
- ret none[int];
+ ret none[str];
}
}
+impure fn scan_dec_digits(reader rdr) -> str {
+
+ auto c = rdr.curr();
+ let str res = "";
+
+ while (is_dec_digit (c) || c == '_') {
+ if (c != '_') {
+ res += _str.from_bytes(vec(c as u8));
+ }
+ rdr.bump();
+ c = rdr.curr();
+ }
+
+ ret res;
+}
+
impure fn scan_number(mutable char c, reader rdr) -> token.token {
auto accum_int = 0;
+ let str dec_str = "";
+ let bool is_dec_integer = false;
auto n = rdr.next();
if (c == '0' && n == 'x') {
@@ -386,7 +404,12 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token {
c = rdr.curr();
}
} else {
- accum_int = scan_dec_digits(rdr);
+ dec_str = scan_dec_digits(rdr);
+ is_dec_integer = true;
+ }
+
+ if (is_dec_integer) {
+ accum_int = digits_to_string(dec_str);
}
c = rdr.curr();
@@ -443,20 +466,19 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token {
}
}
c = rdr.curr();
+
if (c == '.') {
// Parse a floating-point number.
rdr.bump();
- auto accum_int1 = scan_dec_digits(rdr);
- auto base_str = _int.to_str(accum_int, 10u) + "."
- + _int.to_str(accum_int1, 10u);
+ auto dec_part = scan_dec_digits(rdr);
+ auto float_str = dec_str + "." + dec_part;
c = rdr.curr();
- auto exponent_str = "";
- let option.t[int] maybe_exponent = scan_exponent(rdr);
- alt(maybe_exponent) {
- case(some[int](?i)) {
- exponent_str = "e" + _int.to_str(i, 10u);
+ auto exponent_str = scan_exponent(rdr);
+ alt (exponent_str) {
+ case (some[str](?s)) {
+ float_str += s;
}
- case(none[int]) {
+ case (none[str]) {
}
}
@@ -468,27 +490,28 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token {
if (c == '3' && n == '2') {
rdr.bump(); rdr.bump();
ret token.LIT_MACH_FLOAT(util.common.ty_f32,
- base_str + exponent_str);
+ float_str);
}
else if (c == '6' && n == '4') {
rdr.bump(); rdr.bump();
ret token.LIT_MACH_FLOAT(util.common.ty_f64,
- base_str + exponent_str);
+ float_str);
+ /* FIXME: if this is out of range for either a 32-bit or
+ 64-bit float, it won't be noticed till the back-end */
}
}
else {
- ret token.LIT_FLOAT(base_str + exponent_str);
+ ret token.LIT_FLOAT(float_str);
}
}
auto maybe_exponent = scan_exponent(rdr);
alt(maybe_exponent) {
- case(some[int](?i)) {
- ret token.LIT_FLOAT(_int.to_str(accum_int, 10u)
- + "e" + _int.to_str(i, 10u));
+ case(some[str](?s)) {
+ ret token.LIT_FLOAT(dec_str + s);
}
- case(none[int]) {
- ret token.LIT_INT(accum_int);
+ case(none[str]) {
+ ret token.LIT_INT(accum_int);
}
}
}
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 5f9300f7..cf10a402 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -44,6 +44,7 @@ upcall_grow_task
upcall_join
upcall_kill
upcall_log_double
+upcall_log_float
upcall_log_int
upcall_log_str
upcall_malloc
diff --git a/src/test/run-pass/floatlits.rs b/src/test/run-pass/floatlits.rs
new file mode 100644
index 00000000..db82b486
--- /dev/null
+++ b/src/test/run-pass/floatlits.rs
@@ -0,0 +1,8 @@
+fn main() {
+ auto f = 4.999999999999;
+ check (f > 4.90);
+ check (f < 5.0);
+ auto g = 4.90000000001e-10;
+ check(g > 5e-11);
+ check(g < 5e-9);
+} \ No newline at end of file