Nekojimi
97301d13f1
|
2 years ago | |
---|---|---|
src/main/java/moe/nekojimi/nodeprocessor | 2 years ago | |
.gitignore | 3 years ago | |
LICENSE | 3 years ago | |
README.md | 2 years ago | |
nbactions.xml | 2 years ago | |
pom.xml | 2 years ago |
README.md
Inner Platform (Working Title)
A visual graph-based hacking language made for stupid purposes.
Applications
This repository contains the source for three applications:
inner-platform
, the runtime for executing programs
inner-server
, a daemon for managing, debugging, and deploying your programs
inner-editor
, a GUI application for editing programs
Specification
A basic and rubbish spec for the Inner Platfom Hacking Language (IPHL)
Objects & Concepts
The executable unit of IPHL code is the program, which lives in a .iphp file. Non-executable code (i.e libraries) is a module which lives in a .iphm file.
These are mostly the same and so the word program will be used for both cases; maybe I'll have to come up with a generic name for both at some point.
A program is made up of nodes and pipes. A node represents a function, object, or other thing-that-does-processing. A pipe carries values in one direction between nodes, and also carry signals in either direction which transfer control.
Each node has a number of ports, which can be either input or output ports. A pipe always connects one output port to one input port. Normally, any port may have zero to many pipes connected to it, although some nodes may impose a uniqueness rule on their ports (see Ports).
Nodes
A node's purpose is to take input from it's input ports, process it, and send it to the output ports. It may also communicate with other sources it owns (such as a websocket, external process), although it should not cause side effects that are observable from other nodes, unless the programmer sets this up deliberately.
Representation
A node is visually represented by a box; at the top of the box, probably centred, is it's name. This top region may also be used for icons or buttons; the most important for editors is probably a little X button on the top-right, which can be used to remove a node from the program.
Below that is the node's ports (see Ports/Representation); input ports are down the left edge, and output ports are down the right edge. Next to each port (towards the inside) are port labels.
Properties
Things a node has:
- A name, which can be changed but defaults to a value
- A type, which is one of the available node types, see below
- Zero or more input ports
- Zero or more output ports
- A reset function, which clears any transient state from a node
- A check function, which tests if a node has enough input data for it's process function to complete
- A process function, which takes values from the input ports and turns them into values in the output ports.
Nodes should have at least one port (of either type) otherwise they're useless.
Ports
Ports are part of a node, and represent an input or output of data values. All ports have a name (unique within their parent node) and a type (the data type of the values the port will accept or generate).
Representation
A port is visually represented by a small shape, such as a circle. This is drawn on the left or right edge of the port's node; left side for input ports, and right side for output ports. The port shape can touch or overlap the edge, or may be distant from it, whichever you'd prefer.
The colour of a port represents it's type, a listing of suggested colours is below:
- Red: boolean values
- Orange: signal only (see Pipes)
- Blue: integers
- Cyan: floats
- Green: strings
- Yellow: complex objects
- Black/white (depending which way up your colour scheme is): any type, or unknown
The exact colours used is implementation-defined, but it is advised that suitability for colourblind persons (like me!) be considered when choosing them; ensure that colours vary in all three of hue, saturation, and lightness.
If a port's type is an array (or collection, etc), it's colour is that of the array type, but the port icon is double-lined. If it's an array of arrays, who bloody knows what happens, really (more lines?).
Next to a port's shape is the port label. Port labels show the name of a port. Input port labels are left-aligned, and vice versa.
In editor programs, port labels may be replaced with other components that represent a port in a more useful way, such as small text boxes that allow a port's value to be displayed.
Behaviour
Output ports give values to pipes, and input ports take values from pipes.
Pipes
Pipes connect output ports to input ports.
Representation
A pipe is represented by a continuous line, starting at the output port, ending at the input port, and drawn on top of both ports and nodes. How it gets from the start to the finish is implementation-defined.
Pipes are coloured according to their type; they have the same colour as the output port they are connected to (see Ports/Representation) They may vary their shade a little to make them easier to distinguish, or dynamically according to the value they contain, if you want.
Behaviour
Pipes need to implement at least two functions; an available function, which determines if a value can be read from the pipe (without blocking), and a read function which actually does the read.
Program Flow
Node Deque
Internally, each program thread maintains a deque of nodes. At each step of the program, the node at the front of the deque is removed, and this node is processed; it reads or takes values from its input ports, and writes new values to its output ports. When a new value is written to an output port, a signal is sent through any connected pipes.
Operation order
Whenever operations on nodes don't specify an order, dependency ordering is to be used.
Dependency ordering is a partial ordering, which is defined by example as follows;
- If the outputs of a node A are connected to the inputs of a node B, then B is dependent on A.
- If C depends on B, and B depends on A, then C depends on A, too.
- If Y depends on X, but X doesn't depend on Y, then Y is after X in dependency ordering.
- If X and Y both depend on other, they are not comparible in dependency ordering.
- If neither X nor Y depend on each other (they aren't connected at all), they're not comparible in dependency ordering.
If two nodes end up not directly comparable, they are handled in an arbitary order.
To illustrate, consider the following situation:
- A descends from nothing
- B and C both descend from A
- D descends from both B and C
- E descends from A and B
- C descends from F, and F descends from C
B
/
A D
\ /
C
Then dependency ordering might go like this:
A > B > E > C > D > F
All this might not be necessary but it's provided as a hedge until I can work out it's not; the signalling-and-checking process might be sufficent to prevent inconsistency.
Signalling
To transfer control, nodes have a process called signalling; when a node is signalled, it calls its check function to see if there are enough values at the input ports to be processed (see Checking). If so, this node is added to the node deque, normally at the back.
A node is signalled under the following conditions:
- When a signal arrives at an input port from another node, indicating that a new value is available in the pipe.
- When another node wants to pull a value from a pull-port of this node. Note that in this case, the signalled node goes to the front of the node deque, not the back.
- Whenever a node has just finished processing, that same node is signalled again.
- A node may signal itself when an object it controls (running in another thread) receives new data. For example, a node implementing a bot on an IM program will signal itself when a new message arrives; a node representing a button will signal itself when the button is pressed.
- At the start of the program, the start nodes are signalled.
Checking
A node's check function returns a boolean value, indicating if there are enough input values at it's ports to allow the node to be processed. Generally, nodes will implement one of two sets of behaviour:
- Function-like nodes will have a checking function that requires that all input ports with a connected pipe must have a value ready. They may define some input ports as optional, meaning that processing can occur if there is no pipe connected to that port, but if there is a pipe then a value is needed. An optional port has its name displayed in (brackets).
- Object-like nodes will have a checking function that requires only a value at any connected input port. These will typically represent an object's getter methods or similar one-argument functions.
Program Start
At the start of the program, the following things happen in order:
- All nodes are asked to reset; this means to clear any volatile state information they hold. Nodes may keep persistent state between runs of the program, but only if this is an obvious part of their function.
- Start nodes are signalled in an arbitrary order.
File Types
IPHL code is stored in YAML format, although with renamed file extensions. Programs themselves are stored in .iphp files (for Inner Platform Hacking Program) while modules (parts of programs) are stored in .iphm files (Inner Platform Hacking Module). Besides their different contents, the two file types are identical.
The exact structure of these files isn't defined yet, but each one is composed of a number of sections. Most sections are optional; if a IPHL editor doesn't know what to do with an section, it should pass it through without touching it.
- shebang: files always begin with #!/bin/innerplatform, which identifies them to the shell. This is also a YAML comment.
metadata:
contains metadata: what this file is, who made it, and so on.name:
(string) the name of this file. It should be the same as the file name if possible.author:
(string) who made the file. This is also used as the namespace. When storing module files on the disk, they are grouped into directories by author name.license
: (string) the name of the license the file is distributed under. The default value is WTFPL.
code:
contains the actual nodes and pipes. This is the only mandatory section.layout:
contains layout information: chiefly, where the nodes are positioned on screen, and what routes the pipes take.