@tishlang/tish 1.6.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 (79) 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 +3 -1
  10. package/crates/tish/tests/integration_test.rs +197 -47
  11. package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
  12. package/crates/tish/tests/shortcircuit.rs +19 -4
  13. package/crates/tish_ast/src/ast.rs +12 -14
  14. package/crates/tish_build_utils/src/lib.rs +31 -6
  15. package/crates/tish_builtins/src/array.rs +52 -21
  16. package/crates/tish_builtins/src/construct.rs +2 -8
  17. package/crates/tish_builtins/src/globals.rs +30 -15
  18. package/crates/tish_builtins/src/lib.rs +5 -5
  19. package/crates/tish_builtins/src/math.rs +5 -3
  20. package/crates/tish_builtins/src/string.rs +71 -19
  21. package/crates/tish_bytecode/src/chunk.rs +0 -1
  22. package/crates/tish_bytecode/src/compiler.rs +164 -60
  23. package/crates/tish_bytecode/src/opcode.rs +13 -4
  24. package/crates/tish_bytecode/src/peephole.rs +2 -2
  25. package/crates/tish_compile/src/codegen.rs +921 -299
  26. package/crates/tish_compile/src/infer.rs +69 -19
  27. package/crates/tish_compile/src/lib.rs +15 -5
  28. package/crates/tish_compile/src/resolve.rs +112 -69
  29. package/crates/tish_compile/src/types.rs +10 -14
  30. package/crates/tish_compile_js/src/codegen.rs +34 -13
  31. package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
  32. package/crates/tish_compiler_wasm/src/lib.rs +16 -13
  33. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +39 -48
  34. package/crates/tish_core/src/json.rs +5 -3
  35. package/crates/tish_core/src/lib.rs +1 -1
  36. package/crates/tish_core/src/uri.rs +9 -6
  37. package/crates/tish_core/src/value.rs +92 -28
  38. package/crates/tish_cranelift/src/link.rs +6 -9
  39. package/crates/tish_cranelift/src/lower.rs +14 -8
  40. package/crates/tish_eval/src/eval.rs +389 -142
  41. package/crates/tish_eval/src/lib.rs +10 -6
  42. package/crates/tish_eval/src/natives.rs +95 -38
  43. package/crates/tish_eval/src/promise.rs +14 -8
  44. package/crates/tish_eval/src/timers.rs +28 -19
  45. package/crates/tish_eval/src/value.rs +10 -3
  46. package/crates/tish_fmt/src/lib.rs +29 -13
  47. package/crates/tish_lexer/src/lib.rs +217 -63
  48. package/crates/tish_lexer/src/token.rs +6 -6
  49. package/crates/tish_llvm/src/lib.rs +15 -8
  50. package/crates/tish_lsp/src/main.rs +41 -43
  51. package/crates/tish_native/src/build.rs +1 -6
  52. package/crates/tish_native/src/lib.rs +48 -19
  53. package/crates/tish_opt/src/lib.rs +67 -50
  54. package/crates/tish_parser/src/lib.rs +36 -11
  55. package/crates/tish_parser/src/parser.rs +172 -87
  56. package/crates/tish_runtime/src/http.rs +15 -6
  57. package/crates/tish_runtime/src/http_fetch.rs +24 -14
  58. package/crates/tish_runtime/src/lib.rs +224 -168
  59. package/crates/tish_runtime/src/promise.rs +1 -5
  60. package/crates/tish_runtime/src/ws.rs +45 -20
  61. package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
  62. package/crates/tish_ui/src/jsx.rs +41 -22
  63. package/crates/tish_ui/src/lib.rs +2 -2
  64. package/crates/tish_vm/src/vm.rs +309 -112
  65. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
  66. package/crates/tish_wasm/src/lib.rs +38 -28
  67. package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
  68. package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
  69. package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
  70. package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
  71. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  72. package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
  73. package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
  74. package/package.json +1 -1
  75. package/platform/darwin-arm64/tish +0 -0
  76. package/platform/darwin-x64/tish +0 -0
  77. package/platform/linux-arm64/tish +0 -0
  78. package/platform/linux-x64/tish +0 -0
  79. package/platform/win32-x64/tish.exe +0 -0
@@ -5,9 +5,9 @@
5
5
 
6
6
  #[cfg(feature = "regex")]
7
7
  use std::cell::RefCell;
8
+ use std::fmt;
8
9
  #[cfg(feature = "regex")]
9
10
  use std::rc::Rc;
10
- use std::fmt;
11
11
  use std::sync::OnceLock;
