@tishlang/tish 1.7.0 → 1.9.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 (99) hide show
  1. package/Cargo.toml +2 -0
  2. package/README.md +2 -0
  3. package/bin/tish +0 -0
  4. package/crates/js_to_tish/src/transform/expr.rs +28 -8
  5. package/crates/js_to_tish/src/transform/stmt.rs +49 -22
  6. package/crates/tish/Cargo.toml +14 -5
  7. package/crates/tish/src/cargo_native_registry.rs +29 -0
  8. package/crates/tish/src/cli_help.rs +16 -10
  9. package/crates/tish/src/main.rs +87 -32
  10. package/crates/tish/src/repl_completion.rs +3 -3
  11. package/crates/tish/tests/cargo_example_compile.rs +1 -1
  12. package/crates/tish/tests/integration_test.rs +19 -7
  13. package/crates/tish/tests/shortcircuit.rs +1 -1
  14. package/crates/tish_ast/src/ast.rs +80 -9
  15. package/crates/tish_build_utils/Cargo.toml +4 -0
  16. package/crates/tish_build_utils/src/lib.rs +105 -2
  17. package/crates/tish_builtins/Cargo.toml +5 -1
  18. package/crates/tish_builtins/src/array.rs +13 -12
  19. package/crates/tish_builtins/src/construct.rs +34 -33
  20. package/crates/tish_builtins/src/globals.rs +12 -11
  21. package/crates/tish_builtins/src/helpers.rs +2 -1
  22. package/crates/tish_builtins/src/object.rs +3 -2
  23. package/crates/tish_builtins/src/string.rs +73 -3
  24. package/crates/tish_bytecode/src/compiler.rs +12 -14
  25. package/crates/tish_bytecode/src/opcode.rs +12 -3
  26. package/crates/tish_compile/Cargo.toml +1 -0
  27. package/crates/tish_compile/src/codegen.rs +745 -199
  28. package/crates/tish_compile/src/infer.rs +6 -0
  29. package/crates/tish_compile/src/lib.rs +4 -3
  30. package/crates/tish_compile/src/resolve.rs +180 -82
  31. package/crates/tish_compile/src/types.rs +175 -11
  32. package/crates/tish_compile_js/Cargo.toml +1 -0
  33. package/crates/tish_compile_js/src/codegen.rs +152 -29
  34. package/crates/tish_compile_js/src/lib.rs +3 -1
  35. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +31 -12
  36. package/crates/tish_core/Cargo.toml +8 -0
  37. package/crates/tish_core/src/json.rs +102 -53
  38. package/crates/tish_core/src/lib.rs +3 -1
  39. package/crates/tish_core/src/macros.rs +5 -5
  40. package/crates/tish_core/src/value.rs +53 -15
  41. package/crates/tish_core/src/vmref.rs +178 -0
  42. package/crates/tish_eval/Cargo.toml +17 -2
  43. package/crates/tish_eval/src/eval.rs +90 -28
  44. package/crates/tish_eval/src/http.rs +61 -0
  45. package/crates/tish_eval/src/lib.rs +3 -3
  46. package/crates/tish_eval/src/natives.rs +41 -0
  47. package/crates/tish_eval/src/value.rs +7 -3
  48. package/crates/tish_eval/src/value_convert.rs +13 -5
  49. package/crates/tish_fmt/src/lib.rs +120 -30
  50. package/crates/tish_lexer/src/lib.rs +20 -5
  51. package/crates/tish_lexer/src/token.rs +4 -0
  52. package/crates/tish_llvm/src/lib.rs +3 -1
  53. package/crates/tish_lsp/Cargo.toml +4 -1
  54. package/crates/tish_lsp/README.md +1 -1
  55. package/crates/tish_lsp/src/builtin_goto.rs +261 -0
  56. package/crates/tish_lsp/src/import_goto.rs +549 -0
  57. package/crates/tish_lsp/src/main.rs +502 -102
  58. package/crates/tish_native/src/build.rs +3 -2
  59. package/crates/tish_native/src/lib.rs +6 -2
  60. package/crates/tish_opt/src/lib.rs +17 -2
  61. package/crates/tish_parser/src/lib.rs +10 -3
  62. package/crates/tish_parser/src/parser.rs +346 -56
  63. package/crates/tish_pg/Cargo.toml +34 -0
  64. package/crates/tish_pg/README.md +38 -0
  65. package/crates/tish_pg/src/error.rs +52 -0
  66. package/crates/tish_pg/src/lib.rs +967 -0
  67. package/crates/tish_resolve/Cargo.toml +13 -0
  68. package/crates/tish_resolve/src/lib.rs +3436 -0
  69. package/crates/tish_resolve/src/pos.rs +133 -0
  70. package/crates/tish_runtime/Cargo.toml +68 -3
  71. package/crates/tish_runtime/src/http.rs +1123 -141
  72. package/crates/tish_runtime/src/http_fetch.rs +15 -14
  73. package/crates/tish_runtime/src/http_hyper.rs +418 -0
  74. package/crates/tish_runtime/src/http_prefork.rs +189 -0
  75. package/crates/tish_runtime/src/lib.rs +159 -29
  76. package/crates/tish_runtime/src/promise.rs +199 -36
  77. package/crates/tish_runtime/src/promise_io.rs +2 -1
  78. package/crates/tish_runtime/src/timers.rs +37 -1
  79. package/crates/tish_runtime/src/ws.rs +26 -28
  80. package/crates/tish_ui/src/jsx.rs +279 -8
  81. package/crates/tish_ui/src/lib.rs +5 -2
  82. package/crates/tish_ui/src/runtime/hooks.rs +406 -45
  83. package/crates/tish_ui/src/runtime/mod.rs +36 -9
  84. package/crates/tish_vm/Cargo.toml +15 -5
  85. package/crates/tish_vm/src/vm.rs +506 -259
  86. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +3 -1
  87. package/crates/tish_wasm/src/lib.rs +17 -14
  88. package/crates/tish_wasm_runtime/Cargo.toml +2 -1
  89. package/crates/tish_wasm_runtime/src/lib.rs +1 -1
  90. package/crates/tishlang_cargo_bindgen/Cargo.toml +1 -0
  91. package/crates/tishlang_cargo_bindgen/src/discover.rs +68 -0
  92. package/crates/tishlang_cargo_bindgen/src/lib.rs +5 -4
  93. package/justfile +8 -0
  94. package/package.json +1 -1
  95. package/platform/darwin-arm64/tish +0 -0
  96. package/platform/darwin-x64/tish +0 -0
  97. package/platform/linux-arm64/tish +0 -0
  98. package/platform/linux-x64/tish +0 -0
  99. package/platform/win32-x64/tish.exe +0 -0
