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