12
12
  use tishlang_builtins::helpers::extract_num;
13
13
  #[cfg(feature = "fs")]
@@ -17,77 +17,70 @@ pub use tishlang_core::ObjectMap;
17
17
  pub use tishlang_core::Value;
18
18
 
19
19
  pub use tishlang_builtins::construct::{
20
- audio_context_constructor_value as tish_audio_context_constructor,
21
- construct as tish_construct,
20
+ audio_context_constructor_value as tish_audio_context_constructor, construct as tish_construct,
22
21
  uint8_array_constructor_value as tish_uint8_array_constructor,
23
22
  };
24
23
 
25
24
  // Re-export array methods from tishlang_builtins
26
25
  pub use tishlang_builtins::array::{
27
- push as array_push_impl,
28
- pop as array_pop,
29
- shift as array_shift,
30
- unshift as array_unshift_impl,
31
- index_of as array_index_of_impl,
32
- includes as array_includes_impl,
33
- join as array_join_impl,
34
- reverse as array_reverse,
35
- shuffle as array_shuffle,
36
- splice as array_splice_impl,
37
- slice as array_slice_impl,
38
- concat as array_concat_impl,
39
- flat as array_flat_impl,
40
- map as array_map,
41
- filter as array_filter,
42
- reduce as array_reduce,
43
- for_each as array_for_each,
44
- find as array_find,
45
- find_index as array_find_index,
46
- some as array_some,
47
- every as array_every,
48
- flat_map as array_flat_map,
49
- sort_default as array_sort_default,
50
- sort_with_comparator as array_sort_with_comparator,
51
- sort_numeric_asc as array_sort_numeric_asc,
26
+ concat as array_concat_impl, every as array_every, filter as array_filter, find as array_find,
27
+ find_index as array_find_index, flat as array_flat_impl, flat_map as array_flat_map,
28
+ for_each as array_for_each, includes as array_includes_impl, index_of as array_index_of_impl,
29
+ join as array_join_impl, map as array_map, pop as array_pop, push as array_push_impl,
30
+ reduce as array_reduce, reverse as array_reverse, shift as array_shift,
31
+ shuffle as array_shuffle, slice as array_slice_impl, some as array_some,
32
+ sort_default as array_sort_default, sort_numeric_asc as array_sort_numeric_asc,
52
33
  sort_numeric_desc as array_sort_numeric_desc,
34
+ sort_with_comparator as array_sort_with_comparator, splice as array_splice_impl,
35
+ unshift as array_unshift_impl,
53
36
  };
54
37
 
55
38
  // Re-export string methods from tishlang_builtins
56
39
  pub use tishlang_builtins::string::{
57
- index_of as string_index_of_impl,
58
- includes as string_includes_impl,
59
- slice as string_slice_impl,
60
- substring as string_substring_impl,
61
- split as string_split_impl,
40
+ char_at as string_char_at_impl, char_code_at as string_char_code_at_impl,
41
+ ends_with as string_ends_with_impl, includes as string_includes_impl,
42
+ index_of as string_index_of_impl, last_index_of as string_last_index_of_impl,
43
+ pad_end as string_pad_end_impl, pad_start as string_pad_start_impl,
44
+ repeat as string_repeat_impl, replace as string_replace_impl,
45
+ replace_all as string_replace_all_impl, slice as string_slice_impl, split as string_split_impl,
46
+ starts_with as string_starts_with_impl, substring as string_substring_impl,
47
+ to_lower_case as string_to_lower_case, to_upper_case as string_to_upper_case,
62
48
  trim as string_trim,
63
- to_upper_case as string_to_upper_case,
64
- to_lower_case as string_to_lower_case,
65
- starts_with as string_starts_with_impl,
66
- ends_with as string_ends_with_impl,
67
- replace as string_replace_impl,
68
- replace_all as string_replace_all_impl,
69
- char_at as string_char_at_impl,
70
- char_code_at as string_char_code_at_impl,
71
- repeat as string_repeat_impl,
72
- pad_start as string_pad_start_impl,
73
- pad_end as string_pad_end_impl,
74
- last_index_of as string_last_index_of_impl,
75
49
  };
76
50
 
77
51
  // Wrapper functions to maintain API compatibility
