@tishlang/tish 1.13.2 → 2.0.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 (106) hide show
  1. package/Cargo.toml +2 -0
  2. package/bin/tish +0 -0
  3. package/crates/js_to_tish/src/transform/expr.rs +1 -0
  4. package/crates/tish/Cargo.toml +11 -3
  5. package/crates/tish/build.rs +21 -0
  6. package/crates/tish/src/cli_help.rs +15 -4
  7. package/crates/tish/src/main.rs +93 -21
  8. package/crates/tish/src/repl_completion.rs +0 -1
  9. package/crates/tish/tests/error_source_location.rs +36 -0
  10. package/crates/tish/tests/fixtures/runtime_error_location.tish +5 -0
  11. package/crates/tish/tests/fixtures/trycatch_runtime_errors.tish +15 -0
  12. package/crates/tish/tests/fixtures/tty_capability.tish +9 -0
  13. package/crates/tish/tests/integration_test.rs +402 -91
  14. package/crates/tish/tests/trycatch_runtime_errors.rs +45 -0
  15. package/crates/tish/tests/tty_capability.rs +43 -0
  16. package/crates/tish_ast/src/ast.rs +37 -8
  17. package/crates/tish_builtins/Cargo.toml +2 -0
  18. package/crates/tish_builtins/src/array.rs +375 -13
  19. package/crates/tish_builtins/src/collections.rs +481 -0
  20. package/crates/tish_builtins/src/construct.rs +59 -19
  21. package/crates/tish_builtins/src/date.rs +538 -0
  22. package/crates/tish_builtins/src/globals.rs +86 -6
  23. package/crates/tish_builtins/src/iterator.rs +129 -0
  24. package/crates/tish_builtins/src/lib.rs +5 -0
  25. package/crates/tish_builtins/src/number.rs +96 -0
  26. package/crates/tish_builtins/src/object.rs +2 -2
  27. package/crates/tish_builtins/src/string.rs +19 -20
  28. package/crates/tish_builtins/src/symbol.rs +1 -1
  29. package/crates/tish_builtins/src/typedarrays.rs +298 -0
  30. package/crates/tish_bytecode/src/chunk.rs +69 -1
  31. package/crates/tish_bytecode/src/compiler.rs +933 -89
  32. package/crates/tish_bytecode/src/encoding.rs +2 -0
  33. package/crates/tish_bytecode/src/lib.rs +2 -1
  34. package/crates/tish_bytecode/src/opcode.rs +47 -4
  35. package/crates/tish_bytecode/src/serialize.rs +31 -1
  36. package/crates/tish_compile/Cargo.toml +1 -0
  37. package/crates/tish_compile/src/check.rs +774 -0
  38. package/crates/tish_compile/src/codegen.rs +2334 -349
  39. package/crates/tish_compile/src/infer.rs +1395 -6
  40. package/crates/tish_compile/src/lib.rs +50 -8
  41. package/crates/tish_compile/src/resolve.rs +584 -21
  42. package/crates/tish_compile/src/types.rs +106 -2
  43. package/crates/tish_compile_js/src/codegen.rs +67 -0
  44. package/crates/tish_compile_js/src/tests_jsx.rs +64 -0
  45. package/crates/tish_core/Cargo.toml +7 -1
  46. package/crates/tish_core/src/console_style.rs +11 -1
  47. package/crates/tish_core/src/json.rs +81 -38
  48. package/crates/tish_core/src/lib.rs +3 -0
  49. package/crates/tish_core/src/shape.rs +85 -0
  50. package/crates/tish_core/src/value.rs +679 -25
  51. package/crates/tish_core/src/vmref.rs +13 -8
  52. package/crates/tish_cranelift/src/link.rs +17 -4
  53. package/crates/tish_cranelift_runtime/Cargo.toml +1 -0
  54. package/crates/tish_eval/Cargo.toml +6 -0
  55. package/crates/tish_eval/src/eval.rs +665 -117
  56. package/crates/tish_eval/src/http.rs +4 -1
  57. package/crates/tish_eval/src/natives.rs +165 -13
  58. package/crates/tish_eval/src/value.rs +31 -13
  59. package/crates/tish_eval/src/value_convert.rs +10 -4
  60. package/crates/tish_ffi/Cargo.toml +26 -0
  61. package/crates/tish_ffi/src/lib.rs +518 -0
  62. package/crates/tish_ffi/tests/fixtures/testmod/Cargo.toml +18 -0
  63. package/crates/tish_ffi/tests/fixtures/testmod/src/lib.rs +46 -0
  64. package/crates/tish_ffi/tests/loader.rs +65 -0
  65. package/crates/tish_fmt/src/lib.rs +43 -5
  66. package/crates/tish_lexer/src/lib.rs +397 -9
  67. package/crates/tish_lexer/src/token.rs +7 -0
  68. package/crates/tish_lint/src/lib.rs +2 -10
  69. package/crates/tish_lsp/src/import_goto.rs +2 -0
  70. package/crates/tish_lsp/src/main.rs +439 -26
  71. package/crates/tish_native/src/build.rs +55 -1
  72. package/crates/tish_opt/src/lib.rs +126 -23
  73. package/crates/tish_parser/src/lib.rs +55 -1
  74. package/crates/tish_parser/src/parser.rs +456 -34
  75. package/crates/tish_pg/src/lib.rs +3 -3
  76. package/crates/tish_resolve/src/lib.rs +99 -59
  77. package/crates/tish_runtime/Cargo.toml +4 -0
  78. package/crates/tish_runtime/src/http.rs +66 -17
  79. package/crates/tish_runtime/src/http_fetch.rs +29 -8
  80. package/crates/tish_runtime/src/http_hyper.rs +25 -2
  81. package/crates/tish_runtime/src/lib.rs +299 -44
  82. package/crates/tish_runtime/src/promise.rs +328 -18
  83. package/crates/tish_runtime/src/timers.rs +13 -7
  84. package/crates/tish_runtime/src/tty.rs +226 -0
  85. package/crates/tish_runtime/src/ws.rs +35 -18
  86. package/crates/tish_runtime/tests/fetch_readable_stream.rs +2 -2
  87. package/crates/tish_ui/src/jsx.rs +10 -0
  88. package/crates/tish_ui/src/runtime/hooks.rs +19 -15
  89. package/crates/tish_ui/src/runtime/mod.rs +15 -12
  90. package/crates/tish_vm/Cargo.toml +14 -1
  91. package/crates/tish_vm/src/jit.rs +1050 -0
  92. package/crates/tish_vm/src/lib.rs +2 -0
  93. package/crates/tish_vm/src/vm.rs +1546 -202
  94. package/crates/tish_vm/tests/concurrent_shared_state.rs +140 -0
  95. package/crates/tish_wasm/src/lib.rs +6 -2
  96. package/crates/tish_wasm_runtime/src/gpu.rs +17 -1
  97. package/crates/tishlang_cargo_bindgen/src/classify.rs +1 -3
  98. package/crates/tishlang_cargo_bindgen/src/lib.rs +2 -2
  99. package/crates/tishlang_cargo_bindgen/src/metadata.rs +1 -1
  100. package/justfile +8 -0
  101. package/package.json +1 -1
  102. package/platform/darwin-arm64/tish +0 -0
  103. package/platform/darwin-x64/tish +0 -0
  104. package/platform/linux-arm64/tish +0 -0
  105. package/platform/linux-x64/tish +0 -0
  106. package/platform/win32-x64/tish.exe +0 -0
