@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
@@ -54,29 +54,70 @@ impl RegExpFlags {
54
54
  let mut result = Self::default();
55
55
  for c in flags.chars() {
56
56
  match c {
57
- 'g' => { if result.global { return Err(format!("duplicate flag '{}'", c)); } result.global = true; }
58
- 'i' => { if result.ignore_case { return Err(format!("duplicate flag '{}'", c)); } result.ignore_case = true; }
59
- 'm' => { if result.multiline { return Err(format!("duplicate flag '{}'", c)); } result.multiline = true; }
60
- 's' => { if result.dot_all { return Err(format!("duplicate flag '{}'", c)); } result.dot_all = true; }
61
- 'u' => { if result.unicode { return Err(format!("duplicate flag '{}'", c)); } result.unicode = true; }
62
- 'y' => { if result.sticky { return Err(format!("duplicate flag '{}'", c)); } result.sticky = true; }
57
+ 'g' => {
58
+ if result.global {
59
+ return Err(format!("duplicate flag '{}'", c));
60
+ }
61
+ result.global = true;
62
+ }
63
+ 'i' => {
64
+ if result.ignore_case {
65
+ return Err(format!("duplicate flag '{}'", c));
66
+ }
67
+ result.ignore_case = true;
68
+ }
69
+ 'm' => {
70
+ if result.multiline {
71
+ return Err(format!("duplicate flag '{}'", c));
72
+ }
73
+ result.multiline = true;
74
+ }
75
+ 's' => {
76
+ if result.dot_all {
77
+ return Err(format!("duplicate flag '{}'", c));
78
+ }
79
+ result.dot_all = true;
80
+ }
81
+ 'u' => {
82
+ if result.unicode {
83
+ return Err(format!("duplicate flag '{}'", c));
84
+ }
85
+ result.unicode = true;
86
+ }
87
+ 'y' => {
88
+ if result.sticky {
89
+ return Err(format!("duplicate flag '{}'", c));
90
+ }
91
+ result.sticky = true;
92
+ }
63
93
  _ => return Err(format!("unknown flag '{}'", c)),
64
94
  }
65
95
  }
66
96
  Ok(result)
67
97
  }
68
-
69
98
  }
70
99
 
71
100
  #[cfg(feature = "regex")]
72
101
  impl std::fmt::Display for RegExpFlags {
73
102
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74
- if self.global { f.write_str("g")?; }
75
- if self.ignore_case { f.write_str("i")?; }
76
- if self.multiline { f.write_str("m")?; }
77
- if self.dot_all { f.write_str("s")?; }
78
- if self.unicode { f.write_str("u")?; }
79
- if self.sticky { f.write_str("y")?; }
103
+ if self.global {
104
+ f.write_str("g")?;
105
+ }
106
+ if self.ignore_case {
107
+ f.write_str("i")?;
108
+ }
109
+ if self.multiline {
110
+ f.write_str("m")?;
111
+ }
112
+ if self.dot_all {
113
+ f.write_str("s")?;
114
+ }
115
+ if self.unicode {
116
+ f.write_str("u")?;
117
+ }
118
+ if self.sticky {
119
+ f.write_str("y")?;
120
+ }
80
121
  Ok(())
81
122
  }
82
123
  }
