@tishlang/tish-format 1.0.12 → 1.0.13

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 (164) hide show
  1. package/Cargo.toml +49 -0
  2. package/LICENSE +13 -0
  3. package/README.md +138 -0
  4. package/bin/tish-format +0 -0
  5. package/crates/js_to_tish/Cargo.toml +11 -0
  6. package/crates/js_to_tish/README.md +18 -0
  7. package/crates/js_to_tish/src/error.rs +55 -0
  8. package/crates/js_to_tish/src/lib.rs +11 -0
  9. package/crates/js_to_tish/src/span_util.rs +35 -0
  10. package/crates/js_to_tish/src/transform/expr.rs +610 -0
  11. package/crates/js_to_tish/src/transform/stmt.rs +503 -0
  12. package/crates/js_to_tish/src/transform.rs +60 -0
  13. package/crates/tish/Cargo.toml +54 -0
  14. package/crates/tish/src/cargo_native_registry.rs +32 -0
  15. package/crates/tish/src/cli_help.rs +565 -0
  16. package/crates/tish/src/main.rs +781 -0
  17. package/crates/tish/src/repl_completion.rs +200 -0
  18. package/crates/tish/tests/cargo_example_compile.rs +67 -0
  19. package/crates/tish/tests/fixtures/cargo_example_project/Cargo.toml +3 -0
  20. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/Cargo.toml +11 -0
  21. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +12 -0
  22. package/crates/tish/tests/fixtures/cargo_example_project/package.json +10 -0
  23. package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +3 -0
  24. package/crates/tish/tests/integration_test.rs +1095 -0
  25. package/crates/tish/tests/run_optimize_stdout_parity.rs +50 -0
  26. package/crates/tish/tests/shortcircuit.rs +65 -0
  27. package/crates/tish_ast/Cargo.toml +9 -0
  28. package/crates/tish_ast/src/ast.rs +620 -0
  29. package/crates/tish_ast/src/lib.rs +5 -0
  30. package/crates/tish_build_utils/Cargo.toml +11 -0
  31. package/crates/tish_build_utils/src/lib.rs +577 -0
  32. package/crates/tish_builtins/Cargo.toml +20 -0
  33. package/crates/tish_builtins/src/array.rs +441 -0
  34. package/crates/tish_builtins/src/construct.rs +159 -0
  35. package/crates/tish_builtins/src/globals.rs +213 -0
  36. package/crates/tish_builtins/src/helpers.rs +35 -0
  37. package/crates/tish_builtins/src/lib.rs +16 -0
  38. package/crates/tish_builtins/src/math.rs +89 -0
  39. package/crates/tish_builtins/src/object.rs +36 -0
  40. package/crates/tish_builtins/src/string.rs +647 -0
  41. package/crates/tish_builtins/src/symbol.rs +83 -0
  42. package/crates/tish_bytecode/Cargo.toml +17 -0
  43. package/crates/tish_bytecode/src/chunk.rs +96 -0
  44. package/crates/tish_bytecode/src/compiler.rs +1760 -0
  45. package/crates/tish_bytecode/src/encoding.rs +100 -0
  46. package/crates/tish_bytecode/src/lib.rs +19 -0
  47. package/crates/tish_bytecode/src/opcode.rs +142 -0
  48. package/crates/tish_bytecode/src/peephole.rs +189 -0
  49. package/crates/tish_bytecode/src/serialize.rs +163 -0
  50. package/crates/tish_bytecode/tests/break_continue_bytecode.rs +44 -0
  51. package/crates/tish_bytecode/tests/constant_folding.rs +84 -0
  52. package/crates/tish_bytecode/tests/sort_optimization.rs +31 -0
  53. package/crates/tish_compile/Cargo.toml +26 -0
  54. package/crates/tish_compile/src/codegen.rs +5332 -0
  55. package/crates/tish_compile/src/infer.rs +292 -0
  56. package/crates/tish_compile/src/lib.rs +164 -0
  57. package/crates/tish_compile/src/resolve.rs +1388 -0
  58. package/crates/tish_compile/src/types.rs +501 -0
  59. package/crates/tish_compile_js/Cargo.toml +18 -0
  60. package/crates/tish_compile_js/examples/jsx_vdom_smoke.tish +8 -0
  61. package/crates/tish_compile_js/src/codegen.rs +871 -0
  62. package/crates/tish_compile_js/src/error.rs +20 -0
  63. package/crates/tish_compile_js/src/lib.rs +26 -0
  64. package/crates/tish_compile_js/src/tests_jsx.rs +350 -0
  65. package/crates/tish_compiler_wasm/Cargo.toml +21 -0
  66. package/crates/tish_compiler_wasm/src/lib.rs +57 -0
  67. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +473 -0
  68. package/crates/tish_core/Cargo.toml +26 -0
  69. package/crates/tish_core/src/console_style.rs +160 -0
  70. package/crates/tish_core/src/json.rs +387 -0
  71. package/crates/tish_core/src/lib.rs +17 -0
  72. package/crates/tish_core/src/macros.rs +36 -0
  73. package/crates/tish_core/src/uri.rs +118 -0
  74. package/crates/tish_core/src/value.rs +696 -0
  75. package/crates/tish_core/src/vmref.rs +178 -0
  76. package/crates/tish_cranelift/Cargo.toml +19 -0
  77. package/crates/tish_cranelift/src/lib.rs +43 -0
  78. package/crates/tish_cranelift/src/link.rs +117 -0
  79. package/crates/tish_cranelift/src/lower.rs +85 -0
  80. package/crates/tish_cranelift_runtime/Cargo.toml +25 -0
  81. package/crates/tish_cranelift_runtime/src/lib.rs +45 -0
  82. package/crates/tish_eval/Cargo.toml +45 -0
  83. package/crates/tish_eval/src/eval.rs +3717 -0
  84. package/crates/tish_eval/src/http.rs +188 -0
  85. package/crates/tish_eval/src/lib.rs +99 -0
  86. package/crates/tish_eval/src/natives.rs +399 -0
  87. package/crates/tish_eval/src/promise.rs +179 -0
  88. package/crates/tish_eval/src/regex.rs +299 -0
  89. package/crates/tish_eval/src/timers.rs +120 -0
  90. package/crates/tish_eval/src/value.rs +318 -0
  91. package/crates/tish_eval/src/value_convert.rs +111 -0
  92. package/crates/tish_fmt/Cargo.toml +16 -0
  93. package/crates/tish_fmt/src/bin/tish-fmt.rs +41 -0
  94. package/crates/tish_fmt/src/lib.rs +2101 -0
  95. package/crates/tish_jsx_web/Cargo.toml +9 -0
  96. package/crates/tish_jsx_web/README.md +5 -0
  97. package/crates/tish_jsx_web/src/lib.rs +2 -0
  98. package/crates/tish_lexer/Cargo.toml +9 -0
  99. package/crates/tish_lexer/src/lib.rs +716 -0
  100. package/crates/tish_lexer/src/token.rs +163 -0
  101. package/crates/tish_lint/Cargo.toml +18 -0
  102. package/crates/tish_lint/src/bin/tish-lint.rs +195 -0
  103. package/crates/tish_lint/src/lib.rs +289 -0
  104. package/crates/tish_llvm/Cargo.toml +13 -0
  105. package/crates/tish_llvm/src/lib.rs +115 -0
  106. package/crates/tish_lsp/Cargo.toml +25 -0
  107. package/crates/tish_lsp/README.md +26 -0
  108. package/crates/tish_lsp/src/builtin_goto.rs +362 -0
  109. package/crates/tish_lsp/src/import_goto.rs +562 -0
  110. package/crates/tish_lsp/src/main.rs +1046 -0
  111. package/crates/tish_native/Cargo.toml +16 -0
  112. package/crates/tish_native/src/build.rs +427 -0
  113. package/crates/tish_native/src/config.rs +48 -0
  114. package/crates/tish_native/src/lib.rs +416 -0
  115. package/crates/tish_opt/Cargo.toml +13 -0
  116. package/crates/tish_opt/src/lib.rs +943 -0
  117. package/crates/tish_parser/Cargo.toml +11 -0
  118. package/crates/tish_parser/src/lib.rs +332 -0
  119. package/crates/tish_parser/src/parser.rs +2304 -0
  120. package/crates/tish_pg/Cargo.toml +34 -0
  121. package/crates/tish_pg/README.md +38 -0
  122. package/crates/tish_pg/src/error.rs +52 -0
  123. package/crates/tish_pg/src/lib.rs +955 -0
  124. package/crates/tish_resolve/Cargo.toml +13 -0
  125. package/crates/tish_resolve/src/lib.rs +3561 -0
  126. package/crates/tish_resolve/src/pos.rs +141 -0
  127. package/crates/tish_runtime/Cargo.toml +96 -0
  128. package/crates/tish_runtime/src/http.rs +1298 -0
  129. package/crates/tish_runtime/src/http_fetch.rs +471 -0
  130. package/crates/tish_runtime/src/http_hyper.rs +418 -0
  131. package/crates/tish_runtime/src/http_prefork.rs +189 -0
  132. package/crates/tish_runtime/src/lib.rs +1192 -0
  133. package/crates/tish_runtime/src/native_promise.rs +15 -0
  134. package/crates/tish_runtime/src/promise.rs +248 -0
  135. package/crates/tish_runtime/src/promise_io.rs +38 -0
  136. package/crates/tish_runtime/src/timers.rs +166 -0
  137. package/crates/tish_runtime/src/ws.rs +761 -0
  138. package/crates/tish_runtime/tests/fetch_readable_stream.rs +102 -0
  139. package/crates/tish_ui/Cargo.toml +17 -0
  140. package/crates/tish_ui/src/jsx.rs +682 -0
  141. package/crates/tish_ui/src/lib.rs +20 -0
  142. package/crates/tish_ui/src/runtime/hooks.rs +569 -0
  143. package/crates/tish_ui/src/runtime/mod.rs +180 -0
  144. package/crates/tish_vm/Cargo.toml +47 -0
  145. package/crates/tish_vm/src/lib.rs +39 -0
  146. package/crates/tish_vm/src/vm.rs +2192 -0
  147. package/crates/tish_vm/tests/fixtures/or_string_cmd.tish +2 -0
  148. package/crates/tish_vm/tests/lexical_scope_declare.rs +34 -0
  149. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +150 -0
  150. package/crates/tish_wasm/Cargo.toml +15 -0
  151. package/crates/tish_wasm/src/lib.rs +424 -0
  152. package/crates/tish_wasm_runtime/Cargo.toml +37 -0
  153. package/crates/tish_wasm_runtime/src/gpu.rs +413 -0
  154. package/crates/tish_wasm_runtime/src/lib.rs +42 -0
  155. package/crates/tishlang_cargo_bindgen/Cargo.toml +26 -0
  156. package/crates/tishlang_cargo_bindgen/src/classify.rs +263 -0
  157. package/crates/tishlang_cargo_bindgen/src/discover.rs +125 -0
  158. package/crates/tishlang_cargo_bindgen/src/infer.rs +382 -0
  159. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  160. package/crates/tishlang_cargo_bindgen/src/main.rs +167 -0
  161. package/crates/tishlang_cargo_bindgen/src/metadata.rs +117 -0
  162. package/justfile +268 -0
  163. package/package.json +1 -1
  164. package/platform/darwin-arm64/tish-fmt +0 -0
