From b40480ae70e940db081a9cba5a8f2c9cf0211f19 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Tue, 22 Mar 2011 15:33:43 -0700 Subject: [PATCH] Further support for floating-point. Literals with exponents work and literals with the 'f32' or 'f64' suffixes work as well. In addition, logging things with the f32 or f64 type works. (float is still assumed to be a synonym for f64). --- src/Makefile | 3 +- src/comp/front/ast.rs | 1 + src/comp/front/lexer.rs | 78 +++++++++++++++++++++++++++++++++---- src/comp/front/parser.rs | 4 ++ src/comp/front/token.rs | 1 + src/comp/middle/trans.rs | 49 +++++++++++++++++------ src/comp/middle/typeck.rs | 3 +- src/rt/rust_upcall.cpp | 9 ++++- src/test/run-pass/float2.rs | 23 +++++++++++ 9 files changed, 149 insertions(+), 22 deletions(-) create mode 100644 src/test/run-pass/float2.rs diff --git a/src/Makefile b/src/Makefile index bd084e0246e82..ccf7bb21508d6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -419,7 +419,8 @@ self: $(CFG_RUSTC) # Float doesn't work in boot -FLOAT_XFAILS := test/run-pass/float.rs +FLOAT_XFAILS := test/run-pass/float.rs \ + test/run-pass/float2.rs # Temporarily xfail tests broken by the nominal-tags change. diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index cdeea2418098a..d48792d117ea6 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -256,6 +256,7 @@ tag lit_ { lit_uint(uint); lit_mach_int(ty_mach, int); lit_float(str); + lit_mach_float(ty_mach, str); lit_nil; lit_bool(bool); } diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index d4948503d5964..b2c681b1754bf 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -3,6 +3,9 @@ import std._str; import std._int; import std.map; import std.map.hashmap; +import std.option; +import std.option.some; +import std.option.none; import util.common; import util.common.new_str_hash; @@ -333,6 +336,28 @@ impure fn scan_dec_digits(reader rdr) -> int { ret accum_int; } +impure fn scan_exponent(reader rdr) -> option.t[int] { + auto c = rdr.curr(); + auto sign = 1; + + if(c == 'e' || c == 'E') { + rdr.bump(); + c = rdr.curr(); + if(c == '-') { + sign = -1; + rdr.bump(); + } + else if(c == '+') { + rdr.bump(); + } + auto exponent = scan_dec_digits(rdr); + ret(some(sign * exponent)); + } + else { + ret none[int]; + } +} + impure fn scan_number(mutable char c, reader rdr) -> token.token { auto accum_int = 0; auto n = rdr.next(); @@ -364,7 +389,7 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token { } else { accum_int = scan_dec_digits(rdr); } - + c = rdr.curr(); n = rdr.next(); @@ -418,17 +443,54 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token { ret token.LIT_UINT(accum_int as uint); } } - n = rdr.curr(); - if(n == '.') { + c = rdr.curr(); + if(c == '.') { // Parse a floating-point number. rdr.bump(); auto accum_int1 = scan_dec_digits(rdr); - ret token.LIT_FLOAT(_int.to_str(accum_int, 10u) + "." - + _int.to_str(accum_int1, 10u)); - // FIXME: Parse exponent. + auto base_str = _int.to_str(accum_int, 10u) + "." + + _int.to_str(accum_int1, 10u); + 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); + } + case(none[int]) { + } + } + + c = rdr.curr(); + if(c == 'f') { + rdr.bump(); + c = rdr.curr(); + n = rdr.next(); + if(c == '3' && n == '2') { + rdr.bump(); rdr.bump(); + ret token.LIT_MACH_FLOAT(util.common.ty_f32, + base_str + exponent_str); + } + else if(c == '6' && n == '4') { + rdr.bump(); rdr.bump(); + ret token.LIT_MACH_FLOAT(util.common.ty_f64, + base_str + exponent_str); + } + } + else { + ret token.LIT_FLOAT(base_str + exponent_str); + } } - else { - ret token.LIT_INT(accum_int); + + 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(none[int]) { + ret token.LIT_INT(accum_int); + } } } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index f1f8a91887f14..9e13e706af4eb 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -545,6 +545,10 @@ impure fn parse_lit(parser p) -> ast.lit { p.bump(); lit = ast.lit_mach_int(tm, i); } + case (token.LIT_MACH_FLOAT(?tm, ?s)) { + p.bump(); + lit = ast.lit_mach_float(tm, s); + } case (token.LIT_CHAR(?c)) { p.bump(); lit = ast.lit_char(c); diff --git a/src/comp/front/token.rs b/src/comp/front/token.rs index a1fb1cd0174f7..46fd0735641f2 100644 --- a/src/comp/front/token.rs +++ b/src/comp/front/token.rs @@ -127,6 +127,7 @@ tag token { LIT_UINT(uint); LIT_MACH_INT(ty_mach, int); LIT_FLOAT(str); + LIT_MACH_FLOAT(ty_mach, str); LIT_STR(str); LIT_CHAR(char); LIT_BOOL(bool); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b75af85038686..ebae4844da174 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -763,6 +763,10 @@ fn C_float(str s) -> ValueRef { ret llvm.LLVMConstRealOfString(T_float(), _str.buf(s)); } +fn C_floating(str s, TypeRef t) -> ValueRef { + ret llvm.LLVMConstRealOfString(t, _str.buf(s)); +} + fn C_nil() -> ValueRef { // NB: See comment above in T_void(). ret C_integral(0, T_i1()); @@ -2338,6 +2342,14 @@ fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef { case(ast.lit_float(?fs)) { ret C_float(fs); } + case(ast.lit_mach_float(?tm, ?s)) { + auto t = T_float(); + alt(tm) { + case(common.ty_f32) { t = T_f32(); } + case(common.ty_f64) { t = T_f64(); } + } + ret C_floating(s, t); + } case (ast.lit_char(?c)) { ret C_integral(c as int, T_char()); } @@ -4582,13 +4594,34 @@ fn trans_log(@block_ctxt cx, @ast.expr e) -> result { auto sub = trans_expr(cx, e); auto e_ty = ty.expr_ty(e); - alt (e_ty.struct) { - case(ty.ty_float) { - auto tmp = sub.bcx.build.Alloca(T_float()); + if(ty.type_is_fp(e_ty)) { + let TypeRef tr; + let bool is32bit = false; + alt(e_ty.struct) { + case(ty.ty_machine(util.common.ty_f32)) { + tr = T_f32(); + is32bit = true; + } + case(ty.ty_machine(util.common.ty_f64)) { + tr = T_f64(); + } + case(_) { + tr = T_float(); + } + } + if(is32bit) { + ret trans_upcall(sub.bcx, + "upcall_log_float", + vec(sub.val)); + } + else { + auto tmp = sub.bcx.build.Alloca(tr); sub.bcx.build.Store(sub.val, tmp); - sub = res(sub.bcx, tmp); + auto v = vp2i(sub.bcx, tmp); + ret trans_upcall(sub.bcx, + "upcall_log_double", + vec(v)); } - case(_) { } } alt (e_ty.struct) { @@ -4598,12 +4631,6 @@ fn trans_log(@block_ctxt cx, @ast.expr e) -> result { "upcall_log_str", vec(v)); } - case (ty.ty_float) { - auto v = vp2i(sub.bcx, sub.val); - ret trans_upcall(sub.bcx, - "upcall_log_float", - vec(v)); - } case (_) { ret trans_upcall(sub.bcx, "upcall_log_int", diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index dbeeb8f903e50..6767d59d8bb29 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1497,7 +1497,8 @@ fn check_lit(@ast.lit lit) -> @ty.t { case (ast.lit_str(_)) { sty = ty.ty_str; } case (ast.lit_char(_)) { sty = ty.ty_char; } case (ast.lit_int(_)) { sty = ty.ty_int; } - case (ast.lit_float(_)) { sty = ty.ty_float; } + case (ast.lit_float(_)) { sty = ty.ty_float; } + case (ast.lit_mach_float(?tm, _)) { sty = ty.ty_machine(tm); } case (ast.lit_uint(_)) { sty = ty.ty_uint; } case (ast.lit_mach_int(?tm, _)) { sty = ty.ty_machine(tm); } case (ast.lit_nil) { sty = ty.ty_nil; } diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 30306104859c6..19f1ec9070d08 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -40,7 +40,14 @@ void upcall_log_int(rust_task *task, int32_t i) { } extern "C" CDECL -void upcall_log_float(rust_task *task, double *f) { +void upcall_log_float(rust_task *task, float f) { + LOG_UPCALL_ENTRY(task); + task->log(rust_log::UPCALL | rust_log::ULOG, + "rust: %12.12f", f); +} + +extern "C" CDECL +void upcall_log_double(rust_task *task, double *f) { LOG_UPCALL_ENTRY(task); task->log(rust_log::UPCALL | rust_log::ULOG, "rust: %12.12f", *f); diff --git a/src/test/run-pass/float2.rs b/src/test/run-pass/float2.rs new file mode 100644 index 0000000000000..0c111ba9779e8 --- /dev/null +++ b/src/test/run-pass/float2.rs @@ -0,0 +1,23 @@ +fn main() { + auto a = 1.5e6; + auto b = 1.5E6; + auto c = 1e6; + auto d = 1E6; + auto e = 3.0f32; + auto f = 5.9f64; + auto g = 1.e6f32; + auto h = 1.0e7f64; + auto i = 1.0E7f64; + auto j = 3.1e+9; + auto k = 3.2e-10; + + check(a == b); + check(c < b); + check(c == d); + check(e < g); + check(f < h); + check(g == 1000000.0f32); + check(h == i); + check(j > k); + check(k < a); +} \ No newline at end of file