functionalscript 0.1.608 → 0.2.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/CHANGELOG.md +10 -0
- package/Cargo.lock +4 -0
- package/Cargo.toml +4 -2
- package/README.md +1 -1
- package/com/cpp/module.f.d.mts +4 -8
- package/com/cpp/module.f.mjs +20 -25
- package/com/cpp/testlib.f.mjs +3 -4
- package/com/cs/module.f.d.mts +4 -8
- package/com/cs/module.f.mjs +18 -23
- package/com/cs/testlib.f.mjs +3 -5
- package/com/rust/module.f.d.mts +3 -7
- package/com/rust/module.f.mjs +25 -30
- package/com/rust/nanocom/src/cobject.rs +1 -1
- package/com/rust/testlib.f.mjs +3 -5
- package/com/test/build.f.d.mts +2 -2
- package/com/test/build.f.mjs +2 -2
- package/com/test/build.mjs +4 -4
- package/com/test/rust/src/lib.rs +4 -4
- package/com/types/module.f.d.mts +5 -10
- package/com/types/module.f.mjs +5 -12
- package/commonjs/build/module.f.d.mts +13 -17
- package/commonjs/build/module.f.mjs +23 -28
- package/commonjs/build/test.f.mjs +4 -4
- package/commonjs/module/function/module.f.d.mts +0 -2
- package/commonjs/module/function/module.f.mjs +0 -2
- package/commonjs/module/module.f.d.mts +16 -21
- package/commonjs/module/module.f.mjs +2 -9
- package/commonjs/module.d.mts +1 -5
- package/commonjs/module.f.d.mts +0 -2
- package/commonjs/module.f.mjs +0 -2
- package/commonjs/module.mjs +2 -7
- package/commonjs/package/dependencies/module.f.d.mts +3 -7
- package/commonjs/package/dependencies/module.f.mjs +5 -10
- package/commonjs/package/dependencies/test.f.mjs +1 -1
- package/commonjs/package/module.f.d.mts +12 -18
- package/commonjs/package/module.f.mjs +6 -13
- package/commonjs/package/test.f.mjs +1 -1
- package/commonjs/path/module.f.d.mts +25 -32
- package/commonjs/path/module.f.mjs +12 -23
- package/commonjs/path/test.f.mjs +11 -11
- package/commonjs/test.mjs +1 -1
- package/dev/module.f.d.mts +1 -4
- package/dev/module.f.mjs +1 -4
- package/dev/module.mjs +1 -1
- package/dev/test/module.f.d.mts +2 -3
- package/dev/test/module.f.mjs +5 -7
- package/djs/module.f.d.mts +13 -18
- package/djs/module.f.mjs +12 -19
- package/djs/parser/module.f.d.mts +53 -37
- package/djs/parser/module.f.mjs +278 -131
- package/djs/parser/test.f.d.mts +4 -0
- package/djs/parser/test.f.mjs +186 -70
- package/djs/test.f.mjs +4 -4
- package/djs/tokenizer/module.f.d.mts +6 -10
- package/djs/tokenizer/module.f.mjs +19 -22
- package/djs/tokenizer/test.f.mjs +7 -7
- package/doc/LANGUAGE.md +17 -16
- package/doc/README.md +14 -50
- package/fsc/README.md +0 -3
- package/fsc/module.f.d.mts +4 -9
- package/fsc/module.f.mjs +17 -24
- package/fsc/test.f.mjs +3 -3
- package/fsm/README.md +1 -1
- package/fsm/module.f.d.mts +13 -20
- package/fsm/module.f.mjs +27 -38
- package/fsm/test.f.mjs +8 -8
- package/html/README.md +24 -0
- package/html/module.f.d.mts +7 -12
- package/html/module.f.mjs +14 -23
- package/html/test.f.mjs +4 -4
- package/issues/01-test-debug.md +3 -0
- package/issues/{publish.md → 05-publish.md} +8 -8
- package/issues/17-djs-extension.md +6 -0
- package/issues/README.md +20 -13
- package/issues/lang/1000-json.md +38 -0
- package/issues/lang/2110-default-export.md +2 -2
- package/issues/lang/2310-undefined.md +1 -1
- package/issues/lang/2330-property-accessor.md +225 -0
- package/issues/lang/2360-built-in.md +54 -47
- package/issues/lang/3240-export.md +44 -0
- package/issues/lang/README.md +64 -22
- package/issues/test.f.d.mts +16 -0
- package/issues/test.f.mjs +57 -0
- package/js/tokenizer/module.f.d.mts +18 -17
- package/js/tokenizer/module.f.mjs +80 -61
- package/js/tokenizer/test.f.mjs +15 -12
- package/json/module.f.d.mts +18 -26
- package/json/module.f.mjs +18 -31
- package/json/parser/module.f.d.mts +9 -13
- package/json/parser/module.f.mjs +9 -14
- package/json/parser/test.f.mjs +7 -7
- package/json/serializer/module.f.d.mts +11 -20
- package/json/serializer/module.f.mjs +14 -29
- package/json/serializer/test.f.mjs +2 -2
- package/json/test.f.mjs +3 -3
- package/json/tokenizer/module.f.d.mts +6 -10
- package/json/tokenizer/module.f.mjs +16 -20
- package/json/tokenizer/test.f.mjs +6 -6
- package/jsr.json +1 -1
- package/nanvm-lib/Cargo.toml +6 -0
- package/nanvm-lib/src/extension.rs +119 -0
- package/nanvm-lib/src/interface.rs +136 -0
- package/nanvm-lib/src/lib.rs +7 -0
- package/nanvm-lib/src/naive.rs +229 -0
- package/nanvm-lib/src/nanenum.rs +230 -0
- package/nanvm-lib/src/nullish.rs +7 -0
- package/nanvm-lib/src/sign.rs +5 -0
- package/nanvm-lib/src/simple.rs +32 -0
- package/nanvm-lib/tests/test.f.d.mts +36 -0
- package/nanvm-lib/tests/test.f.mjs +79 -0
- package/nanvm-lib/tests/test.rs +108 -0
- package/nodejs/version/main.mjs +1 -1
- package/nodejs/version/module.f.d.mts +4 -9
- package/nodejs/version/module.f.mjs +2 -7
- package/nodejs/version/test.f.mjs +3 -3
- package/package.json +1 -1
- package/prime_field/module.f.d.mts +20 -23
- package/prime_field/module.f.mjs +9 -12
- package/prime_field/test.f.mjs +1 -1
- package/secp/module.f.d.mts +27 -28
- package/secp/module.f.mjs +38 -39
- package/secp/test.f.mjs +4 -4
- package/sha2/module.f.d.mts +8 -16
- package/sha2/module.f.mjs +7 -20
- package/sha2/test.f.mjs +4 -4
- package/text/README.md +2 -2
- package/text/ascii/module.f.d.mts +69 -72
- package/text/ascii/module.f.mjs +5 -10
- package/text/ascii/test.f.mjs +3 -3
- package/text/module.f.d.mts +9 -14
- package/text/module.f.mjs +7 -14
- package/text/sgr/module.f.d.mts +7 -9
- package/text/sgr/module.f.mjs +2 -4
- package/text/test.f.mjs +3 -3
- package/text/utf16/module.f.d.mts +8 -15
- package/text/utf16/module.f.mjs +17 -28
- package/text/utf16/test.f.mjs +5 -5
- package/text/utf8/module.f.d.mts +4 -9
- package/text/utf8/module.f.mjs +9 -16
- package/text/utf8/test.f.mjs +4 -4
- package/types/array/module.f.d.mts +14 -24
- package/types/array/module.f.mjs +8 -25
- package/types/array/test.f.mjs +3 -3
- package/types/bigfloat/module.f.d.mts +4 -9
- package/types/bigfloat/module.f.mjs +3 -10
- package/types/bigfloat/test.f.mjs +1 -1
- package/types/bigint/module.f.d.mts +16 -64
- package/types/bigint/module.f.mjs +11 -30
- package/types/bigint/test.f.mjs +1 -1
- package/types/btree/find/module.f.d.mts +20 -26
- package/types/btree/find/module.f.mjs +8 -17
- package/types/btree/find/test.f.mjs +7 -7
- package/types/btree/module.f.d.mts +4 -8
- package/types/btree/module.f.mjs +6 -11
- package/types/btree/remove/module.f.d.mts +7 -12
- package/types/btree/remove/module.f.mjs +10 -17
- package/types/btree/remove/test.f.mjs +5 -5
- package/types/btree/set/module.f.d.mts +3 -7
- package/types/btree/set/module.f.mjs +4 -9
- package/types/btree/set/test.f.mjs +4 -4
- package/types/btree/test.f.mjs +9 -9
- package/types/btree/types/module.f.d.mts +0 -2
- package/types/btree/types/module.f.mjs +0 -2
- package/types/byte_set/module.f.d.mts +16 -29
- package/types/byte_set/module.f.mjs +14 -39
- package/types/byte_set/test.f.mjs +5 -5
- package/types/function/compare/module.f.d.mts +9 -15
- package/types/function/compare/module.f.mjs +3 -12
- package/types/function/compare/test.f.mjs +1 -1
- package/types/function/module.f.d.mts +20 -27
- package/types/function/module.f.mjs +4 -15
- package/types/function/operator/module.f.d.mts +28 -43
- package/types/function/operator/module.f.mjs +14 -41
- package/types/function/test.f.mjs +1 -1
- package/types/list/module.f.d.mts +56 -91
- package/types/list/module.f.mjs +45 -114
- package/types/list/test.f.mjs +10 -10
- package/types/map/module.f.d.mts +15 -24
- package/types/map/module.f.mjs +15 -30
- package/types/map/test.f.mjs +2 -2
- package/types/nibble_set/module.f.d.mts +10 -20
- package/types/nibble_set/module.f.mjs +7 -24
- package/types/nibble_set/test.f.mjs +2 -2
- package/types/nullable/module.f.d.mts +3 -8
- package/types/nullable/module.f.mjs +2 -9
- package/types/nullable/test.f.mjs +1 -1
- package/types/number/module.f.d.mts +7 -13
- package/types/number/module.f.mjs +8 -19
- package/types/number/test.f.mjs +1 -1
- package/types/object/module.f.d.mts +11 -18
- package/types/object/module.f.mjs +9 -20
- package/types/object/test.f.mjs +1 -1
- package/types/range/module.f.d.mts +3 -8
- package/types/range/module.f.mjs +2 -9
- package/types/range/test.f.mjs +1 -1
- package/types/range_map/module.f.d.mts +9 -15
- package/types/range_map/module.f.mjs +9 -18
- package/types/range_map/test.f.mjs +32 -32
- package/types/result/module.d.mts +3 -3
- package/types/result/module.f.d.mts +6 -12
- package/types/result/module.f.mjs +3 -12
- package/types/result/module.mjs +2 -2
- package/types/sorted_list/module.f.d.mts +22 -28
- package/types/sorted_list/module.f.mjs +10 -19
- package/types/sorted_list/test.f.mjs +7 -7
- package/types/sorted_set/module.f.d.mts +6 -12
- package/types/sorted_set/module.f.mjs +7 -16
- package/types/sorted_set/test.f.mjs +7 -7
- package/types/string/module.f.d.mts +8 -14
- package/types/string/module.f.mjs +10 -21
- package/types/string/test.f.mjs +2 -2
- package/types/string_set/module.f.d.mts +8 -16
- package/types/string_set/module.f.mjs +12 -27
- package/types/string_set/test.f.mjs +1 -1
- package/issues/lang/2351-property-accessor.md +0 -44
- package/issues/lang/2352-property-call.md +0 -43
- package/issues/lang/2353-property-at.md +0 -19
- package/issues/test-debug.md +0 -12
- /package/issues/{esm.md → 02-esm.md} +0 -0
- /package/issues/{djs.md → 03-djs.md} +0 -0
- /package/issues/{fs-load.md → 11-fs-load.md} +0 -0
- /package/issues/lang/{2330-grouping.md → 2350-grouping.md} +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
use core::fmt;
|
|
2
|
+
|
|
3
|
+
use crate::{nullish::Nullish, sign::Sign, simple::Simple};
|
|
4
|
+
|
|
5
|
+
pub trait Container: Clone {
|
|
6
|
+
type Header;
|
|
7
|
+
type Item;
|
|
8
|
+
fn header(&self) -> &Self::Header;
|
|
9
|
+
/// For now, we use a slice.
|
|
10
|
+
/// We may change it in the future to support more sophisticated containers.
|
|
11
|
+
fn items(&self) -> &[Self::Item];
|
|
12
|
+
fn new(header: Self::Header, items: impl IntoIterator<Item = Self::Item>) -> Self;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
pub trait Complex<U: Any>: PartialEq + Sized + Container {
|
|
16
|
+
fn to_unknown(self) -> U;
|
|
17
|
+
fn try_from_unknown(u: U) -> Result<Self, U>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub trait String16<U: Any<String16 = Self>>:
|
|
21
|
+
Complex<U> + Container<Header = (), Item = u16>
|
|
22
|
+
{
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub trait BigInt<U: Any<BigInt = Self>>:
|
|
26
|
+
Complex<U> + Container<Header = Sign, Item = u64>
|
|
27
|
+
{
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pub trait Array<U: Any<Array = Self>>: Complex<U> + Container<Header = (), Item = U> {}
|
|
31
|
+
|
|
32
|
+
pub trait Object<U: Any<Object = Self>>:
|
|
33
|
+
Complex<U> + Container<Header = (), Item = (U::String16, U)>
|
|
34
|
+
{
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub trait Function<U: Any<Function = Self>>:
|
|
38
|
+
Complex<U> + Container<Header = u32, Item = u8>
|
|
39
|
+
{
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pub trait Any: PartialEq + Sized + Clone + fmt::Debug {
|
|
43
|
+
type String16: String16<Self>;
|
|
44
|
+
type BigInt: BigInt<Self>;
|
|
45
|
+
type Array: Array<Self>;
|
|
46
|
+
type Object: Object<Self>;
|
|
47
|
+
type Function: Function<Self>;
|
|
48
|
+
|
|
49
|
+
fn pack(u: Unpacked<Self>) -> Self;
|
|
50
|
+
fn unpack(self) -> Unpacked<Self>;
|
|
51
|
+
|
|
52
|
+
fn new_simple(value: Simple) -> Self;
|
|
53
|
+
fn try_to_simple(&self) -> Option<Simple>;
|
|
54
|
+
|
|
55
|
+
fn try_to<C: Complex<Self>>(self) -> Result<C, Self> {
|
|
56
|
+
C::try_from_unknown(self)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn to_string(self) -> Self::String16 {
|
|
60
|
+
if let Some(simple) = self.try_to_simple() {
|
|
61
|
+
return simple.to_string::<Self>()
|
|
62
|
+
}
|
|
63
|
+
if let Ok(v) = self.clone().try_to::<Self::String16>() {
|
|
64
|
+
return v;
|
|
65
|
+
}
|
|
66
|
+
if self.clone().try_to::<Self::Array>().is_ok() {
|
|
67
|
+
return "".to_string16::<Self>()
|
|
68
|
+
}
|
|
69
|
+
if self.clone().try_to::<Self::Object>().is_ok() {
|
|
70
|
+
return "[object Object]".to_string16::<Self>()
|
|
71
|
+
}
|
|
72
|
+
// bigint and function
|
|
73
|
+
todo!()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#[derive(PartialEq, Debug, Clone)]
|
|
78
|
+
pub enum Unpacked<U: Any> {
|
|
79
|
+
Nullish(Nullish),
|
|
80
|
+
Bool(bool),
|
|
81
|
+
Number(f64),
|
|
82
|
+
String16(U::String16),
|
|
83
|
+
BigInt(U::BigInt),
|
|
84
|
+
Array(U::Array),
|
|
85
|
+
Object(U::Object),
|
|
86
|
+
Function(U::Function),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
pub trait Extension: Sized {
|
|
90
|
+
fn to_complex<C: Complex<impl Any> + Container<Header = ()>>(self) -> C
|
|
91
|
+
where
|
|
92
|
+
Self: IntoIterator<Item = C::Item>,
|
|
93
|
+
{
|
|
94
|
+
C::new((), self)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fn to_string16_unknown<U: Any>(self) -> U
|
|
98
|
+
where
|
|
99
|
+
Self: IntoIterator<Item = u16>,
|
|
100
|
+
{
|
|
101
|
+
self.to_complex::<U::String16>().to_unknown()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fn to_array_unknown(self) -> Self::Item
|
|
105
|
+
where
|
|
106
|
+
Self: IntoIterator<Item: Any>,
|
|
107
|
+
{
|
|
108
|
+
self.to_complex::<<Self::Item as Any>::Array>()
|
|
109
|
+
.to_unknown()
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
fn to_object_unknown<U: Any>(self) -> U
|
|
113
|
+
where Self: IntoIterator<Item = (U::String16, U)>
|
|
114
|
+
{
|
|
115
|
+
self.to_complex::<U::Object>().to_unknown()
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
impl<T> Extension for T {}
|
|
120
|
+
|
|
121
|
+
// Utf8
|
|
122
|
+
|
|
123
|
+
pub trait Utf8 {
|
|
124
|
+
fn to_string16<U: Any>(&self) -> U::String16;
|
|
125
|
+
fn to_unknown<U: Any>(&self) -> U;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
impl Utf8 for str {
|
|
129
|
+
fn to_string16<U: Any>(&self) -> U::String16 {
|
|
130
|
+
self.encode_utf16().to_complex()
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
fn to_unknown<U: Any>(&self) -> U {
|
|
134
|
+
self.to_string16::<U>().to_unknown()
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
use core::{fmt, marker::PhantomData};
|
|
2
|
+
use std::rc;
|
|
3
|
+
|
|
4
|
+
use crate::{interface::{self, Utf8}, nullish::Nullish, sign::Sign, simple::Simple};
|
|
5
|
+
|
|
6
|
+
pub trait Policy {
|
|
7
|
+
type Header: PartialEq + fmt::Debug + Clone;
|
|
8
|
+
type Item: fmt::Debug;
|
|
9
|
+
fn items_eq(a: &[Self::Item], b: &[Self::Item]) -> bool;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
#[derive(Clone)]
|
|
13
|
+
pub struct ValuePolicy<H, T>(PhantomData<(H, T)>);
|
|
14
|
+
|
|
15
|
+
impl<H: PartialEq + fmt::Debug + Clone, T: PartialEq + fmt::Debug> Policy for ValuePolicy<H, T> {
|
|
16
|
+
type Header = H;
|
|
17
|
+
type Item = T;
|
|
18
|
+
fn items_eq(a: &[Self::Item], b: &[Self::Item]) -> bool {
|
|
19
|
+
a == b
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[derive(Clone)]
|
|
24
|
+
pub struct RefPolicy<H, T>(PhantomData<(H, T)>);
|
|
25
|
+
|
|
26
|
+
impl<H: PartialEq + fmt::Debug + Clone, T: fmt::Debug> Policy for RefPolicy<H, T> {
|
|
27
|
+
type Header = H;
|
|
28
|
+
type Item = T;
|
|
29
|
+
fn items_eq(a: &[Self::Item], b: &[Self::Item]) -> bool {
|
|
30
|
+
a.as_ptr() == b.as_ptr()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
pub struct Complex<P: Policy> {
|
|
35
|
+
header: P::Header,
|
|
36
|
+
items: rc::Rc<[P::Item]>,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl<P: Policy> Clone for Complex<P> {
|
|
40
|
+
fn clone(&self) -> Self {
|
|
41
|
+
Self { header: self.header.clone(), items: self.items.clone() }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl<P: Policy> fmt::Debug for Complex<P> {
|
|
46
|
+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
47
|
+
f.debug_struct("Complex")
|
|
48
|
+
.field("header", &self.header)
|
|
49
|
+
.field("items", &self.items)
|
|
50
|
+
.finish()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl<P: Policy> PartialEq for Complex<P> {
|
|
55
|
+
fn eq(&self, other: &Self) -> bool {
|
|
56
|
+
self.header == other.header && P::items_eq(&self.items, &other.items)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
impl<P: Policy> interface::Container for Complex<P> {
|
|
61
|
+
type Header = P::Header;
|
|
62
|
+
type Item = P::Item;
|
|
63
|
+
fn items(&self) -> &[Self::Item] {
|
|
64
|
+
&*self.items
|
|
65
|
+
}
|
|
66
|
+
fn header(&self) -> &Self::Header {
|
|
67
|
+
&self.header
|
|
68
|
+
}
|
|
69
|
+
fn new(header: Self::Header, items: impl IntoIterator<Item = Self::Item>) -> Self {
|
|
70
|
+
Self {
|
|
71
|
+
header,
|
|
72
|
+
items: rc::Rc::from_iter(items),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// String
|
|
78
|
+
|
|
79
|
+
pub type String16 = Complex<ValuePolicy<(), u16>>;
|
|
80
|
+
|
|
81
|
+
impl interface::Complex<Any> for String16 {
|
|
82
|
+
fn to_unknown(self) -> Any {
|
|
83
|
+
Any::String16(self)
|
|
84
|
+
}
|
|
85
|
+
fn try_from_unknown(u: Any) -> Result<Self, Any> {
|
|
86
|
+
if let Any::String16(v) = u {
|
|
87
|
+
Ok(v)
|
|
88
|
+
} else {
|
|
89
|
+
Err(u)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
impl interface::String16<Any> for String16 {}
|
|
95
|
+
|
|
96
|
+
// BigInt
|
|
97
|
+
|
|
98
|
+
pub type BigInt = Complex<ValuePolicy<Sign, u64>>;
|
|
99
|
+
|
|
100
|
+
impl interface::Complex<Any> for BigInt {
|
|
101
|
+
fn to_unknown(self) -> Any {
|
|
102
|
+
Any::BigInt(self)
|
|
103
|
+
}
|
|
104
|
+
fn try_from_unknown(u: Any) -> Result<Self, Any> {
|
|
105
|
+
if let Any::BigInt(v) = u {
|
|
106
|
+
Ok(v)
|
|
107
|
+
} else {
|
|
108
|
+
Err(u)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
impl interface::BigInt<Any> for BigInt {}
|
|
114
|
+
|
|
115
|
+
// Array
|
|
116
|
+
|
|
117
|
+
pub type Array = Complex<RefPolicy<(), Any>>;
|
|
118
|
+
|
|
119
|
+
impl interface::Complex<Any> for Array {
|
|
120
|
+
fn to_unknown(self) -> Any {
|
|
121
|
+
Any::Array(self)
|
|
122
|
+
}
|
|
123
|
+
fn try_from_unknown(u: Any) -> Result<Self, Any> {
|
|
124
|
+
if let Any::Array(v) = u {
|
|
125
|
+
Ok(v)
|
|
126
|
+
} else {
|
|
127
|
+
Err(u)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
impl interface::Array<Any> for Array {}
|
|
133
|
+
|
|
134
|
+
// Object
|
|
135
|
+
|
|
136
|
+
pub type Object = Complex<RefPolicy<(), (String16, Any)>>;
|
|
137
|
+
|
|
138
|
+
impl interface::Complex<Any> for Object {
|
|
139
|
+
fn to_unknown(self) -> Any {
|
|
140
|
+
Any::Object(self)
|
|
141
|
+
}
|
|
142
|
+
fn try_from_unknown(u: Any) -> Result<Self, Any> {
|
|
143
|
+
if let Any::Object(v) = u {
|
|
144
|
+
Ok(v)
|
|
145
|
+
} else {
|
|
146
|
+
Err(u)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
impl interface::Object<Any> for Object {}
|
|
152
|
+
|
|
153
|
+
// Function
|
|
154
|
+
|
|
155
|
+
pub type Function = Complex<RefPolicy<u32, u8>>;
|
|
156
|
+
|
|
157
|
+
impl interface::Complex<Any> for Function {
|
|
158
|
+
fn to_unknown(self) -> Any {
|
|
159
|
+
Any::Function(self)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
fn try_from_unknown(u: Any) -> Result<Self, Any> {
|
|
163
|
+
if let Any::Function(v) = u {
|
|
164
|
+
Ok(v)
|
|
165
|
+
} else {
|
|
166
|
+
Err(u)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
impl interface::Function<Any> for Function {}
|
|
172
|
+
|
|
173
|
+
// Unknown
|
|
174
|
+
|
|
175
|
+
#[derive(PartialEq, Debug, Clone)]
|
|
176
|
+
pub enum Any {
|
|
177
|
+
Simple(Simple),
|
|
178
|
+
String16(String16),
|
|
179
|
+
BigInt(BigInt),
|
|
180
|
+
Array(Array),
|
|
181
|
+
Object(Object),
|
|
182
|
+
Function(Function),
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
impl interface::Any for Any {
|
|
186
|
+
type String16 = String16;
|
|
187
|
+
type BigInt = BigInt;
|
|
188
|
+
type Array = Array;
|
|
189
|
+
type Object = Object;
|
|
190
|
+
type Function = Function;
|
|
191
|
+
|
|
192
|
+
fn new_simple(value: Simple) -> Self {
|
|
193
|
+
Self::Simple(value)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
fn try_to_simple(&self) -> Option<Simple> {
|
|
197
|
+
if let Self::Simple(v) = self {
|
|
198
|
+
Some(v.clone())
|
|
199
|
+
} else {
|
|
200
|
+
None
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
fn pack(u: interface::Unpacked<Self>) -> Self {
|
|
205
|
+
match u {
|
|
206
|
+
interface::Unpacked::Nullish(n) => Self::Simple(Simple::Nullish(n)),
|
|
207
|
+
interface::Unpacked::Bool(n) => Self::Simple(Simple::Boolean(n)),
|
|
208
|
+
interface::Unpacked::Number(n) => Self::Simple(Simple::Number(n)),
|
|
209
|
+
interface::Unpacked::String16(n) => Self::String16(n),
|
|
210
|
+
interface::Unpacked::BigInt(n) => Self::BigInt(n),
|
|
211
|
+
interface::Unpacked::Array(n) => Self::Array(n),
|
|
212
|
+
interface::Unpacked::Object(n) => Self::Object(n),
|
|
213
|
+
interface::Unpacked::Function(n) => Self::Function(n),
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
fn unpack(self) -> interface::Unpacked<Self> {
|
|
218
|
+
match self {
|
|
219
|
+
Any::Simple(Simple::Nullish(n)) => interface::Unpacked::Nullish(n),
|
|
220
|
+
Any::Simple(Simple::Boolean(n)) => interface::Unpacked::Bool(n),
|
|
221
|
+
Any::Simple(Simple::Number(n)) => interface::Unpacked::Number(n),
|
|
222
|
+
Any::String16(complex) => interface::Unpacked::String16(complex),
|
|
223
|
+
Any::BigInt(complex) => interface::Unpacked::BigInt(complex),
|
|
224
|
+
Any::Array(complex) => interface::Unpacked::Array(complex),
|
|
225
|
+
Any::Object(complex) => interface::Unpacked::Object(complex),
|
|
226
|
+
Any::Function(complex) => interface::Unpacked::Function(complex),
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
use core::{marker::PhantomData, mem::forget};
|
|
2
|
+
use std::rc::Rc;
|
|
3
|
+
|
|
4
|
+
trait Raw64: Clone {
|
|
5
|
+
/// Number of bits in the packed structure.
|
|
6
|
+
const BIT_SIZE: u64;
|
|
7
|
+
/// Moving ownership from `v` to `Self`.`
|
|
8
|
+
unsafe fn from_raw64(v: u64) -> Self;
|
|
9
|
+
/// Moving ownership from `self` to `u64`.
|
|
10
|
+
unsafe fn into_raw64(self) -> u64;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
impl<T> Raw64 for Rc<T> {
|
|
14
|
+
const BIT_SIZE: u64 = 48;
|
|
15
|
+
unsafe fn from_raw64(v: u64) -> Self {
|
|
16
|
+
Rc::from_raw(v as _)
|
|
17
|
+
}
|
|
18
|
+
unsafe fn into_raw64(self) -> u64 {
|
|
19
|
+
Rc::into_raw(self) as *const _ as _
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[derive(Clone)]
|
|
24
|
+
enum NaNEnum<T: Raw64> {
|
|
25
|
+
Number(f64),
|
|
26
|
+
Else(T),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const NEGATIVE: u64 = 1 << 63;
|
|
30
|
+
|
|
31
|
+
const NOT_FINITE: u64 = 0b0111_1111_1111_0000 << 48;
|
|
32
|
+
|
|
33
|
+
const INFINITY: u64 = NOT_FINITE;
|
|
34
|
+
|
|
35
|
+
const NEG_INFINITY: u64 = INFINITY | NEGATIVE;
|
|
36
|
+
|
|
37
|
+
const NAN: u64 = NOT_FINITE | (1 << 51);
|
|
38
|
+
|
|
39
|
+
const ELSE: u64 = NAN | NEGATIVE;
|
|
40
|
+
|
|
41
|
+
const ELSE_DATA: u64 = (1 << 51) - 1;
|
|
42
|
+
|
|
43
|
+
// INFINITY: 7FF0...
|
|
44
|
+
// -INFINITY: FFF0...
|
|
45
|
+
// NAN : 7FF8...
|
|
46
|
+
// ELSE : FFF8...
|
|
47
|
+
// NUMBER : ...
|
|
48
|
+
|
|
49
|
+
/// Represents packed implementation of `NaNEnum`.
|
|
50
|
+
///
|
|
51
|
+
/// Note: currently, only `2^51` values are allowed for `Else`.
|
|
52
|
+
/// However, there are `2^53 - 3` are available,
|
|
53
|
+
/// so it's possible to use more than 51 bits in the future.
|
|
54
|
+
struct NaNEnumPack<T: Raw64>(u64, PhantomData<T>);
|
|
55
|
+
|
|
56
|
+
impl<T: Raw64> NaNEnumPack<T> {
|
|
57
|
+
fn check(&self, mask: u64) -> bool {
|
|
58
|
+
self.0 & mask == mask
|
|
59
|
+
}
|
|
60
|
+
/// Creates a temporary object that should be `forget` after using.
|
|
61
|
+
unsafe fn tmp_unpack(&self) -> NaNEnum<T> {
|
|
62
|
+
if self.check(ELSE) {
|
|
63
|
+
NaNEnum::Else(T::from_raw64(self.0 & ELSE_DATA))
|
|
64
|
+
} else {
|
|
65
|
+
NaNEnum::Number(f64::from_bits(self.0))
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
fn unpack(self) -> NaNEnum<T> {
|
|
69
|
+
let result = unsafe { self.tmp_unpack() };
|
|
70
|
+
forget(self);
|
|
71
|
+
result
|
|
72
|
+
}
|
|
73
|
+
fn pack(v: NaNEnum<T>) -> Self {
|
|
74
|
+
assert!(T::BIT_SIZE <= 51);
|
|
75
|
+
Self(
|
|
76
|
+
match v {
|
|
77
|
+
NaNEnum::Number(n) => n.to_bits(),
|
|
78
|
+
NaNEnum::Else(e) => unsafe { e.into_raw64() | ELSE },
|
|
79
|
+
},
|
|
80
|
+
PhantomData,
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
impl<T: Raw64> Clone for NaNEnumPack<T> {
|
|
86
|
+
fn clone(&self) -> Self {
|
|
87
|
+
let tmp = unsafe { self.tmp_unpack() };
|
|
88
|
+
let c = tmp.clone();
|
|
89
|
+
forget(tmp);
|
|
90
|
+
Self::pack(c)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
impl<T: Raw64> Drop for NaNEnumPack<T> {
|
|
95
|
+
fn drop(&mut self) {
|
|
96
|
+
unsafe { self.tmp_unpack() };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#[cfg(test)]
|
|
101
|
+
mod test {
|
|
102
|
+
use core::{mem::{forget, needs_drop}, ptr::null};
|
|
103
|
+
use std::rc::Rc;
|
|
104
|
+
|
|
105
|
+
use crate::nanenum::{Raw64, NEGATIVE, NOT_FINITE};
|
|
106
|
+
|
|
107
|
+
use super::{NaNEnum, NaNEnumPack};
|
|
108
|
+
|
|
109
|
+
// See https://doc.rust-lang.org/std/mem/fn.needs_drop.html
|
|
110
|
+
|
|
111
|
+
trait Dropable {
|
|
112
|
+
const _A: () = assert!(needs_drop::<Self>());
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
trait NonDropable {
|
|
116
|
+
const _A: () = assert!(!needs_drop::<Self>());
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#[test]
|
|
120
|
+
fn test_f64() {
|
|
121
|
+
assert_eq!(f64::INFINITY.to_bits(), NOT_FINITE);
|
|
122
|
+
assert_eq!((f64::NEG_INFINITY).to_bits(), NOT_FINITE | NEGATIVE);
|
|
123
|
+
assert_eq!(f64::NAN.to_bits(), NOT_FINITE | (1 << 51));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[test]
|
|
127
|
+
fn test_pack() {
|
|
128
|
+
static mut I: u64 = 0;
|
|
129
|
+
|
|
130
|
+
struct P();
|
|
131
|
+
|
|
132
|
+
impl Default for P {
|
|
133
|
+
fn default() -> Self {
|
|
134
|
+
unsafe { I += 1 };
|
|
135
|
+
Self()
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
impl Clone for P {
|
|
140
|
+
fn clone(&self) -> Self {
|
|
141
|
+
Self::default()
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
impl Drop for P {
|
|
146
|
+
fn drop(&mut self) {
|
|
147
|
+
unsafe { I -= 1 };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
impl Raw64 for P {
|
|
152
|
+
const BIT_SIZE: u64 = 0;
|
|
153
|
+
unsafe fn from_raw64(v: u64) -> Self {
|
|
154
|
+
Self()
|
|
155
|
+
}
|
|
156
|
+
unsafe fn into_raw64(self) -> u64 {
|
|
157
|
+
forget(self);
|
|
158
|
+
0
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//
|
|
163
|
+
|
|
164
|
+
{
|
|
165
|
+
unsafe { assert_eq!(I, 0) };
|
|
166
|
+
{
|
|
167
|
+
let x = P::default();
|
|
168
|
+
unsafe { assert_eq!(I, 1) };
|
|
169
|
+
let m = NaNEnum::Else(x);
|
|
170
|
+
unsafe { assert_eq!(I, 1) };
|
|
171
|
+
let p = NaNEnumPack::pack(m);
|
|
172
|
+
unsafe { assert_eq!(I, 1) };
|
|
173
|
+
let p1 = p.clone();
|
|
174
|
+
unsafe { assert_eq!(I, 2) };
|
|
175
|
+
let m1 = p1.unpack();
|
|
176
|
+
unsafe { assert_eq!(I, 2) };
|
|
177
|
+
if let NaNEnum::Else(x1) = m1 {
|
|
178
|
+
unsafe { assert_eq!(I, 2) };
|
|
179
|
+
// assert_ne!(&x as *const _, null())
|
|
180
|
+
// assert_ne!(&m as *const _, null())
|
|
181
|
+
assert_ne!(&p as *const _, null());
|
|
182
|
+
// assert_ne!(&p1 as *const _, null());
|
|
183
|
+
// assert_ne!(&m1 as *const _, null());
|
|
184
|
+
assert_ne!(&x1 as *const _, null());
|
|
185
|
+
} else {
|
|
186
|
+
panic!()
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
unsafe { assert_eq!(I, 0) };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//
|
|
193
|
+
|
|
194
|
+
{
|
|
195
|
+
unsafe { assert_eq!(I, 0) };
|
|
196
|
+
{
|
|
197
|
+
let x = P::default();
|
|
198
|
+
unsafe { assert_eq!(I, 1) };
|
|
199
|
+
let m = NaNEnum::Else(x.clone());
|
|
200
|
+
unsafe { assert_eq!(I, 2) };
|
|
201
|
+
let p = NaNEnumPack::pack(m.clone());
|
|
202
|
+
unsafe { assert_eq!(I, 3) };
|
|
203
|
+
let p1 = p.clone();
|
|
204
|
+
unsafe { assert_eq!(I, 4) };
|
|
205
|
+
let m1 = p1.clone().unpack();
|
|
206
|
+
unsafe { assert_eq!(I, 5) };
|
|
207
|
+
if let NaNEnum::Else(x1) = m1.clone() {
|
|
208
|
+
unsafe { assert_eq!(I, 6) };
|
|
209
|
+
assert_ne!(&x as *const _, null());
|
|
210
|
+
assert_ne!(&m as *const _, null());
|
|
211
|
+
assert_ne!(&p as *const _, null());
|
|
212
|
+
assert_ne!(&p1 as *const _, null());
|
|
213
|
+
assert_ne!(&m1 as *const _, null());
|
|
214
|
+
assert_ne!(&x1 as *const _, null());
|
|
215
|
+
} else {
|
|
216
|
+
panic!()
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
unsafe { assert_eq!(I, 0) };
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#[test]
|
|
224
|
+
fn test_ptr() {
|
|
225
|
+
let x = Rc::new("hello");
|
|
226
|
+
let m = NaNEnum::Else(x);
|
|
227
|
+
let p = NaNEnumPack::pack(m);
|
|
228
|
+
let p1 = p.clone();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// https://developer.mozilla.org/en-US/docs/Glossary/Nullish
|
|
2
|
+
/// "In JavaScript, a nullish value is the value which is either null or undefined. Nullish values are always falsy."
|
|
3
|
+
#[derive(Debug, PartialEq, Clone, Copy)]
|
|
4
|
+
pub enum Nullish {
|
|
5
|
+
Null,
|
|
6
|
+
Undefined,
|
|
7
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
use crate::{
|
|
2
|
+
interface::{Any, Utf8},
|
|
3
|
+
nullish::Nullish,
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
#[derive(PartialEq, Debug, Clone)]
|
|
7
|
+
pub enum Simple {
|
|
8
|
+
Nullish(Nullish),
|
|
9
|
+
Boolean(bool),
|
|
10
|
+
Number(f64),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
impl Simple {
|
|
14
|
+
pub fn to_unknown<U: Any>(self) -> U {
|
|
15
|
+
U::new_simple(self)
|
|
16
|
+
}
|
|
17
|
+
pub fn to_string<U: Any>(self) -> U::String16 {
|
|
18
|
+
match self {
|
|
19
|
+
Simple::Nullish(v) => (match v {
|
|
20
|
+
Nullish::Null => "null",
|
|
21
|
+
Nullish::Undefined => "undefined",
|
|
22
|
+
})
|
|
23
|
+
.to_string16::<U>(),
|
|
24
|
+
Simple::Boolean(v) => (match v {
|
|
25
|
+
true => "true",
|
|
26
|
+
false => "false",
|
|
27
|
+
})
|
|
28
|
+
.to_string16::<U>(),
|
|
29
|
+
Simple::Number(_) => todo!(),
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
namespace eq {
|
|
3
|
+
function nullish(): void;
|
|
4
|
+
namespace boolean {
|
|
5
|
+
export function boolean_1(): void;
|
|
6
|
+
export { boolean_1 as boolean };
|
|
7
|
+
export function nullish_1(): void;
|
|
8
|
+
export { nullish_1 as nullish };
|
|
9
|
+
}
|
|
10
|
+
namespace number {
|
|
11
|
+
export function number_1(): void;
|
|
12
|
+
export { number_1 as number };
|
|
13
|
+
export function nullish_2(): void;
|
|
14
|
+
export { nullish_2 as nullish };
|
|
15
|
+
}
|
|
16
|
+
namespace string {
|
|
17
|
+
export function string_1(): void;
|
|
18
|
+
export { string_1 as string };
|
|
19
|
+
export function number_2(): void;
|
|
20
|
+
export { number_2 as number };
|
|
21
|
+
}
|
|
22
|
+
namespace bigint {
|
|
23
|
+
export function bigint_1(): void;
|
|
24
|
+
export { bigint_1 as bigint };
|
|
25
|
+
}
|
|
26
|
+
namespace array {
|
|
27
|
+
export function array_1(): void;
|
|
28
|
+
export { array_1 as array };
|
|
29
|
+
}
|
|
30
|
+
namespace object {
|
|
31
|
+
export function object_1(): void;
|
|
32
|
+
export { object_1 as object };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export default _default;
|