@tishlang/tish 1.9.1 → 1.10.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/bin/tish +0 -0
  2. package/crates/js_to_tish/src/transform/expr.rs +8 -6
  3. package/crates/js_to_tish/src/transform/stmt.rs +12 -13
  4. package/crates/tish/Cargo.toml +1 -1
  5. package/crates/tish/src/cargo_native_registry.rs +4 -1
  6. package/crates/tish/src/main.rs +11 -8
  7. package/crates/tish/tests/integration_test.rs +145 -7
  8. package/crates/tish_ast/src/ast.rs +3 -9
  9. package/crates/tish_build_utils/src/lib.rs +43 -15
  10. package/crates/tish_builtins/src/array.rs +2 -3
  11. package/crates/tish_builtins/src/construct.rs +15 -28
  12. package/crates/tish_builtins/src/globals.rs +18 -16
  13. package/crates/tish_builtins/src/helpers.rs +1 -4
  14. package/crates/tish_builtins/src/lib.rs +1 -0
  15. package/crates/tish_builtins/src/object.rs +10 -10
  16. package/crates/tish_builtins/src/string.rs +1 -3
  17. package/crates/tish_builtins/src/symbol.rs +83 -0
  18. package/crates/tish_compile/src/codegen.rs +123 -138
  19. package/crates/tish_compile/src/lib.rs +25 -3
  20. package/crates/tish_compile/src/resolve.rs +6 -3
  21. package/crates/tish_compile/src/types.rs +6 -6
  22. package/crates/tish_compile_js/src/codegen.rs +50 -29
  23. package/crates/tish_compile_js/src/tests_jsx.rs +44 -0
  24. package/crates/tish_core/src/console_style.rs +9 -0
  25. package/crates/tish_core/src/json.rs +17 -7
  26. package/crates/tish_core/src/macros.rs +2 -2
  27. package/crates/tish_core/src/value.rs +192 -4
  28. package/crates/tish_cranelift_runtime/Cargo.toml +4 -0
  29. package/crates/tish_eval/src/eval.rs +135 -73
  30. package/crates/tish_eval/src/http.rs +18 -12
  31. package/crates/tish_eval/src/lib.rs +29 -0
  32. package/crates/tish_eval/src/regex.rs +1 -1
  33. package/crates/tish_eval/src/value.rs +89 -4
  34. package/crates/tish_eval/src/value_convert.rs +30 -8
  35. package/crates/tish_fmt/src/lib.rs +4 -1
  36. package/crates/tish_lexer/src/lib.rs +7 -2
  37. package/crates/tish_llvm/src/lib.rs +2 -2
  38. package/crates/tish_lsp/src/builtin_goto.rs +111 -10
  39. package/crates/tish_lsp/src/import_goto.rs +35 -22
  40. package/crates/tish_lsp/src/main.rs +118 -85
  41. package/crates/tish_native/src/build.rs +187 -10
  42. package/crates/tish_native/src/lib.rs +92 -8
  43. package/crates/tish_parser/src/lib.rs +77 -0
  44. package/crates/tish_parser/src/parser.rs +71 -74
  45. package/crates/tish_pg/src/error.rs +1 -1
  46. package/crates/tish_pg/src/lib.rs +61 -73
  47. package/crates/tish_resolve/src/lib.rs +283 -158
  48. package/crates/tish_resolve/src/pos.rs +10 -2
  49. package/crates/tish_runtime/Cargo.toml +3 -0
  50. package/crates/tish_runtime/src/http.rs +39 -39
  51. package/crates/tish_runtime/src/http_fetch.rs +12 -12
  52. package/crates/tish_runtime/src/lib.rs +26 -43
  53. package/crates/tish_runtime/src/native_promise.rs +0 -11
  54. package/crates/tish_runtime/src/promise.rs +14 -1
  55. package/crates/tish_runtime/src/promise_io.rs +1 -4
  56. package/crates/tish_runtime/src/ws.rs +40 -27
  57. package/crates/tish_runtime/tests/fetch_readable_stream.rs +10 -8
  58. package/crates/tish_ui/src/jsx.rs +6 -4
  59. package/crates/tish_ui/src/lib.rs +2 -2
  60. package/crates/tish_ui/src/runtime/hooks.rs +5 -15
  61. package/crates/tish_ui/src/runtime/mod.rs +16 -17
  62. package/crates/tish_vm/Cargo.toml +2 -0
  63. package/crates/tish_vm/src/vm.rs +218 -153
  64. package/crates/tish_wasm/src/lib.rs +33 -7
  65. package/crates/tish_wasm_runtime/Cargo.toml +4 -1
  66. package/crates/tish_wasm_runtime/src/lib.rs +2 -1
  67. package/crates/tishlang_cargo_bindgen/src/classify.rs +1 -3
  68. package/crates/tishlang_cargo_bindgen/src/discover.rs +10 -5
  69. package/crates/tishlang_cargo_bindgen/src/infer.rs +18 -8
  70. package/crates/tishlang_cargo_bindgen/src/lib.rs +25 -26
  71. package/crates/tishlang_cargo_bindgen/src/main.rs +41 -38
  72. package/crates/tishlang_cargo_bindgen/src/metadata.rs +4 -1
  73. package/justfile +3 -3
  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