@@ -0,0 +1,503 @@
1
+ //! Convert OXC statements to Tish statements.
2
+
3
+ use std::sync::Arc;
4
+
5
+ use oxc::ast::ast::Statement as OxcStmt;
6
+ use oxc::semantic::Semantic;
7
+ use tishlang_ast::{Span, Statement};
8
+
9
+ use super::expr;
10
+ use crate::error::{ConvertError, ConvertErrorKind};
11
+ use crate::span_util;
12
+
13
+ type Ctx<'a> = (&'a Semantic<'a>, &'a str);
14
+
15
+ /// Convert OXC program body (statements) to Tish statements.
16
+ pub fn convert_statements(
17
+ body: &[OxcStmt<'_>],
18
+ semantic: &Semantic<'_>,
19
+ source: &str,
20
+ ) -> Result<Vec<Statement>, ConvertError> {
21
+ let ctx = (semantic, source);
22
+ body.iter().map(|s| convert_statement(s, &ctx)).collect()
23
+ }
24
+
25
+ fn convert_statement(stmt: &OxcStmt<'_>, ctx: &Ctx<'_>) -> Result<Statement, ConvertError> {
26
+ let span = span_util::oxc_span_to_tish(ctx.1, stmt);
27
+ match stmt {
28
+ OxcStmt::BlockStatement(b) => {
29
+ let statements = convert_statements(&b.body, ctx.0, ctx.1)?;
30
+ Ok(Statement::Block { statements, span })
31
+ }
32
+ OxcStmt::VariableDeclaration(v) => convert_var_decl(v, ctx, span),
33
+ OxcStmt::ExpressionStatement(e) => {
34
+ let expr = expr::convert_expr(&e.expression, ctx)?;
35
+ Ok(Statement::ExprStmt { expr, span })
36
+ }
37
+ OxcStmt::IfStatement(i) => {
38
+ let cond = expr::convert_expr(&i.test, ctx)?;
39
+ let then_branch = Box::new(convert_statement(&i.consequent, ctx)?);
40
+ let else_branch = i
41
+ .alternate
42
+ .as_ref()
43
+ .map(|a| convert_statement(a, ctx))
44
+ .transpose()?
45
+ .map(Box::new);
46
+ Ok(Statement::If {
47
+ cond,
48
+ then_branch,
49
+ else_branch,
50
+ span,
51
+ })
52
+ }
53
+ OxcStmt::ReturnStatement(r) => {
54
+ let value = r
55
+ .argument
56
+ .as_ref()
57
+ .map(|a| expr::convert_expr(a, ctx))
58
+ .transpose()?;
59
+ Ok(Statement::Return { value, span })
60
+ }
61
+ OxcStmt::BreakStatement(_) => Ok(Statement::Break { span }),
62
+ OxcStmt::ContinueStatement(_) => Ok(Statement::Continue { span }),
63
+ OxcStmt::WhileStatement(w) => {
64
+ let cond = expr::convert_expr(&w.test, ctx)?;
65
+ let body = Box::new(convert_statement(&w.body, ctx)?);
66
+ Ok(Statement::While { cond, body, span })
67
+ }
68
+ OxcStmt::DoWhileStatement(d) => {
69
+ let cond = expr::convert_expr(&d.test, ctx)?;
70
+ let body = Box::new(convert_statement(&d.body, ctx)?);
71
+ Ok(Statement::DoWhile { body, cond, span })
72
+ }
73
+ OxcStmt::ForStatement(f) => convert_for_statement(f, ctx, span),
74
+ OxcStmt::ForOfStatement(f) => convert_for_of_statement(f, ctx, span),
75
+ OxcStmt::SwitchStatement(s) => convert_switch_statement(s, ctx, span),
76
+ OxcStmt::ThrowStatement(t) => {
77
+ let value = expr::convert_expr(&t.argument, ctx)?;
78
+ Ok(Statement::Throw { value, span })
79
+ }
80
+ OxcStmt::TryStatement(t) => convert_try_statement(t, ctx, span),
81
+ OxcStmt::FunctionDeclaration(f) => convert_function_decl(f, ctx, span),
82
+ OxcStmt::EmptyStatement(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
83
+ what: "empty statement".into(),
84
+ hint: None,
85
+ })),
86
+ OxcStmt::ForInStatement(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
87
+ what: "for-in".into(),
88
+ hint: Some("Tish omits for-in".into()),
89
+ })),
90
+ OxcStmt::ClassDeclaration(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
91
+ what: "class".into(),
92
+ hint: Some("Tish does not support classes".into()),
93
+ })),
94
+ OxcStmt::WithStatement(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
95
+ what: "with".into(),
96
+ hint: None,
97
+ })),
98
+ OxcStmt::DebuggerStatement(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
99
+ what: "debugger".into(),
100
+ hint: None,
101
+ })),
102
+ OxcStmt::LabeledStatement(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
103
+ what: "labeled statement".into(),
104
+ hint: None,
105
+ })),
106
+ OxcStmt::ImportDeclaration(i) => convert_import(i, ctx, span),
107
+ OxcStmt::ExportDefaultDeclaration(e) => convert_export_default(e, ctx, span),
108
+ OxcStmt::ExportNamedDeclaration(e) => convert_export_named(e, ctx, span),
109
+ OxcStmt::ExportAllDeclaration(_) => Err(ConvertError::new(ConvertErrorKind::Unsupported {
110
+ what: "export *".into(),
111
+ hint: None,
112
+ })),
113
+ _ => Err(ConvertError::new(ConvertErrorKind::Unsupported {
114
+ what: format!("{:?}", std::mem::discriminant(stmt)),
115
+ hint: None,
116
+ })),
117
+ }
118
+ }
119
+
120
+ fn convert_declaration(
121
+ decl: &oxc::ast::ast::Declaration<'_>,
122
+ ctx: &Ctx<'_>,
123
+ ) -> Result<Statement, ConvertError> {
124
+ let span = span_util::oxc_span_to_tish(ctx.1, decl);
125
+ match decl {
126
+ oxc::ast::ast::Declaration::VariableDeclaration(v) => convert_var_decl(v, ctx, span),
127
+ oxc::ast::ast::Declaration::FunctionDeclaration(f) => convert_function_decl(f, ctx, span),
128
+ _ => Err(ConvertError::new(ConvertErrorKind::Unsupported {
129
+ what: format!("declaration: {:?}", std::mem::discriminant(decl)),
130
+ hint: None,
131
+ })),
132
+ }
133
+ }
134
+
135
+ fn convert_var_decl(
136
+ v: &oxc::ast::ast::VariableDeclaration<'_>,
137
+ ctx: &Ctx<'_>,
138
+ span: Span,
139
+ ) -> Result<Statement, ConvertError> {
140
+ let mutable = matches!(v.kind, oxc::ast::ast::VariableDeclarationKind::Let);
141
+ if v.declarations.len() == 1 {
142
+ let d = &v.declarations[0];
143
+ let id = &d.id;
144
+ let init = d
145
+ .init
146
+ .as_ref()
147
+ .map(|i| expr::convert_expr(i, ctx))
148
+ .transpose()?;
149
+ match id {
150
+ oxc::ast::ast::BindingPattern::BindingIdentifier(b) => {
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
+ Ok(Statement::VarDecl {
154
+ name,
155
+ name_span,
156
+ mutable,
157
+ type_ann: None,
158
+ init,
159
+ span,
160
+ })
161
+ }
162
+ _ => {
163
+ let init = d
164
+ .init
165
+ .as_ref()
166
+ .map(|i| expr::convert_expr(i, ctx))
167
+ .transpose()?
168
+ .ok_or_else(|| {
169
+ ConvertError::new(ConvertErrorKind::Incompatible {
170
+ what: "destructuring declaration".into(),
171
+ reason: "initializer required".into(),
172
+ })
173
+ })?;
174
+ let pattern = expr::convert_destruct_pattern(id)?;
175
+ Ok(Statement::VarDeclDestructure {
176
+ pattern,
177
+ mutable,
178
+ init,
179
+ span,
180
+ })
181
+ }
182
+ }
183
+ } else {
184
+ Err(ConvertError::new(ConvertErrorKind::Incompatible {
185
+ what: "multi-declarator variable declaration".into(),
186
+ reason: "split into separate declarations".into(),
187
+ }))
188
+ }
189
+ }
190
+
191
+ fn convert_for_statement(
192
+ f: &oxc::ast::ast::ForStatement<'_>,
193
+ ctx: &Ctx<'_>,
194
+ span: Span,
195
+ ) -> Result<Statement, ConvertError> {
196
+ let init = f
197
+ .init
198
+ .as_ref()
199
+ .map(|i| match i {
200
+ oxc::ast::ast::ForStatementInit::VariableDeclaration(v) => {
201
+ convert_var_decl(v, ctx, span_util::stub_span()).map(Box::new)
202
+ }
203
+ _ => {
204
+ if let Some(e) = i.as_expression() {
205
+ expr::convert_expr(e, ctx).map(|expr| {
206
+ Box::new(Statement::ExprStmt {
207
+ expr,
208
+ span: span_util::stub_span(),
209
+ })
210
+ })
211
+ } else {
212
+ Err(ConvertError::new(ConvertErrorKind::Unsupported {
213
+ what: "for init".into(),
214
+ hint: None,
215
+ }))
216
+ }
217
+ }
218
+ })
219
+ .transpose()?;
220
+ let cond = f
221
+ .test
222
+ .as_ref()
223
+ .map(|e| expr::convert_expr(e, ctx))
224
+ .transpose()?;
225
+ let update = f
226
+ .update
227
+ .as_ref()
228
+ .map(|e| expr::convert_expr(e, ctx))
229
+ .transpose()?;
230
+ let body = Box::new(convert_statement(&f.body, ctx)?);
231
+ Ok(Statement::For {
232
+ init,
233
+ cond,
234
+ update,
235
+ body,
236
+ span,
237
+ })
238
+ }
239
+
240
+ fn convert_for_of_statement(
241
+ f: &oxc::ast::ast::ForOfStatement<'_>,
242
+ ctx: &Ctx<'_>,
243
+ span: Span,
244
+ ) -> Result<Statement, ConvertError> {
245
+ let (name, name_span) = match &f.left {
246
+ oxc::ast::ast::ForStatementLeft::VariableDeclaration(v) => {
247
+ if v.declarations.len() == 1 {
248
+ let d = &v.declarations[0];
249
+ match &d.id {
250
+ oxc::ast::ast::BindingPattern::BindingIdentifier(b) => (
251
+ b.name.as_str(),
252
+ span_util::oxc_span_to_tish(ctx.1, b.as_ref()),
253
+ ),
254
+ _ => {
255
+ return Err(ConvertError::new(ConvertErrorKind::Incompatible {
256
+ what: "for-of with destructuring".into(),
257
+ reason: "use simple identifier".into(),
258
+ }))
259
+ }
260
+ }
261
+ } else {
262
+ return Err(ConvertError::new(ConvertErrorKind::Incompatible {
263
+ what: "for-of with multiple bindings".into(),
264
+ reason: "not supported".into(),
265
+ }));
266
+ }
267
+ }
268
+ _ => {
269
+ return Err(ConvertError::new(ConvertErrorKind::Incompatible {
270
+ what: "for-of (use variable declaration in left)".into(),
271
+ reason: "e.g. for (const x of arr)".into(),
272
+ }))
273
+ }
274
+ };
275
+ let iterable = expr::convert_expr(&f.right, ctx)?;
276
+ let body = Box::new(convert_statement(&f.body, ctx)?);
277
+ Ok(Statement::ForOf {
278
+ name: Arc::from(name),
279
+ name_span,
280
+ iterable,
281
+ body,
282
+ span,
283
+ })
284
+ }
285
+
286
+ fn convert_switch_statement(
287
+ s: &oxc::ast::ast::SwitchStatement<'_>,
288
+ ctx: &Ctx<'_>,
289
+ span: Span,
290
+ ) -> Result<Statement, ConvertError> {
291
+ let expr = expr::convert_expr(&s.discriminant, ctx)?;
292
+ let mut cases = Vec::new();
293
+ let mut default_body: Option<Vec<Statement>> = None;
294
+ for c in &s.cases {
295
+ let stmts = convert_statements(&c.consequent, ctx.0, ctx.1)?;
296
+ match &c.test {
297
+ Some(t) => cases.push((Some(expr::convert_expr(t, ctx)?), stmts)),
298
+ None => default_body = Some(stmts),
299
+ }
300
+ }
301
+ Ok(Statement::Switch {
302
+ expr,
303
+ cases,
304
+ default_body,
305
+ span,
306
+ })
307
+ }
308
+
309
+ fn convert_try_statement(
310
+ t: &oxc::ast::ast::TryStatement<'_>,
311
+ ctx: &Ctx<'_>,
312
+ span: Span,
313
+ ) -> Result<Statement, ConvertError> {
314
+ // TryStatement.block is BlockStatement; convert its body to Statement::Block
315
+ let body_stmts = convert_statements(&t.block.body, ctx.0, ctx.1)?;
316
+ let body = Box::new(Statement::Block {
317
+ statements: body_stmts,
318
+ span: span_util::oxc_span_to_tish(ctx.1, &*t.block),
319
+ });
320
+ let (catch_param, catch_param_span, catch_body) = match &t.handler {
321
+ Some(h) => {
322
+ let (param, pspan) = h
323
+ .param
324
+ .as_ref()
325
+ .and_then(|cp: &oxc::ast::ast::CatchParameter<'_>| {
326
+ if let oxc::ast::ast::BindingPattern::BindingIdentifier(b) = &cp.pattern {
327
+ Some((
328
+ Arc::from(b.name.as_str()),
329
+ span_util::oxc_span_to_tish(ctx.1, b.as_ref()),
330
+ ))
331
+ } else {
332
+ None
333
+ }
334
+ })
335
+ .map_or((None, None), |(n, s)| (Some(n), Some(s)));
336
+ let catch_stmts = convert_statements(&h.body.body, ctx.0, ctx.1)?;
337
+ let cb = Box::new(Statement::Block {
338
+ statements: catch_stmts,
339
+ span: span_util::oxc_span_to_tish(ctx.1, &*h.body),
340
+ });
341
+ (param, pspan, Some(cb))
342
+ }
343
+ None => (None, None, None),
344
+ };
345
+ let finally_body = t
346
+ .finalizer
347
+ .as_ref()
348
+ .map(|f| {
349
+ let stmts = convert_statements(&f.body, ctx.0, ctx.1)?;
350
+ Ok(Box::new(Statement::Block {
351
+ statements: stmts,
352
+ span: span_util::oxc_span_to_tish(ctx.1, &**f),
353
+ }))
354
+ })
355
+ .transpose()?;
356
+ Ok(Statement::Try {
357
+ body,
358
+ catch_param,
359
+ catch_param_span,
360
+ catch_body,
361
+ finally_body,
362
+ span,
363
+ })
364
+ }
365
+
366
+ fn convert_function_decl(
367
+ f: &oxc::ast::ast::Function<'_>,
368
+ ctx: &Ctx<'_>,
369
+ span: Span,
370
+ ) -> Result<Statement, ConvertError> {
371
+ let async_ = f.r#async;
372
+ let name: Arc<str> =
373
+ f.id.as_ref()
374
+ .map(|id| Arc::from(id.name.as_str()))
375
+ .unwrap_or_else(|| Arc::from(""));
376
+ let name_span =
377
+ f.id.as_ref()
378
+ .map(|id| span_util::oxc_span_to_tish(ctx.1, id))
379
+ .unwrap_or_else(span_util::stub_span);
380
+ let (params, rest_param) = expr::convert_params(&f.params, ctx)?;
381
+ let body = match &f.body {
382
+ Some(fb) => {
383
+ let stmts = convert_statements(&fb.statements, ctx.0, ctx.1)?;
384
+ Box::new(Statement::Block {
385
+ statements: stmts,
386
+ span: span_util::oxc_span_to_tish(ctx.1, fb.as_ref()),
387
+ })
388
+ }
389
+ None => {
390
+ return Err(ConvertError::new(ConvertErrorKind::Incompatible {
391
+ what: "function body".into(),
392
+ reason: "expected block".into(),
393
+ }))
394
+ }
395
+ };
396
+ Ok(Statement::FunDecl {
397
+ async_,
398
+ name,
399
+ name_span,
400
+ params,
401
+ rest_param,
402
+ return_type: None,
403
+ body,
404
+ span,
405
+ })
406
+ }
407
+
408
+ fn convert_import(
409
+ i: &oxc::ast::ast::ImportDeclaration<'_>,
410
+ ctx: &Ctx<'_>,
411
+ span: Span,
412
+ ) -> Result<Statement, ConvertError> {
413
+ let from: Arc<str> = Arc::from(i.source.value.as_str());
414
+ let mut specifiers = Vec::new();
415
+ if let Some(specs) = &i.specifiers {
416
+ for s in specs.iter() {
417
+ match s {
418
+ oxc::ast::ast::ImportDeclarationSpecifier::ImportSpecifier(is) => {
419
+ let imported_name = is.imported.name().as_str();
420
+ let local_name = is.local.name.as_str();
421
+ let name_span = crate::span_util::oxc_span_to_tish(ctx.1, &is.imported);
422
+ let (alias, alias_span) = if imported_name == local_name {
423
+ (None, None)
424
+ } else {
425
+ (
426
+ Some(Arc::from(local_name)),
427
+ Some(crate::span_util::oxc_span_to_tish(ctx.1, &is.local)),
428
+ )
429
+ };
430
+ specifiers.push(tishlang_ast::ImportSpecifier::Named {
431
+ name: Arc::from(imported_name),
432
+ name_span,
433
+ alias,
434
+ alias_span,
435
+ });
436
+ }
437
+ oxc::ast::ast::ImportDeclarationSpecifier::ImportDefaultSpecifier(ds) => {
438
+ let name_span = crate::span_util::oxc_span_to_tish(ctx.1, &ds.local);
439
+ specifiers.push(tishlang_ast::ImportSpecifier::Default {
440
+ name: Arc::from(ds.local.name.as_str()),
441
+ name_span,
442
+ });
443
+ }
444
+ oxc::ast::ast::ImportDeclarationSpecifier::ImportNamespaceSpecifier(ns) => {
445
+ let name_span = crate::span_util::oxc_span_to_tish(ctx.1, &ns.local);
446
+ specifiers.push(tishlang_ast::ImportSpecifier::Namespace {
447
+ name: Arc::from(ns.local.name.as_str()),
448
+ name_span,
449
+ });
450
+ }
451
+ }
452
+ }
453
+ }
454
+ Ok(Statement::Import {
455
+ specifiers,
456
+ from,
457
+ span,
458
+ })
459
+ }
460
+
461
+ fn convert_export_default(
462
+ e: &oxc::ast::ast::ExportDefaultDeclaration<'_>,
463
+ ctx: &Ctx<'_>,
464
+ span: Span,
465
+ ) -> Result<Statement, ConvertError> {
466
+ let declaration = if let Some(expr) = e.declaration.as_expression() {
467
+ let expr = expr::convert_expr(expr, ctx)?;
468
+ tishlang_ast::ExportDeclaration::Default(expr)
469
+ } else if let oxc::ast::ast::ExportDefaultDeclarationKind::FunctionDeclaration(f) =
470
+ &e.declaration
471
+ {
472
+ let stmt = convert_function_decl(f.as_ref(), ctx, span_util::stub_span())?;
473
+ tishlang_ast::ExportDeclaration::Named(Box::new(stmt))
474
+ } else {
475
+ return Err(ConvertError::new(ConvertErrorKind::Unsupported {
476
+ what: "export default (this form)".into(),
477
+ hint: None,
478
+ }));
479
+ };
480
+ Ok(Statement::Export {
481
+ declaration: Box::new(declaration),
482
+ span,
483
+ })
484
+ }
485
+
486
+ fn convert_export_named(
487
+ e: &oxc::ast::ast::ExportNamedDeclaration<'_>,
488
+ ctx: &Ctx<'_>,
489
+ span: Span,
490
+ ) -> Result<Statement, ConvertError> {
491
+ if let Some(decl) = &e.declaration {
492
+ let stmt = convert_declaration(decl, ctx)?;
493
+ Ok(Statement::Export {
494
+ declaration: Box::new(tishlang_ast::ExportDeclaration::Named(Box::new(stmt))),
495
+ span,
496
+ })
497
+ } else {
498
+ Err(ConvertError::new(ConvertErrorKind::Unsupported {
499
+ what: "export { ... } (re-exports)".into(),
500
+ hint: None,
501
+ }))
502
+ }
503
+ }
@@ -0,0 +1,60 @@
1
+ //! Convert OXC AST (with semantic info) to Tish AST.
2
+
3
+ mod expr;
4
+ mod stmt;
5
+
6
+ use oxc::allocator::Allocator;
7
+ use oxc::parser::Parser;
8
+ use oxc::semantic::SemanticBuilder;
9
+ use oxc::span::SourceType;
10
+ use tishlang_ast::Program;
11
+
12
+ use crate::error::{ConvertError, ConvertErrorKind};
13
+ use crate::transform::stmt::convert_statements;
14
+
15
+ /// Convert JavaScript source to Tish AST.
16
+ ///
17
+ /// Performs parse, semantic analysis, normalization (var/function hoisting),
18
+ /// and transformation to Tish AST.
19
+ pub fn convert(js_source: &str) -> Result<Program, ConvertError> {
20
+ let allocator = Allocator::default();
21
+ let source_type = SourceType::from_path("script.js").unwrap();
22
+ let parser_ret = Parser::new(&allocator, js_source, source_type).parse();
23
+
24
+ if parser_ret.panicked {
25
+ let msg = parser_ret
26
+ .errors
27
+ .iter()
28
+ .map(|e| format!("{e:?}"))
29
+ .collect::<Vec<_>>()
30
+ .join("; ");
31
+ return Err(ConvertError::new(ConvertErrorKind::Parse(msg)));
32
+ }
33
+ if !parser_ret.errors.is_empty() {
34
+ let msg = parser_ret
35
+ .errors
36
+ .into_iter()
37
+ .map(|e| format!("{e:?}"))
38
+ .collect::<Vec<_>>()
39
+ .join("; ");
40
+ return Err(ConvertError::new(ConvertErrorKind::Parse(msg)));
41
+ }
42
+
43
+ let program = parser_ret.program;
44
+ let semantic_ret = SemanticBuilder::new()
45
+ .with_check_syntax_error(true)
46
+ .build(&program);
47
+
48
+ if !semantic_ret.errors.is_empty() {
49
+ let msg = semantic_ret
50
+ .errors
51
+ .into_iter()
52
+ .map(|e| format!("{e:?}"))
53
+ .collect::<Vec<_>>()
54
+ .join("; ");
55
+ return Err(ConvertError::new(ConvertErrorKind::Semantic(msg)));
56
+ }
57
+
58
+ let statements = convert_statements(&program.body, &semantic_ret.semantic, js_source)?;
59
+ Ok(Program { statements })
60
+ }
@@ -0,0 +1,54 @@
1
+ [package]
2
+ name = "tishlang"
3
+ version = "0.0.0-dev"
4
+ edition = "2021"
5
+ description = "Tish CLI - run, REPL, compile to native"
6
+ license-file = { workspace = true }
7
+ repository = { workspace = true }
8
+
9
+ [[bin]]
10
+ name = "tish"
11
+ path = "src/main.rs"
12
+
13
+ [features]
14
+ # The published `tish` CLI always includes every optional runtime (http, timers, fs, process, regex, ws).
15
+ # Use `cargo build -p tishlang --no-default-features` when you need a locked-down toolchain
16
+ # (see workspace `justfile`). `tish run --feature …` / `tish build --feature …` gate what runs
17
+ # or what gets linked into a *native output* binary — they are not the primary way to ship a
18
+ # “full” vs “empty” CLI.
19
+ default = ["full"]
20
+ # Alias: same dependency edges as `default` (kept for `--features full` in CI and docs).
21
+ # Includes `pg` so `tish run` can resolve `import … from '@tishlang/pg'` (`cargo:tish_pg`) on the bytecode VM.
22
+ full = ["http", "fs", "process", "regex", "ws", "timers", "pg"]
23
+ # Opt-out: build without Postgres (`cargo build -p tishlang --no-default-features --features http,...`).
24
+ pg = ["dep:tishlang_pg"]
25
+ # Individual capability flags
26
+ http = ["tishlang_eval/http", "tishlang_runtime/http", "tishlang_compile/http", "tishlang_vm/http"]
27
+ timers = ["tishlang_eval/timers", "tishlang_compile/timers", "tishlang_vm/timers"]
28
+ fs = ["tishlang_eval/fs", "tishlang_runtime/fs", "tishlang_compile/fs", "tishlang_vm/fs"]
29
+ process = ["tishlang_eval/process", "tishlang_runtime/process", "tishlang_compile/process", "tishlang_vm/process"]
30
+ regex = ["tishlang_eval/regex", "tishlang_runtime/regex", "tishlang_compile/regex", "tishlang_vm/regex"]
31
+ ws = ["tishlang_eval/ws", "tishlang_runtime/ws", "tishlang_compile/ws", "tishlang_vm/ws"]
32
+ # GPU compute — Apple Silicon only
33
+ [dependencies]
34
+ rustyline = { version = "17", features = ["with-file-history"] }
35
+ tishlang_lexer = { path = "../tish_lexer", version = ">=0.1" }
36
+ tishlang_ast = { path = "../tish_ast", version = ">=0.1" }
37
+ tishlang_parser = { path = "../tish_parser", version = ">=0.1" }
38
+ tishlang_eval = { path = "../tish_eval", version = ">=0.1" }
39
+ tishlang_compile = { path = "../tish_compile", version = ">=0.1" }
40
+ tishlang_compile_js = { path = "../tish_compile_js", version = ">=0.1" }
41
+ tishlang_bytecode = { path = "../tish_bytecode", version = ">=0.1" }
42
+ tishlang_opt = { path = "../tish_opt", version = ">=0.1" }
43
+ tishlang_vm = { path = "../tish_vm", version = ">=0.1" }
44
+ tishlang_native = { path = "../tish_native", version = ">=0.1" }
45
+ tishlang_llvm = { path = "../tish_llvm", version = ">=0.1" }
46
+ tishlang_wasm = { path = "../tish_wasm", version = ">=0.1" }
47
+ tishlang_runtime = { path = "../tish_runtime", version = ">=0.1" }
48
+ tishlang_core = { path = "../tish_core", version = ">=0.1" }
49
+ tishlang_js_to_tish = { path = "../js_to_tish", version = ">=0.1" }
50
+ clap = { version = "4.6.0", features = ["derive", "color"] }
51
+ tishlang_pg = { path = "../tish_pg", version = ">=0.1", optional = true }
52
+
53
+ [dev-dependencies]
54
+ rayon = "1.11"
@@ -0,0 +1,32 @@
1
+ //! Registers `cargo:*` Rust shims on the bytecode VM (`tish run`, REPL).
2
+ //!
3
+ //! Native `tish build` outputs register their own crates at link time; the
4
+ //! interpreter path must populate [`tishlang_vm::Vm::register_native_module`].
5
+
6
+ #[cfg(feature = "pg")]
7
+ pub(crate) fn register_bytecode_native_modules(vm: &mut tishlang_vm::Vm) {
8
+ use std::sync::Arc;
9
+ use tishlang_core::{ObjectMap, Value};
10
+
11
+ let mut om = ObjectMap::with_capacity(8);
12
+ om.insert(
13
+ Arc::from("per_worker_client"),
14
+ Value::native(tishlang_pg::per_worker_client),
15
+ );
16
+ om.insert(Arc::from("connect"), Value::native(tishlang_pg::connect));
17
+ om.insert(Arc::from("prepare"), Value::native(tishlang_pg::prepare));
18
+ om.insert(
19
+ Arc::from("query_prepared"),
20
+ Value::native(tishlang_pg::query_prepared),
21
+ );
22
+ om.insert(
23
+ Arc::from("query_all"),
24
+ Value::native(tishlang_pg::query_all),
25
+ );
26
+ om.insert(Arc::from("migrate"), Value::native(tishlang_pg::migrate));
27
+ om.insert(Arc::from("close"), Value::native(tishlang_pg::close));
28
+ vm.register_native_module("cargo:tish_pg", om);
29
+ }
30
+
31
+ #[cfg(not(feature = "pg"))]
32
+ pub(crate) fn register_bytecode_native_modules(_vm: &mut tishlang_vm::Vm) {}