Skip to content

Commit 8914b2a

Browse files
committed
upd
1 parent 6dc6181 commit 8914b2a

9 files changed

Lines changed: 167 additions & 68 deletions

File tree

notes/generic_clone.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# The generic::clone method
2+
3+
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()
72+
- Return o

notes/global-objects.md

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
- [ ] (Whack (?Red) engine) fx namespace = "http://www.sweaxizone.com/2015/whack/fx"
33
- [ ] SX namespace = "http://www.sweaxizone.com/2015/shockscript/global"
44
- [ ] generic namespace = "http://www.sweaxizone.com/2015/shockscript/generic"
5-
- [ ] 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
66
- [ ] 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)
77
- [ ] Intl namespace = "sx.intl"
88
- [ ] Temporal namespace = "sx.temporal"
@@ -58,39 +58,12 @@
5858
- [ ] 9. Simple enums === (flags are interned, so that would work)
5959
- [ ] 10. Perform a deep field equality comparison -- Last case (not ===)
6060
- [ ] 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()
93-
- [ ] Return o
61+
- [ ] `genericn::clone(deep:boolean=):Object` (`generic::clone`)
62+
- [ ] See generic_clone.md
63+
- [ ] serial_internal::fromJSON(...)
64+
- [ ] serial_internal::toJSON(...)
65+
- [ ] serial_internal::fromXML(...)
66+
- [ ] serial_internal::toXML(...)
9467
- [ ] `meta::class()`
9568
- [ ] Final
9669
- [ ] toString()

notes/serial_internal.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# serial_internal
2+
3+
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.

src/conversions.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This section describes which type conversions are available.
44

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.
66

77
```sx
88
v as t // returns t?. failure returns null
@@ -64,9 +64,9 @@ ShockScript allows implicit coercions from `t.<...>` to `t.<...>` where `t` is a
6464
>
6565
> For other types, using an unexpected type somewhere in place of type parameters may lead to an internal error during runtime.
6666
67-
## Explicit conversions
67+
## Casts
6868

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.
7070

7171
| Kind | Result |
7272
| ----------------------------------------- | ----------------------- |
@@ -76,7 +76,7 @@ Explicit conversions occur when resolving `v as t` or `t(v)`, after trying an im
7676
| To a contravariant `[t]` type | A new Array filtering out incompatible elements. |
7777
| To a possibly incompatible `Map.<K, V>` type | A new Map filtering out incompatible fields. |
7878
| 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>` |
8080
| `string` to enumeration | Identification of an enumeration variant by its `string` name. |
8181
| Number to enumeration (using the same numeric type) | For regular enumerations, identifies a variant by its numeric value. For flag enumerations, identifies variant bits. |
8282
| 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
9797
9898
**Parameterized types**
9999

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.
101101

102102
> **Note**: These conversions are always safe for Array, Map and Set types, as they create new objects.
103103
>

src/overview/clone.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
# Clone
22

3-
The `generic::clone` method present in objects performs a general clone.
3+
`generic::clone` performs a common clone.
44

55
```sx
66
o.generic::clone()
77
```
88

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:
1010

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+
```
1219

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.

src/overview/namespaces.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,13 @@
22

33
ShockScript defines properties whose name is tied to a namespace, which is useful for version control and protection.
44

5-
**FunInternal.sx**
6-
7-
```sx
8-
package org.lazy.runner {
9-
/** @private */
10-
public namespace FunInternal = "http://www.fun.com/2007/runner/internals";
11-
}
12-
```
13-
145
**Helper.sx**
156

167
```sx
178
package org.lazy.runner {
189
public class Helper {
10+
private namespace FunInternal = "http://www.fun.com/2007/runner/internals";
11+
1912
/** @private */
2013
FunInternal const cache : [double] = [];
2114
@@ -34,6 +27,8 @@ package org.lazy.runner.advanced {
3427
import org.lazy.runner.*;
3528
3629
public function friend(helper:Helper) {
30+
namespace FunInternal = "http://www.fun.com/2007/runner/internals";
31+
3732
helper.FunInternal::cache.push(10);
3833
}
3934
}

src/overview/serial.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Serial
22

3-
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.

src/overview/whack_ds/good_bad.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class Box extends UIComponent {
143143
// 3 - effects & custom hooks
144144
...
145145
146-
// 5 - final
146+
// 4 - final
147147
...
148148
final = (
149149
<></>

src/serial.md

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# Serial
22

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.
44

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.
66
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.
810

911
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:
1012

@@ -13,18 +15,14 @@ The default behavior while deserializing into a class *c* other than primitive t
1315
2. Else
1416
1. Let o = Create a new instance of *c* without evaluating the constructor
1517
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.
1719
5. Return *o*
1820

1921
Simple enums, including Flags enums, are serialized and deserialized in a different way from algebraic enums.
2022

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-
2523
## JSON
2624

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:
2826

2927
```sx
3028
import js = sx.serial.json.*
@@ -61,9 +59,10 @@ enum Item {
6159
}
6260
```
6361

64-
Remarks:
65-
62+
- The rename excludes any base namespaces.
6663
- 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.
6766

6867
### Skip
6968

@@ -87,11 +86,35 @@ enum Item {
8786
}
8887
```
8988

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+
90111
### Classes as variants
91112

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
93116

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.
95118

96119
### Custom implementation
97120

@@ -137,6 +160,12 @@ The `default xml namespace = ns` statement influences serialization or deseriali
137160

138161
> **Note**: Lacking content.
139162
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+
140169
### Marking a field as a tag
141170

142171
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 {
153182

154183
### Arrays
155184

156-
Arrays or tuples translate to roughly:
185+
Arrays or tuples translate to roughly, always unpacked:
157186

158187
```xml
159188
<value>x</value>

0 commit comments

Comments
 (0)