@tishlang/tish 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/Cargo.toml +1 -0
  2. package/bin/tish +0 -0
  3. package/crates/js_to_tish/src/error.rs +2 -8
  4. package/crates/js_to_tish/src/transform/expr.rs +101 -130
  5. package/crates/js_to_tish/src/transform/stmt.rs +25 -22
  6. package/crates/tish/Cargo.toml +1 -1
  7. package/crates/tish/src/cli_help.rs +76 -29
  8. package/crates/tish/src/main.rs +85 -54
  9. package/crates/tish/tests/cargo_example_compile.rs +67 -0
  10. package/crates/tish/tests/fixtures/cargo_example_project/Cargo.toml +3 -0
  11. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/Cargo.toml +11 -0
  12. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +12 -0
  13. package/crates/tish/tests/fixtures/cargo_example_project/package.json +10 -0
  14. package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +3 -0
  15. package/crates/tish/tests/integration_test.rs +197 -47
  16. package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
  17. package/crates/tish/tests/shortcircuit.rs +19 -4
  18. package/crates/tish_ast/src/ast.rs +12 -14
  19. package/crates/tish_build_utils/src/lib.rs +64 -6
  20. package/crates/tish_builtins/src/array.rs +52 -21
  21. package/crates/tish_builtins/src/construct.rs +2 -8
  22. package/crates/tish_builtins/src/globals.rs +30 -15
  23. package/crates/tish_builtins/src/lib.rs +5 -5
  24. package/crates/tish_builtins/src/math.rs +5 -3
  25. package/crates/tish_builtins/src/string.rs +71 -19
  26. package/crates/tish_bytecode/src/chunk.rs +0 -1
  27. package/crates/tish_bytecode/src/compiler.rs +164 -60
  28. package/crates/tish_bytecode/src/opcode.rs +13 -4
  29. package/crates/tish_bytecode/src/peephole.rs +2 -2
  30. package/crates/tish_compile/Cargo.toml +1 -0
  31. package/crates/tish_compile/src/codegen.rs +989 -318
  32. package/crates/tish_compile/src/infer.rs +69 -19
  33. package/crates/tish_compile/src/lib.rs +21 -8
  34. package/crates/tish_compile/src/resolve.rs +515 -94
  35. package/crates/tish_compile/src/types.rs +10 -14
  36. package/crates/tish_compile_js/src/codegen.rs +34 -13
  37. package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
  38. package/crates/tish_compiler_wasm/src/lib.rs +16 -13
  39. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +40 -48
  40. package/crates/tish_core/src/json.rs +5 -3
  41. package/crates/tish_core/src/lib.rs +1 -1
  42. package/crates/tish_core/src/uri.rs +9 -6
  43. package/crates/tish_core/src/value.rs +92 -28
  44. package/crates/tish_cranelift/src/link.rs +6 -9
  45. package/crates/tish_cranelift/src/lower.rs +14 -8
  46. package/crates/tish_eval/src/eval.rs +398 -141
  47. package/crates/tish_eval/src/lib.rs +10 -6
  48. package/crates/tish_eval/src/natives.rs +95 -38
  49. package/crates/tish_eval/src/promise.rs +14 -8
  50. package/crates/tish_eval/src/timers.rs +28 -19
  51. package/crates/tish_eval/src/value.rs +10 -3
  52. package/crates/tish_fmt/src/lib.rs +29 -13
  53. package/crates/tish_lexer/src/lib.rs +217 -63
  54. package/crates/tish_lexer/src/token.rs +6 -6
  55. package/crates/tish_llvm/src/lib.rs +15 -8
  56. package/crates/tish_lsp/src/main.rs +41 -43
  57. package/crates/tish_native/src/build.rs +38 -15
  58. package/crates/tish_native/src/lib.rs +76 -32
  59. package/crates/tish_opt/src/lib.rs +67 -50
  60. package/crates/tish_parser/src/lib.rs +36 -11
  61. package/crates/tish_parser/src/parser.rs +172 -87
  62. package/crates/tish_runtime/src/http.rs +15 -6
  63. package/crates/tish_runtime/src/http_fetch.rs +24 -14
  64. package/crates/tish_runtime/src/lib.rs +224 -168
  65. package/crates/tish_runtime/src/promise.rs +1 -5
  66. package/crates/tish_runtime/src/ws.rs +45 -20
  67. package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
  68. package/crates/tish_ui/src/jsx.rs +41 -22
  69. package/crates/tish_ui/src/lib.rs +2 -2
  70. package/crates/tish_vm/src/vm.rs +320 -116
  71. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
  72. package/crates/tish_wasm/src/lib.rs +38 -28
  73. package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
  74. package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
  75. package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
  76. package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
  77. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  78. package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
  79. package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
  80. package/package.json +1 -1
  81. package/platform/darwin-arm64/tish +0 -0
  82. package/platform/darwin-x64/tish +0 -0
  83. package/platform/linux-arm64/tish +0 -0
  84. package/platform/linux-x64/tish +0 -0
  85. package/platform/win32-x64/tish.exe +0 -0
