@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
@@ -6,7 +6,8 @@ use std::path::Path;
6
6
  use tishlang_compile::ResolvedNativeModule;
7
7
 
8
8
  /// `tishlang_runtime` Cargo feature names (subset of CLI / compile feature names).
9
- const RUNTIME_CARGO_FEATURES: &[&str] = &["http", "fs", "process", "regex", "ws"];
9
+ const RUNTIME_CARGO_FEATURES: &[&str] =
10
+ &["http", "http-hyper", "http-io-uring", "fs", "process", "regex", "ws"];
10
11
 
11
12
  /// Map CLI/compile features to flags passed to `tishlang_runtime` in the temp crate's Cargo.toml.
12
13
  /// `full` enables every optional runtime capability (matches `tish build --feature full` / LANGUAGE.md).
@@ -122,16 +123,12 @@ path = "src/main.rs"
122
123
  strip = true
123
124
  panic = "abort"
124
125
  codegen-units = 1
125
- lto = "thin"
126
+ lto = "fat"
126
127
 
127
128
  [dependencies]
128
129
  tishlang_runtime = {{ path = {:?}{} }}
129
130
  {}{}"#,
130
- out_name,
131
- runtime_path,
132
- features_str,
133
- more_deps,
134
- ui_dep
131
+ out_name, runtime_path, features_str, more_deps, ui_dep
135
132
  );
136
133
 
137
134
  fs::write(build_dir.join("Cargo.toml"), cargo_toml)
@@ -182,4 +179,3 @@ mod tests {
182
179
  assert_eq!(f.len(), 5);
183
180
  }
184
181
  }
185
-
@@ -80,15 +80,19 @@ pub fn compile_to_native(
80
80
  .map_err(|e| NativeError { message: e })
81
81
  }
