Interaction net virtual machine
https://higherorderco.github.io/IVM-doc/doc/ivm/index.html
- Take a look at the sum example (or at the tests) to get a feeling for the syntax:
- A
Connection
is written likea ~ b
. The two ends of aConnection
areConnector
s, which can be either a port or an agent - Agents are written like
A(a, b)
, where the auxiliary ports are written inside the parentheses, and the principal port is represented by the agent itself- E.g.
r ~ A(a, a)
means thatr
is connected to A's principal port, and A's auxiliary ports are connected to each other - Connections are transitive, so
r ~ A(a, b), a ~ b
would mean the same
- E.g.
- The syntax allows nested agents in the RHS of rules, e.g.
n ~ Succ(Zero)
as a shorthand forn ~ Succ(z), z ~ Zero
(also for the read back, the net's connections are transformed into nested form for improved readability)- E.g.
r ~ A(a, B(C(b, c), D(d, e)))
gets internally flattened intor ~ A(a, _0), _0 ~ B(_1, _2), _1 ~ C(b, c), _2 ~ D(d, e)
during parsing
- E.g.
- The LHS of a rule must be an active pair of agents and cannot contain context beyond that:
- E.g.
X(a, b) ~ Y(c, d)
is an active pair - No nested agents (e.g.
A(B(a, b), c) ~ B
) because reductions only work on the context of active pairs - For the agents in the active pair of a rule LHS, auxiliary ports cannot be specified to be connected:
- neither within one agent of the active pair (e.g.
A(a, a) ~ B
is not allowed) - nor between the two agents of the active pair (e.g.
X(a, b) ~ Y(a, d)
is not allowed)
- neither within one agent of the active pair (e.g.
- E.g.
- A
- Take a look at
src/parser/ast.rs
to see how the AST is structured, how it gets validated and turned into anINetProgram
viaValidatedAst::into_inet_program
- Take a look at
src/rule_book.rs
to see how the rule book works - Take a look at
src/inet.rs
to see how the interaction net is implemented
cargo run -- examples/sum.ivm
./benches/cmp_ivm_hvm.sh
cargo test
- Add type system for agents (e.g.
Zero
andSucc(p)
areNat
constructors) and ports, distinguish input/output ports (constructors/destructors) and port partitions as suggested by Lafont - Polymorphic rules, e.g.
rule[b: Nat] Eq(ret, a) ~ b = IsZero(ret) ~ d, AbsDiff(d, a) ~ b
is equivalent to spelling out the rule for each constructor ofNat
:rule Eq(ret, a) ~ Zero = IsZero(ret) ~ d, AbsDiff(d, a) ~ Zero
rule Eq(ret, a) ~ Succ(b) = IsZero(ret) ~ d, AbsDiff(d, a) ~ Succ(b)
- Syntactic sugar for return:
ret <- A(a, b)
as shorthand forA(ret, a) ~ b
. This is useful for example for the sum example, in rules where the result is returned via a port:- E.g. for
Add
:- Currently:
rule Add(ret, a) ~ Succ(b) = ret ~ Succ(cnt), Add(cnt, a) ~ b
- With sugar:
rule Add(ret, a) ~ Succ(b) = ret ~ Succ(cnt), cnt <- Add(a, b)
- Currently:
- E.g. for
Mul
:- Currently:
rule Mul(ret, a) ~ Succ(b) = Dup(a2, a3) ~ a, Add(ret, a2) ~ cnt, Mul(cnt, a3) ~ b
- With sugar:
rule Mul(ret, a) ~ Succ(b) = Dup(a2, a3) ~ a, ret <- Add(a2, cnt), cnt <- Mul(a3, b)
- Currently:
- E.g. for
- Syntactic sugar for implicit wires, for FP-like nesting:
X(_ <- A(a, b))
as a shorthand forX(cnt), cnt <- A(a, b))
. Then:- The
Add
rule becomes:rule Add(ret, a) ~ Succ(b) = ret ~ Succ(_ <- Add(a, b))
, which is closer to FP syntax (Succ(Add(a, b))
) - The
Mul
rule becomes:rule Mul(ret, a) ~ Succ(b) = Dup(a2, a3) ~ a, ret <- Add(a2, _ <- Mul(a3, b))
, which is closer to FP syntax (Add(a2, Mul(a3, b))
)
- The
- Built-in DUP/SUP/ERA nodes & rules and brackets for lambda calculus
- Parallel reduction using rayon
- Static analysis to determine which reductions benefit from parallelism vs which ones are blocked by previous reductions