v.gen.js: fix method calls and other codegen parts, rand module compiles (#11205)
parent
c51f83efba
commit
0121c8b4fd
|
@ -84,11 +84,11 @@ fn (a &array) set_len(i int) {
|
|||
}
|
||||
|
||||
pub fn (mut a array) sort_with_compare(compare voidptr) {
|
||||
#a.arr.sort(compare)
|
||||
#a.val.arr.sort(compare)
|
||||
}
|
||||
|
||||
pub fn (mut a array) sort() {
|
||||
#a.arr.sort($sortComparator)
|
||||
#a.val.arr.sort($sortComparator)
|
||||
}
|
||||
|
||||
pub fn (a array) index(v string) int {
|
||||
|
@ -110,16 +110,16 @@ pub fn (a array) slice(start int, end int) array {
|
|||
}
|
||||
|
||||
pub fn (mut a array) insert(i int, val voidptr) {
|
||||
#a.arr.splice(i,0,val)
|
||||
#a.val.arr.splice(i,0,val)
|
||||
}
|
||||
|
||||
pub fn (mut a array) insert_many(i int, val voidptr, size int) {
|
||||
#a.arr.splice(i,0,...val.slice(0,+size))
|
||||
#a.val.arr.splice(i,0,...val.slice(0,+size))
|
||||
}
|
||||
|
||||
pub fn (mut a array) join(separator string) string {
|
||||
mut res := ''
|
||||
#res = new builtin.string(a.arr.join(separator +''));
|
||||
#res = new builtin.string(a.val.arr.join(separator +''));
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ pub fn (mut a array) delete(i int) {
|
|||
|
||||
// delete_many deletes `size` elements beginning with index `i`
|
||||
pub fn (mut a array) delete_many(i int, size int) {
|
||||
#a.arr.splice(i.valueOf(),size.valueOf())
|
||||
#a.val.arr.splice(i.valueOf(),size.valueOf())
|
||||
}
|
||||
|
||||
// prepend prepends one value to the array.
|
||||
|
@ -186,7 +186,7 @@ pub fn (a array) reverse() array {
|
|||
}
|
||||
|
||||
pub fn (mut a array) reverse_in_place() {
|
||||
#a.arr.reverse()
|
||||
#a.val.arr.reverse()
|
||||
}
|
||||
|
||||
#array.prototype.$includes = function (elem) { return this.arr.find(function(e) { return vEq(elem,e); }) !== undefined;}
|
||||
|
@ -195,7 +195,7 @@ pub fn (mut a array) reverse_in_place() {
|
|||
// resulting in a single output value.
|
||||
pub fn (a array) reduce(iter fn (int, int) int, accum_start int) int {
|
||||
mut accum_ := accum_start
|
||||
#for (let i of a) {
|
||||
#for (let i = 0;i < a.arr.length;i++) {
|
||||
#accum_ = iter(accum_, a.arr[i])
|
||||
#}
|
||||
|
||||
|
@ -204,7 +204,7 @@ pub fn (a array) reduce(iter fn (int, int) int, accum_start int) int {
|
|||
|
||||
pub fn (mut a array) pop() voidptr {
|
||||
mut res := voidptr(0)
|
||||
#res = a.arr.pop()
|
||||
#res = a.val.arr.pop()
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -237,5 +237,5 @@ pub fn (a array) contains(key voidptr) bool {
|
|||
|
||||
// delete_last effectively removes last element of an array.
|
||||
pub fn (mut a array) delete_last() {
|
||||
#a.arr.pop();
|
||||
#a.val.arr.pop();
|
||||
}
|
||||
|
|
|
@ -4,3 +4,35 @@ module builtin
|
|||
pub fn js_throw(s any) {
|
||||
#throw (s instanceof Error ? s : new Error(s))
|
||||
}
|
||||
|
||||
pub fn println(s any) {
|
||||
$if js_freestanding {
|
||||
#print(s.toString())
|
||||
} $else {
|
||||
#console.log(s.toString())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(s any) {
|
||||
$if js_node {
|
||||
#$process.stdout.write(s.toString())
|
||||
} $else {
|
||||
panic('Cannot `print` in a browser, use `println` instead')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eprintln(s any) {
|
||||
$if js_freestanding {
|
||||
#print(s.toString())
|
||||
} $else {
|
||||
#console.error(s.toString())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eprint(s any) {
|
||||
$if js_node {
|
||||
#$process.stderr.write(s.toString())
|
||||
} $else {
|
||||
panic('Cannot `eprint` in a browser, use `println` instead')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,34 +6,6 @@ module builtin
|
|||
|
||||
fn (a any) toString()
|
||||
|
||||
pub fn println(s any) {
|
||||
// Quickfix to properly print basic types
|
||||
// TODO: Add proper detection code for this
|
||||
JS.console.log(s.toString())
|
||||
}
|
||||
|
||||
pub fn print(s any) {
|
||||
// TODO
|
||||
// $if js.node {
|
||||
JS.process.stdout.write(s.toString())
|
||||
// } $else {
|
||||
// panic('Cannot `print` in a browser, use `println` instead')
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn eprintln(s any) {
|
||||
JS.console.error(s.toString())
|
||||
}
|
||||
|
||||
pub fn eprint(s any) {
|
||||
// TODO
|
||||
// $if js.node {
|
||||
JS.process.stderr.write(s.toString())
|
||||
// } $else {
|
||||
// panic('Cannot `eprint` in a browser, use `eprintln` instead')
|
||||
// }
|
||||
}
|
||||
|
||||
// Exits the process in node, and halts execution in the browser
|
||||
// because `process.exit` is undefined. Workaround for not having
|
||||
// a 'real' way to exit in the browser.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
module config
|
||||
|
||||
import rand.seed
|
||||
|
||||
// PRNGConfigStruct is a configuration struct for creating a new instance of the default RNG.
|
||||
// Note that the RNGs may have a different number of u32s required for seeding. The default
|
||||
// generator WyRand used 64 bits, ie. 2 u32s so that is the default. In case your desired generator
|
||||
// uses a different number of u32s, use the `seed.time_seed_array()` method with the correct
|
||||
// number of u32s.
|
||||
pub struct PRNGConfigStruct {
|
||||
pub:
|
||||
seed_ []u32 = seed.time_seed_array(2)
|
||||
}
|
|
@ -3,18 +3,9 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module rand
|
||||
|
||||
import rand.seed
|
||||
import rand.config
|
||||
import rand.wyrand
|
||||
|
||||
// PRNGConfigStruct is a configuration struct for creating a new instance of the default RNG.
|
||||
// Note that the RNGs may have a different number of u32s required for seeding. The default
|
||||
// generator WyRand used 64 bits, ie. 2 u32s so that is the default. In case your desired generator
|
||||
// uses a different number of u32s, use the `seed.time_seed_array()` method with the correct
|
||||
// number of u32s.
|
||||
pub struct PRNGConfigStruct {
|
||||
seed_ []u32 = seed.time_seed_array(2)
|
||||
}
|
||||
|
||||
// PRNG is a common interface for all PRNGs that can be used seamlessly with the rand
|
||||
// modules's API. It defines all the methods that a PRNG (in the vlib or custom made) must
|
||||
// implement in order to ensure that _all_ functions can be used with the generator.
|
||||
|
@ -52,7 +43,7 @@ fn init() {
|
|||
}
|
||||
|
||||
// new_default returns a new instance of the default RNG. If the seed is not provided, the current time will be used to seed the instance.
|
||||
pub fn new_default(config PRNGConfigStruct) &PRNG {
|
||||
pub fn new_default(config config.PRNGConfigStruct) &PRNG {
|
||||
mut rng := &wyrand.WyRandRNG{}
|
||||
rng.seed(config.seed_)
|
||||
return rng
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
module time
|
||||
|
||||
// parse returns time from a date string.
|
||||
//
|
||||
// TODO(playX): JS Date expects iso8061 format of strings and other formats
|
||||
// are implementation dependant, we probably want to implement parsing in JS.
|
||||
pub fn parse(s string) Time {
|
||||
mut res := Time{}
|
||||
#let date = new Date(s.str)
|
||||
#res.year.val = date.getFullYear()
|
||||
#res.month.val = date.getMonth()
|
||||
#res.day.val = date.getDay()
|
||||
#res.hour.val = date.getHours()
|
||||
#res.minute.val = date.getMinutes()
|
||||
#res.second.val = date.getSeconds()
|
||||
#res.microsecond.val = date.getMilliseconds() * 1000
|
||||
#res.unix.val = (date.getTime() / 1000).toFixed(0)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn parse_iso8601(s string) ?Time {
|
||||
return parse(s)
|
||||
}
|
|
@ -304,8 +304,8 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
|||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
default_value: 'new Number(0)'
|
||||
constructor: 'this.val = val | 0'
|
||||
value_of: 'this.val | 0'
|
||||
constructor: 'this.val = Number(val)'
|
||||
value_of: 'Number(this.val)'
|
||||
to_string: 'this.valueOf().toString()'
|
||||
eq: 'this.valueOf() === other.valueOf()'
|
||||
to_jsval: '+this'
|
||||
|
|
|
@ -308,7 +308,7 @@ pub fn (mut g JsGen) init() {
|
|||
g.definitions.writeln('"use strict";')
|
||||
g.definitions.writeln('')
|
||||
g.definitions.writeln('var \$global = (new Function("return this"))();')
|
||||
g.definitions.writeln('function \$ref(value) { this.val = value; } ')
|
||||
g.definitions.writeln('function \$ref(value) { if (value instanceof \$ref) { return value; } this.val = value; } ')
|
||||
g.definitions.writeln('\$ref.prototype.valueOf = function() { return this.val; } ')
|
||||
if g.pref.backend != .js_node {
|
||||
g.definitions.writeln('const \$process = {')
|
||||
|
@ -736,17 +736,16 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
|||
}
|
||||
ast.PrefixExpr {
|
||||
if node.op in [.amp, .mul] {
|
||||
// C pointers/references: ignore them
|
||||
if node.op == .amp {
|
||||
if !node.right_type.is_pointer() {
|
||||
// if !node.right_type.is_pointer() {
|
||||
// kind of weird way to handle references but it allows us to access type methods easily.
|
||||
g.write('(function(x) {')
|
||||
g.write(' return { val: x, __proto__: Object.getPrototypeOf(x), valueOf: function() { return this.val; } }})( ')
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.expr(node.right)
|
||||
}
|
||||
//} else {
|
||||
// g.expr(node.right)
|
||||
// }
|
||||
} else {
|
||||
g.write('(')
|
||||
g.expr(node.right)
|
||||
|
@ -1150,14 +1149,22 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
|
|||
if args.len > 0 {
|
||||
g.write(', ')
|
||||
}
|
||||
if it.params[0].is_mut {
|
||||
g.write('${it.params[0].name} = new \$ref(this)')
|
||||
} else {
|
||||
g.write('${it.params[0].name} = this')
|
||||
}
|
||||
}
|
||||
g.writeln(') {')
|
||||
for i, arg in args {
|
||||
is_varg := i == args.len - 1 && it.is_variadic
|
||||
if is_varg {
|
||||
name := g.js_name(arg.name)
|
||||
if is_varg {
|
||||
g.writeln('$name = new array($name);')
|
||||
} else {
|
||||
if arg.typ.is_ptr() || arg.is_mut {
|
||||
g.writeln('$name = new \$ref($name)')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1514,7 +1521,141 @@ fn (mut g JsGen) gen_array_init_values(exprs []ast.Expr) {
|
|||
g.write(']')
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_method_call(it ast.CallExpr) bool {
|
||||
g.call_stack << it
|
||||
|
||||
mut name := g.js_name(it.name)
|
||||
call_return_is_optional := it.return_type.has_flag(.optional)
|
||||
if call_return_is_optional {
|
||||
g.writeln('(function(){')
|
||||
g.inc_indent()
|
||||
g.writeln('try {')
|
||||
g.inc_indent()
|
||||
g.write('return builtin.unwrap(')
|
||||
}
|
||||
sym := g.table.get_type_symbol(it.receiver_type)
|
||||
if sym.kind == .array {
|
||||
if sym.kind == .array && it.name in ['map', 'filter'] {
|
||||
g.expr(it.left)
|
||||
mut ltyp := it.left_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write('.')
|
||||
// Prevent 'it' from getting shadowed inside the match
|
||||
node := it
|
||||
g.write(it.name)
|
||||
g.write('(')
|
||||
expr := node.args[0].expr
|
||||
match expr {
|
||||
ast.AnonFn {
|
||||
g.gen_fn_decl(expr.decl)
|
||||
g.write(')')
|
||||
return true
|
||||
}
|
||||
ast.Ident {
|
||||
if expr.kind == .function {
|
||||
g.write(g.js_name(expr.name))
|
||||
g.write(')')
|
||||
return true
|
||||
} else if expr.kind == .variable {
|
||||
v_sym := g.table.get_type_symbol(expr.var_info().typ)
|
||||
if v_sym.kind == .function {
|
||||
g.write(g.js_name(expr.name))
|
||||
g.write(')')
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
||||
g.write('it => ')
|
||||
g.expr(node.args[0].expr)
|
||||
g.write(')')
|
||||
return true
|
||||
}
|
||||
|
||||
left_sym := g.table.get_type_symbol(it.left_type)
|
||||
if left_sym.kind == .array {
|
||||
if it.name in special_array_methods {
|
||||
g.expr(it.left)
|
||||
mut ltyp := it.left_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write('.')
|
||||
|
||||
g.gen_array_method_call(it)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
// interfaces require dynamic dispatch. To obtain method table we use getPrototypeOf
|
||||
g.write('Object.getPrototypeOf(')
|
||||
g.expr(it.left)
|
||||
mut ltyp := it.left_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write(').$name .call(')
|
||||
g.expr(it.left)
|
||||
g.write(',')
|
||||
for i, arg in it.args {
|
||||
g.expr(arg.expr)
|
||||
if i != it.args.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
}
|
||||
// end method call
|
||||
g.write(')')
|
||||
|
||||
if call_return_is_optional {
|
||||
// end unwrap
|
||||
g.writeln(')')
|
||||
g.dec_indent()
|
||||
// begin catch block
|
||||
g.writeln('} catch(err) {')
|
||||
g.inc_indent()
|
||||
// gen or block contents
|
||||
match it.or_block.kind {
|
||||
.block {
|
||||
if it.or_block.stmts.len > 1 {
|
||||
g.stmts(it.or_block.stmts[..it.or_block.stmts.len - 1])
|
||||
}
|
||||
g.write('return ')
|
||||
g.stmt(it.or_block.stmts.last())
|
||||
}
|
||||
.propagate {
|
||||
panicstr := '`optional not set (\${err})`'
|
||||
if g.file.mod.name == 'main' && g.fn_decl.name == 'main.main' {
|
||||
g.writeln('return builtin.panic($panicstr)')
|
||||
} else {
|
||||
g.writeln('builtin.js_throw(err)')
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
// end catch
|
||||
g.dec_indent()
|
||||
g.writeln('}')
|
||||
// end anon fn
|
||||
g.dec_indent()
|
||||
g.write('})()')
|
||||
}
|
||||
g.call_stack.delete_last()
|
||||
return true
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
||||
if it.is_method {
|
||||
if g.gen_method_call(it) {
|
||||
return
|
||||
}
|
||||
}
|
||||
g.call_stack << it
|
||||
mut name := g.js_name(it.name)
|
||||
call_return_is_optional := it.return_type.has_flag(.optional)
|
||||
|
@ -1525,59 +1666,13 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
|||
g.inc_indent()
|
||||
g.write('return builtin.unwrap(')
|
||||
}
|
||||
|
||||
g.expr(it.left)
|
||||
|
||||
if it.is_method { // foo.bar.baz()
|
||||
sym := g.table.get_type_symbol(it.receiver_type)
|
||||
g.write('.')
|
||||
if sym.kind == .array && it.name in ['map', 'filter'] {
|
||||
// Prevent 'it' from getting shadowed inside the match
|
||||
node := it
|
||||
g.write(it.name)
|
||||
g.write('(')
|
||||
expr := node.args[0].expr
|
||||
match expr {
|
||||
ast.AnonFn {
|
||||
g.gen_fn_decl(expr.decl)
|
||||
g.write(')')
|
||||
return
|
||||
}
|
||||
ast.Ident {
|
||||
if expr.kind == .function {
|
||||
g.write(g.js_name(expr.name))
|
||||
g.write(')')
|
||||
return
|
||||
} else if expr.kind == .variable {
|
||||
v_sym := g.table.get_type_symbol(expr.var_info().typ)
|
||||
if v_sym.kind == .function {
|
||||
g.write(g.js_name(expr.name))
|
||||
g.write(')')
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
||||
g.write('it => ')
|
||||
g.expr(node.args[0].expr)
|
||||
g.write(')')
|
||||
return
|
||||
}
|
||||
|
||||
left_sym := g.table.get_type_symbol(it.left_type)
|
||||
if left_sym.kind == .array {
|
||||
node := it
|
||||
if node.name in special_array_methods {
|
||||
g.gen_array_method_call(it)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if name in g.builtin_fns {
|
||||
g.write('builtin.')
|
||||
}
|
||||
}
|
||||
|
||||
g.write('${name}(')
|
||||
for i, arg in it.args {
|
||||
g.expr(arg.expr)
|
||||
|
@ -1782,6 +1877,14 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_deref_ptr(ty ast.Type) {
|
||||
mut t := ty
|
||||
for t.is_ptr() {
|
||||
g.write('.val')
|
||||
t = t.deref()
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||
l_sym := g.table.get_type_symbol(it.left_type)
|
||||
r_sym := g.table.get_type_symbol(it.right_type)
|
||||
|
@ -1804,10 +1907,12 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
g.cast_stack << greater_typ
|
||||
g.write('BigInt((')
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write(').\$toJS())')
|
||||
g.write(' $it.op ')
|
||||
g.write('BigInt((')
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.write(').\$toJS())')
|
||||
g.cast_stack.delete_last()
|
||||
g.write(')')
|
||||
|
@ -1820,30 +1925,41 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
has_operator_overloading := g.table.type_has_method(l_sym, '==')
|
||||
if has_operator_overloading {
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write('.eq(')
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.write(')')
|
||||
// Shallow equatables
|
||||
} else if l_sym.kind in js.shallow_equatables && r_sym.kind in js.shallow_equatables {
|
||||
// wrap left expr in parens so binary operations will work correctly.
|
||||
g.write('(')
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write(')')
|
||||
g.write('.eq(')
|
||||
g.cast_stack << int(l_sym.kind)
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.cast_stack.delete_last()
|
||||
g.write(')')
|
||||
} else {
|
||||
g.write('vEq(')
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write(', ')
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.write(')')
|
||||
}
|
||||
} else if l_sym.kind == .array && it.op == .left_shift { // arr << 1
|
||||
g.write('Array.prototype.push.call(')
|
||||
g.expr(it.left)
|
||||
mut ltyp := it.left_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write('.arr,')
|
||||
array_info := l_sym.info as ast.Array
|
||||
// arr << [1, 2]
|
||||
|
@ -1854,6 +1970,12 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
g.write(')')
|
||||
} else if r_sym.kind in [.array, .map, .string] && it.op in [.key_in, .not_in] {
|
||||
g.expr(it.right)
|
||||
|
||||
mut ltyp := it.right_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
if r_sym.kind == .map {
|
||||
g.write('.map.has(')
|
||||
} else if r_sym.kind == .string {
|
||||
|
@ -1868,6 +1990,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
g.write(')')
|
||||
} else if it.op in [.key_is, .not_is] { // foo is Foo
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write(' instanceof ')
|
||||
g.write(g.typ(it.right_type))
|
||||
} else if it.op in [.lt, .gt, .ge, .le] && g.table.type_has_method(l_sym, '<')
|
||||
|
@ -1877,19 +2000,24 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
}
|
||||
if it.op in [.lt, .ge] {
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write('.\$lt (')
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.write('.\$lt (')
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write(')')
|
||||
}
|
||||
} else {
|
||||
has_operator_overloading := g.table.type_has_method(l_sym, it.op.str())
|
||||
if has_operator_overloading {
|
||||
g.expr(it.left)
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
name := match it.op.str() {
|
||||
'+' {
|
||||
'\$add'
|
||||
|
@ -1913,6 +2041,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
}
|
||||
g.write('.$name (')
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
g.write(')')
|
||||
} else {
|
||||
mut greater_typ := 0
|
||||
|
@ -1933,10 +2062,11 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
|||
}
|
||||
|
||||
g.expr(it.left)
|
||||
|
||||
g.gen_deref_ptr(it.left_type)
|
||||
g.write(' $it.op ')
|
||||
|
||||
g.expr(it.right)
|
||||
g.gen_deref_ptr(it.right_type)
|
||||
|
||||
if is_arithmetic {
|
||||
g.cast_stack.delete_last()
|
||||
|
@ -2033,8 +2163,10 @@ fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
|
|||
|
||||
fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) {
|
||||
g.expr(it.expr)
|
||||
if it.expr_type.is_ptr() {
|
||||
g.write('.valueOf()')
|
||||
mut ltyp := it.expr_type
|
||||
for ltyp.is_ptr() {
|
||||
g.write('.val')
|
||||
ltyp = ltyp.deref()
|
||||
}
|
||||
g.write('.$it.field_name')
|
||||
}
|
||||
|
@ -2078,7 +2210,8 @@ fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
|
|||
}
|
||||
|
||||
fn (mut g JsGen) gen_string_literal(it ast.StringLiteral) {
|
||||
text := it.val.replace("'", "\\'")
|
||||
mut text := it.val.replace("'", "'")
|
||||
text = text.replace('"', '\\"')
|
||||
should_cast := !(g.cast_stack.len > 0 && g.cast_stack.last() == ast.string_type_idx)
|
||||
if true || should_cast {
|
||||
if g.file.mod.name == 'builtin' {
|
||||
|
@ -2086,7 +2219,7 @@ fn (mut g JsGen) gen_string_literal(it ast.StringLiteral) {
|
|||
}
|
||||
g.write('string(')
|
||||
}
|
||||
g.write("'$text'")
|
||||
g.write("\"$text\"")
|
||||
if true || should_cast {
|
||||
g.write(')')
|
||||
}
|
||||
|
@ -2166,6 +2299,9 @@ fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
|
|||
g.cast_stack << it.typ
|
||||
typ := g.typ(it.typ)
|
||||
if !is_literal {
|
||||
if it.typ.is_ptr() {
|
||||
g.write('new \$ref(')
|
||||
}
|
||||
if typ !in js.v_types || g.ns.name == 'builtin' {
|
||||
g.write('new ')
|
||||
}
|
||||
|
@ -2177,6 +2313,9 @@ fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
|
|||
}
|
||||
if !is_literal {
|
||||
g.write(')')
|
||||
if it.typ.is_ptr() {
|
||||
g.write(')')
|
||||
}
|
||||
}
|
||||
g.cast_stack.delete_last()
|
||||
}
|
||||
|
|
|
@ -60,16 +60,16 @@ true
|
|||
0
|
||||
1
|
||||
1.1
|
||||
[1, 2, 3, 4]
|
||||
[1, 5, 6, 2, 3, 4]
|
||||
[[1, 2], 3, 4]
|
||||
[[1, 2], [5, 6], 3, 4]
|
||||
0
|
||||
1
|
||||
1
|
||||
0
|
||||
1
|
||||
1.1
|
||||
[1, 2, 3, 4]
|
||||
[5, 6, 1, 2, 3, 4]
|
||||
[[1, 2], 3, 4]
|
||||
[[5, 6], [1, 2], 3, 4]
|
||||
5
|
||||
true
|
||||
1.1
|
||||
|
@ -152,11 +152,11 @@ true
|
|||
true
|
||||
true
|
||||
true
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
15
|
||||
20
|
||||
14
|
||||
-6
|
||||
-7
|
||||
[2, 4, 6]
|
||||
[is, awesome]
|
||||
[2, 3, 4, 6, 8, 9, 10]
|
||||
|
@ -278,9 +278,9 @@ a
|
|||
123
|
||||
123
|
||||
[[1, 2, 3]]
|
||||
[[[1, 2, 3]]]
|
||||
[[1, 2, 3]]
|
||||
[[1, 2, 3]]
|
||||
[[1, 2, 3]]
|
||||
[[[1, 2, 3]]]
|
||||
true
|
||||
true
|
||||
true
|
||||
|
|
Loading…
Reference in New Issue