@@ -159,6 +159,8 @@ impl<'a> Parser<'a> {
159
159
  }
160
160
  TokenKind::Import => self.parse_import()?,
161
161
  TokenKind::Export => self.parse_export()?,
162
+ TokenKind::Type => self.parse_type_alias()?,
163
+ TokenKind::Declare => self.parse_declare()?,
162
164
  _ => {
163
165
  let expr = self.parse_expr()?;
164
166
  let span_end = expr.span().end;
@@ -216,11 +218,26 @@ impl<'a> Parser<'a> {
216
218
  self.advance();
217
219
  }
218
220
 
221
+ let peek_end = self.peek().map(|x| x.span.end);
222
+ let last_end = statements.last().map(|s| s.span().end);
223
+ let end = match (peek_end, last_end) {
224
+ (Some(p), Some(l)) => {
225
+ if p.0 > l.0 || (p.0 == l.0 && p.1 > l.1) {
226
+ p
227
+ } else {
228
+ l
229
+ }
230
+ }
231
+ (Some(p), None) => p,
232
+ (None, Some(l)) => l,
233
+ (None, None) => span_start,
234
+ };
235
+
219
236
  Ok(Statement::Block {
220
237
  statements,
221
238
  span: Span {
222
239
  start: span_start,
223
- end: self.peek().map(|x| x.span.end).unwrap_or(span_start),
240
+ end,
224
241
  },
225
242
  })
226
243
  }
@@ -248,8 +265,12 @@ impl<'a> Parser<'a> {
248
265
  });
249
266
  }
250
267
 
251
- let name = self
252
- .expect(TokenKind::Ident)?
268
+ let name_tok = self.expect(TokenKind::Ident)?;
269
+ let name_span = Span {
270
+ start: name_tok.span.start,
271
+ end: name_tok.span.end,
272
+ };
273
+ let name = name_tok
253
274
  .literal
254
275
  .clone()
255
276
  .ok_or("Expected identifier")?;
@@ -270,6 +291,7 @@ impl<'a> Parser<'a> {
270
291
  };
