@tishlang/tish 1.6.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 +3 -1
- 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 +31 -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/src/codegen.rs +921 -299
- package/crates/tish_compile/src/infer.rs +69 -19
- package/crates/tish_compile/src/lib.rs +15 -5
- package/crates/tish_compile/src/resolve.rs +112 -69
- 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 +39 -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 +389 -142
- 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 +1 -6
- package/crates/tish_native/src/lib.rs +48 -19
- 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 +309 -112
- 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
|
@@ -80,9 +80,11 @@ 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(),
|
|
@@ -121,9 +123,15 @@ pub fn compile_to_native(
|
|
|
121
123
|
})
|
|
122
124
|
}
|
|
123
125
|
Backend::Llvm => {
|
|
124
|
-
let modules =
|
|
125
|
-
.map_err(|e|
|
|
126
|
-
|
|
126
|
+
let modules =
|
|
127
|
+
tishlang_compile::resolve_project(entry_path, project_root).map_err(|e| {
|
|
128
|
+
NativeError {
|
|
129
|
+
message: e.to_string(),
|
|
130
|
+
}
|
|
131
|
+
})?;
|
|
132
|
+
tishlang_compile::detect_cycles(&modules).map_err(|e| NativeError {
|
|
133
|
+
message: e.to_string(),
|
|
134
|
+
})?;
|
|
127
135
|
let program = {
|
|
128
136
|
let prog = tishlang_compile::merge_modules(modules).map_err(|e| NativeError {
|
|
129
137
|
message: e.to_string(),
|
|
@@ -180,12 +188,17 @@ pub fn compile_program_to_native(
|
|
|
180
188
|
|
|
181
189
|
match backend {
|
|
182
190
|
Backend::Rust => {
|
|
183
|
-
let program = if optimize {
|
|
191
|
+
let program = if optimize {
|
|
192
|
+
tishlang_opt::optimize(program)
|
|
193
|
+
} else {
|
|
194
|
+
program.clone()
|
|
195
|
+
};
|
|
184
196
|
let root = project_root.unwrap_or_else(|| Path::new("."));
|
|
185
197
|
let native_modules = tishlang_compile::resolve_native_modules(&program, root)
|
|
186
198
|
.map_err(|e| NativeError { message: e })?;
|
|
187
|
-
let native_build =
|
|
188
|
-
|
|
199
|
+
let native_build =
|
|
200
|
+
tishlang_compile::compute_native_build_artifacts(&program, root, &native_modules)
|
|
201
|
+
.map_err(|e| NativeError { message: e })?;
|
|
189
202
|
let mut all_features = features.to_vec();
|
|
190
203
|
for f in tishlang_compile::extract_native_import_features(&program) {
|
|
191
204
|
if !all_features.contains(&f) {
|
|
@@ -200,9 +213,7 @@ pub fn compile_program_to_native(
|
|
|
200
213
|
&native_build.native_init,
|
|
201
214
|
optimize,
|
|
202
215
|
)
|
|
203
|
-
.map_err(|e| NativeError {
|
|
204
|
-
message: e.message,
|
|
205
|
-
})?;
|
|
216
|
+
.map_err(|e| NativeError { message: e.message })?;
|
|
206
217
|
crate::build::build_via_cargo(
|
|
207
218
|
&rust_code,
|
|
208
219
|
native_modules,
|
|
@@ -220,15 +231,25 @@ pub fn compile_program_to_native(
|
|
|
220
231
|
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
232
|
});
|
|
222
233
|
}
|
|
223
|
-
let program = if optimize {
|
|
234
|
+
let program = if optimize {
|
|
235
|
+
tishlang_opt::optimize(program)
|
|
236
|
+
} else {
|
|
237
|
+
program.clone()
|
|
238
|
+
};
|
|
224
239
|
let chunk = if optimize {
|
|
225
|
-
tishlang_bytecode::compile(&program).map_err(|e| NativeError {
|
|
240
|
+
tishlang_bytecode::compile(&program).map_err(|e| NativeError {
|
|
241
|
+
message: e.to_string(),
|
|
242
|
+
})?
|
|
226
243
|
} else {
|
|
227
|
-
tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
|
|
244
|
+
tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
|
|
245
|
+
message: e.to_string(),
|
|
246
|
+
})?
|
|
228
247
|
};
|
|
229
248
|
let cranelift_features = tishlang_compile::extract_native_import_features(&program);
|
|
230
249
|
tishlang_cranelift::compile_chunk_to_native(&chunk, output_path, &cranelift_features)
|
|
231
|
-
.map_err(|e| NativeError {
|
|
250
|
+
.map_err(|e| NativeError {
|
|
251
|
+
message: e.to_string(),
|
|
252
|
+
})
|
|
232
253
|
}
|
|
233
254
|
Backend::Llvm => {
|
|
234
255
|
if tishlang_compile::has_external_native_imports(program) {
|
|
@@ -236,11 +257,19 @@ pub fn compile_program_to_native(
|
|
|
236
257
|
message: "LLVM backend does not support external native imports (tish:…, cargo:…, @scope/pkg).".to_string(),
|
|
237
258
|
});
|
|
238
259
|
}
|
|
239
|
-
let program = if optimize {
|
|
260
|
+
let program = if optimize {
|
|
261
|
+
tishlang_opt::optimize(program)
|
|
262
|
+
} else {
|
|
263
|
+
program.clone()
|
|
264
|
+
};
|
|
240
265
|
let chunk = if optimize {
|
|
241
|
-
tishlang_bytecode::compile(&program).map_err(|e| NativeError {
|
|
266
|
+
tishlang_bytecode::compile(&program).map_err(|e| NativeError {
|
|
267
|
+
message: e.to_string(),
|
|
268
|
+
})?
|
|
242
269
|
} else {
|
|
243
|
-
tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
|
|
270
|
+
tishlang_bytecode::compile_unoptimized(&program).map_err(|e| NativeError {
|
|
271
|
+
message: e.to_string(),
|
|
272
|
+
})?
|
|
244
273
|
};
|
|
245
274
|
let llvm_features = tishlang_compile::extract_native_import_features(&program);
|
|
246
275
|
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
|
|
|
@@ -79,7 +75,9 @@ fn optimize_statement(stmt: &Statement) -> Statement {
|
|
|
79
75
|
Statement::If {
|
|
80
76
|
cond: opt_cond,
|
|
81
77
|
then_branch: Box::new(optimize_statement(then_branch)),
|
|
82
|
-
else_branch: else_branch
|
|
78
|
+
else_branch: else_branch
|
|
79
|
+
.as_ref()
|
|
80
|
+
.map(|b| Box::new(optimize_statement(b))),
|
|
83
81
|
span: *span,
|
|
84
82
|
}
|
|
85
83
|
}
|
|
@@ -144,21 +142,12 @@ fn optimize_statement(stmt: &Statement) -> Statement {
|
|
|
144
142
|
expr: optimize_expr(expr),
|
|
145
143
|
cases: cases
|
|
146
144
|
.iter()
|
|
147
|
-
.map(|(ce, stmts)|
|
|
148
|
-
(
|
|
149
|
-
ce.as_ref().map(optimize_expr),
|
|
150
|
-
optimize_block(stmts),
|
|
151
|
-
)
|
|
152
|
-
})
|
|
145
|
+
.map(|(ce, stmts)| (ce.as_ref().map(optimize_expr), optimize_block(stmts)))
|
|
153
146
|
.collect(),
|
|
154
147
|
default_body: default_body.as_ref().map(|stmts| optimize_block(stmts)),
|
|
155
148
|
span: *span,
|
|
156
149
|
},
|
|
157
|
-
Statement::DoWhile {
|
|
158
|
-
body,
|
|
159
|
-
cond,
|
|
160
|
-
span,
|
|
161
|
-
} => Statement::DoWhile {
|
|
150
|
+
Statement::DoWhile { body, cond, span } => Statement::DoWhile {
|
|
162
151
|
body: Box::new(optimize_statement(body)),
|
|
163
152
|
cond: optimize_expr(cond),
|
|
164
153
|
span: *span,
|
|
@@ -177,7 +166,9 @@ fn optimize_statement(stmt: &Statement) -> Statement {
|
|
|
177
166
|
body: Box::new(optimize_statement(body)),
|
|
178
167
|
catch_param: catch_param.clone(),
|
|
179
168
|
catch_body: catch_body.as_ref().map(|b| Box::new(optimize_statement(b))),
|
|
180
|
-
finally_body: finally_body
|
|
169
|
+
finally_body: finally_body
|
|
170
|
+
.as_ref()
|
|
171
|
+
.map(|b| Box::new(optimize_statement(b))),
|
|
181
172
|
span: *span,
|
|
182
173
|
},
|
|
183
174
|
Statement::Import { .. } | Statement::Export { .. } => stmt.clone(),
|
|
@@ -232,7 +223,12 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
232
223
|
name: Arc::clone(name),
|
|
233
224
|
span: *span,
|
|
234
225
|
},
|
|
235
|
-
Expr::Binary {
|
|
226
|
+
Expr::Binary {
|
|
227
|
+
left,
|
|
228
|
+
op,
|
|
229
|
+
right,
|
|
230
|
+
span,
|
|
231
|
+
} => {
|
|
236
232
|
let opt_left = optimize_expr(left);
|
|
237
233
|
let opt_right = optimize_expr(right);
|
|
238
234
|
|
|
@@ -324,32 +320,28 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
324
320
|
span: *span,
|
|
325
321
|
}
|
|
326
322
|
}
|
|
327
|
-
Expr::Call {
|
|
328
|
-
callee,
|
|
329
|
-
args,
|
|
330
|
-
span,
|
|
331
|
-
} => Expr::Call {
|
|
323
|
+
Expr::Call { callee, args, span } => Expr::Call {
|
|
332
324
|
callee: Box::new(optimize_expr(callee)),
|
|
333
325
|
args: args
|
|
334
326
|
.iter()
|
|
335
327
|
.map(|a| match a {
|
|
336
328
|
tishlang_ast::CallArg::Expr(e) => tishlang_ast::CallArg::Expr(optimize_expr(e)),
|
|
337
|
-
tishlang_ast::CallArg::Spread(e) =>
|
|
329
|
+
tishlang_ast::CallArg::Spread(e) => {
|
|
330
|
+
tishlang_ast::CallArg::Spread(optimize_expr(e))
|
|
331
|
+
}
|
|
338
332
|
})
|
|
339
333
|
.collect(),
|
|
340
334
|
span: *span,
|
|
341
335
|
},
|
|
342
|
-
Expr::New {
|
|
343
|
-
callee,
|
|
344
|
-
args,
|
|
345
|
-
span,
|
|
346
|
-
} => Expr::New {
|
|
336
|
+
Expr::New { callee, args, span } => Expr::New {
|
|
347
337
|
callee: Box::new(optimize_expr(callee)),
|
|
348
338
|
args: args
|
|
349
339
|
.iter()
|
|
350
340
|
.map(|a| match a {
|
|
351
341
|
tishlang_ast::CallArg::Expr(e) => tishlang_ast::CallArg::Expr(optimize_expr(e)),
|
|
352
|
-
tishlang_ast::CallArg::Spread(e) =>
|
|
342
|
+
tishlang_ast::CallArg::Spread(e) => {
|
|
343
|
+
tishlang_ast::CallArg::Spread(optimize_expr(e))
|
|
344
|
+
}
|
|
353
345
|
})
|
|
354
346
|
.collect(),
|
|
355
347
|
span: *span,
|
|
@@ -385,14 +377,11 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
385
377
|
optional: *optional,
|
|
386
378
|
span: *span,
|
|
387
379
|
},
|
|
388
|
-
Expr::NullishCoalesce {
|
|
389
|
-
left,
|
|
390
|
-
right,
|
|
391
|
-
span,
|
|
392
|
-
} => {
|
|
380
|
+
Expr::NullishCoalesce { left, right, span } => {
|
|
393
381
|
let opt_left = optimize_expr(left);
|
|
394
382
|
if let Expr::Literal {
|
|
395
|
-
value: Literal::Null,
|
|
383
|
+
value: Literal::Null,
|
|
384
|
+
..
|
|
396
385
|
} = &opt_left
|
|
397
386
|
{
|
|
398
387
|
return optimize_expr(right);
|
|
@@ -444,13 +433,23 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
444
433
|
| Expr::PostfixDec { .. }
|
|
445
434
|
| Expr::PrefixInc { .. }
|
|
446
435
|
| Expr::PrefixDec { .. } => expr.clone(),
|
|
447
|
-
Expr::CompoundAssign {
|
|
436
|
+
Expr::CompoundAssign {
|
|
437
|
+
name,
|
|
438
|
+
op,
|
|
439
|
+
value,
|
|
440
|
+
span,
|
|
441
|
+
} => Expr::CompoundAssign {
|
|
448
442
|
name: Arc::clone(name),
|
|
449
443
|
op: *op,
|
|
450
444
|
value: Box::new(optimize_expr(value)),
|
|
451
445
|
span: *span,
|
|
452
446
|
},
|
|
453
|
-
Expr::LogicalAssign {
|
|
447
|
+
Expr::LogicalAssign {
|
|
448
|
+
name,
|
|
449
|
+
op,
|
|
450
|
+
value,
|
|
451
|
+
span,
|
|
452
|
+
} => Expr::LogicalAssign {
|
|
454
453
|
name: Arc::clone(name),
|
|
455
454
|
op: *op,
|
|
456
455
|
value: Box::new(optimize_expr(value)),
|
|
@@ -478,11 +477,7 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
478
477
|
value: Box::new(optimize_expr(value)),
|
|
479
478
|
span: *span,
|
|
480
479
|
},
|
|
481
|
-
Expr::ArrowFunction {
|
|
482
|
-
params,
|
|
483
|
-
body,
|
|
484
|
-
span,
|
|
485
|
-
} => {
|
|
480
|
+
Expr::ArrowFunction { params, body, span } => {
|
|
486
481
|
let opt_body = match body {
|
|
487
482
|
ArrowBody::Expr(e) => ArrowBody::Expr(Box::new(optimize_expr(e))),
|
|
488
483
|
ArrowBody::Block(s) => ArrowBody::Block(Box::new(optimize_statement(s))),
|
|
@@ -493,7 +488,11 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
493
488
|
span: *span,
|
|
494
489
|
}
|
|
495
490
|
}
|
|
496
|
-
Expr::TemplateLiteral {
|
|
491
|
+
Expr::TemplateLiteral {
|
|
492
|
+
quasis,
|
|
493
|
+
exprs,
|
|
494
|
+
span,
|
|
495
|
+
} => Expr::TemplateLiteral {
|
|
497
496
|
quasis: quasis.iter().map(Arc::clone).collect(),
|
|
498
497
|
exprs: exprs.iter().map(optimize_expr).collect(),
|
|
499
498
|
span: *span,
|
|
@@ -503,7 +502,11 @@ fn optimize_expr(expr: &Expr) -> Expr {
|
|
|
503
502
|
span: *span,
|
|
504
503
|
},
|
|
505
504
|
Expr::JsxElement { .. } | Expr::JsxFragment { .. } => expr.clone(),
|
|
506
|
-
Expr::NativeModuleLoad {
|
|
505
|
+
Expr::NativeModuleLoad {
|
|
506
|
+
spec,
|
|
507
|
+
export_name,
|
|
508
|
+
span,
|
|
509
|
+
} => Expr::NativeModuleLoad {
|
|
507
510
|
spec: Arc::clone(spec),
|
|
508
511
|
export_name: Arc::clone(export_name),
|
|
509
512
|
span: *span,
|
|
@@ -699,8 +702,12 @@ fn try_fold_binop(left: &Literal, op: BinOp, right: &Literal) -> Option<Literal>
|
|
|
699
702
|
Add => {
|
|
700
703
|
if matches!(left, Literal::String(_)) || matches!(right, Literal::String(_)) {
|
|
701
704
|
return Some(Literal::String(
|
|
702
|
-
format!(
|
|
703
|
-
|
|
705
|
+
format!(
|
|
706
|
+
"{}{}",
|
|
707
|
+
literal_to_display_string(left),
|
|
708
|
+
literal_to_display_string(right)
|
|
709
|
+
)
|
|
710
|
+
.into(),
|
|
704
711
|
));
|
|
705
712
|
}
|
|
706
713
|
Literal::Number(ln + rn)
|
|
@@ -769,7 +776,11 @@ mod tests {
|
|
|
769
776
|
[tishlang_ast::Statement::ExprStmt { expr, .. }] => expr,
|
|
770
777
|
_ => panic!("expected single expr stmt"),
|
|
771
778
|
};
|
|
772
|
-
assert!(
|
|
779
|
+
assert!(
|
|
780
|
+
has_literal_number(expr, -42.0),
|
|
781
|
+
"expected -42, got {:?}",
|
|
782
|
+
expr
|
|
783
|
+
);
|
|
773
784
|
}
|
|
774
785
|
|
|
775
786
|
#[test]
|
|
@@ -781,7 +792,13 @@ mod tests {
|
|
|
781
792
|
_ => panic!("expected single expr stmt"),
|
|
782
793
|
};
|
|
783
794
|
assert!(
|
|
784
|
-
matches!(
|
|
795
|
+
matches!(
|
|
796
|
+
expr,
|
|
797
|
+
Expr::Literal {
|
|
798
|
+
value: Literal::Bool(false),
|
|
799
|
+
..
|
|
800
|
+
}
|
|
801
|
+
),
|
|
785
802
|
"expected false, got {:?}",
|
|
786
803
|
expr
|
|
787
804
|
);
|
|
@@ -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
|
}
|
|
@@ -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 {
|
|
215
|
+
Expr::Member {
|
|
216
|
+
object,
|
|
217
|
+
prop: tishlang_ast::MemberProp::Name(p),
|
|
218
|
+
..
|
|
219
|
+
} => {
|
|
199
220
|
assert_eq!(p.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,7 +238,9 @@ 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
|
}
|