@tishlang/tish 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -0
- package/bin/tish +0 -0
- package/crates/js_to_tish/src/error.rs +2 -8
- package/crates/js_to_tish/src/transform/expr.rs +101 -130
- package/crates/js_to_tish/src/transform/stmt.rs +25 -22
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/src/cli_help.rs +76 -29
- package/crates/tish/src/main.rs +85 -54
- package/crates/tish/tests/cargo_example_compile.rs +67 -0
- package/crates/tish/tests/fixtures/cargo_example_project/Cargo.toml +3 -0
- package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/Cargo.toml +11 -0
- package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +12 -0
- package/crates/tish/tests/fixtures/cargo_example_project/package.json +10 -0
- package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +3 -0
- package/crates/tish/tests/integration_test.rs +197 -47
- package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
- package/crates/tish/tests/shortcircuit.rs +19 -4
- package/crates/tish_ast/src/ast.rs +12 -14
- package/crates/tish_build_utils/src/lib.rs +64 -6
- package/crates/tish_builtins/src/array.rs +52 -21
- package/crates/tish_builtins/src/construct.rs +2 -8
- package/crates/tish_builtins/src/globals.rs +30 -15
- package/crates/tish_builtins/src/lib.rs +5 -5
- package/crates/tish_builtins/src/math.rs +5 -3
- package/crates/tish_builtins/src/string.rs +71 -19
- package/crates/tish_bytecode/src/chunk.rs +0 -1
- package/crates/tish_bytecode/src/compiler.rs +164 -60
- package/crates/tish_bytecode/src/opcode.rs +13 -4
- package/crates/tish_bytecode/src/peephole.rs +2 -2
- package/crates/tish_compile/Cargo.toml +1 -0
- package/crates/tish_compile/src/codegen.rs +989 -318
- package/crates/tish_compile/src/infer.rs +69 -19
- package/crates/tish_compile/src/lib.rs +21 -8
- package/crates/tish_compile/src/resolve.rs +515 -94
- package/crates/tish_compile/src/types.rs +10 -14
- package/crates/tish_compile_js/src/codegen.rs +34 -13
- package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
- package/crates/tish_compiler_wasm/src/lib.rs +16 -13
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +40 -48
- package/crates/tish_core/src/json.rs +5 -3
- package/crates/tish_core/src/lib.rs +1 -1
- package/crates/tish_core/src/uri.rs +9 -6
- package/crates/tish_core/src/value.rs +92 -28
- package/crates/tish_cranelift/src/link.rs +6 -9
- package/crates/tish_cranelift/src/lower.rs +14 -8
- package/crates/tish_eval/src/eval.rs +398 -141
- package/crates/tish_eval/src/lib.rs +10 -6
- package/crates/tish_eval/src/natives.rs +95 -38
- package/crates/tish_eval/src/promise.rs +14 -8
- package/crates/tish_eval/src/timers.rs +28 -19
- package/crates/tish_eval/src/value.rs +10 -3
- package/crates/tish_fmt/src/lib.rs +29 -13
- package/crates/tish_lexer/src/lib.rs +217 -63
- package/crates/tish_lexer/src/token.rs +6 -6
- package/crates/tish_llvm/src/lib.rs +15 -8
- package/crates/tish_lsp/src/main.rs +41 -43
- package/crates/tish_native/src/build.rs +38 -15
- package/crates/tish_native/src/lib.rs +76 -32
- package/crates/tish_opt/src/lib.rs +67 -50
- package/crates/tish_parser/src/lib.rs +36 -11
- package/crates/tish_parser/src/parser.rs +172 -87
- package/crates/tish_runtime/src/http.rs +15 -6
- package/crates/tish_runtime/src/http_fetch.rs +24 -14
- package/crates/tish_runtime/src/lib.rs +224 -168
- package/crates/tish_runtime/src/promise.rs +1 -5
- package/crates/tish_runtime/src/ws.rs +45 -20
- package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
- package/crates/tish_ui/src/jsx.rs +41 -22
- package/crates/tish_ui/src/lib.rs +2 -2
- package/crates/tish_vm/src/vm.rs +320 -116
- package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
- package/crates/tish_wasm/src/lib.rs +38 -28
- package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
- package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
- package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
- package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
- package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
- package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
- package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
- package/package.json +1 -1
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- package/platform/win32-x64/tish.exe +0 -0
package/Cargo.toml
CHANGED
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,
|
|
9
|
-
|
|
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 {
|
|
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)?);
|
|
@@ -112,10 +117,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
112
117
|
})
|
|
113
118
|
}
|
|
114
119
|
OxcExpr::LogicalExpression(l) => {
|
|
115
|
-
if matches!(
|
|
116
|
-
l.operator,
|
|
117
|
-
oxc::ast::ast::LogicalOperator::Coalesce
|
|
118
|
-
) {
|
|
120
|
+
if matches!(l.operator, oxc::ast::ast::LogicalOperator::Coalesce) {
|
|
119
121
|
Ok(Expr::NullishCoalesce {
|
|
120
122
|
left: Box::new(convert_expr(&l.left, ctx)?),
|
|
121
123
|
right: Box::new(convert_expr(&l.right, ctx)?),
|
|
@@ -155,12 +157,12 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
155
157
|
OxcExpr::ArrowFunctionExpression(arrow) => {
|
|
156
158
|
let params = convert_arrow_params(&arrow.params, ctx)?;
|
|
157
159
|
let body = if arrow.expression {
|
|
158
|
-
let e = arrow
|
|
159
|
-
|
|
160
|
-
.ok_or_else(|| ConvertError::new(ConvertErrorKind::Incompatible {
|
|
160
|
+
let e = arrow.get_expression().ok_or_else(|| {
|
|
161
|
+
ConvertError::new(ConvertErrorKind::Incompatible {
|
|
161
162
|
what: "arrow expression body".into(),
|
|
162
163
|
reason: "expected expression".into(),
|
|
163
|
-
})
|
|
164
|
+
})
|
|
165
|
+
})?;
|
|
164
166
|
ArrowBody::Expr(Box::new(convert_expr(e, ctx)?))
|
|
165
167
|
} else {
|
|
166
168
|
let stmts = super::stmt::convert_statements(&arrow.body.statements, ctx.0, ctx.1)?;
|
|
@@ -169,11 +171,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
169
171
|
span: span_util::oxc_span_to_tish(ctx.1, &*arrow.body),
|
|
170
172
|
}))
|
|
171
173
|
};
|
|
172
|
-
Ok(Expr::ArrowFunction {
|
|
173
|
-
params,
|
|
174
|
-
body,
|
|
175
|
-
span,
|
|
176
|
-
})
|
|
174
|
+
Ok(Expr::ArrowFunction { params, body, span })
|
|
177
175
|
}
|
|
178
176
|
OxcExpr::AwaitExpression(a) => Ok(Expr::Await {
|
|
179
177
|
operand: Box::new(convert_expr(&a.argument, ctx)?),
|
|
@@ -226,11 +224,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
226
224
|
}))
|
|
227
225
|
}
|
|
228
226
|
};
|
|
229
|
-
Ok(Expr::ArrowFunction {
|
|
230
|
-
params,
|
|
231
|
-
body,
|
|
232
|
-
span,
|
|
233
|
-
})
|
|
227
|
+
Ok(Expr::ArrowFunction { params, body, span })
|
|
234
228
|
}
|
|
235
229
|
_ => Err(ConvertError::new(ConvertErrorKind::Unsupported {
|
|
236
230
|
what: format!("expression: {:?}", std::mem::discriminant(expr)),
|
|
@@ -285,7 +279,10 @@ fn convert_call_arg(
|
|
|
285
279
|
) -> Result<tishlang_ast::CallArg, ConvertError> {
|
|
286
280
|
if arg.is_spread() {
|
|
287
281
|
if let oxc::ast::ast::Argument::SpreadElement(s) = arg {
|
|
288
|
-
Ok(tishlang_ast::CallArg::Spread(convert_expr(
|
|
282
|
+
Ok(tishlang_ast::CallArg::Spread(convert_expr(
|
|
283
|
+
&s.argument,
|
|
284
|
+
ctx,
|
|
285
|
+
)?))
|
|
289
286
|
} else {
|
|
290
287
|
unreachable!()
|
|
291
288
|
}
|
|
@@ -307,10 +304,12 @@ fn convert_array_element(
|
|
|
307
304
|
oxc::ast::ast::ArrayExpressionElement::SpreadElement(s) => {
|
|
308
305
|
Ok(ArrayElement::Spread(convert_expr(&s.argument, ctx)?))
|
|
309
306
|
}
|
|
310
|
-
oxc::ast::ast::ArrayExpressionElement::Elision(_) =>
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
307
|
+
oxc::ast::ast::ArrayExpressionElement::Elision(_) => {
|
|
308
|
+
Ok(ArrayElement::Expr(Expr::Literal {
|
|
309
|
+
value: Literal::Null,
|
|
310
|
+
span: span_util::stub_span(),
|
|
311
|
+
}))
|
|
312
|
+
}
|
|
314
313
|
_ => {
|
|
315
314
|
if let Some(e) = el.as_expression() {
|
|
316
315
|
Ok(ArrayElement::Expr(convert_expr(e, ctx)?))
|
|
@@ -358,77 +357,59 @@ fn convert_assignment(
|
|
|
358
357
|
let name = id.name.as_str();
|
|
359
358
|
let value = Box::new(convert_expr(right, ctx)?);
|
|
360
359
|
return match &a.operator {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
}
|
|
360
|
+
oxc::ast::ast::AssignmentOperator::Assign => Ok(Expr::Assign {
|
|
361
|
+
name: Arc::from(name),
|
|
362
|
+
value,
|
|
363
|
+
span,
|
|
364
|
+
}),
|
|
365
|
+
oxc::ast::ast::AssignmentOperator::Addition => Ok(Expr::CompoundAssign {
|
|
366
|
+
name: Arc::from(name),
|
|
367
|
+
op: CompoundOp::Add,
|
|
368
|
+
value,
|
|
369
|
+
span,
|
|
370
|
+
}),
|
|
371
|
+
oxc::ast::ast::AssignmentOperator::Subtraction => Ok(Expr::CompoundAssign {
|
|
372
|
+
name: Arc::from(name),
|
|
373
|
+
op: CompoundOp::Sub,
|
|
374
|
+
value,
|
|
375
|
+
span,
|
|
376
|
+
}),
|
|
377
|
+
oxc::ast::ast::AssignmentOperator::Multiplication => Ok(Expr::CompoundAssign {
|
|
378
|
+
name: Arc::from(name),
|
|
379
|
+
op: CompoundOp::Mul,
|
|
380
|
+
value,
|
|
381
|
+
span,
|
|
382
|
+
}),
|
|
383
|
+
oxc::ast::ast::AssignmentOperator::Division => Ok(Expr::CompoundAssign {
|
|
384
|
+
name: Arc::from(name),
|
|
385
|
+
op: CompoundOp::Div,
|
|
386
|
+
value,
|
|
387
|
+
span,
|
|
388
|
+
}),
|
|
389
|
+
oxc::ast::ast::AssignmentOperator::Remainder => Ok(Expr::CompoundAssign {
|
|
390
|
+
name: Arc::from(name),
|
|
391
|
+
op: CompoundOp::Mod,
|
|
392
|
+
value,
|
|
393
|
+
span,
|
|
394
|
+
}),
|
|
395
|
+
oxc::ast::ast::AssignmentOperator::LogicalAnd => Ok(Expr::LogicalAssign {
|
|
396
|
+
name: Arc::from(name),
|
|
397
|
+
op: LogicalAssignOp::AndAnd,
|
|
398
|
+
value,
|
|
399
|
+
span,
|
|
400
|
+
}),
|
|
401
|
+
oxc::ast::ast::AssignmentOperator::LogicalOr => Ok(Expr::LogicalAssign {
|
|
402
|
+
name: Arc::from(name),
|
|
403
|
+
op: LogicalAssignOp::OrOr,
|
|
404
|
+
value,
|
|
405
|
+
span,
|
|
406
|
+
}),
|
|
407
|
+
oxc::ast::ast::AssignmentOperator::LogicalNullish => Ok(Expr::LogicalAssign {
|
|
408
|
+
name: Arc::from(name),
|
|
409
|
+
op: LogicalAssignOp::Nullish,
|
|
410
|
+
value,
|
|
411
|
+
span,
|
|
412
|
+
}),
|
|
432
413
|
_ => Err(ConvertError::new(ConvertErrorKind::Unsupported {
|
|
433
414
|
what: "assignment operator".into(),
|
|
434
415
|
hint: None,
|
|
@@ -458,24 +439,14 @@ fn convert_update_expr(
|
|
|
458
439
|
}
|
|
459
440
|
};
|
|
460
441
|
Ok(match (u.operator, u.prefix) {
|
|
461
|
-
(oxc::ast::ast::UpdateOperator::Increment, true) => {
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
(oxc::ast::ast::UpdateOperator::
|
|
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
|
-
}
|
|
442
|
+
(oxc::ast::ast::UpdateOperator::Increment, true) => Expr::PrefixInc { name, span },
|
|
443
|
+
(oxc::ast::ast::UpdateOperator::Increment, false) => Expr::PostfixInc { name, span },
|
|
444
|
+
(oxc::ast::ast::UpdateOperator::Decrement, true) => Expr::PrefixDec { name, span },
|
|
445
|
+
(oxc::ast::ast::UpdateOperator::Decrement, false) => Expr::PostfixDec { name, span },
|
|
473
446
|
})
|
|
474
447
|
}
|
|
475
448
|
|
|
476
|
-
fn convert_bin_op(
|
|
477
|
-
op: &oxc::ast::ast::BinaryOperator,
|
|
478
|
-
) -> Result<BinOp, ConvertError> {
|
|
449
|
+
fn convert_bin_op(op: &oxc::ast::ast::BinaryOperator) -> Result<BinOp, ConvertError> {
|
|
479
450
|
Ok(match op {
|
|
480
451
|
oxc::ast::ast::BinaryOperator::Equality => BinOp::Eq,
|
|
481
452
|
oxc::ast::ast::BinaryOperator::Inequality => BinOp::Ne,
|
|
@@ -554,24 +525,24 @@ pub fn convert_params(
|
|
|
554
525
|
let fp = p;
|
|
555
526
|
{
|
|
556
527
|
let name = match &fp.pattern {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
528
|
+
oxc::ast::ast::BindingPattern::BindingIdentifier(b) => b.name.as_str(),
|
|
529
|
+
_ => {
|
|
530
|
+
return Err(ConvertError::new(ConvertErrorKind::Unsupported {
|
|
531
|
+
what: "destructuring in params".into(),
|
|
532
|
+
hint: None,
|
|
533
|
+
}))
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
let default = fp
|
|
537
|
+
.initializer
|
|
538
|
+
.as_ref()
|
|
539
|
+
.map(|e| convert_expr(e, ctx))
|
|
540
|
+
.transpose()?;
|
|
541
|
+
typed_params.push(FunParam::Simple(TypedParam {
|
|
542
|
+
name: Arc::from(name),
|
|
543
|
+
type_ann: None,
|
|
544
|
+
default,
|
|
545
|
+
}));
|
|
575
546
|
}
|
|
576
547
|
}
|
|
577
548
|
if rest_param.is_none() {
|
|
@@ -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::{
|
|
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,7 +141,11 @@ 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
|
|
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());
|
|
@@ -314,13 +313,16 @@ fn convert_try_statement(
|
|
|
314
313
|
});
|
|
315
314
|
let (catch_param, catch_body) = match &t.handler {
|
|
316
315
|
Some(h) => {
|
|
317
|
-
let param = h
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
316
|
+
let param = h
|
|
317
|
+
.param
|
|
318
|
+
.as_ref()
|
|
319
|
+
.and_then(|cp: &oxc::ast::ast::CatchParameter<'_>| {
|
|
320
|
+
if let oxc::ast::ast::BindingPattern::BindingIdentifier(b) = &cp.pattern {
|
|
321
|
+
Some(Arc::from(b.name.as_str()))
|
|
322
|
+
} else {
|
|
323
|
+
None
|
|
324
|
+
}
|
|
325
|
+
});
|
|
324
326
|
let catch_stmts = convert_statements(&h.body.body, ctx.0, ctx.1)?;
|
|
325
327
|
let cb = Box::new(Statement::Block {
|
|
326
328
|
statements: catch_stmts,
|
|
@@ -356,11 +358,10 @@ fn convert_function_decl(
|
|
|
356
358
|
span: Span,
|
|
357
359
|
) -> Result<Statement, ConvertError> {
|
|
358
360
|
let async_ = f.r#async;
|
|
359
|
-
let name: Arc<str> =
|
|
360
|
-
.id
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
.unwrap_or_else(|| Arc::from(""));
|
|
361
|
+
let name: Arc<str> =
|
|
362
|
+
f.id.as_ref()
|
|
363
|
+
.map(|id| Arc::from(id.name.as_str()))
|
|
364
|
+
.unwrap_or_else(|| Arc::from(""));
|
|
364
365
|
let (params, rest_param) = expr::convert_params(&f.params, ctx)?;
|
|
365
366
|
let body = match &f.body {
|
|
366
367
|
Some(fb) => {
|
|
@@ -439,7 +440,9 @@ fn convert_export_default(
|
|
|
439
440
|
let declaration = if let Some(expr) = e.declaration.as_expression() {
|
|
440
441
|
let expr = expr::convert_expr(expr, ctx)?;
|
|
441
442
|
tishlang_ast::ExportDeclaration::Default(expr)
|
|
442
|
-
} else if let oxc::ast::ast::ExportDefaultDeclarationKind::FunctionDeclaration(f) =
|
|
443
|
+
} else if let oxc::ast::ast::ExportDefaultDeclarationKind::FunctionDeclaration(f) =
|
|
444
|
+
&e.declaration
|
|
445
|
+
{
|
|
443
446
|
let stmt = convert_function_decl(f.as_ref(), ctx, span_util::stub_span())?;
|
|
444
447
|
tishlang_ast::ExportDeclaration::Named(Box::new(stmt))
|
|
445
448
|
} else {
|
package/crates/tish/Cargo.toml
CHANGED
|
@@ -9,7 +9,7 @@ use clap::{CommandFactory, Parser, Subcommand};
|
|
|
9
9
|
|
|
10
10
|
/// FIGlet-style block letters (UTF-8). On a TTY, a short expand + palette-color animation runs.
|
|
11
11
|
const TISH_BANNER_LINES: &[&str] = &[
|
|
12
|
-
|
|
12
|
+
"",
|
|
13
13
|
"████████╗██╗███████╗██╗ ██╗",
|
|
14
14
|
"╚══██╔══╝██║██╔════╝██║ ██║",
|
|
15
15
|
" ██║ ██║███████╗███████║",
|
|
@@ -26,13 +26,13 @@ const BANNER_FRAME_MS: u64 = 20;
|
|
|
26
26
|
|
|
27
27
|
/// Orange → Yellow → Green → Teal → Blue → Purple → Pink (matching the brand palette).
|
|
28
28
|
const PALETTE: &[(u8, u8, u8)] = &[
|
|
29
|
-
(255, 159,
|
|
30
|
-
(255, 213,
|
|
31
|
-
(
|
|
32
|
-
(
|
|
33
|
-
(
|
|
34
|
-
(175,
|
|
35
|
-
(255,
|
|
29
|
+
(255, 159, 64), // Orange
|
|
30
|
+
(255, 213, 64), // Yellow
|
|
31
|
+
(52, 199, 89), // Green
|
|
32
|
+
(48, 209, 188), // Teal
|
|
33
|
+
(10, 132, 255), // Blue
|
|
34
|
+
(175, 82, 222), // Purple
|
|
35
|
+
(255, 55, 148), // Pink
|
|
36
36
|
];
|
|
37
37
|
|
|
38
38
|
fn ease_out_cubic(t: f32) -> f32 {
|
|
@@ -128,8 +128,8 @@ pub fn print_tish_banner() {
|
|
|
128
128
|
pub fn build_command() -> clap::Command {
|
|
129
129
|
Cli::command()
|
|
130
130
|
.after_help(cli_after_help())
|
|
131
|
-
.mut_subcommand("run",
|
|
132
|
-
.mut_subcommand("repl",
|
|
131
|
+
.mut_subcommand("run", |sub| sub.after_help(run_after_help()))
|
|
132
|
+
.mut_subcommand("repl", |sub| sub.after_help(repl_after_help()))
|
|
133
133
|
.mut_subcommand("build", |sub| sub.after_long_help(build_after_help()))
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -138,7 +138,10 @@ fn count_help_lines(cmd: &mut clap::Command, sub_name: Option<&str>) -> usize {
|
|
|
138
138
|
let mut buf = Vec::<u8>::new();
|
|
139
139
|
if let Some(name) = sub_name {
|
|
140
140
|
if cmd.find_subcommand(name).is_some() {
|
|
141
|
-
let _ = cmd
|
|
141
|
+
let _ = cmd
|
|
142
|
+
.find_subcommand_mut(name)
|
|
143
|
+
.unwrap()
|
|
144
|
+
.write_long_help(&mut buf);
|
|
142
145
|
} else {
|
|
143
146
|
let _ = cmd.write_long_help(&mut buf);
|
|
144
147
|
}
|
|
@@ -236,8 +239,11 @@ pub fn print_banner_with_help(argv: &[String]) {
|
|
|
236
239
|
let mut out = io::stdout().lock();
|
|
237
240
|
write_tish_banner_frame(&mut out, 1.0, 0);
|
|
238
241
|
let _ = writeln!(out); // blank separator (row n+1)
|
|
239
|
-
|
|
240
|
-
let _ = writeln!(
|
|
242
|
+
// ── Manual prefix (MAIN_PREFIX_LINES = 4 lines) ──────────────────
|
|
243
|
+
let _ = writeln!(
|
|
244
|
+
out,
|
|
245
|
+
"{H_PURPLE}Tish{H_RESET} {H_GREY}(version {VERSION}){H_RESET}"
|
|
246
|
+
);
|
|
241
247
|
let _ = writeln!(out, "Minimal TS/JS-ish language");
|
|
242
248
|
let _ = writeln!(out, "{H_PINK}https://tishlang.com{H_RESET}");
|
|
243
249
|
let _ = writeln!(out); // blank before Usage
|
|
@@ -289,20 +295,24 @@ fn rgb_bold(r: u8, g: u8, b: u8) -> Style {
|
|
|
289
295
|
/// Orange → section headers / usage. Teal → literals (commands, flags). Yellow → placeholders.
|
|
290
296
|
pub fn cargo_help_styles() -> Styles {
|
|
291
297
|
Styles::styled()
|
|
292
|
-
.header(rgb_bold(255, 159,
|
|
293
|
-
.usage(rgb_bold(255, 159,
|
|
294
|
-
.literal(rgb_bold(
|
|
295
|
-
.placeholder(rgb_bold(255, 213,
|
|
296
|
-
.error(rgb_bold(255,
|
|
297
|
-
.valid(rgb_bold(
|
|
298
|
-
.invalid(rgb_bold(255,
|
|
298
|
+
.header(rgb_bold(255, 159, 64)) // Orange – "Commands:", "Options:", "Usage:"
|
|
299
|
+
.usage(rgb_bold(255, 159, 64)) // Orange
|
|
300
|
+
.literal(rgb_bold(48, 209, 188)) // Teal – run, repl, --help, -V …
|
|
301
|
+
.placeholder(rgb_bold(255, 213, 64)) // Yellow – <FILE>, <NAME>, …
|
|
302
|
+
.error(rgb_bold(255, 55, 148)) // Pink – error messages
|
|
303
|
+
.valid(rgb_bold(52, 199, 89)) // Green – valid values
|
|
304
|
+
.invalid(rgb_bold(255, 55, 148)) // Pink – invalid values
|
|
299
305
|
}
|
|
300
306
|
|
|
301
307
|
/// Returns the colored `after_help` text for the top-level `tish --help`.
|
|
302
308
|
/// Colors are emitted only when stdout is a TTY.
|
|
303
309
|
pub fn cli_after_help() -> String {
|
|
304
310
|
let (oh, t, r) = if io::stdout().is_terminal() {
|
|
305
|
-
(
|
|
311
|
+
(
|
|
312
|
+
"\x1b[1;38;2;255;159;64m",
|
|
313
|
+
"\x1b[1;38;2;48;209;188m",
|
|
314
|
+
"\x1b[0m",
|
|
315
|
+
)
|
|
306
316
|
} else {
|
|
307
317
|
("", "", "")
|
|
308
318
|
};
|
|
@@ -346,7 +356,11 @@ Omit --feature to use every capability linked into this binary."
|
|
|
346
356
|
/// Returns the colored `after_help` for `tish run --help`.
|
|
347
357
|
pub fn run_after_help() -> String {
|
|
348
358
|
let (oh, t, r) = if io::stdout().is_terminal() {
|
|
349
|
-
(
|
|
359
|
+
(
|
|
360
|
+
"\x1b[1;38;2;255;159;64m",
|
|
361
|
+
"\x1b[1;38;2;48;209;188m",
|
|
362
|
+
"\x1b[0m",
|
|
363
|
+
)
|
|
350
364
|
} else {
|
|
351
365
|
("", "", "")
|
|
352
366
|
};
|
|
@@ -356,7 +370,11 @@ pub fn run_after_help() -> String {
|
|
|
356
370
|
/// Returns the colored `after_help` for `tish repl --help`.
|
|
357
371
|
pub fn repl_after_help() -> String {
|
|
358
372
|
let (oh, t, r) = if io::stdout().is_terminal() {
|
|
359
|
-
(
|
|
373
|
+
(
|
|
374
|
+
"\x1b[1;38;2;255;159;64m",
|
|
375
|
+
"\x1b[1;38;2;48;209;188m",
|
|
376
|
+
"\x1b[0m",
|
|
377
|
+
)
|
|
360
378
|
} else {
|
|
361
379
|
("", "", "")
|
|
362
380
|
};
|
|
@@ -366,7 +384,11 @@ pub fn repl_after_help() -> String {
|
|
|
366
384
|
/// Returns the colored `after_long_help` for `tish build --help`.
|
|
367
385
|
pub fn build_after_help() -> String {
|
|
368
386
|
let (oh, t, r) = if io::stdout().is_terminal() {
|
|
369
|
-
(
|
|
387
|
+
(
|
|
388
|
+
"\x1b[1;38;2;255;159;64m",
|
|
389
|
+
"\x1b[1;38;2;48;209;188m",
|
|
390
|
+
"\x1b[0m",
|
|
391
|
+
)
|
|
370
392
|
} else {
|
|
371
393
|
("", "", "")
|
|
372
394
|
};
|
|
@@ -421,10 +443,20 @@ pub(crate) struct Cli {
|
|
|
421
443
|
#[derive(Parser)]
|
|
422
444
|
pub(crate) struct RunArgs {
|
|
423
445
|
/// Path to a `.tish` file, or `-` to read the program from stdin (like `node -`).
|
|
424
|
-
#[arg(
|
|
446
|
+
#[arg(
|
|
447
|
+
required = true,
|
|
448
|
+
allow_hyphen_values = true,
|
|
449
|
+
value_name = "FILE",
|
|
450
|
+
help_heading = "Arguments"
|
|
451
|
+
)]
|
|
425
452
|
pub file: String,
|
|
426
453
|
/// `vm` or `interp` (see `tish --help` for capabilities / `--feature`).
|
|
427
|
-
#[arg(
|
|
454
|
+
#[arg(
|
|
455
|
+
long,
|
|
456
|
+
default_value = "vm",
|
|
457
|
+
value_name = "NAME",
|
|
458
|
+
help_heading = "Options"
|
|
459
|
+
)]
|
|
428
460
|
pub backend: String,
|
|
429
461
|
/// Subset of capabilities (see `tish --help` for the full list).
|
|
430
462
|
#[arg(
|
|
@@ -442,7 +474,12 @@ pub(crate) struct RunArgs {
|
|
|
442
474
|
#[derive(Parser)]
|
|
443
475
|
pub(crate) struct ReplArgs {
|
|
444
476
|
/// `vm` or `interp` (see `tish --help`).
|
|
445
|
-
#[arg(
|
|
477
|
+
#[arg(
|
|
478
|
+
long,
|
|
479
|
+
default_value = "vm",
|
|
480
|
+
value_name = "NAME",
|
|
481
|
+
help_heading = "Options"
|
|
482
|
+
)]
|
|
446
483
|
pub backend: String,
|
|
447
484
|
/// Subset of capabilities (see `tish --help` for the full list).
|
|
448
485
|
#[arg(
|
|
@@ -467,10 +504,20 @@ pub(crate) struct BuildArgs {
|
|
|
467
504
|
)]
|
|
468
505
|
pub output: String,
|
|
469
506
|
/// `native`, `js`, `wasm`, or `wasi` (see long help below).
|
|
470
|
-
#[arg(
|
|
507
|
+
#[arg(
|
|
508
|
+
long,
|
|
509
|
+
default_value = "native",
|
|
510
|
+
value_name = "TARGET",
|
|
511
|
+
help_heading = "Options"
|
|
512
|
+
)]
|
|
471
513
|
pub target: String,
|
|
472
514
|
/// `rust`, `cranelift`, or `llvm` (only for `--target native`).
|
|
473
|
-
#[arg(
|
|
515
|
+
#[arg(
|
|
516
|
+
long,
|
|
517
|
+
default_value = "rust",
|
|
518
|
+
value_name = "BACKEND",
|
|
519
|
+
help_heading = "Options"
|
|
520
|
+
)]
|
|
474
521
|
pub native_backend: String,
|
|
475
522
|
/// Capability subset for native output (see long help below).
|
|
476
523
|
#[arg(
|