added #import, broke demo into two files
[fleet.git] / src / edu / berkeley / fleet / FleetParser.java
index b05e75c..1e32059 100644 (file)
@@ -8,55 +8,211 @@ import edu.berkeley.sbp.bind.*;
 import edu.berkeley.sbp.util.*;
 import java.util.*;
 import java.io.*;
+import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
 
+/**
+ *  @author Adam Megacz <megacz@cs.berkeley.edu>
+ *  @author Thomas Kho <tkho@eecs.berkeley.edu>
+ */
 public class FleetParser {
 
     public static void main(String[] s) throws Exception {
+        for(int i=0; i<s.length; i++) {
+            if (s[i].startsWith("--color=")) {
+                String val = s[i].substring(s[i].indexOf('=')+1);
+                if (val.equals("on")) {
+                    Log.ansi_color = true;
+                    continue;
+                } else if (val.equals("off")) {
+                    Log.ansi_color = false;
+                    continue;
+                }
+            } else if (s[i].startsWith("--inboxes=")) {
+                String val = s[i].substring(s[i].indexOf('=')+1);
+                if (val.equals("configured")) {
+                    DataInbox.defaultInstruction =
+                        new Instruction(null, null, Integer.MAX_VALUE, TAKE, false, false, true);
+                    continue;
+                } else if (val.equals("unconfigured")) {
+                    DataInbox.defaultInstruction = null;
+                    continue;
+                }
+            } else if (s[i].startsWith("--memory=")) {
+                String val = s[i].substring(s[i].indexOf('=')+1);
+                if (val.equals("hide")) {
+                    debugMemory = false;
+                    continue;
+                } else if (val.equals("show")) {
+                    debugMemory = true;
+                    continue;
+                }
+            }
+            System.out.println("Fleeterpreter usage:");
+            System.out.println("");
+            System.out.println("  --color={on|off}");
+            System.out.println("  --inboxes={configured|unconfigured}");
+            System.out.println("  --memory={hide|show}");
+            System.exit(-1);
+        }
         go(new InputStreamReader(System.in));
     }
 
     public static void go(Reader r) throws Exception {
+        Fleet fleet = new Fleet();
+        FleetParser fp = new FleetParser(fleet);
+        fp.walk((Tree<String>)parse(r));
+        fp.done();
+    }
+
+    public static Tree<String> parse(Reader r) 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);
+        Union   grammar            = Grammar.create(parsedGrammar, "s", new Grammar.Bindings() { });
+        Parser  parser             = new CharParser(grammar);
+        Tree tree = parser.parse(new CharInput(r)).expand1();
+        return tree;
+    }
 
-        Log.println("about to parse: tests/test.fleet");
-        Tree tree = mathParser.parse(new CharInput(r)).expand1();
+    private Fleet fleet;
+    private ArrayList<String> imports = new ArrayList<String>();
+    private CodeBag rootCodeBag;
+    private static boolean debugMemory = true;
 
-        // 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.
+    public FleetParser(Fleet fleet) {
+        this.fleet = fleet;
+    }
 
-        Log.println();
-        Log.println("dispatching root codebag:");
-        Log.println(program.root);
+    public void done() {
+        if (rootCodeBag != null) {
+            if (debugMemory) { fleet.dumpMem(); }
+            System.out.println(rootCodeBag);
+            rootCodeBag.dispatch(fleet);
+            fleet.go();
+            if (debugMemory) { fleet.dumpMem(); }
+        }
+    }
 