@@ -96,23 +137,36 @@ impl TishRegExp {
96
137
  pub fn new(pattern: &str, flags_str: &str) -> Result<Self, String> {
97
138
  let flags = RegExpFlags::from_string(flags_str)?;
98
139
  let mut regex_pattern = pattern.to_string();
99
-
140
+
100
141
  if flags.ignore_case || flags.multiline || flags.dot_all {
101
142
  let mut flag_prefix = String::from("(?");
102
- if flags.ignore_case { flag_prefix.push('i'); }
103
- if flags.multiline { flag_prefix.push('m'); }
104
- if flags.dot_all { flag_prefix.push('s'); }
143
+ if flags.ignore_case {
144
+ flag_prefix.push('i');
145
+ }
146
+ if flags.multiline {
147
+ flag_prefix.push('m');
148
+ }
149
+ if flags.dot_all {
150
+ flag_prefix.push('s');
151
+ }
105
152
  flag_prefix.push(')');
106
153
  regex_pattern = format!("{}{}", flag_prefix, regex_pattern);
107
154
  }
108
-
109
- let regex = Regex::new(&regex_pattern)
110
- .map_err(|e| format!("Invalid regular expression: {}", e))?;
111
-
112
- Ok(Self { source: pattern.to_string(), flags, regex: Arc::new(regex), last_index: 0 })
155
+
156
+ let regex =
157
+ Regex::new(&regex_pattern).map_err(|e| format!("Invalid regular expression: {}", e))?;
158
+
159
+ Ok(Self {
160
+ source: pattern.to_string(),
161
+ flags,
162
+ regex: Arc::new(regex),
163
+ last_index: 0,
164
+ })
113
165
  }
114
166
 
115
- pub fn flags_string(&self) -> String { self.flags.to_string() }
167
+ pub fn flags_string(&self) -> String {
168
+ self.flags.to_string()
169
+ }
116
170
 
117
171
  pub fn test(&mut self, input: &str) -> bool {
118
172
  if self.flags.global || self.flags.sticky {
@@ -121,10 +175,10 @@ impl TishRegExp {
121
175
  self.last_index = 0;
122
176
  return false;
123
177
  }
124
-
178
+
125
179
  let byte_start: usize = input.chars().take(start).map(|c| c.len_utf8()).sum();
126
180
  let search_str = &input[byte_start..];
127
-
181
+
128
182
  match self.regex.find(search_str) {
129
183
  Ok(Some(m)) => {
130
184
  if self.flags.sticky && m.start() != 0 {
@@ -176,7 +230,12 @@ impl std::fmt::Debug for Value {
176
230
  Value::Object(obj) => write!(f, "Object({:?})", obj.borrow()),
177
231
  Value::Function(_) => write!(f, "Function"),
178
232
  #[cfg(feature = "regex")]
179
- Value::RegExp(re) => write!(f, "RegExp(/{}/{})", re.borrow().source, re.borrow().flags_string()),
233
+ Value::RegExp(re) => write!(
234
+ f,
235
+ "RegExp(/{}/{})",
236
+ re.borrow().source,
237
+ re.borrow().flags_string()
238
+ ),
180
239
  Value::Promise(_) => write!(f, "Promise"),
181
240
  Value::Opaque(o) => write!(f, "{}(opaque)", o.type_name()),
182
241
  }
@@ -202,7 +261,8 @@ impl Value {
202
261
  Value::Bool(b) => b.to_string(),
203
262
  Value::Null => "null".to_string(),
204
263
  Value::Array(arr) => {
205
- let inner: Vec<String> = arr.borrow().iter().map(|v| v.to_display_string()).collect();
264
+ let inner: Vec<String> =
265
+ arr.borrow().iter().map(|v| v.to_display_string()).collect();
206
266
  format!("[{}]", inner.join(", "))
207
267
  }
208
268
  Value::Object(obj) => {
@@ -378,7 +438,11 @@ impl Value {
378
438
  "trim".into(),
379
439
  ]
380
440
  }
381
- Value::Number(_) => vec!["toFixed".into(), "toExponential".into(), "toPrecision".into()],
441
+ Value::Number(_) => vec![
442
+ "toFixed".into(),
443
+ "toExponential".into(),
444
+ "toPrecision".into(),
445
+ ],
382
446
  _ => vec![],
383
447
  }
384
448
  }
@@ -12,9 +12,8 @@ pub fn link_to_binary(
12
12
  output_path: &Path,
13
13
  features: &[String],
14
14
  ) -> Result<(), CraneliftError> {
15
- let workspace_root = tishlang_build_utils::find_workspace_root().map_err(|e| CraneliftError {
16
- message: e,
17
- })?;
15
+ let workspace_root =
16
+ tishlang_build_utils::find_workspace_root().map_err(|e| CraneliftError { message: e })?;
18
17
  let out_name = output_path
19
18
  .file_stem()
20
19
  .and_then(|s| s.to_str())
@@ -104,17 +103,15 @@ fn main() {{
104
103
  message: format!("Cannot write build.rs: {}", e),
105
104
  })?;
106
105
 
107
- tishlang_build_utils::run_cargo_build(&build_dir, None).map_err(|e| CraneliftError { message: e })?;
106
+ tishlang_build_utils::run_cargo_build(&build_dir, None)
107
+ .map_err(|e| CraneliftError { message: e })?;
108
108
 
109
109
  let binary_dir = build_dir.join("target").join("release");
110
- let binary =
111
- tishlang_build_utils::find_release_binary(&binary_dir, out_name)
112
- .map_err(|e| CraneliftError { message: e })?;
110
+ let binary = tishlang_build_utils::find_release_binary(&binary_dir, out_name)
111
+ .map_err(|e| CraneliftError { message: e })?;
113
112
  let target = tishlang_build_utils::resolve_output_path(output_path, out_name);
114
113
  tishlang_build_utils::copy_binary_to_output(&binary, &target)
115
114
  .map_err(|e| CraneliftError { message: e })?;
116
115
 
117
116
  Ok(())
118
117
  }
119
-
120
-
@@ -7,8 +7,8 @@
7
7
 
8
8
  use std::path::Path;
9
9
 
10
- use cranelift::codegen::settings::Configurable;
11
10
  use cranelift::codegen::settings;
11
+ use cranelift::codegen::settings::Configurable;
12
12
  use cranelift_module::{DataDescription, Linkage, Module};
13
13
  use cranelift_object::{ObjectBuilder, ObjectModule};
14
14
 
@@ -18,9 +18,11 @@ use crate::CraneliftError;
18
18
 
19
19
  pub fn lower_and_emit(chunk: &Chunk, object_path: &Path) -> Result<(), CraneliftError> {
20
20
  let mut settings_builder = settings::builder();
21
- settings_builder.set("opt_level", "speed").map_err(|_| CraneliftError {
22
- message: "Failed to set opt_level".to_string(),
23
- })?;
21
+ settings_builder
22
+ .set("opt_level", "speed")
23
+ .map_err(|_| CraneliftError {
24
+ message: "Failed to set opt_level".to_string(),
25
+ })?;
24
26
  let flags = settings::Flags::new(settings_builder);
25
27
 
26
28
  let isa_builder = cranelift_native::builder().map_err(|e| CraneliftError {
@@ -30,10 +32,14 @@ pub fn lower_and_emit(chunk: &Chunk, object_path: &Path) -> Result<(), Cranelift
30
32
  message: format!("Failed to finish ISA: {}", e),
31
33
  })?;
32
34
 
33
- let object_builder = ObjectBuilder::new(isa, "tishlang_cranelift", cranelift_module::default_libcall_names())
34
- .map_err(|e| CraneliftError {
35
- message: format!("Failed to create ObjectBuilder: {}", e),
36
- })?;
35
+ let object_builder = ObjectBuilder::new(
36
+ isa,
37
+ "tishlang_cranelift",
38
+ cranelift_module::default_libcall_names(),
39
+ )
40
+ .map_err(|e| CraneliftError {
41
+ message: format!("Failed to create ObjectBuilder: {}", e),
42
+ })?;
37
43
  let mut module = ObjectModule::new(object_builder);
38
44
 
39
45
  // Serialize chunk and emit as data - link step will build a Rust binary that reads it