@tishlang/tish 1.7.0 → 1.9.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 (99) hide show
  1. package/Cargo.toml +2 -0
  2. package/README.md +2 -0
  3. package/bin/tish +0 -0
  4. package/crates/js_to_tish/src/transform/expr.rs +28 -8
  5. package/crates/js_to_tish/src/transform/stmt.rs +49 -22
  6. package/crates/tish/Cargo.toml +14 -5
  7. package/crates/tish/src/cargo_native_registry.rs +29 -0
  8. package/crates/tish/src/cli_help.rs +16 -10
  9. package/crates/tish/src/main.rs +87 -32
  10. package/crates/tish/src/repl_completion.rs +3 -3
  11. package/crates/tish/tests/cargo_example_compile.rs +1 -1
  12. package/crates/tish/tests/integration_test.rs +19 -7
  13. package/crates/tish/tests/shortcircuit.rs +1 -1
  14. package/crates/tish_ast/src/ast.rs +80 -9
  15. package/crates/tish_build_utils/Cargo.toml +4 -0
  16. package/crates/tish_build_utils/src/lib.rs +105 -2
  17. package/crates/tish_builtins/Cargo.toml +5 -1
  18. package/crates/tish_builtins/src/array.rs +13 -12
  19. package/crates/tish_builtins/src/construct.rs +34 -33
  20. package/crates/tish_builtins/src/globals.rs +12 -11
  21. package/crates/tish_builtins/src/helpers.rs +2 -1
  22. package/crates/tish_builtins/src/object.rs +3 -2
  23. package/crates/tish_builtins/src/string.rs +73 -3
  24. package/crates/tish_bytecode/src/compiler.rs +12 -14
  25. package/crates/tish_bytecode/src/opcode.rs +12 -3
  26. package/crates/tish_compile/Cargo.toml +1 -0
  27. package/crates/tish_compile/src/codegen.rs +745 -199
  28. package/crates/tish_compile/src/infer.rs +6 -0
  29. package/crates/tish_compile/src/lib.rs +4 -3
  30. package/crates/tish_compile/src/resolve.rs +180 -82
  31. package/crates/tish_compile/src/types.rs +175 -11
  32. package/crates/tish_compile_js/Cargo.toml +1 -0
  33. package/crates/tish_compile_js/src/codegen.rs +152 -29
  34. package/crates/tish_compile_js/src/lib.rs +3 -1
  35. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +31 -12
  36. package/crates/tish_core/Cargo.toml +8 -0
  37. package/crates/tish_core/src/json.rs +102 -53
  38. package/crates/tish_core/src/lib.rs +3 -1
  39. package/crates/tish_core/src/macros.rs +5 -5
  40. package/crates/tish_core/src/value.rs +53 -15
  41. package/crates/tish_core/src/vmref.rs +178 -0
  42. package/crates/tish_eval/Cargo.toml +17 -2
  43. package/crates/tish_eval/src/eval.rs +90 -28
  44. package/crates/tish_eval/src/http.rs +61 -0
  45. package/crates/tish_eval/src/lib.rs +3 -3
  46. package/crates/tish_eval/src/natives.rs +41 -0
  47. package/crates/tish_eval/src/value.rs +7 -3
  48. package/crates/tish_eval/src/value_convert.rs +13 -5
  49. package/crates/tish_fmt/src/lib.rs +120 -30
  50. package/crates/tish_lexer/src/lib.rs +20 -5
  51. package/crates/tish_lexer/src/token.rs +4 -0
  52. package/crates/tish_llvm/src/lib.rs +3 -1
  53. package/crates/tish_lsp/Cargo.toml +4 -1
  54. package/crates/tish_lsp/README.md +1 -1
  55. package/crates/tish_lsp/src/builtin_goto.rs +261 -0
  56. package/crates/tish_lsp/src/import_goto.rs +549 -0
  57. package/crates/tish_lsp/src/main.rs +502 -102
  58. package/crates/tish_native/src/build.rs +3 -2
  59. package/crates/tish_native/src/lib.rs +6 -2
  60. package/crates/tish_opt/src/lib.rs +17 -2
  61. package/crates/tish_parser/src/lib.rs +10 -3
  62. package/crates/tish_parser/src/parser.rs +346 -56
  63. package/crates/tish_pg/Cargo.toml +34 -0
  64. package/crates/tish_pg/README.md +38 -0
  65. package/crates/tish_pg/src/error.rs +52 -0
  66. package/crates/tish_pg/src/lib.rs +967 -0
  67. package/crates/tish_resolve/Cargo.toml +13 -0
  68. package/crates/tish_resolve/src/lib.rs +3436 -0
  69. package/crates/tish_resolve/src/pos.rs +133 -0
  70. package/crates/tish_runtime/Cargo.toml +68 -3
  71. package/crates/tish_runtime/src/http.rs +1123 -141
  72. package/crates/tish_runtime/src/http_fetch.rs +15 -14
  73. package/crates/tish_runtime/src/http_hyper.rs +418 -0
  74. package/crates/tish_runtime/src/http_prefork.rs +189 -0
  75. package/crates/tish_runtime/src/lib.rs +159 -29
  76. package/crates/tish_runtime/src/promise.rs +199 -36
  77. package/crates/tish_runtime/src/promise_io.rs +2 -1
  78. package/crates/tish_runtime/src/timers.rs +37 -1
  79. package/crates/tish_runtime/src/ws.rs +26 -28
  80. package/crates/tish_ui/src/jsx.rs +279 -8
  81. package/crates/tish_ui/src/lib.rs +5 -2
  82. package/crates/tish_ui/src/runtime/hooks.rs +406 -45
  83. package/crates/tish_ui/src/runtime/mod.rs +36 -9
  84. package/crates/tish_vm/Cargo.toml +15 -5
  85. package/crates/tish_vm/src/vm.rs +506 -259
  86. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +3 -1
  87. package/crates/tish_wasm/src/lib.rs +17 -14
  88. package/crates/tish_wasm_runtime/Cargo.toml +2 -1
  89. package/crates/tish_wasm_runtime/src/lib.rs +1 -1
  90. package/crates/tishlang_cargo_bindgen/Cargo.toml +1 -0
  91. package/crates/tishlang_cargo_bindgen/src/discover.rs +68 -0
  92. package/crates/tishlang_cargo_bindgen/src/lib.rs +5 -4
  93. package/justfile +8 -0
  94. package/package.json +1 -1
  95. package/platform/darwin-arm64/tish +0 -0
  96. package/platform/darwin-x64/tish +0 -0
  97. package/platform/linux-arm64/tish +0 -0
  98. package/platform/linux-x64/tish +0 -0
  99. package/platform/win32-x64/tish.exe +0 -0
