Homework 3

This commit is contained in:
Carlos Galindo 2020-01-15 22:32:25 +01:00
commit 0afc86ceeb
Signed by: kauron
GPG key ID: 83E68706DEE119A3
129 changed files with 3163 additions and 4316 deletions

View file

@ -5,6 +5,10 @@ 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;
import cd.ir.Symbol.VariableSymbol;
import cd.util.Pair;
import cd.util.debug.AstOneLine;
@ -56,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),
@ -73,14 +77,20 @@ public abstract class Ast {
super(fixedCount);
}
/** Type that this expression will evaluate to (computed in semantic phase). */
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);
/** Copies any non-AST fields. */
protected <E extends Expr> E postCopy(E item) {
{
item.type = type;
}
return item;
}
}
@ -140,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; }
/**
@ -167,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) {
@ -210,6 +220,12 @@ public abstract class Ast {
return visitor.cast(this, arg);
}
@Override
protected <E extends Expr> E postCopy(E item) {
((Cast)item).type = type;
return super.postCopy(item);
}
}
public static class IntConst extends LeafExpr {
@ -253,6 +269,8 @@ public abstract class Ast {
public final String fieldName;
public VariableSymbol sym;
public Field(Expr arg, String fieldName) {
super(arg);
assert arg != null && fieldName != null;
@ -264,6 +282,12 @@ public abstract class Ast {
return visitor.field(this, arg);
}
@Override
protected <E extends Expr> E postCopy(E item) {
((Field)item).sym = sym;
return super.postCopy(item);
}
}
public static class Index extends LeftRightExpr {
@ -314,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);
@ -340,6 +364,8 @@ public abstract class Ast {
public String name;
public VariableSymbol sym;
/**
* Use this constructor to build an instance of this AST
* in the parser.
@ -351,6 +377,29 @@ public abstract class Ast {
public <R, A> R accept(ExprVisitor<R, A> visitor, A arg) {
return visitor.var(this, arg);
}
/**
* Use this static function to build an instance after the
* semantic phase; it fills in the {@link #type} and {@link #sym}
* fields.
*/
public static Var withSym(VariableSymbol sym) {
Var v = new Var(sym.name);
v.sym = sym;
v.type = sym.type;
return v;
}
@Override
protected <E extends Expr> E postCopy(E item) {
((Var)item).sym = sym;
return super.postCopy(item);
}
public void setSymbol(VariableSymbol variableSymbol) {
sym = variableSymbol;
name = sym.toString();
}
}
@ -367,6 +416,8 @@ public abstract class Ast {
public String methodName;
public MethodSymbol sym;
public MethodCallExpr(Expr rcvr, String methodName, List<Expr> arguments) {
super(-1);
assert rcvr != null && methodName != null && arguments != null;
@ -588,6 +639,8 @@ public abstract class Ast {
public String type;
public String name;
public VariableSymbol sym;
public VarDecl(String type, String name) {
this(0, type, name);
}
@ -631,6 +684,7 @@ public abstract class Ast {
public String name;
public List<String> argumentTypes;
public List<String> argumentNames;
public MethodSymbol sym;
public MethodDecl(
String returnType,
String name,
@ -672,6 +726,8 @@ public abstract class Ast {
public String name;
public String superClass;
public ClassSymbol sym;
public ClassDecl(
String name,
String superClass,

View file

@ -16,17 +16,6 @@ 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
@ -56,7 +45,6 @@ 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);
}

172
src/cd/ir/Symbol.java Normal file
View file

@ -0,0 +1,172 @@
package cd.ir;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class Symbol {
public final String name;
public static abstract class TypeSymbol extends Symbol {
public TypeSymbol(String name) {
super(name);
}
public abstract boolean isReferenceType();
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)
return true;
// null is a subtype of any reference type
if (sym.isReferenceType() && this == ClassSymbol.nullType)
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;
return false;
}
}
public static class PrimitiveTypeSymbol extends TypeSymbol {
/** Symbols for the built-in primitive types */
public static final PrimitiveTypeSymbol intType = new PrimitiveTypeSymbol("int");
public static final PrimitiveTypeSymbol voidType = new PrimitiveTypeSymbol("void");
public static final PrimitiveTypeSymbol booleanType = new PrimitiveTypeSymbol("boolean");
public PrimitiveTypeSymbol(String name) {
super(name);
}
public boolean isReferenceType() {
return false;
}
}
public static class ArrayTypeSymbol extends TypeSymbol {
public final TypeSymbol elementType;
public ArrayTypeSymbol(TypeSymbol elementType) {
super(elementType.name+"[]");
this.elementType = elementType;
}
public boolean isReferenceType() {
return true;
}
}
public static class ClassSymbol extends TypeSymbol {
public final Ast.ClassDecl ast;
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<>();
/** 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 ClassSymbol(Ast.ClassDecl ast) {
super(ast.name);
this.ast = ast;
}
/** Used to create the default {@code Object}
* and {@code <null>} types */
public ClassSymbol(String name) {
super(name);
this.ast = null;
}
public boolean isReferenceType() {
return true;
}
public VariableSymbol getField(String name) {
VariableSymbol fsym = fields.get(name);
if (fsym == null && superClass != null)
return superClass.getField(name);
return fsym;
}
public MethodSymbol getMethod(String name) {
MethodSymbol msym = methods.get(name);
if (msym == null && superClass != null)
return superClass.getMethod(name);
return msym;
}
}
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 TypeSymbol returnType;
public MethodSymbol(Ast.MethodDecl ast) {
super(ast.name);
this.ast = ast;
}
public String toString() {
return name + "(...)";
}
}
public static class VariableSymbol extends Symbol {
public enum Kind { PARAM, LOCAL, FIELD }
public final TypeSymbol type;
public final Kind kind;
public VariableSymbol(String name, TypeSymbol type) {
this(name, type, Kind.PARAM);
}
public VariableSymbol(String name, TypeSymbol type, Kind kind) {
super(name);
this.type = type;
this.kind = kind;
}
public String toString() {
return name;
}
}
protected Symbol(String name) {
this.name = name;
}
}