| 1 | module js |
| 2 | |
| 3 | import v.util |
| 4 | import v.ast |
| 5 | |
| 6 | fn (mut g JsGen) gen_plain_infix_expr(node ast.InfixExpr) { |
| 7 | it := node |
| 8 | l_sym := g.table.final_sym(it.left_type) |
| 9 | r_sym := g.table.final_sym(it.right_type) |
| 10 | greater_typ := g.greater_typ(it.left_type, it.right_type) |
| 11 | cast_ty := if greater_typ == it.left_type { l_sym.cname } else { r_sym.cname } |
| 12 | g.write('new ${g.js_name(cast_ty)}( ') |
| 13 | g.cast_stack << greater_typ |
| 14 | if node.op == .power { |
| 15 | if !g.pref.output_es5 && ((l_sym.kind == .i64 || l_sym.kind == .u64) |
| 16 | || (r_sym.kind == .i64 || r_sym.kind == .u64)) { |
| 17 | g.write('BigInt(') |
| 18 | g.expr(node.left) |
| 19 | g.gen_deref_ptr(node.left_type) |
| 20 | g.write('.valueOf()) ** BigInt(') |
| 21 | g.expr(node.right) |
| 22 | g.gen_deref_ptr(node.right_type) |
| 23 | g.write('.valueOf())') |
| 24 | } else { |
| 25 | g.write('Math.pow(') |
| 26 | g.expr(node.left) |
| 27 | g.gen_deref_ptr(node.left_type) |
| 28 | g.write('.valueOf(), ') |
| 29 | g.expr(node.right) |
| 30 | g.gen_deref_ptr(node.right_type) |
| 31 | g.write('.valueOf())') |
| 32 | } |
| 33 | g.cast_stack.delete_last() |
| 34 | g.write(')') |
| 35 | return |
| 36 | } |
| 37 | if !g.pref.output_es5 && ((l_sym.kind == .i64 || l_sym.kind == .u64) |
| 38 | || (r_sym.kind == .i64 || r_sym.kind == .u64)) { |
| 39 | g.write('BigInt(') |
| 40 | g.expr(node.left) |
| 41 | g.gen_deref_ptr(node.left_type) |
| 42 | g.write('.valueOf())') |
| 43 | g.write(' ${node.op.str()} ') |
| 44 | g.write('BigInt(') |
| 45 | g.expr(node.right) |
| 46 | g.gen_deref_ptr(node.left_type) |
| 47 | g.write('.valueOf())') |
| 48 | } else { |
| 49 | g.expr(node.left) |
| 50 | g.gen_deref_ptr(node.left_type) |
| 51 | g.write('.valueOf()') |
| 52 | g.write(' ${node.op.str()} ') |
| 53 | g.expr(node.right) |
| 54 | g.gen_deref_ptr(node.left_type) |
| 55 | g.write('.valueOf()') |
| 56 | } |
| 57 | |
| 58 | g.cast_stack.delete_last() |
| 59 | g.write(')') |
| 60 | } |
| 61 | |
| 62 | fn (mut g JsGen) infix_expr_arithmetic_op(node ast.InfixExpr) { |
| 63 | left := g.unwrap(node.left_type) |
| 64 | right := g.unwrap(node.right_type) |
| 65 | method := g.table.find_method(left.sym, node.op.str()) or { |
| 66 | g.gen_plain_infix_expr(node) |
| 67 | return |
| 68 | } |
| 69 | left_styp := g.styp(left.typ.set_nr_muls(0)) |
| 70 | g.write(left_styp) |
| 71 | g.write('_') |
| 72 | g.write(util.replace_op(node.op.str())) |
| 73 | g.write('(') |
| 74 | g.op_arg(node.left, method.params[0].typ, left.typ) |
| 75 | g.write(', ') |
| 76 | g.op_arg(node.right, method.params[1].typ, right.typ) |
| 77 | g.write(')') |
| 78 | } |
| 79 | |
| 80 | fn (mut g JsGen) op_arg(expr ast.Expr, expected ast.Type, got ast.Type) { |
| 81 | mut needs_closing := 0 |
| 82 | mut nr_muls := got.nr_muls() |
| 83 | if expected.is_ptr() { |
| 84 | if nr_muls > 0 { |
| 85 | nr_muls-- |
| 86 | } else { |
| 87 | g.write('new \$ref(') |
| 88 | needs_closing++ |
| 89 | } |
| 90 | } |
| 91 | g.expr(expr) |
| 92 | g.write('.val'.repeat(nr_muls)) |
| 93 | for i := 0; i < needs_closing; i++ { |
| 94 | g.write(')') |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | fn (mut g JsGen) infix_expr_eq_op(node ast.InfixExpr) { |
| 99 | left := g.unwrap(node.left_type) |
| 100 | right := g.unwrap(node.right_type) |
| 101 | has_operator_overloading := g.table.has_method(left.sym, '==') |
| 102 | g.write('new bool(') |
| 103 | if (left.typ.is_ptr() && right.typ.is_int()) || (right.typ.is_ptr() && left.typ.is_int()) { |
| 104 | g.gen_plain_infix_expr(node) |
| 105 | } else if has_operator_overloading { |
| 106 | if node.op == .ne { |
| 107 | g.write('!') |
| 108 | } |
| 109 | g.write(g.styp(left.unaliased.set_nr_muls(0))) |
| 110 | g.write('__eq(') |
| 111 | g.expr(node.left) |
| 112 | g.gen_deref_ptr(node.left_type) |
| 113 | g.write(',') |
| 114 | g.expr(node.right) |
| 115 | g.gen_deref_ptr(node.right_type) |
| 116 | g.write(')') |
| 117 | if node.op == .ne { |
| 118 | g.write('.valueOf()') |
| 119 | } |
| 120 | } else if left.typ.idx() == right.typ.idx() |
| 121 | && left.sym.kind in [.array, .array_fixed, .alias, .map, .struct, .sum_type] { |
| 122 | match left.sym.kind { |
| 123 | .alias { |
| 124 | ptr_typ := g.gen_alias_equality_fn(left.typ) |
| 125 | if node.op == .ne { |
| 126 | g.write('!') |
| 127 | } |
| 128 | g.write('${ptr_typ}_alias_eq(') |
| 129 | g.expr(node.left) |
| 130 | g.gen_deref_ptr(node.left_type) |
| 131 | g.write(', ') |
| 132 | g.expr(node.right) |
| 133 | g.gen_deref_ptr(node.right_type) |
| 134 | g.write(')') |
| 135 | if node.op == .ne { |
| 136 | g.write('.valueOf()') |
| 137 | } |
| 138 | } |
| 139 | .array { |
| 140 | ptr_typ := g.gen_array_equality_fn(left.unaliased.clear_flag(.shared_f)) |
| 141 | if node.op == .ne { |
| 142 | g.write('!') |
| 143 | } |
| 144 | g.write('${ptr_typ}_arr_eq(') |
| 145 | g.expr(node.left) |
| 146 | g.gen_deref_ptr(node.left_type) |
| 147 | g.write(', ') |
| 148 | g.expr(node.right) |
| 149 | g.gen_deref_ptr(node.right_type) |
| 150 | g.write(')') |
| 151 | if node.op == .ne { |
| 152 | g.write('.valueOf()') |
| 153 | } |
| 154 | } |
| 155 | .array_fixed { |
| 156 | ptr_typ := g.gen_fixed_array_equality_fn(left.unaliased) |
| 157 | if node.op == .ne { |
| 158 | g.write('!') |
| 159 | } |
| 160 | g.write('${ptr_typ}_arr_eq(') |
| 161 | g.expr(node.left) |
| 162 | g.gen_deref_ptr(node.left_type) |
| 163 | g.write(', ') |
| 164 | g.expr(node.right) |
| 165 | g.gen_deref_ptr(node.right_type) |
| 166 | g.write(')') |
| 167 | if node.op == .ne { |
| 168 | g.write('.valueOf()') |
| 169 | } |
| 170 | } |
| 171 | .map { |
| 172 | ptr_typ := g.gen_map_equality_fn(left.unaliased) |
| 173 | if node.op == .ne { |
| 174 | g.write('!') |
| 175 | } |
| 176 | g.write('${ptr_typ}_map_eq(') |
| 177 | g.expr(node.left) |
| 178 | g.gen_deref_ptr(node.left_type) |
| 179 | g.write(', ') |
| 180 | g.expr(node.right) |
| 181 | g.gen_deref_ptr(node.right_type) |
| 182 | g.write(')') |
| 183 | if node.op == .ne { |
| 184 | g.write('.valueOf()') |
| 185 | } |
| 186 | } |
| 187 | .struct { |
| 188 | ptr_typ := g.gen_struct_equality_fn(left.unaliased) |
| 189 | if node.op == .ne { |
| 190 | g.write('!') |
| 191 | } |
| 192 | g.write('${ptr_typ}_struct_eq(') |
| 193 | g.expr(node.left) |
| 194 | g.gen_deref_ptr(node.left_type) |
| 195 | g.write(', ') |
| 196 | g.expr(node.right) |
| 197 | g.gen_deref_ptr(node.right_type) |
| 198 | g.write(')') |
| 199 | if node.op == .ne { |
| 200 | g.write('.valueOf()') |
| 201 | } |
| 202 | } |
| 203 | .sum_type { |
| 204 | ptr_typ := g.gen_sumtype_equality_fn(left.unaliased) |
| 205 | if node.op == .ne { |
| 206 | g.write('!') |
| 207 | } |
| 208 | g.write('${ptr_typ}_sumtype_eq(') |
| 209 | |
| 210 | g.expr(node.left) |
| 211 | g.gen_deref_ptr(node.left_type) |
| 212 | g.write(', ') |
| 213 | g.expr(node.right) |
| 214 | g.gen_deref_ptr(node.right_type) |
| 215 | g.write(')') |
| 216 | if node.op == .ne { |
| 217 | g.write('.valueOf()') |
| 218 | } |
| 219 | } |
| 220 | else {} |
| 221 | } |
| 222 | } else if !g.pref.output_es5 |
| 223 | && (left.sym.kind in [.i64, .u64] || right.sym.kind in [.i64, .u64]) { |
| 224 | if left.sym.kind in [.i64, .u64] && node.right is ast.IntegerLiteral { |
| 225 | g.expr(node.left) |
| 226 | g.gen_deref_ptr(node.left_type) |
| 227 | g.write('.valueOf() ${node.op.str()} ') |
| 228 | g.cast_stack << left.typ |
| 229 | g.expr(node.right) |
| 230 | g.cast_stack.delete_last() |
| 231 | g.gen_deref_ptr(node.right_type) |
| 232 | g.write('.valueOf()') |
| 233 | } else if right.sym.kind in [.i64, .u64] && node.left is ast.IntegerLiteral { |
| 234 | g.cast_stack << right.typ |
| 235 | g.expr(node.left) |
| 236 | g.cast_stack.delete_last() |
| 237 | g.gen_deref_ptr(node.left_type) |
| 238 | g.write('.valueOf() ${node.op.str()} ') |
| 239 | g.expr(node.right) |
| 240 | g.gen_deref_ptr(node.right_type) |
| 241 | g.write('.valueOf()') |
| 242 | } else { |
| 243 | g.expr(node.left) |
| 244 | g.gen_deref_ptr(node.left_type) |
| 245 | g.write('.valueOf() ${node.op.str()} ') |
| 246 | g.expr(node.right) |
| 247 | g.gen_deref_ptr(node.right_type) |
| 248 | g.write('.valueOf()') |
| 249 | } |
| 250 | } else { |
| 251 | g.expr(node.left) |
| 252 | g.gen_deref_ptr(node.left_type) |
| 253 | g.write('.valueOf() ${node.op.str()} ') |
| 254 | g.expr(node.right) |
| 255 | g.gen_deref_ptr(node.right_type) |
| 256 | g.write('.valueOf()') |
| 257 | } |
| 258 | g.write(')') |
| 259 | } |
| 260 | |
| 261 | fn (mut g JsGen) infix_expr_cmp_op(node ast.InfixExpr) { |
| 262 | left := g.unwrap(node.left_type) |
| 263 | right := g.unwrap(node.right_type) |
| 264 | has_operator_overloading := g.table.has_method(left.sym, '<') |
| 265 | g.write('new bool(') |
| 266 | if left.sym.kind == right.sym.kind && has_operator_overloading { |
| 267 | if node.op in [.le, .ge] { |
| 268 | g.write('!') |
| 269 | } |
| 270 | g.write(g.styp(left.typ.set_nr_muls(0))) |
| 271 | g.write('__lt') |
| 272 | if node.op in [.lt, .ge] { |
| 273 | g.write('(') |
| 274 | |
| 275 | g.expr(node.left) |
| 276 | g.gen_deref_ptr(left.typ) |
| 277 | g.write(', ') |
| 278 | g.expr(node.right) |
| 279 | g.gen_deref_ptr(right.typ) |
| 280 | g.write(')') |
| 281 | } else { |
| 282 | g.write('(') |
| 283 | g.expr(node.right) |
| 284 | g.gen_deref_ptr(left.typ) |
| 285 | g.write(', ') |
| 286 | g.expr(node.left) |
| 287 | g.gen_deref_ptr(right.typ) |
| 288 | g.write(')') |
| 289 | } |
| 290 | } else if !g.pref.output_es5 |
| 291 | && (left.sym.kind in [.i64, .u64] || right.sym.kind in [.i64, .u64]) { |
| 292 | if left.sym.kind in [.i64, .u64] && node.right is ast.IntegerLiteral { |
| 293 | g.expr(node.left) |
| 294 | g.gen_deref_ptr(node.left_type) |
| 295 | g.write('.valueOf() ${node.op.str()} ') |
| 296 | g.cast_stack << left.typ |
| 297 | g.expr(node.right) |
| 298 | g.cast_stack.delete_last() |
| 299 | g.gen_deref_ptr(node.right_type) |
| 300 | g.write('.valueOf()') |
| 301 | } else if right.sym.kind in [.i64, .u64] && node.left is ast.IntegerLiteral { |
| 302 | g.cast_stack << right.typ |
| 303 | g.expr(node.left) |
| 304 | g.cast_stack.delete_last() |
| 305 | g.gen_deref_ptr(node.left_type) |
| 306 | g.write('.valueOf() ${node.op.str()} ') |
| 307 | g.expr(node.right) |
| 308 | g.gen_deref_ptr(node.right_type) |
| 309 | g.write('.valueOf()') |
| 310 | } else { |
| 311 | g.expr(node.left) |
| 312 | g.gen_deref_ptr(node.left_type) |
| 313 | g.write('.valueOf() ${node.op.str()} ') |
| 314 | g.expr(node.right) |
| 315 | g.gen_deref_ptr(node.right_type) |
| 316 | g.write('.valueOf()') |
| 317 | } |
| 318 | } else { |
| 319 | g.expr(node.left) |
| 320 | g.gen_deref_ptr(node.left_type) |
| 321 | g.write('.valueOf() ${node.op.str()} ') |
| 322 | g.expr(node.right) |
| 323 | g.gen_deref_ptr(node.right_type) |
| 324 | g.write('.valueOf()') |
| 325 | } |
| 326 | |
| 327 | g.write(')') |
| 328 | } |
| 329 | |
| 330 | fn (mut g JsGen) infix_expr_left_shift_op(node ast.InfixExpr) { |
| 331 | left := g.unwrap(node.left_type) |
| 332 | right := g.unwrap(node.right_type) |
| 333 | if left.unaliased_sym.kind == .array { |
| 334 | // arr << val |
| 335 | array_info := left.unaliased_sym.info as ast.Array |
| 336 | g.write('array_push(') |
| 337 | old_inside_left_shift := g.inside_left_shift |
| 338 | g.inside_left_shift = true |
| 339 | defer { |
| 340 | g.inside_left_shift = old_inside_left_shift |
| 341 | } |
| 342 | //&& array_info.elem_type != g.unwrap_generic(node.right_type) |
| 343 | if right.unaliased_sym.kind == .array && array_info.elem_type != right.typ { |
| 344 | g.expr(node.left) |
| 345 | g.gen_deref_ptr(left.typ) |
| 346 | g.write(',') |
| 347 | g.expr(node.right) |
| 348 | g.gen_deref_ptr(right.typ) |
| 349 | g.write('.arr.arr') |
| 350 | g.write(',true)') |
| 351 | } else { |
| 352 | g.expr(node.left) |
| 353 | g.gen_deref_ptr(left.typ) |
| 354 | g.write(',') |
| 355 | g.expr(node.right) |
| 356 | g.write(',false)') |
| 357 | } |
| 358 | } else { |
| 359 | g.gen_plain_infix_expr(node) |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) { |
| 364 | l_sym := g.unwrap(node.left_type) |
| 365 | r_sym := g.unwrap(node.right_type) |
| 366 | if node.op == .not_in { |
| 367 | g.write('!') |
| 368 | } |
| 369 | if r_sym.unaliased_sym.kind in [.array, .array_fixed] { |
| 370 | fn_name := g.gen_array_contains_method(node.right_type) |
| 371 | g.write('(${fn_name}(') |
| 372 | g.expr(node.right) |
| 373 | g.gen_deref_ptr(node.right_type) |
| 374 | g.write(',') |
| 375 | g.expr(node.left) |
| 376 | g.write(')') |
| 377 | if node.op == .not_in { |
| 378 | g.write('.valueOf()') |
| 379 | } |
| 380 | g.write(')') |
| 381 | return |
| 382 | } else if r_sym.unaliased_sym.kind == .map { |
| 383 | g.expr(node.right) |
| 384 | g.gen_deref_ptr(node.right_type) |
| 385 | g.write('.has(') |
| 386 | g.expr(node.left) |
| 387 | /* |
| 388 | if l_sym.sym.kind == .string { |
| 389 | g.write('.str') |
| 390 | } else { |
| 391 | g.write('.valueOf()') |
| 392 | }*/ |
| 393 | g.write('.\$toJS()') |
| 394 | g.write(')') |
| 395 | } else { |
| 396 | g.write('.str.includes(') |
| 397 | g.expr(node.right) |
| 398 | g.gen_deref_ptr(node.right_type) |
| 399 | g.expr(node.left) |
| 400 | if l_sym.sym.kind == .string { |
| 401 | g.write('.str') |
| 402 | } else { |
| 403 | g.write('.valueOf()') |
| 404 | } |
| 405 | g.write(')') |
| 406 | } |
| 407 | |
| 408 | /* |
| 409 | if r_sym.kind == .map { |
| 410 | g.write('.map.has(') |
| 411 | } else if r_sym.kind == .string { |
| 412 | g.write('.str.includes(') |
| 413 | } else { |
| 414 | g.write('.\$includes(') |
| 415 | } |
| 416 | g.expr(node.left) |
| 417 | if l_sym.kind == .string { |
| 418 | g.write('.str') |
| 419 | } |
| 420 | g.write(')')*/ |
| 421 | } |
| 422 | |
| 423 | fn (mut g JsGen) infix_is_not_is_op(node ast.InfixExpr) { |
| 424 | rsym := g.unwrap(node.right_type).unaliased_sym |
| 425 | |
| 426 | if rsym.info is ast.SumType { |
| 427 | g.write('[') |
| 428 | variants := g.unwrap_sum_type(node.right_type) |
| 429 | for i, v in variants { |
| 430 | g.write(g.js_name(v.unaliased_sym.name)) |
| 431 | if i < variants.len - 1 { |
| 432 | g.write(', ') |
| 433 | } |
| 434 | } |
| 435 | g.write('].some(t => ') |
| 436 | g.expr(node.left) |
| 437 | g.gen_deref_ptr(node.left_type) |
| 438 | g.write(' instanceof t.valueOf())') |
| 439 | } else { |
| 440 | g.expr(node.left) |
| 441 | g.gen_deref_ptr(node.left_type) |
| 442 | g.write(' instanceof ') |
| 443 | g.write(g.js_name(rsym.name)) |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | fn (mut g JsGen) infix_expr(node ast.InfixExpr) { |
| 448 | match node.op { |
| 449 | .plus, .minus, .mul, .power, .div, .mod { |
| 450 | g.infix_expr_arithmetic_op(node) |
| 451 | } |
| 452 | .eq, .ne { |
| 453 | g.infix_expr_eq_op(node) |
| 454 | } |
| 455 | .gt, .ge, .lt, .le { |
| 456 | g.infix_expr_cmp_op(node) |
| 457 | } |
| 458 | .logical_or, .and { |
| 459 | g.gen_plain_infix_expr(node) |
| 460 | } |
| 461 | .left_shift { |
| 462 | g.infix_expr_left_shift_op(node) |
| 463 | } |
| 464 | .not_in, .key_in { |
| 465 | g.infix_in_not_in_op(node) |
| 466 | } |
| 467 | .key_is, .not_is { |
| 468 | g.infix_is_not_is_op(node) |
| 469 | } |
| 470 | else { |
| 471 | g.gen_plain_infix_expr(node) |
| 472 | } |
| 473 | } |
| 474 | } |
| 475 | |