@tishlang/tish 1.5.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.
Files changed (85) hide show
  1. package/Cargo.toml +1 -0
  2. package/bin/tish +0 -0
  3. package/crates/js_to_tish/src/error.rs +2 -8
  4. package/crates/js_to_tish/src/transform/expr.rs +101 -130
  5. package/crates/js_to_tish/src/transform/stmt.rs +25 -22
  6. package/crates/tish/Cargo.toml +1 -1
  7. package/crates/tish/src/cli_help.rs +76 -29
  8. package/crates/tish/src/main.rs +85 -54
  9. package/crates/tish/tests/cargo_example_compile.rs +67 -0
  10. package/crates/tish/tests/fixtures/cargo_example_project/Cargo.toml +3 -0
  11. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/Cargo.toml +11 -0
  12. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +12 -0
  13. package/crates/tish/tests/fixtures/cargo_example_project/package.json +10 -0
  14. package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +3 -0
  15. package/crates/tish/tests/integration_test.rs +197 -47
  16. package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
  17. package/crates/tish/tests/shortcircuit.rs +19 -4
  18. package/crates/tish_ast/src/ast.rs +12 -14
  19. package/crates/tish_build_utils/src/lib.rs +64 -6
  20. package/crates/tish_builtins/src/array.rs +52 -21
  21. package/crates/tish_builtins/src/construct.rs +2 -8
  22. package/crates/tish_builtins/src/globals.rs +30 -15
  23. package/crates/tish_builtins/src/lib.rs +5 -5
  24. package/crates/tish_builtins/src/math.rs +5 -3
  25. package/crates/tish_builtins/src/string.rs +71 -19
  26. package/crates/tish_bytecode/src/chunk.rs +0 -1
  27. package/crates/tish_bytecode/src/compiler.rs +164 -60
  28. package/crates/tish_bytecode/src/opcode.rs +13 -4
  29. package/crates/tish_bytecode/src/peephole.rs +2 -2
  30. package/crates/tish_compile/Cargo.toml +1 -0
  31. package/crates/tish_compile/src/codegen.rs +989 -318
  32. package/crates/tish_compile/src/infer.rs +69 -19
  33. package/crates/tish_compile/src/lib.rs +21 -8
  34. package/crates/tish_compile/src/resolve.rs +515 -94
  35. package/crates/tish_compile/src/types.rs +10 -14
  36. package/crates/tish_compile_js/src/codegen.rs +34 -13
  37. package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
  38. package/crates/tish_compiler_wasm/src/lib.rs +16 -13
  39. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +40 -48
  40. package/crates/tish_core/src/json.rs +5 -3
  41. package/crates/tish_core/src/lib.rs +1 -1
  42. package/crates/tish_core/src/uri.rs +9 -6
  43. package/crates/tish_core/src/value.rs +92 -28
  44. package/crates/tish_cranelift/src/link.rs +6 -9
  45. package/crates/tish_cranelift/src/lower.rs +14 -8
  46. package/crates/tish_eval/src/eval.rs +398 -141
  47. package/crates/tish_eval/src/lib.rs +10 -6
  48. package/crates/tish_eval/src/natives.rs +95 -38
  49. package/crates/tish_eval/src/promise.rs +14 -8
  50. package/crates/tish_eval/src/timers.rs +28 -19
  51. package/crates/tish_eval/src/value.rs +10 -3
  52. package/crates/tish_fmt/src/lib.rs +29 -13
  53. package/crates/tish_lexer/src/lib.rs +217 -63
  54. package/crates/tish_lexer/src/token.rs +6 -6
  55. package/crates/tish_llvm/src/lib.rs +15 -8
  56. package/crates/tish_lsp/src/main.rs +41 -43
  57. package/crates/tish_native/src/build.rs +38 -15
  58. package/crates/tish_native/src/lib.rs +76 -32
  59. package/crates/tish_opt/src/lib.rs +67 -50
  60. package/crates/tish_parser/src/lib.rs +36 -11
  61. package/crates/tish_parser/src/parser.rs +172 -87
  62. package/crates/tish_runtime/src/http.rs +15 -6
  63. package/crates/tish_runtime/src/http_fetch.rs +24 -14
  64. package/crates/tish_runtime/src/lib.rs +224 -168
  65. package/crates/tish_runtime/src/promise.rs +1 -5
  66. package/crates/tish_runtime/src/ws.rs +45 -20
  67. package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
  68. package/crates/tish_ui/src/jsx.rs +41 -22
  69. package/crates/tish_ui/src/lib.rs +2 -2
  70. package/crates/tish_vm/src/vm.rs +320 -116
  71. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
  72. package/crates/tish_wasm/src/lib.rs +38 -28
  73. package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
  74. package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
  75. package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
  76. package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
  77. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  78. package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
  79. package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
  80. package/package.json +1 -1
  81. package/platform/darwin-arm64/tish +0 -0
  82. package/platform/darwin-x64/tish +0 -0
  83. package/platform/linux-arm64/tish +0 -0
  84. package/platform/linux-x64/tish +0 -0
  85. package/platform/win32-x64/tish.exe +0 -0