@@ -4,9 +4,9 @@ use std::collections::HashMap;
4
4
  use std::sync::Arc;
5
5
 
6
6
  use tishlang_ast::{
7
- ArrayElement, ArrowBody, BinOp, CallArg, DestructElement, DestructPattern, Expr,
8
- ExportDeclaration, FunParam, JsxAttrValue, JsxChild, JsxProp, Literal, LogicalAssignOp,
9
- MemberProp, ObjectProp, Program, Span, Statement,
7
+ ArrayElement, ArrowBody, BinOp, CallArg, DestructElement, DestructPattern, ExportDeclaration,
8
+ Expr, FunParam, JsxAttrValue, JsxChild, JsxProp, Literal, LogicalAssignOp, MemberProp,
9
+ ObjectProp, Program, Span, Statement,
10
10
  };
11
11
 
12
12
  use crate::chunk::{Chunk, Constant};
@@ -120,9 +120,7 @@ impl<'a> Compiler<'a> {
120
120
  slots.push(None);
121
121
  }
122
122
  FunParam::Destructure {
123
- pattern,
124
- default,
125
- ..
123
+ pattern, default, ..
126
124
  } => {
127
125
  if default.is_some() {
128
126
  return Err(CompileError {
@@ -274,8 +272,18 @@ impl<'a> Compiler<'a> {
274
272
  ..
275
273
  } = body_expr
276
274
  {
277
- if let (Expr::Member { object: lo, prop: MemberProp::Name(p), .. }, Expr::Member { object: ro, prop: MemberProp::Name(pr), .. }) =
278
- (left.as_ref(), right.as_ref())
275
+ if let (
276
+ Expr::Member {
277
+ object: lo,
278
+ prop: MemberProp::Name(p),
279
+ ..
280
+ },
281
+ Expr::Member {
282
+ object: ro,
283
+ prop: MemberProp::Name(pr),
284
+ ..
285
+ },
286
+ ) = (left.as_ref(), right.as_ref())
279
287
  {
280
288
  if p != pr {
281
289
  return None;
@@ -327,8 +335,14 @@ impl<'a> Compiler<'a> {
327
335
  ..
328
336
  } = body_expr
329
337
  {
330
- if let (Expr::Ident { name: left_name, .. }, Expr::Ident { name: right_name, .. }) =
331
- (left.as_ref(), right.as_ref())
338
+ if let (
339
+ Expr::Ident {
340
+ name: left_name, ..
341
+ },
342
+ Expr::Ident {
343
+ name: right_name, ..
344
+ },
345
+ ) = (left.as_ref(), right.as_ref())
332
346
  {
333
347
  if left_name.as_ref() == param_a && right_name.as_ref() == param_b {
334
348
  return Some(true);
@@ -360,7 +374,10 @@ impl<'a> Compiler<'a> {
360
374
  ArrowBody::Expr(e) => e.as_ref(),
361
375
  ArrowBody::Block(stmt) => {
362
376
  let s = stmt.as_ref();
363
- if let Statement::Return { value: Some(ref e), .. } = s {
377
+ if let Statement::Return {
378
+ value: Some(ref e), ..
379
+ } = s
380
+ {
364
381
  e
365
382
  } else if let Statement::ExprStmt { expr: ref e, .. } = s {
366
383
  e
@@ -376,9 +393,14 @@ impl<'a> Compiler<'a> {
376
393
  }
377
394
  }
378
395
  // Binary: x op const or const op x
379
- if let Expr::Binary { left, op, right, .. } = expr_ref {
380
- let left_is_param = matches!(left.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
381
- let right_is_param = matches!(right.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
396
+ if let Expr::Binary {
397
+ left, op, right, ..
398
+ } = expr_ref
399
+ {
400
+ let left_is_param =
401
+ matches!(left.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
402
+ let right_is_param =
403
+ matches!(right.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
382
404
  let left_is_literal = matches!(left.as_ref(), Expr::Literal { .. });
383
405
  let right_is_literal = matches!(right.as_ref(), Expr::Literal { .. });
384
406
  if left_is_param && right_is_literal {
@@ -412,7 +434,10 @@ impl<'a> Compiler<'a> {
412
434
  ArrowBody::Expr(e) => e.as_ref(),
413
435
  ArrowBody::Block(stmt) => {
414
436
  let s = stmt.as_ref();
415
- if let Statement::Return { value: Some(ref e), .. } = s {
437
+ if let Statement::Return {
438
+ value: Some(ref e), ..
439
+ } = s
440
+ {
416
441
  e
417
442
  } else if let Statement::ExprStmt { expr: ref e, .. } = s {
418
443
  e
@@ -421,12 +446,29 @@ impl<'a> Compiler<'a> {
421
446
  }
422
447
  }
423
448
  };
424
- if let Expr::Binary { left, op, right, .. } = expr_ref {
425
- if !matches!(op, BinOp::Eq | BinOp::Ne | BinOp::StrictEq | BinOp::StrictNe | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::And | BinOp::Or) {
449
+ if let Expr::Binary {
450
+ left, op, right, ..
451
+ } = expr_ref
452
+ {
453
+ if !matches!(
454
+ op,
455
+ BinOp::Eq
456
+ | BinOp::Ne
457
+ | BinOp::StrictEq
458
+ | BinOp::StrictNe
459
+ | BinOp::Lt
460
+ | BinOp::Le
461
+ | BinOp::Gt
462
+ | BinOp::Ge
463
+ | BinOp::And
464
+ | BinOp::Or
465
+ ) {
426
466
  return None;
427
467
  }
428
- let left_is_param = matches!(left.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
429
- let right_is_param = matches!(right.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
468
+ let left_is_param =
469
+ matches!(left.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
470
+ let right_is_param =
471
+ matches!(right.as_ref(), Expr::Ident { name, .. } if name.as_ref() == param_name);
430
472
  let left_is_literal = matches!(left.as_ref(), Expr::Literal { .. });
431
473
  let right_is_literal = matches!(right.as_ref(), Expr::Literal { .. });
432
474
  if left_is_param && right_is_literal {
@@ -534,10 +576,9 @@ impl<'a> Compiler<'a> {
534
576
  continue_patches: Vec::new(),
535
577
  continue_is_forward_jump: false,
536
578
  });
537
- self.breakable_stack
538
- .push(Breakable::Loop {
539
- unwind_depth: self.block_depth,
540
- });
579
+ self.breakable_stack.push(Breakable::Loop {
580
+ unwind_depth: self.block_depth,
581
+ });
541
582
  self.compile_expr(cond)?;
542
583
  let jump_out = self.emit_jump(Opcode::JumpIfFalse);
543
584
  // JumpIfFalse already pops condition when taking body
@@ -580,10 +621,9 @@ impl<'a> Compiler<'a> {
580
621
  continue_patches: Vec::new(),
581
622
  continue_is_forward_jump: true,
582
623
  });
583
- self.breakable_stack
584
- .push(Breakable::Loop {
585
- unwind_depth: self.block_depth,
586
- });
624
+ self.breakable_stack.push(Breakable::Loop {
625
+ unwind_depth: self.block_depth,
626
+ });
587
627
  self.compile_statement(body)?;
588
628
  let update_start = self.chunk.code.len();
589
629
  if let Some(u) = update {
@@ -604,7 +644,12 @@ impl<'a> Compiler<'a> {
604
644
  self.breakable_stack.pop();
605
645
  self.scope.pop();
606
646
  }
607
- Statement::ForOf { name, iterable, body, .. } => {
647
+ Statement::ForOf {
648
+ name,
649
+ iterable,
650
+ body,
651
+ ..
652
+ } => {
608
653
  self.compile_expr(iterable)?;
609
654
  self.scope.push(HashMap::new());
610
655
  let arr_name = Arc::from("__forof_arr__");
@@ -615,12 +660,18 @@ impl<'a> Compiler<'a> {
615
660
  let len_idx = self.name_idx(&len_name);
616
661
  let name_idx = self.name_idx(name);
617
662
  self.emit_u16(Opcode::DeclareVar, arr_idx);
618
- self.scope.last_mut().unwrap().insert(arr_name.clone(), false);
663
+ self.scope
664
+ .last_mut()
665
+ .unwrap()
666
+ .insert(arr_name.clone(), false);
619
667
  self.emit_u16(Opcode::LoadVar, arr_idx);
620
668
  let len_name_idx = self.name_idx(&Arc::from("length"));
621
669
  self.emit_u16(Opcode::GetMember, len_name_idx);
622
670
  self.emit_u16(Opcode::DeclareVar, len_idx);
623
- self.scope.last_mut().unwrap().insert(len_name.clone(), false);
671
+ self.scope
672
+ .last_mut()
673
+ .unwrap()
674
+ .insert(len_name.clone(), false);
624
675
  let zero_idx = self.constant_idx(Constant::Number(0.0));
625
676
  self.emit(Opcode::LoadConst);
626
677
  self.chunk.write_u16(zero_idx);
@@ -632,15 +683,17 @@ impl<'a> Compiler<'a> {
632
683
  continue_patches: Vec::new(),
633
684
  continue_is_forward_jump: false,
634
685
  });
635
- self.breakable_stack
636
- .push(Breakable::Loop {
637
- unwind_depth: self.block_depth,
638
- });
686
+ self.breakable_stack.push(Breakable::Loop {
687
+ unwind_depth: self.block_depth,
688
+ });
639
689
  self.emit_u16(Opcode::LoadVar, arr_idx);
640
690
  self.emit_u16(Opcode::LoadVar, i_idx);
641
691
  self.emit(Opcode::GetIndex);
642
692
  self.emit_u16(Opcode::DeclareVar, name_idx);
643
- self.scope.last_mut().unwrap().insert(Arc::clone(name), false);
693
+ self.scope
694
+ .last_mut()
695
+ .unwrap()
696
+ .insert(Arc::clone(name), false);
644
697
  self.compile_statement(body)?;
645
698
  self.emit_u16(Opcode::LoadVar, i_idx);
646
699
  let one_idx = self.constant_idx(Constant::Number(1.0));
@@ -678,9 +731,8 @@ impl<'a> Compiler<'a> {
678
731
  }
679
732
  Statement::Break { .. } => {
680
733
  let unwind_depth = match self.breakable_stack.last() {
681
- Some(Breakable::Loop { unwind_depth }) | Some(Breakable::Switch { unwind_depth }) => {
682
- *unwind_depth
683
- }
734
+ Some(Breakable::Loop { unwind_depth })
735
+ | Some(Breakable::Switch { unwind_depth }) => *unwind_depth,
684
736
  None => {
685
737
  return Err(CompileError {
686
738
  message: "break not inside a loop or switch".to_string(),
@@ -694,7 +746,11 @@ impl<'a> Compiler<'a> {
694
746
  self.loop_stack.last_mut().unwrap().break_patches.push(pos);
695
747
  }
696
748
  Some(Breakable::Switch { .. }) => {
697
- self.switch_stack.last_mut().unwrap().break_patches.push(pos);
749
+ self.switch_stack
750
+ .last_mut()
751
+ .unwrap()
752
+ .break_patches
753
+ .push(pos);
698
754
  }
699
755
  None => {}
700
756
  }
@@ -764,7 +820,10 @@ impl<'a> Compiler<'a> {
764
820
  self.chunk.write_u16(idx);
765
821
  let idx = self.name_idx(name);
766
822
  self.emit_u16(Opcode::DeclareVar, idx);
767
- self.scope.last_mut().unwrap().insert(Arc::clone(name), false);
823
+ self.scope
824
+ .last_mut()
825
+ .unwrap()
826
+ .insert(Arc::clone(name), false);
768
827
  }
769
828
  Statement::DoWhile { body, cond, .. } => {
770
829
  let start = self.chunk.code.len();
@@ -773,10 +832,9 @@ impl<'a> Compiler<'a> {
773
832
  continue_patches: Vec::new(),
774
833
  continue_is_forward_jump: false,
775
834
  });
776
- self.breakable_stack
777
- .push(Breakable::Loop {
778
- unwind_depth: self.block_depth,
779
- });
835
+ self.breakable_stack.push(Breakable::Loop {
836
+ unwind_depth: self.block_depth,
837
+ });
780
838
  self.compile_statement(body)?;
781
839
  let cond_start = self.chunk.code.len();
782
840
  self.compile_expr(cond)?;
@@ -794,7 +852,12 @@ impl<'a> Compiler<'a> {
794
852
  self.patch_jump(p, end);
795
853
  }
796
854
  }
797
- Statement::Switch { expr, cases, default_body, .. } => {
855
+ Statement::Switch {
856
+ expr,
857
+ cases,
858
+ default_body,
859
+ ..
860
+ } => {
798
861
  let switch_unwind_depth = self.block_depth;
799
862
  self.switch_stack.push(SwitchInfo {
800
863
  break_patches: Vec::new(),
@@ -899,7 +962,8 @@ impl<'a> Compiler<'a> {
899
962
  if let Some(finally) = finally_body {
900
963
  self.compile_statement(finally)?;
901
964
  }
902
- let catch_offset = catch_start.wrapping_sub(catch_offset_pos).wrapping_sub(3) as u16;
965
+ let catch_offset =
966
+ catch_start.wrapping_sub(catch_offset_pos).wrapping_sub(3) as u16;
903
967
  self.chunk.code[catch_offset_pos + 1] = (catch_offset >> 8) as u8;
904
968
  self.chunk.code[catch_offset_pos + 2] = (catch_offset & 0xff) as u8;
905
969
  }
@@ -1008,7 +1072,9 @@ impl<'a> Compiler<'a> {
1008
1072
  let idx = self.name_idx(name);
1009
1073
  self.emit_u16(Opcode::LoadVar, idx);
1010
1074
  }
1011
- Expr::Binary { left, op, right, .. } => {
1075
+ Expr::Binary {
1076
+ left, op, right, ..
1077
+ } => {
1012
1078
  match op {
1013
1079
  BinOp::And => {
1014
1080
  // Short-circuit: a && b => if !a then a else b
@@ -1049,16 +1115,29 @@ impl<'a> Compiler<'a> {
1049
1115
  && args.len() == 1
1050
1116
  && matches!(args[0], CallArg::Expr(_))
1051
1117
  {
1052
- if let (Expr::Member { object, prop: MemberProp::Name(key), optional: false, .. }, CallArg::Expr(cmp_expr)) =
1053
- (callee.as_ref(), &args[0])
1118
+ if let (
1119
+ Expr::Member {
1120
+ object,
1121
+ prop: MemberProp::Name(key),
1122
+ optional: false,
1123
+ ..
1124
+ },
1125
+ CallArg::Expr(cmp_expr),
1126
+ ) = (callee.as_ref(), &args[0])
1054
1127
  {
1055
1128
  if key.as_ref() == "sort" {
1056
- if let Some(ascending) = Self::detect_numeric_sort_comparator(cmp_expr) {
1129
+ if let Some(ascending) = Self::detect_numeric_sort_comparator(cmp_expr)
1130
+ {
1057
1131
  self.compile_expr(object)?;
1058
- self.emit_u8(Opcode::ArraySortNumeric, if ascending { 0 } else { 1 });
1132
+ self.emit_u8(
1133
+ Opcode::ArraySortNumeric,
1134
+ if ascending { 0 } else { 1 },
1135
+ );
1059
1136
  return Ok(());
1060
1137
  }
1061
- if let Some((prop, ascending)) = Self::detect_property_sort_comparator(cmp_expr) {
1138
+ if let Some((prop, ascending)) =
1139
+ Self::detect_property_sort_comparator(cmp_expr)
1140
+ {
1062
1141
  self.compile_expr(object)?;
1063
1142
  let prop_idx = self.constant_idx(Constant::String(prop));
1064
1143
  self.emit(Opcode::ArraySortByProperty);
@@ -1211,7 +1290,9 @@ impl<'a> Compiler<'a> {
1211
1290
  self.patch_jump(jump_end, self.chunk.code.len());
1212
1291
  }
1213
1292
  Expr::Array { elements, .. } => {
1214
- let has_spread = elements.iter().any(|e| matches!(e, ArrayElement::Spread(_)));
1293
+ let has_spread = elements
1294
+ .iter()
1295
+ .any(|e| matches!(e, ArrayElement::Spread(_)));
1215
1296
  if has_spread {
1216
1297
  // Build array incrementally: start with [], concat each element
1217
1298
  self.emit_u16(Opcode::NewArray, 0);
@@ -1376,7 +1457,9 @@ impl<'a> Compiler<'a> {
1376
1457
  self.emit(Opcode::Dup);
1377
1458
  self.emit_u16(Opcode::StoreVar, idx);
1378
1459
  }
1379
- Expr::CompoundAssign { name, op, value, .. } => {
1460
+ Expr::CompoundAssign {
1461
+ name, op, value, ..
1462
+ } => {
1380
1463
  let idx = self.name_idx(name);
1381
1464
  self.emit_u16(Opcode::LoadVar, idx);
1382
1465
  self.compile_expr(value)?;
@@ -1384,20 +1467,32 @@ impl<'a> Compiler<'a> {
1384
1467
  self.emit(Opcode::Dup);
1385
1468
  self.emit_u16(Opcode::StoreVar, idx);
1386
1469
  }
1387
- Expr::MemberAssign { object, prop, value, .. } => {
1470
+ Expr::MemberAssign {
1471
+ object,
1472
+ prop,
1473
+ value,
1474
+ ..
1475
+ } => {
1388
1476
  self.compile_expr(object)?;
1389
1477
  self.compile_expr(value)?;
1390
1478
  let idx = self.name_idx(prop);
1391
1479
  self.emit_u16(Opcode::SetMember, idx); // SetMember pops obj, val and pushes val back
1392
1480
  }
1393
- Expr::IndexAssign { object, index, value, .. } => {
1481
+ Expr::IndexAssign {
1482
+ object,
1483
+ index,
1484
+ value,
1485
+ ..
1486
+ } => {
1394
1487
  self.compile_expr(object)?;
1395
1488
  self.compile_expr(index)?;
1396
1489
  self.compile_expr(value)?;
1397
1490
  self.emit(Opcode::Dup); // leave copy for assignment expression result
1398
1491
  self.emit(Opcode::SetIndex);
1399
1492
  }
1400
- Expr::NativeModuleLoad { spec, export_name, .. } => {
1493
+ Expr::NativeModuleLoad {
1494
+ spec, export_name, ..
1495
+ } => {
1401
1496
  let spec_idx = self.constant_idx(Constant::String(Arc::clone(spec)));
1402
1497
  let export_idx = self.constant_idx(Constant::String(Arc::clone(export_name)));
1403
1498
  self.emit(Opcode::LoadNativeExport);
@@ -1405,7 +1500,10 @@ impl<'a> Compiler<'a> {
1405
1500
  self.chunk.write_u16(export_idx);
1406
1501
  }
1407
1502
  Expr::JsxElement {
1408
- tag, props, children, ..
1503
+ tag,
1504
+ props,
1505
+ children,
1506
+ ..
1409
1507
  } => {
1410
1508
  self.compile_jsx_element(tag, props, children)?;
1411
1509
  }
@@ -1422,7 +1520,9 @@ impl<'a> Compiler<'a> {
1422
1520
  self.compile_expr(operand)?;
1423
1521
  self.emit_u16(Opcode::Call, 1);
1424
1522
  }
1425
- Expr::LogicalAssign { name, op, value, .. } => {
1523
+ Expr::LogicalAssign {
1524
+ name, op, value, ..
1525
+ } => {
1426
1526
  let idx = self.name_idx(name);
1427
1527
  match op {
1428
1528
  LogicalAssignOp::OrOr => {
@@ -1515,7 +1615,11 @@ impl<'a> Compiler<'a> {
1515
1615
  let h_idx = self.name_idx(&Arc::from("h"));
1516
1616
  self.emit_u16(Opcode::LoadGlobal, h_idx);
1517
1617
  let tag_str = tag.as_ref();
1518
- let is_component = tag_str.chars().next().map(|c| c.is_uppercase()).unwrap_or(false);
1618
+ let is_component = tag_str
1619
+ .chars()
1620
+ .next()
1621
+ .map(|c| c.is_uppercase())
1622
+ .unwrap_or(false);
1519
1623
  if is_component {
1520
1624
  let tag_idx = self.name_idx(tag);
1521
1625
  self.emit_u16(Opcode::LoadGlobal, tag_idx);
@@ -109,10 +109,19 @@ impl Opcode {
109
109
  /// Size in bytes of this instruction at `ip` (including operands). Returns None if truncated.
110
110
  pub fn instruction_size(self, code: &[u8], ip: usize) -> Option<usize> {
111
111
  let size = match self {
112
- Opcode::Nop | Opcode::Pop | Opcode::Dup | Opcode::Return | Opcode::ExitTry
113
- | Opcode::ArrayMapIdentity | Opcode::CallSpread | Opcode::ConstructSpread
114
- | Opcode::EnterBlock | Opcode::ExitBlock => 1,
115
- Opcode::ArraySortByProperty | Opcode::ArrayMapBinOp | Opcode::ArrayFilterBinOp
112
+ Opcode::Nop
113
+ | Opcode::Pop
114
+ | Opcode::Dup
115
+ | Opcode::Return
116
+ | Opcode::ExitTry
117
+ | Opcode::ArrayMapIdentity
118
+ | Opcode::CallSpread
119
+ | Opcode::ConstructSpread
120
+ | Opcode::EnterBlock
121
+ | Opcode::ExitBlock => 1,
122
+ Opcode::ArraySortByProperty
123
+ | Opcode::ArrayMapBinOp
124
+ | Opcode::ArrayFilterBinOp
116
125
  | Opcode::LoadNativeExport => 5,
117
126
  _ => 3,
118
127
  };
@@ -162,8 +162,8 @@ fn chain_jumps(code: &mut [u8]) {
162
162
  let current_offset = read_i16(code, ip + 1) as isize;
163
163
  let current_target = (ip as isize + 3 + current_offset).max(0) as usize;
164
164
  if let Some(final_target) = final_jump_target(code, ip) {
165
- let target_ok = final_target == code.len()
166
- || insn_starts.contains(&final_target);
165
+ let target_ok =
166
+ final_target == code.len() || insn_starts.contains(&final_target);
167
167
  if final_target != current_target && target_ok {
168
168
  let new_offset = final_target as i32 - (ip + 3) as i32;
169
169
  if (i16::MIN as i32..=i16::MAX as i32).contains(&new_offset) {
@@ -22,3 +22,4 @@ tishlang_ui = { path = "../tish_ui", version = ">=0.1", default-features = false
22
22
  serde_json = "1.0"
23
23
 
24
24
  [dev-dependencies]
25
+ tempfile = "3"