Merge branch 'master' of git://git.hcoop.net/git/crawshaw/fleet
[fleet.git] / src / edu / berkeley / fleet / assembler / Parser.java
index 2b2dc45..3a1fdbd 100644 (file)
@@ -1,22 +1,37 @@
 package edu.berkeley.fleet.assembler;
-
 import edu.berkeley.fleet.api.*;
-
 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 static edu.berkeley.fleet.util.BitManipulations.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.api.Instruction.Set;
+import static edu.berkeley.fleet.api.Instruction.*;
+import static edu.berkeley.fleet.api.Instruction.Set.*;
+import static edu.berkeley.fleet.api.Predicate.*;
+import edu.berkeley.fleet.two.*;
+import edu.berkeley.fleet.fpga.*;
+import edu.berkeley.fleet.interpreter.*;
 import java.util.*;
 import java.io.*;
 
+
 /**
  *  @author Adam Megacz <megacz@cs.berkeley.edu>
  */
-class Parser {
+public class Parser {
 
-    Parser(Fleet fleet) {
+    private static final BitVector SIGNAL_ZERO = new BitVector(1);
+    private static final BitVector SIGNAL_ONE  = new BitVector(1);
+    static {
+        SIGNAL_ONE.set(0,true);
+    }
+    
+    /** WARNING: this class may change in the future; it is not a stable interface */
+    public Parser(Fleet fleet) {
+        expect = new ArrayList<Long>();
         this.fleet = fleet;
     }
 
@@ -30,92 +45,142 @@ class Parser {
     // codebags in numerical order
     private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
     private HashMap<String,CodeBag> codeBagsByName = new HashMap<String,CodeBag>();
+    
+    private CodeBag getCodeBag(String name) {
+        CodeBag cb = codeBagsByName.get(name);
+        if (cb!=null) return cb;
+        return new CodeBag(name);
+    }
 
-    Tree<String> parse(Reader r) throws Exception {
+    private static Union grammar;
+    private static synchronized Union getGrammar() throws Exception {
+        if (grammar != null) return grammar;
         InputStream grammarStream =
             Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/assembler/fleet.g");
-        CharParser metaGrammarParser   = new CharParser(MetaGrammar.newInstance());
+        CharParser metaGrammarParser   = new CharParser(GrammarAST.getMetaGrammar());
         Tree<String> parsedGrammar     = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
-        Union   grammar                = Grammar.create(parsedGrammar, "s", new Grammar.Bindings() { });
-        CharParser  parser             = new CharParser(grammar);
-        Tree tree = parser.parse(new CharInput(r)).expand1();
-        return tree;
+        grammar                        = GrammarAST.buildFromAST(parsedGrammar, "s", new GrammarAST.ImportResolver() {
+                public InputStream getImportStream(String importname) { return null; }
+            });
+        return grammar;
     }
 
-    public void parse(Reader r, OutputStream out) throws Exception {
+    // FIXME: this ought to be cached via serialization, I think
+    private static CharParser cp = null;
+    Tree<String> parseIt(Reader r) throws Exception {
+        if (cp==null)
+            cp = new CharParser(getGrammar());
+        CharInput ci = new CharInput(r);
+        Forest f = cp.parse(ci);
+        return f.expand1();
+    }
 
+    public Instruction[] parse(Reader r) throws Exception {
         // this needs to be "code bag zero"
         CodeBag baseCodeBag = new CodeBag();
         CodeBag rootCodeBag = new CodeBag();
-        baseCodeBag.add(new Instruction.Literal.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1));
-        walk((Tree<String>)parse(r), rootCodeBag);
-        
+        skip = false;
+        Tree<String> parsed = (Tree<String>)parseIt(r);
+        walk(parsed, rootCodeBag);
+
         // map from arbitrary identifiers to actual addresses
         int[] codeBagMap = new int[codeBags.size()];
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        CountingOutputStream cos   = new CountingOutputStream(baos);
-        DataOutputStream dos       = new DataOutputStream(cos);
+        int count = 0;
         for(int i=0; i<codeBags.size(); i++) {
             CodeBag c = codeBags.get(i);
-            dos.flush();
-            codeBagMap[i] = cos.getCount();
-            for(Instruction inst : c)
-                fleet.writeInstruction(dos, inst);
+            codeBagMap[i] = count;
+            for(Instruction inst : c) {
+                count++;
+            }
         }
 
         // now write for real
-        dos = new DataOutputStream(out);
-        cos = new CountingOutputStream(dos);
+        count = 0;
+        ArrayList<Instruction> ret = new ArrayList<Instruction>();
         for(int i=0; i<codeBags.size(); i++) {
             CodeBag c = codeBags.get(i);
-            dos.flush();
-            for(Instruction inst : c) {
-                if (inst instanceof Instruction.Literal.CodeBagDescriptor) {
-                    dos.flush();
-                    cos.getCount();
-                    Instruction.Literal.CodeBagDescriptor old = (Instruction.Literal.CodeBagDescriptor)inst;
-                    int offset = fleet.computeOffset(cos.getCount(), codeBagMap[(int)old.offset]);
-                    inst = new Instruction.Literal.CodeBagDescriptor(old.dest,
-                                                                     offset,
-                                                                     codeBags.get((int)old.offset).size());
+            for(int j=0; j<c.size(); j++) {
+                Instruction inst = c.get(j);
+                if (c.isCBD.contains(j)) {
+                    Set old = (Set)inst;
+                    long lit = 0;
+                    lit = ((FleetTwoFleet)fleet).CBD_SIZE.setval(lit, codeBags.get((int)old.immediate).size());
+                    lit = ((FleetTwoFleet)fleet).CBD_OFFSET.setval(lit, codeBagMap[(int)old.immediate]);
+                    inst = new Set(old.dock, false, IgnoreOLC, SetDest.DataLatch, lit);
                 }
-                fleet.writeInstruction(dos, inst);
+                ret.add(inst);
+                count++;
             }
         }
-        dos.flush();
+        long startcbd = 0;
+        for(int i=0; i<codeBags.size(); i++) {
+            if (codeBags.get(i)==rootCodeBag) {
+                long lit = 0;
+                lit = ((FleetTwoFleet)fleet).CBD_SIZE.setval(lit, codeBags.get(i).size());
+                lit = ((FleetTwoFleet)fleet).CBD_OFFSET.setval(lit, codeBagMap[i]);
+                startcbd = lit;
+            }
+        }
+        if (codeBags.size()<=2)
+            return (Instruction[])ret.toArray(new Instruction[0]);
+        return fixup((Instruction[])ret.toArray(new Instruction[0]), startcbd);
     }
 
-    public void parse(Reader r, ArrayList<Instruction> out) throws Exception {
-        // this needs to be "code bag zero"
-        CodeBag baseCodeBag = new CodeBag();
-        CodeBag rootCodeBag = new CodeBag();
-        Instruction inst0 = new Instruction.Literal.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1);
-        baseCodeBag.add(inst0);
-        walk((Tree<String>)parse(r), rootCodeBag);
+    private Instruction[] fixup(Instruction[] instructions, long startcbd) {
+        ArrayList<Instruction> ret = new ArrayList<Instruction>();
+        Fleet fpga = fleet;
 
-        // map from arbitrary identifiers to actual addresses
-        int[] codeBagMap = new int[codeBags.size()];
-        ArrayList<Instruction> temp = new ArrayList<Instruction>();
-        for(int i=0; i<codeBags.size(); i++) {
-            codeBagMap[i] = temp.size();
-            for(Instruction inst : codeBags.get(i))
-                temp.add(inst);
-        }
+        Dock inAddrWrite = null;
+        Dock inDataWrite = null;
+        Dock inCBD       = null;
+        Dock out         = null;
+        Dock debugIn     = null;
+        Dock ihorn       = null;
 
-        // now write for real
-        for(int i=0; i<codeBags.size(); i++) {
-            CodeBag c = codeBags.get(i);
-            for(Instruction inst : c) {
-                if (inst instanceof Instruction.Literal.CodeBagDescriptor) {
-                    Instruction.Literal.CodeBagDescriptor old = (Instruction.Literal.CodeBagDescriptor)inst;
-                    int offset = fleet.computeOffset(out.size(), codeBagMap[(int)old.offset]);
-                    inst = new Instruction.Literal.CodeBagDescriptor(old.dest,
-                                                                     offset,
-                                                                     codeBags.get((int)old.offset).size());
-                }
-                out.add(inst);
+        for(Ship ship : fpga) {
+            if ("Memory".equals(ship.getType()) && ship.getOrdinal()==0) {
+                inAddrWrite = ship.getDock("inAddrWrite");
+                inDataWrite = ship.getDock("inDataWrite");
+                inCBD = ship.getDock("inCBD");
+                out = ship.getDock("out");
+                ihorn = out;
+                //ihorn = ship.getDock("outIhorn");
+            }
+            if ("Debug".equals(ship.getType()) && ship.getOrdinal()==0) {
+                debugIn = ship.getDock("in");
             }
         }
+
+        for(int i=0; i<instructions.length; i++) {
+            long lit = ((FleetTwoFleet)fpga).writeInstruction(instructions[i], out);
+            ret.add(discard(out));
+            ret.add(new Instruction.Shift(inDataWrite, false, IgnoreOLC, new BitVector(fpga.getShiftWidth()).set(getField(36, 19, lit))));
+            ret.add(new Instruction.Shift(inDataWrite, false, IgnoreOLC, new BitVector(fpga.getShiftWidth()).set(getField(18,  0, lit))));
+            ret.add(deliver(inDataWrite));
+            ret.add(new Instruction.Shift(inAddrWrite, false, IgnoreOLC, new BitVector(fpga.getShiftWidth()).set(getField(36, 19, i))));
+            ret.add(new Instruction.Shift(inAddrWrite, false, IgnoreOLC, new BitVector(fpga.getShiftWidth()).set(getField(18,  0, i))));
+            ret.add(deliver(inAddrWrite));
+        }
+        ret.add(new Instruction.Shift(inCBD, false, IgnoreOLC, new BitVector(fpga.getShiftWidth()).set(getField(36, 19, startcbd))));
+        ret.add(new Instruction.Shift(inCBD, false, IgnoreOLC, new BitVector(fpga.getShiftWidth()).set(getField(18,  0, startcbd))));
+        ret.add(wait(inCBD));
+        ret.add(deliver(inCBD));
+        ret.add(sendto(out, out.getPath(inCBD.getDataDestination(),null)));
+
+        int count = (int)((FleetTwoFleet)fleet).CBD_SIZE.getval(startcbd);
+        // FIXME FIXME FIXME!
+        int MAX_ILC = 31;
+        int num_instrs = 0;
+        while(count > 0) {
+            int num = Math.min(count, MAX_ILC);
+            num_instrs+=2;
+            count -= num;
+            ret.add(new Instruction.Set(ihorn, false, IgnoreOLC, SetDest.InnerLoopCounter, num));
+            ret.add(new Instruction.Move(ihorn, false, IgnoreOLC, false, null,false,true,true,true,true,false));
+        }
+        if (num_instrs > ihorn.getInstructionFifoSize()) throw new RuntimeException();
+
+        return (Instruction[])ret.toArray(new Instruction[0]);
     }
 
     /** in the first pass, codebags are assigned "addresses" in arbitrary order */
@@ -130,47 +195,30 @@ class Parser {
                 for(Tree<String> statement : t.child(1))
                     fillCodeBag(statement, cb);
    
-        } else if (head.equals("Import")) {
-            imports.add(string(t.child(0)));
-
-        } else if (head.equals("Ship")) {
+        } else if (head.equals("#ship")) {
             String name = name(t.child(0));
             String type = string(t.child(1));
             Ship ship = null;
-            if (fleet instanceof edu.berkeley.fleet.interpreter.Interpreter) {
-                edu.berkeley.fleet.interpreter.Interpreter interpreter =
-                    ((edu.berkeley.fleet.interpreter.Interpreter)fleet);
-                String classname = type;
-                boolean good = false;
-                for(String s : imports)
-                    if ((ship = interpreter.tryCreate(s+"."+classname, name)) != null)
-                        break;
+
+            if (fleet instanceof FleetWithDynamicShips) {
+                FleetWithDynamicShips dyn = ((FleetWithDynamicShips)fleet);
+                ship = dyn.createShip(type, name);
                 if (ship==null)
-                    throw new RuntimeException("couldn't find a ship called \""+classname+"\"");
+                    throw new RuntimeException("couldn't find a ship called \""+type+"\"");
             } else {
                 ship = allocateShip(type);
             }
             shipMap.put(name, ship);
 
-        } else if (head.equals("Include")) {
-            try {
-                walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))), cb);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-            
-        } else if (head.equals("Memory")) {
-            if (((edu.berkeley.fleet.interpreter.Interpreter)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)));
-            ((edu.berkeley.fleet.interpreter.Interpreter)fleet).mem = mem;
+        } else if (head.equals("#expect")) {
+            expect.add(number(t.child(0)));
+        } else if (head.equals("#skip")) {
+            skip = true;
+
         }
     }
 
-    String string(Tree<String> t) {
+    private static String string(Tree<String> t) {
         String ret = "";
         if (t.head() != null) ret += t.head();
         for(Tree<String> c : t)
@@ -178,23 +226,55 @@ class Parser {
         return ret;
     }
 
-    String name(Tree<String> t) {
+    private static String stringBody(Tree<String> t) {
+        String ret = "";
+        for(Tree<String> c : t)
+            ret += string(c);
+        return ret;
+    }
+
+    private static String name(Tree<String> t) {
         return string(t.child(0))+string(t.child(1));
     }
 
-    BenkoBox portReference(Tree<String> t) {
-        if (!"Port".equals(t.head())) return null;
+    Path path(Dock dock, Tree<String> t) {
+        if (!"Dock".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
         String shipName = name(t.child(0));
         String portName = name(t.child(1));
         Ship ship = shipMap.get(shipName);
         if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
-        for(BenkoBox b : ship.getBenkoBoxes())
+        Destination ret = null;
+        Dock bb = null;
+        for(Dock b : ship)
+            if (b.getName().equals(portName)) {
+                bb = b;
+            }
+        if (bb==null)
+            throw new RuntimeException("no such pump \""+portName+"\"");
+        if (t.size() >= 3) {
+            if (":i".equals(t.child(2).head())) return dock.getPath(bb.getInstructionDestination(),SIGNAL_ZERO);
+            if (":1".equals(t.child(2).head())) return dock.getPath(bb.getDataDestination(),SIGNAL_ONE);
+            if (":0".equals(t.child(2).head())) return dock.getPath(bb.getDataDestination(),SIGNAL_ZERO);
+        }
+        return dock.getPath(bb.getDataDestination(),SIGNAL_ZERO);
+    }
+
+    Dock dock(Tree<String> t) {
+        if (!"Dock".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head()))
+            throw new RuntimeException(t+"");
+        String shipName = name(t.child(0));
+        String portName = name(t.child(1));
+        Ship ship = shipMap.get(shipName);
+        if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\"");
+        Dock bb = null;
+        for(Dock b : ship)
             if (b.getName().equals(portName))
                 return b;
-        throw new RuntimeException("no such benkobox \""+portName+"\" on ships of type \""+ship.getType()+"\"");
+        throw new RuntimeException("no such pump \""+portName+"\"");
     }
 
     private HashMap<String,Integer> numAllocated = new HashMap<String,Integer>();
+
     Ship allocateShip(String shipType) {
         int allocated = 0;
         if (numAllocated.get(shipType) != null)
@@ -212,84 +292,298 @@ class Parser {
         throw new RuntimeException("no more ships of type \""+shipType+"\"");
     }
 
+    private long parseSSL(Tree t) {
+        String shipType = name(t.child(0));
+        String portName = name(t.child(1));
+        Ship chosenship = null;
+        for(Ship ship : fleet) {
+            if (ship.getType().equals(shipType)) {
+                chosenship = ship;
+                break;
+            }
+        }
+        if (chosenship==null) throw new RuntimeException("no ships of type " + shipType);
+        Dock chosenport = chosenship.getDock(portName);
+        Tree specs = t.child(2);
+        long literal = 0;
+        for(int i=0; i<specs.size(); i++) {
+            Tree tt = specs.child(i);
+            literal |= resolveLiteral(chosenport, stringBody(tt));
+        }
+        return literal;
+    }
+
+    private static long resolveLiteral(Dock dd, String s) {
+        long val = 0;
+        long ret = 0;
+        boolean hasval = false;
+        if (s.indexOf('=') != -1) {
+            val = Long.parseLong(s.substring(s.indexOf('=')+1));
+            s = s.substring(0, s.indexOf('='));
+            hasval = true;
+        }
+        ShipDescription.Constant c = ((FleetTwoDock)dd).getDockConstant(s);
+        if (c==null) throw new RuntimeException("no constant " + s + " on dock " + dd);
+        ret |= c.setbits;
+        ret &= ~c.clearbits;
+        if (hasval)
+            ret |= ((~(0xffffffffffffffffL << c.numberWidth)) & val) << c.numberOffset;
+        return ret;
+    }
+
+    private static FlagFunction parseFlags(Tree<String> t) {
+        FlagFunction ret = FlagFunction.ZERO;
+        for(int i=0; i<t.size(); i++) {
+            String s = t.child(i).head();
+            if (s.equals("0"))  ret = ret.add(FlagFunction.ZERO);
+            if (s.equals("1"))  ret = ret.add(FlagFunction.ONE);
+            if (s.equals("a"))  ret = ret.add(FlagA);
+            if (s.equals("!a")) ret = ret.add(NotFlagA);
+            if (s.equals("b"))  ret = ret.add(FlagB);
+            if (s.equals("!b")) ret = ret.add(NotFlagB);
+            if (s.equals("c"))  ret = ret.add(FlagC);
+            if (s.equals("!c")) ret = ret.add(NotFlagC);
+        }
+        return ret;
+    }
+
+    private int anoncount = 1;
     void fillCodeBag(Tree<String> t, CodeBag cb) {
         if (t.head()==null) return;
-        else if (t.head().equals("NamedCodeBag")) {
-            CodeBag cb2 = new CodeBag(name(t.child(0)));
+        else if (t.head().equals("CodeBagDef")) {
+            CodeBag cb2 = getCodeBag(name(t.child(0)));
             for(Tree<String> statement : t.child(1))
                 fillCodeBag(statement, cb2);
 
-        } else if (t.head().equals("Literal")) {
-            int literal = Integer.parseInt(string(t.child(0)));
-            BenkoBox benkobox = portReference(t.child(1));
-            cb.add(new Instruction.Literal.Absolute(benkobox, literal));
-
         } else if (t.head().equals("Fiber")) {
-            BenkoBox benkobox = portReference(t.child(0));
+            Dock dock = (Dock)dock(t.child(0));
             
             OUTER: for(Tree tt : t.child(1)) {
+
+                if ("tail".equals(tt.head()))    {
+                    cb.add(new Tail(dock));
+                    continue;
+                }
+
                 int count = 1;
-                Tree ttx = null;
-                boolean recycle = false;
-                ttx = tt.child(1);
-                if (tt.size() > 1) {
-                    tt = tt.child(0);
-                    if (tt.size() > 0 && tt.child(0).size()>0) {
-                        tt = tt.child(0);
-                        if (tt.child(0).size() == 0) count=1;
-                        else if (tt.child(0).size() > 0 && "Star".equals(tt.child(0).child(0).head())) count=0;
-                        else count = Integer.parseInt(string(tt.child(0)));
-                        if (tt.size() > 1 && tt.child(1).size() > 0)
-                            recycle = true;
+                Predicate predicate = Default;
+                boolean looping = false;
+                boolean interruptible = false;
+                for(int i=0; i<tt.child(0).size(); i++) {
+                    Tree ttt = tt.child(0).child(i);
+                    if ("[a]".equals(ttt.head()))  predicate = FlagA;
+                    if ("[b]".equals(ttt.head()))  predicate = FlagB;
+                    if ("[c]".equals(ttt.head()))  predicate = FlagC;
+                    if ("[!a]".equals(ttt.head())) predicate = NotFlagA;
+                    if ("[!b]".equals(ttt.head())) predicate = NotFlagB;
+                    if ("[!c]".equals(ttt.head())) predicate = NotFlagC;
+                    if ("[*]".equals(ttt.head()))  predicate = IgnoreOLC;
+                    if ("[olc=0]".equals(ttt.head()))  predicate = OLCZero;
+                    if ("[Rq]".equals(ttt.head()))  looping = true;
+                }
+                tt = tt.child(1);
+                if ("tail".equals(tt.head()))    {
+                    cb.add(new Tail(dock));
+                    continue;
+                } else if ("flags".equals(tt.head()))    {
+                    cb.add(new Set(dock, looping, predicate, parseFlags(tt.child(0)), parseFlags(tt.child(1))));
+                    continue;
+                } else if ("olc=word".equals(tt.head()))    {
+                    cb.add(new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch));
+                    continue;
+                } else if ("ilc=word".equals(tt.head()))    {
+                    cb.add(new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch));
+                    continue;
+                } else if ("*".equals(tt.head()))    {
+                    cb.add(new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity));
+                    continue;
+                } else if ("olc=int".equals(tt.head()))    {
+                    cb.add(new Set(dock, looping, predicate, SetDest.OuterLoopCounter, (number(tt.child(0)))));
+                    continue;
+                } else if ("ilc=int".equals(tt.head()))    {
+                    cb.add(new Set(dock, looping, predicate, SetDest.InnerLoopCounter, (number(tt.child(0)))));
+                    continue;
+                } else if ("--".equals(tt.head())) {
+                    cb.add(new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.Decrement));
+                    continue;
+                } else if ("nop".equals(tt.head())) {
+                    if (tt.size() > 0 && "[T]".equals(tt.child(0).head())) interruptible = true;
+                    cb.add(new Move(dock, looping, predicate, interruptible, null, false, false, false, false, false, false));
+                } else if ("shift".equals(tt.head())) {
+                    cb.add(new Shift(dock, looping, predicate,
+                                     new BitVector(dock.getShip().getFleet().getShiftWidth()).set(number(tt.child(0)))));
+                    continue;
+                } else if ("flush".equals(tt.head())) {
+                    cb.add(new Flush(dock, looping, predicate));
+                    continue;
+                } else if ("word".equals(tt.head())) {
+                    long literal = 0;
+                    if (tt.child(0).head().equals("CodeBagBody")) {
+                        Tree<String> tq = tt;
+                        CodeBag cb2 = getCodeBag("anon"+(anoncount++));
+                        for(Tree<String> statement : tq.child(0))
+                            fillCodeBag(statement, cb2);
+                        cb.add(new Set(dock, looping, predicate, SetDest.DataLatch, (cb2.getFakeAddress())), true);
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("Name")) {
+                        String refname = name(tt.child(0));
+                        CodeBag cb2 = getCodeBag(refname);
+                        cb.add(new Set(dock, looping, predicate, SetDest.DataLatch, (cb2.getFakeAddress())), true);
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("[")) {
+                        literal = parseSSL(tt.child(0));
+                    } else {
+                        literal = number(tt.child(0));
+                    }
+                    count = 1;
+                    /*
+                    if ("int".equals(tt.child(1).head())) {
+                        count = (int)number(tt.child(1));
+                    } else if ("forever".equals(tt.child(1).head())) {
+                        count = 0;
                     }
+                    */
+
+
+                    if (((FleetTwoFleet)fleet).isSmallEnoughToFit(literal)) {
+                        cb.add(new Set(dock, looping, predicate, SetDest.DataLatch, (literal)));
+                    } else {
+                        int counter = 0;
+                        while(counter < dock.getShip().getFleet().getWordWidth()) counter += fleet.getShiftWidth();
+                        while(counter > 0) {
+                            cb.add(new Shift(dock, looping, predicate,
+                                             new BitVector(dock.getShip().getFleet().getShiftWidth())
+                                             .set(getField(counter-1, counter-fleet.getShiftWidth(), literal))));
+                            counter -= fleet.getShiftWidth();
+                        }
+                    }
+                        
+                    continue;
                 }
+                Tree ttx = null;
+                boolean requeue = false;
+                if ("[T]".equals(tt.child(0).head()))  interruptible = true;
+                ttx = tt.child(tt.size()-1);
                 boolean tokenIn = false;
                 boolean dataIn = false;
                 boolean latch = false;
                 boolean dataOut = false;
                 boolean tokenOut = false;
-                BenkoBox dest = null;
+                boolean dispatch = false;
+                boolean localLiteral = false;
+                boolean ignoreUntilLast = false;
+                long literal = 0;
+                Path path = null;
                 for(int i=0; i<ttx.size(); i++) {
                     Tree ttt = ttx.child(i);
-                    if      ("Wait".equals(ttt.head()))    { tokenIn = true; }
-                    else if ("Nop".equals(ttt.head()))     { }
-                    else if ("Kill".equals(ttt.head()))    {
-                        cb.add(new Instruction.Kill(benkobox, count));
-                        continue OUTER;
+                    if      ("recv token".equals(ttt.head()))    { tokenIn = true; }
+                    else if ("discard".equals(ttt.head())) { dataIn = true; latch = false; }
+                    else if ("take".equals(ttt.head()))    { dataIn = true; latch = true; }
+                    else if ("collect".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                        latch = true;
+                    }
+                    else if ("collect path".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                        latch = false;
+                        dispatch = true;
+                    }
+                    else if ("collect packet".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                        latch = true;
+                        dispatch = true;
+                    }
+                    else if ("collect nothing".equals(ttt.head()))    {
+                        if (dock.isInputDock())
+                            throw new RuntimeException("you can't use \"collect\" at input docks; try \"recv\" instead");
+                        dataIn = true;
+                    }
+                    else if ("recv".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                        latch = true;
+                    }
+                    else if ("recv path".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                        latch = false;
+                        dispatch = true;
+                    }
+                    else if ("recv packet".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
+                        latch = true;
+                        dispatch = true;
+                    }
+                    else if ("recv nothing".equals(ttt.head()))    {
+                        if (dock.isOutputDock())
+                            throw new RuntimeException("you can't use \"recv\" at input docks; try \"collect\" instead");
+                        dataIn = true;
                     }
-                    else if ("Discard".equals(ttt.head())) { dataIn = true; latch = false; }
-                    else if ("Take".equals(ttt.head()))    { dataIn = true; latch = true; }
-                    else if ("SendTo".equals(ttt.head()))  { dataOut = true; dest = portReference(ttt.child(0)); }
-                    else if ("Deliver".equals(ttt.head())) { dataOut = true;  }
-                    else if ("Ack".equals(ttt.head()))     { tokenOut = true; dest = portReference(ttt.child(0)); }
+                    else if ("send".equals(ttt.head()))  {
+                        dataOut = true;
+                    }
+                    else if ("send to".equals(ttt.head()))  { dataOut = true; path = path(dock, ttt.child(0)); }
+                    else if ("deliver".equals(ttt.head())) { dataOut = true;  }
+                    else if ("send token".equals(ttt.head()))     { tokenOut = true; }
+                    else if ("send token to".equals(ttt.head()))     { tokenOut = true; path = path(dock, ttt.child(0)); }
                 }
-                cb.add(new Instruction.Executable(benkobox,
-                                                  dest, count, tokenIn, dataIn,
-                                                  latch, dataOut, tokenOut, recycle));
+                cb.add(new Move(dock, looping, predicate,
+                                            interruptible, path, tokenIn, dataIn,
+                                            latch, dispatch, dataOut, tokenOut));
             }
         }
     }
 
-    private static class CountingOutputStream extends FilterOutputStream {
-        public CountingOutputStream(OutputStream os) { super(os); }
-        int count = 0;
-        public int getCount() { return count; }
-        public void write(int b) throws IOException {
-            super.write(b);
-            count++;
-        }
-        public void write(byte[] b, int off, int len) throws IOException {
-            super.write(b, off, len);
-            count += len;
-        }
-    }
-
     private class CodeBag extends ArrayList<Instruction> {
-        public int address = -1;
-        public CodeBag() { codeBags.add(this); }
-        public CodeBag(String name) { this(); codeBagsByName.put(name, this); }
+        public long address = -1;
+        public final String name;
+        private HashSet<Integer> isCBD = new HashSet<Integer>();
+        public CodeBag() { codeBags.add(this); this.name = "root"; }
+        public CodeBag(String name) { codeBags.add(this); codeBagsByName.put(name, this); this.name = name; }
         public long getFakeAddress() { return codeBags.indexOf(this); }
         public boolean equals(Object o) { return this==o; }
+        public void add(Instruction i, boolean isCBD) {
+            if (isCBD) this.isCBD.add(size());
+            add(i);
+        }
+    }
+
+    // hideous hack
+    public static ArrayList<Long> expect;
+    public static boolean         skip;
+
+    private static long number(Tree t) {
+        String ret = "";
+        for(Object c : t.child(2)) ret += ((Tree)c).head();
+        boolean negative = "-".equals(t.child(0).head());
+        ret = ret.trim();
+        long val = 0;
+        if      ("0x".equals(t.child(1).head())) val = Long.parseLong(ret, 16);
+        else if ("0b".equals(t.child(1).head())) val = Long.parseLong(ret, 2);
+        else                                     val = Long.parseLong(ret);
+        if (negative) val = -1L * val;
+        return val;
+    }
+    /**
+     *  This interface marks Fleets which can create ships on the fly, like the fleeterpreter;
+     *  if available, the parser will use this interface to create ships out of #ship definitions.
+     */
+    public static interface FleetWithDynamicShips {
+        public Ship createShip(String shiptype, String shipname);
     }
 
+    private static Move discard(Dock dock)           { return new Move(dock, false, IgnoreOLC, false, null, false, true,  false, false, false, false); }
+    private static Move deliver(Dock dock)           { return new Move(dock, false, IgnoreOLC, false, null, false, false, false, false, true,  false); }
+    private static Move wait(Dock dock)              { return new Move(dock, false, IgnoreOLC, false, null, true,  false, false, false, false, false); }
+    private static Move sendto(Dock dock, Path path) { return new Move(dock, false, IgnoreOLC, false, path, false, false, false, false, true,  false); }
 }