v/vlib/v/gen/js/infix.v

375 lines
8.6 KiB
V

module js
import v.util
import v.ast
fn (mut g JsGen) gen_plain_infix_expr(node ast.InfixExpr) {
it := node
l_sym := g.table.get_final_type_symbol(it.left_type)
r_sym := g.table.get_final_type_symbol(it.right_type)
greater_typ := g.greater_typ(it.left_type, it.right_type)
cast_ty := if greater_typ == it.left_type { l_sym.cname } else { r_sym.cname }
g.write('new ${g.js_name(cast_ty)}( ')
g.cast_stack << greater_typ
if (l_sym.kind == .i64 || l_sym.kind == .u64) || (r_sym.kind == .i64 || r_sym.kind == .u64) {
g.write('BigInt(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write('.valueOf())')
g.write(' $node.op.str() ')
g.write('BigInt(')
g.expr(node.right)
g.gen_deref_ptr(node.left_type)
g.write('.valueOf())')
} else {
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write('.valueOf()')
g.write(' $node.op.str() ')
g.expr(node.right)
g.gen_deref_ptr(node.left_type)
g.write('.valueOf()')
}
g.cast_stack.delete_last()
g.write(')')
}
fn (mut g JsGen) infix_expr_arithmetic_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
method := g.table.type_find_method(left.sym, node.op.str()) or {
g.gen_plain_infix_expr(node)
return
}
left_styp := g.typ(left.typ.set_nr_muls(0))
g.write(left_styp)
g.write('_')
g.write(util.replace_op(node.op.str()))
g.write('(')
g.op_arg(node.left, method.params[0].typ, left.typ)
g.write(', ')
g.op_arg(node.right, method.params[1].typ, right.typ)
g.write(')')
}
fn (mut g JsGen) op_arg(expr ast.Expr, expected ast.Type, got ast.Type) {
mut needs_closing := 0
mut nr_muls := got.nr_muls()
if expected.is_ptr() {
if nr_muls > 0 {
nr_muls--
} else {
g.write('new \$ref(')
needs_closing++
}
}
g.expr(expr)
g.write('.val'.repeat(nr_muls))
for i := 0; i < needs_closing; i++ {
g.write(')')
}
}
fn (mut g JsGen) infix_expr_eq_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '==')
g.write('new bool(')
if (left.typ.is_ptr() && right.typ.is_int()) || (right.typ.is_ptr() && left.typ.is_int()) {
g.gen_plain_infix_expr(node)
} else if has_operator_overloading {
if node.op == .ne {
g.write('!')
}
g.write(g.typ(left.unaliased.set_nr_muls(0)))
g.write('__eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(',')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
} else if left.typ.idx() == right.typ.idx()
&& left.sym.kind in [.array, .array_fixed, .alias, .map, .struct_, .sum_type] {
match left.sym.kind {
.alias {
ptr_typ := g.gen_alias_equality_fn(left.typ)
if node.op == .ne {
g.write('!')
}
g.write('${ptr_typ}_alias_eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
}
.array {
ptr_typ := g.gen_array_equality_fn(left.unaliased.clear_flag(.shared_f))
if node.op == .ne {
g.write('!')
}
g.write('${ptr_typ}_arr_eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
}
.array_fixed {
ptr_typ := g.gen_fixed_array_equality_fn(left.unaliased)
if node.op == .ne {
g.write('!')
}
g.write('${ptr_typ}_arr_eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
}
.map {
ptr_typ := g.gen_map_equality_fn(left.unaliased)
if node.op == .ne {
g.write('!')
}
g.write('${ptr_typ}_map_eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
}
.struct_ {
ptr_typ := g.gen_struct_equality_fn(left.unaliased)
if node.op == .ne {
g.write('!')
}
g.write('${ptr_typ}_struct_eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
}
.sum_type {
ptr_typ := g.gen_sumtype_equality_fn(left.unaliased)
if node.op == .ne {
g.write('!')
}
g.write('${ptr_typ}_sumtype_eq(')
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(')')
if node.op == .ne {
g.write('.valueOf()')
}
}
else {}
}
} else {
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write('.valueOf() $node.op.str() ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write('.valueOf()')
}
g.write(')')
}
fn (mut g JsGen) infix_expr_cmp_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '<')
g.write('new bool(')
if left.sym.kind == right.sym.kind && has_operator_overloading {
if node.op in [.le, .ge] {
g.write('!')
}
g.write(g.typ(left.typ.set_nr_muls(0)))
g.write('__lt')
if node.op in [.lt, .ge] {
g.write('(')
g.expr(node.left)
g.gen_deref_ptr(left.typ)
g.write(', ')
g.expr(node.right)
g.gen_deref_ptr(right.typ)
g.write(')')
} else {
g.write('(')
g.expr(node.right)
g.gen_deref_ptr(left.typ)
g.write(', ')
g.expr(node.left)
g.gen_deref_ptr(right.typ)
g.write(')')
}
} else {
g.expr(node.left)
g.gen_deref_ptr(node.left_type)
g.write('.valueOf() $node.op.str() ')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write('.valueOf()')
}
g.write(')')
}
fn (mut g JsGen) infix_expr_left_shift_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
if left.unaliased_sym.kind == .array {
// arr << val
array_info := left.unaliased_sym.info as ast.Array
g.write('array_push(')
//&& array_info.elem_type != g.unwrap_generic(node.right_type)
if right.unaliased_sym.kind == .array && array_info.elem_type != right.typ {
g.expr(node.left)
g.gen_deref_ptr(left.typ)
g.write(',')
g.expr(node.right)
g.gen_deref_ptr(right.typ)
g.write('.arr.arr')
g.write(',true)')
} else {
g.expr(node.left)
g.gen_deref_ptr(left.typ)
g.write(',')
g.expr(node.right)
g.write(',false)')
}
} else {
g.gen_plain_infix_expr(node)
}
}
fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
l_sym := g.unwrap(node.left_type)
r_sym := g.unwrap(node.right_type)
if node.op == .not_in {
g.write('!')
}
if r_sym.unaliased_sym.kind == .array {
fn_name := g.gen_array_contains_method(node.right_type)
g.write('(${fn_name}(')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write(',')
g.expr(node.left)
g.write(')')
if node.op == .not_in {
g.write('.valueOf()')
}
g.write(')')
return
} else if r_sym.unaliased_sym.kind == .map {
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.write('.map.has(')
g.expr(node.left)
/*
if l_sym.sym.kind == .string {
g.write('.str')
} else {
g.write('.valueOf()')
}*/
g.write('.\$toJS()')
g.write(')')
} else {
g.write('.str.includes(')
g.expr(node.right)
g.gen_deref_ptr(node.right_type)
g.expr(node.left)
if l_sym.sym.kind == .string {
g.write('.str')
} else {
g.write('.valueOf()')
}
g.write(')')
}
/*
if r_sym.kind == .map {
g.write('.map.has(')
} else if r_sym.kind == .string {
g.write('.str.includes(')
} else {
g.write('.\$includes(')
}
g.expr(node.left)
if l_sym.kind == .string {
g.write('.str')
}
g.write(')')*/
}
fn (mut g JsGen) infix_is_not_is_op(node ast.InfixExpr) {
g.expr(node.left)
rsym := g.table.get_type_symbol(g.unwrap(node.right_type).typ)
g.gen_deref_ptr(node.left_type)
g.write(' instanceof ')
g.write(g.js_name(rsym.name))
}
fn (mut g JsGen) infix_expr(node ast.InfixExpr) {
match node.op {
.plus, .minus, .mul, .div, .mod {
g.infix_expr_arithmetic_op(node)
}
.eq, .ne {
g.infix_expr_eq_op(node)
}
.gt, .ge, .lt, .le {
g.infix_expr_cmp_op(node)
}
.logical_or, .and {
g.gen_plain_infix_expr(node)
}
.left_shift {
g.infix_expr_left_shift_op(node)
}
.not_in, .key_in {
g.infix_in_not_in_op(node)
}
.key_is, .not_is {
g.infix_is_not_is_op(node)
}
else {
g.gen_plain_infix_expr(node)
}
}
}