@tishlang/tish 1.0.13 → 1.0.14
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/crates/js_to_tish/Cargo.toml +4 -2
- package/crates/js_to_tish/src/span_util.rs +1 -1
- package/crates/js_to_tish/src/transform/expr.rs +15 -15
- package/crates/js_to_tish/src/transform/stmt.rs +7 -7
- package/crates/js_to_tish/src/transform.rs +1 -1
- package/crates/tish/Cargo.toml +22 -22
- package/crates/tish/src/main.rs +46 -46
- package/crates/tish/src/repl_completion.rs +4 -4
- package/crates/tish/tests/integration_test.rs +28 -28
- package/crates/tish_ast/Cargo.toml +3 -1
- package/crates/tish_ast/src/ast.rs +1 -1
- package/crates/tish_build_utils/Cargo.toml +3 -1
- package/crates/tish_build_utils/src/lib.rs +18 -6
- package/crates/tish_builtins/Cargo.toml +5 -3
- package/crates/tish_builtins/src/array.rs +2 -2
- package/crates/tish_builtins/src/globals.rs +3 -3
- package/crates/tish_builtins/src/helpers.rs +1 -1
- package/crates/tish_builtins/src/lib.rs +3 -3
- package/crates/tish_builtins/src/math.rs +1 -1
- package/crates/tish_builtins/src/object.rs +2 -2
- package/crates/tish_builtins/src/string.rs +1 -1
- package/crates/tish_bytecode/Cargo.toml +9 -7
- package/crates/tish_bytecode/src/chunk.rs +1 -1
- package/crates/tish_bytecode/src/compiler.rs +1 -1
- package/crates/tish_bytecode/src/encoding.rs +6 -6
- package/crates/tish_bytecode/tests/constant_folding.rs +7 -7
- package/crates/tish_bytecode/tests/shortcircuit.rs +11 -11
- package/crates/tish_bytecode/tests/sort_optimization.rs +3 -3
- package/crates/tish_compile/Cargo.toml +6 -4
- package/crates/tish_compile/src/codegen.rs +96 -96
- package/crates/tish_compile/src/lib.rs +2 -2
- package/crates/tish_compile/src/resolve.rs +7 -7
- package/crates/tish_compile/src/types.rs +1 -1
- package/crates/tish_compile_js/Cargo.toml +8 -6
- package/crates/tish_compile_js/src/codegen.rs +12 -12
- package/crates/tish_compile_js/src/js_intrinsics.rs +1 -1
- package/crates/tish_compile_js/src/lib.rs +2 -2
- package/crates/tish_compile_js/src/tests_jsx.rs +2 -2
- package/crates/tish_compiler_wasm/Cargo.toml +8 -6
- package/crates/tish_compiler_wasm/src/lib.rs +12 -12
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +3 -3
- package/crates/tish_core/Cargo.toml +3 -1
- package/crates/tish_core/src/lib.rs +1 -1
- package/crates/tish_core/src/macros.rs +1 -1
- package/crates/tish_core/src/value.rs +1 -1
- package/crates/tish_cranelift/Cargo.toml +6 -4
- package/crates/tish_cranelift/src/lib.rs +2 -2
- package/crates/tish_cranelift/src/link.rs +11 -11
- package/crates/tish_cranelift/src/lower.rs +3 -3
- package/crates/tish_cranelift_runtime/Cargo.toml +9 -7
- package/crates/tish_cranelift_runtime/src/lib.rs +2 -2
- package/crates/tish_eval/Cargo.toml +10 -8
- package/crates/tish_eval/src/eval.rs +35 -35
- package/crates/tish_eval/src/http.rs +1 -1
- package/crates/tish_eval/src/lib.rs +3 -3
- package/crates/tish_eval/src/natives.rs +2 -2
- package/crates/tish_eval/src/regex.rs +2 -2
- package/crates/tish_eval/src/value.rs +7 -7
- package/crates/tish_eval/src/value_convert.rs +3 -3
- package/crates/tish_fmt/Cargo.toml +3 -3
- package/crates/tish_fmt/src/bin/tish-fmt.rs +1 -1
- package/crates/tish_fmt/src/lib.rs +3 -3
- package/crates/tish_jsx_web/Cargo.toml +3 -1
- package/crates/tish_lexer/Cargo.toml +3 -1
- package/crates/tish_lint/Cargo.toml +3 -3
- package/crates/tish_lint/src/bin/tish-lint.rs +3 -3
- package/crates/tish_lint/src/lib.rs +15 -15
- package/crates/tish_llvm/Cargo.toml +7 -5
- package/crates/tish_llvm/src/lib.rs +10 -10
- package/crates/tish_lsp/Cargo.toml +5 -5
- package/crates/tish_lsp/src/main.rs +35 -35
- package/crates/tish_native/Cargo.toml +10 -8
- package/crates/tish_native/src/build.rs +8 -8
- package/crates/tish_native/src/lib.rs +39 -39
- package/crates/tish_opt/Cargo.toml +5 -3
- package/crates/tish_opt/src/lib.rs +27 -27
- package/crates/tish_parser/Cargo.toml +5 -3
- package/crates/tish_parser/src/lib.rs +4 -4
- package/crates/tish_parser/src/parser.rs +2 -2
- package/crates/tish_runtime/Cargo.toml +7 -5
- package/crates/tish_runtime/src/http.rs +1 -1
- package/crates/tish_runtime/src/http_fetch.rs +2 -2
- package/crates/tish_runtime/src/lib.rs +21 -21
- package/crates/tish_runtime/src/native_promise.rs +1 -1
- package/crates/tish_runtime/src/promise.rs +2 -2
- package/crates/tish_runtime/src/promise_io.rs +1 -1
- package/crates/tish_runtime/src/timers.rs +1 -1
- package/crates/tish_runtime/src/ws.rs +1 -1
- package/crates/tish_runtime/tests/fetch_readable_stream.rs +2 -2
- package/crates/tish_vm/Cargo.toml +14 -12
- package/crates/tish_vm/src/lib.rs +2 -2
- package/crates/tish_vm/src/vm.rs +42 -42
- package/crates/tish_wasm/Cargo.toml +8 -6
- package/crates/tish_wasm/src/lib.rs +17 -17
- package/crates/tish_wasm_runtime/Cargo.toml +9 -7
- package/crates/tish_wasm_runtime/src/lib.rs +4 -4
- package/justfile +4 -4
- 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
|
@@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
|
|
|
8
8
|
use std::rc::Rc;
|
|
9
9
|
use std::sync::Arc;
|
|
10
10
|
|
|
11
|
-
use
|
|
11
|
+
use tishlang_ast::{BinOp, CompoundOp, ExportDeclaration, Expr, ImportSpecifier, Literal, LogicalAssignOp, MemberProp, Span, Statement, UnaryOp};
|
|
12
12
|
|
|
13
13
|
use crate::value::Value;
|
|
14
14
|
#[cfg(any(feature = "fs", feature = "process"))]
|
|
@@ -179,7 +179,7 @@ impl Evaluator {
|
|
|
179
179
|
*self.current_dir.borrow_mut() = dir.map(PathBuf::from);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
pub fn eval_program(&mut self, program: &
|
|
182
|
+
pub fn eval_program(&mut self, program: &tishlang_ast::Program) -> Result<Value, String> {
|
|
183
183
|
let mut last = Value::Null;
|
|
184
184
|
for stmt in &program.statements {
|
|
185
185
|
last = self.eval_statement(stmt).map_err(|e| e.to_string())?;
|
|
@@ -508,7 +508,7 @@ impl Evaluator {
|
|
|
508
508
|
let source = std::fs::read_to_string(&path).map_err(|e| {
|
|
509
509
|
EvalError::Error(format!("Cannot read {}: {}", path.display(), e))
|
|
510
510
|
})?;
|
|
511
|
-
let program =
|
|
511
|
+
let program = tishlang_parser::parse(&source).map_err(|e| {
|
|
512
512
|
EvalError::Error(format!("Parse error in {}: {}", path.display(), e))
|
|
513
513
|
})?;
|
|
514
514
|
let module_scope = Scope::child(Rc::clone(&self.scope));
|
|
@@ -588,7 +588,7 @@ impl Evaluator {
|
|
|
588
588
|
#[cfg(not(feature = "fs"))]
|
|
589
589
|
{
|
|
590
590
|
return Err(EvalError::Error(
|
|
591
|
-
"tish:fs requires the fs feature. Rebuild with: cargo build -p
|
|
591
|
+
"tish:fs requires the fs feature. Rebuild with: cargo build -p tishlang --features fs".into(),
|
|
592
592
|
));
|
|
593
593
|
}
|
|
594
594
|
}
|
|
@@ -609,7 +609,7 @@ impl Evaluator {
|
|
|
609
609
|
#[cfg(not(feature = "http"))]
|
|
610
610
|
{
|
|
611
611
|
return Err(EvalError::Error(
|
|
612
|
-
"tish:http requires the http feature. Rebuild with: cargo build -p
|
|
612
|
+
"tish:http requires the http feature. Rebuild with: cargo build -p tishlang --features http".into(),
|
|
613
613
|
));
|
|
614
614
|
}
|
|
615
615
|
}
|
|
@@ -626,7 +626,7 @@ impl Evaluator {
|
|
|
626
626
|
#[cfg(not(feature = "ws"))]
|
|
627
627
|
{
|
|
628
628
|
return Err(EvalError::Error(
|
|
629
|
-
"tish:ws requires the ws feature. Rebuild with: cargo build -p
|
|
629
|
+
"tish:ws requires the ws feature. Rebuild with: cargo build -p tishlang --features ws".into(),
|
|
630
630
|
));
|
|
631
631
|
}
|
|
632
632
|
}
|
|
@@ -657,7 +657,7 @@ impl Evaluator {
|
|
|
657
657
|
#[cfg(not(feature = "process"))]
|
|
658
658
|
{
|
|
659
659
|
return Err(EvalError::Error(
|
|
660
|
-
"tish:process requires the process feature. Rebuild with: cargo build -p
|
|
660
|
+
"tish:process requires the process feature. Rebuild with: cargo build -p tishlang --features process".into(),
|
|
661
661
|
));
|
|
662
662
|
}
|
|
663
663
|
}
|
|
@@ -1520,10 +1520,10 @@ impl Evaluator {
|
|
|
1520
1520
|
let mut vals = Vec::with_capacity(elements.len());
|
|
1521
1521
|
for elem in elements {
|
|
1522
1522
|
match elem {
|
|
1523
|
-
|
|
1523
|
+
tishlang_ast::ArrayElement::Expr(e) => {
|
|
1524
1524
|
vals.push(self.eval_expr(e)?);
|
|
1525
1525
|
}
|
|
1526
|
-
|
|
1526
|
+
tishlang_ast::ArrayElement::Spread(e) => {
|
|
1527
1527
|
let spread_val = self.eval_expr(e)?;
|
|
1528
1528
|
if let Value::Array(arr) = spread_val {
|
|
1529
1529
|
vals.extend(arr.borrow().iter().cloned());
|
|
@@ -1537,10 +1537,10 @@ impl Evaluator {
|
|
|
1537
1537
|
let mut map = HashMap::new();
|
|
1538
1538
|
for prop in props {
|
|
1539
1539
|
match prop {
|
|
1540
|
-
|
|
1540
|
+
tishlang_ast::ObjectProp::KeyValue(k, v) => {
|
|
1541
1541
|
map.insert(Arc::clone(k), self.eval_expr(v)?);
|
|
1542
1542
|
}
|
|
1543
|
-
|
|
1543
|
+
tishlang_ast::ObjectProp::Spread(e) => {
|
|
1544
1544
|
let spread_val = self.eval_expr(e)?;
|
|
1545
1545
|
if let Value::Object(obj) = spread_val {
|
|
1546
1546
|
for (k, v) in obj.borrow().iter() {
|
|
@@ -1754,10 +1754,10 @@ impl Evaluator {
|
|
|
1754
1754
|
}
|
|
1755
1755
|
}
|
|
1756
1756
|
Expr::ArrowFunction { params, body, .. } => {
|
|
1757
|
-
use
|
|
1757
|
+
use tishlang_ast::ArrowBody;
|
|
1758
1758
|
// Convert arrow function to regular function using Arc for cheap cloning
|
|
1759
1759
|
let param_names: Arc<[Arc<str>]> = params.iter().map(|p| Arc::clone(&p.name)).collect();
|
|
1760
|
-
let defaults: Arc<[Option<
|
|
1760
|
+
let defaults: Arc<[Option<tishlang_ast::Expr>]> = params.iter().map(|p| p.default.clone()).collect();
|
|
1761
1761
|
let body_stmt = match body {
|
|
1762
1762
|
ArrowBody::Expr(expr) => {
|
|
1763
1763
|
// Expression body: wrap in implicit return
|
|
@@ -2144,7 +2144,7 @@ impl Evaluator {
|
|
|
2144
2144
|
Value::Serve => self.run_http_server(args),
|
|
2145
2145
|
#[cfg(any(feature = "http", feature = "ws"))]
|
|
2146
2146
|
Value::CoreFn(f) => {
|
|
2147
|
-
let ca: Result<Vec<
|
|
2147
|
+
let ca: Result<Vec<tishlang_core::Value>, String> =
|
|
2148
2148
|
args.iter().map(crate::value_convert::eval_to_core).collect();
|
|
2149
2149
|
let ca = ca.map_err(EvalError::Error)?;
|
|
2150
2150
|
Ok(crate::value_convert::core_to_eval(f(&ca)))
|
|
@@ -2161,7 +2161,7 @@ impl Evaluator {
|
|
|
2161
2161
|
let method = opaque.get_method(method_name.as_ref()).ok_or_else(|| {
|
|
2162
2162
|
EvalError::Error(format!("Method {} not found on {}", method_name, opaque.type_name()))
|
|
2163
2163
|
})?;
|
|
2164
|
-
let core_args: Result<Vec<
|
|
2164
|
+
let core_args: Result<Vec<tishlang_core::Value>, String> =
|
|
2165
2165
|
args.iter().map(crate::value_convert::eval_to_core).collect();
|
|
2166
2166
|
let core_args = core_args.map_err(EvalError::Error)?;
|
|
2167
2167
|
let result = method(&core_args);
|
|
@@ -2473,14 +2473,14 @@ impl Evaluator {
|
|
|
2473
2473
|
Ok(Value::Null)
|
|
2474
2474
|
}
|
|
2475
2475
|
|
|
2476
|
-
fn eval_call_args(&self, args: &[
|
|
2476
|
+
fn eval_call_args(&self, args: &[tishlang_ast::CallArg]) -> Result<Vec<Value>, EvalError> {
|
|
2477
2477
|
let mut result = Vec::with_capacity(args.len());
|
|
2478
2478
|
for arg in args {
|
|
2479
2479
|
match arg {
|
|
2480
|
-
|
|
2480
|
+
tishlang_ast::CallArg::Expr(e) => {
|
|
2481
2481
|
result.push(self.eval_expr(e)?);
|
|
2482
2482
|
}
|
|
2483
|
-
|
|
2483
|
+
tishlang_ast::CallArg::Spread(e) => {
|
|
2484
2484
|
let spread_val = self.eval_expr(e)?;
|
|
2485
2485
|
if let Value::Array(arr) = spread_val {
|
|
2486
2486
|
result.extend(arr.borrow().iter().cloned());
|
|
@@ -2491,9 +2491,9 @@ impl Evaluator {
|
|
|
2491
2491
|
Ok(result)
|
|
2492
2492
|
}
|
|
2493
2493
|
|
|
2494
|
-
fn bind_destruct_pattern(&mut self, pattern: &
|
|
2494
|
+
fn bind_destruct_pattern(&mut self, pattern: &tishlang_ast::DestructPattern, value: &Value, mutable: bool) -> Result<(), EvalError> {
|
|
2495
2495
|
match pattern {
|
|
2496
|
-
|
|
2496
|
+
tishlang_ast::DestructPattern::Array(elements) => {
|
|
2497
2497
|
let arr = match value {
|
|
2498
2498
|
Value::Array(a) => a.borrow().clone(),
|
|
2499
2499
|
_ => return Err(EvalError::Error("Cannot destructure non-array value".to_string())),
|
|
@@ -2502,15 +2502,15 @@ impl Evaluator {
|
|
|
2502
2502
|
for (i, elem) in elements.iter().enumerate() {
|
|
2503
2503
|
if let Some(el) = elem {
|
|
2504
2504
|
match el {
|
|
2505
|
-
|
|
2505
|
+
tishlang_ast::DestructElement::Ident(name) => {
|
|
2506
2506
|
let val = arr.get(i).cloned().unwrap_or(Value::Null);
|
|
2507
2507
|
self.scope.borrow_mut().set(Arc::clone(name), val, mutable);
|
|
2508
2508
|
}
|
|
2509
|
-
|
|
2509
|
+
tishlang_ast::DestructElement::Pattern(nested) => {
|
|
2510
2510
|
let val = arr.get(i).cloned().unwrap_or(Value::Null);
|
|
2511
2511
|
self.bind_destruct_pattern(nested, &val, mutable)?;
|
|
2512
2512
|
}
|
|
2513
|
-
|
|
2513
|
+
tishlang_ast::DestructElement::Rest(name) => {
|
|
2514
2514
|
let rest: Vec<Value> = arr.iter().skip(i).cloned().collect();
|
|
2515
2515
|
self.scope.borrow_mut().set(Arc::clone(name), Value::Array(Rc::new(RefCell::new(rest))), mutable);
|
|
2516
2516
|
break;
|
|
@@ -2519,7 +2519,7 @@ impl Evaluator {
|
|
|
2519
2519
|
}
|
|
2520
2520
|
}
|
|
2521
2521
|
}
|
|
2522
|
-
|
|
2522
|
+
tishlang_ast::DestructPattern::Object(props) => {
|
|
2523
2523
|
let obj = match value {
|
|
2524
2524
|
Value::Object(o) => o.borrow().clone(),
|
|
2525
2525
|
_ => return Err(EvalError::Error("Cannot destructure non-object value".to_string())),
|
|
@@ -2528,13 +2528,13 @@ impl Evaluator {
|
|
|
2528
2528
|
for prop in props {
|
|
2529
2529
|
let val = obj.get(&prop.key).cloned().unwrap_or(Value::Null);
|
|
2530
2530
|
match &prop.value {
|
|
2531
|
-
|
|
2531
|
+
tishlang_ast::DestructElement::Ident(name) => {
|
|
2532
2532
|
self.scope.borrow_mut().set(Arc::clone(name), val, mutable);
|
|
2533
2533
|
}
|
|
2534
|
-
|
|
2534
|
+
tishlang_ast::DestructElement::Pattern(nested) => {
|
|
2535
2535
|
self.bind_destruct_pattern(nested, &val, mutable)?;
|
|
2536
2536
|
}
|
|
2537
|
-
|
|
2537
|
+
tishlang_ast::DestructElement::Rest(_) => {
|
|
2538
2538
|
return Err(EvalError::Error("Rest not supported in object destructuring".to_string()));
|
|
2539
2539
|
}
|
|
2540
2540
|
}
|
|
@@ -3098,7 +3098,7 @@ impl Evaluator {
|
|
|
3098
3098
|
for a in args {
|
|
3099
3099
|
cv.push(crate::value_convert::eval_to_core(a)?);
|
|
3100
3100
|
}
|
|
3101
|
-
Ok(crate::value_convert::core_to_eval(
|
|
3101
|
+
Ok(crate::value_convert::core_to_eval(tishlang_runtime::web_socket_client(&cv)))
|
|
3102
3102
|
}
|
|
3103
3103
|
|
|
3104
3104
|
#[cfg(feature = "ws")]
|
|
@@ -3107,7 +3107,7 @@ impl Evaluator {
|
|
|
3107
3107
|
for a in args {
|
|
3108
3108
|
cv.push(crate::value_convert::eval_to_core(a)?);
|
|
3109
3109
|
}
|
|
3110
|
-
Ok(crate::value_convert::core_to_eval(
|
|
3110
|
+
Ok(crate::value_convert::core_to_eval(tishlang_runtime::web_socket_server_construct(&cv)))
|
|
3111
3111
|
}
|
|
3112
3112
|
|
|
3113
3113
|
#[cfg(feature = "ws")]
|
|
@@ -3115,7 +3115,7 @@ impl Evaluator {
|
|
|
3115
3115
|
let conn = args.first().ok_or("wsSend(conn, data) requires conn")?;
|
|
3116
3116
|
let conn_core = crate::value_convert::eval_to_core(conn)?;
|
|
3117
3117
|
let data = args.get(1).map(|v| v.to_string()).unwrap_or_default();
|
|
3118
|
-
Ok(Value::Bool(
|
|
3118
|
+
Ok(Value::Bool(tishlang_runtime::ws_send_native(&conn_core, &data)))
|
|
3119
3119
|
}
|
|
3120
3120
|
|
|
3121
3121
|
#[cfg(feature = "ws")]
|
|
@@ -3124,7 +3124,7 @@ impl Evaluator {
|
|
|
3124
3124
|
for a in args {
|
|
3125
3125
|
cv.push(crate::value_convert::eval_to_core(a)?);
|
|
3126
3126
|
}
|
|
3127
|
-
Ok(crate::value_convert::core_to_eval(
|
|
3127
|
+
Ok(crate::value_convert::core_to_eval(tishlang_runtime::ws_broadcast_native(&cv)))
|
|
3128
3128
|
}
|
|
3129
3129
|
|
|
3130
3130
|
#[cfg(feature = "http")]
|
|
@@ -3133,8 +3133,8 @@ impl Evaluator {
|
|
|
3133
3133
|
for a in args {
|
|
3134
3134
|
cv.push(crate::value_convert::eval_to_core(a)?);
|
|
3135
3135
|
}
|
|
3136
|
-
match
|
|
3137
|
-
|
|
3136
|
+
match tishlang_runtime::fetch_promise(cv) {
|
|
3137
|
+
tishlang_core::Value::Promise(p) => Ok(Value::CorePromise(p)),
|
|
3138
3138
|
_ => Err("internal: fetch did not return Promise".into()),
|
|
3139
3139
|
}
|
|
3140
3140
|
}
|
|
@@ -3145,8 +3145,8 @@ impl Evaluator {
|
|
|
3145
3145
|
for a in args {
|
|
3146
3146
|
cv.push(crate::value_convert::eval_to_core(a)?);
|
|
3147
3147
|
}
|
|
3148
|
-
match
|
|
3149
|
-
|
|
3148
|
+
match tishlang_runtime::fetch_all_promise(cv) {
|
|
3149
|
+
tishlang_core::Value::Promise(p) => Ok(Value::CorePromise(p)),
|
|
3150
3150
|
_ => Err("internal: fetchAll did not return Promise".into()),
|
|
3151
3151
|
}
|
|
3152
3152
|
}
|
|
@@ -26,7 +26,7 @@ pub trait TishNativeModule: Send + Sync {
|
|
|
26
26
|
pub use regex::TishRegExp;
|
|
27
27
|
|
|
28
28
|
pub fn run(source: &str) -> Result<Value, String> {
|
|
29
|
-
let program =
|
|
29
|
+
let program = tishlang_parser::parse(source)?;
|
|
30
30
|
let mut eval = Evaluator::new();
|
|
31
31
|
let result = eval.eval_program(&program)?;
|
|
32
32
|
#[cfg(feature = "http")]
|
|
@@ -38,7 +38,7 @@ pub fn run(source: &str) -> Result<Value, String> {
|
|
|
38
38
|
/// Format an interpreter value for console output (Node/Bun-style colors when `colors` is true).
|
|
39
39
|
pub fn format_value_for_console(value: &Value, colors: bool) -> String {
|
|
40
40
|
match value_convert::eval_to_core(value) {
|
|
41
|
-
Ok(core_val) =>
|
|
41
|
+
Ok(core_val) => tishlang_core::format_value_styled(&core_val, colors),
|
|
42
42
|
Err(_) => value.to_string(),
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -49,7 +49,7 @@ pub fn run_file(path: &std::path::Path, project_root: Option<&std::path::Path>)
|
|
|
49
49
|
.canonicalize()
|
|
50
50
|
.map_err(|e| format!("Cannot canonicalize {}: {}", path.display(), e))?;
|
|
51
51
|
let source = std::fs::read_to_string(&path).map_err(|e| format!("Cannot read {}: {}", path.display(), e))?;
|
|
52
|
-
let program =
|
|
52
|
+
let program = tishlang_parser::parse(&source)?;
|
|
53
53
|
let mut eval = Evaluator::new();
|
|
54
54
|
eval.set_current_dir(project_root.or(path.parent()));
|
|
55
55
|
let result = eval.eval_program(&program)?;
|
|
@@ -96,12 +96,12 @@ pub fn boolean_native(args: &[Value]) -> Result<Value, String> {
|
|
|
96
96
|
|
|
97
97
|
pub fn decode_uri(args: &[Value]) -> Result<Value, String> {
|
|
98
98
|
let s = args.first().map(|v| v.to_string()).unwrap_or_default();
|
|
99
|
-
Ok(Value::String(
|
|
99
|
+
Ok(Value::String(tishlang_core::percent_decode(&s).unwrap_or(s).into()))
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
pub fn encode_uri(args: &[Value]) -> Result<Value, String> {
|
|
103
103
|
let s = args.first().map(|v| v.to_string()).unwrap_or_default();
|
|
104
|
-
Ok(Value::String(
|
|
104
|
+
Ok(Value::String(tishlang_core::percent_encode(&s).into()))
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
pub fn math_abs(args: &[Value]) -> Result<Value, String> {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
//! JavaScript-compatible regular expression support for Tish.
|
|
2
2
|
//!
|
|
3
|
-
//! Re-exports core types from
|
|
3
|
+
//! Re-exports core types from tishlang_core and provides interpreter-specific functionality.
|
|
4
4
|
|
|
5
5
|
use std::cell::RefCell;
|
|
6
6
|
use std::collections::HashMap;
|
|
7
7
|
use std::rc::Rc;
|
|
8
8
|
use std::sync::Arc;
|
|
9
9
|
|
|
10
|
-
pub use
|
|
10
|
+
pub use tishlang_core::{RegExpFlags, TishRegExp};
|
|
11
11
|
|
|
12
12
|
use crate::value::Value;
|
|
13
13
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//!
|
|
3
3
|
//! This module defines the interpreter's `Value` type, which includes variants
|
|
4
4
|
//! like `Function`, `Native`, and `Serve` that hold AST or interpreter-specific
|
|
5
|
-
//! data. The compiled runtime uses `
|
|
5
|
+
//! data. The compiled runtime uses `tishlang_core::Value` instead, which has a
|
|
6
6
|
//! different shape (no AST-carrying variants). The split is intentional.
|
|
7
7
|
|
|
8
8
|
use std::cell::RefCell;
|
|
@@ -10,12 +10,12 @@ use std::collections::HashMap;
|
|
|
10
10
|
use std::rc::Rc;
|
|
11
11
|
use std::sync::Arc;
|
|
12
12
|
|
|
13
|
-
use
|
|
13
|
+
use tishlang_ast::{Expr, Statement};
|
|
14
14
|
#[cfg(any(feature = "http", feature = "ws"))]
|
|
15
|
-
use
|
|
15
|
+
use tishlang_core::NativeFn as CoreNativeFn;
|
|
16
16
|
#[cfg(feature = "http")]
|
|
17
|
-
use
|
|
18
|
-
use
|
|
17
|
+
use tishlang_core::TishPromise;
|
|
18
|
+
use tishlang_core::TishOpaque;
|
|
19
19
|
|
|
20
20
|
#[cfg(feature = "http")]
|
|
21
21
|
pub use crate::promise::PromiseResolver;
|
|
@@ -62,10 +62,10 @@ pub enum Value {
|
|
|
62
62
|
/// Timer builtins: setTimeout, setInterval. Need evaluator for callback.
|
|
63
63
|
#[cfg(feature = "http")]
|
|
64
64
|
TimerBuiltin(std::sync::Arc<str>),
|
|
65
|
-
/// Native `
|
|
65
|
+
/// Native `tishlang_core` Promise (fetch / reader.read / response.text).
|
|
66
66
|
#[cfg(feature = "http")]
|
|
67
67
|
CorePromise(Arc<dyn TishPromise>),
|
|
68
|
-
/// `
|
|
68
|
+
/// `tishlang_core::Value::Function` (e.g. response.text/json, ws send/receive) callable from eval.
|
|
69
69
|
#[cfg(any(feature = "http", feature = "ws"))]
|
|
70
70
|
CoreFn(CoreNativeFn),
|
|
71
71
|
/// Opaque handle to a native Rust type (e.g. Polars DataFrame).
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
//! Conversion between
|
|
1
|
+
//! Conversion between tishlang_eval::Value and tishlang_core::Value for opaque method calls.
|
|
2
2
|
|
|
3
3
|
use std::cell::RefCell;
|
|
4
4
|
use std::collections::HashMap;
|
|
5
5
|
use std::rc::Rc;
|
|
6
6
|
use std::sync::Arc;
|
|
7
7
|
|
|
8
|
-
use
|
|
8
|
+
use tishlang_core::Value as CoreValue;
|
|
9
9
|
|
|
10
10
|
use crate::value::Value;
|
|
11
11
|
|
|
@@ -68,7 +68,7 @@ pub fn core_to_eval(v: CoreValue) -> Value {
|
|
|
68
68
|
CoreValue::Function(f) => Value::CoreFn(Rc::clone(&f)),
|
|
69
69
|
#[cfg(not(any(feature = "http", feature = "ws")))]
|
|
70
70
|
CoreValue::Function(_) => Value::Null,
|
|
71
|
-
//
|
|
71
|
+
// tishlang_core gets regex from http or regex features; handle RegExp when it exists
|
|
72
72
|
#[cfg(any(feature = "http", feature = "regex"))]
|
|
73
73
|
CoreValue::RegExp(re) => {
|
|
74
74
|
#[cfg(feature = "regex")]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
2
|
+
name = "tishlang_fmt"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Opinionated formatter for Tish source (parse → pretty-print)"
|
|
@@ -12,5 +12,5 @@ path = "src/bin/tish-fmt.rs"
|
|
|
12
12
|
|
|
13
13
|
[dependencies]
|
|
14
14
|
clap = { version = "4.6.0", features = ["derive"] }
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
tishlang_ast = { path = "../tish_ast" }
|
|
16
|
+
tishlang_parser = { path = "../tish_parser" }
|
|
@@ -24,7 +24,7 @@ fn main() {
|
|
|
24
24
|
|
|
25
25
|
fn run(path: &str, check: bool) -> Result<(), String> {
|
|
26
26
|
let source = fs::read_to_string(path).map_err(|e| format!("Cannot read {}: {}", path, e))?;
|
|
27
|
-
let formatted =
|
|
27
|
+
let formatted = tishlang_fmt::format_source(&source)?;
|
|
28
28
|
if check {
|
|
29
29
|
if formatted != source {
|
|
30
30
|
return Err(format!(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//! Pretty-print Tish AST to source. Style: 2-space indent, braces for blocks, trailing newline.
|
|
2
2
|
|
|
3
|
-
use
|
|
3
|
+
use tishlang_ast::{
|
|
4
4
|
ArrayElement, ArrowBody, BinOp, CallArg, CompoundOp, DestructElement, DestructPattern,
|
|
5
5
|
ExportDeclaration, Expr, ImportSpecifier, JsxAttrValue, JsxChild, JsxProp,
|
|
6
6
|
Literal, LogicalAssignOp, MemberProp, ObjectProp, Program, Statement, TypeAnnotation,
|
|
@@ -9,7 +9,7 @@ use tish_ast::{
|
|
|
9
9
|
|
|
10
10
|
/// Format Tish source. On parse error, returns the parser message.
|
|
11
11
|
pub fn format_source(source: &str) -> Result<String, String> {
|
|
12
|
-
let program =
|
|
12
|
+
let program = tishlang_parser::parse(source)?;
|
|
13
13
|
Ok(format_program(&program))
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -879,6 +879,6 @@ mod tests {
|
|
|
879
879
|
fn round_trip_simple() {
|
|
880
880
|
let src = "fn add(a, b) {\n return a + b\n}\n";
|
|
881
881
|
let out = format_source(src).unwrap();
|
|
882
|
-
let _ =
|
|
882
|
+
let _ = tishlang_parser::parse(&out).unwrap();
|
|
883
883
|
}
|
|
884
884
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
2
|
+
name = "tishlang_jsx_web"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "JSX / DOM runtime snippets for Tish JS target only (not used by native)"
|
|
6
6
|
|
|
7
|
+
license-file = { workspace = true }
|
|
8
|
+
repository = { workspace = true }
|
|
7
9
|
[dependencies]
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
2
|
+
name = "tishlang_lexer"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Tish lexer with indent normalization and tab/space handling"
|
|
6
6
|
|
|
7
|
+
license-file = { workspace = true }
|
|
8
|
+
repository = { workspace = true }
|
|
7
9
|
[dependencies]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
2
|
+
name = "tishlang_lint"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "AST-based linter for Tish"
|
|
@@ -13,5 +13,5 @@ path = "src/bin/tish-lint.rs"
|
|
|
13
13
|
[dependencies]
|
|
14
14
|
clap = { version = "4.6.0", features = ["derive"] }
|
|
15
15
|
walkdir = "2"
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
tishlang_ast = { path = "../tish_ast" }
|
|
17
|
+
tishlang_parser = { path = "../tish_parser" }
|
|
@@ -43,15 +43,15 @@ fn run(paths: &[String]) -> Result<(), String> {
|
|
|
43
43
|
let mut errors = 0;
|
|
44
44
|
for f in files {
|
|
45
45
|
let src = fs::read_to_string(&f).map_err(|e| format!("{}: {}", f.display(), e))?;
|
|
46
|
-
match
|
|
46
|
+
match tishlang_lint::lint_source(&src) {
|
|
47
47
|
Ok(diags) => {
|
|
48
48
|
for d in diags {
|
|
49
49
|
let sev = match d.severity {
|
|
50
|
-
|
|
50
|
+
tishlang_lint::Severity::Error => {
|
|
51
51
|
errors += 1;
|
|
52
52
|
"error"
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
tishlang_lint::Severity::Warning => "warning",
|
|
55
55
|
};
|
|
56
56
|
println!(
|
|
57
57
|
"{}:{}:{}: {} [{}] {}",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
use std::collections::HashSet;
|
|
4
4
|
|
|
5
|
-
use
|
|
5
|
+
use tishlang_ast::{Expr, ObjectProp, Program, Statement};
|
|
6
6
|
|
|
7
7
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
8
8
|
pub enum Severity {
|
|
@@ -32,7 +32,7 @@ pub fn lint_program(program: &Program) -> Vec<LintDiagnostic> {
|
|
|
32
32
|
|
|
33
33
|
/// Lint source: parse then lint. Parse errors are not reported here.
|
|
34
34
|
pub fn lint_source(source: &str) -> Result<Vec<LintDiagnostic>, String> {
|
|
35
|
-
let program =
|
|
35
|
+
let program = tishlang_parser::parse(source)?;
|
|
36
36
|
Ok(lint_program(&program))
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -104,7 +104,7 @@ fn lint_stmt(s: &Statement, out: &mut Vec<LintDiagnostic>) {
|
|
|
104
104
|
}
|
|
105
105
|
Statement::DoWhile { body, .. } => lint_stmt(body, out),
|
|
106
106
|
Statement::Export { declaration, .. } => {
|
|
107
|
-
if let
|
|
107
|
+
if let tishlang_ast::ExportDeclaration::Named(inner) = declaration.as_ref() {
|
|
108
108
|
lint_stmt(inner, out);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -137,7 +137,7 @@ fn stmt_span(s: &Statement) -> (u32, u32) {
|
|
|
137
137
|
let sp = match s {
|
|
138
138
|
Statement::Block { span, .. } => *span,
|
|
139
139
|
Statement::Try { span, .. } => *span,
|
|
140
|
-
_ =>
|
|
140
|
+
_ => tishlang_ast::Span {
|
|
141
141
|
start: (1, 1),
|
|
142
142
|
end: (1, 1),
|
|
143
143
|
},
|
|
@@ -175,8 +175,8 @@ fn lint_expr(e: &Expr, out: &mut Vec<LintDiagnostic>) {
|
|
|
175
175
|
lint_expr(callee, out);
|
|
176
176
|
for a in args {
|
|
177
177
|
match a {
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
tishlang_ast::CallArg::Expr(x) => lint_expr(x, out),
|
|
179
|
+
tishlang_ast::CallArg::Spread(x) => lint_expr(x, out),
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
}
|
|
@@ -204,8 +204,8 @@ fn lint_expr(e: &Expr, out: &mut Vec<LintDiagnostic>) {
|
|
|
204
204
|
Expr::Array { elements, .. } => {
|
|
205
205
|
for el in elements {
|
|
206
206
|
match el {
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
tishlang_ast::ArrayElement::Expr(x) => lint_expr(x, out),
|
|
208
|
+
tishlang_ast::ArrayElement::Spread(x) => lint_expr(x, out),
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -227,8 +227,8 @@ fn lint_expr(e: &Expr, out: &mut Vec<LintDiagnostic>) {
|
|
|
227
227
|
lint_expr(value, out);
|
|
228
228
|
}
|
|
229
229
|
Expr::ArrowFunction { body, .. } => match body {
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
tishlang_ast::ArrowBody::Expr(x) => lint_expr(x, out),
|
|
231
|
+
tishlang_ast::ArrowBody::Block(b) => lint_stmt(b, out),
|
|
232
232
|
},
|
|
233
233
|
Expr::TemplateLiteral { exprs, .. } => {
|
|
234
234
|
for x in exprs {
|
|
@@ -240,23 +240,23 @@ fn lint_expr(e: &Expr, out: &mut Vec<LintDiagnostic>) {
|
|
|
240
240
|
Expr::JsxElement { props, children, .. } => {
|
|
241
241
|
for pr in props {
|
|
242
242
|
match pr {
|
|
243
|
-
|
|
244
|
-
if let
|
|
243
|
+
tishlang_ast::JsxProp::Attr { value, .. } => {
|
|
244
|
+
if let tishlang_ast::JsxAttrValue::Expr(x) = value {
|
|
245
245
|
lint_expr(x, out);
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
|
-
|
|
248
|
+
tishlang_ast::JsxProp::Spread(x) => lint_expr(x, out),
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
for ch in children {
|
|
252
|
-
if let
|
|
252
|
+
if let tishlang_ast::JsxChild::Expr(x) = ch {
|
|
253
253
|
lint_expr(x, out);
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
Expr::JsxFragment { children, .. } => {
|
|
258
258
|
for ch in children {
|
|
259
|
-
if let
|
|
259
|
+
if let tishlang_ast::JsxChild::Expr(x) = ch {
|
|
260
260
|
lint_expr(x, out);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
2
|
+
name = "tishlang_llvm"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "LLVM backend for Tish (bytecode → native via clang/LLVM)"
|
|
6
6
|
|
|
7
|
+
license-file = { workspace = true }
|
|
8
|
+
repository = { workspace = true }
|
|
7
9
|
[dependencies]
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
tishlang_bytecode = { path = "../tish_bytecode" }
|
|
11
|
+
tishlang_compile = { path = "../tish_compile" }
|
|
12
|
+
tishlang_cranelift = { path = "../tish_cranelift" }
|
|
13
|
+
tishlang_build_utils = { path = "../tish_build_utils" }
|