Open
Description
TLDR, these proposed changes:
- Allow function parameters, record fields and variant case payloads to have default values, as long as they're constant.
- When subtyping; allow variant cases to fall back on cases which have non-unit payload.
- Strip the
option
type from its special status in various places.
Definition
literal-bool ::= 'false' | 'true'
literal-char ::= '"' <core:stringelem> '"'
constant ::= unit
| (bool <literal-bool>)
| (s8 <core:s8>) | (u8 <core:u8>)
| (s16 <core:s16>) | (u16 <core:u16>)
| (s32 <core:s32>) | (u32 <core:u32>)
| (s64 <core:s64>) | (u64 <core:u64>)
| (float32 <core:f32>) | (float64 <core:f64>)
| (char <literal-char>) | (string <core:string>)
| (record (field <name> <constant>)*)
| (variant (case <name> <constant>))
| (list <intertype> <constant>*)
Regarding the list
constant: every provided <constant>
must be a subtype of the list's <intertype>
.
Aliases
false ↦ (bool false)
true ↦ (bool true)
(tuple <constant>*) ↦ (record (field "𝒊" <constant>)*) for 𝒊=0,1,...
(flags <name>*) ↦ (record (field <name> (bool true))*)
none ↦ (variant (case "none" unit))
(some <constant>) ↦ (variant (case "some" <constant>))
(ok <constant>) ↦ (variant (case "ok" <constant>))
(error <constant>) ↦ (variant (case "error" <constant>))
Types
Every constant expression has a fully deterministic interface type.
- Primitive constants map 1:1 to an interface type.
- List constants declare the element intertype in the constant expression itself.
- Record and Variant constants generate an ad-hoc interface type derived from the constant itself. Example:
Constant:
(record
(field "a" (s16 42))
(field "b" (string "Wasm"))
(field "c" (variant (case "ok" (bool true))))
(field "d" (list u8 (u8 3) (u8 5) (u8 8) (u8 13)))
)
Generated type:
(record
(field "a" s16)
(field "b" string)
(field "c" (variant (case "ok" bool)))
(field "d" (list u8))
)
Updates to existing definitions
- (record (field <name> <intertype>)*)
+ (record (field <name> <intertype> (default <constant>)?)*)
* <constant> must be a subtype of <intertype>
- (variant (case <name> <intertype> (refines <name>)?)*)
+ (variant (case <name> <intertype> (default <constant>)? (refines <name> <constant>?)?)*)
* The <constant> of the `default` clause must be a subtype of <intertype> from the same case.
* The <constant> of the `refines` clause must be a subtype of <intertype> from the case <name> refers to.
* The <constant> in the `refines` clause is optional when the case `<name>` refers to has a `default` value.
- (func <id>? (param <name>? <intertype>)* (result <intertype>))
+ (func <id>? (param <name>? <intertype> (default <constant>)?)* (result <intertype>))
* A param's <constant> must be a subtype of <intertype>
- (flags <name>*) ↦ (record (field <name> bool)*)
+ (flags <name>*) ↦ (record (field <name> bool (default (bool false)))*)
- (option <intertype>) ↦ (variant (case "none") (case "some" <intertype>))
+ (option <intertype>) ↦ (variant (case "none" unit (default unit)) (case "some" <intertype>))
- `record`: fields can be reordered; covariant field payload subtyping; superfluous fields can be ignored in the subtype; `option` fields can be ignored in the supertype
+ `record`: fields can be reordered; covariant field payload subtyping; superfluous fields can be ignored in the subtype; missing fields are set to the `default` value declared in the supertype.
- `func`: parameter names must match in order; contravariant parameter subtyping; superfluous parameters can be ignored in the subtype; `option` parameters can be ignored in the supertype; covariant result subtyping
+ `func`: parameter names must match in order; contravariant parameter subtyping; superfluous parameters can be ignored in the subtype; missing parameters are set to the `default` value declared in the supertype; covariant result subtyping
This is already more detailed than I intended it to be. Let me know if there is interest in pursuing this any further.
Metadata
Metadata
Assignees
Labels
No labels