@tishlang/tish 1.0.12 → 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 +47 -46
- package/crates/tish/src/repl_completion.rs +4 -4
- package/crates/tish/tests/integration_test.rs +47 -27
- 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
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
2
|
+
name = "tishlang_js_to_tish"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Vanilla JavaScript to Tish AST converter"
|
|
6
6
|
|
|
7
|
+
license-file = { workspace = true }
|
|
8
|
+
repository = { workspace = true }
|
|
7
9
|
[dependencies]
|
|
8
10
|
oxc = { version = "0.121", features = ["semantic"] }
|
|
9
|
-
|
|
11
|
+
tishlang_ast = { path = "../tish_ast" }
|
|
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
|
|
4
4
|
|
|
5
5
|
use oxc::ast::ast::Expression as OxcExpr;
|
|
6
6
|
use oxc::semantic::Semantic;
|
|
7
|
-
use
|
|
7
|
+
use tishlang_ast::{
|
|
8
8
|
ArrayElement, ArrowBody, BinOp, CompoundOp, DestructPattern, Expr, Literal, LogicalAssignOp,
|
|
9
9
|
MemberProp, ObjectProp, TypedParam,
|
|
10
10
|
};
|
|
@@ -155,7 +155,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
155
155
|
ArrowBody::Expr(Box::new(convert_expr(e, ctx)?))
|
|
156
156
|
} else {
|
|
157
157
|
let stmts = super::stmt::convert_statements(&arrow.body.statements, ctx.0, ctx.1)?;
|
|
158
|
-
ArrowBody::Block(Box::new(
|
|
158
|
+
ArrowBody::Block(Box::new(tishlang_ast::Statement::Block {
|
|
159
159
|
statements: stmts,
|
|
160
160
|
span: span_util::oxc_span_to_tish(ctx.1, &*arrow.body),
|
|
161
161
|
}))
|
|
@@ -205,7 +205,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
205
205
|
let body = match &f.body {
|
|
206
206
|
Some(fb) => {
|
|
207
207
|
let stmts = super::stmt::convert_statements(&fb.statements, ctx.0, ctx.1)?;
|
|
208
|
-
ArrowBody::Block(Box::new(
|
|
208
|
+
ArrowBody::Block(Box::new(tishlang_ast::Statement::Block {
|
|
209
209
|
statements: stmts,
|
|
210
210
|
span: span_util::oxc_span_to_tish(ctx.1, fb.as_ref()),
|
|
211
211
|
}))
|
|
@@ -233,7 +233,7 @@ pub fn convert_expr(expr: &OxcExpr<'_>, ctx: &Ctx<'_>) -> Result<Expr, ConvertEr
|
|
|
233
233
|
fn convert_chain_element(
|
|
234
234
|
ce: &oxc::ast::ast::ChainElement<'_>,
|
|
235
235
|
ctx: &Ctx<'_>,
|
|
236
|
-
span:
|
|
236
|
+
span: tishlang_ast::Span,
|
|
237
237
|
) -> Result<Expr, ConvertError> {
|
|
238
238
|
match ce {
|
|
239
239
|
oxc::ast::ast::ChainElement::StaticMemberExpression(m) => {
|
|
@@ -273,15 +273,15 @@ fn convert_chain_element(
|
|
|
273
273
|
fn convert_call_arg(
|
|
274
274
|
arg: &oxc::ast::ast::Argument<'_>,
|
|
275
275
|
ctx: &Ctx<'_>,
|
|
276
|
-
) -> Result<
|
|
276
|
+
) -> Result<tishlang_ast::CallArg, ConvertError> {
|
|
277
277
|
if arg.is_spread() {
|
|
278
278
|
if let oxc::ast::ast::Argument::SpreadElement(s) = arg {
|
|
279
|
-
Ok(
|
|
279
|
+
Ok(tishlang_ast::CallArg::Spread(convert_expr(&s.argument, ctx)?))
|
|
280
280
|
} else {
|
|
281
281
|
unreachable!()
|
|
282
282
|
}
|
|
283
283
|
} else if let Some(e) = arg.as_expression() {
|
|
284
|
-
Ok(
|
|
284
|
+
Ok(tishlang_ast::CallArg::Expr(convert_expr(e, ctx)?))
|
|
285
285
|
} else {
|
|
286
286
|
Err(ConvertError::new(ConvertErrorKind::Unsupported {
|
|
287
287
|
what: "call argument".into(),
|
|
@@ -340,7 +340,7 @@ fn convert_object_prop(
|
|
|
340
340
|
fn convert_assignment(
|
|
341
341
|
a: &oxc::ast::ast::AssignmentExpression<'_>,
|
|
342
342
|
ctx: &Ctx<'_>,
|
|
343
|
-
span:
|
|
343
|
+
span: tishlang_ast::Span,
|
|
344
344
|
) -> Result<Expr, ConvertError> {
|
|
345
345
|
let (left, right) = (&a.left, &a.right);
|
|
346
346
|
if let Some(oxc::ast::ast::SimpleAssignmentTarget::AssignmentTargetIdentifier(id)) =
|
|
@@ -435,7 +435,7 @@ fn convert_assignment(
|
|
|
435
435
|
fn convert_update_expr(
|
|
436
436
|
u: &oxc::ast::ast::UpdateExpression<'_>,
|
|
437
437
|
_ctx: &Ctx<'_>,
|
|
438
|
-
span:
|
|
438
|
+
span: tishlang_ast::Span,
|
|
439
439
|
) -> Result<Expr, ConvertError> {
|
|
440
440
|
let name: Arc<str> = match &u.argument {
|
|
441
441
|
oxc::ast::ast::SimpleAssignmentTarget::AssignmentTargetIdentifier(id) => {
|
|
@@ -498,13 +498,13 @@ fn convert_bin_op(
|
|
|
498
498
|
|
|
499
499
|
fn convert_unary_op(
|
|
500
500
|
op: &oxc::ast::ast::UnaryOperator,
|
|
501
|
-
) -> Result<
|
|
501
|
+
) -> Result<tishlang_ast::UnaryOp, ConvertError> {
|
|
502
502
|
Ok(match op {
|
|
503
|
-
oxc::ast::ast::UnaryOperator::LogicalNot =>
|
|
504
|
-
oxc::ast::ast::UnaryOperator::UnaryNegation =>
|
|
505
|
-
oxc::ast::ast::UnaryOperator::UnaryPlus =>
|
|
506
|
-
oxc::ast::ast::UnaryOperator::BitwiseNot =>
|
|
507
|
-
oxc::ast::ast::UnaryOperator::Void =>
|
|
503
|
+
oxc::ast::ast::UnaryOperator::LogicalNot => tishlang_ast::UnaryOp::Not,
|
|
504
|
+
oxc::ast::ast::UnaryOperator::UnaryNegation => tishlang_ast::UnaryOp::Neg,
|
|
505
|
+
oxc::ast::ast::UnaryOperator::UnaryPlus => tishlang_ast::UnaryOp::Pos,
|
|
506
|
+
oxc::ast::ast::UnaryOperator::BitwiseNot => tishlang_ast::UnaryOp::BitNot,
|
|
507
|
+
oxc::ast::ast::UnaryOperator::Void => tishlang_ast::UnaryOp::Void,
|
|
508
508
|
_ => {
|
|
509
509
|
return Err(ConvertError::new(ConvertErrorKind::Unsupported {
|
|
510
510
|
what: format!("unary operator: {op:?}"),
|
|
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
|
|
4
4
|
|
|
5
5
|
use oxc::ast::ast::Statement as OxcStmt;
|
|
6
6
|
use oxc::semantic::Semantic;
|
|
7
|
-
use
|
|
7
|
+
use tishlang_ast::{Statement, Span};
|
|
8
8
|
|
|
9
9
|
use super::expr;
|
|
10
10
|
use crate::error::{ConvertError, ConvertErrorKind};
|
|
@@ -406,18 +406,18 @@ fn convert_import(
|
|
|
406
406
|
} else {
|
|
407
407
|
Some(Arc::from(local_name))
|
|
408
408
|
};
|
|
409
|
-
specifiers.push(
|
|
409
|
+
specifiers.push(tishlang_ast::ImportSpecifier::Named {
|
|
410
410
|
name: Arc::from(imported_name),
|
|
411
411
|
alias,
|
|
412
412
|
});
|
|
413
413
|
}
|
|
414
414
|
oxc::ast::ast::ImportDeclarationSpecifier::ImportDefaultSpecifier(ds) => {
|
|
415
|
-
specifiers.push(
|
|
415
|
+
specifiers.push(tishlang_ast::ImportSpecifier::Default(Arc::from(
|
|
416
416
|
ds.local.name.as_str(),
|
|
417
417
|
)));
|
|
418
418
|
}
|
|
419
419
|
oxc::ast::ast::ImportDeclarationSpecifier::ImportNamespaceSpecifier(ns) => {
|
|
420
|
-
specifiers.push(
|
|
420
|
+
specifiers.push(tishlang_ast::ImportSpecifier::Namespace(Arc::from(
|
|
421
421
|
ns.local.name.as_str(),
|
|
422
422
|
)));
|
|
423
423
|
}
|
|
@@ -438,10 +438,10 @@ fn convert_export_default(
|
|
|
438
438
|
) -> Result<Statement, ConvertError> {
|
|
439
439
|
let declaration = if let Some(expr) = e.declaration.as_expression() {
|
|
440
440
|
let expr = expr::convert_expr(expr, ctx)?;
|
|
441
|
-
|
|
441
|
+
tishlang_ast::ExportDeclaration::Default(expr)
|
|
442
442
|
} else if let oxc::ast::ast::ExportDefaultDeclarationKind::FunctionDeclaration(f) = &e.declaration {
|
|
443
443
|
let stmt = convert_function_decl(f.as_ref(), ctx, span_util::stub_span())?;
|
|
444
|
-
|
|
444
|
+
tishlang_ast::ExportDeclaration::Named(Box::new(stmt))
|
|
445
445
|
} else {
|
|
446
446
|
return Err(ConvertError::new(ConvertErrorKind::Unsupported {
|
|
447
447
|
what: "export default (this form)".into(),
|
|
@@ -462,7 +462,7 @@ fn convert_export_named(
|
|
|
462
462
|
if let Some(decl) = &e.declaration {
|
|
463
463
|
let stmt = convert_declaration(decl, ctx)?;
|
|
464
464
|
Ok(Statement::Export {
|
|
465
|
-
declaration: Box::new(
|
|
465
|
+
declaration: Box::new(tishlang_ast::ExportDeclaration::Named(Box::new(stmt))),
|
|
466
466
|
span,
|
|
467
467
|
})
|
|
468
468
|
} else {
|
|
@@ -7,7 +7,7 @@ use oxc::allocator::Allocator;
|
|
|
7
7
|
use oxc::parser::Parser;
|
|
8
8
|
use oxc::semantic::SemanticBuilder;
|
|
9
9
|
use oxc::span::SourceType;
|
|
10
|
-
use
|
|
10
|
+
use tishlang_ast::Program;
|
|
11
11
|
|
|
12
12
|
use crate::error::{ConvertError, ConvertErrorKind};
|
|
13
13
|
use crate::transform::stmt::convert_statements;
|
package/crates/tish/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "
|
|
3
|
-
version = "
|
|
2
|
+
name = "tishlang"
|
|
3
|
+
version = "1.0.14"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Tish CLI - run, REPL, compile to native"
|
|
6
6
|
license-file = { workspace = true }
|
|
@@ -16,28 +16,28 @@ default = []
|
|
|
16
16
|
# Full: all capabilities enabled (for development/trusted environments)
|
|
17
17
|
full = ["http", "fs", "process", "regex", "ws"]
|
|
18
18
|
# Individual capability flags
|
|
19
|
-
http = ["
|
|
20
|
-
fs = ["
|
|
21
|
-
process = ["
|
|
22
|
-
regex = ["
|
|
23
|
-
ws = ["
|
|
19
|
+
http = ["tishlang_eval/http", "tishlang_runtime/http", "tishlang_compile/http", "tishlang_vm/http"]
|
|
20
|
+
fs = ["tishlang_eval/fs", "tishlang_runtime/fs", "tishlang_compile/fs", "tishlang_vm/fs"]
|
|
21
|
+
process = ["tishlang_eval/process", "tishlang_runtime/process", "tishlang_compile/process", "tishlang_vm/process"]
|
|
22
|
+
regex = ["tishlang_eval/regex", "tishlang_runtime/regex", "tishlang_compile/regex", "tishlang_vm/regex"]
|
|
23
|
+
ws = ["tishlang_eval/ws", "tishlang_runtime/ws", "tishlang_compile/ws", "tishlang_vm/ws"]
|
|
24
24
|
[dependencies]
|
|
25
25
|
rustyline = { version = "17", features = ["with-file-history"] }
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
tishlang_lexer = { path = "../tish_lexer" }
|
|
27
|
+
tishlang_ast = { path = "../tish_ast" }
|
|
28
|
+
tishlang_parser = { path = "../tish_parser" }
|
|
29
|
+
tishlang_eval = { path = "../tish_eval" }
|
|
30
|
+
tishlang_compile = { path = "../tish_compile" }
|
|
31
|
+
tishlang_compile_js = { path = "../tish_compile_js" }
|
|
32
|
+
tishlang_bytecode = { path = "../tish_bytecode" }
|
|
33
|
+
tishlang_opt = { path = "../tish_opt" }
|
|
34
|
+
tishlang_vm = { path = "../tish_vm" }
|
|
35
|
+
tishlang_native = { path = "../tish_native" }
|
|
36
|
+
tishlang_llvm = { path = "../tish_llvm" }
|
|
37
|
+
tishlang_wasm = { path = "../tish_wasm" }
|
|
38
|
+
tishlang_runtime = { path = "../tish_runtime" }
|
|
39
|
+
tishlang_core = { path = "../tish_core" }
|
|
40
|
+
tishlang_js_to_tish = { path = "../js_to_tish" }
|
|
41
41
|
clap = { version = "4.6.0", features = ["derive"] }
|
|
42
42
|
|
|
43
43
|
[dev-dependencies]
|
package/crates/tish/src/main.rs
CHANGED
|
@@ -14,6 +14,7 @@ use rustyline::{Behavior, ColorMode, CompletionType, Config, Editor};
|
|
|
14
14
|
#[derive(Parser)]
|
|
15
15
|
#[command(name = "tish")]
|
|
16
16
|
#[command(about = "Tish - minimal TS/JS-compatible language")]
|
|
17
|
+
#[command(version = env!("CARGO_PKG_VERSION"))]
|
|
17
18
|
#[command(after_help = "To disable optimizations: TISH_NO_OPTIMIZE=1")]
|
|
18
19
|
pub(crate) struct Cli {
|
|
19
20
|
#[command(subcommand)]
|
|
@@ -116,42 +117,42 @@ fn run_file(path: &str, backend: &str, _features: &[String], no_optimize: bool)
|
|
|
116
117
|
});
|
|
117
118
|
|
|
118
119
|
let program = if path.extension().map(|e| e == "js") == Some(true) {
|
|
119
|
-
let prog =
|
|
120
|
+
let prog = tishlang_js_to_tish::convert(&fs::read_to_string(&path).map_err(|e| format!("{}", e))?)
|
|
120
121
|
.map_err(|e| format!("{}", e))?;
|
|
121
122
|
if no_optimize {
|
|
122
123
|
prog
|
|
123
124
|
} else {
|
|
124
|
-
|
|
125
|
+
tishlang_opt::optimize(&prog)
|
|
125
126
|
}
|
|
126
127
|
} else {
|
|
127
|
-
let modules =
|
|
128
|
-
|
|
129
|
-
let prog =
|
|
128
|
+
let modules = tishlang_compile::resolve_project(&path, project_root)?;
|
|
129
|
+
tishlang_compile::detect_cycles(&modules)?;
|
|
130
|
+
let prog = tishlang_compile::merge_modules(modules)?;
|
|
130
131
|
if no_optimize {
|
|
131
132
|
prog
|
|
132
133
|
} else {
|
|
133
|
-
|
|
134
|
+
tishlang_opt::optimize(&prog)
|
|
134
135
|
}
|
|
135
136
|
};
|
|
136
137
|
|
|
137
138
|
if backend == "interp" {
|
|
138
|
-
let mut eval =
|
|
139
|
+
let mut eval = tishlang_eval::Evaluator::new();
|
|
139
140
|
let value = eval.eval_program(&program)?;
|
|
140
|
-
if !matches!(value,
|
|
141
|
-
println!("{}",
|
|
141
|
+
if !matches!(value, tishlang_eval::Value::Null) {
|
|
142
|
+
println!("{}", tishlang_eval::format_value_for_console(&value, tishlang_core::use_console_colors()));
|
|
142
143
|
}
|
|
143
144
|
return Ok(());
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
// VM backend (bytecode) - supports native imports when built with fs/http/process features
|
|
147
148
|
let chunk = if no_optimize {
|
|
148
|
-
|
|
149
|
+
tishlang_bytecode::compile_unoptimized(&program).map_err(|e| e.to_string())?
|
|
149
150
|
} else {
|
|
150
|
-
|
|
151
|
+
tishlang_bytecode::compile(&program).map_err(|e| e.to_string())?
|
|
151
152
|
};
|
|
152
|
-
let value =
|
|
153
|
-
if !matches!(value,
|
|
154
|
-
println!("{}",
|
|
153
|
+
let value = tishlang_vm::run(&chunk)?;
|
|
154
|
+
if !matches!(value, tishlang_core::Value::Null) {
|
|
155
|
+
println!("{}", tishlang_core::format_value_styled(&value, tishlang_core::use_console_colors()));
|
|
155
156
|
}
|
|
156
157
|
Ok(())
|
|
157
158
|
}
|
|
@@ -161,7 +162,7 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
161
162
|
let mut buffer = String::new();
|
|
162
163
|
|
|
163
164
|
if backend == "interp" {
|
|
164
|
-
let mut eval =
|
|
165
|
+
let mut eval = tishlang_eval::Evaluator::new();
|
|
165
166
|
let mut multiline = String::new();
|
|
166
167
|
loop {
|
|
167
168
|
let prompt = repl_prompt(multiline.is_empty());
|
|
@@ -170,7 +171,7 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
170
171
|
buffer.clear();
|
|
171
172
|
if io::stdin().read_line(&mut buffer).map_err(|e| e.to_string())? == 0 {
|
|
172
173
|
if !multiline.is_empty() {
|
|
173
|
-
let _ =
|
|
174
|
+
let _ = tishlang_parser::parse(multiline.trim());
|
|
174
175
|
}
|
|
175
176
|
break;
|
|
176
177
|
}
|
|
@@ -184,12 +185,12 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
184
185
|
multiline.push('\n');
|
|
185
186
|
multiline.push_str(line);
|
|
186
187
|
}
|
|
187
|
-
match
|
|
188
|
+
match tishlang_parser::parse(multiline.trim()) {
|
|
188
189
|
Ok(program) => {
|
|
189
190
|
match eval.eval_program(&program) {
|
|
190
191
|
Ok(v) => {
|
|
191
|
-
if !matches!(v,
|
|
192
|
-
println!("{}",
|
|
192
|
+
if !matches!(v, tishlang_eval::Value::Null) {
|
|
193
|
+
println!("{}", tishlang_eval::format_value_for_console(&v, tishlang_core::use_console_colors()));
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
196
|
Err(e) => eprintln!("{}", e),
|
|
@@ -213,7 +214,7 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
213
214
|
if !std::io::stdin().is_terminal() {
|
|
214
215
|
eprintln!("Note: Tab completion and grey preview require an interactive terminal (TTY).");
|
|
215
216
|
}
|
|
216
|
-
let vm = Rc::new(RefCell::new(
|
|
217
|
+
let vm = Rc::new(RefCell::new(tishlang_vm::Vm::new()));
|
|
217
218
|
let completer = repl_completion::ReplCompleter {
|
|
218
219
|
vm: Rc::clone(&vm),
|
|
219
220
|
no_optimize,
|
|
@@ -245,12 +246,12 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
245
246
|
if buffer.is_empty() {
|
|
246
247
|
break;
|
|
247
248
|
}
|
|
248
|
-
match
|
|
249
|
+
match tishlang_parser::parse(buffer.trim()) {
|
|
249
250
|
Ok(program) => {
|
|
250
251
|
let compile_fn = if no_optimize {
|
|
251
|
-
|
|
252
|
+
tishlang_bytecode::compile_for_repl_unoptimized
|
|
252
253
|
} else {
|
|
253
|
-
|
|
254
|
+
tishlang_bytecode::compile_for_repl
|
|
254
255
|
};
|
|
255
256
|
if let Ok(chunk) = compile_fn(&program) {
|
|
256
257
|
let _ = vm.borrow_mut().run(&chunk);
|
|
@@ -276,19 +277,19 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
276
277
|
buffer.push('\n');
|
|
277
278
|
buffer.push_str(line);
|
|
278
279
|
}
|
|
279
|
-
match
|
|
280
|
+
match tishlang_parser::parse(buffer.trim()) {
|
|
280
281
|
Ok(program) => {
|
|
281
282
|
let compile_fn = if no_optimize {
|
|
282
|
-
|
|
283
|
+
tishlang_bytecode::compile_for_repl_unoptimized
|
|
283
284
|
} else {
|
|
284
|
-
|
|
285
|
+
tishlang_bytecode::compile_for_repl
|
|
285
286
|
};
|
|
286
287
|
match compile_fn(&program) {
|
|
287
288
|
Ok(chunk) => {
|
|
288
289
|
match vm.borrow_mut().run(&chunk) {
|
|
289
290
|
Ok(v) => {
|
|
290
|
-
if !matches!(v,
|
|
291
|
-
println!("{}",
|
|
291
|
+
if !matches!(v, tishlang_core::Value::Null) {
|
|
292
|
+
println!("{}", tishlang_core::format_value_styled(&v, tishlang_core::use_console_colors()));
|
|
292
293
|
}
|
|
293
294
|
}
|
|
294
295
|
Err(e) => eprintln!("{}", e),
|
|
@@ -318,7 +319,7 @@ fn run_repl(backend: &str, no_optimize: bool) -> Result<(), String> {
|
|
|
318
319
|
|
|
319
320
|
/// REPL prompt with green caret when stdout is a TTY (platform-style).
|
|
320
321
|
fn repl_prompt(primary: bool) -> String {
|
|
321
|
-
if
|
|
322
|
+
if tishlang_core::use_console_colors() {
|
|
322
323
|
if primary {
|
|
323
324
|
"\x1b[32m> \x1b[0m".to_string()
|
|
324
325
|
} else {
|
|
@@ -338,15 +339,15 @@ fn tish_history_path() -> Option<PathBuf> {
|
|
|
338
339
|
home.map(|h| PathBuf::from(h).join(".tish_history"))
|
|
339
340
|
}
|
|
340
341
|
|
|
341
|
-
fn parse_jsx_mode(s: &str) -> Result<
|
|
342
|
+
fn parse_jsx_mode(s: &str) -> Result<tishlang_compile_js::JsxMode, String> {
|
|
342
343
|
match s {
|
|
343
344
|
"legacy" => Err(
|
|
344
345
|
"--jsx legacy was removed. Use --jsx lattish (default) with lattish merged into your \
|
|
345
346
|
bundle, or --jsx vdom with Lattish's createRoot."
|
|
346
347
|
.to_string(),
|
|
347
348
|
),
|
|
348
|
-
"vdom" => Ok(
|
|
349
|
-
"lattish" => Ok(
|
|
349
|
+
"vdom" => Ok(tishlang_compile_js::JsxMode::Vdom),
|
|
350
|
+
"lattish" => Ok(tishlang_compile_js::JsxMode::LattishH),
|
|
350
351
|
other => Err(format!(
|
|
351
352
|
"Unknown --jsx {:?}: use lattish (default) or vdom.",
|
|
352
353
|
other
|
|
@@ -374,20 +375,20 @@ fn compile_to_js(
|
|
|
374
375
|
"export fn __TishJsxRoot() {{\n return (\n{}\n )\n}}",
|
|
375
376
|
source.trim()
|
|
376
377
|
);
|
|
377
|
-
let program =
|
|
378
|
+
let program = tishlang_parser::parse(&wrapped)
|
|
378
379
|
.map_err(|e| format!("JSX wrapper parse: {}", e))?;
|
|
379
380
|
let p = if optimize {
|
|
380
|
-
|
|
381
|
+
tishlang_opt::optimize(&program)
|
|
381
382
|
} else {
|
|
382
383
|
program
|
|
383
384
|
};
|
|
384
|
-
|
|
385
|
+
tishlang_compile_js::compile_with_jsx(&p, optimize, jsx_mode).map_err(|e| format!("{}", e))?
|
|
385
386
|
} else if input_path.extension().map(|e| e == "js") == Some(true) {
|
|
386
387
|
let source = fs::read_to_string(input_path).map_err(|e| format!("{}", e))?;
|
|
387
|
-
let program =
|
|
388
|
-
|
|
388
|
+
let program = tishlang_js_to_tish::convert(&source).map_err(|e| format!("{}", e))?;
|
|
389
|
+
tishlang_compile_js::compile_with_jsx(&program, optimize, jsx_mode).map_err(|e| format!("{}", e))?
|
|
389
390
|
} else {
|
|
390
|
-
|
|
391
|
+
tishlang_compile_js::compile_project_with_jsx(input_path, project_root, optimize, jsx_mode)
|
|
391
392
|
.map_err(|e| format!("{}", e))?
|
|
392
393
|
};
|
|
393
394
|
|
|
@@ -431,8 +432,8 @@ fn compile_file(
|
|
|
431
432
|
|
|
432
433
|
if target == "wasm" && is_js {
|
|
433
434
|
let source = fs::read_to_string(&input_path).map_err(|e| format!("{}", e))?;
|
|
434
|
-
let program =
|
|
435
|
-
return
|
|
435
|
+
let program = tishlang_js_to_tish::convert(&source).map_err(|e| format!("{}", e))?;
|
|
436
|
+
return tishlang_wasm::compile_program_to_wasm(&program, Path::new(output_path), optimize)
|
|
436
437
|
.map_err(|e| format!("{}", e));
|
|
437
438
|
}
|
|
438
439
|
|
|
@@ -444,7 +445,7 @@ fn compile_file(
|
|
|
444
445
|
Some(p)
|
|
445
446
|
}
|
|
446
447
|
});
|
|
447
|
-
return
|
|
448
|
+
return tishlang_wasm::compile_to_wasm(&input_path, project_root, Path::new(output_path), optimize)
|
|
448
449
|
.map_err(|e| e.to_string());
|
|
449
450
|
}
|
|
450
451
|
|
|
@@ -456,7 +457,7 @@ fn compile_file(
|
|
|
456
457
|
Some(p)
|
|
457
458
|
}
|
|
458
459
|
});
|
|
459
|
-
return
|
|
460
|
+
return tishlang_wasm::compile_to_wasi(&input_path, project_root, Path::new(output_path), optimize)
|
|
460
461
|
.map_err(|e| e.to_string());
|
|
461
462
|
}
|
|
462
463
|
|
|
@@ -494,8 +495,8 @@ fn compile_file(
|
|
|
494
495
|
|
|
495
496
|
if is_js {
|
|
496
497
|
let source = fs::read_to_string(&input_path).map_err(|e| format!("{}", e))?;
|
|
497
|
-
let program =
|
|
498
|
-
|
|
498
|
+
let program = tishlang_js_to_tish::convert(&source).map_err(|e| format!("{}", e))?;
|
|
499
|
+
tishlang_native::compile_program_to_native(
|
|
499
500
|
&program,
|
|
500
501
|
project_root,
|
|
501
502
|
Path::new(output_path),
|
|
@@ -505,7 +506,7 @@ fn compile_file(
|
|
|
505
506
|
)
|
|
506
507
|
.map_err(|e| e.to_string())?;
|
|
507
508
|
} else {
|
|
508
|
-
|
|
509
|
+
tishlang_native::compile_to_native(
|
|
509
510
|
&input_path,
|
|
510
511
|
project_root,
|
|
511
512
|
Path::new(output_path),
|
|
@@ -579,7 +580,7 @@ mod cli_tests {
|
|
|
579
580
|
fn dump_ast(path: &str) -> Result<(), String> {
|
|
580
581
|
let source =
|
|
581
582
|
fs::read_to_string(path).map_err(|e| format!("Cannot read {}: {}", path, e))?;
|
|
582
|
-
let program =
|
|
583
|
+
let program = tishlang_parser::parse(&source)?;
|
|
583
584
|
println!("{:#?}", program);
|
|
584
585
|
Ok(())
|
|
585
586
|
}
|
|
@@ -12,9 +12,9 @@ use rustyline::validate::Validator;
|
|
|
12
12
|
use rustyline::Context;
|
|
13
13
|
use rustyline::Helper;
|
|
14
14
|
|
|
15
|
-
use
|
|
16
|
-
use
|
|
17
|
-
use
|
|
15
|
+
use tishlang_bytecode::{compile_for_repl, compile_for_repl_unoptimized};
|
|
16
|
+
use tishlang_parser;
|
|
17
|
+
use tishlang_vm::Vm;
|
|
18
18
|
|
|
19
19
|
/// Tish keywords for bare-word completion (Python-style).
|
|
20
20
|
const KEYWORDS: &[&str] = &[
|
|
@@ -79,7 +79,7 @@ impl ReplCompleter {
|
|
|
79
79
|
}
|
|
80
80
|
let member_prefix = line_before_cursor[last_dot + 1..].trim();
|
|
81
81
|
|
|
82
|
-
let program =
|
|
82
|
+
let program = tishlang_parser::parse(prefix_expr).ok()?;
|
|
83
83
|
let compile_fn = if self.no_optimize {
|
|
84
84
|
compile_for_repl_unoptimized
|
|
85
85
|
} else {
|