@@ -0,0 +1,133 @@
1
+ //! Map LSP (UTF-16) positions to lexer [`Span`] corners (1-based line, 1-based **character** column).
2
+
3
+ use tishlang_ast::Span;
4
+
5
+ /// Byte offset in `source` for LSP `Position` (0-based line, UTF-16 code unit column).
6
+ pub fn lsp_position_to_byte_offset(source: &str, line: u32, character: u32) -> Option<usize> {
7
+ let mut cur_line: u32 = 0;
8
+ let mut col_utf16: u32 = 0;
9
+ for (i, ch) in source.char_indices() {
10
+ if cur_line == line && col_utf16 == character {
11
+ return Some(i);
12
+ }
13
+ if ch == '\n' {
14
+ if cur_line == line {
15
+ return Some(i);
16
+ }
17
+ cur_line += 1;
18
+ col_utf16 = 0;
19
+ } else if cur_line == line {
20
+ col_utf16 = col_utf16.saturating_add(ch.len_utf16() as u32);
21
+ }
22
+ }
23
+ if cur_line == line && col_utf16 == character {
24
+ Some(source.len())
25
+ } else {
26
+ None
27
+ }
28
+ }
29
+
30
+ fn line_byte_start(source: &str, line1: usize) -> Option<usize> {
31
+ if line1 == 0 {
32
+ return None;
33
+ }
34
+ if line1 == 1 {
35
+ return Some(0);
36
+ }
37
+ let mut line = 1usize;
38
+ let mut offset = 0usize;
39
+ for ch in source.chars() {
40
+ offset += ch.len_utf8();
41
+ if ch == '\n' {
42
+ line += 1;
43
+ if line == line1 {
44
+ return Some(offset);
45
+ }
46
+ }
47
+ }
48
+ None
49
+ }
50
+
51
+ /// Byte offset for lexer (1-based line, 1-based char column) — first character of that cell.
52
+ pub fn lex_corner_to_byte_offset(source: &str, line1: usize, col1: usize) -> Option<usize> {
53
+ let line_str = source.lines().nth(line1.checked_sub(1)?)?;
54
+ let base = line_byte_start(source, line1)?;
55
+ let mut pos = base;
56
+ let mut c = 1usize;
57
+ for ch in line_str.chars() {
58
+ if c == col1 {
59
+ return Some(pos);
60
+ }
61
+ c += 1;
62
+ pos += ch.len_utf8();
63
+ }
64
+ if c == col1 {
65
+ Some(pos)
66
+ } else {
67
+ None
68
+ }
69
+ }
70
+
71
+ /// Half-open byte range `[start, end)` for lexer span corners.
72
+ pub fn lex_span_byte_range(source: &str, span: &Span) -> Option<(usize, usize)> {
73
+ let start = lex_corner_to_byte_offset(source, span.start.0, span.start.1)?;
74
+ let end = lex_corner_to_byte_offset(source, span.end.0, span.end.1).unwrap_or(start);
75
+ let end = end.max(start);
76
+ Some((start, end))
77
+ }
78
+
79
+ /// LSP `(line, character)` for the lexer corner `span.start` (first character of the span).
80
+ pub fn lsp_position_for_span_start(source: &str, span: &Span) -> Option<(u32, u32)> {
81
+ let b = lex_corner_to_byte_offset(source, span.start.0, span.start.1)?;
82
+ byte_offset_to_lsp(source, b)
83
+ }
84
+
85
+ pub fn byte_offset_to_lsp(source: &str, byte: usize) -> Option<(u32, u32)> {
86
+ let mut line = 0u32;
87
+ let mut utf16 = 0u32;
88
+ for (i, ch) in source.char_indices() {
89
+ if i == byte {
90
+ return Some((line, utf16));
91
+ }
92
+ if ch == '\n' {
93
+ line += 1;
94
+ utf16 = 0;
95
+ } else {
96
+ utf16 += ch.len_utf16() as u32;
97
+ }
98
+ }
99
+ if byte == source.len() {
100
+ Some((line, utf16))
101
+ } else {
102
+ None
103
+ }
104
+ }
105
+
106
+ /// True if LSP position lies inside `span` (half-open in byte space).
107
+ pub fn span_contains_lsp_position(source: &str, span: &Span, lsp_line: u32, lsp_character: u32) -> bool {
108
+ let Some(b) = lsp_position_to_byte_offset(source, lsp_line, lsp_character) else {
109
+ return false;
110
+ };
111
+ let Some((lo, hi)) = lex_span_byte_range(source, span) else {
112
+ return false;
113
+ };
114
+ b >= lo && b < hi
115
+ }
116
+
117
+ /// LSP start (inclusive) and end (exclusive) positions for a lexer span.
118
+ pub fn span_to_lsp_range_exclusive(source: &str, span: &Span) -> Option<((u32, u32), (u32, u32))> {
119
+ let (lo, hi) = lex_span_byte_range(source, span)?;
120
+ Some((byte_offset_to_lsp(source, lo)?, byte_offset_to_lsp(source, hi)?))
121
+ }
122
+
123
+ #[cfg(test)]
124
+ mod tests {
125
+ use super::*;
126
+
127
+ #[test]
128
+ fn lsp_first_char() {
129
+ let s = "let x = 1\n";
130
+ assert_eq!(lsp_position_to_byte_offset(s, 0, 0), Some(0));
131
+ assert_eq!(lsp_position_to_byte_offset(s, 0, 4), Some(4));
132
+ }
133
+ }
@@ -8,12 +8,67 @@ license-file = { workspace = true }
8
8
  repository = { workspace = true }