@@ -3,10 +3,8 @@
3
3
  //! Used by both tishlang_vm (bytecode) and tishlang_runtime (compiled). Keeps tishlang_vm
4
4
  //! independent of tishlang_runtime.
5
5
 
6
- use std::cell::RefCell;
7
- use tishlang_core::VmRef;
8
- use std::rc::Rc;
9
6
  use std::sync::Arc;
7
+ use tishlang_core::VmRef;
10
8
  use tishlang_core::{percent_decode, percent_encode, ObjectMap, Value};
11
9
 
12
10
  /// Boolean(value) - coerce to bool
@@ -76,6 +74,7 @@ pub fn object_keys(args: &[Value]) -> Value {
76
74
  if let Some(Value::Object(obj)) = args.first() {
77
75
  let obj_borrow = obj.borrow();
78
76
  let keys: Vec<Value> = obj_borrow
77
+ .strings
79
78
  .keys()
80
79
  .map(|k| Value::String(Arc::clone(k)))
81
80
  .collect();
@@ -89,7 +88,7 @@ pub fn object_keys(args: &[Value]) -> Value {
89
88
  pub fn object_values(args: &[Value]) -> Value {
90
89
  if let Some(Value::Object(obj)) = args.first() {
91
90
  let obj_borrow = obj.borrow();
92
- let values: Vec<Value> = obj_borrow.values().cloned().collect();
91
+ let values: Vec<Value> = obj_borrow.strings.values().cloned().collect();
93
92
  Value::Array(VmRef::new(values))
94
93
  } else {
95
94
  Value::Array(VmRef::new(Vec::new()))
@@ -101,13 +100,9 @@ pub fn object_entries(args: &[Value]) -> Value {
101
100
  if let Some(Value::Object(obj)) = args.first() {
102
101
  let obj_borrow = obj.borrow();
103
102
  let entries: Vec<Value> = obj_borrow
103
+ .strings
104
104
  .iter()
105
- .map(|(k, v)| {
106
- Value::Array(VmRef::new(vec![
107
- Value::String(Arc::clone(k)),
108
- v.clone(),
109
- ]))
110
- })
105
+ .map(|(k, v)| Value::Array(VmRef::new(vec![Value::String(Arc::clone(k)), v.clone()])))
111
106
  .collect();
112
107
  Value::Array(VmRef::new(entries))
113
108
  } else {
@@ -127,7 +122,7 @@ pub fn object_assign(args: &[Value]) -> Value {
127
122
  .skip(1)
128
123
  .map(|source| {
129
124
  if let Value::Object(src) = source {
130
- src.borrow().len()
125
+ src.borrow().len_entries()
131
126
  } else {
132
127
  0
133
128
  }
@@ -135,13 +130,20 @@ pub fn object_assign(args: &[Value]) -> Value {
135
130
  .sum();
136
131
 
137
132
  let mut target_mut = target.borrow_mut();
138
- target_mut.reserve(additional_capacity);
133
+ target_mut.strings.reserve(additional_capacity);
139
134
 
140
135
  for source in args.iter().skip(1) {
141
136
  if let Value::Object(src) = source {
142
137
  let src_borrow = src.borrow();
143
- for (k, v) in src_borrow.iter() {
144
- target_mut.insert(Arc::clone(k), v.clone());
138
+ for (k, v) in src_borrow.strings.iter() {
139
+ target_mut.strings.insert(Arc::clone(k), v.clone());
140
+ }
141
+ if let Some(ss) = &src_borrow.symbols {
142
+ if target_mut.symbols.is_none() {
143
+ target_mut.symbols = Some(Default::default());
144
+ }
145
+ let dst = target_mut.symbols.as_mut().unwrap();
146
+ dst.extend(ss.iter().map(|(id, v)| (*id, v.clone())));
145
147
  }
146
148
  }
147
149
  }
@@ -204,8 +206,8 @@ pub fn object_from_entries(args: &[Value]) -> Value {
204
206
  }
205
207
  }
206
208
 
207
- Value::Object(VmRef::new(obj))
209
+ Value::object(obj)
208
210
  } else {
209
- Value::Object(VmRef::new(ObjectMap::default()))
211
+ Value::empty_object()
210
212
  }
211
213
  }
@@ -1,8 +1,5 @@
1
1
  //! Common helper functions used across builtin implementations.
2
2
 
3
- use std::cell::RefCell;
4
- use tishlang_core::VmRef;
5
- use std::rc::Rc;
6
3
  use std::sync::Arc;
7
4
  use tishlang_core::{ObjectMap, Value};
8
5
 
@@ -26,7 +23,7 @@ pub fn normalize_index(idx: &Value, len: i64, default: usize) -> usize {
26
23
  pub fn make_error_value(e: impl std::fmt::Display) -> Value {
27
24
  let mut obj = ObjectMap::with_capacity(1);
28
25
  obj.insert(Arc::from("error"), Value::String(e.to_string().into()));
29
- Value::Object(VmRef::new(obj))
26
+ Value::object(obj)
30
27
  }
31
28
 
32
29
  /// Extract a number from a Value, returning None for non-numbers.
@@ -11,5 +11,6 @@ pub mod helpers;
11
11
  pub mod math;
12
12
  pub mod object;
13
13
  pub mod string;
14
+ pub mod symbol;
14
15
 
15
16
  pub use tishlang_core::Value;
@@ -3,34 +3,34 @@
3
3
  //! This module will contain shared object method implementations.
4
4
  //! Functions will be migrated here from tishlang_runtime and tishlang_eval.
5
5
 
6
- use std::cell::RefCell;
7
- use tishlang_core::VmRef;
8
- use std::rc::Rc;
9
6
  use std::sync::Arc;
10
- use tishlang_core::{ObjectMap, Value};
7
+ use tishlang_core::{ObjectData, ObjectMap, Value, VmRef};
11
8
 
12
9
  /// Create a new empty object Value.
13
10
  pub fn new() -> Value {
14
- Value::Object(VmRef::new(ObjectMap::default()))
11
+ Value::empty_object()
15
12
  }
16
13
 
17
14
  /// Create a new object Value with a given capacity.
18
15
  pub fn with_capacity(capacity: usize) -> Value {
19
- Value::Object(VmRef::new(ObjectMap::with_capacity(capacity)))
16
+ Value::Object(VmRef::new(ObjectData {
17
+ strings: ObjectMap::with_capacity(capacity),
18
+ symbols: None,
19
+ }))
20
20
  }
21
21
 
22
- /// Get the keys of an object.
22
+ /// Get the keys of an object (string keys only; matches `Object.keys` in JS).
23
23
  pub fn keys(obj: &Value) -> Option<Vec<Arc<str>>> {
24
24
  match obj {
25
- Value::Object(map) => Some(map.borrow().keys().cloned().collect()),
25
+ Value::Object(map) => Some(map.borrow().strings.keys().cloned().collect()),
26
26
  _ => None,
27
27
  }
28
28
  }
29
29
 
30
- /// Get the values of an object.
30
+ /// Get the values of an object (string-keyed properties only).
31
31
  pub fn values(obj: &Value) -> Option<Vec<Value>> {
32
32
  match obj {
33
- Value::Object(map) => Some(map.borrow().values().cloned().collect()),
33
+ Value::Object(map) => Some(map.borrow().strings.values().cloned().collect()),
34
34
  _ => None,
35
35
  }
36
36
  }
@@ -4,11 +4,9 @@
4
4
  //! JavaScript, matching .length and .charAt(). Byte offsets are never exposed.
5
5
 
6
6
  use crate::helpers::normalize_index;
7
- use tishlang_core::VmRef;
8
- use std::cell::RefCell;
9
- use std::rc::Rc;
10
7
  use std::sync::Arc;
11
8
  use tishlang_core::Value;
9
+ use tishlang_core::VmRef;
12
10
 
13
11
  /// Byte offset -> character index.
14
12
  fn byte_to_char_index(s: &str, byte_offset: usize) -> usize {
@@ -0,0 +1,83 @@
1
+ //! ECMAScript-style `Symbol`, `Symbol.for`, `Symbol.keyFor`.
2
+
3
+ use std::collections::hash_map::Entry;
4
+ use std::sync::{Arc, Mutex, OnceLock};
5
+
6
+ use std::collections::HashMap;
7
+
8
+ use tishlang_core::{alloc_symbol_id, ObjectMap, TishSymbol, Value};
9
+
10
+ static SYMBOL_FOR_REGISTRY: OnceLock<Mutex<HashMap<Arc<str>, Arc<TishSymbol>>>> = OnceLock::new();
11
+
12
+ fn symbol_registry() -> &'static Mutex<HashMap<Arc<str>, Arc<TishSymbol>>> {
13
+ SYMBOL_FOR_REGISTRY.get_or_init(|| Mutex::new(HashMap::new()))
14
+ }
15
+
16
+ fn symbol_for_impl(key: &str) -> Value {
17
+ let k: Arc<str> = key.into();
18
+ let mut reg = symbol_registry().lock().unwrap();
19
+ let sym = match reg.entry(Arc::clone(&k)) {
20
+ Entry::Occupied(e) => e.get().clone(),
21
+ Entry::Vacant(v) => {
22
+ let id = alloc_symbol_id();
23
+ let sym = TishSymbol::new_registry(id, Arc::clone(&k), None);
24
+ v.insert(Arc::clone(&sym));
25
+ sym
26
+ }
27
+ };
28
+ Value::Symbol(sym)
29
+ }
30
+
31
+ fn symbol_new(args: &[Value]) -> Value {
32
+ let desc = args.first().and_then(|v| {
33
+ if matches!(v, Value::Null) {
34
+ None
35
+ } else {
36
+ Some(v.to_display_string().into())
37
+ }
38
+ });
39
+ Value::Symbol(TishSymbol::new_unique(desc))
40
+ }
41
+
42
+ fn symbol_key_for_impl(args: &[Value]) -> Value {
43
+ match args.first() {
44
+ Some(Value::Symbol(s)) => s
45
+ .registry_key
46
+ .as_ref()
47
+ .map(|k| Value::String(Arc::clone(k)))
48
+ .unwrap_or(Value::Null),
49
+ _ => Value::Null,
50
+ }
51
+ }
52
+
53
+ /// Global `Symbol`: `Symbol("desc")` via `__call` / `__construct`, `Symbol.for`, `Symbol.keyFor`.
54
+ pub fn symbol_object() -> Value {
55
+ let call = Value::native(symbol_new);
56
+ let for_fn = Value::native(|args: &[Value]| {
57
+ let key = args
58
+ .first()
59
+ .map(|v| v.to_display_string())
60
+ .unwrap_or_default();
61
+ symbol_for_impl(&key)
62
+ });
63
+ let key_for = Value::native(symbol_key_for_impl);
64
+ let mut m = ObjectMap::default();
65
+ m.insert(Arc::from("__call"), call.clone());
66
+ m.insert(Arc::from("__construct"), call);
67
+ m.insert(Arc::from("for"), for_fn);
68
+ m.insert(Arc::from("keyFor"), key_for);
69
+ Value::object(m)
70
+ }
71
+
72
+ #[cfg(test)]
73
+ mod tests {
74
+ use super::*;
75
+ use tishlang_core::value_call;
76
+
77
+ #[test]
78
+ fn symbol_global_value_call() {
79
+ let o = symbol_object();
80
+ let r = value_call(&o, &[Value::String("hi".into())]);
81
+ assert!(matches!(r, Value::Symbol(_)));
82
+ }
83
+ }