From 2f6b2dd18952180eb248fd3e1fefe8dfbfe45953 Mon Sep 17 00:00:00 2001 From: playX Date: Sat, 21 Aug 2021 17:18:57 +0300 Subject: [PATCH] js: math.big support, f{32,64}_bits,from_bits support, typeof(expr).name support (#11260) --- vlib/math/big/{big.v => big.c.v} | 0 vlib/math/big/big.js.v | 198 +++++++++++++++++++++++++++++ vlib/math/{unsafe.v => unsafe.c.v} | 0 vlib/math/unsafe.js.v | 59 +++++++++ vlib/v/gen/js/js.v | 48 ++++++- 5 files changed, 304 insertions(+), 1 deletion(-) rename vlib/math/big/{big.v => big.c.v} (100%) create mode 100644 vlib/math/big/big.js.v rename vlib/math/{unsafe.v => unsafe.c.v} (100%) create mode 100644 vlib/math/unsafe.js.v diff --git a/vlib/math/big/big.v b/vlib/math/big/big.c.v similarity index 100% rename from vlib/math/big/big.v rename to vlib/math/big/big.c.v diff --git a/vlib/math/big/big.js.v b/vlib/math/big/big.js.v new file mode 100644 index 0000000000..0ed469ca8b --- /dev/null +++ b/vlib/math/big/big.js.v @@ -0,0 +1,198 @@ +module big + +struct JS.BigInt {} + +#const jsNumber = Number; + +pub struct Number { +} + +pub fn new() Number { + return Number{} +} + +pub fn from_int(i int) Number { + n := Number{} + #n.value = BigInt(+i) + + return n +} + +pub fn from_u64(u u64) Number { + n := Number{} + #n.value = BigInt(u.val) + + return n +} + +pub fn from_hex_string(input string) Number { + n := Number{} + #n.value = BigInt(input.val) + + return n +} + +pub fn from_string(input string) Number { + n := Number{} + #n.value = BigInt(input.val) + + return n +} + +pub fn (n &Number) int() int { + r := 0 + #r.val = jsNumber(n.val.value) + + return r +} + +pub fn (n &Number) str() string { + s := '' + #s.str = n.val.value + "" + + return s +} + +pub fn (a &Number) + (b &Number) Number { + c := Number{} + #c.value = a.val.value + b.val.value + + return c +} + +pub fn (a &Number) - (b &Number) Number { + c := Number{} + #c.value = a.val.value - b.val.value + + return c +} + +pub fn (a &Number) / (b &Number) Number { + c := Number{} + #c.value = a.val.value / b.val.value + + return c +} + +pub fn (a &Number) * (b &Number) Number { + c := Number{} + #c.value = a.val.value * b.val.value + + return c +} + +/* +pub fn (a &Number) % (b &Number) Number { + c := Number{} + # c.value = a.val.value % b.val.value + return c +}*/ + +pub fn divmod(a &Number, b &Number) (Number, Number) { + c := Number{} + d := Number{} + #c.value = a.val.value / b.val.value + #d.value = a.val.value % b.val.value + + return c, d +} + +pub fn cmp(a &Number, b &Number) int { + res := 0 + + #if (a.val.value < b.val.value) res.val = -1 + #else if (a.val.value > b.val.value) res.val = 1 + #else res.val = 0 + + return res +} + +pub fn (a &Number) is_zero() bool { + res := false + #res.val = a.val.value == BigInt(0) + + return res +} + +pub fn (mut a Number) inc() { + #a.val.value = a.val.value + BigInt(1) +} + +pub fn (mut a Number) dec() { + #a.val.value = a.val.value - BigInt(1) +} + +pub fn (a &Number) isqrt() Number { + b := Number{} + #let x0 = a.val.value >> 1n + #if (x0) { + #let x1 = (x0 + a.val.value / x0) >> 1n + #while (x1 < x0) { + #x0 = x1 + #x1 = (x0 + a.val.value / x0) >> 1n + #} + #b.value = x0 + #} else { b.value = a.val.value; } + + return b +} + +pub fn b_and(a &Number, b &Number) Number { + c := Number{} + #c.value = a.val.value & b.val.value + + return c +} + +pub fn b_or(a &Number, b &Number) Number { + c := Number{} + #c.value = a.val.value | b.val.value + + return c +} + +pub fn b_xor(a &Number, b &Number) Number { + c := Number{} + #c.value = a.val.value ^ b.val.value + + return c +} + +pub fn (a &Number) lshift(nbits int) Number { + c := Number{} + #c.value = a.val.value << BigInt(+nbits) + + return c +} + +pub fn (a &Number) rshift(nbits int) Number { + c := Number{} + #c.value = a.val.value << BigInt(+nbits) + + return c +} + +pub fn (a &Number) clone() Number { + b := Number{} + #b.value = a.val.value + + return b +} + +pub fn factorial(nn &Number) Number { + mut n := nn.clone() + mut a := nn.clone() + n.dec() + mut i := 1 + for !n.is_zero() { + res := a * n + n.dec() + a = res + i++ + } + return a +} + +pub fn fact(n int) Number { + return factorial(from_int(n)) +} diff --git a/vlib/math/unsafe.v b/vlib/math/unsafe.c.v similarity index 100% rename from vlib/math/unsafe.v rename to vlib/math/unsafe.c.v diff --git a/vlib/math/unsafe.js.v b/vlib/math/unsafe.js.v new file mode 100644 index 0000000000..38ee16710c --- /dev/null +++ b/vlib/math/unsafe.js.v @@ -0,0 +1,59 @@ +module math + +// f32_bits returns the IEEE 754 binary representation of f, +// with the sign bit of f and the result in the same bit position. +// f32_bits(f32_from_bits(x)) == x. +pub fn f32_bits(f f32) u32 { + p := u32(0) + #let buffer = new ArrayBuffer(4) + #let floatArr = new Float32Array(buffer) + #floatArr[0] = f.val + #let uintArr = new Uint32Array(buffer) + #p.val = uintArr[0] + + return p +} + +// f32_from_bits returns the floating-point number corresponding +// to the IEEE 754 binary representation b, with the sign bit of b +// and the result in the same bit position. +// f32_from_bits(f32_bits(x)) == x. +pub fn f32_from_bits(b u32) f32 { + p := f32(0.0) + #let buffer = new ArrayBuffer(4) + #let floatArr = new Float32Array(buffer) + #let uintArr = new Uint32Array(buffer) + #uintArr[0] = Number(b.val) + #p.val = floatArr[0] + + return p +} + +// f64_bits returns the IEEE 754 binary representation of f, +// with the sign bit of f and the result in the same bit position, +// and f64_bits(f64_from_bits(x)) == x. +pub fn f64_bits(f f64) u64 { + p := u64(0) + #let buffer = new ArrayBuffer(8) + #let floatArr = new Float64Array(buffer) + #floatArr[0] = f.val + #let uintArr = new BigUint64Array(buffer) + #p.val = uintArr[0] + + return p +} + +// f64_from_bits returns the floating-point number corresponding +// to the IEEE 754 binary representation b, with the sign bit of b +// and the result in the same bit position. +// f64_from_bits(f64_bits(x)) == x. +pub fn f64_from_bits(b u64) f64 { + p := 0.0 + #let buffer = new ArrayBuffer(8) + #let floatArr = new Float64Array(buffer) + #let uintArr = new BigUint64Array(buffer) + #uintArr[0] = Number(b.val) + #p.val = floatArr[0] + + return p +} diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 58d128e111..988262e766 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -1149,7 +1149,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) { if args.len > 0 { g.write(', ') } - if it.params[0].is_mut { + if it.params[0].is_mut || it.params[0].typ.is_ptr() { g.write('${it.params[0].name} = new \$ref(this)') } else { g.write('${it.params[0].name} = this') @@ -2174,7 +2174,53 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) { g.write(')') } +fn (mut g JsGen) type_name(raw_type ast.Type) { + typ := raw_type + sym := g.table.get_type_symbol(typ) + mut s := '' + if sym.kind == .function { + // todo: properly print function signatures + if typ.is_ptr() { + s = '&function' + } else { + s = 'function' + } + } else { + s = g.table.type_to_str(g.unwrap_generic(typ)) + } + g.write('new builtin.string("$s")') +} + fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) { + if it.name_type > 0 { + node := it + match node.gkind_field { + .name { + g.type_name(it.name_type) + return + } + .typ { + g.write('new builtin.int(') + + g.write('${int(g.unwrap_generic(it.name_type))}') + g.write(')') + g.write(')') + return + } + .unknown { + if node.field_name == 'name' { + g.type_name(it.name_type) + return + } else if node.field_name == 'idx' { + g.write('new builtin.int(') + g.write('${int(g.unwrap_generic(it.name_type))}') + g.write(')') + return + } + panic('unknown generic field $it.pos') + } + } + } g.expr(it.expr) mut ltyp := it.expr_type for ltyp.is_ptr() {