9
9
  [features]
10
10
  default = []
11
- http = ["tokio", "reqwest", "futures", "bytes", "tiny_http", "tishlang_core/regex"]
11
+ http = [
12
+ "dep:tokio",
13
+ "dep:reqwest",
14
+ "dep:futures",
15
+ "dep:bytes",
16
+ "dep:tiny_http",
17
+ "dep:socket2",
18
+ "dep:libc",
19
+ "dep:arc-swap",
20
+ "tishlang_core/regex",
21
+ # `serve(port, handler)` dispatches handler closures across worker
22
+ # threads (or subprocesses, in prefork mode). Both require `Value: Send`.
23
+ "tishlang_core/send-values",
24
+ "tishlang_builtins/send-values",
25
+ "send-values",
26
+ ]
27
+ # Enables `Arc`/`Mutex` values in `tishlang_core` so `Value: Send + Sync`.
28
+ # Used by `http` / `ws` and by dependents (e.g. `tish-callbacks`) that keep
29
+ # `Value` in a `static` registry and dispatch from multi-threaded async libs.
30
+ send-values = [
31
+ "tishlang_core/send-values",
32
+ "tishlang_builtins/send-values",
33
+ ]
34
+ # Phase-3 item 13: io_uring-backed accept + send loop (Linux only).
35
+ # Disabled by default; enable with `--feature http,http-io-uring` on Linux
36
+ # to pick up the experimental accept path.
37
+ http-io-uring = ["http"]
38
+ # hyper-based HTTP backend: async single-threaded tokio runtime per core, no
39
+ # per-connection OS threads. Unblocks the tiny_http thread-churn ceiling on
40
+ # macOS loopback (~140k RPS) and enables HTTP/2. Opt-in via the
41
+ # `TISH_HTTP_BACKEND=hyper` env var at runtime when the feature is compiled in.
42
+ http-hyper = [
43
+ "http",
44
+ "dep:hyper",
45
+ "dep:hyper-util",
46
+ "dep:http-body-util",
47
+ "dep:http",
48
+ "dep:pin-project-lite",
49
+ "dep:core_affinity",
50
+ "tokio/net",
51
+ "tokio/rt",
52
+ "tokio/io-util",
53
+ ]
12
54
  fs = []
