Skip to content

Commit

Permalink
jule: add underscore support for numeric literals
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Jan 28, 2024
1 parent b6eee34 commit c52155a
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 92 deletions.
8 changes: 3 additions & 5 deletions std/conv/atob.jule
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,12 @@ pub fn conv_bool(s: str): (bool, ConvError) {
ret true, ConvError.Ok
| "0" | "f" | "F" | "false" | "FALSE" | "False":
ret false, ConvError.Ok
|:
ret false, ConvError.InvalidSyntax
}
ret false, ConvError.InvalidSyntax
}

// Returns "true" or "false" according to the value of b.
pub fn fmt_bool(b: bool): str {
if b {
ret "true"
}
ret "false"
ret if b { "true" } else { "false" }
}
16 changes: 13 additions & 3 deletions std/conv/atof.jule
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ fn read_float(s: str): (mantissa: u64, exp: int, neg: bool,
let mut dp = 0
for i < s.len; i++ {
let c = s[i]
match true {
match {
| c == '_':
continue
| c == '.':
if sawdot {
goto loop_end
Expand Down Expand Up @@ -203,7 +205,10 @@ loop_end:
ret
}
let mut e = 0
for i < s.len && ('0' <= s[i] && s[i] <= '9'); i++ {
for i < s.len && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ {
if s[i] == '_' {
continue
}
if e < 10000 {
e = e*10 + int(s[i]) - '0'
}
Expand Down Expand Up @@ -248,6 +253,8 @@ impl Decimal {
let mut sawdigits = false
for i < s.len; i++ {
match {
| s[i] == '_':
continue
| s[i] == '.':
if sawdot {
ret
Expand Down Expand Up @@ -299,7 +306,10 @@ impl Decimal {
ret
}
let mut e = 0
for i < s.len && ('0' <= s[i] && s[i] <= '9'); i++ {
for i < s.len && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ {
if s[i] == '_' {
continue
}
if e < 10000 {
e = e*10 + int(s[i]) - '0'
}
Expand Down
25 changes: 16 additions & 9 deletions std/conv/atoi.jule
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ const __INT_SIZE = 32 << (^uint(0) >> 63)
// Is the size in bits of an int or uint value.
pub const INT_SIZE = __INT_SIZE

const MAX_UINT64 = u64.MAX // 1<<64 - 1

// Is a lower-case letter if and only if
// c is either that lower-case letter or the equivalent upper-case letter.
// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'.
// Note that lower of non-letters can produce other non-letters.
fn lower(c: byte): byte { ret c | ('x' - 'X') }
fn lower(c: byte): byte {
ret c | ('x' - 'X')
}

// Is like parse_int but for unsigned numbers.
//
Expand Down Expand Up @@ -88,19 +88,24 @@ pub fn parse_uint(mut s: str, mut base: int, mut bit_size: int): (u64, ConvError
ret 0, ConvError.InvalidBitSize
}

// Cutoff is the smallest number such that cutoff*base > MAX_UINT64.
// Cutoff is the smallest number such that cutoff*base > u64.MAX.
// Use compile-time constants for common cases.
let mut cutoff: u64 = 0
match base {
| 10: cutoff = MAX_UINT64/10 + 1
| 16: cutoff = MAX_UINT64/16 + 1
|: cutoff = MAX_UINT64/u64(base) + 1
| 10:
cutoff = u64.MAX/10 + 1
| 16:
cutoff = u64.MAX/16 + 1
|:
cutoff = u64.MAX/u64(base) + 1
}

let mut max_val: u64 = 0
match bit_size {
| 32: max_val = u32.MAX
| 64: max_val = u64.MAX
| 32:
max_val = u32.MAX
| 64:
max_val = u64.MAX
}
/*
let mut prec = 1
Expand All @@ -117,6 +122,8 @@ pub fn parse_uint(mut s: str, mut base: int, mut bit_size: int): (u64, ConvError
d = c - '0'
| 'a' <= lower(c) && lower(c) <= 'z':
d = lower(c) - 'a' + 10
| c == '_':
continue
|:
ret 0, ConvError.InvalidSyntax
}
Expand Down
49 changes: 20 additions & 29 deletions std/conv/ftoa.jule
Original file line number Diff line number Diff line change
Expand Up @@ -76,29 +76,29 @@ struct DecimalSlice {
// The special precision -1 uses the smallest number of digits
// necessary such that parse_float will return f exactly.
pub fn fmt_float(f: f64, fmt: byte, prec: int, bit_size: int): str {
ret str(generic_ftoa(nil, f, fmt, prec, bit_size))
ret str(generic_ftoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bit_size))
}

fn generic_ftoa(mut dst: []byte, val: f64, fmt: byte, mut prec: int, bit_size: int): []byte {
let mut bits: u64 = 0
let mut flt: *FloatInfo = nil
let mut flt: &FloatInfo = nil
match bit_size {
| 32:
bits = u64(math::f32_bits(f32(val)))
flt = &F32_INFO
flt = unsafe { (&FloatInfo)(&F32_INFO) }
| 64:
bits = math::f64_bits(val)
flt = &F64_INFO
flt = unsafe { (&FloatInfo)(&F64_INFO) }
|:
panic("std::conv: illegal bit_size")
}

let neg = unsafe { bits>>(flt.expbits+flt.mantbits) } != 0
let mut exp = unsafe { int(bits>>flt.mantbits) & int(1<<flt.expbits - 1) }
let mut mant = unsafe { bits & (u64(1)<<flt.mantbits - 1) }
let neg = bits>>(flt.expbits+flt.mantbits) != 0
let mut exp = int(bits>>flt.mantbits) & int(1<<flt.expbits - 1)
let mut mant = bits & (u64(1)<<flt.mantbits - 1)

match exp {
| unsafe { int(1<<flt.expbits - 1) }:
| int(1<<flt.expbits - 1):
// +inf, nan
match {
| mant != 0:
Expand All @@ -113,20 +113,20 @@ fn generic_ftoa(mut dst: []byte, val: f64, fmt: byte, mut prec: int, bit_size: i
exp++
|:
// add implicit top bit
mant |= u64(1) << unsafe { flt.mantbits }
mant |= u64(1) << flt.mantbits
}
exp += unsafe { flt.bias }
exp += flt.bias

// Pick off easy binary, hex formats.
if fmt == 'b' {
ret fmt_b(dst, neg, mant, exp, unsafe { *flt })
ret fmt_b(dst, neg, mant, exp, *flt)
}
if fmt == 'x' || fmt == 'X' {
ret fmt_x(dst, prec, fmt, neg, mant, exp, unsafe { *flt })
ret fmt_x(dst, prec, fmt, neg, mant, exp, *flt)
}

if !OPTIMIZE {
ret big_ftoa(dst, prec, fmt, neg, mant, exp, unsafe { *flt })
ret big_ftoa(dst, prec, fmt, neg, mant, exp, *flt)
}

let mut digs = DecimalSlice{}
Expand All @@ -136,7 +136,7 @@ fn generic_ftoa(mut dst: []byte, val: f64, fmt: byte, mut prec: int, bit_size: i
if shortest {
// Use Ryu algorithm.
digs.d = make([]byte, 32)
ryu_ftoa_shortest(digs, mant, unsafe { exp-int(flt.mantbits) }, unsafe { *flt })
ryu_ftoa_shortest(digs, mant, exp-int(flt.mantbits), *flt)
ok = true
// Precision for shortest representation mode.
match fmt {
Expand Down Expand Up @@ -164,16 +164,16 @@ fn generic_ftoa(mut dst: []byte, val: f64, fmt: byte, mut prec: int, bit_size: i
}
if bit_size == 32 && digits <= 9 {
digs.d = make([]byte, 24)
ryu_ftoa_fixed32(digs, u32(mant), unsafe { exp-int(flt.mantbits) }, digits)
ryu_ftoa_fixed32(digs, u32(mant), exp-int(flt.mantbits), digits)
ok = true
} else if digits <= 18 {
digs.d = make([]byte, 24)
ryu_ftoa_fixed64(digs, mant, unsafe { exp-int(flt.mantbits) }, digits)
ryu_ftoa_fixed64(digs, mant, exp-int(flt.mantbits), digits)
ok = true
}
}
if !ok {
ret big_ftoa(dst, prec, fmt, neg, mant, exp, unsafe { *flt })
ret big_ftoa(dst, prec, fmt, neg, mant, exp, *flt)
}
ret fmt_digits(dst, shortest, neg, digs, prec, fmt)
}
Expand Down Expand Up @@ -532,10 +532,7 @@ fn fmt_x(mut dst: []byte, prec: int, fmt: byte, neg: bool,
}
}

let mut hex = lowerhex
if fmt == 'X' {
hex = upperhex
}
let hex = if fmt == 'X' { UPPERHEX } else { LOWERHEX }

// sign, 0x, leading digit
if neg {
Expand Down Expand Up @@ -587,15 +584,9 @@ fn fmt_x(mut dst: []byte, prec: int, fmt: byte, neg: bool,
}

fn min(a: int, b: int): int {
if a < b {
ret a
}
ret b
ret if a < b { a } else { b }
}

fn max(a: int, b: int): int {
if a > b {
ret a
}
ret b
ret if a > b { a } else { b }
}
8 changes: 6 additions & 2 deletions std/conv/itoa.jule
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ pub fn fmt_int(i: i64, base: int): str {
}

// Is equivalent to fmt_int(i64(i), 10).
pub fn itoa(i: int): str { ret fmt_int(i64(i), 10) }
pub fn itoa(i: int): str {
ret fmt_int(i64(i), 10)
}

// Returns the string for an i with 0 <= i < nSmalls.
fn small(i: int): str {
Expand All @@ -89,7 +91,9 @@ fn small(i: int): str {
ret SMALLS_STR[i*2 : i*2+2]
}

fn is_power_of_two(x: int): bool { ret x&(x-1) == 0 }
fn is_power_of_two(x: int): bool {
ret x&(x-1) == 0
}

// Computes the string representation of u in the given base.
// If neg is set, u is treated as negative int64 value. If append_ is
Expand Down
4 changes: 2 additions & 2 deletions std/conv/quote.jule
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ====================================================

const lowerhex = "0123456789abcdef"
const upperhex = "0123456789ABCDEF"
const LOWERHEX = "0123456789abcdef"
const UPPERHEX = "0123456789ABCDEF"
Loading

0 comments on commit c52155a

Please sign in to comment.