78
- pub fn array_push(arr: &Value, args: &[Value]) -> Value { array_push_impl(arr, args) }
79
- pub fn array_unshift(arr: &Value, args: &[Value]) -> Value { array_unshift_impl(arr, args) }
80
- pub fn array_index_of(arr: &Value, search: &Value) -> Value { array_index_of_impl(arr, search) }
52
+ pub fn array_push(arr: &Value, args: &[Value]) -> Value {
53
+ array_push_impl(arr, args)
54
+ }
55
+ pub fn array_unshift(arr: &Value, args: &[Value]) -> Value {
56
+ array_unshift_impl(arr, args)
57
+ }
58
+ pub fn array_index_of(arr: &Value, search: &Value) -> Value {
59
+ array_index_of_impl(arr, search)
60
+ }
81
61
  pub fn array_includes(arr: &Value, search: &Value, from: &Value) -> Value {
82
62
  array_includes_impl(arr, search, Some(from))
83
63
  }
84
- pub fn array_join(arr: &Value, sep: &Value) -> Value { array_join_impl(arr, sep) }
85
- pub fn array_splice(arr: &Value, start: &Value, delete_count: Option<&Value>, items: &[Value]) -> Value {
64
+ pub fn array_join(arr: &Value, sep: &Value) -> Value {
65
+ array_join_impl(arr, sep)
66
+ }
67
+ pub fn array_splice(
68
+ arr: &Value,
69
+ start: &Value,
70
+ delete_count: Option<&Value>,
71
+ items: &[Value],
72
+ ) -> Value {
86
73
  array_splice_impl(arr, start, delete_count, items)
87
74
  }
88
- pub fn array_slice(arr: &Value, start: &Value, end: &Value) -> Value { array_slice_impl(arr, start, end) }
89
- pub fn array_concat(arr: &Value, args: &[Value]) -> Value { array_concat_impl(arr, args) }
90
- pub fn array_flat(arr: &Value, depth: &Value) -> Value { array_flat_impl(arr, depth) }
75
+ pub fn array_slice(arr: &Value, start: &Value, end: &Value) -> Value {
76
+ array_slice_impl(arr, start, end)
77
+ }
78
+ pub fn array_concat(arr: &Value, args: &[Value]) -> Value {
79
+ array_concat_impl(arr, args)
80
+ }
81
+ pub fn array_flat(arr: &Value, depth: &Value) -> Value {
82
+ array_flat_impl(arr, depth)
83
+ }
91
84
 
92
85
  pub fn array_sort(arr: &Value, comparator: Option<&Value>) -> Value {
93
86
  match comparator {
@@ -102,11 +95,21 @@ pub fn string_index_of(s: &Value, search: &Value, from: &Value) -> Value {
102
95
  pub fn string_includes(s: &Value, search: &Value, from: &Value) -> Value {
103
96
  string_includes_impl(s, search, Some(from))
104
97
  }
105
- pub fn string_slice(s: &Value, start: &Value, end: &Value) -> Value { string_slice_impl(s, start, end) }
106
- pub fn string_substring(s: &Value, start: &Value, end: &Value) -> Value { string_substring_impl(s, start, end) }
107
- pub fn string_split(s: &Value, sep: &Value) -> Value { string_split_impl(s, sep) }
108
- pub fn string_starts_with(s: &Value, search: &Value) -> Value { string_starts_with_impl(s, search) }
109
- pub fn string_ends_with(s: &Value, search: &Value) -> Value { string_ends_with_impl(s, search) }
98
+ pub fn string_slice(s: &Value, start: &Value, end: &Value) -> Value {
99
+ string_slice_impl(s, start, end)
100
+ }
101
+ pub fn string_substring(s: &Value, start: &Value, end: &Value) -> Value {
102
+ string_substring_impl(s, start, end)
103
+ }
104
+ pub fn string_split(s: &Value, sep: &Value) -> Value {
105
+ string_split_impl(s, sep)
106
+ }
107
+ pub fn string_starts_with(s: &Value, search: &Value) -> Value {
108
+ string_starts_with_impl(s, search)
109
+ }
110
+ pub fn string_ends_with(s: &Value, search: &Value) -> Value {
111
+ string_ends_with_impl(s, search)
112
+ }
110
113
  pub fn string_replace(s: &Value, search: &Value, replacement: &Value) -> Value {
111
114
  #[cfg(feature = "regex")]
112
115
  if matches!(search, Value::RegExp(_)) {
@@ -114,12 +117,24 @@ pub fn string_replace(s: &Value, search: &Value, replacement: &Value) -> Value {
114
117
  }
115
118
  string_replace_impl(s, search, replacement)
116
119
  }
117
- pub fn string_replace_all(s: &Value, search: &Value, replacement: &Value) -> Value { string_replace_all_impl(s, search, replacement) }
118
- pub fn string_char_at(s: &Value, idx: &Value) -> Value { string_char_at_impl(s, idx) }
119
- pub fn string_char_code_at(s: &Value, idx: &Value) -> Value { string_char_code_at_impl(s, idx) }
120
- pub fn string_repeat(s: &Value, count: &Value) -> Value { string_repeat_impl(s, count) }
121
- pub fn string_pad_start(s: &Value, target_len: &Value, pad: &Value) -> Value { string_pad_start_impl(s, target_len, pad) }
122
- pub fn string_pad_end(s: &Value, target_len: &Value, pad: &Value) -> Value { string_pad_end_impl(s, target_len, pad) }
120
+ pub fn string_replace_all(s: &Value, search: &Value, replacement: &Value) -> Value {
121
+ string_replace_all_impl(s, search, replacement)
122
+ }
123
+ pub fn string_char_at(s: &Value, idx: &Value) -> Value {
124
+ string_char_at_impl(s, idx)
125
+ }
126
+ pub fn string_char_code_at(s: &Value, idx: &Value) -> Value {
127
+ string_char_code_at_impl(s, idx)
128
+ }
129
+ pub fn string_repeat(s: &Value, count: &Value) -> Value {
130
+ string_repeat_impl(s, count)
131
+ }
132
+ pub fn string_pad_start(s: &Value, target_len: &Value, pad: &Value) -> Value {
133
+ string_pad_start_impl(s, target_len, pad)
134
+ }
135
+ pub fn string_pad_end(s: &Value, target_len: &Value, pad: &Value) -> Value {
136
+ string_pad_end_impl(s, target_len, pad)
137
+ }
123
138
  pub fn string_last_index_of(s: &Value, search: &Value, position: &Value) -> Value {
124
139
  string_last_index_of_impl(s, search, position)
125
140
  }
@@ -244,23 +259,15 @@ pub mod ops {
244
259
  }
245
260
 
246
261
  use tishlang_builtins::globals::{
247
- array_is_array as builtins_array_is_array,
248
- boolean as builtins_boolean,
249
- decode_uri as builtins_decode_uri,
250
- encode_uri as builtins_encode_uri,
251
- is_finite as builtins_is_finite,
252
- is_nan as builtins_is_nan,
253
- object_assign as builtins_object_assign,
254
- object_entries as builtins_object_entries,
255
- object_from_entries as builtins_object_from_entries,
256
- object_keys as builtins_object_keys,
262
+ array_is_array as builtins_array_is_array, boolean as builtins_boolean,
263
+ decode_uri as builtins_decode_uri, encode_uri as builtins_encode_uri,
264
+ is_finite as builtins_is_finite, is_nan as builtins_is_nan,
265
+ object_assign as builtins_object_assign, object_entries as builtins_object_entries,
266
+ object_from_entries as builtins_object_from_entries, object_keys as builtins_object_keys,
257
267
  object_values as builtins_object_values,
258
268
  string_from_char_code as builtins_string_from_char_code,
259
269
  };
260
- use tishlang_core::{
261
- json_parse as core_json_parse,
262
- json_stringify as core_json_stringify,
263
- };
270
+ use tishlang_core::{json_parse as core_json_parse, json_stringify as core_json_stringify};
264
271
 
265
272
  /// Error type for Tish throw/catch.
266
273
  #[derive(Debug, Clone)]
@@ -290,14 +297,12 @@ enum LogLevel {
290
297
  static LOG_LEVEL: OnceLock<LogLevel> = OnceLock::new();
291
298
 
292
299
  fn get_log_level() -> LogLevel {
293
- *LOG_LEVEL.get_or_init(|| {
294
- match std::env::var("TISH_LOG_LEVEL").as_deref() {
295
- Ok("debug") => LogLevel::Debug,
296
- Ok("info") => LogLevel::Info,
297
- Ok("warn") => LogLevel::Warn,
298
- Ok("error") => LogLevel::Error,
299
- _ => LogLevel::Log,
300
- }
300
+ *LOG_LEVEL.get_or_init(|| match std::env::var("TISH_LOG_LEVEL").as_deref() {
301
+ Ok("debug") => LogLevel::Debug,
302
+ Ok("info") => LogLevel::Info,
303
+ Ok("warn") => LogLevel::Warn,
304
+ Ok("error") => LogLevel::Error,
305
+ _ => LogLevel::Log,
301
306
  })
302
307
  }
303
308
 
@@ -363,39 +368,59 @@ pub fn encode_uri(args: &[Value]) -> Value {
363
368
 
364
369
  // Math functions - use tishlang_builtins::math
365
370
  pub use tishlang_builtins::math::{
366
- abs as tish_math_abs_impl,
367
- sqrt as tish_math_sqrt_impl,
368
- floor as tish_math_floor_impl,
369
- ceil as tish_math_ceil_impl,
370
- round as tish_math_round_impl,
371
- sin as tish_math_sin_impl,
372
- cos as tish_math_cos_impl,
373
- tan as tish_math_tan_impl,
374
- exp as tish_math_exp_impl,
375
- trunc as tish_math_trunc_impl,
376
- min as tish_math_min_impl,
377
- max as tish_math_max_impl,
378
- pow as tish_math_pow_impl,
379
- sign as tish_math_sign_impl,
380
- random as tish_math_random_impl,
371
+ abs as tish_math_abs_impl, ceil as tish_math_ceil_impl, cos as tish_math_cos_impl,
372
+ exp as tish_math_exp_impl, floor as tish_math_floor_impl, max as tish_math_max_impl,
373
+ min as tish_math_min_impl, pow as tish_math_pow_impl, random as tish_math_random_impl,
374
+ round as tish_math_round_impl, sign as tish_math_sign_impl, sin as tish_math_sin_impl,
375
+ sqrt as tish_math_sqrt_impl, tan as tish_math_tan_impl, trunc as tish_math_trunc_impl,
381
376
  };
382
377
 
383
378
  // Wrapper functions to maintain API (existing callers use math_* naming)
384
- pub fn math_abs(args: &[Value]) -> Value { tish_math_abs_impl(args) }
385
- pub fn math_sqrt(args: &[Value]) -> Value { tish_math_sqrt_impl(args) }
386
- pub fn math_floor(args: &[Value]) -> Value { tish_math_floor_impl(args) }
387
- pub fn math_ceil(args: &[Value]) -> Value { tish_math_ceil_impl(args) }
388
- pub fn math_round(args: &[Value]) -> Value { tish_math_round_impl(args) }
389
- pub fn math_min(args: &[Value]) -> Value { tish_math_min_impl(args) }
390
- pub fn math_max(args: &[Value]) -> Value { tish_math_max_impl(args) }
391
- pub fn math_sin(args: &[Value]) -> Value { tish_math_sin_impl(args) }
392
- pub fn math_cos(args: &[Value]) -> Value { tish_math_cos_impl(args) }
393
- pub fn math_tan(args: &[Value]) -> Value { tish_math_tan_impl(args) }
394
- pub fn math_exp(args: &[Value]) -> Value { tish_math_exp_impl(args) }
395
- pub fn math_trunc(args: &[Value]) -> Value { tish_math_trunc_impl(args) }
396
- pub fn math_pow(args: &[Value]) -> Value { tish_math_pow_impl(args) }
397
- pub fn math_sign(args: &[Value]) -> Value { tish_math_sign_impl(args) }
398
- pub fn math_random(args: &[Value]) -> Value { tish_math_random_impl(args) }
379
+ pub fn math_abs(args: &[Value]) -> Value {
380
+ tish_math_abs_impl(args)
381
+ }
382
+ pub fn math_sqrt(args: &[Value]) -> Value {
383
+ tish_math_sqrt_impl(args)
384
+ }
385
+ pub fn math_floor(args: &[Value]) -> Value {
386
+ tish_math_floor_impl(args)
387
+ }
388
+ pub fn math_ceil(args: &[Value]) -> Value {
389
+ tish_math_ceil_impl(args)
390
+ }
391
+ pub fn math_round(args: &[Value]) -> Value {
392
+ tish_math_round_impl(args)
393
+ }
394
+ pub fn math_min(args: &[Value]) -> Value {
395
+ tish_math_min_impl(args)
396
+ }
397
+ pub fn math_max(args: &[Value]) -> Value {
398
+ tish_math_max_impl(args)
399
+ }
400
+ pub fn math_sin(args: &[Value]) -> Value {
401
+ tish_math_sin_impl(args)
402
+ }
403
+ pub fn math_cos(args: &[Value]) -> Value {
404
+ tish_math_cos_impl(args)
405
+ }
406
+ pub fn math_tan(args: &[Value]) -> Value {
407
+ tish_math_tan_impl(args)
408
+ }
409
+ pub fn math_exp(args: &[Value]) -> Value {
410
+ tish_math_exp_impl(args)
411
+ }
412
+ pub fn math_trunc(args: &[Value]) -> Value {
413
+ tish_math_trunc_impl(args)
414
+ }
415
+ pub fn math_pow(args: &[Value]) -> Value {
416
+ tish_math_pow_impl(args)
417
+ }
418
+ pub fn math_sign(args: &[Value]) -> Value {
419
+ tish_math_sign_impl(args)
420
+ }
421
+ pub fn math_random(args: &[Value]) -> Value {
422
+ tish_math_random_impl(args)
423
+ }
399
424
 
400
425
  pub fn math_log(args: &[Value]) -> Value {
401
426
  let n = extract_num(args.first()).unwrap_or(f64::NAN);
@@ -408,7 +433,10 @@ pub fn json_stringify(args: &[Value]) -> Value {
408
433
  }
409
434
 
410
435
  pub fn json_parse(args: &[Value]) -> Value {
411
- let s = args.first().map(|v| v.to_display_string()).unwrap_or_default();
436
+ let s = args
437
+ .first()
438
+ .map(|v| v.to_display_string())
439
+ .unwrap_or_default();
412
440
  core_json_parse(&s).unwrap_or(Value::Null)
413
441
  }
414
442
 
@@ -431,10 +459,13 @@ pub fn string_from_char_code(args: &[Value]) -> Value {
431
459
 
432
460
  #[cfg(feature = "process")]
433
461
  pub fn process_exit(args: &[Value]) -> Value {
434
- let code = args.first().and_then(|v| match v {
435
- Value::Number(n) => Some(*n as i32),
436
- _ => None,
437
- }).unwrap_or(0);
462
+ let code = args
463
+ .first()
464
+ .and_then(|v| match v {
465
+ Value::Number(n) => Some(*n as i32),
466
+ _ => None,
467
+ })
468
+ .unwrap_or(0);
438
469
  std::process::exit(code);
439
470
  }
440
471
 
@@ -449,7 +480,10 @@ pub fn process_cwd(_args: &[Value]) -> Value {
449
480
  #[cfg(feature = "process")]
450
481
  pub fn process_exec(args: &[Value]) -> Value {
451
482
  use std::process::Command;
452
- let cmd = args.first().map(|v| v.to_display_string()).unwrap_or_default();
483
+ let cmd = args
484
+ .first()
485
+ .map(|v| v.to_display_string())
486
+ .unwrap_or_default();
453
487
  if cmd.is_empty() {
454
488
  return Value::Number(0.0);
455
489
  }
@@ -461,7 +495,10 @@ pub fn process_exec(args: &[Value]) -> Value {
461
495
 
462
496
  #[cfg(feature = "fs")]
463
497
  pub fn read_file(args: &[Value]) -> Value {
464
- let path = args.first().map(|v| v.to_display_string()).unwrap_or_default();
498
+ let path = args
499
+ .first()
500
+ .map(|v| v.to_display_string())
501
+ .unwrap_or_default();
465
502
  match std::fs::read_to_string(&path) {
466
503
  Ok(content) => Value::String(content.into()),
467
504
  Err(e) => make_error_value(e),
@@ -470,8 +507,14 @@ pub fn read_file(args: &[Value]) -> Value {
470
507
 
471
508
  #[cfg(feature = "fs")]
472
509
  pub fn write_file(args: &[Value]) -> Value {
473
- let path = args.first().map(|v| v.to_display_string()).unwrap_or_default();
474
- let content = args.get(1).map(|v| v.to_display_string()).unwrap_or_default();
510
+ let path = args
511
+ .first()
512
+ .map(|v| v.to_display_string())
513
+ .unwrap_or_default();
514
+ let content = args
515
+ .get(1)
516
+ .map(|v| v.to_display_string())
517
+ .unwrap_or_default();
475
518
  match std::fs::write(&path, &content) {
476
519
  Ok(()) => Value::Bool(true),
477
520
  Err(e) => make_error_value(e),
@@ -480,13 +523,19 @@ pub fn write_file(args: &[Value]) -> Value {
480
523
 
481
524
  #[cfg(feature = "fs")]
482
525
  pub fn file_exists(args: &[Value]) -> Value {
483
- let path = args.first().map(|v| v.to_display_string()).unwrap_or_default();
526
+ let path = args
527
+ .first()
528
+ .map(|v| v.to_display_string())
529
+ .unwrap_or_default();
484
530
  Value::Bool(std::path::Path::new(&path).exists())
485
531
  }
486
532
 
487
533
  #[cfg(feature = "fs")]
488
534
  pub fn is_dir(args: &[Value]) -> Value {
489
- let path = args.first().map(|v| v.to_display_string()).unwrap_or_default();
535
+ let path = args
536
+ .first()
537
+ .map(|v| v.to_display_string())
538
+ .unwrap_or_default();
490
539
  Value::Bool(std::path::Path::new(&path).is_dir())
491
540
  }
492
541
 
@@ -494,7 +543,10 @@ pub fn is_dir(args: &[Value]) -> Value {
494
543
  pub fn read_dir(args: &[Value]) -> Value {
495
544
  use std::cell::RefCell;
496
545
  use std::rc::Rc;
497
- let path = args.first().map(|v| v.to_display_string()).unwrap_or_else(|| ".".to_string());
546
+ let path = args
547
+ .first()
548
+ .map(|v| v.to_display_string())
549
+ .unwrap_or_else(|| ".".to_string());
498
550
  match std::fs::read_dir(&path) {
499
551
  Ok(entries) => {
500
552
  let files: Vec<Value> = entries
@@ -509,7 +561,10 @@ pub fn read_dir(args: &[Value]) -> Value {
509
561
 
510
562
  #[cfg(feature = "fs")]
511
563
  pub fn mkdir(args: &[Value]) -> Value {
512
- let path = args.first().map(|v| v.to_display_string()).unwrap_or_default();
564
+ let path = args
565
+ .first()
566
+ .map(|v| v.to_display_string())
567
+ .unwrap_or_default();
513
568
  match std::fs::create_dir_all(&path) {
514
569
  Ok(()) => Value::Bool(true),
515
570
  Err(e) => make_error_value(e),
@@ -634,7 +689,7 @@ pub fn in_operator(key: &Value, obj: &Value) -> Value {
634
689
  Value::Number(n) => n.to_string().into(),
635
690
  _ => return Value::Bool(false),
636
691
  };
637
-
692
+
638
693
  let result = match obj {
639
694
  Value::Object(map) => map.borrow().contains_key(&key_str),
640
695
  Value::Array(arr) => {
@@ -647,7 +702,7 @@ pub fn in_operator(key: &Value, obj: &Value) -> Value {
647
702
  }
648
703
  _ => false,
649
704
  };
650
-
705
+
651
706
  Value::Bool(result)
652
707
  }
653
708
 
@@ -696,19 +751,17 @@ mod ws;
696
751
 
697
752
  #[cfg(feature = "ws")]
698
753
  pub use ws::{
699
- web_socket_client, web_socket_server_accept, web_socket_server_construct, web_socket_server_listen,
700
- ws_broadcast_native, ws_send_native,
754
+ web_socket_client, web_socket_server_accept, web_socket_server_construct,
755
+ web_socket_server_listen, ws_broadcast_native, ws_send_native,
701
756
  };
702
757
 
703
758
  #[cfg(feature = "http")]
704
759
  pub use http::{
705
- await_fetch as http_await_fetch,
706
- await_fetch_all as http_await_fetch_all,
707
- serve as http_serve,
760
+ await_fetch as http_await_fetch, await_fetch_all as http_await_fetch_all, serve as http_serve,
708
761
  };
709
762
 
710
763
  #[cfg(any(feature = "http", feature = "ws"))]
711
- pub use timers::{set_timeout as timer_set_timeout, clear_timeout as timer_clear_timeout};
764
+ pub use timers::{clear_timeout as timer_clear_timeout, set_timeout as timer_set_timeout};
712
765
 
713
766
  #[cfg(feature = "http")]
714
767
  pub use promise::promise_object;
@@ -718,7 +771,7 @@ pub use native_promise::{await_promise, fetch_all_promise, fetch_async_promise,
718
771
 
719
772
  // RegExp Support
720
773
  #[cfg(feature = "regex")]
721
- pub use tishlang_core::{TishRegExp, RegExpFlags};
774
+ pub use tishlang_core::{RegExpFlags, TishRegExp};
722
775
 
723
776
  #[cfg(feature = "regex")]
724
777
  pub fn regexp_new(args: &[Value]) -> Value {
@@ -833,7 +886,7 @@ pub fn string_split_regex(s: &Value, separator: &Value, limit: Option<usize>) ->
833
886
  Value::String(s) => s.as_ref(),
834
887
  _ => return Value::Array(Rc::new(RefCell::new(vec![s.clone()]))),
835
888
  };
836
-
889
+
837
890
  let max = limit.unwrap_or(usize::MAX);
838
891
  if max == 0 {
839
892
  return Value::Array(Rc::new(RefCell::new(Vec::new())));
@@ -844,22 +897,24 @@ pub fn string_split_regex(s: &Value, separator: &Value, limit: Option<usize>) ->
844
897
  let re = re.borrow();
845
898
  let mut result = Vec::new();
846
899
  let mut last_end = 0;
847
-
900
+
848
901
  for mat in re.regex.find_iter(input) {
849
902
  match mat {
850
903
  Ok(m) => {
851
- if result.len() >= max - 1 { break; }
904
+ if result.len() >= max - 1 {
905
+ break;
906
+ }
852
907
  result.push(Value::String(input[last_end..m.start()].into()));
853
908
  last_end = m.end();
854
909
  }
855
910
  Err(_) => break,
856
911
  }
857
912
  }
858
-
913
+
859
914
  if result.len() < max {
860
915
  result.push(Value::String(input[last_end..].into()));
861
916
  }
862
-
917
+
863
918
  Value::Array(Rc::new(RefCell::new(result)))
864
919
  }
865
920
  Value::String(sep) => {
@@ -883,11 +938,11 @@ pub fn string_match_regex(s: &Value, regexp: &Value) -> Value {
883
938
  match regexp {
884
939
  Value::RegExp(re) => {
885
940
  let mut re = re.borrow_mut();
886
-
941
+
887
942
  if re.flags.global {
888
943
  let mut matches = Vec::new();
889
944
  re.last_index = 0;
890
-
945
+
891
946
  while let Ok(Some(m)) = re.regex.find_from_pos(input, re.last_index) {
892
947
  matches.push(Value::String(m.as_str().into()));
893
948
  if m.start() == m.end() {
@@ -895,22 +950,26 @@ pub fn string_match_regex(s: &Value, regexp: &Value) -> Value {
895
950
  } else {
896
951
  re.last_index = m.end();
897
952
  }
898
- if re.last_index > input.len() { break; }
953
+ if re.last_index > input.len() {
954
+ break;
955
+ }
899
956
  }
900
-
957
+
901
958
  re.last_index = 0;
902
-
903
- if matches.is_empty() { Value::Null } else { Value::Array(Rc::new(RefCell::new(matches))) }
959
+
960
+ if matches.is_empty() {
961
+ Value::Null
962
+ } else {
963
+ Value::Array(Rc::new(RefCell::new(matches)))
964
+ }
904
965
  } else {
905
966
  regexp_exec_impl(&mut re, input)
906
967
  }
907
968
  }
908
- Value::String(pattern) => {
909
- match tishlang_core::TishRegExp::new(pattern, "") {
910
- Ok(mut re) => regexp_exec_impl(&mut re, input),
911
- Err(_) => Value::Null,
912
- }
913
- }
969
+ Value::String(pattern) => match tishlang_core::TishRegExp::new(pattern, "") {
970
+ Ok(mut re) => regexp_exec_impl(&mut re, input),
971
+ Err(_) => Value::Null,
972
+ },
914
973
  _ => Value::Null,
915
974
  }
916
975
  }
@@ -997,19 +1056,16 @@ pub fn string_search_regex(s: &Value, regexp: &Value) -> Value {
997
1056
  _ => Value::Number(-1.0),
998
1057
  }
999
1058
  }
1000
- Value::String(pattern) => {
1001
-
1002
- match tishlang_core::TishRegExp::new(pattern, "") {
1003
- Ok(re) => match re.regex.find(input) {
1004
- Ok(Some(m)) => {
1005
- let char_index = input[..m.start()].chars().count();
1006
- Value::Number(char_index as f64)
1007
- }
1008
- _ => Value::Number(-1.0),
1009
- },
1010
- Err(_) => Value::Number(-1.0),
1011
- }
1012
- }
1059
+ Value::String(pattern) => match tishlang_core::TishRegExp::new(pattern, "") {
1060
+ Ok(re) => match re.regex.find(input) {
1061
+ Ok(Some(m)) => {
1062
+ let char_index = input[..m.start()].chars().count();
1063
+ Value::Number(char_index as f64)
1064
+ }
1065
+ _ => Value::Number(-1.0),
1066
+ },
1067
+ Err(_) => Value::Number(-1.0),
1068
+ },
1013
1069
  _ => Value::Number(-1.0),
1014
1070
  }
1015
1071
  }
@@ -44,11 +44,7 @@ pub fn promise_all(args: &[Value]) -> Value {
44
44
  /// Promise.race(iterable) - returns first element of array.
45
45
  pub fn promise_race(args: &[Value]) -> Value {
46
46
  match args.first() {
47
- Some(Value::Array(arr)) => arr
48
- .borrow()
49
- .first()
50
- .cloned()
51
- .unwrap_or(Value::Null),
47
+ Some(Value::Array(arr)) => arr.borrow().first().cloned().unwrap_or(Value::Null),
52
48
  _ => Value::Null,
53
49
  }
54
50
  }