271
292
  Ok(Statement::VarDecl {
272
293
  name,
294
+ name_span,
273
295
  mutable,
274
296
  type_ann,
275
297
  init,
@@ -300,12 +322,16 @@ impl<'a> Parser<'a> {
300
322
  // Rest element: ...rest
301
323
  if matches!(self.peek_kind(), Some(TokenKind::Spread)) {
302
324
  self.advance();
303
- let name = self
304
- .expect(TokenKind::Ident)?
325
+ let name_tok = self.expect(TokenKind::Ident)?;
326
+ let name_span = Span {
327
+ start: name_tok.span.start,
328
+ end: name_tok.span.end,
329
+ };
330
+ let name = name_tok
305
331
  .literal
306
332
  .clone()
307
333
  .ok_or("Expected identifier")?;
308
- elements.push(Some(DestructElement::Rest(name)));
334
+ elements.push(Some(DestructElement::Rest(name, name_span)));
309
335
  break;
310
336
  }
311
337
 
@@ -316,13 +342,16 @@ impl<'a> Parser<'a> {
316
342
  DestructElement::Pattern(Box::new(nested))
317
343
  }
318
344
  Some(TokenKind::Ident) => {
319
- let name = self
320
- .advance()
321
- .ok_or("Unexpected EOF")?
345
+ let name_tok = self.advance().ok_or("Unexpected EOF")?;
346
+ let name_span = Span {
347
+ start: name_tok.span.start,
348
+ end: name_tok.span.end,
349
+ };
350
+ let name = name_tok
322
351
  .literal
323
352
  .clone()
324
353
  .ok_or("Expected identifier")?;
325
- DestructElement::Ident(name)
354
+ DestructElement::Ident(name, name_span)
326
355
  }
327
356
  _ => return Err("Expected identifier or pattern in destructuring".to_string()),
328
357
  };
@@ -344,8 +373,12 @@ impl<'a> Parser<'a> {
344
373
  let mut props = Vec::new();
345
374
 
346
375
  while !matches!(self.peek_kind(), Some(TokenKind::RBrace)) {
347
- let key = self
348
- .expect(TokenKind::Ident)?
376
+ let key_tok = self.expect(TokenKind::Ident)?;
377
+ let key_span = Span {
378
+ start: key_tok.span.start,
379
+ end: key_tok.span.end,
380
+ };
381
+ let key = key_tok
349
382
  .literal
350
383
  .clone()
351
384
  .ok_or("Expected identifier")?;
@@ -359,19 +392,22 @@ impl<'a> Parser<'a> {
359
392
  DestructElement::Pattern(Box::new(nested))
360
393
  }
361
394
  Some(TokenKind::Ident) => {
362
- let name = self
363
- .advance()
364
- .ok_or("Unexpected EOF")?
395
+ let name_tok = self.advance().ok_or("Unexpected EOF")?;
396
+ let name_span = Span {
397
+ start: name_tok.span.start,
398
+ end: name_tok.span.end,
399
+ };
400
+ let name = name_tok
365
401
  .literal
366
402
  .clone()
367
403
  .ok_or("Expected identifier")?;
368
- DestructElement::Ident(name)
404
+ DestructElement::Ident(name, name_span)
369
405
  }
370
406
  _ => return Err("Expected identifier or pattern after ':'".to_string()),
371
407
  }
372
408
  } else {
373
409
  // Shorthand: { key } is equivalent to { key: key }
374
- DestructElement::Ident(key.clone())
410
+ DestructElement::Ident(key.clone(), key_span)
375
411
  };
376
412
 
377
413
  props.push(DestructProp { key, value });
@@ -412,8 +448,12 @@ impl<'a> Parser<'a> {
412
448
  default,
413
449
  });
414
450
  }
415
- let param_name = self
416
- .expect(TokenKind::Ident)?
451
+ let param_tok = self.expect(TokenKind::Ident)?;
452
+ let name_span = Span {
453
+ start: param_tok.span.start,
454
+ end: param_tok.span.end,
455
+ };
456
+ let param_name = param_tok
417
457
  .literal
418
458
  .clone()
419
459
  .ok_or("Expected param name")?;
@@ -431,6 +471,7 @@ impl<'a> Parser<'a> {
431
471
  };
432
472
  Ok(FunParam::Simple(TypedParam {
433
473
  name: param_name,
474
+ name_span,
434
475
  type_ann,
435
476
  default,
436
477
  }))
@@ -468,6 +509,11 @@ impl<'a> Parser<'a> {
468
509
  let name = tok.literal.clone().ok_or("Expected type name")?;
469
510
  Ok(TypeAnnotation::Simple(name))
470
511
  }
512
+ Some(TokenKind::Type | TokenKind::Declare) => {
513
+ let tok = self.advance().ok_or("Expected type name")?;
514
+ let name = tok.literal.clone().ok_or("Expected type name")?;
515
+ Ok(TypeAnnotation::Simple(name))
516
+ }
471
517
  // Handle keywords that can be type names
472
518
  Some(TokenKind::Null) => {
473
519
  self.advance();
@@ -491,8 +537,13 @@ impl<'a> Parser<'a> {
491
537
  let typ = self.parse_type_annotation()?;
492
538
  props.push((key, typ));
493
539
  if !matches!(self.peek_kind(), Some(TokenKind::RBrace)) {
494
- // Allow trailing comma or require comma between items
495
- if matches!(self.peek_kind(), Some(TokenKind::Comma)) {
540
+ // Accept `,` or `;` between items (TypeScript-style
541
+ // semicolons are common in interface/object type
542
+ // declarations); also tolerate a trailing separator.
543
+ if matches!(
544
+ self.peek_kind(),
545
+ Some(TokenKind::Comma) | Some(TokenKind::Semicolon)
546
+ ) {
496
547
  self.advance();
497
548
  }
498
549
  }
@@ -511,9 +562,7 @@ impl<'a> Parser<'a> {
511
562
  }
512
563
  }
513
564
  self.expect(TokenKind::RParen)?;
514
- // Expect => for return type
515
- self.expect(TokenKind::Assign)?; // =
516
- self.expect(TokenKind::Gt)?; // > (forms =>)
565
+ self.expect(TokenKind::Arrow)?;
517
566
  let returns = self.parse_type_annotation()?;
518
567
  Ok(TypeAnnotation::Function {
519
568
  params,
@@ -526,8 +575,12 @@ impl<'a> Parser<'a> {
526
575
 
527
576
  fn parse_fun_decl(&mut self, async_: bool) -> Result<Statement, String> {
528
577
  let span_start = self.expect(TokenKind::Fn)?.span.start;
529
- let name = self
530
- .expect(TokenKind::Ident)?
578
+ let name_tok = self.expect(TokenKind::Ident)?;
579
+ let name_span = Span {
580
+ start: name_tok.span.start,
581
+ end: name_tok.span.end,
582
+ };
583
+ let name = name_tok
531
584
  .literal
532
585
  .clone()
533
586
  .ok_or("Expected function name")?;
@@ -537,8 +590,12 @@ impl<'a> Parser<'a> {
537
590
  while !matches!(self.peek_kind(), Some(TokenKind::RParen)) {
538
591
  if matches!(self.peek_kind(), Some(TokenKind::Spread)) {
539
592
  self.advance();
540
- let param_name = self
541
- .expect(TokenKind::Ident)?
593
+ let rest_tok = self.expect(TokenKind::Ident)?;
594
+ let rest_name_span = Span {
595
+ start: rest_tok.span.start,
596
+ end: rest_tok.span.end,
597
+ };
598
+ let param_name = rest_tok
542
599
  .literal
543
600
  .clone()
544
601
  .ok_or("Expected rest param name")?;
@@ -551,6 +608,7 @@ impl<'a> Parser<'a> {
551
608
  };
552
609
  rest_param = Some(TypedParam {
553
610
  name: param_name,
611
+ name_span: rest_name_span,
554
612
  type_ann,
555
613
  default: None,
556
614
  });
@@ -589,13 +647,182 @@ impl<'a> Parser<'a> {
589
647
  Box::new(self.parse_block()?)
590
648
  };
591
649
 
650
+ // Span must cover the whole declaration through the body. `peek().start` alone can sit on
651
+ // the opening `{` (same as `span_start` at EOF) or otherwise truncate before inner spans.
652
+ let peek_start = self.peek().map(|t| t.span.start).unwrap_or(span_start);
653
+ let body_end = body.as_ref().span().end;
654
+ let end = if peek_start.0 > body_end.0
655
+ || (peek_start.0 == body_end.0 && peek_start.1 > body_end.1)
656
+ {
657
+ peek_start
658
+ } else {
659
+ body_end
660
+ };
661
+
592
662
  Ok(Statement::FunDecl {
593
663
  async_,
594
664
  name,
665
+ name_span,
595
666
  params,
596
667
  rest_param,
597
668
  return_type,
598
669
  body,
670
+ span: Span {
671
+ start: span_start,
672
+ end,
673
+ },
674
+ })
675
+ }
676
+
677
+ fn parse_type_alias(&mut self) -> Result<Statement, String> {
678
+ let span_start = self.expect(TokenKind::Type)?.span.start;
679
+ let name_tok = self.expect(TokenKind::Ident)?;
680
+ let name_span = Span {
681
+ start: name_tok.span.start,
682
+ end: name_tok.span.end,
683
+ };
684
+ let name = name_tok
685
+ .literal
686
+ .clone()
687
+ .ok_or("Expected type alias name")?;
688
+ self.expect(TokenKind::Assign)?;
689
+ let ty = self.parse_type_annotation()?;
690
+ Ok(Statement::TypeAlias {
691
+ name,
692
+ name_span,
693
+ ty,
694
+ span: self.span_end(span_start),
695
+ })
696
+ }
697
+
698
+ fn parse_declare(&mut self) -> Result<Statement, String> {
699
+ let span_start = self.expect(TokenKind::Declare)?.span.start;
700
+ let async_ = if matches!(self.peek_kind(), Some(TokenKind::Async)) {
701
+ self.advance();
702
+ true
703
+ } else {
704
+ false
705
+ };
706
+ if matches!(self.peek_kind(), Some(TokenKind::Fn)) {
707
+ return self.parse_declare_fun(span_start, async_);
708
+ }
709
+ let const_ = match self.peek_kind() {
710
+ Some(TokenKind::Let) => {
711
+ self.advance();
712
+ false
713
+ }
714
+ Some(TokenKind::Const) => {
715
+ self.advance();
716
+ true
717
+ }
718
+ _ => {
719
+ return Err(
720
+ "Expected `let`, `const`, `async fn`, or `fn` after `declare`".to_string(),
721
+ );
722
+ }
723
+ };
724
+ let name_tok = self.expect(TokenKind::Ident)?;
725
+ let name_span = Span {
726
+ start: name_tok.span.start,
727
+ end: name_tok.span.end,
728
+ };
729
+ let name = name_tok
730
+ .literal
731
+ .clone()
732
+ .ok_or("Expected identifier")?;
733
+ let type_ann = if matches!(self.peek_kind(), Some(TokenKind::Colon)) {
734
+ self.advance();
735
+ Some(self.parse_type_annotation()?)
736
+ } else {
737
+ None
738
+ };
739
+ if matches!(self.peek_kind(), Some(TokenKind::Assign)) {
740
+ return Err("`declare` cannot have an initializer".to_string());
741
+ }
742
+ Ok(Statement::DeclareVar {
743
+ name,
744
+ name_span,
745
+ type_ann,
746
+ const_,
747
+ span: self.span_end(span_start),
748
+ })
749
+ }
750
+
751
+ fn parse_declare_fun(
752
+ &mut self,
753
+ span_start: (usize, usize),
754
+ async_: bool,
755
+ ) -> Result<Statement, String> {
756
+ self.expect(TokenKind::Fn)?;
757
+ let name_tok = self.expect(TokenKind::Ident)?;
758
+ let name_span = Span {
759
+ start: name_tok.span.start,
760
+ end: name_tok.span.end,
761
+ };
762
+ let name = name_tok
763
+ .literal
764
+ .clone()
765
+ .ok_or("Expected function name")?;
766
+ self.expect(TokenKind::LParen)?;
767
+ let mut params = Vec::with_capacity(4);
768
+ let mut rest_param = None;
769
+ while !matches!(self.peek_kind(), Some(TokenKind::RParen)) {
770
+ if matches!(self.peek_kind(), Some(TokenKind::Spread)) {
771
+ self.advance();
772
+ let rest_tok = self.expect(TokenKind::Ident)?;
773
+ let rest_name_span = Span {
774
+ start: rest_tok.span.start,
775
+ end: rest_tok.span.end,
776
+ };
777
+ let param_name = rest_tok
778
+ .literal
779
+ .clone()
780
+ .ok_or("Expected rest param name")?;
781
+ let type_ann = if matches!(self.peek_kind(), Some(TokenKind::Colon)) {
782
+ self.advance();
783
+ Some(self.parse_type_annotation()?)
784
+ } else {
785
+ None
786
+ };
787
+ rest_param = Some(TypedParam {
788
+ name: param_name,
789
+ name_span: rest_name_span,
790
+ type_ann,
791
+ default: None,
792
+ });
793
+ if !matches!(self.peek_kind(), Some(TokenKind::RParen)) {
794
+ return Err("Rest parameter must be last".to_string());
795
+ }
796
+ break;
797
+ }
798
+ params.push(self.parse_fun_param()?);
799
+ if !matches!(self.peek_kind(), Some(TokenKind::RParen)) {
800
+ self.expect(TokenKind::Comma)?;
801
+ }
802
+ }
803
+ self.expect(TokenKind::RParen)?;
804
+ let return_type = if matches!(self.peek_kind(), Some(TokenKind::Colon)) {
805
+ self.advance();
806
+ Some(self.parse_type_annotation()?)
807
+ } else {
808
+ None
809
+ };
810
+ if matches!(
811
+ self.peek_kind(),
812
+ Some(TokenKind::Assign | TokenKind::LBrace | TokenKind::Indent)
813
+ ) {
814
+ return Err("`declare function` must not have a body".to_string());
815
+ }
816
+ if matches!(self.peek_kind(), Some(TokenKind::Semicolon)) {
817
+ self.advance();
818
+ }
819
+ Ok(Statement::DeclareFun {
820
+ async_,
821
+ name,
822
+ name_span,
823
+ params,
824
+ rest_param,
825
+ return_type,
599
826
  span: self.span_end(span_start),
600
827
  })
601
828
  }
@@ -640,8 +867,12 @@ impl<'a> Parser<'a> {
640
867
  let mutable = matches!(self.peek_kind(), Some(TokenKind::Let));
641
868
  let var_span_start = self.peek().map(|t| t.span.start).unwrap_or((0, 0));
642
869
  self.advance();
643
- let name = self
644
- .expect(TokenKind::Ident)?
870
+ let for_name_tok = self.expect(TokenKind::Ident)?;
871
+ let name_span = Span {
872
+ start: for_name_tok.span.start,
873
+ end: for_name_tok.span.end,
874
+ };
875
+ let name = for_name_tok
645
876
  .literal
646
877
  .clone()
647
878
  .ok_or("Expected identifier")?;
@@ -652,6 +883,7 @@ impl<'a> Parser<'a> {
652
883
  let body = Box::new(self.parse_block_or_statement()?);
653
884
  return Ok(Statement::ForOf {
654
885
  name,
886
+ name_span,
655
887
  iterable,
656
888
  body,
657
889
  span: self.span_end(span_start),
@@ -674,6 +906,7 @@ impl<'a> Parser<'a> {
674
906
  }
675
907
  Some(Box::new(Statement::VarDecl {
676
908
  name,
909
+ name_span,
677
910
  mutable,
678
911
  type_ann,
679
912
  init: init_expr,
@@ -815,13 +1048,19 @@ impl<'a> Parser<'a> {
815
1048
  let body = Box::new(self.parse_block_or_statement()?);
816
1049
 
817
1050
  let mut catch_param = None;
1051
+ let mut catch_param_span = None;
818
1052
  let mut catch_body = None;
819
1053
  let mut finally_body = None;
820
1054
 
821
1055
  if matches!(self.peek_kind(), Some(TokenKind::Catch)) {
822
1056
  self.advance();
823
1057
  self.expect(TokenKind::LParen)?;
824
- catch_param = self.expect(TokenKind::Ident)?.literal.clone();
1058
+ let catch_tok = self.expect(TokenKind::Ident)?;
1059
+ catch_param_span = Some(Span {
1060
+ start: catch_tok.span.start,
1061
+ end: catch_tok.span.end,
1062
+ });
1063
+ catch_param = catch_tok.literal.clone();
825
1064
  self.expect(TokenKind::RParen)?;
826
1065
  catch_body = Some(Box::new(self.parse_block_or_statement()?));
827
1066
  }
@@ -838,6 +1077,7 @@ impl<'a> Parser<'a> {
838
1077
  Ok(Statement::Try {
839
1078
  body,
840
1079
  catch_param,
1080
+ catch_param_span,
841
1081
  catch_body,
842
1082
  finally_body,
843
1083
  span: self.span_end(span_start),
@@ -851,25 +1091,42 @@ impl<'a> Parser<'a> {
851
1091
  self.advance();
852
1092
  let mut specs = Vec::new();
853
1093
  while !matches!(self.peek_kind(), Some(TokenKind::RBrace)) {
854
- let name = self
855
- .expect(TokenKind::Ident)?
1094
+ let name_tok = self.expect(TokenKind::Ident)?;
1095
+ let name_span = Span {
1096
+ start: name_tok.span.start,
1097
+ end: name_tok.span.end,
1098
+ };
1099
+ let name = name_tok
856
1100
  .literal
857
1101
  .clone()
858
1102
  .ok_or("Expected identifier in import")?;
859
- let alias = if matches!(self.peek_kind(), Some(TokenKind::Ident))
1103
+ let (alias, alias_span) = if matches!(self.peek_kind(), Some(TokenKind::Ident))
860
1104
  && self.peek().and_then(|t| t.literal.as_deref()) == Some("as")
861
1105
  {
862
1106
  self.advance(); // consume 'as'
863
- Some(
864
- self.expect(TokenKind::Ident)?
865
- .literal
866
- .clone()
867
- .ok_or("Expected alias after 'as'")?,
1107
+ let alias_tok = self.expect(TokenKind::Ident)?;
1108
+ let asp = Span {
1109
+ start: alias_tok.span.start,
1110
+ end: alias_tok.span.end,
1111
+ };
1112
+ (
1113
+ Some(
1114
+ alias_tok
1115
+ .literal
1116
+ .clone()
1117
+ .ok_or("Expected alias after 'as'")?,
1118
+ ),
1119
+ Some(asp),
868
1120
  )
869
1121
  } else {
870
- None
1122
+ (None, None)
871
1123
  };
872
- specs.push(ImportSpecifier::Named { name, alias });
1124
+ specs.push(ImportSpecifier::Named {
1125
+ name,
1126
+ name_span,
1127
+ alias,
1128
+ alias_span,
1129
+ });
873
1130
  if !matches!(self.peek_kind(), Some(TokenKind::RBrace)) {
874
1131
  self.expect(TokenKind::Comma)?;
875
1132
  }
@@ -883,20 +1140,31 @@ impl<'a> Parser<'a> {
883
1140
  if as_tok.literal.as_deref() != Some("as") {
884
1141
  return Err("Expected 'as' after '*' in namespace import".to_string());
885
1142
  }
886
- let alias = self
887
- .expect(TokenKind::Ident)?
1143
+ let alias_tok = self.expect(TokenKind::Ident)?;
1144
+ let name_span = Span {
1145
+ start: alias_tok.span.start,
1146
+ end: alias_tok.span.end,
1147
+ };
1148
+ let alias = alias_tok
888
1149
  .literal
889
1150
  .clone()
890
1151
  .ok_or("Expected identifier after 'as'")?;
891
- vec![ImportSpecifier::Namespace(alias)]
1152
+ vec![ImportSpecifier::Namespace {
1153
+ name: alias,
1154
+ name_span,
1155
+ }]
892
1156
  } else if matches!(self.peek_kind(), Some(TokenKind::Ident)) {
893
1157
  // Default: import X from "..."
894
- let name = self
895
- .expect(TokenKind::Ident)?
1158
+ let def_tok = self.expect(TokenKind::Ident)?;
1159
+ let name_span = Span {
1160
+ start: def_tok.span.start,
1161
+ end: def_tok.span.end,
1162
+ };
1163
+ let name = def_tok
896
1164
  .literal
897
1165
  .clone()
898
1166
  .ok_or("Expected identifier")?;
899
- vec![ImportSpecifier::Default(name)]
1167
+ vec![ImportSpecifier::Default { name, name_span }]
900
1168
  } else {
901
1169
  return Err("Expected { }, * as name, or default import".to_string());
902
1170
  };
@@ -922,6 +1190,10 @@ impl<'a> Parser<'a> {
922
1190
  self.advance();
923
1191
  let expr = self.parse_expr()?;
924
1192
  ExportDeclaration::Default(expr)
1193
+ } else if matches!(self.peek_kind(), Some(TokenKind::Type)) {
1194
+ ExportDeclaration::Named(Box::new(self.parse_type_alias()?))
1195
+ } else if matches!(self.peek_kind(), Some(TokenKind::Declare)) {
1196
+ ExportDeclaration::Named(Box::new(self.parse_declare()?))
925
1197
  } else if matches!(self.peek_kind(), Some(TokenKind::Const)) {
926
1198
  ExportDeclaration::Named(Box::new(self.parse_var_decl(false)?))
927
1199
  } else if matches!(self.peek_kind(), Some(TokenKind::Let)) {
@@ -935,7 +1207,10 @@ impl<'a> Parser<'a> {
935
1207
  }
936
1208
  ExportDeclaration::Named(Box::new(self.parse_fun_decl(async_)?))
937
1209
  } else {
938
- return Err("Expected 'default', 'const', 'let', or 'fn' after export".to_string());
1210
+ return Err(
1211
+ "Expected 'default', 'type', 'declare', 'const', 'let', or 'fn' after export"
1212
+ .to_string(),
1213
+ );
939
1214
  };
940
1215
  Ok(Statement::Export {
941
1216
  declaration: Box::new(declaration),
@@ -970,7 +1245,7 @@ impl<'a> Parser<'a> {
970
1245
  // Member assignment: obj.prop = val
971
1246
  if let Expr::Member {
972
1247
  object,
973
- prop: MemberProp::Name(prop_name),
1248
+ prop: MemberProp::Name { name: prop_name, .. },
974
1249
  ..
975
1250
  } = &left
976
1251
  {
@@ -1208,16 +1483,23 @@ impl<'a> Parser<'a> {
1208
1483
  TokenKind::Dot | TokenKind::OptionalChain => {
1209
1484
  let optional = kind == TokenKind::OptionalChain;
1210
1485
  self.advance();
1211
- let prop = self
1212
- .expect(TokenKind::Ident)?
1486
+ let prop_tok = self.expect(TokenKind::Ident)?;
1487
+ let prop = prop_tok
1213
1488
  .literal
1214
1489
  .clone()
1215
1490
  .ok_or("Expected property name")?;
1491
+ let prop_span = Span {
1492
+ start: prop_tok.span.start,
1493
+ end: prop_tok.span.end,
1494
+ };
1216
1495
  let start = expr.span().start;
1217
1496
  let end = self.peek().map(|x| x.span.start).unwrap_or(start);
1218
1497
  expr = Expr::Member {
1219
1498
  object: Box::new(expr),
1220
- prop: MemberProp::Name(prop),
1499
+ prop: MemberProp::Name {
1500
+ name: prop,
1501
+ span: prop_span,
1502
+ },
1221
1503
  optional,
1222
1504
  span: Span { start, end },
1223
1505
  };
@@ -1321,16 +1603,23 @@ impl<'a> Parser<'a> {
1321
1603
  TokenKind::Dot | TokenKind::OptionalChain => {
1322
1604
  let optional = kind == TokenKind::OptionalChain;
1323
1605
  self.advance();
1324
- let prop = self
1325
- .expect(TokenKind::Ident)?
1606
+ let prop_tok = self.expect(TokenKind::Ident)?;
1607
+ let prop = prop_tok
1326
1608
  .literal
1327
1609
  .clone()
1328
1610
  .ok_or("Expected property name")?;
1611
+ let prop_span = Span {
1612
+ start: prop_tok.span.start,
1613
+ end: prop_tok.span.end,
1614
+ };
1329
1615
  let start = expr.span().start;
1330
1616
  let end = self.peek().map(|x| x.span.start).unwrap_or(start);
1331
1617
  expr = Expr::Member {
1332
1618
  object: Box::new(expr),
1333
- prop: MemberProp::Name(prop),
1619
+ prop: MemberProp::Name {
1620
+ name: prop,
1621
+ span: prop_span,
1622
+ },
1334
1623
  optional,
1335
1624
  span: Span { start, end },
1336
1625
  };
@@ -1424,6 +1713,7 @@ impl<'a> Parser<'a> {
1424
1713
  return Ok(Expr::ArrowFunction {
1425
1714
  params: vec![FunParam::Simple(TypedParam {
1426
1715
  name: name.clone(),
1716
+ name_span: span,
1427
1717
  type_ann: None,
1428
1718
  default: None,
1429
1719
  })],
@@ -1491,7 +1781,7 @@ impl<'a> Parser<'a> {
1491
1781
  } else {
1492
1782
  let key_tok = self.advance().ok_or("Expected object key")?;
1493
1783
  let (key, key_span, is_ident_key) = match key_tok.kind {
1494
- TokenKind::Ident => {
1784
+ TokenKind::Ident | TokenKind::Type | TokenKind::Declare => {
1495
1785
  let k = key_tok.literal.clone().ok_or("Expected key")?;
1496
1786
  let sp = Span {
1497
1787
  start: key_tok.span.start,