-        Fleet fleet = new Fleet();
-        program.configure(fleet);
-
-        Log.println("memory before execution:");
-        Log.print("  ");
-        for(int i=0; i<fleet.mem.length; i++)
-            Log.print(fleet.mem[i] + " ");
-        Log.println();
-
-        Log.println();
-        Log.println("enabling execution...");
-        fleet.go();
-        Log.println("execution halted.");
-
-        Log.println();
-        Log.println("memory after execution:");
-        Log.print("  ");
-        for(int i=0; i<fleet.mem.length; i++)
-            Log.print(fleet.mem[i] + " ");
-        Log.println();
+    public void walk(Tree<String> t) {
+        String head = t.head();
+        if (head==null) {
+        } else if (head.equals("Program")) {
+            for(Tree<String> tc : t.child(0))
+                walk(tc);
+            CodeBag cb = new CodeBag(null, null);
+            if (t.size()>1)
+                for(Tree<String> statement : t.child(1))
+                    fillCodeBag(statement, cb);
+            rootCodeBag = cb;
+   
+        } else if (head.equals("Import")) {
+            imports.add(string(t.child(0)));
+
+        } else if (head.equals("Ship")) {
+            String name = name(t.child(0));
+            String classname = string(t.child(1));
+            boolean good = false;
+            for(String s : imports)
+                if (fleet.tryCreate(s+"."+classname, name)) {
+                    good = true;
+                    break;
+                }
+            if (!good)
+                throw new RuntimeException("couldn't find a ship called \""+classname+"\"");
+
+        } else if (head.equals("Include")) {
+            try {
+                walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))));
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            
+        } else if (head.equals("Memory")) {
+            if (fleet.mem.length != 0)
+                throw new RuntimeException("multiple memory directives found");
+            Tree<String> m = t.child(0);
+            int[] mem = new int[m.size()];
+            for(int i=0; i<mem.length; i++)
+                mem[i] = Integer.parseInt(string(m.child(i)));
+            fleet.mem = mem;
+        }
+    }
+
+    public String string(Tree<String> t) {
+        String ret = "";
+        if (t.head() != null) ret += t.head();
+        for(Tree<String> c : t)
+            ret += string(c);
+        return ret;
+    }
+
+    public String name(Tree<String> t) {
+        return string(t.child(0))+string(t.child(1));
+    }
+
+    public PortReference portReference(Tree<String> t) {
+        if (!"Port".equals(t.head())) return null;
+        return new PortReference(name(t.child(0)), name(t.child(1)));
+    }
+
+    public void fillCodeBag(Tree<String> t, CodeBag cb) {
+        if (t.head()==null) return;
+        else if (t.head().equals("NamedCodeBag")) {
+            CodeBag cb2 = new CodeBag(cb, name(t.child(0)));
+            for(Tree<String> statement : t.child(1))
+                fillCodeBag(statement, cb2);
+
+        } else if (t.head().equals("Instruction")) {
+            Tree<String> opcode = t.child(0);
+            boolean trigger = opcode != null && opcode.size()>0 && "Triggered".equals(opcode.child(0).head());
+
+            int count = 0;
+            Tree arrow = t.child(2);
+            if      (arrow.head().equals("->"))     count = 1;
+            else if (arrow.head().equals("-[*]->")) count = Integer.MAX_VALUE;
+            else if (arrow.head().equals("-["))     count = Integer.parseInt(string(arrow.child(0)));
+
+            Tree opcodebody = opcode.size()==0 ? null : opcode.child(0).child(opcode.size()-1);
+            
+            PortReference d = portReference(t.child(3));
+            if (t.child(1).head() == null) {
+                int literal = Integer.parseInt(string(t.child(1)));
+                cb.add(new Literal.LiteralDatum(literal, d, false, count));
+
+            } else if ("AnonymousCodeBag".equals(t.child(1).head())) {
+                CodeBag cb3 = new CodeBag(cb, null);
+                for(Tree<String> tc : t.child(1).child(0))
+                    fillCodeBag(tc, cb3);
+                cb.add(new Literal.LiteralDatum(cb3.getDescriptor(), d, true));
+
+            } else if ("CodeBagRef".equals(t.child(1).head())) {
+                cb.add(new Literal.CodeBagRef(name(t.child(1).child(0)), cb, d));
+
+            } else if ("ShipSpecific".equals(t.child(1).head())) {
+                cb.add(new Literal.ShipSpecific(string(t.child(1).child(0)), d, count));
+
+            } else {
+                PortReference s = portReference(t.child(1));
+                Instruction inst = null;
+                if (opcodebody==null)         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
+                else if (opcodebody.head().equals("nop"))            inst = new Instruction(s, d, count, IGNORE, false,  trigger, false);
+                else if (opcodebody.head().equals("synthesize"))     inst = new Instruction(s, d, count, IGNORE, false,  trigger, true);
+                else if (opcodebody.head().equals("synthesize+ack")) inst = new Instruction(s, d, count, IGNORE, true,   trigger, true);
+                else if (opcodebody.head().equals("wait"))           inst = new Instruction(s, d, count, COPY,   false,  trigger, false);
+                else if (opcodebody.head().equals("discard"))        inst = new Instruction(s, d, count, TAKE,   false,  trigger, false);
+                else if (opcodebody.head().equals("nop+ack"))        inst = new Instruction(s, d, count, IGNORE, true,   trigger, false);
+                else if (opcodebody.head().equals("wait+ack"))       inst = new Instruction(s, d, count, COPY,   true,   trigger, false);
+                else if (opcodebody.head().equals("discard+ack"))    inst = new Instruction(s, d, count, TAKE,   true,   trigger, false);
+                else if (opcodebody.head().equals("copy"))           inst = new Instruction(s, d, count, COPY,   false,  trigger, true);
+                else if (opcodebody.head().equals("copy+ack"))       inst = new Instruction(s, d, count, COPY,   true,   trigger, true);
+                else if (opcodebody.head().equals("move"))           inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
+                else if (opcodebody.head().equals("move+ack"))       inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
+                else if (opcodebody.head().equals("accept"))         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
+                else if (opcodebody.head().equals("accept+ack"))     inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
+                cb.add(inst);
+            }
+        }
     }
 
 }