13
55
  process = []
14
56
  regex = ["tishlang_core/regex"]
15
- # WebSocket (JS-like API). Modular: import { WebSocket, Server } from 'tish:ws'
16
- ws = ["tokio", "tokio/net", "tokio/io-util", "tokio-tungstenite", "futures-util", "lazy_static"]
57
+ # WebSocket (JS-like API). Modular: import { WebSocket, Server } from 'tish:ws'.
58
+ # Requires `send-values` because the WS server keeps an `Arc<dyn Fn + Send +
59
+ # Sync>`-typed listener closure that captures `VmRef`s; under `Rc<RefCell>`
60
+ # those captures aren't `Send` and the closure won't satisfy `NativeFn`.
61
+ ws = [
62
+ "dep:tokio",
63
+ "tokio/net",
64
+ "tokio/io-util",
65
+ "dep:tokio-tungstenite",
66
+ "dep:futures-util",
67
+ "dep:lazy_static",
68
+ "send-values",
69
+ "tishlang_core/send-values",
70
+ "tishlang_builtins/send-values",
71
+ ]
17
72
 
18
73
  [dependencies]
19
74
  tishlang_core = { path = "../tish_core", version = ">=0.1" }
@@ -23,6 +78,16 @@ reqwest = { version = "0.13.2", default-features = false, features = ["rustls",
23
78
  futures = { version = "0.3.32", optional = true }
24
79
  bytes = { version = "1", optional = true }
25
80
  tiny_http = { version = "0.12.0", optional = true }
81
+ socket2 = { version = "0.5", features = ["all"], optional = true }
82
+ libc = { version = "0.2", optional = true }
83
+ arc-swap = { version = "1", optional = true }
84
+ # hyper backend (feature = http-hyper)
85
+ hyper = { version = "1", default-features = false, features = ["server", "http1", "http2"], optional = true }
86
+ hyper-util = { version = "0.1", features = ["server", "tokio"], optional = true }
87
+ http-body-util = { version = "0.1", optional = true }
88
+ http = { version = "1", optional = true }
89
+ pin-project-lite = { version = "0.2", optional = true }
90
+ core_affinity = { version = "0.8", optional = true }
26
91
  tokio-tungstenite = { version = "0.29", optional = true }
27
92
  futures-util = { version = "0.3", optional = true }
28
93
  lazy_static = { version = "1", optional = true }