@tishlang/tish-format 1.0.12 → 2.0.1
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 +51 -0
- package/LICENSE +13 -0
- package/bin/tish-format +0 -0
- package/crates/js_to_tish/Cargo.toml +11 -0
- package/crates/js_to_tish/README.md +18 -0
- package/crates/js_to_tish/src/error.rs +55 -0
- package/crates/js_to_tish/src/lib.rs +11 -0
- package/crates/js_to_tish/src/span_util.rs +35 -0
- package/crates/js_to_tish/src/transform/expr.rs +611 -0
- package/crates/js_to_tish/src/transform/stmt.rs +503 -0
- package/crates/js_to_tish/src/transform.rs +60 -0
- package/crates/tish/Cargo.toml +62 -0
- package/crates/tish/build.rs +21 -0
- package/crates/tish/src/cargo_native_registry.rs +32 -0
- package/crates/tish/src/cli_help.rs +576 -0
- package/crates/tish/src/main.rs +853 -0
- package/crates/tish/src/repl_completion.rs +199 -0
- package/crates/tish/tests/cargo_example_compile.rs +67 -0
- package/crates/tish/tests/error_source_location.rs +36 -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/fixtures/runtime_error_location.tish +5 -0
- package/crates/tish/tests/fixtures/trycatch_runtime_errors.tish +15 -0
- package/crates/tish/tests/fixtures/tty_capability.tish +9 -0
- package/crates/tish/tests/integration_test.rs +1406 -0
- package/crates/tish/tests/run_optimize_stdout_parity.rs +50 -0
- package/crates/tish/tests/shortcircuit.rs +65 -0
- package/crates/tish/tests/trycatch_runtime_errors.rs +45 -0
- package/crates/tish/tests/tty_capability.rs +43 -0
- package/crates/tish_ast/Cargo.toml +9 -0
- package/crates/tish_ast/src/ast.rs +649 -0
- package/crates/tish_ast/src/lib.rs +5 -0
- package/crates/tish_build_utils/Cargo.toml +11 -0
- package/crates/tish_build_utils/src/lib.rs +577 -0
- package/crates/tish_builtins/Cargo.toml +22 -0
- package/crates/tish_builtins/src/array.rs +803 -0
- package/crates/tish_builtins/src/collections.rs +481 -0
- package/crates/tish_builtins/src/construct.rs +199 -0
- package/crates/tish_builtins/src/date.rs +538 -0
- package/crates/tish_builtins/src/globals.rs +293 -0
- package/crates/tish_builtins/src/helpers.rs +35 -0
- package/crates/tish_builtins/src/iterator.rs +129 -0
- package/crates/tish_builtins/src/lib.rs +21 -0
- package/crates/tish_builtins/src/math.rs +89 -0
- package/crates/tish_builtins/src/number.rs +96 -0
- package/crates/tish_builtins/src/object.rs +36 -0
- package/crates/tish_builtins/src/string.rs +646 -0
- package/crates/tish_builtins/src/symbol.rs +83 -0
- package/crates/tish_builtins/src/typedarrays.rs +298 -0
- package/crates/tish_bytecode/Cargo.toml +17 -0
- package/crates/tish_bytecode/src/chunk.rs +164 -0
- package/crates/tish_bytecode/src/compiler.rs +2604 -0
- package/crates/tish_bytecode/src/encoding.rs +102 -0
- package/crates/tish_bytecode/src/lib.rs +20 -0
- package/crates/tish_bytecode/src/opcode.rs +185 -0
- package/crates/tish_bytecode/src/peephole.rs +189 -0
- package/crates/tish_bytecode/src/serialize.rs +193 -0
- package/crates/tish_bytecode/tests/break_continue_bytecode.rs +44 -0
- package/crates/tish_bytecode/tests/constant_folding.rs +84 -0
- package/crates/tish_bytecode/tests/sort_optimization.rs +31 -0
- package/crates/tish_compile/Cargo.toml +27 -0
- package/crates/tish_compile/src/check.rs +774 -0
- package/crates/tish_compile/src/codegen.rs +7317 -0
- package/crates/tish_compile/src/infer.rs +1681 -0
- package/crates/tish_compile/src/lib.rs +206 -0
- package/crates/tish_compile/src/resolve.rs +1951 -0
- package/crates/tish_compile/src/types.rs +605 -0
- package/crates/tish_compile_js/Cargo.toml +18 -0
- package/crates/tish_compile_js/examples/jsx_vdom_smoke.tish +8 -0
- package/crates/tish_compile_js/src/codegen.rs +938 -0
- package/crates/tish_compile_js/src/error.rs +20 -0
- package/crates/tish_compile_js/src/lib.rs +26 -0
- package/crates/tish_compile_js/src/tests_jsx.rs +414 -0
- package/crates/tish_compiler_wasm/Cargo.toml +21 -0
- package/crates/tish_compiler_wasm/src/lib.rs +57 -0
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +473 -0
- package/crates/tish_core/Cargo.toml +32 -0
- package/crates/tish_core/src/console_style.rs +170 -0
- package/crates/tish_core/src/json.rs +430 -0
- package/crates/tish_core/src/lib.rs +20 -0
- package/crates/tish_core/src/macros.rs +36 -0
- package/crates/tish_core/src/shape.rs +85 -0
- package/crates/tish_core/src/uri.rs +118 -0
- package/crates/tish_core/src/value.rs +1350 -0
- package/crates/tish_core/src/vmref.rs +183 -0
- package/crates/tish_cranelift/Cargo.toml +19 -0
- package/crates/tish_cranelift/src/lib.rs +43 -0
- package/crates/tish_cranelift/src/link.rs +130 -0
- package/crates/tish_cranelift/src/lower.rs +85 -0
- package/crates/tish_cranelift_runtime/Cargo.toml +26 -0
- package/crates/tish_cranelift_runtime/src/lib.rs +45 -0
- package/crates/tish_eval/Cargo.toml +51 -0
- package/crates/tish_eval/src/eval.rs +4265 -0
- package/crates/tish_eval/src/http.rs +191 -0
- package/crates/tish_eval/src/lib.rs +99 -0
- package/crates/tish_eval/src/natives.rs +551 -0
- package/crates/tish_eval/src/promise.rs +179 -0
- package/crates/tish_eval/src/regex.rs +299 -0
- package/crates/tish_eval/src/timers.rs +120 -0
- package/crates/tish_eval/src/value.rs +336 -0
- package/crates/tish_eval/src/value_convert.rs +117 -0
- package/crates/tish_ffi/Cargo.toml +26 -0
- package/crates/tish_ffi/src/lib.rs +518 -0
- package/crates/tish_ffi/tests/fixtures/testmod/Cargo.toml +18 -0
- package/crates/tish_ffi/tests/fixtures/testmod/src/lib.rs +46 -0
- package/crates/tish_ffi/tests/loader.rs +65 -0
- package/crates/tish_fmt/Cargo.toml +16 -0
- package/crates/tish_fmt/src/bin/tish-fmt.rs +41 -0
- package/crates/tish_fmt/src/lib.rs +2157 -0
- package/crates/tish_jsx_web/Cargo.toml +9 -0
- package/crates/tish_jsx_web/README.md +5 -0
- package/crates/tish_jsx_web/src/lib.rs +2 -0
- package/crates/tish_lexer/Cargo.toml +9 -0
- package/crates/tish_lexer/src/lib.rs +1104 -0
- package/crates/tish_lexer/src/token.rs +170 -0
- package/crates/tish_lint/Cargo.toml +18 -0
- package/crates/tish_lint/src/bin/tish-lint.rs +195 -0
- package/crates/tish_lint/src/lib.rs +281 -0
- package/crates/tish_llvm/Cargo.toml +13 -0
- package/crates/tish_llvm/src/lib.rs +115 -0
- package/crates/tish_lsp/Cargo.toml +25 -0
- package/crates/tish_lsp/README.md +26 -0
- package/crates/tish_lsp/src/builtin_goto.rs +362 -0
- package/crates/tish_lsp/src/import_goto.rs +564 -0
- package/crates/tish_lsp/src/main.rs +1459 -0
- package/crates/tish_native/Cargo.toml +16 -0
- package/crates/tish_native/src/build.rs +481 -0
- package/crates/tish_native/src/config.rs +48 -0
- package/crates/tish_native/src/lib.rs +416 -0
- package/crates/tish_opt/Cargo.toml +13 -0
- package/crates/tish_opt/src/lib.rs +1046 -0
- package/crates/tish_parser/Cargo.toml +11 -0
- package/crates/tish_parser/src/lib.rs +386 -0
- package/crates/tish_parser/src/parser.rs +2726 -0
- package/crates/tish_pg/Cargo.toml +34 -0
- package/crates/tish_pg/README.md +38 -0
- package/crates/tish_pg/src/error.rs +52 -0
- package/crates/tish_pg/src/lib.rs +955 -0
- package/crates/tish_resolve/Cargo.toml +13 -0
- package/crates/tish_resolve/src/lib.rs +3601 -0
- package/crates/tish_resolve/src/pos.rs +141 -0
- package/crates/tish_runtime/Cargo.toml +100 -0
- package/crates/tish_runtime/src/http.rs +1347 -0
- package/crates/tish_runtime/src/http_fetch.rs +492 -0
- package/crates/tish_runtime/src/http_hyper.rs +441 -0
- package/crates/tish_runtime/src/http_prefork.rs +189 -0
- package/crates/tish_runtime/src/lib.rs +1447 -0
- package/crates/tish_runtime/src/native_promise.rs +15 -0
- package/crates/tish_runtime/src/promise.rs +558 -0
- package/crates/tish_runtime/src/promise_io.rs +38 -0
- package/crates/tish_runtime/src/timers.rs +172 -0
- package/crates/tish_runtime/src/tty.rs +226 -0
- package/crates/tish_runtime/src/ws.rs +778 -0
- package/crates/tish_runtime/tests/fetch_readable_stream.rs +102 -0
- package/crates/tish_ui/Cargo.toml +17 -0
- package/crates/tish_ui/src/jsx.rs +692 -0
- package/crates/tish_ui/src/lib.rs +20 -0
- package/crates/tish_ui/src/runtime/hooks.rs +573 -0
- package/crates/tish_ui/src/runtime/mod.rs +183 -0
- package/crates/tish_vm/Cargo.toml +60 -0
- package/crates/tish_vm/src/jit.rs +1050 -0
- package/crates/tish_vm/src/lib.rs +41 -0
- package/crates/tish_vm/src/vm.rs +3536 -0
- package/crates/tish_vm/tests/concurrent_shared_state.rs +140 -0
- package/crates/tish_vm/tests/fixtures/or_string_cmd.tish +2 -0
- package/crates/tish_vm/tests/lexical_scope_declare.rs +34 -0
- package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +150 -0
- package/crates/tish_wasm/Cargo.toml +15 -0
- package/crates/tish_wasm/src/lib.rs +428 -0
- package/crates/tish_wasm_runtime/Cargo.toml +37 -0
- package/crates/tish_wasm_runtime/src/gpu.rs +429 -0
- package/crates/tish_wasm_runtime/src/lib.rs +42 -0
- package/crates/tishlang_cargo_bindgen/Cargo.toml +26 -0
- package/crates/tishlang_cargo_bindgen/src/classify.rs +261 -0
- package/crates/tishlang_cargo_bindgen/src/discover.rs +125 -0
- package/crates/tishlang_cargo_bindgen/src/infer.rs +382 -0
- package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
- package/crates/tishlang_cargo_bindgen/src/main.rs +167 -0
- package/crates/tishlang_cargo_bindgen/src/metadata.rs +117 -0
- package/justfile +276 -0
- package/package.json +2 -2
- package/platform/darwin-arm64/tish-fmt +0 -0
- package/platform/darwin-x64/tish-fmt +0 -0
- package/platform/linux-arm64/tish-fmt +0 -0
- package/platform/linux-x64/tish-fmt +0 -0
- package/platform/win32-x64/tish-fmt.exe +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
//! HTTP server for the Tish interpreter. Client `fetch` uses `tishlang_runtime` from eval.
|
|
2
|
+
|
|
3
|
+
use crate::value::{PropMap, Value};
|
|
4
|
+
use std::fs::File;
|
|
5
|
+
use std::sync::Arc;
|
|
6
|
+
|
|
7
|
+
use tokio::runtime::Runtime;
|
|
8
|
+
|
|
9
|
+
thread_local! {
|
|
10
|
+
pub(crate) static RUNTIME: Runtime = tokio::runtime::Builder::new_multi_thread()
|
|
11
|
+
.worker_threads(4)
|
|
12
|
+
.enable_all()
|
|
13
|
+
.build()
|
|
14
|
+
.expect("Failed to create tokio runtime");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Create an HTTP server that listens on the given port.
|
|
18
|
+
pub fn create_server(port: u16) -> Result<tiny_http::Server, String> {
|
|
19
|
+
let addr = format!("0.0.0.0:{}", port);
|
|
20
|
+
tiny_http::Server::http(&addr).map_err(|e| format!("Failed to start server: {}", e))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Convert a tiny_http::Request into a Tish Value object.
|
|
24
|
+
pub fn request_to_value(request: &mut tiny_http::Request) -> Value {
|
|
25
|
+
let mut obj: PropMap = PropMap::with_capacity(6);
|
|
26
|
+
|
|
27
|
+
obj.insert(
|
|
28
|
+
Arc::from("method"),
|
|
29
|
+
Value::String(request.method().to_string().into()),
|
|
30
|
+
);
|
|
31
|
+
obj.insert(
|
|
32
|
+
Arc::from("url"),
|
|
33
|
+
Value::String(request.url().to_string().into()),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
let path = request.url().split('?').next().unwrap_or("/");
|
|
37
|
+
obj.insert(Arc::from("path"), Value::String(path.into()));
|
|
38
|
+
|
|
39
|
+
let query_string = request.url().split('?').nth(1).unwrap_or("");
|
|
40
|
+
obj.insert(Arc::from("query"), Value::String(query_string.into()));
|
|
41
|
+
|
|
42
|
+
let mut headers_obj: PropMap = PropMap::with_capacity(request.headers().len());
|
|
43
|
+
for header in request.headers() {
|
|
44
|
+
headers_obj.insert(
|
|
45
|
+
Arc::from(header.field.as_str().as_str()),
|
|
46
|
+
Value::String(header.value.as_str().into()),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
obj.insert(Arc::from("headers"), Value::object(headers_obj));
|
|
50
|
+
|
|
51
|
+
let mut body = String::new();
|
|
52
|
+
let _ = request.as_reader().read_to_string(&mut body);
|
|
53
|
+
obj.insert(Arc::from("body"), Value::String(body.into()));
|
|
54
|
+
|
|
55
|
+
Value::object(obj)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// Extract response data from a Tish Value object.
|
|
59
|
+
pub fn value_to_response(value: &Value) -> (u16, Vec<(String, String)>, String) {
|
|
60
|
+
let default_status = 200u16;
|
|
61
|
+
let default_body = String::new();
|
|
62
|
+
|
|
63
|
+
let (status, headers, body) = match value {
|
|
64
|
+
Value::Object(obj) => {
|
|
65
|
+
let obj_ref = obj.borrow();
|
|
66
|
+
|
|
67
|
+
let status = obj_ref
|
|
68
|
+
.strings
|
|
69
|
+
.get("status")
|
|
70
|
+
.and_then(|v| match v {
|
|
71
|
+
Value::Number(n) => Some(*n as u16),
|
|
72
|
+
_ => None,
|
|
73
|
+
})
|
|
74
|
+
.unwrap_or(default_status);
|
|
75
|
+
|
|
76
|
+
let body = obj_ref
|
|
77
|
+
.strings
|
|
78
|
+
.get("body")
|
|
79
|
+
.map(|v| v.to_string())
|
|
80
|
+
.unwrap_or_default();
|
|
81
|
+
|
|
82
|
+
let headers = obj_ref
|
|
83
|
+
.strings
|
|
84
|
+
.get("headers")
|
|
85
|
+
.and_then(|v| match v {
|
|
86
|
+
Value::Object(h) => Some(
|
|
87
|
+
h.borrow()
|
|
88
|
+
.strings
|
|
89
|
+
.iter()
|
|
90
|
+
.map(|(k, v)| (k.to_string(), v.to_string()))
|
|
91
|
+
.collect(),
|
|
92
|
+
),
|
|
93
|
+
_ => None,
|
|
94
|
+
})
|
|
95
|
+
.unwrap_or_default();
|
|
96
|
+
|
|
97
|
+
(status, headers, body)
|
|
98
|
+
}
|
|
99
|
+
Value::String(s) => (default_status, vec![], s.to_string()),
|
|
100
|
+
_ => (default_status, vec![], default_body),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
(status, headers, body)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// `(status, headers, file path)` extracted from a response object's `file` key.
|
|
107
|
+
type FileResponse = (u16, Vec<(String, String)>, String);
|
|
108
|
+
|
|
109
|
+
/// If the response value has a `file` key, stream that path (binary-safe). Matches `tishlang_runtime` HTTP behavior.
|
|
110
|
+
pub(crate) fn extract_file_from_response(
|
|
111
|
+
value: &Value,
|
|
112
|
+
) -> Option<FileResponse> {
|
|
113
|
+
let Value::Object(obj) = value else {
|
|
114
|
+
return None;
|
|
115
|
+
};
|
|
116
|
+
let obj_ref = obj.borrow();
|
|
117
|
+
let file_val = obj_ref.strings.get("file")?;
|
|
118
|
+
let Value::String(file_path) = file_val else {
|
|
119
|
+
return None;
|
|
120
|
+
};
|
|
121
|
+
let file_path = file_path.to_string();
|
|
122
|
+
let status = obj_ref
|
|
123
|
+
.strings
|
|
124
|
+
.get("status")
|
|
125
|
+
.and_then(|v| match v {
|
|
126
|
+
Value::Number(n) => Some(*n as u16),
|
|
127
|
+
_ => None,
|
|
128
|
+
})
|
|
129
|
+
.unwrap_or(200);
|
|
130
|
+
let headers = obj_ref
|
|
131
|
+
.strings
|
|
132
|
+
.get("headers")
|
|
133
|
+
.and_then(|v| match v {
|
|
134
|
+
Value::Object(h) => Some(
|
|
135
|
+
h.borrow()
|
|
136
|
+
.strings
|
|
137
|
+
.iter()
|
|
138
|
+
.map(|(k, v)| (k.to_string(), v.to_string()))
|
|
139
|
+
.collect(),
|
|
140
|
+
),
|
|
141
|
+
_ => None,
|
|
142
|
+
})
|
|
143
|
+
.unwrap_or_default();
|
|
144
|
+
Some((status, headers, file_path))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
pub(crate) fn send_file_response(
|
|
148
|
+
request: tiny_http::Request,
|
|
149
|
+
status: u16,
|
|
150
|
+
headers: Vec<(String, String)>,
|
|
151
|
+
file_path: String,
|
|
152
|
+
) {
|
|
153
|
+
let file = match File::open(&file_path) {
|
|
154
|
+
Ok(f) => f,
|
|
155
|
+
Err(e) => {
|
|
156
|
+
eprintln!("Failed to open file {}: {}", file_path, e);
|
|
157
|
+
let fallback =
|
|
158
|
+
tiny_http::Response::from_string(format!("File not found: {}", file_path))
|
|
159
|
+
.with_status_code(tiny_http::StatusCode(500));
|
|
160
|
+
let _ = request.respond(fallback);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
let status_code = tiny_http::StatusCode(status);
|
|
165
|
+
let mut response = tiny_http::Response::from_file(file).with_status_code(status_code);
|
|
166
|
+
for (key, value) in headers {
|
|
167
|
+
if let Ok(header) = tiny_http::Header::from_bytes(key.as_bytes(), value.as_bytes()) {
|
|
168
|
+
response = response.with_header(header);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
let _ = request.respond(response);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/// Send a response using tiny_http.
|
|
175
|
+
pub fn send_response(
|
|
176
|
+
request: tiny_http::Request,
|
|
177
|
+
status: u16,
|
|
178
|
+
headers: Vec<(String, String)>,
|
|
179
|
+
body: String,
|
|
180
|
+
) {
|
|
181
|
+
let status_code = tiny_http::StatusCode(status);
|
|
182
|
+
let mut response = tiny_http::Response::from_string(body).with_status_code(status_code);
|
|
183
|
+
|
|
184
|
+
for (key, value) in headers {
|
|
185
|
+
if let Ok(header) = tiny_http::Header::from_bytes(key.as_bytes(), value.as_bytes()) {
|
|
186
|
+
response = response.with_header(header);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let _ = request.respond(response);
|
|
191
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//! Tish tree-walk interpreter.
|
|
2
|
+
|
|
3
|
+
mod eval;
|
|
4
|
+
#[cfg(feature = "http")]
|
|
5
|
+
mod http;
|
|
6
|
+
mod natives;
|
|
7
|
+
#[cfg(feature = "http")]
|
|
8
|
+
mod promise;
|
|
9
|
+
#[cfg(feature = "regex")]
|
|
10
|
+
pub mod regex;
|
|
11
|
+
#[cfg(feature = "timers")]
|
|
12
|
+
mod timers;
|
|
13
|
+
mod value;
|
|
14
|
+
pub mod value_convert;
|
|
15
|
+
|
|
16
|
+
pub use eval::Evaluator;
|
|
17
|
+
pub use value::PropMap;
|
|
18
|
+
pub use value::Value;
|
|
19
|
+
|
|
20
|
+
/// Trait for pluggable native modules (e.g. Polars). Implement to register
|
|
21
|
+
/// globals with the interpreter. Return a map of (global_name, Value).
|
|
22
|
+
pub trait TishNativeModule: Send + Sync {
|
|
23
|
+
fn name(&self) -> &'static str;
|
|
24
|
+
fn register(&self) -> std::collections::HashMap<std::sync::Arc<str>, Value>;
|
|
25
|
+
|
|
26
|
+
/// Virtual `tish:*` modules for `import { x } from 'tish:…'` (e.g. `tish:polars`).
|
|
27
|
+
/// Return `(specifier, exports_object)` pairs. Default: none.
|
|
28
|
+
fn virtual_builtin_modules(&self) -> Vec<(&'static str, Value)> {
|
|
29
|
+
vec![]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
#[cfg(feature = "regex")]
|
|
33
|
+
pub use regex::TishRegExp;
|
|
34
|
+
|
|
35
|
+
pub fn run(source: &str) -> Result<Value, String> {
|
|
36
|
+
let program = tishlang_parser::parse(source)?;
|
|
37
|
+
let mut eval = Evaluator::new();
|
|
38
|
+
let result = eval.eval_program(&program)?;
|
|
39
|
+
#[cfg(feature = "timers")]
|
|
40
|
+
eval.run_timer_phase()?;
|
|
41
|
+
Ok(result)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// Run a Tish file with import/export support. Resolves relative imports from the file's directory.
|
|
45
|
+
/// Format an interpreter value for console output (Node/Bun-style colors when `colors` is true).
|
|
46
|
+
pub fn format_value_for_console(value: &Value, colors: bool) -> String {
|
|
47
|
+
match value_convert::eval_to_core(value) {
|
|
48
|
+
Ok(core_val) => tishlang_core::format_value_styled(&core_val, colors),
|
|
49
|
+
Err(_) => value.to_string(),
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Run a Tish file with import/export support. Resolves relative imports from the file's directory.
|
|
54
|
+
pub fn run_file(
|
|
55
|
+
path: &std::path::Path,
|
|
56
|
+
project_root: Option<&std::path::Path>,
|
|
57
|
+
) -> Result<Value, String> {
|
|
58
|
+
let path = path
|
|
59
|
+
.canonicalize()
|
|
60
|
+
.map_err(|e| format!("Cannot canonicalize {}: {}", path.display(), e))?;
|
|
61
|
+
let source = std::fs::read_to_string(&path)
|
|
62
|
+
.map_err(|e| format!("Cannot read {}: {}", path.display(), e))?;
|
|
63
|
+
let program = tishlang_parser::parse(&source)?;
|
|
64
|
+
let mut eval = Evaluator::new();
|
|
65
|
+
eval.set_current_dir(project_root.or(path.parent()));
|
|
66
|
+
let result = eval.eval_program(&program)?;
|
|
67
|
+
#[cfg(feature = "timers")]
|
|
68
|
+
eval.run_timer_phase()?;
|
|
69
|
+
Ok(result)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#[cfg(test)]
|
|
73
|
+
mod global_scope_tests {
|
|
74
|
+
use super::*;
|
|
75
|
+
|
|
76
|
+
#[test]
|
|
77
|
+
fn symbol_global_loads() {
|
|
78
|
+
let mut e = Evaluator::new();
|
|
79
|
+
let program = tishlang_parser::parse("Symbol").expect("parse");
|
|
80
|
+
let r = e.eval_program(&program);
|
|
81
|
+
assert!(
|
|
82
|
+
r.is_ok(),
|
|
83
|
+
"expected Symbol global, got {:?}",
|
|
84
|
+
r.as_ref().err()
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#[test]
|
|
89
|
+
fn symbol_call_under_typeof_loads() {
|
|
90
|
+
let mut e = Evaluator::new();
|
|
91
|
+
let program = tishlang_parser::parse("typeof Symbol(\"z\")").expect("parse");
|
|
92
|
+
let r = e.eval_program(&program);
|
|
93
|
+
assert!(
|
|
94
|
+
r.is_ok(),
|
|
95
|
+
"expected Symbol global for typeof Symbol(\"z\"), got {:?}",
|
|
96
|
+
r.as_ref().err()
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|