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 {
|
for typ_name in v_types {
|
||||||
// TODO: JsDoc
|
// TODO: JsDoc
|
||||||
match typ_name {
|
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
|
// TODO: Bounds checking
|
||||||
g.gen_builtin_prototype(
|
g.gen_builtin_prototype(
|
||||||
typ_name: typ_name
|
typ_name: typ_name
|
||||||
|
@ -311,6 +311,29 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
||||||
to_jsval: '+this'
|
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' {
|
'byte' {
|
||||||
g.gen_builtin_prototype(
|
g.gen_builtin_prototype(
|
||||||
typ_name: typ_name
|
typ_name: typ_name
|
||||||
|
|
|
@ -1770,7 +1770,30 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
if is_not {
|
if is_not {
|
||||||
g.write('!(')
|
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 {
|
if it.op == .eq || it.op == .ne {
|
||||||
has_operator_overloading := g.table.type_has_method(l_sym, '==')
|
has_operator_overloading := g.table.type_has_method(l_sym, '==')
|
||||||
if has_operator_overloading {
|
if has_operator_overloading {
|
||||||
|
@ -1842,7 +1865,6 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
} else {
|
} 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())
|
has_operator_overloading := g.table.type_has_method(l_sym, it.op.str())
|
||||||
if has_operator_overloading {
|
if has_operator_overloading {
|
||||||
g.expr(it.left)
|
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)
|
should_int := (l in ast.integer_type_idxs && r in ast.integer_type_idxs)
|
||||||
if should_int {
|
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
|
// just guessing this order
|
||||||
if ast.i64_type_idx in lr {
|
if ast.i64_type_idx in lr {
|
||||||
return ast.Type(ast.i64_type_idx)
|
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)
|
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))
|
|| (it.expr is ast.FloatLiteral && it.typ in ast.float_type_idxs))
|
||||||
// Skip cast if type is the same as the parrent caster
|
// 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 g.cast_stack.len > 0 && is_literal {
|
||||||
if it.typ == g.cast_stack[g.cast_stack.len - 1] {
|
if it.typ == g.cast_stack[g.cast_stack.len - 1] {
|
||||||
|
g.expr(it.expr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
true
|
||||||
true
|
false
|
||||||
true
|
true
|
||||||
true
|
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