v.gen.js: implement `u64` and `i64` with BigInt (#11174)
parent
34d39ccb64
commit
b72d1e5e86
|
@ -299,7 +299,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
|||
for typ_name in v_types {
|
||||
// TODO: JsDoc
|
||||
match typ_name {
|
||||
'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', 'int_literal', 'size_t' {
|
||||
'i8', 'i16', 'int', 'u16', 'u32', 'int_literal', 'size_t' {
|
||||
// TODO: Bounds checking
|
||||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
|
@ -311,6 +311,29 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
|||
to_jsval: '+this'
|
||||
)
|
||||
}
|
||||
// u64 and i64 are so big that their values do not fit into JS number so we use BigInt.
|
||||
'u64' {
|
||||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
default_value: 'BigInt(0)'
|
||||
constructor: 'this.val = BigInt.asUintN(64,BigInt(val))'
|
||||
value_of: 'this.val'
|
||||
to_string: 'this.val.toString()'
|
||||
eq: 'this.valueOf() === other.valueOf()'
|
||||
to_jsval: 'this.val'
|
||||
)
|
||||
}
|
||||
'i64' {
|
||||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
default_value: 'BigInt(0)'
|
||||
constructor: 'this.val = BigInt.asIntN(64,BigInt(val))'
|
||||
value_of: 'this.val'
|
||||
to_string: 'this.val.toString()'
|
||||
eq: 'this.valueOf() === other.valueOf()'
|
||||
to_jsval: 'this.val'
|
||||
)
|
||||
}
|
||||
'byte' {
|
||||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
|
|
|
@ -1770,7 +1770,30 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
if is_not {
|
||||
g.write('!(')
|
||||
}
|
||||
|
||||
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
||||
if is_arithmetic && ((l_sym.kind == .i64 || l_sym.kind == .u64)
|
||||
|| (r_sym.kind == .i64 || r_sym.kind == .u64)) {
|
||||
// if left or right is i64 or u64 we convert them to bigint to perform operation.
|
||||
greater_typ := g.greater_typ(it.left_type, it.right_type)
|
||||
if g.ns.name == 'builtin' {
|
||||
g.write('new ')
|
||||
}
|
||||
g.write('${g.typ(greater_typ)}(')
|
||||
g.cast_stack << greater_typ
|
||||
g.write('BigInt((')
|
||||
g.expr(it.left)
|
||||
g.write(').\$toJS())')
|
||||
g.write(' $it.op ')
|
||||
g.write('BigInt((')
|
||||
g.expr(it.right)
|
||||
g.write(').\$toJS())')
|
||||
g.cast_stack.delete_last()
|
||||
g.write(')')
|
||||
if is_not {
|
||||
g.write(')')
|
||||
}
|
||||
return
|
||||
}
|
||||
if it.op == .eq || it.op == .ne {
|
||||
has_operator_overloading := g.table.type_has_method(l_sym, '==')
|
||||
if has_operator_overloading {
|
||||
|
@ -1842,7 +1865,6 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
g.write(')')
|
||||
}
|
||||
} else {
|
||||
is_arithmetic := it.op in [token.Kind.plus, .minus, .mul, .div, .mod]
|
||||
has_operator_overloading := g.table.type_has_method(l_sym, it.op.str())
|
||||
if has_operator_overloading {
|
||||
g.expr(it.left)
|
||||
|
@ -1926,7 +1948,9 @@ fn (mut g JsGen) greater_typ(left ast.Type, right ast.Type) ast.Type {
|
|||
}
|
||||
should_int := (l in ast.integer_type_idxs && r in ast.integer_type_idxs)
|
||||
if should_int {
|
||||
// cant add to u64 - if (ast.u64_type_idx in lr) { return ast.Type(ast.u64_type_idx) }
|
||||
if ast.u64_type_idx in lr {
|
||||
return ast.Type(ast.u64_type_idx)
|
||||
}
|
||||
// just guessing this order
|
||||
if ast.i64_type_idx in lr {
|
||||
return ast.Type(ast.i64_type_idx)
|
||||
|
@ -2099,8 +2123,20 @@ fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
|
|||
is_literal := ((it.expr is ast.IntegerLiteral && it.typ in ast.integer_type_idxs)
|
||||
|| (it.expr is ast.FloatLiteral && it.typ in ast.float_type_idxs))
|
||||
// Skip cast if type is the same as the parrent caster
|
||||
tsym := g.table.get_type_symbol(it.typ)
|
||||
if it.expr is ast.IntegerLiteral && (tsym.kind == .i64 || tsym.kind == .u64) {
|
||||
if g.ns.name == 'builtin' {
|
||||
g.write('new ')
|
||||
}
|
||||
g.write(tsym.kind.str())
|
||||
g.write('(BigInt(')
|
||||
g.write(it.expr.val)
|
||||
g.write('n))')
|
||||
return
|
||||
}
|
||||
if g.cast_stack.len > 0 && is_literal {
|
||||
if it.typ == g.cast_stack[g.cast_stack.len - 1] {
|
||||
g.expr(it.expr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ true
|
|||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
false
|
||||
true
|
||||
true
|
||||
true
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
18446744073709551615
|
||||
0
|
||||
true
|
||||
25600000
|
|
@ -0,0 +1,7 @@
|
|||
fn main() {
|
||||
println(u64(18446744073709551615))
|
||||
println(u64(18446744073709551615) + 1)
|
||||
|
||||
println(u64(42) == u64(42))
|
||||
println(u64(100000) * 256)
|
||||
}
|
Loading…
Reference in New Issue