What is Structural Synthesis and what is it for?
The purpose of this tool is to provide a means of synthesizing and channeling structured data using a hierarchical state system. The system supports reactive IO and serialization of its dynamic generator objects.
Let's throw around some use cases, there are an unlimited number.
Gentyl can generate:
- events, worlds and enemies within games.
- language reflecting the structure of grammar.
- Test Cases in an Automated testing program.
- music and art with WebGL and Web Audio.
- solutions in an evolutionary computation algorithm.
- posts to appear in a feed.
- Whatever.. the list will grow!
Gentyl can also:
- Destructure
- Compose
- Store
- Stream processing
- Asynchonous input-output
Gentyl is:
- data focused model of execution
- dynamically typed
- built with typescript
- runnable on any javascript platform
- tested with jasmine
- process hierarchy
Basics
the fundamental unit is a G-node.
a G-node represents a generator object that can be resolved to produce objects.
G-nodes have 3 parts:
- Crown: | the compositional tree structure of what is generated.
- Form: | a description of how the node behaves, through Tractors and other properties.
- Context: | the items of state modified by and informing the results of Tractors. Appears as this.
each part is represented by an object argument
an example G-node used to generate cats with eventual exhaustion of names could look like this.
var gentyl = var G = gentylG var catGen = ; catGen // -> a size 34 cat with 10 ferocity called TigercatGen // -> a size 34 cat with 10 ferocity called Magnus
although it is not necessary to call prepare() before resolve; it will call it internally if it is left out, it is an important stage in the setup of the node
Structure
G-nodes contain a map, array, or value that contain/is G-nodes and primitives. The recursive architecture means static values in the tree can be converted to dynamic generators at a whim, as seen with ferocity becoming an increasing function of 'intensity'. The functions can gain access to their parent node's state using context association mode strings =+ (track parent) or =_ (track root). Here 'intensity' is a root property that determines both size and ferocity.
{ return objc + objm*thisintensity //This A} { return Math } var NamePicker = var catGen = ;
This G-Node will create cats like above with names like above but with sizes increasing in sequence (10, 12, 14..) and ferocity increasing but also with random influence, could be (6, 12, 9). Notice how easily nodes can be refactored the 'NamePicker' here can be used elsewhere without interfering with the state.
Advanced
the following will outline the advanced features, explaining the concepts and components involved. For detailed examples please refer to the jasmine specs.
Sharing State
Gentyl is caring about state, it doesn't marginalise it like other functional reactive technologies. State is controlled by localising it to each node and constructing a special this object. Children are able to access and modify the parent state by explicitly saying they will, but not the other way around, thus the state dependency structure matches the containment structure. There are three access modes and three ways to designate the source.
State Construction Modes.
Mode | Symbol | Mnemonic | Meaning |
---|---|---|---|
Track | = | The train tracks | No modification only awareness of changes. |
Share | & | And we will work together | Child can modify the designated source. |
Inherit | (pipe) | It's you or me | The parent state is prototype/superclass. |
Designators
type | symbol | Mnemonic | meaning |
---|---|---|---|
parent | + | up by one | designate the direct parent. |
root | _ | at the bottom | designate the root of the structure. |
arbitrary | x | back up x stops | designate x steps up the parent chain. |
for example ' &+ ' means share parent, ' |_ ' means inherit from the root. ' =2 ' means track my parents parent. These can be combined but there are rules about conflicting names and not sharing.
Tractors
At the heart of the execution model, doing all the heavy lifting, are Tractors. These are functions that are bound to the constructed context object of the G-node, that are called at some point in the execution of a G-node. They are called tractors because of how they form a 'tract' through a context from argument to return which is able to disturb the state within. They are always provided as unbound functions, typically not closures, they refer to the context through this. Tractors are always provided as a single letter property of the form object. The only possible tractors are currently resolver, carrier, selector and preparator at the core and injector, ejector and targeter in Gentyl's IO system.
Function | Symbol | Arguments | Returns | Role | |
---|---|---|---|---|---|
Preparator | p | 1:initialization arguments passed to prepare() and replicate() | void | works as a constructor for the state of the generator | |
Carrier | c | 1: the argument passed from the parent or resolve() of the root | the argument passed to the components | appropriation, elaborating, preparation. | |
Selector | s | 1: the argument returned from the carrier, 2:the full set of keys or indicies as array | the iterable with the indicies or keys of children that will resolve | filtering, execution, selective dispatch. | |
Resolver | r | 1: The resolved component object, 2:the value passed to resolve this node | value passed back to the parent | composition, interpretation, filtering data. | |
Injector(input) | i | 1:the input argument | if is root, the value passed to the root resolve for the input event. otherwise unused | the function is for feeding data arriving asynchronously into the system | |
Ejector(output) | o | The resolve return value for the associated G-node | The value that is passed to the output dispatching function | output preprocessing, extraction, representation | |
Targeter | t | 1: the input argument | A string or array of strings that is the output labels of G-nodes that will execute when this node recieves input | selective dispatch, output filtering |
Methods
These are the methods of the G-Node object, most of them perform recursively to capture the whole structure.
Name | Purpose |
---|---|
prepare(prepArgs) | This method transforms the tree of unprepared g-node, creating parent links and constructing the state dependencies. It is a necessary operation before resolve otherwise the functions would not be able to access the wider context. |
resolve(resArgs) -> result | Take the resolve args recursively working out to the leaf nodes through carrier and selector and back through the resolver. This is the fundamental generative action the running of the core algorithm. |
replicate(prepArgs) -> G-Node | Produce a copy of the original node(called the ancestor), replicas have isolated state but share their form. The relationship between ancestor, replicate and the resultant gnode is much like a prototype, new keyword and the instance. Therefore G-Nodes are their own prototype. |
bundle()-> G-bundle | This action is a serialization of the G-node structure that can be converted to JSON and recovered later, so long as a means of recovering the functions within the form is provided(currently only recoverable within the required module instance). it is recoverable by calling R(G-bundle). |
shell() -> SignalShell | This is the io mechanism of gentyl. A signal shell is an object with ins and outs: {ins:{label1:inpFunction1, label2:inpFunction2... }, outs:{label1:outputSignal1, label2:outputSignal2}}. calling the input function for a label calls functions that inject data into the system . The output signals can have callbacks attached to them, these will be called when the node with the corresponding output label is resolved. |