@@ -29,6 +29,7 @@ pub fn binop_to_u8(op: BinOp) -> u8 {
29
29
  Shl => 19,
30
30
  Shr => 20,
31
31
  In => 21,
32
+ UShr => 22,
32
33
  }
33
34
  }
34
35
 
@@ -58,6 +59,7 @@ pub fn u8_to_binop(b: u8) -> Option<BinOp> {
58
59
  19 => Shl,
59
60
  20 => Shr,
60
61
  21 => In,
62
+ 22 => UShr,
61
63
  _ => return None,
62
64
  })
63
65
  }
@@ -12,7 +12,8 @@ pub const NO_REST_PARAM: u16 = 0xFFFF;
12
12
 
13
13
  pub use chunk::{Chunk, Constant};
14
14
  pub use compiler::{
15
- compile, compile_for_repl, compile_for_repl_unoptimized, compile_unoptimized, CompileError,
15
+ compile, compile_for_repl, compile_for_repl_unoptimized, compile_unoptimized,
16
+ compile_with_source, CompileError,
16
17
  };
17
18
  pub use encoding::{binop_to_u8, compound_op_to_u8, u8_to_binop, u8_to_unaryop, unaryop_to_u8};
18
19
  pub use opcode::Opcode;
@@ -96,14 +96,51 @@ pub enum Opcode {
96
96
  /// Pop the `await` operand value; if it is a `Promise`, block until settled, push the result,
97
97
  /// or unwind to `catch` like `Throw` on rejection.
98
98
  AwaitPromise = 43,
99
+ /// Load a local variable by frame slot (operand: u16 slot). Fast path: direct
100
+ /// index into the current call frame's locals, no name lookup.
101
+ LoadLocal = 44,
102
+ /// Store top of stack into a local frame slot (operand: u16 slot). Leaves nothing.
103
+ StoreLocal = 45,
104
+ /// Load a captured variable from an enclosing frame (operands: u16 hops, u16 slot).
105
+ /// Walks `hops` parent frames, then indexes `slot`.
106
+ LoadUpvalue = 46,
107
+ /// Store top of stack into an enclosing frame slot (operands: u16 hops, u16 slot).
108
+ StoreUpvalue = 47,
109
+ /// Begin a per-iteration binding region for a loop variable (operand: u16 name index).
110
+ /// Registers the name so closures created in the loop body snapshot it into a fresh overlay
111
+ /// (ES `let` per-iteration semantics); the rest of the frame stays shared. Emitted only when
112
+ /// the loop body creates a closure, so closure-free (hot) loops are untouched.
113
+ LoopVarsBegin = 48,
114
+ /// End the innermost per-iteration binding region (no operand).
115
+ LoopVarsEnd = 49,
116
+ /// Push `Bool(param_index >= argc)` — true when the positional argument at `param_index`
117
+ /// was not supplied by the caller (operand: u16 param index). Emitted by the function
118
+ /// prologue so default parameter values apply only for *missing* args, matching the
119
+ /// interpreter: an explicit `null` argument does NOT trigger the default.
120
+ ArgMissing = 50,
121
+ /// Direct self-recursive call (operand: u16 arg count). Emitted by the compiler ONLY when a
122
+ /// `fn NAME` body calls `NAME(args)` and `NAME` is provably the function itself (not shadowed
123
+ /// by a param/local, not reassigned anywhere in the body). Args are on the stack as for `Call`,
124
+ /// but the callee is implicitly the currently-executing chunk — no name lookup, no closure
125
+ /// dispatch. The numeric JIT lowers this to a native recursive call (the big recursion win);
126
+ /// the VM runs the current chunk directly. Behaviour is identical to `LoadVar NAME; Call argc`.
127
+ SelfCall = 51,
128
+ /// Normalize the top-of-stack iterable for `for…of`: a JS iterator object (one with a
129
+ /// callable `next()` returning `{ value, done }`, e.g. a `Map`/`Set` `.values()` result)
130
+ /// is drained into an array; arrays/strings/anything else pass through unchanged. Emitted
131
+ /// right after the iterable expression so the existing index-based loop can iterate it.
132
+ IterNormalize = 52,
133
+ /// `delete obj[key]` / `delete obj.prop`. Pops `[obj, key]`, removes the property
134
+ /// (objects: drop the key; arrays: set the index to a null hole), pushes `true`.
135
+ DeleteIndex = 53,
99
136
  }
