Homework 1
This commit is contained in:
parent
49bca7f856
commit
12f678a924
43 changed files with 3703 additions and 0 deletions
121
src/cd/util/FileUtil.java
Normal file
121
src/cd/util/FileUtil.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
package cd.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FileUtil {
|
||||
|
||||
public static String readAll(Reader ubReader) throws IOException {
|
||||
try (BufferedReader bReader = new BufferedReader(ubReader)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (true) {
|
||||
int ch = bReader.read();
|
||||
if (ch == -1)
|
||||
break;
|
||||
|
||||
sb.append((char) ch);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String read(File file) throws IOException {
|
||||
return readAll(new FileReader(file));
|
||||
}
|
||||
|
||||
public static void write(File file, String text) throws IOException {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
writer.write(text);
|
||||
}
|
||||
}
|
||||
|
||||
public static String runCommand(File dir, String[] command,
|
||||
String[] substs, String input, boolean detectError)
|
||||
throws IOException {
|
||||
// Substitute the substitution strings $0, $1, etc
|
||||
String newCommand[] = new String[command.length];
|
||||
for (int i = 0; i < command.length; i++) {
|
||||
String newItem = command[i];
|
||||
for (int j = 0; j < substs.length; j++)
|
||||
newItem = newItem.replace("$" + j, substs[j]);
|
||||
newCommand[i] = newItem;
|
||||
}
|
||||
|
||||
// Run the command in the specified directory
|
||||
ProcessBuilder pb = new ProcessBuilder(newCommand);
|
||||
pb.directory(dir);
|
||||
pb.redirectErrorStream(true);
|
||||
final Process p = pb.start();
|
||||
if (input != null && !input.equals("")) {
|
||||
try (OutputStreamWriter osw = new OutputStreamWriter(p.getOutputStream())) {
|
||||
osw.write(input);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final StringBuffer result = new StringBuffer();
|
||||
// thread to read stdout from child so that p.waitFor() is interruptible
|
||||
// by JUnit's timeout mechanism. Otherwise it would block in readAll()
|
||||
Thread t = new Thread () {
|
||||
public void run() {
|
||||
try {
|
||||
result.append(readAll(new InputStreamReader(p.getInputStream())));
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
t.start();
|
||||
|
||||
if (detectError) {
|
||||
int err = p.waitFor();
|
||||
|
||||
// hack: same as ReferenceServer returns when
|
||||
// a dynamic error occurs running the interpreter
|
||||
if (err != 0)
|
||||
return "Error: " + err + "\n";
|
||||
}
|
||||
|
||||
t.join();
|
||||
return result.toString();
|
||||
} catch (InterruptedException e) {
|
||||
return "Error: execution of " + command[0] + " got interrupted (probably timed out)\n";
|
||||
} finally {
|
||||
// in case child is still running, destroy
|
||||
p.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all .javali under directory {@code testDir}, adding File objects
|
||||
* into {@code result} for each one.
|
||||
*/
|
||||
public static void findJavaliFiles(File testDir, List<Object[]> result) {
|
||||
for (File testFile : testDir.listFiles()) {
|
||||
if (testFile.getName().endsWith(".javali"))
|
||||
result.add(new Object[] { testFile });
|
||||
else if (testFile.isDirectory())
|
||||
findJavaliFiles(testFile, result);
|
||||
}
|
||||
}
|
||||
|
||||
/** Finds all .javali under directory {@code testDir} and returns them. */
|
||||
public static List<File> findJavaliFiles(File testDir) {
|
||||
List<File> result = new ArrayList<File>();
|
||||
for (File testFile : testDir.listFiles()) {
|
||||
if (testFile.getName().endsWith(".javali"))
|
||||
result.add(testFile);
|
||||
else if (testFile.isDirectory())
|
||||
result.addAll(findJavaliFiles(testFile));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
53
src/cd/util/Pair.java
Normal file
53
src/cd/util/Pair.java
Normal file
|
@ -0,0 +1,53 @@
|
|||
package cd.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Simple class for joining two objects of the same type */
|
||||
public class Pair<T> {
|
||||
public T a;
|
||||
public T b;
|
||||
|
||||
public Pair(T a, T b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public static <T> List<Pair<T>> zip(List<T> listA, List<T> listB) {
|
||||
List<Pair<T>> res = new ArrayList<Pair<T>>();
|
||||
for (int i = 0; i < Math.min(listA.size(), listB.size()); i++) {
|
||||
res.add(new Pair<T>(listA.get(i), listB.get(i)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static <T> List<T> unzipA(List<Pair<T>> list) {
|
||||
List<T> res = new ArrayList<T>();
|
||||
for (Pair<T> p : list)
|
||||
res.add(p.a);
|
||||
return res;
|
||||
}
|
||||
|
||||
public static <T> List<T> unzipB(List<Pair<T>> list) {
|
||||
List<T> res = new ArrayList<T>();
|
||||
for (Pair<T> p : list)
|
||||
res.add(p.b);
|
||||
return res;
|
||||
}
|
||||
|
||||
public static String join(
|
||||
List<Pair<?>> pairs,
|
||||
String itemSep,
|
||||
String pairSep) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (Pair<?> pair : pairs) {
|
||||
if (!first) sb.append(pairSep);
|
||||
sb.append(pair.a);
|
||||
sb.append(itemSep);
|
||||
sb.append(pair.b);
|
||||
first = false;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
16
src/cd/util/Tuple.java
Normal file
16
src/cd/util/Tuple.java
Normal file
|
@ -0,0 +1,16 @@
|
|||
package cd.util;
|
||||
|
||||
/** Simple class for joining two objects of different type */
|
||||
public class Tuple<A,B> {
|
||||
public A a;
|
||||
public B b;
|
||||
|
||||
public Tuple(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(" + a.toString() + ", " + b.toString() + ")";
|
||||
}
|
||||
}
|
125
src/cd/util/debug/AstDump.java
Normal file
125
src/cd/util/debug/AstDump.java
Normal file
|
@ -0,0 +1,125 @@
|
|||
package cd.util.debug;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import cd.ir.Ast;
|
||||
import cd.ir.AstVisitor;
|
||||
import cd.util.Pair;
|
||||
|
||||
public class AstDump {
|
||||
|
||||
public static String toString(Ast ast) {
|
||||
return toString(ast, "");
|
||||
}
|
||||
|
||||
public static String toString(List<? extends Ast> astRoots) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Ast a : astRoots) {
|
||||
sb.append(toString(a));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String toString(Ast ast, String indent) {
|
||||
AstDump ad = new AstDump();
|
||||
ad.dump(ast, indent);
|
||||
return ad.sb.toString();
|
||||
}
|
||||
|
||||
public static String toStringFlat(Ast ast) {
|
||||
AstDump ad = new AstDump();
|
||||
ad.dumpFlat(ast);
|
||||
return ad.sb.toString();
|
||||
}
|
||||
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
private Visitor vis = new Visitor();
|
||||
|
||||
protected void dump(Ast ast, String indent) {
|
||||
// print out the overall class structure
|
||||
sb.append(indent);
|
||||
String nodeName = ast.getClass().getSimpleName();
|
||||
List<Pair<?>> flds = vis.visit(ast, null);
|
||||
sb.append(String.format("%s (%s)\n",
|
||||
nodeName,
|
||||
Pair.join(flds, ": ", ", ")));
|
||||
|
||||
// print out any children
|
||||
String newIndent = indent + "| ";
|
||||
for (Ast child : ast.children()) {
|
||||
dump(child, newIndent);
|
||||
}
|
||||
}
|
||||
|
||||
protected void dumpFlat(Ast ast) {
|
||||
String nodeName = ast.getClass().getSimpleName();
|
||||
List<Pair<?>> flds = vis.visit(ast, null);
|
||||
sb.append(String.format("%s(%s)[",
|
||||
nodeName,
|
||||
Pair.join(flds, ":", ",")));
|
||||
|
||||
// print out any children
|
||||
for (int child = 0; child < ast.children().size(); child++) {
|
||||
dumpFlat(ast.children().get(child));
|
||||
if (child < ast.children().size() - 1)
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
sb.append("]");
|
||||
}
|
||||
|
||||
protected class Visitor extends AstVisitor<List<Pair<?>>, Void> {
|
||||
|
||||
@Override
|
||||
protected List<Pair<?>> dflt(Ast ast, Void arg) {
|
||||
ArrayList<Pair<?>> res = new ArrayList<Pair<?>>();
|
||||
|
||||
// Get the list of fields and sort them by name:
|
||||
java.lang.Class<? extends Ast> rclass = ast.getClass();
|
||||
List<java.lang.reflect.Field> rflds =
|
||||
Arrays.asList(rclass.getFields());
|
||||
Collections.sort(rflds, new Comparator<java.lang.reflect.Field> () {
|
||||
public int compare(Field o1, Field o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
// Create pairs for each one that is not of type Ast:
|
||||
for (java.lang.reflect.Field rfld : rflds) {
|
||||
rfld.setAccessible(true);
|
||||
|
||||
// ignore various weird fields that show up from
|
||||
// time to time:
|
||||
if (rfld.getName().startsWith("$"))
|
||||
continue;
|
||||
|
||||
// ignore fields of AST type, and rwChildren (they should be
|
||||
// uncovered using the normal tree walk)
|
||||
if (rfld.getType().isAssignableFrom(Ast.class))
|
||||
continue;
|
||||
if (rfld.getName().equals("rwChildren"))
|
||||
continue;
|
||||
|
||||
// ignore NULL fields, but add others to our list of pairs
|
||||
try {
|
||||
Object value = rfld.get(ast);
|
||||
if (value != null)
|
||||
res.add(new Pair<Object>(rfld.getName(), value));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
160
src/cd/util/debug/AstOneLine.java
Normal file
160
src/cd/util/debug/AstOneLine.java
Normal file
|
@ -0,0 +1,160 @@
|
|||
package cd.util.debug;
|
||||
|
||||
import cd.ir.Ast;
|
||||
import cd.ir.Ast.Assign;
|
||||
import cd.ir.Ast.BinaryOp;
|
||||
import cd.ir.Ast.BooleanConst;
|
||||
import cd.ir.Ast.BuiltInRead;
|
||||
import cd.ir.Ast.BuiltInWrite;
|
||||
import cd.ir.Ast.BuiltInWriteln;
|
||||
import cd.ir.Ast.Cast;
|
||||
import cd.ir.Ast.ClassDecl;
|
||||
import cd.ir.Ast.Field;
|
||||
import cd.ir.Ast.IfElse;
|
||||
import cd.ir.Ast.Index;
|
||||
import cd.ir.Ast.IntConst;
|
||||
import cd.ir.Ast.MethodDecl;
|
||||
import cd.ir.Ast.NewArray;
|
||||
import cd.ir.Ast.NewObject;
|
||||
import cd.ir.Ast.Nop;
|
||||
import cd.ir.Ast.NullConst;
|
||||
import cd.ir.Ast.Seq;
|
||||
import cd.ir.Ast.ThisRef;
|
||||
import cd.ir.Ast.UnaryOp;
|
||||
import cd.ir.Ast.Var;
|
||||
import cd.ir.Ast.VarDecl;
|
||||
import cd.ir.Ast.WhileLoop;
|
||||
import cd.ir.AstVisitor;
|
||||
|
||||
public class AstOneLine {
|
||||
|
||||
public static String toString(Ast ast) {
|
||||
return new Visitor().visit(ast, null);
|
||||
}
|
||||
|
||||
protected static class Visitor extends AstVisitor<String, Void> {
|
||||
|
||||
public String str(Ast ast) {
|
||||
return ast.accept(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String assign(Assign ast, Void arg) {
|
||||
return String.format("%s = %s", str(ast.left()), str(ast.right()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String binaryOp(BinaryOp ast, Void arg) {
|
||||
return String.format("(%s %s %s)",
|
||||
str(ast.left()), ast.operator.repr, str(ast.right()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String booleanConst(BooleanConst ast, Void arg) {
|
||||
return Boolean.toString(ast.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String builtInRead(BuiltInRead ast, Void arg) {
|
||||
return String.format("read()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String builtInWrite(BuiltInWrite ast, Void arg) {
|
||||
return String.format("write(%s)", str(ast.arg()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String builtInWriteln(BuiltInWriteln ast, Void arg) {
|
||||
return String.format("writeln()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cast(Cast ast, Void arg) {
|
||||
return String.format("(%s)(%s)", ast.typeName, str(ast.arg()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String classDecl(ClassDecl ast, Void arg) {
|
||||
return String.format("class %s {...}", ast.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String field(Field ast, Void arg) {
|
||||
return String.format("%s.%s", str(ast.arg()), ast.fieldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ifElse(IfElse ast, Void arg) {
|
||||
return String.format("if (%s) {...} else {...}", str(ast.condition()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String index(Index ast, Void arg) {
|
||||
return String.format("%s[%s]", str(ast.left()), str(ast.right()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String intConst(IntConst ast, Void arg) {
|
||||
return Integer.toString(ast.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String methodDecl(MethodDecl ast, Void arg) {
|
||||
return String.format("%s %s(...) {...}", ast.returnType, ast.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String newArray(NewArray ast, Void arg) {
|
||||
return String.format("new %s[%s]", ast.typeName, str(ast.arg()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String newObject(NewObject ast, Void arg) {
|
||||
return String.format("new %s()", ast.typeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nop(Nop ast, Void arg) {
|
||||
return "nop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nullConst(NullConst ast, Void arg) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String seq(Seq ast, Void arg) {
|
||||
return "(...)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String thisRef(ThisRef ast, Void arg) {
|
||||
return "this";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String unaryOp(UnaryOp ast, Void arg) {
|
||||
return String.format("%s(%s)", ast.operator.repr, str(ast.arg()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String var(Var ast, Void arg) {
|
||||
{
|
||||
return ast.name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String varDecl(VarDecl ast, Void arg) {
|
||||
return String.format("%s %s", ast.type, ast.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String whileLoop(WhileLoop ast, Void arg) {
|
||||
return String.format("while (%s) {...}", str(ast.condition()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue