-package edu.berkeley.fleet.parser;
+package edu.berkeley.fleet.assembler;
import edu.berkeley.fleet.api.*;
-// used only for special interpreter parsing extensions
-import edu.berkeley.fleet.interpreter.Interpreter;
-import edu.berkeley.fleet.interpreter.CodeBag;
-
import edu.berkeley.sbp.*;
import edu.berkeley.sbp.chr.*;
import edu.berkeley.sbp.misc.*;
import java.util.*;
import java.io.*;
-// FIXME: eliminate use of CodeBag class
-
/**
* @author Adam Megacz <megacz@cs.berkeley.edu>
- * @author Thomas Kho <tkho@eecs.berkeley.edu>
*/
-public class Parser {
+class Parser {
- public Parser(Fleet fleet) {
+ Parser(Fleet fleet) {
this.fleet = fleet;
}
//////////////////////////////////////////////////////////////////////////////
- private HashMap<String,Ship> shipMap =
- new HashMap<String,Ship>();
+ private Fleet fleet;
+ private ArrayList<String> imports = new ArrayList<String>();
- static Tree<String> parse(Reader r) throws Exception {
+ private HashMap<String,Ship> shipMap = new HashMap<String,Ship>();
+
+ // codebags in numerical order
+ private ArrayList<CodeBag> codeBags = new ArrayList<CodeBag>();
+ private HashMap<String,CodeBag> codeBagsByName = new HashMap<String,CodeBag>();
+
+ Tree<String> parse(Reader r) throws Exception {
InputStream grammarStream =
Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/parser/fleet.g");
CharParser metaGrammarParser = new CharParser(MetaGrammar.newInstance());
return tree;
}
- private Fleet fleet;
- private ArrayList<String> imports = new ArrayList<String>();
+ public void parse(Reader r, OutputStream out) 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);
+
+ // 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);
+ 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);
+ }
+
+ // now write for real
+ dos = new DataOutputStream(out);
+ cos = new CountingOutputStream(dos);
+ 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());
+ }
+ fleet.writeInstruction(dos, inst);
+ }
+ }
+ dos.flush();
+ }
+
+ 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);
+ // 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);
+ }
- public CodeBag walk(Reader r) throws Exception {
- return walk((Tree<String>)parse(r));
+ // 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);
+ }
+ }
}
- CodeBag walk(Tree<String> t) {
- CodeBag rootCodeBag = null;
+ /** in the first pass, codebags are assigned "addresses" in arbitrary order */
+ void walk(Tree<String> t, CodeBag cb) {
+
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);
+ walk(tc, cb);
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)));
String name = name(t.child(0));
String type = string(t.child(1));
Ship ship = null;
- if (fleet instanceof Fleet) {
+ 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)fleet).tryCreate(s+"."+classname, name)) != null)
+ if ((ship = interpreter.tryCreate(s+"."+classname, name)) != null)
break;
if (ship==null)
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))))));
+ walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))), cb);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else if (head.equals("Memory")) {
- if (((Interpreter)fleet).mem.length != 0)
+ 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)));
- ((Interpreter)fleet).mem = mem;
+ ((edu.berkeley.fleet.interpreter.Interpreter)fleet).mem = mem;
}
- return rootCodeBag;
}
String string(Tree<String> t) {
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)));
+ CodeBag cb2 = new CodeBag(name(t.child(0)));
for(Tree<String> statement : t.child(1))
fillCodeBag(statement, cb2);
else if ("Ack".equals(ttt.head())) { tokenOut = true; dest = portReference(ttt.child(0)); }
}
cb.add(new Instruction.Executable(benkobox,
- dest, count, tokenIn, dataIn, latch, dataOut, tokenOut, recycle));
+ dest, count, tokenIn, dataIn,
+ latch, dataOut, tokenOut, recycle));
}
}
}
+
+ 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 getFakeAddress() { return codeBags.indexOf(this); }
+ public boolean equals(Object o) { return this==o; }
+ }
+
}