ShipDescription: add support for conditional sections
[fleet.git] / src / edu / berkeley / fleet / two / ShipDescription.java
index 159442c..19be168 100644 (file)
@@ -6,18 +6,27 @@ import java.util.*;
 /** NOT YET FINALIZED: A description (specification) of a ship */
 public class ShipDescription implements Iterable<DockDescription> {
 
+    private Fleet fleet;
     private String name;
-    private LinkedHashMap<String,DockDescription> docks     = new LinkedHashMap<String,DockDescription>();
-    private HashMap<String,String>                sections  = new HashMap<String,String>();
-    private HashMap<String,Constant>              constants = new HashMap<String,Constant>();
+    private LinkedHashMap<String,DockDescription> docks         = new LinkedHashMap<String,DockDescription>();
+    private LinkedHashMap<String,DockDescription> ports = new LinkedHashMap<String,DockDescription>();
+    private HashMap<String,String>                sections      = new HashMap<String,String>();
+    private HashMap<String,BitVector>              constants     = new HashMap<String,BitVector>();
 
     public String getName() { return name; }
     public String getSection(String sectionName) { return sections.get(sectionName); }
     public DockDescription getDockDescription(String name) { return docks.get(name); }
     public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
+    public Iterable<DockDescription> ports() {
+        return ports.values();
+    }
+
+    public final LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
 
-    public ShipDescription(String name, BufferedReader r) throws IOException {
+    public ShipDescription(Fleet fleet, String name, BufferedReader r) throws IOException {
+        if (name.endsWith(".ship")) name = name.substring(0, name.length()-".ship".length());
         this.name = name;
+        this.fleet = fleet;
         String sectionName = null;
         StringBuffer sb = new StringBuffer();
         while(true) {
@@ -31,6 +40,21 @@ public class ShipDescription implements Iterable<DockDescription> {
                     sectionName = sectionName.substring(1);
                 while(sectionName.endsWith("="))
                     sectionName = sectionName.substring(0, sectionName.length()-1);
+                sectionName = sectionName.trim();
+
+                if (sectionName.indexOf(':') != -1) {
+                    String subtype = sectionName.substring(sectionName.indexOf(':')+1);
+                    sectionName = sectionName.substring(0, sectionName.indexOf(':'));
+                    boolean good = false;
+                    for(Class c = fleet.getClass(); c!=Object.class; c = c.getSuperclass()) {
+                        if (subtype.equals(c.getSimpleName()))
+                            good = true;
+                    }
+                    if (!good) {
+                        sectionName = null;
+                        continue;
+                    }
+                }
                 sectionName = sectionName.trim().toLowerCase();
                 continue;
             }
@@ -40,8 +64,10 @@ public class ShipDescription implements Iterable<DockDescription> {
             processSection(s);
     }
 
-    public Constant getConstant(String name) {
-        return constants.get(name);
+    public BitVector getConstant(String name) {
+        BitVector c = constants.get(name);
+        if (c==null) throw new RuntimeException("unknown constant " + name);
+        return c;
     }
 
     private void processSection(String section) throws IOException {
@@ -62,7 +88,7 @@ public class ShipDescription implements Iterable<DockDescription> {
                 if (key.startsWith("constant")) {
                     String constname = key.substring("constant".length()+1).trim();
                     String val       = s.substring(s.indexOf(':')+1).trim();
-                    constants.put(constname, new Constant(val));
+                    constants.put(constname, new BitVector(fleet.getWordWidth()).set(Integer.parseInt(val)));
                 }
             }
         } else if (section.equals("ports")) {
@@ -74,15 +100,30 @@ public class ShipDescription implements Iterable<DockDescription> {
 
                 String key = s.substring(0, s.indexOf(':')).trim();
                 boolean inbox = false;
+                boolean dockless = false;
                 key = key.replaceAll("  +", " ");
                 if      (key.equals("data in"))   { inbox = true;  }
                 else if (key.equals("data out"))  { inbox = false; }
                 else if (key.equals("in"))        { inbox = true;  }
+                else if (key.equals("dockless out")) { inbox = false; dockless = true; }
                 else if (key.equals("out"))       { inbox = false; }
+                else if (key.startsWith("percolate")) { 
+                    key = s;
+                    key = key.substring("percolate".length()+1).trim();
+                    PercolatedPort.PortType type = null;
+                    if (key.startsWith("up")) type = PercolatedPort.PortType.UP;
+                    if (key.startsWith("down")) type = PercolatedPort.PortType.DOWN;
+                    if (key.startsWith("inout")) type = PercolatedPort.PortType.INOUT;
+                    key = key.substring(key.indexOf(':')+1).trim();
+                    String name = key.substring(0, key.indexOf(' '));
+                    int width = Integer.parseInt(key.substring(key.indexOf(' ')).trim());
+                    percolatedPorts.add(new PercolatedPort(name, width, type));
+                    continue;
+                }
                 else if (key.startsWith("constant")) {
                     String constname = key.substring("constant".length()+1).trim();
                     String val       = s.substring(s.indexOf(':')+1).trim();
-                    p.addConstant(constname, new Constant(val));
+                    p.addConstant(constname, new BitVector(fleet.getWordWidth()).set(Integer.parseInt(val)));
                     continue;
                 } else if (key.startsWith("shortcut to")) {
                     continue;
@@ -95,8 +136,9 @@ public class ShipDescription implements Iterable<DockDescription> {
                 String dest    = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1)  : "";
                 p = docks.get(boxname);
                 if (p==null) {
-                    p = new DockDescription(this, boxname, !rightSide, inbox);
-                    docks.put(boxname, p);
+                    p = new DockDescription(this, boxname, !rightSide, inbox, dockless);
+                    ports.put(boxname, p);
+                    if (!dockless) docks.put(boxname, p);
                 }
             }
         }
@@ -180,33 +222,4 @@ public class ShipDescription implements Iterable<DockDescription> {
             pw.println(tex);
     }
 
-    // FIXME: merge with BitMask
-    public class Constant {
-        public long    setbits   = 0;
-        public long    clearbits = 0;
-        public boolean signExtend = false;
-        public int     numberOffset = 0;
-        public int     numberWidth = 0;
-        public Constant(String s) {
-            if (s.startsWith("0x")) {
-                setbits = Long.parseLong(s.substring(2), 16);
-                clearbits = ~setbits;
-            } else if (s.length() == 37) {
-                for(int i=36; i>=0; i--) {
-                    char c = s.charAt(36-i);
-                    switch(c) {
-                        case '0': clearbits |= (1<<i); break;
-                        case '1': setbits   |= (1<<i); break;
-                        case '.': break;
-                        case 's': signExtend = true;  numberOffset = i; numberWidth++; break;
-                        case 'u': signExtend = false; numberOffset = i; numberWidth++; break;
-                    }
-                }
-            } else {
-                setbits = Long.parseLong(s);
-                clearbits = ~setbits;
-            }
-        }
-    }
-
 }