You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `generic::clone` method is efficient and does not rely on runtime type information.
4
+
5
+
It is non-final because the ShockScript compiler auto-overrides it for each class.
6
+
7
+
Circular references are not preserved.
8
+
9
+
```sx
10
+
genericn function clone(deep:boolean = true):Object (this)
11
+
```
12
+
13
+
## Primitive types
14
+
15
+
For String, Boolean and Numbers:
16
+
17
+
```sx
18
+
/*
19
+
override genericn function clone(deep:boolean = true):Object (
20
+
this
21
+
);
22
+
*/
23
+
```
24
+
25
+
## Tuples
26
+
27
+
```sx
28
+
/*
29
+
override genericn function clone(deep:boolean = true):Object (
30
+
this
31
+
);
32
+
*/
33
+
```
34
+
35
+
## map {} records
36
+
37
+
Handle that well.
38
+
39
+
## tap {} records
40
+
41
+
Handle that well.
42
+
43
+
## Simple enums
44
+
45
+
```sx
46
+
/*
47
+
override genericn function clone(deep:boolean = true):Object (
48
+
this
49
+
);
50
+
*/
51
+
```
52
+
53
+
## Default behavior for other classes
54
+
55
+
If the class defines a `clone` method, it is used by `generic::clone`, and the verifier:
56
+
57
+
- Ensures its signature's result type is either the enclosing class, `Object` or `*`.
58
+
- Ensures its signature consists only of optional or rest parameters.
59
+
- Understands the first Boolean parameter as `deep`.
60
+
61
+
(In this case, the ShockScript compiler must remember to decide between calling the dispatch or non-dispatch version of `clone` (if it has not been overriden).)
62
+
63
+
Otherwise the behavior is roughly:
64
+
65
+
- Let o:c
66
+
- If `c[[Constructor]].length == 0`
67
+
- o = new c()
68
+
- Else
69
+
- o = Create a new instance of c without evaluating the constructor (*preinitialize*)
70
+
- Copy instance fields from this to o
71
+
- If deep=true, map the field value to fieldVal?.generic::clone()
-[ ]GenericNamespace = same as generic, but can be used as an access modifier in definitions
5
+
-[ ]genericn = same as generic, but can be used as an access modifier in definitions
6
6
-[ ] meta namespace = "http://www.sweaxizone.com/2015/shockscript/meta" (under the hood it's not really that URI; it's the global "meta" system namespace)
7
7
-[ ] Intl namespace = "sx.intl"
8
8
-[ ] Temporal namespace = "sx.temporal"
@@ -58,39 +58,12 @@
58
58
-[ ]9. Simple enums === (flags are interned, so that would work)
59
59
-[ ]10. Perform a deep field equality comparison -- Last case (not ===)
60
60
-[ ] Field/element equality goes as `x === undefined ? y === undefined : x === null ? y === null : x.equals(y)`
61
-
-[ ]`GenericNamespace::clone(deep:boolean=):Object` (used mostly as `generic::clone`, but the access modifier needs to use GenericNamespace due to `generic` being reserved as an attribute for multi-methods)
62
-
-[ ] final
63
-
-[ ] deep=true by default
64
-
-[ ] Circular references are not preserved.
65
-
-[ ] Steps
66
-
-[ ]1. Have we cached the cloning method f (without using a bound method) of the object's exact constructor?
67
-
-[ ]1. Let o = The resulting of calling f with (this) or (this, deep). -- Check f Function length (1 or 2 (deep=))
68
-
-[ ]2. Throw a TypeError if o is undefined or null or o's constructor is not exactly this's constructor.
69
-
-[ ]3. Return o
70
-
-[ ] A MUST: For boolean, string and each Number data type's Class provide a pre-cached Function (self):* that returns self as is
71
-
-[ ] NOTE: To clarify, sx.meta.* should provide a function somewhere for retrieving a class's instance method as a Function that clearly takes the `this` receiver as a regular parameter.
72
-
-[ ]2. Tuples
73
-
-[ ]3. map { } records
74
-
-[ ]4. tap { } records (special kind of classes)
75
-
-[ ]5. For simple enums, return as is
76
-
-[ ]6. Detect a fixture, compatible clone method (optional deep=?)
77
-
-[ ] If found
78
-
-[ ] Cache it as a non-bound-method.
79
-
-[ ] Let o = The resulting of calling f with (this) or (this, deep). -- Check f Function length (1 or 2 (deep=))
80
-
-[ ] Throw a TypeError if o is undefined or null or o's constructor is not exactly this's constructor.
81
-
-[ ] Return o
82
-
-[ ]7. Let f = DefaultCloneBehavior
83
-
-[ ]8. Cache f as the cloning method of this
84
-
-[ ]9. Return the result of calling f with (this) or (this, deep).
85
-
-[ ] DefaultCloneBehavior(self, deep)
86
-
-[ ] Let c = self.meta::class()
87
-
-[ ] If c[[Constructor]].length == 0
88
-
-[ ] Let o = new c()
89
-
-[ ] Else
90
-
-[ ] Let o = Create a new instance of c without evaluating the constructor
91
-
-[ ] Copy instance fields from self to o
92
-
-[ ] If deep=true, map the field value to val?.generic::clone()
The Serial facility must be efficient, thus we auto-generate internal method overrides for adequately annotatated types (Serial/XS).
4
+
5
+
- Serial annotatated types must, if not implementing one or both of `fromJSON` and `toJSON`, must have Serial annotatated fields (ignore the `*` type).
6
+
- XS annotatated types must, if not implementing one or both of `fromXML` and `toXML`, must have XS annotatated fields (ignore the `*` type).
7
+
- Auto generate serial_internal::fromJSON for every Serial annotatated type.
8
+
- Reuse fromJSON() if the type implements that.
9
+
- Auto generate serial_internal::toJSON overrides for every Serial annotatated type.
10
+
- Reuse toJSON() if the type implements that.
11
+
- Auto generate serial_internal::fromXML for every XS annotatated type.
12
+
- Reuse fromXML() if the type implements that.
13
+
- Auto generate serial_internal::toXML overrides for every XS annotatated type.
14
+
- Reuse toXML() if the type implements that.
15
+
16
+
See spec/serial.
17
+
18
+
## Verifications
19
+
20
+
- Ensure the Serial/XS meta-data are correct.
21
+
- If the surrounding class/ADT is Serial/XS annotatated and fromJSON/toJSON/fromXML/toXML are implemented, ensure they have the expected signature.
Copy file name to clipboardExpand all lines: src/conversions.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
This section describes which type conversions are available.
4
4
5
-
Explicit conversions may occur as either `t(v)` (strict conversion) or `v as t` (optional conversion). The behavior of the call operator over a type may not always be a conversion depending on if `t` implements the self-attached `meta::invoke()` meta-method.
5
+
Casts may occur as either `t(v)` (strict conversion) or `v as t` (optional conversion). The behavior of the call operator over a type may not always be a conversion depending on if `t` implements the self-attached `meta::invoke()` meta-method.
6
6
7
7
```sx
8
8
v as t // returns t?. failure returns null
@@ -64,9 +64,9 @@ ShockScript allows implicit coercions from `t.<...>` to `t.<...>` where `t` is a
64
64
>
65
65
> For other types, using an unexpected type somewhere in place of type parameters may lead to an internal error during runtime.
66
66
67
-
## Explicit conversions
67
+
## Casts
68
68
69
-
Explicit conversions occur when resolving `v as t` or `t(v)`, after trying an implicit coercion.
69
+
Casts occur when resolving `v as t` or `t(v)`, after trying an implicit coercion.
@@ -76,7 +76,7 @@ Explicit conversions occur when resolving `v as t` or `t(v)`, after trying an im
76
76
| To a contravariant `[t]` type | A new Array filtering out incompatible elements. |
77
77
| To a possibly incompatible `Map.<K, V>` type | A new Map filtering out incompatible fields. |
78
78
| To a contravariant `Set.<t>` type | A new Set filtering out incompatible elements. |
79
-
| To same parameterized type if not Array, nor Map and nor Set and current type arguments can explicitly convert to the target type arguments | E.g. `c.<*>` to `c.<double>`|
79
+
| To same parameterized type if not Array, nor Map and nor Set and if current type arguments can cast to the target type arguments | E.g. `c.<*>` to `c.<double>`|
80
80
|`string` to enumeration | Identification of an enumeration variant by its `string` name. |
81
81
| Number to enumeration (using the same numeric type) | For regular enumerations, identifies a variant by its numeric value. For flag enumerations, identifies variant bits. |
82
82
| To `string`| For `undefined`, returns `"undefined"`; for `null`, returns `"null"`; for other types, invokes `toString()`. |
@@ -97,7 +97,7 @@ Explicit conversions occur when resolving `v as t` or `t(v)`, after trying an im
97
97
98
98
**Parameterized types**
99
99
100
-
ShockScript allows explicit convertions from `t.<...>` to `t.<...>` where `t` is a parameterized type, where the final type contains type arguments which the original type's type arguments may explicitly convert to.
100
+
ShockScript allows casts from `t.<...>` to `t.<...>` where `t` is a parameterized type, where the final type contains type arguments which the original type's type arguments may cast to.
101
101
102
102
> **Note**: These conversions are always safe for Array, Map and Set types, as they create new objects.
The `generic::clone`method present in objects performs a general clone.
3
+
`generic::clone` performs a common clone.
4
4
5
5
```sx
6
6
o.generic::clone()
7
7
```
8
8
9
-
For classes that need their own clone implementation and need to be used with `generic::clone`, it is best to have a `clone` method with either a `function():C` or `function(boolean=):C` signature (where the boolean is the `deep` parameter); any additional optional parameters are allowed after `deep`.
9
+
You may customize it for a class with:
10
10
11
-
> **Note**: It is best for the `deep` parameter to default to `true` for consistency. If you forget or don't care about the `deep` parameter, make sure the method indeed clones deeply for consistency.
11
+
```sx
12
+
public function clone(deep:boolean = true):c {
13
+
}
14
+
15
+
// or
16
+
public function clone():c {
17
+
}
18
+
```
12
19
13
-
Depending on the use-case, `clone` methods may be implemented for skipping the clone (i.e. returning the same object reference), accompanied by an `equals` method that does simply `===`.
20
+
Any parameters are allowed as long as they are optional; however if the first one is a Boolean, it is understood as the `deep` parameter.
ShockScript includes a feature similar to the Serde framework from the Rust language, used for serialization and deserialization of user data types, except it is fully based in runtime type information.
3
+
ShockScript includes a facility related to the Serde framework from the Rust language, used for serialization and deserialization of user data types.
4
+
5
+
The ShockScript compiler does auto-generate internal overrides for supporting this facility efficiently.
Copy file name to clipboardExpand all lines: src/serial.md
+43-14Lines changed: 43 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,12 @@
1
1
# Serial
2
2
3
-
The Serial feature allows serializing and deserializing complex types into data formats like JSON and possibly other user types.
3
+
The Serial facility allows serializing and deserializing complex types into data formats like JSON and XML. YAML and TOML are mostly compatible with JSON.
4
4
5
-
This feature may only be used with classes that are annotatated with either the `Serial` or `XS` meta-data, otherwise a TypeError is thrown while serializing or deserializing.
5
+
> **Note**: The compiler generates efficient code for serialization and deserialization.
6
6
7
-
Variants of an algebraic data type do not need to specify the `Serial` or `XS` meta-data.
7
+
This facility requires annotatating classes with either the `Serial` or `XS` meta-data, otherwise a TypeError is thrown while serializing or deserializing.
8
+
9
+
Variants of an algebraic data type do not need to specify the `Serial` or `XS` meta-data if the ADT does that already.
8
10
9
11
The default behavior while deserializing into a class *c* other than primitive types and certain global classes, unless defining a self-attached `fromJSON` or `fromXML` method, is roughly:
10
12
@@ -13,18 +15,14 @@ The default behavior while deserializing into a class *c* other than primitive t
13
15
2. Else
14
16
1. Let o = Create a new instance of *c* without evaluating the constructor
15
17
3. Let *fields* = Each *o*\[*k*\] field that is not configured with the `skip="true"` option.
16
-
4. Assign each field of *fields* to the respective data document field with the appropriate parsing of the field's data type, applying any configured rename.
18
+
4. Assign each field of *fields* to the respective data document field with appropriate parsing, applying any configured rename.
17
19
5. Return *o*
18
20
19
21
Simple enums, including Flags enums, are serialized and deserialized in a different way from algebraic enums.
20
22
21
-
The reason for requiring the Serial or XS meta-data is for making the default behavior more explicit, which may be adjusted with methods like `fromJSON` and `toJSON`.
22
-
23
-
> **Note**: This section lacks certain contents yet.
24
-
25
23
## JSON
26
24
27
-
How one serializes or deserializes into/from JSON using the Serial feature:
25
+
How one serializes or deserializes into/from JSON using the Serial facility:
28
26
29
27
```sx
30
28
import js = sx.serial.json.*
@@ -61,9 +59,10 @@ enum Item {
61
59
}
62
60
```
63
61
64
-
Remarks:
65
-
62
+
- The rename excludes any base namespaces.
66
63
- For enumeration variant's field renames, more than one assign is allowed, in case the user needs an assign in the name of the renamed field.
64
+
- For ADTs, if no rename is specified, the variant name is used (including any base namespaces inside the ADT delimited by dot) instead.
65
+
- For class-hierarchies used as variants, like nodes resulting from a parser, if no rename is specified, the class's fully qualified name (excluding the package name) is used instead.
67
66
68
67
### Skip
69
68
@@ -87,11 +86,35 @@ enum Item {
87
86
}
88
87
```
89
88
89
+
### Tag
90
+
91
+
The Serial `tag` option allows specifying the property used to identify the kind of an ADT or inheritance-based class. If it is not specified, no property is used; instead, a wrapper plain object is used with the variant name, as in:
92
+
93
+
```json
94
+
{
95
+
"left": {
96
+
"Plus": {
97
+
"left": {
98
+
"Number": 10
99
+
},
100
+
"right": {
101
+
"Number": 9
102
+
}
103
+
}
104
+
},
105
+
"right": {
106
+
"Number": 7
107
+
}
108
+
}
109
+
```
110
+
90
111
### Classes as variants
91
112
92
-
Users may need hierarchical class definitions rather than algebraic type definitions mainly due to inheritance and other factors. The `Serial` meta-data may be used to configure these.
113
+
Users may want inheritance-based class definitions rather than ADTs (algebraic data types). Those do naturally work.
114
+
115
+
### Unions
93
116
94
-
> **Note**: Lacking content. Migrate some plans from the Whack Engine 2024 for this.
117
+
When using union types, there is a small chance of conflict depending on the union members: if two have the same name, one is preferred over the other. This does not happen for most cases though, so we won't bother much with that for now.
95
118
96
119
### Custom implementation
97
120
@@ -137,6 +160,12 @@ The `default xml namespace = ns` statement influences serialization or deseriali
137
160
138
161
> **Note**: Lacking content.
139
162
163
+
### Tag
164
+
165
+
For ADTs, tags representing variants are named either after the variant's name (including any base namespaces inside the ADT delimited by dot), or based on the rename (excluding any base namespaces).
166
+
167
+
For class-hierarchies used as variants, like nodes resulting from a parser, tags are named either after the class's fully qualified name (excluding the package name), or based on the rename (excluding any base namespaces).
168
+
140
169
### Marking a field as a tag
141
170
142
171
A field is implicitly a tag. For using an attribute instead for a field of a primitive type or whose type implements `fromXML` and `toXML` methods that take or return a text node, that field may be marked as an attribute using `attribute="true"`.
@@ -153,7 +182,7 @@ package {
153
182
154
183
### Arrays
155
184
156
-
Arrays or tuples translate to roughly:
185
+
Arrays or tuples translate to roughly, always unpacked:
0 commit comments