100
137
 
101
138
  impl Opcode {
102
- /// Decode byte to opcode. Safe for b in 0..=43 (matches #[repr(u8)] discriminants).
139
+ /// Decode byte to opcode. Safe for b in 0..=53 (matches #[repr(u8)] discriminants).
103
140
  #[inline]
104
141
  pub fn from_u8(b: u8) -> Option<Opcode> {
105
- if b <= 43 {
106
- Some(unsafe { std::mem::transmute(b) })
142
+ if b <= 53 {
143
+ Some(unsafe { std::mem::transmute::<u8, Opcode>(b) })
107
144
  } else {
108
145
  None
109
146
  }
@@ -127,11 +164,17 @@ impl Opcode {
127
164
  | Opcode::ConstructSpread
128
165
  | Opcode::EnterBlock
129
166
  | Opcode::ExitBlock
167
+ | Opcode::LoopVarsEnd
168
+ | Opcode::IterNormalize
169
+ | Opcode::DeleteIndex
130
170
  | Opcode::AwaitPromise => 1,
131
171
  Opcode::ArraySortByProperty
132
172
  | Opcode::ArrayMapBinOp
133
173
  | Opcode::ArrayFilterBinOp
134
- | Opcode::LoadNativeExport => 5,
174
+ | Opcode::LoadNativeExport
175
+ | Opcode::LoadUpvalue
176
+ | Opcode::StoreUpvalue => 5,
177
+ // LoadLocal / StoreLocal take a single u16 operand → 3 bytes (default).
135
178
  _ => 3,
136
179
  };
137
180
  if ip + size > code.len() {
@@ -48,6 +48,8 @@ pub fn serialize(chunk: &Chunk) -> Vec<u8> {
48
48
  }
49
49
  out.extend_from_slice(&chunk.rest_param_index.to_le_bytes());
50
50
  out.extend_from_slice(&chunk.param_count.to_le_bytes());
51
+ out.extend_from_slice(&chunk.num_slots.to_le_bytes());
52
+ out.push(if chunk.slot_based { 1 } else { 0 });
51
53
  out
52
54
  }
53
55
 
@@ -146,12 +148,34 @@ pub fn deserialize(mut data: &[u8]) -> Result<Chunk, String> {
146
148
  super::NO_REST_PARAM
147
149
  };
148
150
  let param_count = if data.len() >= 2 {
149
- let (p_bytes, _) = data.split_at(2);
151
+ let (p_bytes, rest) = data.split_at(2);
152
+ data = rest;
150
153
  u16::from_le_bytes(p_bytes.try_into().unwrap())
151
154
  } else {
152
155
  0
153
156
  };
157
+ let num_slots = if data.len() >= 2 {
158
+ let (s_bytes, rest) = data.split_at(2);
159
+ data = rest;
160
+ u16::from_le_bytes(s_bytes.try_into().unwrap())
161
+ } else {
162
+ 0
163
+ };
164
+ let slot_based = if !data.is_empty() {
165
+ let b = data[0] != 0;
166
+ data = &data[1..];
167
+ b
168
+ } else {
169
+ false
170
+ };
171
+ let _ = data;
154
172
 
173
+ // Inline caches are a runtime-only cache, not serialized — start empty, sized to `names`.
174
+ let inline_caches = crate::chunk::InlineCaches(
175
+ (0..names.len())
176
+ .map(|_| std::sync::atomic::AtomicU64::new(0))
177
+ .collect(),
178
+ );
155
179
  Ok(Chunk {
156
180
  code,
157
181
  constants,
@@ -159,5 +183,11 @@ pub fn deserialize(mut data: &[u8]) -> Result<Chunk, String> {
159
183
  nested,
160
184
  rest_param_index,
161
185
  param_count,
186
+ num_slots,
187
+ slot_based,
188
+ inline_caches,
189
+ // Debug-only; not part of the serialized format (issue #74).
190
+ lines: Vec::new(),
191
+ source: None,
162
192
  })
163
193
  }
@@ -14,6 +14,7 @@ fs = []
14
14
  process = []
15
15
  regex = []
16
16
  ws = []
17
+ tty = []
17
18
 
18
19
  [dependencies]
19
20
  tishlang_ast = { path = "../tish_ast", version = ">=0.1" }