diff --git a/src/std/std.zr b/src/std/std.zr index 8871ad6..016123e 100644 --- a/src/std/std.zr +++ b/src/std/std.zr @@ -249,6 +249,9 @@ func io.printf[..] : void else if s[0] == 'c' io.print_char(_var_arg(i) as u8) i += 1 + else if s[0] == 'f' + io.print_f64(_var_arg(i) as i64) + i += 1 else if s[0] == '%' io.print_char('%') else if s[0] == 0 @@ -293,6 +296,87 @@ func io.println_i64[x: i64] : void x->to_str_buf(s) io.println(s as str) +// TODO: fix when we implement f64 params +func io.print_f64[x: i64] : void + s := _stackalloc(64) + f64.to_str_buf(x, s) + io.print(s as str) + +func f64.to_str_buf[x: i64, buf: ptr] : void + bits := x + sign := (bits >> 63) & 1 + exp := (bits >> 52) & 0x7ff + mant := bits & 0x000fffffffffffff + + if exp == 0x7ff + if mant == 0 + if sign + mem.copy("-inf" as ptr, buf, 5) + else + mem.copy("inf" as ptr, buf, 4) + else + mem.copy("nan" as ptr, buf, 4) + return + + p := 0 + if sign + buf[p] = '-' + p += 1 + bits = bits & 0x7fffffffffffffff + + if exp == 0 && mant == 0 + buf[p] = '0' + buf[p+1] = '.' + buf[p+2] = '0' + buf[p+3] = 0 + return + + sig := mant + if exp != 0 + sig = sig | 0x0010000000000000 + + shift := exp - 1075 + + if shift >= 0 + (sig << shift)->to_str_buf(buf + p) + while buf[p] + p += 1 + buf[p] = '.' + buf[p+1] = '0' + buf[p+2] = 0 + return + + ns := -shift + + if ns <= 52 + int_part := sig >> ns + int_part->to_str_buf(buf + p) + while buf[p] + p += 1 + else + buf[p] = '0' + p += 1 + + buf[p] = '.' + p += 1 + + mask := (1 << ns) - 1 + frac := sig & mask + + for i in 0..6 + if frac == 0 + if i > 0 + break + buf[p] = '0' + p += 1 + break + frac = frac * 10 + digit := frac >> ns + buf[p] = '0' + digit as u8 + p += 1 + frac = frac & mask + buf[p] = 0 + func io.read_char[] : u8 c := 0 as u8 _builtin_syscall(SYS_read, STDIN, ^c, 1) @@ -394,7 +478,7 @@ func str.format_into[..] : i64 i := 3 n := 0 - tmp := _stackalloc(21) as str + tmp := _stackalloc(64) as str while s[0] if s[0] == '%' @@ -426,6 +510,14 @@ func str.format_into[..] : i64 buf[n] = _var_arg(i) as u8 n += 1 i += 1 + else if s[0] == 'f' + // TODO: fix when we implement f64 params + f64.to_str_buf(_var_arg(i), tmp as ptr) + tmp_len := tmp->len() + remaining := size - n - 1 + mem.copy(tmp as ptr, buf + n, math.min(tmp_len, remaining)) + n += tmp_len + i += 1 else if s[0] == '%' if n < size - 1 buf[n] = '%' @@ -1080,7 +1172,6 @@ func os.time[] : i64 out := tv->tv_sec * 1000 + tv->tv_usec / 1000 return out -// voodoo magic func os.run_shell_command[command: str] : i64, bool pid := _builtin_syscall(SYS_fork) if pid < 0 diff --git a/src/typechecker.rs b/src/typechecker.rs index caea63e..5c51c25 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -300,9 +300,6 @@ impl<'a> TypeChecker<'a> { "unrecognized type: ".to_owned() + &return_type ); } - if return_type == "f64" { - return error!(&return_types[0].loc, "returning f64 not implemented yet"); - } self.current_function_return_type = return_type.clone(); @@ -559,13 +556,13 @@ impl<'a> TypeChecker<'a> { Ok(field.field_type.clone()) } ExprKind::Cast { expr, type_name } => { - if type_name.lexeme == "f64" { + let expr_type = self.typecheck_expr(env, expr)?; + if expr_type != "any" && type_name.lexeme == "f64" { return error!( &type_name.loc, - "use _builtin_cvtsi2sd and _builtin_cvttsd2si to cast to f64" + "use _builtin_cvtsi2sd and _builtin_cvttsd2si to cast between integers and f64" ); } - self.typecheck_expr(env, expr)?; if !self.is_valid_type_name(&type_name.lexeme) { return error!( &type_name.loc,