Formal proposals for changes to the code, new libraries, etc.
The meta-programming type, allowing you to:
TYPE NAME {
# keys ...
meta PURPOSE {
# description ...
}
}
TYPE and NAME work the same as defining a normal struct. Although PURPOSE goes where the name usually goes, this is instead a (name-compliant) keyword that has been registered as a meta extension. It could be registered by a tool or by the core itself.
For meta-programming, these registrations are suggested:
Tool-specific options could include describing the export format for Exchange or styling options for a GUI render of the struct.
This allows for defining the types for new keys. In order to be future-proof, these definitions should override existing keys with a warning while allowing library-internal references to reach the expected type and default despite this collision.
The keys can be defined with a literal of the type name or as a struct with keys pre-defined. This occludes literals with their data key pre-defined but defining it as a string should have the desired effect in that case.
number {
a: 1
size: 4 bytes
meta keys {
a: number
}
}
This allows for defining defaults for new keys and overriding defaults for existing keys.
number ShortByDefault {
meta defaults {
size: 2 bytes
}
}
This allows for imposing restrictions on allowable substructs. It cannot add substructs which would otherwise be disallowed by the type, though.
It has a key allow which is a list of allowable substruct types.
zip MyFiles {
meta children {
allow: [string, png]
}
}
Redefine what the “top” struct is, of the substructs.
At a technical level, this acts similarly to removing the name from the actual top-level struct and putting that name onto the target substruct. However, this also has some differences when using the meta’d struct as a type.
When this struct is used as a type, all keys (except basing keys) and children are moved into the top struct. If necessary, options can be designed for allowing users to select which keys and children move, and the current design can simply be the default.
Relative references within the meta’d struct adhere to the defined hierarchy. But child subscription references outside go to the new top, instead. This is explained by how substruct referencing works, normally (see technical description above as well as the references proposal).
bin SizedZip {
number NotSize { size: 2 }
number Size { size: 2 }
zip Data {
size: @parent{Size}
}
meta top {
is: @parent{Data}
}
}
This allows for interpreting how the basic value is interpreted when instantiating this as a key-struct. Unlike most other meta types, defining multiple of these makes sense, as doing so allows for interpretting multiple forms of basic declarations.
It has a key input which describes the structure of the basic as it’s declared by an author (e.g. type("a")
, the string a
) and the latter describes what keys to put where.
It has a substruct output which describes where to put the data pulled from the basic declaration. Use @{basic}
to refer to the the input value from this substruct. This way, other places won’t need to refer to the basic directly and can just rely on the keys it writes to.
The system will scan any declared basics in order and pick the first one whose type matches.
meta basic {
input: string
output {
something: @{basic}
length: math("@{basic}.length * 2")
}
}
This is a proposed method of handling dynamic usage if it’s ever required. I struggle to find a justification for it to exist, however.
Output may also accept a substruct key which allows for dynamic naming of keys. However, existence and type assertions will still take place, so the key name must exist.
meta basic {
input: list { type: [literal, any] }
output {
key {
name: @{basic}[0]
value: @{basic}[1]
}
}
}
Similarly, the same can be done for substructs with substruct.
meta basic {
input:
output {
substruct {
type: @{basic}[0]
name: @{basic}[1]
keys {
# ...
}
}
}
}
This allows for defining information about the struct to the author or user detailing what it does, how it’s used, what each key means, etc.
For information on substructs, define a meta help
in that substruct.
meta help {
name: Full name of the struct
summary: Short description of what it's for
description: Long description of what it's for, how to use it, etc.
keys {
key1: What this key is for, etc.
key2: note that the type and defaults can
key3: be retrieved from the struct declaration itself
}
}
@this
refers to the struct which is using it, and thus @parent
refers to its parent. This seems more intuitive since most of the time these structs will be used as a type. This functionality may be part of whatever functionality instantiates this as a type, instead, though.