--- /dev/null
+
+run: fleet.jar
+ java -cp lib/edu.berkeley.sbp.jar:fleet.jar edu.berkeley.fleet.FleetParser < test.fleet
+
+fleet.jar: $(shell find src -name \*.java) fleet.g
+ mkdir -p bin
+ cp fleet.g bin
+ javac -cp lib/edu.berkeley.sbp.jar -d bin $(shell find src -name \*.java)
+ cd bin; jar cvf ../$@ .
--- /dev/null
+// The FLEET Assembly Language Grammar
+// As specified in document 2005-ucies06
+
+// comments are included where the grammar had to go beyond the strict
+// "letter of the law" in ies06
+
+// Note that this is the *entire, complete* formal specification of
+// the grammar. An equivalent lex+yacc grammar and support code would
+// be several times as long.
+
+Comment = "//" ~[\n]* "\n"
+ | "/*" ~[\n]* "*/"
+
+w = [\r\n ]*
+ws = (w | Comment)* -> ~[\r\n ]
+
+s = ws! Program ws!
+Program = Program::
+ (Directive ws!)*
+ CodeBagBody
+
+Directive = Memory:: "#memory" "{" (int +/ (ws! "," ws!)) "}" /ws
+ | Import:: "#import" [A-Za-z_.]++ /ws
+ | Ship:: "#ship" shipname ":" [A-Za-z_\.]++ /ws
+
+
+Statement = Move ((ws ";")?)!
+ | CodeBag
+// | ^"#define" Port Port /ws
+
+Move = Source ^"->" Destination /ws
+ | Source ^"->*" Destination /ws
+ | Port ^":=" Source /ws
+
+Destination = Port +/ (ws! "," ws!)
+Source = Port
+ | CodeBag
+CodeBagBody = CodeBag:: (Statement +/ ws)
+CodeBag = NamedCodeBag::
+ name:(name ws! ":" ws!)?
+ "{"
+ ws! statements:(Statement +/ ws) ws!
+ "}"
+ (ws! ";")?!
+
+//Port = Port:: shipname ("." portname)*
+Port = Port:: shipname "." portname
+ | Port:: shipname
+shipname = ShipName:: name (index?)
+portname = PortName:: name (index?)
+name = [A-Za-z0-9\[\]]**
+index = "[" [0-9]+ "]"
+ | [0-9]+
+int = [0-9]++
+
--- /dev/null
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class AdderShip extends Ship {
+
+ Inbox in1 = new Inbox("in1");
+ Inbox in2 = new Inbox("in2");
+ Outbox out = new Outbox("out");
+
+ public AdderShip(Fleet fleet, String name) {
+ super(fleet, name);
+ }
+
+ public void service() {
+ if (!in1.empty() && !in2.empty())
+ out.add(in1.remove() + in2.remove());
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.bind.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+
+public class Fleet {
+
+ /** some "halt ship" can turn this on to stop the interpreter */
+ public boolean halt = false;
+
+ public int[] mem = new int[0];
+ public ArrayList<String> imports = new ArrayList<String>();
+
+ public HashMap<String,Ship> ships = new HashMap<String,Ship>();
+
+ public void go() {
+ while(!halt)
+ for(Ship ship : ships.values())
+ ship._service();
+ }
+
+ public Ship.Inbox getInbox(String ship, String port) {
+ Ship s = ships.get(ship);
+ if (s == null) throw new RuntimeException("unknown ship \""+ship+"\"");
+ Ship.Inbox ret = s.inboxes.get(port);
+ if (ret == null) throw new RuntimeException("unknown port \""+ship+"."+port+"\"");
+ return ret;
+ }
+
+ public Ship.Outbox getOutbox(String ship, String port) {
+ Ship s = ships.get(ship);
+ if (s == null) throw new RuntimeException("unknown ship \""+ship+"\"");
+ Ship.Outbox ret = s.outboxes.get(port);
+ if (ret == null) throw new RuntimeException("unknown port \""+ship+"."+port+"\"");
+ return ret;
+ }
+
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.bind.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+
+public class FleetParser {
+
+ public static void main(String[] s) throws Exception {
+
+ InputStream grammarStream =
+ FleetParser.class.getClassLoader().getResourceAsStream("fleet.g");
+
+ Parser metaGrammarParser = new CharParser(MetaGrammar.newInstance());
+ Tree<String> parsedGrammar = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
+ Grammar.Bindings gbr = new AnnotationGrammarBindings(Program.class);
+ Union mathGrammar = Grammar.create(parsedGrammar, "s", gbr);
+ Parser mathParser = new CharParser(mathGrammar);
+
+ System.out.println("about to parse: tests/test.fleet");
+ Tree tree = mathParser.parse(new CharInput(System.in)).expand1();
+
+ // below is ugly voodoo which will go away very soon. ignore it.
+ TreeFunctor tf = (TreeFunctor)tree.head();
+ Program program = (Program)tf.invoke(tree);
+ // above is ugly voodoo which will go away very soon. ignore it.
+
+ System.out.println();
+ System.out.println("dispatching root codebag:");
+ System.out.println(program.root);
+
+ Fleet fleet = new Fleet();
+ program.configure(fleet);
+
+ System.out.println("memory before execution:");
+ System.out.print(" ");
+ for(int i=0; i<fleet.mem.length; i++)
+ System.out.print(fleet.mem[i] + " ");
+ System.out.println();
+
+ System.out.println();
+ System.out.println("enabling execution...");
+ fleet.go();
+ System.out.println("execution halted.");
+
+ System.out.println();
+ System.out.println("memory after execution:");
+ System.out.print(" ");
+ for(int i=0; i<fleet.mem.length; i++)
+ System.out.print(fleet.mem[i] + " ");
+ System.out.println();
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class HaltShip extends Ship {
+
+ Inbox in = new Inbox("in");
+
+ public HaltShip(Fleet fleet, String name) {
+ super(fleet, name);
+ }
+
+ public void service() {
+ if (!in.empty())
+ fleet.halt = true;
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class MemReadShip extends Ship {
+
+ Inbox addr = new Inbox("addr");
+ Outbox data = new Outbox("data");
+
+ public MemReadShip(Fleet fleet, String name) {
+ super(fleet, name);
+ }
+
+ public void service() {
+ // note that the memory interface is pipelined (buffered)
+ if (!addr.empty())
+ data.add(fleet.mem[addr.remove()]);
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class MemWriteShip extends Ship {
+
+ Inbox addr = new Inbox("addr");
+ Inbox data = new Inbox("data");
+ Outbox done = new Outbox("done");
+
+ public MemWriteShip(Fleet fleet, String name) {
+ super(fleet, name);
+ }
+
+ public void service() {
+ // note that the memory interface is pipelined (buffered)
+ if (!addr.empty() && !data.empty()) {
+ fleet.mem[addr.remove()] = data.remove();
+ done.add(0);
+ }
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import java.util.*;
+import java.io.*;
+
+public class OneProducerShip extends Ship {
+
+ Outbox out = new Outbox("out");
+
+ public OneProducerShip(Fleet fleet, String name) {
+ super(fleet, name);
+ }
+
+ public void service() {
+ if (out.empty())
+ out.add(1);
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.bind.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+import java.lang.reflect.*;
+
+public class Program {
+
+ Directive[] directives;
+ CodeBag root;
+ public Program(Directive[] directives, CodeBag root) {
+ this.root = root;
+ this.directives = directives;
+ }
+ public void configure(Fleet fleet) {
+ for(Directive directive : directives)
+ directive.configure(fleet);
+ root.dispatch(fleet);
+ }
+
+ // inner classes //////////////////////////////////////////////////////////////////////////////
+
+ public static @bind.as("NamedCodeBag") CodeBag codeBag(String name, Object[] statements) {
+ return codeBag(statements);
+ }
+
+ public static @bind.as("CodeBag") CodeBag codeBag(Object[] statements) {
+ CodeBag ret = new CodeBag();
+ for(Object s : statements) ret.add((Statement)s);
+ return ret;
+ }
+
+ public static @bind.as("->") Statement move(Port source, Port[] dest) {
+ return new Move(source, dest);
+ }
+
+ public static @bind.as("->*") Statement smove(Port source, Port[] dest) {
+ //return new SMove(source, dest);
+ return null;
+ }
+
+ public static @bind.as(":=") Statement gets(Port dest, Port source) {
+ return new Move(source, new Port[] { dest });
+ }
+
+ public static @bind.as("Port") Port port(String ship, String port) {
+ return new Port(ship, port);
+ }
+ public static @bind.as("Port") Port port(String ship) {
+ return new Port(ship, null);
+ }
+
+ public static @bind.as("ShipName") String shipname(String name, String index) { return index==null?name:name+index; }
+ public static @bind.as("PortName") String portname(String name, String index) { return index==null?name:name+index; }
+
+ public static interface Source { }
+ public static interface Destination { }
+ public static interface Statement {
+ public void dispatch(Fleet fleet);
+ }
+
+ public static @bind.as("Program") Program program(Directive[] directives, CodeBag rootCodeBag) {
+ return new Program(directives, rootCodeBag);
+ }
+
+ public static abstract class Directive {
+ public void configure(Fleet fleet) {
+ }
+ }
+
+ public static @bind.as("Memory") MemoryDirective memory(String[] values) {
+ return new MemoryDirective(values);
+ }
+
+ public static class MemoryDirective extends Directive{
+ private int[] mem;
+ public MemoryDirective(String[] values) {
+ this.mem = new int[values.length];
+ for(int i=0; i<mem.length; i++)
+ mem[i] = Integer.parseInt(values[i]);
+ }
+ public void configure(Fleet fleet) {
+ fleet.mem = mem;
+ }
+ }
+
+ public static class ShipDirective extends Directive {
+ String shipname;
+ String classname;
+ public @bind.as("Ship") ShipDirective(String shipname, String classname) {
+ this.shipname = shipname;
+ this.classname = classname;
+ }
+ public void configure(Fleet fleet) {
+ for(String s : fleet.imports)
+ if (tryCreate(fleet, s))
+ return;
+ throw new RuntimeException("unable to instantiate class " + classname);
+ }
+ private boolean tryCreate(Fleet fleet, String packagename) {
+ try {
+ Class c = Class.forName(packagename+"."+classname);
+ Constructor con = c.getConstructor(new Class[] { Fleet.class, String.class });
+ con.newInstance(new Object[] { fleet, shipname });
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ }
+
+ public static class ImportDirective extends Directive {
+ String packagename;
+ public @bind.as("Import") ImportDirective(String packagename) {
+ this.packagename = packagename;
+ }
+ public void configure(Fleet fleet) {
+ fleet.imports.add(packagename);
+ }
+ }
+
+ public static class Move implements Statement {
+ Port source;
+ Port[] dest;
+ public Move(Port source, Port[] dest) { this.source = source; this.dest = dest; }
+ public void dispatch(Fleet fleet) {
+ Ship.Outbox ob = fleet.getOutbox(source.ship, source.port);
+ for(Port d : dest) {
+ Ship.Inbox ib = fleet.getInbox(d.ship, d.port);
+ ob.addDestination(ib);
+ System.out.println("instr: " + ob + " -> " + ib);
+ }
+ }
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(source + " -> ");
+ sb.append(dest[0]);
+ for(int i=1; i<dest.length; i++) {
+ sb.append(", " + dest[i]);
+ }
+ return sb.toString();
+ }
+ }
+
+ public static class Port implements Source, Destination {
+ String ship;
+ String port;
+ public Port(String ship, String port) {
+ this.ship = ship;
+ this.port = port;
+ }
+ public String toString() { return port==null?ship:ship+"."+port; }
+ }
+
+ public static class CodeBag extends ArrayList<Statement> implements Statement {
+ public void dispatch(Fleet fleet) {
+ for(Statement s : this)
+ s.dispatch(fleet);
+ }
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+ for(Statement stmt : this) s.append("\n"+stmt);
+ return "{"+indentify(s.toString())+"\n}";
+ }
+ }
+
+ private static String indentify(String s) {
+ StringBuffer s2 = new StringBuffer();
+ for(int i=0; i<s.length(); i++) {
+ char c = s.charAt(i);
+ s2.append(c);
+ if (c == '\n')
+ s2.append(" ");
+ }
+ return s2.toString();
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet;
+
+import edu.berkeley.sbp.*;
+import edu.berkeley.sbp.chr.*;
+import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.meta.*;
+import edu.berkeley.sbp.bind.*;
+import edu.berkeley.sbp.util.*;
+import java.util.*;
+import java.io.*;
+
+public abstract class Ship {
+
+ HashMap<String,Inbox> inboxes = new HashMap<String,Inbox>();
+ HashMap<String,Outbox> outboxes = new HashMap<String,Outbox>();
+ private String name;
+ protected Fleet fleet;
+
+ /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */
+ public Ship(Fleet fleet, String name) {
+ this.name = name;
+ this.fleet = fleet;
+ fleet.ships.put(name, this);
+ }
+
+ public String toString() { return name; }
+
+ /**
+ * Override this method, check inboxes for the data you need, and
+ * if you find it, deposit results in an outbox; we'll take care
+ * of the rest.
+ */
+ public abstract void service();
+
+ public final void _service() {
+ for(Outbox ob : outboxes.values()) {
+ if (!ob.data.isEmpty() && !ob.destination.isEmpty()) {
+ int data = ob.data.remove();
+ Inbox destination = ob.destination.remove();
+ destination.add(data);
+ System.out.println("data: " + ob + " ----("+data+")----> " + destination);
+ }
+ }
+ service();
+ }
+
+ public class Inbox {
+ private String name;
+ private Queue<Integer> queue = new LinkedList<Integer>();
+ public boolean empty() { return queue.isEmpty(); }
+ public void add(int data) { queue.add(data); }
+ public int remove() { return queue.remove(); }
+ public String toString() { return Ship.this.name+"."+name; }
+ public Inbox(String name) {
+ this.name = name;
+ Ship.this.inboxes.put(name, this);
+ }
+ }
+
+ public class Outbox {
+ private String name;
+ public Queue<Integer> data = new LinkedList<Integer>();
+ public Queue<Inbox> destination = new LinkedList<Inbox>();
+ public void add(int data) { this.data.add(data); }
+ public void addDestination(Inbox destination) { this.destination.add(destination); }
+ public boolean empty() { return data.isEmpty(); }
+ public String toString() { return Ship.this.name+"."+name; }
+ public Outbox(String name) {
+ this.name = name;
+ Ship.this.outboxes.put(name, this);
+ }
+ }
+}
--- /dev/null
+
+#import edu.berkeley.fleet
+
+#ship adder : AdderShip
+#ship memread : MemReadShip
+#ship memwrite : MemWriteShip
+#ship one : OneProducerShip
+#ship halt : HaltShip
+
+#memory { 000, 100, 200, 300, 400, 500 }
+
+one.out -> adder.in1
+one.out -> adder.in2
+adder.out -> memread.addr
+memread.data -> adder.in1
+one.out -> adder.in2
+adder.out -> halt.in