82
82
  Backend::Cranelift => {
83
- let modules = tishlang_compile::resolve_project(entry_path, project_root)
84
- .map_err(|e| NativeError {
85
- message: e.to_string(),
83
+ let modules =
84
+ tishlang_compile::resolve_project(entry_path, project_root).map_err(|e| {
85
+ NativeError {
86
+ message: e.to_string(),
87
+ }
86
88
  })?;
87
89
  tishlang_compile::detect_cycles(&modules).map_err(|e| NativeError {
88
90
  message: e.to_string(),
89
91
  })?;
90
92
  let program = {
91
- let prog = tishlang_compile::merge_modules(modules).map_err(|e| NativeError {
93
+ let prog = tishlang_compile::merge_modules(modules)
94
+ .map(|m| m.program)
95
+ .map_err(|e| NativeError {
92
96
  message: e.to_string(),
93
97
  })?;
94
98
  if optimize {
@@ -121,11 +125,19 @@ pub fn compile_to_native(
121
125
  })
122
126
  }
123
127
  Backend::Llvm => {
124
- let modules = tishlang_compile::resolve_project(entry_path, project_root)
125
- .map_err(|e| NativeError { message: e.to_string() })?;
126
- tishlang_compile::detect_cycles(&modules).map_err(|e| NativeError { message: e.to_string() })?;
128
+ let modules =
129
+ tishlang_compile::resolve_project(entry_path, project_root).map_err(|e| {
130
+ NativeError {
131
+ message: e.to_string(),
132
+ }
133
+ })?;
134
+ tishlang_compile::detect_cycles(&modules).map_err(|e| NativeError {
135
+ message: e.to_string(),
136
+ })?;
127
137
  let program = {
128
- let prog = tishlang_compile::merge_modules(modules).map_err(|e| NativeError {
138
+ let prog = tishlang_compile::merge_modules(modules)
139
+ .map(|m| m.program)
140
+ .map_err(|e| NativeError {
129
141
  message: e.to_string(),
130
142
  })?;
131
143
  if optimize {
@@ -180,12 +192,17 @@ pub fn compile_program_to_native(
180
192
 
181
193
  match backend {
182
194
  Backend::Rust => {
183
- let program = if optimize { tishlang_opt::optimize(program) } else { program.clone() };
195
+ let program = if optimize {
196
+ tishlang_opt::optimize(program)
197
+ } else {
198
+ program.clone()
199
+ };
184
200
  let root = project_root.unwrap_or_else(|| Path::new("."));
185
201
  let native_modules = tishlang_compile::resolve_native_modules(&program, root)
186
202
  .map_err(|e| NativeError { message: e })?;
187
- let native_build = tishlang_compile::compute_native_build_artifacts(&program, root, &native_modules)
188
- .map_err(|e| NativeError { message: e })?;
203
+ let native_build =
204
+ tishlang_compile::compute_native_build_artifacts(&program, root, &native_modules)
205
+ .map_err(|e| NativeError { message: e })?;
189
206
  let mut all_features = features.to_vec();
190
207
  for f in tishlang_compile::extract_native_import_features(&program) {
191
208
  if !all_features.contains(&f) {
@@ -200,9 +217,7 @@ pub fn compile_program_to_native(
200
217
  &native_build.native_init,
201
218
  optimize,
202
219
  )
203
- .map_err(|e| NativeError {
204
- message: e.message,
205
- })?;
220
+ .map_err(|e| NativeError { message: e.message })?;
206
221
  crate::build::build_via_cargo(
207
222
  &rust_code,
208
223
  native_modules,
@@ -220,15 +235,25 @@ pub fn compile_program_to_native(
220
235
  message: "Cranelift backend does not support external native imports (tish:…, cargo:…, @scope/pkg). Built-in tish:fs, tish:http, tish:process are supported.".to_string(),
221
236
  });
222
237
  }
223
- let program = if optimize { tishlang_opt::optimize(program) } else { program.clone() };
238
+ let program = if optimize {
239
+ tishlang_opt::optimize(program)
240
+ } else {
241
+ program.clone()
242
+ };
224
243
  let chunk = if optimize {
225
- tishlang_bytecode::compile(&program).map_err(|e| NativeError { message: e.to_string() })?
244
+ tishlang_bytecode::compile(&program).map_err(|e| NativeError {
245
+ message: e.to_string(),
246
+ })?
226
247
  } else {
227
- tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError { message: e.to_string() })?
248
+ tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
249
+ message: e.to_string(),
250
+ })?
228
251
  };
229
252
  let cranelift_features = tishlang_compile::extract_native_import_features(&program);
230
253
  tishlang_cranelift::compile_chunk_to_native(&chunk, output_path, &cranelift_features)
231
- .map_err(|e| NativeError { message: e.to_string() })
254
+ .map_err(|e| NativeError {
255
+ message: e.to_string(),
256
+ })
232
257
  }
233
258
  Backend::Llvm => {
234
259
  if tishlang_compile::has_external_native_imports(program) {
@@ -236,11 +261,19 @@ pub fn compile_program_to_native(
236
261
  message: "LLVM backend does not support external native imports (tish:…, cargo:…, @scope/pkg).".to_string(),
237
262
  });
238
263
  }
239
- let program = if optimize { tishlang_opt::optimize(program) } else { program.clone() };
264
+ let program = if optimize {
265
+ tishlang_opt::optimize(program)
266
+ } else {
267
+ program.clone()
268
+ };
240
269
  let chunk = if optimize {
241
- tishlang_bytecode::compile(&program).map_err(|e| NativeError { message: e.to_string() })?
270
+ tishlang_bytecode::compile(&program).map_err(|e| NativeError {
271
+ message: e.to_string(),
272
+ })?
242
273
  } else {
243
- tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError { message: e.to_string() })?
274
+ tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
275
+ message: e.to_string(),
276
+ })?
244
277
  };
245
278
  let llvm_features = tishlang_compile::extract_native_import_features(&program);
246
279
  tishlang_llvm::compile_chunk_to_native(&chunk, output_path, &llvm_features)
@@ -10,11 +10,7 @@ use tishlang_ast::{ArrowBody, BinOp, Expr, Literal, Program, Statement, UnaryOp}
10
10
  /// Optimize a Tish program. Returns a new program with transformations applied.
11
11
  pub fn optimize(program: &Program) -> Program {
12
12
  Program {
13
- statements: program
14
- .statements
15
- .iter()
16
- .map(optimize_statement)
17
- .collect(),
13
+ statements: program.statements.iter().map(optimize_statement).collect(),
18
14
  }
19
15
  }
20
16
 
@@ -29,12 +25,14 @@ fn optimize_statement(stmt: &Statement) -> Statement {
29
25
  }
30
26
  Statement::VarDecl {
31
27
  name,
28
+ name_span,
32
29
  mutable,
33
30
  type_ann,
34
31
  init,
35
32
  span,
36
33
  } => Statement::VarDecl {
37
34
  name: Arc::clone(name),
35
+ name_span: *name_span,
38
36
  mutable: *mutable,
39
37
  type_ann: type_ann.clone(),
40
38
  init: init.as_ref().map(optimize_expr),
@@ -79,7 +77,9 @@ fn optimize_statement(stmt: &Statement) -> Statement {
79
77
  Statement::If {
80
78
  cond: opt_cond,
81
79
  then_branch: Box::new(optimize_statement(then_branch)),
82
- else_branch: else_branch.as_ref().map(|b| Box::new(optimize_statement(b))),
80
+ else_branch: else_branch
81
+ .as_ref()
82
+ .map(|b| Box::new(optimize_statement(b))),
83
83
  span: *span,
84
84
  }
85
85
  }
@@ -103,11 +103,13 @@ fn optimize_statement(stmt: &Statement) -> Statement {
103
103
  },
104
104
  Statement::ForOf {
105
105
  name,
106
+ name_span,
106
107
  iterable,
107
108
  body,
108
109
  span,
109
110
  } => Statement::ForOf {
110
111
  name: Arc::clone(name),
112
+ name_span: *name_span,
111
113
  iterable: optimize_expr(iterable),
112
114
  body: Box::new(optimize_statement(body)),
113
115
  span: *span,
@@ -121,6 +123,7 @@ fn optimize_statement(stmt: &Statement) -> Statement {
121
123
  Statement::FunDecl {
122
124
  async_,
123
125
  name,
126
+ name_span,
124
127
  params,
125
128
  rest_param,
126
129
  return_type,
@@ -129,6 +132,7 @@ fn optimize_statement(stmt: &Statement) -> Statement {
129
132
  } => Statement::FunDecl {
130
133
  async_: *async_,
131
134
  name: Arc::clone(name),
135
+ name_span: *name_span,
132
136
  params: params.clone(),
133
137
  rest_param: rest_param.clone(),
134
138
  return_type: return_type.clone(),
@@ -144,21 +148,12 @@ fn optimize_statement(stmt: &Statement) -> Statement {
144
148
  expr: optimize_expr(expr),
145
149
  cases: cases
146
150
  .iter()
147
- .map(|(ce, stmts)| {
148
- (
149
- ce.as_ref().map(optimize_expr),
150
- optimize_block(stmts),
151
- )
152
- })
151
+ .map(|(ce, stmts)| (ce.as_ref().map(optimize_expr), optimize_block(stmts)))
153
152
  .collect(),
154
153
  default_body: default_body.as_ref().map(|stmts| optimize_block(stmts)),
155
154
  span: *span,
156
155
  },
157
- Statement::DoWhile {
158
- body,
159
- cond,
160
- span,
161
- } => Statement::DoWhile {
156
+ Statement::DoWhile { body, cond, span } => Statement::DoWhile {
162
157
  body: Box::new(optimize_statement(body)),
163
158
  cond: optimize_expr(cond),
164
159
  span: *span,
@@ -170,17 +165,25 @@ fn optimize_statement(stmt: &Statement) -> Statement {
170
165
  Statement::Try {
171
166
  body,
172
167
  catch_param,
168
+ catch_param_span,
173
169
  catch_body,
174
170
  finally_body,
175
171
  span,
176
172
  } => Statement::Try {
177
173
  body: Box::new(optimize_statement(body)),
178
174
  catch_param: catch_param.clone(),
175
+ catch_param_span: *catch_param_span,
179
176
  catch_body: catch_body.as_ref().map(|b| Box::new(optimize_statement(b))),
180
- finally_body: finally_body.as_ref().map(|b| Box::new(optimize_statement(b))),
177
+ finally_body: finally_body
178
+ .as_ref()
179
+ .map(|b| Box::new(optimize_statement(b))),
181
180
  span: *span,
182
181
  },
183
- Statement::Import { .. } | Statement::Export { .. } => stmt.clone(),
182
+ Statement::Import { .. }
183
+ | Statement::Export { .. }
184
+ | Statement::TypeAlias { .. }
185
+ | Statement::DeclareVar { .. }
186
+ | Statement::DeclareFun { .. } => stmt.clone(),
184
187
  }
185
188
  }
186
189
 
@@ -232,7 +235,12 @@ fn optimize_expr(expr: &Expr) -> Expr {
232
235
  name: Arc::clone(name),
233
236
  span: *span,
234
237
  },
235
- Expr::Binary { left, op, right, span } => {
238
+ Expr::Binary {
239
+ left,
240
+ op,
241
+ right,
242
+ span,
243
+ } => {
236
244
  let opt_left = optimize_expr(left);
237
245
  let opt_right = optimize_expr(right);
238
246
 
@@ -324,32 +332,28 @@ fn optimize_expr(expr: &Expr) -> Expr {
324
332
  span: *span,
325
333
  }
326
334
  }
327
- Expr::Call {
328
- callee,
329
- args,
330
- span,
331
- } => Expr::Call {
335
+ Expr::Call { callee, args, span } => Expr::Call {
332
336
  callee: Box::new(optimize_expr(callee)),
333
337
  args: args
334
338
  .iter()
335
339
  .map(|a| match a {
336
340
  tishlang_ast::CallArg::Expr(e) => tishlang_ast::CallArg::Expr(optimize_expr(e)),
337
- tishlang_ast::CallArg::Spread(e) => tishlang_ast::CallArg::Spread(optimize_expr(e)),
341
+ tishlang_ast::CallArg::Spread(e) => {
342
+ tishlang_ast::CallArg::Spread(optimize_expr(e))
343
+ }
338
344
  })
339
345
  .collect(),
340
346
  span: *span,
341
347
  },
342
- Expr::New {
343
- callee,
344
- args,
345
- span,
346
- } => Expr::New {
348
+ Expr::New { callee, args, span } => Expr::New {
347
349
  callee: Box::new(optimize_expr(callee)),
348
350
  args: args
349
351
  .iter()
350
352
  .map(|a| match a {
351
353
  tishlang_ast::CallArg::Expr(e) => tishlang_ast::CallArg::Expr(optimize_expr(e)),
352
- tishlang_ast::CallArg::Spread(e) => tishlang_ast::CallArg::Spread(optimize_expr(e)),
354
+ tishlang_ast::CallArg::Spread(e) => {
355
+ tishlang_ast::CallArg::Spread(optimize_expr(e))
356
+ }
353
357
  })
354
358
  .collect(),
355
359
  span: *span,
@@ -362,7 +366,10 @@ fn optimize_expr(expr: &Expr) -> Expr {
362
366
  } => {
363
367
  let opt_obj = optimize_expr(object);
364
368
  let opt_prop = match prop {
365
- tishlang_ast::MemberProp::Name(n) => tishlang_ast::MemberProp::Name(Arc::clone(n)),
369
+ tishlang_ast::MemberProp::Name { name, span } => tishlang_ast::MemberProp::Name {
370
+ name: Arc::clone(name),
371
+ span: *span,
372
+ },
366
373
  tishlang_ast::MemberProp::Expr(e) => {
367
374
  tishlang_ast::MemberProp::Expr(Box::new(optimize_expr(e)))
368
375
  }
@@ -385,14 +392,11 @@ fn optimize_expr(expr: &Expr) -> Expr {
385
392
  optional: *optional,
386
393
  span: *span,
387
394
  },
388
- Expr::NullishCoalesce {
389
- left,
390
- right,
391
- span,
392
- } => {
395
+ Expr::NullishCoalesce { left, right, span } => {
393
396
  let opt_left = optimize_expr(left);
394
397
  if let Expr::Literal {
395
- value: Literal::Null, ..
398
+ value: Literal::Null,
399
+ ..
396
400
  } = &opt_left
397
401
  {
398
402
  return optimize_expr(right);
@@ -444,13 +448,23 @@ fn optimize_expr(expr: &Expr) -> Expr {
444
448
  | Expr::PostfixDec { .. }
445
449
  | Expr::PrefixInc { .. }
446
450
  | Expr::PrefixDec { .. } => expr.clone(),
447
- Expr::CompoundAssign { name, op, value, span } => Expr::CompoundAssign {
451
+ Expr::CompoundAssign {
452
+ name,
453
+ op,
454
+ value,
455
+ span,
456
+ } => Expr::CompoundAssign {
448
457
  name: Arc::clone(name),
449
458
  op: *op,
450
459
  value: Box::new(optimize_expr(value)),
451
460
  span: *span,
452
461
  },
453
- Expr::LogicalAssign { name, op, value, span } => Expr::LogicalAssign {
462
+ Expr::LogicalAssign {
463
+ name,
464
+ op,
465
+ value,
466
+ span,
467
+ } => Expr::LogicalAssign {
454
468
  name: Arc::clone(name),
455
469
  op: *op,
456
470
  value: Box::new(optimize_expr(value)),
@@ -478,11 +492,7 @@ fn optimize_expr(expr: &Expr) -> Expr {
478
492
  value: Box::new(optimize_expr(value)),
479
493
  span: *span,
480
494
  },
481
- Expr::ArrowFunction {
482
- params,
483
- body,
484
- span,
485
- } => {
495
+ Expr::ArrowFunction { params, body, span } => {
486
496
  let opt_body = match body {
487
497
  ArrowBody::Expr(e) => ArrowBody::Expr(Box::new(optimize_expr(e))),
488
498
  ArrowBody::Block(s) => ArrowBody::Block(Box::new(optimize_statement(s))),
@@ -493,7 +503,11 @@ fn optimize_expr(expr: &Expr) -> Expr {
493
503
  span: *span,
494
504
  }
495
505
  }
496
- Expr::TemplateLiteral { quasis, exprs, span } => Expr::TemplateLiteral {
506
+ Expr::TemplateLiteral {
507
+ quasis,
508
+ exprs,
509
+ span,
510
+ } => Expr::TemplateLiteral {
497
511
  quasis: quasis.iter().map(Arc::clone).collect(),
498
512
  exprs: exprs.iter().map(optimize_expr).collect(),
499
513
  span: *span,
@@ -503,7 +517,11 @@ fn optimize_expr(expr: &Expr) -> Expr {
503
517
  span: *span,
504
518
  },
505
519
  Expr::JsxElement { .. } | Expr::JsxFragment { .. } => expr.clone(),
506
- Expr::NativeModuleLoad { spec, export_name, span } => Expr::NativeModuleLoad {
520
+ Expr::NativeModuleLoad {
521
+ spec,
522
+ export_name,
523
+ span,
524
+ } => Expr::NativeModuleLoad {
507
525
  spec: Arc::clone(spec),
508
526
  export_name: Arc::clone(export_name),
509
527
  span: *span,
@@ -699,8 +717,12 @@ fn try_fold_binop(left: &Literal, op: BinOp, right: &Literal) -> Option<Literal>
699
717
  Add => {
700
718
  if matches!(left, Literal::String(_)) || matches!(right, Literal::String(_)) {
701
719
  return Some(Literal::String(
702
- format!("{}{}", literal_to_display_string(left), literal_to_display_string(right))
703
- .into(),
720
+ format!(
721
+ "{}{}",
722
+ literal_to_display_string(left),
723
+ literal_to_display_string(right)
724
+ )
725
+ .into(),
704
726
  ));
705
727
  }
706
728
  Literal::Number(ln + rn)
@@ -769,7 +791,11 @@ mod tests {
769
791
  [tishlang_ast::Statement::ExprStmt { expr, .. }] => expr,
770
792
  _ => panic!("expected single expr stmt"),
771
793
  };
772
- assert!(has_literal_number(expr, -42.0), "expected -42, got {:?}", expr);
794
+ assert!(
795
+ has_literal_number(expr, -42.0),
796
+ "expected -42, got {:?}",
797
+ expr
798
+ );
773
799
  }
774
800
 
775
801
  #[test]
@@ -781,7 +807,13 @@ mod tests {
781
807
  _ => panic!("expected single expr stmt"),
782
808
  };
783
809
  assert!(
784
- matches!(expr, Expr::Literal { value: Literal::Bool(false), .. }),
810
+ matches!(
811
+ expr,
812
+ Expr::Literal {
813
+ value: Literal::Bool(false),
814
+ ..
815
+ }
816
+ ),
785
817
  "expected false, got {:?}",
786
818
  expr
787
819
  );
@@ -38,7 +38,9 @@ mod tests {
38
38
  assert_eq!(program.statements.len(), 1);
39
39
  let stmt = &program.statements[0];
40
40
  let init = match stmt {
41
- Statement::VarDecl { init: Some(ref i), .. } => i,
41
+ Statement::VarDecl {
42
+ init: Some(ref i), ..
43
+ } => i,
42
44
  _ => panic!("expected VarDecl with init"),
43
45
  };
44
46
  let props = match init {
@@ -61,11 +63,14 @@ mod tests {
61
63
 
62
64
  #[test]
63
65
  fn test_object_literal_string_key() {
64
- let program = parse(r#"const o = { "ai-a": 0, human: 1 }"#).expect("parse object with string key");
66
+ let program =
67
+ parse(r#"const o = { "ai-a": 0, human: 1 }"#).expect("parse object with string key");
65
68
  assert_eq!(program.statements.len(), 1);
66
69
  let stmt = &program.statements[0];
67
70
  let init = match stmt {
68
- Statement::VarDecl { init: Some(ref i), .. } => i,
71
+ Statement::VarDecl {
72
+ init: Some(ref i), ..
73
+ } => i,
69
74
  _ => panic!("expected VarDecl with init"),
70
75
  };
71
76
  let props = match init {
@@ -89,7 +94,9 @@ mod tests {
89
94
  assert_eq!(program.statements.len(), 1);
90
95
  let stmt = &program.statements[0];
91
96
  let init = match stmt {
92
- Statement::VarDecl { init: Some(ref i), .. } => i,
97
+ Statement::VarDecl {
98
+ init: Some(ref i), ..
99
+ } => i,
93
100
  _ => panic!("expected VarDecl with init"),
94
101
  };
95
102
  let props = match init {
@@ -134,7 +141,9 @@ mod tests {
134
141
  let e = unwrap_expr_stmt(&program);
135
142
  match e {
136
143
  Expr::New { callee, args, .. } => {
137
- assert!(matches!(callee.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Foo"));
144
+ assert!(
145
+ matches!(callee.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Foo")
146
+ );
138
147
  assert!(args.is_empty());
139
148
  }
140
149
  _ => panic!("expected New, got {:?}", e),
@@ -147,7 +156,9 @@ mod tests {
147
156
  let e = unwrap_expr_stmt(&program);
148
157
  match e {
149
158
  Expr::New { callee, args, .. } => {
150
- assert!(matches!(callee.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Uint8Array"));
159
+ assert!(
160
+ matches!(callee.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Uint8Array")
161
+ );
151
162
  assert_eq!(args.len(), 1);
152
163
  assert!(matches!(&args[0], CallArg::Expr(Expr::Literal { .. })));
153
164
  }
@@ -163,7 +174,7 @@ mod tests {
163
174
  Expr::New { callee, args, .. } => {
164
175
  assert!(matches!(
165
176
  callee.as_ref(),
166
- Expr::Member { prop: tishlang_ast::MemberProp::Name(p), .. } if p.as_ref() == "AudioContext"
177
+ Expr::Member { prop: tishlang_ast::MemberProp::Name { name, .. }, .. } if name.as_ref() == "AudioContext"
167
178
  ));
168
179
  assert!(args.is_empty());
169
180
  }
@@ -179,8 +190,14 @@ mod tests {
179
190
  Expr::New { callee, args, .. } => {
180
191
  assert!(args.is_empty());
181
192
  match callee.as_ref() {
182
- Expr::New { callee: inner, args: inner_args, .. } => {
183
- assert!(matches!(inner.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Date"));
193
+ Expr::New {
194
+ callee: inner,
195
+ args: inner_args,
196
+ ..
197
+ } => {
198
+ assert!(
199
+ matches!(inner.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Date")
200
+ );
184
201
  assert!(inner_args.is_empty());
185
202
  }
186
203
  _ => panic!("expected nested New"),
@@ -195,11 +212,17 @@ mod tests {
195
212
  let program = parse("new Foo().bar").expect("parse");
196
213
  let e = unwrap_expr_stmt(&program);
197
214
  match e {
198
- Expr::Member { object, prop: tishlang_ast::MemberProp::Name(p), .. } => {
199
- assert_eq!(p.as_ref(), "bar");
215
+ Expr::Member {
216
+ object,
217
+ prop: tishlang_ast::MemberProp::Name { name, .. },
218
+ ..
219
+ } => {
220
+ assert_eq!(name.as_ref(), "bar");
200
221
  match object.as_ref() {
201
222
  Expr::New { callee, args, .. } => {
202
- assert!(matches!(callee.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Foo"));
223
+ assert!(
224
+ matches!(callee.as_ref(), Expr::Ident { name, .. } if name.as_ref() == "Foo")
225
+ );
203
226
  assert!(args.is_empty());
204
227
  }
205
228
  _ => panic!("expected New object"),
@@ -215,9 +238,18 @@ mod tests {
215
238
  let e = unwrap_expr_stmt(&program);
216
239
  match e {
217
240
  Expr::New { args, .. } => {
218
- assert!(matches!(&args[0], CallArg::Spread(Expr::Ident { name, .. }) if name.as_ref() == "xs"));
241
+ assert!(
242
+ matches!(&args[0], CallArg::Spread(Expr::Ident { name, .. }) if name.as_ref() == "xs")
243
+ );
219
244
  }
220
245
  _ => panic!("expected New"),
221
246
  }
222
247
  }
248
+
249
+ #[test]
250
+ fn stdlib_builtins_d_tish_parses() {
251
+ const SRC: &str = include_str!("../../../stdlib/builtins.d.tish");
252
+ parse(SRC).expect("stdlib/builtins.d.tish should parse");
253
+ }
254
+
223
255
  }