@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.
- package/bin/tish +0 -0
- package/crates/js_to_tish/src/transform/expr.rs +8 -6
- package/crates/js_to_tish/src/transform/stmt.rs +12 -13
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/src/cargo_native_registry.rs +4 -1
- package/crates/tish/src/main.rs +11 -8
- package/crates/tish/tests/integration_test.rs +145 -7
- package/crates/tish_ast/src/ast.rs +3 -9
- package/crates/tish_build_utils/src/lib.rs +43 -15
- package/crates/tish_builtins/src/array.rs +2 -3
- package/crates/tish_builtins/src/construct.rs +15 -28
- package/crates/tish_builtins/src/globals.rs +18 -16
- package/crates/tish_builtins/src/helpers.rs +1 -4
- package/crates/tish_builtins/src/lib.rs +1 -0
- package/crates/tish_builtins/src/object.rs +10 -10
- package/crates/tish_builtins/src/string.rs +1 -3
- package/crates/tish_builtins/src/symbol.rs +83 -0
- package/crates/tish_compile/src/codegen.rs +123 -138
- package/crates/tish_compile/src/lib.rs +25 -3
- package/crates/tish_compile/src/resolve.rs +6 -3
- package/crates/tish_compile/src/types.rs +6 -6
- package/crates/tish_compile_js/src/codegen.rs +50 -29
- package/crates/tish_compile_js/src/tests_jsx.rs +44 -0
- package/crates/tish_core/src/console_style.rs +9 -0
- package/crates/tish_core/src/json.rs +17 -7
- package/crates/tish_core/src/macros.rs +2 -2
- package/crates/tish_core/src/value.rs +192 -4
- package/crates/tish_cranelift_runtime/Cargo.toml +4 -0
- package/crates/tish_eval/src/eval.rs +135 -73
- package/crates/tish_eval/src/http.rs +18 -12
- package/crates/tish_eval/src/lib.rs +29 -0
- package/crates/tish_eval/src/regex.rs +1 -1
- package/crates/tish_eval/src/value.rs +89 -4
- package/crates/tish_eval/src/value_convert.rs +30 -8
- package/crates/tish_fmt/src/lib.rs +4 -1
- package/crates/tish_lexer/src/lib.rs +7 -2
- package/crates/tish_llvm/src/lib.rs +2 -2
- package/crates/tish_lsp/src/builtin_goto.rs +111 -10
- package/crates/tish_lsp/src/import_goto.rs +35 -22
- package/crates/tish_lsp/src/main.rs +118 -85
- package/crates/tish_native/src/build.rs +187 -10
- package/crates/tish_native/src/lib.rs +92 -8
- package/crates/tish_parser/src/lib.rs +77 -0
- package/crates/tish_parser/src/parser.rs +71 -74
- package/crates/tish_pg/src/error.rs +1 -1
- package/crates/tish_pg/src/lib.rs +61 -73
- package/crates/tish_resolve/src/lib.rs +283 -158
- package/crates/tish_resolve/src/pos.rs +10 -2
- package/crates/tish_runtime/Cargo.toml +3 -0
- package/crates/tish_runtime/src/http.rs +39 -39
- package/crates/tish_runtime/src/http_fetch.rs +12 -12
- package/crates/tish_runtime/src/lib.rs +26 -43
- package/crates/tish_runtime/src/native_promise.rs +0 -11
- package/crates/tish_runtime/src/promise.rs +14 -1
- package/crates/tish_runtime/src/promise_io.rs +1 -4
- package/crates/tish_runtime/src/ws.rs +40 -27
- package/crates/tish_runtime/tests/fetch_readable_stream.rs +10 -8
- package/crates/tish_ui/src/jsx.rs +6 -4
- package/crates/tish_ui/src/lib.rs +2 -2
- package/crates/tish_ui/src/runtime/hooks.rs +5 -15
- package/crates/tish_ui/src/runtime/mod.rs +16 -17
- package/crates/tish_vm/Cargo.toml +2 -0
- package/crates/tish_vm/src/vm.rs +218 -153
- package/crates/tish_wasm/src/lib.rs +33 -7
- package/crates/tish_wasm_runtime/Cargo.toml +4 -1
- package/crates/tish_wasm_runtime/src/lib.rs +2 -1
- package/crates/tishlang_cargo_bindgen/src/classify.rs +1 -3
- package/crates/tishlang_cargo_bindgen/src/discover.rs +10 -5
- package/crates/tishlang_cargo_bindgen/src/infer.rs +18 -8
- package/crates/tishlang_cargo_bindgen/src/lib.rs +25 -26
- package/crates/tishlang_cargo_bindgen/src/main.rs +41 -38
- package/crates/tishlang_cargo_bindgen/src/metadata.rs +4 -1
- package/justfile +3 -3
- package/package.json +1 -1
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- 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().
|
|
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::
|
|
209
|
+
Value::object(obj)
|
|
208
210
|
} else {
|
|
209
|
-
Value::
|
|
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::
|
|
26
|
+
Value::object(obj)
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
/// Extract a number from a Value, returning None for non-numbers.
|
|
@@ -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::
|
|
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(
|
|
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
|
+
}
|