@@ -22,7 +22,9 @@ pub struct InferCtx {
22
22
 
23
23
  impl InferCtx {
24
24
  pub fn new() -> Self {
25
- Self { scopes: vec![HashMap::new()] }
25
+ Self {
26
+ scopes: vec![HashMap::new()],
27
+ }
26
28
  }
27
29
 
28
30
  fn push_scope(&mut self) {
@@ -75,17 +77,16 @@ pub fn infer_expr_type(expr: &Expr, ctx: &InferCtx) -> Option<TypeAnnotation> {
75
77
  Literal::Null => None,
76
78
  },
77
79
  Expr::Ident { name, .. } => ctx.lookup(name.as_ref()).cloned(),
78
- Expr::Binary { left, op, right, .. } => {
80
+ Expr::Binary {
81
+ left, op, right, ..
82
+ } => {
79
83
  let lt = infer_expr_type(left, ctx)?;
80
84
  let rt = infer_expr_type(right, ctx)?;
81
85
  if is_number(&lt) && is_number(&rt) {
82
86
  match op {
83
- BinOp::Add
84
- | BinOp::Sub
85
- | BinOp::Mul
86
- | BinOp::Div
87
- | BinOp::Mod
88
- | BinOp::Pow => Some(number_ann()),
87
+ BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Mod | BinOp::Pow => {
88
+ Some(number_ann())
89
+ }
89
90
  BinOp::Lt
90
91
  | BinOp::Le
91
92
  | BinOp::Gt
@@ -103,7 +104,11 @@ pub fn infer_expr_type(expr: &Expr, ctx: &InferCtx) -> Option<TypeAnnotation> {
103
104
  match op {
104
105
  UnaryOp::Neg | UnaryOp::Pos => {
105
106
  let t = infer_expr_type(operand, ctx)?;
106
- if is_number(&t) { Some(number_ann()) } else { None }
107
+ if is_number(&t) {
108
+ Some(number_ann())
109
+ } else {
110
+ None
111
+ }
107
112
  }
108
113
  UnaryOp::Not => Some(bool_ann()),
109
114
  _ => None,
@@ -117,7 +122,9 @@ pub fn infer_expr_type(expr: &Expr, ctx: &InferCtx) -> Option<TypeAnnotation> {
117
122
  /// type annotations filled in on `VarDecl` nodes.
118
123
  pub fn infer_program(program: &Program) -> Program {
119
124
  let mut ctx = InferCtx::new();
120
- Program { statements: infer_statements(&program.statements, &mut ctx) }
125
+ Program {
126
+ statements: infer_statements(&program.statements, &mut ctx),
127
+ }
121
128
  }
122
129
 
123
130
  fn infer_statements(stmts: &[Statement], ctx: &mut InferCtx) -> Vec<Statement> {
@@ -126,7 +133,13 @@ fn infer_statements(stmts: &[Statement], ctx: &mut InferCtx) -> Vec<Statement> {
126
133
 
127
134
  fn infer_statement(stmt: &Statement, ctx: &mut InferCtx) -> Statement {
128
135
  match stmt {
129
- Statement::VarDecl { name, mutable, type_ann, init, span } => {
136
+ Statement::VarDecl {
137
+ name,
138
+ mutable,
139
+ type_ann,
140
+ init,
141
+ span,
142
+ } => {
130
143
  // Already annotated — propagate into ctx but don't change the node.
131
144
  if let Some(ann) = type_ann {
132
145
  ctx.define(name.as_ref(), ann.clone());
@@ -149,9 +162,18 @@ fn infer_statement(stmt: &Statement, ctx: &mut InferCtx) -> Statement {
149
162
  ctx.push_scope();
150
163
  let stmts = infer_statements(statements, ctx);
151
164
  ctx.pop_scope();
152
- Statement::Block { statements: stmts, span: *span }
165
+ Statement::Block {
166
+ statements: stmts,
167
+ span: *span,
168
+ }
153
169
  }
154
- Statement::For { init, cond, update, body, span } => {
170
+ Statement::For {
171
+ init,
172
+ cond,
173
+ update,
174
+ body,
175
+ span,
176
+ } => {
155
177
  // Scope for loop variable
156
178
  ctx.push_scope();
157
179
  let new_init = init.as_ref().map(|i| Box::new(infer_statement(i, ctx)));
@@ -165,7 +187,12 @@ fn infer_statement(stmt: &Statement, ctx: &mut InferCtx) -> Statement {
165
187
  span: *span,
166
188
  }
167
189
  }
168
- Statement::ForOf { name, iterable, body, span } => {
190
+ Statement::ForOf {
191
+ name,
192
+ iterable,
193
+ body,
194
+ span,
195
+ } => {
169
196
  ctx.push_scope();
170
197
  let new_body = Box::new(infer_statement(body, ctx));
171
198
  ctx.pop_scope();
@@ -180,17 +207,32 @@ fn infer_statement(stmt: &Statement, ctx: &mut InferCtx) -> Statement {
180
207
  ctx.push_scope();
181
208
  let new_body = Box::new(infer_statement(body, ctx));
182
209
  ctx.pop_scope();
183
- Statement::While { cond: cond.clone(), body: new_body, span: *span }
210
+ Statement::While {
211
+ cond: cond.clone(),
212
+ body: new_body,
213
+ span: *span,
214
+ }
184
215
  }
185
216
  Statement::DoWhile { body, cond, span } => {
186
217
  ctx.push_scope();
187
218
  let new_body = Box::new(infer_statement(body, ctx));
188
219
  ctx.pop_scope();
189
- Statement::DoWhile { body: new_body, cond: cond.clone(), span: *span }
220
+ Statement::DoWhile {
221
+ body: new_body,
222
+ cond: cond.clone(),
223
+ span: *span,
224
+ }
190
225
  }
191
- Statement::If { cond, then_branch, else_branch, span } => {
226
+ Statement::If {
227
+ cond,
228
+ then_branch,
229
+ else_branch,
230
+ span,
231
+ } => {
192
232
  let new_then = Box::new(infer_statement(then_branch, ctx));
193
- let new_else = else_branch.as_ref().map(|e| Box::new(infer_statement(e, ctx)));
233
+ let new_else = else_branch
234
+ .as_ref()
235
+ .map(|e| Box::new(infer_statement(e, ctx)));
194
236
  Statement::If {
195
237
  cond: cond.clone(),
196
238
  then_branch: new_then,
@@ -198,7 +240,15 @@ fn infer_statement(stmt: &Statement, ctx: &mut InferCtx) -> Statement {
198
240
  span: *span,
199
241
  }
200
242
  }
201
- Statement::FunDecl { async_, name, params, rest_param, return_type, body, span } => {
243
+ Statement::FunDecl {
244
+ async_,
245
+ name,
246
+ params,
247
+ rest_param,
248
+ return_type,
249
+ body,
250
+ span,
251
+ } => {
202
252
  ctx.push_scope();
203
253
  for p in params {
204
254
  if let FunParam::Simple(tp) = p {
@@ -7,15 +7,18 @@ mod infer;
7
7
  mod resolve;
8
8
  mod types;
9
9
 
10
+ pub use codegen::CompileError;
10
11
  pub use codegen::{
11
12
  compile, compile_project, compile_project_full, compile_with_features,
12
13
  compile_with_native_modules, compile_with_project_root,
13
14
  };
14
- pub use codegen::CompileError;
15
15
  pub use resolve::{
16
- detect_cycles, extract_native_import_features, has_external_native_imports, has_native_imports,
17
- is_builtin_native_spec, merge_modules, resolve_native_modules, resolve_project,
18
- resolve_project_from_stdin, ResolvedNativeModule,
16
+ cargo_export_fn_name, compute_native_build_artifacts, detect_cycles, export_name_to_rust_ident,
17
+ extract_native_import_features, format_rust_dependencies_toml, generate_native_wrapper_rs,
18
+ has_external_native_imports, has_native_imports, infer_native_module_exports,
19
+ is_builtin_native_spec, is_cargo_native_spec, merge_modules, read_project_tish_config,
20
+ resolve_native_modules, resolve_project, resolve_project_from_stdin, NativeBuildArtifacts,
21
+ NativeModuleInit, ResolvedNativeModule,
19
22
  };
20
23
  pub use types::{RustType, TypeContext};
21
24
 
@@ -41,7 +44,10 @@ fn sum(...args: number[]): number {
41
44
  // total should be declared as f64
42
45
  assert!(rust.contains("let mut total: f64"), "expected total: f64");
43
46
  // The return value of run() should convert total back to Value
44
- assert!(rust.contains("Value::Number(total)"), "expected Value::Number(total) wrapping");
47
+ assert!(
48
+ rust.contains("Value::Number(total)"),
49
+ "expected Value::Number(total) wrapping"
50
+ );
45
51
  }
46
52
 
47
53
  #[test]
@@ -57,7 +63,10 @@ for (let i = 0; i < 5; i = i + 1) {
57
63
  let program = parse(src).unwrap();
58
64
  let rust = compile(&program).unwrap();
59
65
  // outerVar and x are f64 (inferred) — Copy assignment, no .clone() needed.
60
- assert!(rust.contains("let mut outerVar: f64"), "expected outerVar: f64");
66
+ assert!(
67
+ rust.contains("let mut outerVar: f64"),
68
+ "expected outerVar: f64"
69
+ );
61
70
  assert!(rust.contains("let mut x: f64"), "expected x: f64");
62
71
  }
63
72
 
@@ -102,13 +111,17 @@ fn factory() {
102
111
  // This test verifies the full benchmark_granular project compiles and that outerVar
103
112
  // is emitted as the inferred f64 type rather than requiring a Value clone.
104
113
  let manifest = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
105
- let bench = manifest.join("../../tests/core/benchmark_granular.tish").canonicalize().unwrap();
114
+ let bench = manifest
115
+ .join("../../tests/core/benchmark_granular.tish")
116
+ .canonicalize()
117
+ .unwrap();
106
118
  // Use same default features as tish CLI (http, fs, process, regex)
107
119
  let features = ["http", "fs", "process", "regex"]
108
120
  .into_iter()
109
121
  .map(String::from)
110
122
  .collect::<Vec<_>>();
111
- let (rust, _, _) = compile_project_full(&bench, bench.parent(), &features, true).unwrap();
123
+ let (rust, _, _, _) =
124
+ compile_project_full(&bench, bench.parent(), &features, true).unwrap();
112
125
  // outerVar = 42 is inferred as f64; f64 is Copy so no .clone() is emitted.
113
126
  assert!(
114
127
  rust.contains("let mut outerVar: f64"),