-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BPML: grok 2 start events from pizza example
- pizza-collaboration.bpmn resource (symlink WIP) - add XML dependency - start porting RhoBuilder to scala - add Json dependency
- Loading branch information
Showing
4 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/home/connolly/projects/bpmn-js-examples/bundling/resources/pizza-collaboration.bpmn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package bpmn2rho | ||
|
||
import js2rho.{RhoBuilder, Name, Process, Printer, RhoPrinter} | ||
|
||
import scala.xml.XML | ||
import scala.xml.Node | ||
|
||
object PizzaOrderTest { | ||
def main(args: Array[String]) = { | ||
println("Hello, world!") | ||
// https://github.com/bpmn-io/bpmn-js-examples/blob/master/bundling/resources/pizza-collaboration.bpmn | ||
val pizzaModelRes = getClass.getResource("/pizza-collaboration.bpmn") | ||
|
||
println(pizzaModelRes) | ||
|
||
val doc = XML.load(pizzaModelRes) | ||
// println(doc \\ "task") | ||
println(doc \\ "startEvent") | ||
|
||
val printer = Printer.fromPrintStream(System.out) | ||
val bld = new RhoPrinter() | ||
|
||
toRho(doc, bld)._printOn(printer) | ||
|
||
} | ||
|
||
// TODO: monadic style instead of Builder? | ||
def toRho(bpml: Node, bld: RhoBuilder): Process = { | ||
val nil = bld.Nil() | ||
def par(ps: Seq[Process]): Process = ps match { | ||
case Seq() => nil | ||
case Seq(first) => first | ||
case first :: rest => bld.Par(first, par(rest)) | ||
} | ||
// xmlns:semantic="http://www.omg.org/spec/BPMN/20100524/MODEL" | ||
val starts = | ||
for (startEvent <- bpml \\ "startEvent"; | ||
id = bld.Var((startEvent \ "@id") text); | ||
name = bld.primitive((startEvent \ "@name") text)) | ||
yield bld.receiving(List((List(bld.Quote(name)), id)), nil) | ||
par(starts) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,308 @@ | ||
package js2rho | ||
|
||
import java.io.PrintStream | ||
|
||
import spray.json._ | ||
import DefaultJsonProtocol._ | ||
|
||
/** | ||
* https://github.com/rchain/rchain/blob/dev/rholang/src/main/bnfc/rholang_mercury.cf | ||
*/ | ||
trait Miranda { | ||
def _printOn(p: Printer): Unit | ||
} | ||
|
||
trait Printer { | ||
def print(s: String): Unit | ||
def begin(s: String): Unit | ||
def newline(): Unit | ||
def end(s: String): Unit | ||
} | ||
|
||
object Printer { | ||
def fromPrintStream(out: PrintStream): Printer = { | ||
var indent = 0; | ||
return new Printer { | ||
def print(txt: String) { out.print(txt) } | ||
def begin(txt: String) { out.print(txt); indent += 1; this.newline() } | ||
def newline() { out.print("\n" + " ".repeat(indent)) } | ||
def end(txt: String) { | ||
this.newline(); out.print(txt); indent -= 1; this.newline() | ||
} | ||
} | ||
} | ||
} | ||
|
||
trait Process extends Miranda { | ||
def quote(): Name | ||
} | ||
|
||
trait Name extends Miranda { | ||
def deref(): Process | ||
} | ||
|
||
trait RhoBuilder { | ||
def Nil(): Process | ||
def primitive(value: Boolean): Process | ||
def primitive(value: Int): Process | ||
def primitive(value: String): Process | ||
|
||
def Var(id: String): Name | ||
def Quote(p: Process): Name | ||
def Drop(n: Name): Process | ||
|
||
def Par(p: Process, q: Process): Process | ||
// TODO: join | ||
def receiving(rx: Seq[(Seq[Name], Name)], body: Process): Process | ||
|
||
/* | ||
* @property {(procs: Process[]) => Process} listExpr | ||
* @property {(procs: Process[]) => Process} tupleExpr | ||
* @property {(entries: Array<{ key: string, value: Process }>) => Process} mapExpr | ||
* @property {(specimen: Process, cases: { lhs: Process, rhs: Process }) => Process } match | ||
* @property {(dest: Name, procs: Array<Process>) => Process} send | ||
* @property {(op: BinOp, lhs: Process, rhs: Process) => Process} binop | ||
* @property {(op: UnOp, arg: Process) => Process} unary | ||
* @property {(name: Name, args: Array<Name>, body: Process) => Process} contract | ||
* @property {(n: Name) => Process} Drop | ||
* @property {(p: Process, q: Process) => Process} Par | ||
* @property {(p: Process) => Name} Quote | ||
* @property {(vars: Array<vdecl>, body: Process) => Process} new_ | ||
* | ||
* @typedef {{ lhs: Name[], rhs: Name}[]} Receipt | ||
*/ | ||
} | ||
|
||
class RhoPrinter extends RhoBuilder { | ||
def aNil(): Process = new Process { | ||
def _printOn(out: Printer) = out.print("Nil") | ||
def quote() = Quote(aNil()) | ||
} | ||
val theNil = aNil() | ||
def Nil() = theNil | ||
|
||
def primitive(v: String) = new Process { | ||
def _printOn(out: Printer) = out.print(v.toJson.toString()) | ||
def quote() = Quote(primitive(v)) | ||
} | ||
def primitive(v: Int) = new Process { | ||
def _printOn(out: Printer) = out.print(v.toJson.toString()) | ||
def quote() = Quote(primitive(v)) | ||
} | ||
def primitive(v: Boolean) = new Process { | ||
def _printOn(out: Printer) = out.print(v.toJson.toString()) | ||
def quote() = Quote(primitive(v)) | ||
} | ||
|
||
def Quote(p: Process) = new Name { | ||
def _printOn(out: Printer) = { | ||
out.print("@{ ") | ||
p._printOn(out) | ||
out.print(" }") | ||
} | ||
def deref() = p | ||
} | ||
def Drop(name: Name) = new Process { | ||
def _printOn(out: Printer) = { | ||
out.print("*") | ||
name._printOn(out) | ||
} | ||
def quote() = name | ||
} | ||
def Var(v: String) = new Name { | ||
def _printOn(out: Printer) = out.print(v) | ||
def deref() = Drop(Var(v)) | ||
} | ||
|
||
def Par(p: Process, q: Process) = | ||
if (p == theNil) { q } | ||
else if (q == theNil) { p } | ||
else | ||
new Process { | ||
def _printOn(out: Printer) = { | ||
p._printOn(out) | ||
out.newline() | ||
out.print("|") | ||
out.newline() | ||
q._printOn(out) | ||
} | ||
def quote() = Quote(Par(p, q)) | ||
} | ||
|
||
def receiving(rx: Seq[(Seq[Name], Name)], proc: Process) = new Process { | ||
def _printOn(out: Printer) = { | ||
out.print("for(") | ||
var first = true; | ||
for ((lhs, rhs) <- rx) { | ||
if (!first) { | ||
out.print("; ") | ||
} | ||
printList(out, lhs) | ||
out.print(" <- ") | ||
rhs._printOn(out) | ||
first = false; | ||
} | ||
out.begin(") {") | ||
proc._printOn(out) | ||
out.end("}") | ||
} | ||
def quote() = Quote(receiving(rx, proc)) | ||
} | ||
def printList(out: Printer, items: Iterable[Miranda]) = { | ||
var first = true; | ||
for (item <- items) { | ||
if (!first) { | ||
out.print(", ") | ||
} | ||
item._printOn(out) | ||
first = false | ||
} | ||
} | ||
/* | ||
const listExpr = (procs) => harden({ | ||
_printOn(out) { | ||
out.print('['); | ||
printList(out, procs); | ||
out.print(']'); | ||
}, | ||
quote: () => Quote(listExpr(procs)) | ||
}); | ||
const tupleExpr = (procs) => harden({ | ||
_printOn(out) { | ||
out.print('('); | ||
printList(out, procs); | ||
out.print(')'); | ||
}, | ||
quote: () => Quote(tupleExpr(procs)) | ||
}); | ||
const mapExpr = (entries) => harden({ | ||
_printOn(out) { | ||
let first = true; | ||
out.print('{'); | ||
for (const { key, value } of entries) { | ||
if (!first) { | ||
out.print(', ') | ||
} | ||
out.print(JSON.stringify(key)); | ||
out.print(': '); | ||
value._printOn(out); | ||
first = false; | ||
} | ||
out.print('}'); | ||
}, | ||
quote: () => Quote(mapExpr(entries)) | ||
}); | ||
const match = (specimen, cases) => harden({ | ||
_printOn(out) { | ||
out.newline(); | ||
out.print("match ("); | ||
specimen._printOn(out); | ||
out.begin(") {"); | ||
for (const { lhs, rhs } of cases) { | ||
lhs._printOn(out); | ||
out.begin(" => {"); | ||
rhs._printOn(out); | ||
out.end("}"); | ||
} | ||
out.end("}"); | ||
} | ||
}); | ||
const printList = (out, items) => { | ||
let first = true; | ||
for (const item of items) { | ||
if (!first) { | ||
out.print(", ") | ||
} | ||
item._printOn(out) | ||
first = false | ||
} | ||
} | ||
const send = (dest, procs) => harden({ | ||
_printOn: (out) => { | ||
dest._printOn(out) | ||
out.print(`!(`) // TODO: !! | ||
printList(out, procs) | ||
out.print(")") | ||
}, | ||
quote: () => Quote(send(dest, procs)) | ||
}); | ||
const binop = (op, lhs, rhs) => harden({ | ||
_printOn: (out) => { | ||
lhs._printOn(out) | ||
out.print(" " + op + " ") | ||
rhs._printOn(out) | ||
}, | ||
quote: () => Quote(binop(op, lhs, rhs)) | ||
}) | ||
const unary = (op, arg) => harden({ | ||
_printOn: (out) => { | ||
out.print(op); | ||
out.print('{'); | ||
arg._printOn(out); | ||
out.print('}') | ||
}, | ||
quote: () => Quote(unary(op, arg)) | ||
}) | ||
const contract = (name, args, body) => harden({ | ||
_printOn: (out) => { | ||
out.print("contract ") | ||
name._printOn(out) | ||
out.print(`(`) | ||
printList(out, args) | ||
out.begin(`) = {`); | ||
body._printOn(out); | ||
out.end("}") | ||
}, | ||
quote: () => Quote(contract(name, args, body)) | ||
}) | ||
const fmtvdecl = (vd) => typeof vd === 'string' ? vd : `${vd[0]}(\`${vd[1]}\`)`; | ||
/** @type {(vlist: vdecl[], body: Process) => Process} */ | ||
const new_ = (vlist, body) => harden({ | ||
_printOn: (out) => { | ||
out.newline(); | ||
out.print("new ") | ||
let first = true; | ||
for (const item of vlist) { | ||
if (!first) { | ||
if (typeof item === 'string') { | ||
out.print(', '); | ||
} else { | ||
out.print(','); | ||
out.newline(); | ||
} | ||
} | ||
out.print(fmtvdecl(item)); | ||
first = false; | ||
} | ||
out.newline(); | ||
out.begin("in {") | ||
body._printOn(out) | ||
out.end("}"); | ||
}, | ||
quote: () => Quote(new_(vlist, body)) | ||
}) | ||
return harden({ | ||
Nil, | ||
primitive, | ||
listExpr, | ||
tupleExpr, | ||
mapExpr, | ||
match, | ||
send, | ||
binop, | ||
unary, | ||
receiving, | ||
contract, | ||
Drop, | ||
Var, | ||
Quote, | ||
Par, | ||
new_, | ||
}); | ||
} | ||
*/ | ||
} |