@tishlang/tish 1.6.0 → 1.8.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 (113) 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/error.rs +2 -8
  5. package/crates/js_to_tish/src/transform/expr.rs +128 -137
  6. package/crates/js_to_tish/src/transform/stmt.rs +62 -32
  7. package/crates/tish/Cargo.toml +15 -5
  8. package/crates/tish/src/cargo_native_registry.rs +29 -0
  9. package/crates/tish/src/cli_help.rs +92 -39
  10. package/crates/tish/src/main.rs +172 -86
  11. package/crates/tish/src/repl_completion.rs +3 -3
  12. package/crates/tish/tests/cargo_example_compile.rs +4 -2
  13. package/crates/tish/tests/integration_test.rs +216 -54
  14. package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
  15. package/crates/tish/tests/shortcircuit.rs +20 -5
  16. package/crates/tish_ast/src/ast.rs +92 -23
  17. package/crates/tish_build_utils/Cargo.toml +4 -0
  18. package/crates/tish_build_utils/src/lib.rs +136 -8
  19. package/crates/tish_builtins/Cargo.toml +5 -1
  20. package/crates/tish_builtins/src/array.rs +65 -33
  21. package/crates/tish_builtins/src/construct.rs +34 -39
  22. package/crates/tish_builtins/src/globals.rs +42 -26
  23. package/crates/tish_builtins/src/helpers.rs +2 -1
  24. package/crates/tish_builtins/src/lib.rs +5 -5
  25. package/crates/tish_builtins/src/math.rs +5 -3
  26. package/crates/tish_builtins/src/object.rs +3 -2
  27. package/crates/tish_builtins/src/string.rs +144 -22
  28. package/crates/tish_bytecode/src/chunk.rs +0 -1
  29. package/crates/tish_bytecode/src/compiler.rs +173 -71
  30. package/crates/tish_bytecode/src/opcode.rs +24 -6
  31. package/crates/tish_bytecode/src/peephole.rs +2 -2
  32. package/crates/tish_compile/Cargo.toml +1 -0
  33. package/crates/tish_compile/src/codegen.rs +1621 -453
  34. package/crates/tish_compile/src/infer.rs +75 -19
  35. package/crates/tish_compile/src/lib.rs +19 -8
  36. package/crates/tish_compile/src/resolve.rs +278 -137
  37. package/crates/tish_compile/src/types.rs +184 -24
  38. package/crates/tish_compile_js/Cargo.toml +1 -0
  39. package/crates/tish_compile_js/src/codegen.rs +181 -37
  40. package/crates/tish_compile_js/src/lib.rs +3 -1
  41. package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
  42. package/crates/tish_compiler_wasm/src/lib.rs +16 -13
  43. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +69 -59
  44. package/crates/tish_core/Cargo.toml +8 -0
  45. package/crates/tish_core/src/json.rs +107 -56
  46. package/crates/tish_core/src/lib.rs +4 -2
  47. package/crates/tish_core/src/macros.rs +5 -5
  48. package/crates/tish_core/src/uri.rs +9 -6
  49. package/crates/tish_core/src/value.rs +145 -43
  50. package/crates/tish_core/src/vmref.rs +178 -0
  51. package/crates/tish_cranelift/src/link.rs +6 -9
  52. package/crates/tish_cranelift/src/lower.rs +14 -8
  53. package/crates/tish_eval/Cargo.toml +17 -2
  54. package/crates/tish_eval/src/eval.rs +474 -165
  55. package/crates/tish_eval/src/http.rs +61 -0
  56. package/crates/tish_eval/src/lib.rs +12 -8
  57. package/crates/tish_eval/src/natives.rs +136 -38
  58. package/crates/tish_eval/src/promise.rs +14 -8
  59. package/crates/tish_eval/src/timers.rs +28 -19
  60. package/crates/tish_eval/src/value.rs +17 -6
  61. package/crates/tish_eval/src/value_convert.rs +13 -5
  62. package/crates/tish_fmt/src/lib.rs +149 -43
  63. package/crates/tish_lexer/src/lib.rs +232 -63
  64. package/crates/tish_lexer/src/token.rs +10 -6
  65. package/crates/tish_llvm/src/lib.rs +17 -8
  66. package/crates/tish_lsp/Cargo.toml +4 -1
  67. package/crates/tish_lsp/README.md +1 -1
  68. package/crates/tish_lsp/src/builtin_goto.rs +261 -0
  69. package/crates/tish_lsp/src/import_goto.rs +549 -0
  70. package/crates/tish_lsp/src/main.rs +504 -106
  71. package/crates/tish_native/src/build.rs +4 -8
  72. package/crates/tish_native/src/lib.rs +54 -21
  73. package/crates/tish_opt/src/lib.rs +84 -52
  74. package/crates/tish_parser/src/lib.rs +45 -13
  75. package/crates/tish_parser/src/parser.rs +505 -130
  76. package/crates/tish_resolve/Cargo.toml +13 -0
  77. package/crates/tish_resolve/src/lib.rs +3436 -0
  78. package/crates/tish_resolve/src/pos.rs +133 -0
  79. package/crates/tish_runtime/Cargo.toml +68 -3
  80. package/crates/tish_runtime/src/http.rs +1136 -145
  81. package/crates/tish_runtime/src/http_fetch.rs +38 -27
  82. package/crates/tish_runtime/src/http_hyper.rs +418 -0
  83. package/crates/tish_runtime/src/http_prefork.rs +189 -0
  84. package/crates/tish_runtime/src/lib.rs +375 -189
  85. package/crates/tish_runtime/src/promise.rs +199 -40
  86. package/crates/tish_runtime/src/promise_io.rs +2 -1
  87. package/crates/tish_runtime/src/timers.rs +37 -1
  88. package/crates/tish_runtime/src/ws.rs +65 -42
  89. package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
  90. package/crates/tish_ui/src/jsx.rs +317 -27
  91. package/crates/tish_ui/src/lib.rs +5 -2
  92. package/crates/tish_ui/src/runtime/hooks.rs +406 -45
  93. package/crates/tish_ui/src/runtime/mod.rs +36 -9
  94. package/crates/tish_vm/Cargo.toml +15 -5
  95. package/crates/tish_vm/src/vm.rs +725 -281
  96. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +11 -4
  97. package/crates/tish_wasm/src/lib.rs +55 -42
  98. package/crates/tish_wasm_runtime/Cargo.toml +2 -1
  99. package/crates/tish_wasm_runtime/src/lib.rs +1 -1
  100. package/crates/tishlang_cargo_bindgen/Cargo.toml +26 -0
  101. package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
  102. package/crates/tishlang_cargo_bindgen/src/discover.rs +120 -0
  103. package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
  104. package/crates/tishlang_cargo_bindgen/src/lib.rs +350 -0
  105. package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
  106. package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
  107. package/justfile +8 -0
  108. package/package.json +1 -1
  109. package/platform/darwin-arm64/tish +0 -0
  110. package/platform/darwin-x64/tish +0 -0
  111. package/platform/linux-arm64/tish +0 -0
  112. package/platform/linux-x64/tish +0 -0
  113. package/platform/win32-x64/tish.exe +0 -0
package/Cargo.toml CHANGED
@@ -28,6 +28,8 @@ members = [
28
28
  "crates/tish_fmt",
29
29
  "crates/tish_lint",
30
30
  "crates/tish_lsp",
31
+ "crates/tish_resolve",
32
+ "crates/tishlang_cargo_bindgen",
31
33
  ]
32
34
  resolver = "2"
33
35
 
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  This npm package ships the **Tish CLI**. It includes platform-specific native binaries under `platform/`; **`npm install`** runs `postinstall`, which copies the correct binary to `bin/tish`. That file is what runs when you invoke `tish` — the CLI itself is native, not Node. Node **22+** is required for install scripts and tooling (e.g. semantic-release in this repo); the `tish` binary has no Node runtime dependency.
6
6
 
7
+ Those prebuilt binaries are built with **`--features full`** (http, fs, process, regex, ws) so `tish run` and the bytecode VM match a full developer toolchain. For a minimal CLI, build `tishlang` from the repo with `--no-default-features` (see the workspace `justfile`).
8
+
7
9
  ## Install
8
10
 
9
11
  ```bash
package/bin/tish CHANGED
Binary file
@@ -30,15 +30,9 @@ pub enum ConvertErrorKind {
30
30
  /// Semantic analysis error from OXC.
31
31
  Semantic(String),
32
32
  /// Unsupported construct (class, this, for-in, etc.).
33
- Unsupported {
34
- what: String,
35
- hint: Option<String>,
36
- },
33
+ Unsupported { what: String, hint: Option<String> },
37
34
  /// JS feature that cannot be expressed in Tish.
38
- Incompatible {
39
- what: String,
40
- reason: String,
41
- },
35
+ Incompatible { what: String, reason: String },
42
36
  }
43
37
 
44
38
  impl fmt::Display for ConvertErrorKind {
@@ -5,8 +5,8 @@ use std::sync::Arc;
5
5
  use oxc::ast::ast::Expression as OxcExpr;
6
6
  use oxc::semantic::Semantic;
7
7
  use tishlang_ast::{
8
- ArrayElement, ArrowBody, BinOp, CompoundOp, DestructPattern, Expr, Literal, LogicalAssignOp,
9
- FunParam, MemberProp, ObjectProp, TypedParam,
8
+ ArrayElement, ArrowBody, BinOp, CompoundOp, DestructPattern, Expr, FunParam, Literal,
9
+ LogicalAssignOp, MemberProp, ObjectProp, TypedParam,
10
10
  };
11
11
 
12
12
  use crate::error::{ConvertError, ConvertErrorKind};
@@ -57,7 +57,12 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
57
57
  let left = Box::new(convert_expr(&b.left, ctx)?);
58
58
  let right = Box::new(convert_expr(&b.right, ctx)?);
59
59
  let op = convert_bin_op(&b.operator)?;
60
- Ok(Expr::Binary { left, op, right, span })
60
+ Ok(Expr::Binary {
61
+ left,
62
+ op,
63
+ right,
64
+ span,
65
+ })
61
66
  }
62
67
  OxcExpr::UnaryExpression(u) => {
63
68
  let operand = Box::new(convert_expr(&u.argument, ctx)?);
@@ -84,9 +89,14 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
84
89
  }
85
90
  OxcExpr::StaticMemberExpression(s) => {
86
91
  let object = Box::new(convert_expr(&s.object, ctx)?);
92
+ let name = Arc::from(s.property.name.as_str());
93
+ let name_span = span_util::oxc_span_to_tish(ctx.1, &s.property);
87
94
  Ok(Expr::Member {
88
95
  object,
89
- prop: MemberProp::Name(Arc::from(s.property.name.as_str())),
96
+ prop: MemberProp::Name {
97
+ name,
98
+ span: name_span,
99
+ },
90
100
  optional: s.optional,
91
101
  span,
92
102
  })
@@ -112,10 +122,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
112
122
  })
113
123
  }
114
124
  OxcExpr::LogicalExpression(l) => {
115
- if matches!(
116
- l.operator,
117
- oxc::ast::ast::LogicalOperator::Coalesce
118
- ) {
125
+ if matches!(l.operator, oxc::ast::ast::LogicalOperator::Coalesce) {
119
126
  Ok(Expr::NullishCoalesce {
120
127
  left: Box::new(convert_expr(&l.left, ctx)?),
121
128
  right: Box::new(convert_expr(&l.right, ctx)?),
@@ -155,12 +162,12 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
155
162
  OxcExpr::ArrowFunctionExpression(arrow) => {
156
163
  let params = convert_arrow_params(&arrow.params, ctx)?;
157
164
  let body = if arrow.expression {
158
- let e = arrow
159
- .get_expression()
160
- .ok_or_else(|| ConvertError::new(ConvertErrorKind::Incompatible {
165
+ let e = arrow.get_expression().ok_or_else(|| {
166
+ ConvertError::new(ConvertErrorKind::Incompatible {
161
167
  what: "arrow expression body".into(),
162
168
  reason: "expected expression".into(),
163
- }))?;
169
+ })
170
+ })?;
164
171
  ArrowBody::Expr(Box::new(convert_expr(e, ctx)?))
165
172
  } else {
166
173
  let stmts = super::stmt::convert_statements(&arrow.body.statements, ctx.0, ctx.1)?;
@@ -169,11 +176,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
169
176
  span: span_util::oxc_span_to_tish(ctx.1, &*arrow.body),
170
177
  }))
171
178
  };
172
- Ok(Expr::ArrowFunction {
173
- params,
174
- body,
175
- span,
176
- })
179
+ Ok(Expr::ArrowFunction { params, body, span })
177
180
  }
178
181
  OxcExpr::AwaitExpression(a) => Ok(Expr::Await {
179
182
  operand: Box::new(convert_expr(&a.argument, ctx)?),
@@ -226,11 +229,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
226
229
  }))
227
230
  }
228
231
  };
229
- Ok(Expr::ArrowFunction {
230
- params,
231
- body,
232
- span,
233
- })
232
+ Ok(Expr::ArrowFunction { params, body, span })
234
233
  }
235
234
  _ => Err(ConvertError::new(ConvertErrorKind::Unsupported {
236
235
  what: format!("expression: {:?}", std::mem::discriminant(expr)),
@@ -247,9 +246,14 @@ fn convert_chain_element(
247
246
  match ce {
248
247
  oxc::ast::ast::ChainElement::StaticMemberExpression(m) => {
249
248
  let object = Box::new(convert_expr(&m.object, ctx)?);
249
+ let name = Arc::from(m.property.name.as_str());
250
+ let name_span = span_util::oxc_span_to_tish(ctx.1, &m.property);
250
251
  Ok(Expr::Member {
251
252
  object,
252
- prop: MemberProp::Name(Arc::from(m.property.name.as_str())),
253
+ prop: MemberProp::Name {
254
+ name,
255
+ span: name_span,
256
+ },
253
257
  optional: m.optional,
254
258
  span,
255
259
  })
@@ -285,7 +289,10 @@ fn convert_call_arg(
285
289
  ) -> Result<tishlang_ast::CallArg, ConvertError> {
286
290
  if arg.is_spread() {
287
291
  if let oxc::ast::ast::Argument::SpreadElement(s) = arg {
288
- Ok(tishlang_ast::CallArg::Spread(convert_expr(&s.argument, ctx)?))
292
+ Ok(tishlang_ast::CallArg::Spread(convert_expr(
293
+ &s.argument,
294
+ ctx,
295
+ )?))
289
296
  } else {
290
297
  unreachable!()
291
298
  }
@@ -307,10 +314,12 @@ fn convert_array_element(
307
314
  oxc::ast::ast::ArrayExpressionElement::SpreadElement(s) => {
308
315
  Ok(ArrayElement::Spread(convert_expr(&s.argument, ctx)?))
309
316
  }
310
- oxc::ast::ast::ArrayExpressionElement::Elision(_) => Ok(ArrayElement::Expr(Expr::Literal {
311
- value: Literal::Null,
312
- span: span_util::stub_span(),
313
- })),
317
+ oxc::ast::ast::ArrayExpressionElement::Elision(_) => {
318
+ Ok(ArrayElement::Expr(Expr::Literal {
319
+ value: Literal::Null,
320
+ span: span_util::stub_span(),
321
+ }))
322
+ }
314
323
  _ => {
315
324
  if let Some(e) = el.as_expression() {
316
325
  Ok(ArrayElement::Expr(convert_expr(e, ctx)?))
@@ -358,77 +367,59 @@ fn convert_assignment(
358
367
  let name = id.name.as_str();
359
368
  let value = Box::new(convert_expr(right, ctx)?);
360
369
  return match &a.operator {
361
- oxc::ast::ast::AssignmentOperator::Assign => {
362
- Ok(Expr::Assign {
363
- name: Arc::from(name),
364
- value,
365
- span,
366
- })
367
- }
368
- oxc::ast::ast::AssignmentOperator::Addition => {
369
- Ok(Expr::CompoundAssign {
370
- name: Arc::from(name),
371
- op: CompoundOp::Add,
372
- value,
373
- span,
374
- })
375
- }
376
- oxc::ast::ast::AssignmentOperator::Subtraction => {
377
- Ok(Expr::CompoundAssign {
378
- name: Arc::from(name),
379
- op: CompoundOp::Sub,
380
- value,
381
- span,
382
- })
383
- }
384
- oxc::ast::ast::AssignmentOperator::Multiplication => {
385
- Ok(Expr::CompoundAssign {
386
- name: Arc::from(name),
387
- op: CompoundOp::Mul,
388
- value,
389
- span,
390
- })
391
- }
392
- oxc::ast::ast::AssignmentOperator::Division => {
393
- Ok(Expr::CompoundAssign {
394
- name: Arc::from(name),
395
- op: CompoundOp::Div,
396
- value,
397
- span,
398
- })
399
- }
400
- oxc::ast::ast::AssignmentOperator::Remainder => {
401
- Ok(Expr::CompoundAssign {
402
- name: Arc::from(name),
403
- op: CompoundOp::Mod,
404
- value,
405
- span,
406
- })
407
- }
408
- oxc::ast::ast::AssignmentOperator::LogicalAnd => {
409
- Ok(Expr::LogicalAssign {
410
- name: Arc::from(name),
411
- op: LogicalAssignOp::AndAnd,
412
- value,
413
- span,
414
- })
415
- }
416
- oxc::ast::ast::AssignmentOperator::LogicalOr => {
417
- Ok(Expr::LogicalAssign {
418
- name: Arc::from(name),
419
- op: LogicalAssignOp::OrOr,
420
- value,
421
- span,
422
- })
423
- }
424
- oxc::ast::ast::AssignmentOperator::LogicalNullish => {
425
- Ok(Expr::LogicalAssign {
426
- name: Arc::from(name),
427
- op: LogicalAssignOp::Nullish,
428
- value,
429
- span,
430
- })
431
- }
370
+ oxc::ast::ast::AssignmentOperator::Assign => Ok(Expr::Assign {
371
+ name: Arc::from(name),
372
+ value,
373
+ span,
374
+ }),
375
+ oxc::ast::ast::AssignmentOperator::Addition => Ok(Expr::CompoundAssign {
376
+ name: Arc::from(name),
377
+ op: CompoundOp::Add,
378
+ value,
379
+ span,
380
+ }),
381
+ oxc::ast::ast::AssignmentOperator::Subtraction => Ok(Expr::CompoundAssign {
382
+ name: Arc::from(name),
383
+ op: CompoundOp::Sub,
384
+ value,
385
+ span,
386
+ }),
387
+ oxc::ast::ast::AssignmentOperator::Multiplication => Ok(Expr::CompoundAssign {
388
+ name: Arc::from(name),
389
+ op: CompoundOp::Mul,
390
+ value,
391
+ span,
392
+ }),
393
+ oxc::ast::ast::AssignmentOperator::Division => Ok(Expr::CompoundAssign {
394
+ name: Arc::from(name),
395
+ op: CompoundOp::Div,
396
+ value,
397
+ span,
398
+ }),
399
+ oxc::ast::ast::AssignmentOperator::Remainder => Ok(Expr::CompoundAssign {
400
+ name: Arc::from(name),
401
+ op: CompoundOp::Mod,
402
+ value,
403
+ span,
404
+ }),
405
+ oxc::ast::ast::AssignmentOperator::LogicalAnd => Ok(Expr::LogicalAssign {
406
+ name: Arc::from(name),
407
+ op: LogicalAssignOp::AndAnd,
408
+ value,
409
+ span,
410
+ }),
411
+ oxc::ast::ast::AssignmentOperator::LogicalOr => Ok(Expr::LogicalAssign {
412
+ name: Arc::from(name),
413
+ op: LogicalAssignOp::OrOr,
414
+ value,
415
+ span,
416
+ }),
417
+ oxc::ast::ast::AssignmentOperator::LogicalNullish => Ok(Expr::LogicalAssign {
418
+ name: Arc::from(name),
419
+ op: LogicalAssignOp::Nullish,
420
+ value,
421
+ span,
422
+ }),
432
423
  _ => Err(ConvertError::new(ConvertErrorKind::Unsupported {
433
424
  what: "assignment operator".into(),
434
425
  hint: None,
@@ -458,24 +449,14 @@ fn convert_update_expr(
458
449
  }
459
450
  };
460
451
  Ok(match (u.operator, u.prefix) {
461
- (oxc::ast::ast::UpdateOperator::Increment, true) => {
462
- Expr::PrefixInc { name, span }
463
- }
464
- (oxc::ast::ast::UpdateOperator::Increment, false) => {
465
- Expr::PostfixInc { name, span }
466
- }
467
- (oxc::ast::ast::UpdateOperator::Decrement, true) => {
468
- Expr::PrefixDec { name, span }
469
- }
470
- (oxc::ast::ast::UpdateOperator::Decrement, false) => {
471
- Expr::PostfixDec { name, span }
472
- }
452
+ (oxc::ast::ast::UpdateOperator::Increment, true) => Expr::PrefixInc { name, span },
453
+ (oxc::ast::ast::UpdateOperator::Increment, false) => Expr::PostfixInc { name, span },
454
+ (oxc::ast::ast::UpdateOperator::Decrement, true) => Expr::PrefixDec { name, span },
455
+ (oxc::ast::ast::UpdateOperator::Decrement, false) => Expr::PostfixDec { name, span },
473
456
  })
474
457
  }
475
458
 
476
- fn convert_bin_op(
477
- op: &oxc::ast::ast::BinaryOperator,
478
- ) -> Result<BinOp, ConvertError> {
459
+ fn convert_bin_op(op: &oxc::ast::ast::BinaryOperator) -> Result<BinOp, ConvertError> {
479
460
  Ok(match op {
480
461
  oxc::ast::ast::BinaryOperator::Equality => BinOp::Eq,
481
462
  oxc::ast::ast::BinaryOperator::Inequality => BinOp::Ne,
@@ -533,8 +514,11 @@ pub fn convert_params(
533
514
  for (i, p) in params.items.iter().enumerate() {
534
515
  if params.rest.is_some() && i == params.items.len() - 1 {
535
516
  if let Some(rest) = &params.rest {
536
- let rest_name = match &rest.rest.argument {
537
- oxc::ast::ast::BindingPattern::BindingIdentifier(b) => b.name.as_str(),
517
+ let (rest_name, rest_name_span) = match &rest.rest.argument {
518
+ oxc::ast::ast::BindingPattern::BindingIdentifier(b) => (
519
+ b.name.as_str(),
520
+ crate::span_util::oxc_span_to_tish(ctx.1, b.as_ref()),
521
+ ),
538
522
  _ => {
539
523
  return Err(ConvertError::new(ConvertErrorKind::Unsupported {
540
524
  what: "rest param with non-identifier".into(),
@@ -544,6 +528,7 @@ pub fn convert_params(
544
528
  };
545
529
  rest_param = Some(TypedParam {
546
530
  name: Arc::from(rest_name),
531
+ name_span: rest_name_span,
547
532
  type_ann: None,
548
533
  default: None,
549
534
  });
@@ -553,31 +538,36 @@ pub fn convert_params(
553
538
  // params.items contains FormalParameter structs (not enum)
554
539
  let fp = p;
555
540
  {
556
- let name = match &fp.pattern {
557
- oxc::ast::ast::BindingPattern::BindingIdentifier(b) => b.name.as_str(),
558
- _ => {
559
- return Err(ConvertError::new(ConvertErrorKind::Unsupported {
560
- what: "destructuring in params".into(),
561
- hint: None,
562
- }))
563
- }
564
- };
565
- let default = fp
566
- .initializer
567
- .as_ref()
568
- .map(|e| convert_expr(e, ctx))
569
- .transpose()?;
570
- typed_params.push(FunParam::Simple(TypedParam {
571
- name: Arc::from(name),
572
- type_ann: None,
573
- default,
574
- }));
541
+ let (name, name_span) = match &fp.pattern {
542
+ oxc::ast::ast::BindingPattern::BindingIdentifier(b) => {
543
+ (b.name.as_str(), crate::span_util::oxc_span_to_tish(ctx.1, b.as_ref()))
544
+ }
545
+ _ => {
546
+ return Err(ConvertError::new(ConvertErrorKind::Unsupported {
547
+ what: "destructuring in params".into(),
548
+ hint: None,
549
+ }))
550
+ }
551
+ };
552
+ let default = fp
553
+ .initializer
554
+ .as_ref()
555
+ .map(|e| convert_expr(e, ctx))
556
+ .transpose()?;
557
+ typed_params.push(FunParam::Simple(TypedParam {
558
+ name: Arc::from(name),
559
+ name_span,
560
+ type_ann: None,
561
+ default,
562
+ }));
575
563
  }
576
564
  }
577
565
  if rest_param.is_none() {
578
566
  if let Some(rest) = &params.rest {
579
- let rest_name = match &rest.rest.argument {
580
- oxc::ast::ast::BindingPattern::BindingIdentifier(b) => b.name.as_str(),
567
+ let (rest_name, rest_name_span) = match &rest.rest.argument {
568
+ oxc::ast::ast::BindingPattern::BindingIdentifier(b) => {
569
+ (b.name.as_str(), crate::span_util::oxc_span_to_tish(ctx.1, b.as_ref()))
570
+ }
581
571
  _ => {
582
572
  return Err(ConvertError::new(ConvertErrorKind::Unsupported {
583
573
  what: "rest param with non-identifier".into(),
@@ -587,6 +577,7 @@ pub fn convert_params(
587
577
  };
588
578
  rest_param = Some(TypedParam {
589
579
  name: Arc::from(rest_name),
580
+ name_span: rest_name_span,
590
581
  type_ann: None,
591
582
  default: None,
592
583
  });
@@ -4,7 +4,7 @@ use std::sync::Arc;
4
4
 
5
5
  use oxc::ast::ast::Statement as OxcStmt;
6
6
  use oxc::semantic::Semantic;
7
- use tishlang_ast::{Statement, Span};
7
+ use tishlang_ast::{Span, Statement};
8
8
 
9
9
  use super::expr;
10
10
  use crate::error::{ConvertError, ConvertErrorKind};
@@ -19,9 +19,7 @@ pub fn convert_statements(
19
19
  source: &str,
20
20
  ) -> Result<Vec<Statement>, ConvertError> {
21
21
  let ctx = (semantic, source);
22
- body.iter()
23
- .map(|s| convert_statement(s, &ctx))
24
- .collect()
22
+ body.iter().map(|s| convert_statement(s, &ctx)).collect()
25
23
  }
26
24
 
27
25
  fn convert_statement(stmt: &OxcStmt<'_>, ctx: &Ctx<'_>) -> Result<Statement, ConvertError> {
@@ -29,10 +27,7 @@ fn convert_statement(stmt: &OxcStmt<'_>, ctx: &Ctx<'_>) -> Result<Statement, Con
29
27
  match stmt {
30
28
  OxcStmt::BlockStatement(b) => {
31
29
  let statements = convert_statements(&b.body, ctx.0, ctx.1)?;
32
- Ok(Statement::Block {
33
- statements,
34
- span,
35
- })
30
+ Ok(Statement::Block { statements, span })
36
31
  }
37
32
  OxcStmt::VariableDeclaration(v) => convert_var_decl(v, ctx, span),
38
33
  OxcStmt::ExpressionStatement(e) => {
@@ -146,12 +141,18 @@ fn convert_var_decl(
146
141
  if v.declarations.len() == 1 {
147
142
  let d = &v.declarations[0];
148
143
  let id = &d.id;
149
- let init = d.init.as_ref().map(|i| expr::convert_expr(i, ctx)).transpose()?;
144
+ let init = d
145
+ .init
146
+ .as_ref()
147
+ .map(|i| expr::convert_expr(i, ctx))
148
+ .transpose()?;
150
149
  match id {
151
150
  oxc::ast::ast::BindingPattern::BindingIdentifier(b) => {
152
151
  let name: Arc<str> = Arc::from(b.name.as_str());
152
+ let name_span = span_util::oxc_span_to_tish(ctx.1, b.as_ref());
153
153
  Ok(Statement::VarDecl {
154
154
  name,
155
+ name_span,
155
156
  mutable,
156
157
  type_ann: None,
157
158
  init,
@@ -241,12 +242,14 @@ fn convert_for_of_statement(
241
242
  ctx: &Ctx<'_>,
242
243
  span: Span,
243
244
  ) -> Result<Statement, ConvertError> {
244
- let name = match &f.left {
245
+ let (name, name_span) = match &f.left {
245
246
  oxc::ast::ast::ForStatementLeft::VariableDeclaration(v) => {
246
247
  if v.declarations.len() == 1 {
247
248
  let d = &v.declarations[0];
248
249
  match &d.id {
249
- oxc::ast::ast::BindingPattern::BindingIdentifier(b) => b.name.as_str(),
250
+ oxc::ast::ast::BindingPattern::BindingIdentifier(b) => {
251
+ (b.name.as_str(), span_util::oxc_span_to_tish(ctx.1, b.as_ref()))
252
+ }
250
253
  _ => {
251
254
  return Err(ConvertError::new(ConvertErrorKind::Incompatible {
252
255
  what: "for-of with destructuring".into(),
@@ -272,6 +275,7 @@ fn convert_for_of_statement(
272
275
  let body = Box::new(convert_statement(&f.body, ctx)?);
273
276
  Ok(Statement::ForOf {
274
277
  name: Arc::from(name),
278
+ name_span,
275
279
  iterable,
276
280
  body,
277
281
  span,
@@ -312,23 +316,30 @@ fn convert_try_statement(
312
316
  statements: body_stmts,
313
317
  span: span_util::oxc_span_to_tish(ctx.1, &*t.block),
314
318
  });
315
- let (catch_param, catch_body) = match &t.handler {
319
+ let (catch_param, catch_param_span, catch_body) = match &t.handler {
316
320
  Some(h) => {
317
- let param = h.param.as_ref().and_then(|cp: &oxc::ast::ast::CatchParameter<'_>| {
318
- if let oxc::ast::ast::BindingPattern::BindingIdentifier(b) = &cp.pattern {
319
- Some(Arc::from(b.name.as_str()))
320
- } else {
321
- None
322
- }
323
- });
321
+ let (param, pspan) = h
322
+ .param
323
+ .as_ref()
324
+ .and_then(|cp: &oxc::ast::ast::CatchParameter<'_>| {
325
+ if let oxc::ast::ast::BindingPattern::BindingIdentifier(b) = &cp.pattern {
326
+ Some((
327
+ Arc::from(b.name.as_str()),
328
+ span_util::oxc_span_to_tish(ctx.1, b.as_ref()),
329
+ ))
330
+ } else {
331
+ None
332
+ }
333
+ })
334
+ .map_or((None, None), |(n, s)| (Some(n), Some(s)));
324
335
  let catch_stmts = convert_statements(&h.body.body, ctx.0, ctx.1)?;
325
336
  let cb = Box::new(Statement::Block {
326
337
  statements: catch_stmts,
327
338
  span: span_util::oxc_span_to_tish(ctx.1, &*h.body),
328
339
  });
329
- (param, Some(cb))
340
+ (param, pspan, Some(cb))
330
341
  }
331
- None => (None, None),
342
+ None => (None, None, None),
332
343
  };
333
344
  let finally_body = t
334
345
  .finalizer
@@ -344,6 +355,7 @@ fn convert_try_statement(
344
355
  Ok(Statement::Try {
345
356
  body,
346
357
  catch_param,
358
+ catch_param_span,
347
359
  catch_body,
348
360
  finally_body,
349
361
  span,
@@ -361,6 +373,11 @@ fn convert_function_decl(
361
373
  .as_ref()
362
374
  .map(|id| Arc::from(id.name.as_str()))
363
375
  .unwrap_or_else(|| Arc::from(""));
376
+ let name_span = f
377
+ .id
378
+ .as_ref()
379
+ .map(|id| span_util::oxc_span_to_tish(ctx.1, id))
380
+ .unwrap_or_else(span_util::stub_span);
364
381
  let (params, rest_param) = expr::convert_params(&f.params, ctx)?;
365
382
  let body = match &f.body {
366
383
  Some(fb) => {
@@ -380,6 +397,7 @@ fn convert_function_decl(
380
397
  Ok(Statement::FunDecl {
381
398
  async_,
382
399
  name,
400
+ name_span,
383
401
  params,
384
402
  rest_param,
385
403
  return_type: None,
@@ -390,7 +408,7 @@ fn convert_function_decl(
390
408
 
391
409
  fn convert_import(
392
410
  i: &oxc::ast::ast::ImportDeclaration<'_>,
393
- _ctx: &Ctx<'_>,
411
+ ctx: &Ctx<'_>,
394
412
  span: Span,
395
413
  ) -> Result<Statement, ConvertError> {
396
414
  let from: Arc<str> = Arc::from(i.source.value.as_str());
@@ -401,25 +419,35 @@ fn convert_import(
401
419
  oxc::ast::ast::ImportDeclarationSpecifier::ImportSpecifier(is) => {
402
420
  let imported_name = is.imported.name().as_str();
403
421
  let local_name = is.local.name.as_str();
404
- let alias = if imported_name == local_name {
405
- None
422
+ let name_span = crate::span_util::oxc_span_to_tish(ctx.1, &is.imported);
423
+ let (alias, alias_span) = if imported_name == local_name {
424
+ (None, None)
406
425
  } else {
407
- Some(Arc::from(local_name))
426
+ (
427
+ Some(Arc::from(local_name)),
428
+ Some(crate::span_util::oxc_span_to_tish(ctx.1, &is.local)),
429
+ )
408
430
  };
409
431
  specifiers.push(tishlang_ast::ImportSpecifier::Named {
410
432
  name: Arc::from(imported_name),
433
+ name_span,
411
434
  alias,
435
+ alias_span,
412
436
  });
413
437
  }
414
438
  oxc::ast::ast::ImportDeclarationSpecifier::ImportDefaultSpecifier(ds) => {
415
- specifiers.push(tishlang_ast::ImportSpecifier::Default(Arc::from(
416
- ds.local.name.as_str(),
417
- )));
439
+ let name_span = crate::span_util::oxc_span_to_tish(ctx.1, &ds.local);
440
+ specifiers.push(tishlang_ast::ImportSpecifier::Default {
441
+ name: Arc::from(ds.local.name.as_str()),
442
+ name_span,
443
+ });
418
444
  }
419
445
  oxc::ast::ast::ImportDeclarationSpecifier::ImportNamespaceSpecifier(ns) => {
420
- specifiers.push(tishlang_ast::ImportSpecifier::Namespace(Arc::from(
421
- ns.local.name.as_str(),
422
- )));
446
+ let name_span = crate::span_util::oxc_span_to_tish(ctx.1, &ns.local);
447
+ specifiers.push(tishlang_ast::ImportSpecifier::Namespace {
448
+ name: Arc::from(ns.local.name.as_str()),
449
+ name_span,
450
+ });
423
451
  }
424
452
  }
425
453
  }
@@ -439,7 +467,9 @@ fn convert_export_default(
439
467
  let declaration = if let Some(expr) = e.declaration.as_expression() {
440
468
  let expr = expr::convert_expr(expr, ctx)?;
441
469
  tishlang_ast::ExportDeclaration::Default(expr)
442
- } else if let oxc::ast::ast::ExportDefaultDeclarationKind::FunctionDeclaration(f) = &e.declaration {
470
+ } else if let oxc::ast::ast::ExportDefaultDeclarationKind::FunctionDeclaration(f) =
471
+ &e.declaration
472
+ {
443
473
  let stmt = convert_function_decl(f.as_ref(), ctx, span_util::stub_span())?;
444
474
  tishlang_ast::ExportDeclaration::Named(Box::new(stmt))
445
475
  } else {