Homework 4
This commit is contained in:
parent
0afc86ceeb
commit
72cc3206c4
125 changed files with 4200 additions and 1636 deletions
|
@ -1,10 +1,5 @@
|
|||
package cd.ir;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import cd.ir.Symbol.ClassSymbol;
|
||||
import cd.ir.Symbol.MethodSymbol;
|
||||
import cd.ir.Symbol.TypeSymbol;
|
||||
|
@ -12,6 +7,11 @@ import cd.ir.Symbol.VariableSymbol;
|
|||
import cd.util.Pair;
|
||||
import cd.util.debug.AstOneLine;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Ast {
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,7 @@ public abstract class Ast {
|
|||
|
||||
/** Convenient debugging printout */
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"(%s)@%x",
|
||||
AstOneLine.toString(this),
|
||||
|
@ -81,7 +81,7 @@ public abstract class Ast {
|
|||
public TypeSymbol type;
|
||||
|
||||
@Override
|
||||
public <R,A> R accept(AstVisitor<R, A> visitor, A arg) {
|
||||
public <R,A> R accept(AstVisitor<R, A> visitor, A arg) {
|
||||
return this.accept((ExprVisitor<R,A>)visitor, arg);
|
||||
}
|
||||
public abstract <R,A> R accept(ExprVisitor<R, A> visitor, A arg);
|
||||
|
@ -150,23 +150,23 @@ public abstract class Ast {
|
|||
* such as "1+2" or "3*4" */
|
||||
public static class BinaryOp extends LeftRightExpr {
|
||||
|
||||
public static enum BOp {
|
||||
|
||||
B_TIMES("*"),
|
||||
B_DIV("/"),
|
||||
B_MOD("%"),
|
||||
B_PLUS("+"),
|
||||
B_MINUS("-"),
|
||||
B_AND("&&"),
|
||||
B_OR("||"),
|
||||
B_EQUAL("=="),
|
||||
B_NOT_EQUAL("!="),
|
||||
B_LESS_THAN("<"),
|
||||
B_LESS_OR_EQUAL("<="),
|
||||
B_GREATER_THAN(">"),
|
||||
B_GREATER_OR_EQUAL(">=");
|
||||
|
||||
public String repr;
|
||||
public static enum BOp {
|
||||
|
||||
B_TIMES("*"),
|
||||
B_DIV("/"),
|
||||
B_MOD("%"),
|
||||
B_PLUS("+"),
|
||||
B_MINUS("-"),
|
||||
B_AND("&&"),
|
||||
B_OR("||"),
|
||||
B_EQUAL("=="),
|
||||
B_NOT_EQUAL("!="),
|
||||
B_LESS_THAN("<"),
|
||||
B_LESS_OR_EQUAL("<="),
|
||||
B_GREATER_THAN(">"),
|
||||
B_GREATER_OR_EQUAL(">=");
|
||||
|
||||
public String repr;
|
||||
private BOp(String repr) { this.repr = repr; }
|
||||
|
||||
/**
|
||||
|
@ -177,26 +177,26 @@ public abstract class Ast {
|
|||
* operator.
|
||||
*/
|
||||
public boolean isCommutative() {
|
||||
switch(this) {
|
||||
case B_PLUS:
|
||||
case B_TIMES:
|
||||
case B_AND:
|
||||
case B_OR:
|
||||
case B_EQUAL:
|
||||
case B_NOT_EQUAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch(this) {
|
||||
case B_PLUS:
|
||||
case B_TIMES:
|
||||
case B_AND:
|
||||
case B_OR:
|
||||
case B_EQUAL:
|
||||
case B_NOT_EQUAL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public BOp operator;
|
||||
|
||||
public BinaryOp(Expr left, BOp operator, Expr right) {
|
||||
super(left, right);
|
||||
this.operator = operator;
|
||||
}
|
||||
};
|
||||
|
||||
public BOp operator;
|
||||
|
||||
public BinaryOp(Expr left, BOp operator, Expr right) {
|
||||
super(left, right);
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, A> R accept(ExprVisitor<R, A> visitor, A arg) {
|
||||
|
@ -338,21 +338,21 @@ public abstract class Ast {
|
|||
|
||||
public static class UnaryOp extends ArgExpr {
|
||||
|
||||
public static enum UOp {
|
||||
U_PLUS("+"),
|
||||
U_MINUS("-"),
|
||||
U_BOOL_NOT("!");
|
||||
public String repr;
|
||||
public static enum UOp {
|
||||
U_PLUS("+"),
|
||||
U_MINUS("-"),
|
||||
U_BOOL_NOT("!");
|
||||
public String repr;
|
||||
private UOp(String repr) { this.repr = repr; }
|
||||
};
|
||||
|
||||
public final UOp operator;
|
||||
|
||||
public UnaryOp(UOp operator, Expr arg) {
|
||||
};
|
||||
|
||||
public final UOp operator;
|
||||
|
||||
public UnaryOp(UOp operator, Expr arg) {
|
||||
super(arg);
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <R, A> R accept(ExprVisitor<R, A> visitor, A arg) {
|
||||
return visitor.unaryOp(this, arg);
|
||||
|
|
31
src/cd/ir/AstRewriteVisitor.java
Normal file
31
src/cd/ir/AstRewriteVisitor.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
package cd.ir;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class AstRewriteVisitor<A> extends AstVisitor<Ast, A> {
|
||||
|
||||
@Override
|
||||
public Ast visitChildren(Ast ast, A arg) {
|
||||
ListIterator<Ast> children = ast.rwChildren.listIterator();
|
||||
while (children.hasNext()) {
|
||||
Ast child = children.next();
|
||||
if (child != null) {
|
||||
Ast replace = visit(child, arg);
|
||||
if (replace != child) {
|
||||
children.set(replace);
|
||||
nodeReplaced(child, replace);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ast;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when a node is replaced. Subclasses can override it to do some
|
||||
* bookkeeping.
|
||||
* <p>
|
||||
* The default implementation does nothing.
|
||||
*/
|
||||
protected void nodeReplaced(Ast oldNode, Ast newNode) {}
|
||||
|
||||
}
|
|
@ -16,6 +16,17 @@ public class AstVisitor<R,A> extends ExprVisitor<R,A> {
|
|||
return ast.accept(this, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides {@link ExprVisitor#visitChildren(Expr, Object)} and
|
||||
* delegates to the more general {@link #visitChildren(Ast, Object)}
|
||||
* with {@link Ast} parameter. This method is final to prevent
|
||||
* overriding only one of the two versions.
|
||||
*/
|
||||
@Override
|
||||
public final R visitChildren(Expr ast, A arg) {
|
||||
return visitChildren((Ast) ast, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* A handy function which visits the children of {@code ast},
|
||||
* providing "arg" to each of them. It returns the result of
|
||||
|
@ -45,6 +56,7 @@ public class AstVisitor<R,A> extends ExprVisitor<R,A> {
|
|||
|
||||
/**
|
||||
* The default action for expressions is to call this */
|
||||
@Override
|
||||
protected R dfltExpr(Expr ast, A arg) {
|
||||
return dflt(ast, arg);
|
||||
}
|
||||
|
|
|
@ -17,41 +17,36 @@ public abstract class Symbol {
|
|||
|
||||
public abstract boolean isReferenceType();
|
||||
|
||||
public String toString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the TypeSymbol is a subtype of the parameter
|
||||
* <br> The conditions are the following
|
||||
* <ul>
|
||||
* <li>Any type is a subtype of itself</li>
|
||||
* <li>Primitive types have no subtypes</li>
|
||||
* <li>Reference types are a subtype of {@code Object}</li>
|
||||
* <li>Reference types are a supertype of {@code null}</li>
|
||||
* <li>Classes can only be subtypes of other classes</li>
|
||||
* <li>Classes that inherit another are its subtypes (recursively)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean isSubtypeOf(TypeSymbol sym) {
|
||||
// Any type is a subtype of itself
|
||||
if (sym == this) return true;
|
||||
// A PrimitiveType doesn't have subtypes
|
||||
if (this instanceof PrimitiveTypeSymbol || sym instanceof PrimitiveTypeSymbol)
|
||||
return false;
|
||||
// Any reference type is a subtype of Object
|
||||
if (this.isReferenceType() && sym == ClassSymbol.objectType)
|
||||
|
||||
public abstract TypeSymbol getSuperType();
|
||||
|
||||
public boolean isSuperTypeOf(TypeSymbol sub) {
|
||||
// "void" is not a subtype of any type not even itself
|
||||
if(this == PrimitiveTypeSymbol.voidType || sub == PrimitiveTypeSymbol.voidType)
|
||||
return false;
|
||||
|
||||
if (sub == this)
|
||||
return true;
|
||||
// null is a subtype of any reference type
|
||||
if (sym.isReferenceType() && this == ClassSymbol.nullType)
|
||||
|
||||
if (this instanceof PrimitiveTypeSymbol || sub instanceof PrimitiveTypeSymbol)
|
||||
return false; // no hierarchy with primitive types
|
||||
|
||||
if (sub == ClassSymbol.nullType && this.isReferenceType())
|
||||
return true;
|
||||
// Class types can only be subtypes of other Class types
|
||||
// A class type is subtype of another if has inherited it
|
||||
if (sym instanceof ClassSymbol && this instanceof ClassSymbol)
|
||||
for (ClassSymbol c = (ClassSymbol) this; c != ClassSymbol.objectType; c = c.superClass)
|
||||
if (c == sym) return true;
|
||||
|
||||
TypeSymbol curr = sub;
|
||||
while (curr != null) {
|
||||
if (curr == this)
|
||||
return true;
|
||||
curr = curr.getSuperType();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PrimitiveTypeSymbol extends TypeSymbol {
|
||||
|
@ -65,9 +60,15 @@ public abstract class Symbol {
|
|||
super(name);
|
||||
}
|
||||
|
||||
public boolean isReferenceType() {
|
||||
@Override
|
||||
public boolean isReferenceType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeSymbol getSuperType() {
|
||||
throw new RuntimeException("should not call this on PrimitiveTypeSymbol");
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArrayTypeSymbol extends TypeSymbol {
|
||||
|
@ -78,10 +79,16 @@ public abstract class Symbol {
|
|||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
public boolean isReferenceType() {
|
||||
@Override
|
||||
public boolean isReferenceType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeSymbol getSuperType() {
|
||||
return ClassSymbol.objectType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ClassSymbol extends TypeSymbol {
|
||||
|
@ -89,12 +96,14 @@ public abstract class Symbol {
|
|||
public ClassSymbol superClass;
|
||||
public final VariableSymbol thisSymbol =
|
||||
new VariableSymbol("this", this);
|
||||
public final Map<String, VariableSymbol> fields = new HashMap<>();
|
||||
public final Map<String, MethodSymbol> methods = new HashMap<>();
|
||||
public final Map<String, VariableSymbol> fields =
|
||||
new HashMap<String, VariableSymbol>();
|
||||
public final Map<String, MethodSymbol> methods =
|
||||
new HashMap<String, MethodSymbol>();
|
||||
|
||||
/** Symbols for the built-in Object and null types */
|
||||
public static final ClassSymbol nullType = new ClassSymbol("<null>");
|
||||
public static final ClassSymbol objectType = new ClassSymbol("Object");
|
||||
public static final ClassSymbol objectType = new ClassSymbol("Object");
|
||||
|
||||
public ClassSymbol(Ast.ClassDecl ast) {
|
||||
super(ast.name);
|
||||
|
@ -108,10 +117,16 @@ public abstract class Symbol {
|
|||
this.ast = null;
|
||||
}
|
||||
|
||||
public boolean isReferenceType() {
|
||||
@Override
|
||||
public boolean isReferenceType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeSymbol getSuperType() {
|
||||
return superClass;
|
||||
}
|
||||
|
||||
public VariableSymbol getField(String name) {
|
||||
VariableSymbol fsym = fields.get(name);
|
||||
if (fsym == null && superClass != null)
|
||||
|
@ -130,8 +145,10 @@ public abstract class Symbol {
|
|||
public static class MethodSymbol extends Symbol {
|
||||
|
||||
public final Ast.MethodDecl ast;
|
||||
public final Map<String, VariableSymbol> locals = new HashMap<>();
|
||||
public final List<VariableSymbol> parameters = new ArrayList<>();
|
||||
public final Map<String, VariableSymbol> locals =
|
||||
new HashMap<String, VariableSymbol>();
|
||||
public final List<VariableSymbol> parameters =
|
||||
new ArrayList<VariableSymbol>();
|
||||
|
||||
public TypeSymbol returnType;
|
||||
|
||||
|
@ -140,14 +157,15 @@ public abstract class Symbol {
|
|||
this.ast = ast;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + "(...)";
|
||||
}
|
||||
}
|
||||
|
||||
public static class VariableSymbol extends Symbol {
|
||||
|
||||
public enum Kind { PARAM, LOCAL, FIELD }
|
||||
public static enum Kind { PARAM, LOCAL, FIELD };
|
||||
public final TypeSymbol type;
|
||||
public final Kind kind;
|
||||
|
||||
|
@ -161,7 +179,8 @@ public abstract class Symbol {
|
|||
this.kind = kind;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
@ -169,4 +188,5 @@ public abstract class Symbol {
|
|||
protected Symbol(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue