Skip to content

Instantly share code, notes, and snippets.

@tgrospic
Last active July 21, 2020 09:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tgrospic/c56316dd769fdb797337dbeb5047e794 to your computer and use it in GitHub Desktop.
Save tgrospic/c56316dd769fdb797337dbeb5047e794 to your computer and use it in GitHub Desktop.
Very simple example of Rholang with Set as the state
object rholang {
/**
* This interface represents terms in our Simple Rholang language.
* Everything is a process.
*/
trait Process
/**
* AST of our Simple Rholang language. It's private and accessible only
* inside this object. The only way to change the state (Set[Process]) is to
* call defined operations (nil, par, send, receive).
*/
private final case class Par(s: Set[Process] = Set()) extends Process
private final case class Send(name: String) extends Process
private final case class Receive(name: String) extends Process
/**
* `nil` and `par` are Monoid operations (empty, combine).
*
* All terms (processes) are collected in a Set defined in Par(Set[Process]).
*/
def nil: Process = Par(s = Set())
def par(p1: Process, p2: Process = nil): Process = (p1, p2) match {
// Combine states from both Par's
// This rule also "erase" `nil` from both sides of Par
// nil | p == p == p | nil
case (Par(s1), Par(s2)) => Par(s1 ++ s2)
// Next two cases flatten nested Par's
// Par(Set(Par(Send(A)))) => Par(Set(Send(A)))
case (Par(s1), p2) => Par(s1 + p2)
case (p1, Par(s2)) => Par(s2 + p1)
// All other cases just collect in a Set
case (p1, p2) => Par(Set(p1, p2))
}
/**
* `send` and `receive` represent basic operations.
*/
def send(name: String): Process = par(Send(name))
def receive(name: String): Process = par(Receive(name))
/**
* Reductions of our super Simple Rholang language.
* When matching Send/Receive are found they are erased.
*/
def eval(proc: Process): Process =
proc match {
case Par(state) =>
val procs = state.foldLeft(Set[Process]()) {
// Reduction of Send if matches Receive
case (acc, send @ Send(name)) =>
if (state.contains(Receive(name))) acc
else if (name.startsWith("OUT")) {
// If special name do something
println(name)
acc
} else acc + send
// Reduction of Receive if matches Send
case (acc, rec @ Receive(name)) =>
if (state.contains(Send(name))) acc
else acc + rec
// For all other combinations we do nothing
case (acc, p) => acc + p
}
Par(procs)
case p => p
}
}
import rholang._
// Defines | as `par` for nicer syntax
implicit class syntaxRholang(private val p1: Process) extends AnyVal {
def |(p2: Process): Process = par(p1, p2)
}
/**
* Our first Simple Rholang program.
*/
val prog1: Process = {
val p1 = send("A")
val p2 = send("B")
val p3 = receive("B")
val p4 = send("B")
val p5 = send("OUT: Special channel!")
val p6 = receive("C")
p1 | p2 | p3 | p4 | p5 | p6 | nil
}
// prog1: rholang.Process = Par(Set(Send(B), Receive(B), Receive(C), Send(OUT: Special channel!), Send(A)))
val prog2 = send("A")
val prog3 = receive("B") | send("A")
// Structural equivalence
val prog4 = send("A") | nil
val prog5 = nil | send("A")
val progEqual_2_4_5 = (prog2 == prog4, prog4 == prog5)
val prog7 = send("A") | send("A")
/**
* Evaluate the program and get remaining processes (state inside Par).
*/
val res = eval(prog1)
// OUT: Special channel!
// res: Process = Par(Set(Receive(C), Send(A)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment