diff --git a/src/Makefile b/src/Makefile index 630babf33c619..83ee89755d801 100644 --- a/src/Makefile +++ b/src/Makefile @@ -417,6 +417,10 @@ self: $(CFG_RUSTC) # Testing ###################################################################### +# Float doesn't work in boot + +FLOAT_XFAILS := test/run-pass/float.rs + # Temporarily xfail tests broken by the nominal-tags change. NOMINAL_TAG_XFAILS := test/run-pass/mlist.rs @@ -441,6 +445,7 @@ TASK_XFAILS := test/run-pass/task-comm-8.rs \ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ $(NOMINAL_TAG_XFAILS) \ $(CONST_TAG_XFAILS) \ + $(FLOAT_XFAILS) \ test/run-pass/arith-unsigned.rs \ test/run-pass/box-compare.rs \ test/run-pass/child-outlives-parent.rs \ diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index a007e76b058e0..fb2e1bfd041bb 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -255,6 +255,7 @@ tag lit_ { lit_int(int); lit_uint(uint); lit_mach_int(ty_mach, int); + lit_float(str); /* represent float as string for now */ lit_nil; lit_bool(bool); } @@ -274,6 +275,7 @@ tag ty_ { ty_bool; ty_int; ty_uint; + ty_float; ty_machine(util.common.ty_mach); ty_char; ty_str; diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 403558e29344a..56269cc223668 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -1,5 +1,6 @@ import std.io; import std._str; +import std._int; import std.map; import std.map.hashmap; import util.common; @@ -314,6 +315,24 @@ impure fn consume_block_comment(reader rdr) { be consume_any_whitespace(rdr); } +impure fn scan_dec_digits(reader rdr) -> int { + + auto c = rdr.curr(); + + let int accum_int = 0; + + while (is_dec_digit(c) || c == '_') { + if (c != '_') { + accum_int *= 10; + accum_int += dec_digit_val(c); + } + rdr.bump(); + c = rdr.curr(); + } + + ret accum_int; +} + impure fn scan_number(mutable char c, reader rdr) -> token.token { auto accum_int = 0; auto n = rdr.next(); @@ -346,15 +365,12 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token { } } - while (is_dec_digit(c) || c == '_') { - if (c != '_') { - accum_int *= 10; - accum_int += dec_digit_val(c); - } - rdr.bump(); - c = rdr.curr(); + if (c != '0' || (n != 'x' && n != 'b')) { + accum_int = scan_dec_digits(rdr); } + c = rdr.curr(); + if (c == 'u' || c == 'i') { let bool signed = (c == 'i'); rdr.bump(); @@ -405,7 +421,18 @@ impure fn scan_number(mutable char c, reader rdr) -> token.token { ret token.LIT_UINT(accum_int as uint); } } - ret token.LIT_INT(accum_int); + n = rdr.curr(); + if(n == '.') { + /* 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)); + /* TODO: exponent */ + } + else { + ret token.LIT_INT(accum_int); + } } impure fn next_token(reader rdr) -> token.token { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 9d3724f9de1f3..f1f8a91887f14 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -537,6 +537,10 @@ impure fn parse_lit(parser p) -> ast.lit { p.bump(); lit = ast.lit_uint(u); } + case (token.LIT_FLOAT(?s)) { + p.bump(); + lit = ast.lit_float(s); + } case (token.LIT_MACH_INT(?tm, ?i)) { p.bump(); lit = ast.lit_mach_int(tm, i); diff --git a/src/comp/front/token.rs b/src/comp/front/token.rs index 62c6406a6b8b6..767d7f65e3b96 100644 --- a/src/comp/front/token.rs +++ b/src/comp/front/token.rs @@ -126,6 +126,7 @@ tag token { LIT_INT(int); LIT_UINT(uint); LIT_MACH_INT(ty_mach, int); + LIT_FLOAT(str); /* represent floating-point as string for now */ LIT_STR(str); LIT_CHAR(char); LIT_BOOL(bool); @@ -295,7 +296,7 @@ fn to_str(token t) -> str { ret _int.to_str(i, 10u) + "_" + ty_mach_to_str(tm); } - + case (LIT_FLOAT(?s)) { ret s; } case (LIT_STR(?s)) { // FIXME: escape. ret "\"" + s + "\""; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c6cd1ab4b122b..ab9feb770f391 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -590,6 +590,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { case (ty.ty_nil) { llty = T_nil(); } case (ty.ty_bool) { llty = T_bool(); } case (ty.ty_int) { llty = T_int(); } + case (ty.ty_float) { llty = T_f64(); } case (ty.ty_uint) { llty = T_int(); } case (ty.ty_machine(?tm)) { alt (tm) { @@ -743,6 +744,12 @@ fn C_integral(int i, TypeRef t) -> ValueRef { ret llvm.LLVMConstIntOfString(t, _str.buf(istr(i)), 10); } +fn C_float(str s) -> ValueRef { + // FIXME: shouldn't use strings + // also, assuming 64-bit floats for now. + ret llvm.LLVMConstRealOfString(T_f64(), _str.buf(s)); +} + fn C_nil() -> ValueRef { // NB: See comment above in T_void(). ret C_integral(0, T_i1()); @@ -871,7 +878,7 @@ fn trans_upcall2(builder b, @glue_fns glues, let ValueRef llglue = glues.upcall_glues.(n); let vec[ValueRef] call_args = vec(llupcall); - + for (ValueRef a in args) { call_args += vec(b.ZExtOrBitCast(a, T_int())); } @@ -2279,6 +2286,9 @@ fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef { } ret C_integral(i, t); } + case(ast.lit_float(?fs)) { + ret C_float(fs); + } case (ast.lit_char(?c)) { ret C_integral(c as int, T_char()); } @@ -2346,6 +2356,7 @@ fn trans_unary(@block_ctxt cx, ast.unop op, @ast.expr e, &ast.ann a) -> result { auto sub = trans_expr(cx, e); + auto e_ty = ty.expr_ty(e); alt (op) { case (ast.bitnot) { @@ -2358,7 +2369,12 @@ fn trans_unary(@block_ctxt cx, ast.unop op, } case (ast.neg) { sub = autoderef(sub.bcx, sub.val, ty.expr_ty(e)); - ret res(sub.bcx, sub.bcx.build.Neg(sub.val)); + if(e_ty.struct == ty.ty_float) { + ret res(sub.bcx, sub.bcx.build.FNeg(sub.val)); + } + else { + ret res(sub.bcx, sub.bcx.build.Neg(sub.val)); + } } case (ast.box) { auto e_ty = ty.expr_ty(e); @@ -2653,17 +2669,50 @@ fn trans_vec_add(@block_ctxt cx, @ty.t t, fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> result { + auto is_float = false; + alt(intype.struct) { + case (ty.ty_float) { + is_float = true; + } + case (_) { + is_float = false; + } + } + alt (op) { case (ast.add) { if (ty.type_is_sequence(intype)) { ret trans_vec_add(cx, intype, lhs, rhs); } - ret res(cx, cx.build.Add(lhs, rhs)); + if (is_float) { + ret res(cx, cx.build.FAdd(lhs, rhs)); + } + else { + ret res(cx, cx.build.Add(lhs, rhs)); + } + } + case (ast.sub) { + if (is_float) { + ret res(cx, cx.build.FSub(lhs, rhs)); + } + else { + ret res(cx, cx.build.Sub(lhs, rhs)); + } + } + + case (ast.mul) { + if (is_float) { + ret res(cx, cx.build.FMul(lhs, rhs)); + } + else { + ret res(cx, cx.build.Mul(lhs, rhs)); + } } - case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); } - case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); } case (ast.div) { + if (is_float) { + ret res(cx, cx.build.FDiv(lhs, rhs)); + } if (ty.type_is_signed(intype)) { ret res(cx, cx.build.SDiv(lhs, rhs)); } else { @@ -2671,6 +2720,9 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, } } case (ast.rem) { + if (is_float) { + ret res(cx, cx.build.FRem(lhs, rhs)); + } if (ty.type_is_signed(intype)) { ret res(cx, cx.build.SRem(lhs, rhs)); } else { @@ -4465,6 +4517,17 @@ 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 sub1 = (sub.bcx).build.Alloca(T_double()); /* guess we're assuming double = float64 for now */ + (sub.bcx).build.Store(sub.val, sub1); + sub.val = sub1; + } + case(_) { + sub = trans_expr(cx, e); + } + } + alt (e_ty.struct) { case (ty.ty_str) { auto v = vp2i(sub.bcx, sub.val); @@ -4472,6 +4535,12 @@ 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", @@ -6238,7 +6307,6 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, collect_items(cx, crate); collect_tag_ctors(cx, crate); trans_constants(cx, crate); - trans_mod(cx, crate.node.module); trans_vec_append_glue(cx); if (!shared) { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index c6fbb5bf14db4..4d11fbd1f8cfe 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -32,6 +32,7 @@ tag sty { ty_nil; ty_bool; ty_int; + ty_float; ty_uint; ty_machine(util.common.ty_mach); ty_char; @@ -158,19 +159,20 @@ fn ty_to_str(&@t typ) -> str { auto s = ""; alt (typ.struct) { - case (ty_native) { s += "native"; } - case (ty_nil) { s += "()"; } - case (ty_bool) { s += "bool"; } - case (ty_int) { s += "int"; } - case (ty_uint) { s += "uint"; } - case (ty_machine(?tm)) { s += common.ty_mach_to_str(tm); } - case (ty_char) { s += "char"; } - case (ty_str) { s += "str"; } + case (ty_native) { s = "native"; } + case (ty_nil) { s = "()"; } + case (ty_bool) { s = "bool"; } + case (ty_int) { s = "int"; } + case (ty_float) { s = "float"; } + case (ty_uint) { s = "uint"; } + case (ty_machine(?tm)) { s = common.ty_mach_to_str(tm); } + case (ty_char) { s = "char"; } + case (ty_str) { s = "str"; } case (ty_box(?tm)) { s += "@" + mt_to_str(tm); } case (ty_vec(?tm)) { s += "vec[" + mt_to_str(tm) + "]"; } - case (ty_port(?t)) { s += "port[" + ty_to_str(t) + "]"; } - case (ty_chan(?t)) { s += "chan[" + ty_to_str(t) + "]"; } - case (ty_type) { s += "type"; } + case (ty_port(?t)) { s = "port[" + ty_to_str(t) + "]"; } + case (ty_chan(?t)) { s = "chan[" + ty_to_str(t) + "]"; } + case (ty_type) { s = "type"; } case (ty_tup(?elems)) { auto f = mt_to_str; @@ -243,6 +245,7 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { case (ty_bool) { ret fld.fold_simple_ty(ty); } case (ty_int) { ret fld.fold_simple_ty(ty); } case (ty_uint) { ret fld.fold_simple_ty(ty); } + case (ty_float) { ret fld.fold_simple_ty(ty); } case (ty_machine(_)) { ret fld.fold_simple_ty(ty); } case (ty_char) { ret fld.fold_simple_ty(ty); } case (ty_str) { ret fld.fold_simple_ty(ty); } @@ -418,6 +421,7 @@ fn type_is_scalar(@t ty) -> bool { case (ty_nil) { ret true; } case (ty_bool) { ret true; } case (ty_int) { ret true; } + case (ty_float) { ret true; } case (ty_uint) { ret true; } case (ty_machine(_)) { ret true; } case (ty_char) { ret true; } @@ -500,6 +504,9 @@ fn type_is_fp(@t ty) -> bool { case (_) { ret false; } } } + case (ty_float) { + ret true; + } case (_) { ret false; } } fail; @@ -1123,6 +1130,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) case (ty.ty_int) { ret struct_cmp(expected, actual); } case (ty.ty_uint) { ret struct_cmp(expected, actual); } case (ty.ty_machine(_)) { ret struct_cmp(expected, actual); } + case (ty.ty_float) { ret struct_cmp(expected, actual); } case (ty.ty_char) { ret struct_cmp(expected, actual); } case (ty.ty_str) { ret struct_cmp(expected, actual); } case (ty.ty_type) { ret struct_cmp(expected, actual); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index e4eaf2fb97a68..c849483e8addd 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1493,6 +1493,7 @@ 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_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/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index 7863f3e7b9afe..0e30ced131da6 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -283,6 +283,9 @@ impure fn print_literal(ps s, @ast.lit lit) { case (ast.lit_uint(?val)) { // TODO clipping? uistr? wrd(s, util.common.istr(val as int) + "u"); } + case (ast.lit_float(?fstr)) { + wrd(s, fstr); + } case (ast.lit_mach_int(?mach,?val)) { wrd(s, util.common.istr(val as int)); wrd(s, util.common.ty_mach_to_str(mach)); diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 7f1a7a03ebcf6..d8a07de4fc911 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -46,6 +46,7 @@ auth middle.metadata = unsafe; auth middle.trans = unsafe; auth middle.trans.copy_args_to_allocas = impure; auth middle.trans.trans_block = impure; +auth middle.trans.trans_log = impure; auth lib.llvm = unsafe; auth pretty.pprust = impure; diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 1dba11024f417..1ffb8285ebff4 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -39,6 +39,13 @@ void upcall_log_int(rust_task *task, int32_t i) { "rust: %" PRId32 " (0x%" PRIx32 ")", i, i); } +extern "C" CDECL +void upcall_log_float(rust_task *task, int32_t f) { + LOG_UPCALL_ENTRY(task); + task->log(rust_log::UPCALL | rust_log::ULOG, + "rust: %12.12f", *((double*)f)); +} + extern "C" CDECL void upcall_log_str(rust_task *task, rust_str *str) { LOG_UPCALL_ENTRY(task); diff --git a/src/test/run-pass/float.rs b/src/test/run-pass/float.rs new file mode 100644 index 0000000000000..d91de117da1bd --- /dev/null +++ b/src/test/run-pass/float.rs @@ -0,0 +1,8 @@ +fn main() { + auto pi = 3.1415927; + + log(-pi * (pi + (2.0/pi)) - (pi * 5.0)); + if(pi == 5.0 || pi < 10.0 || pi <= 2.0 || pi != 22.0/7.0 || pi >= 10.0 || pi > 1.0) { + log("yes"); + } +} \ No newline at end of file