package compiler.frames;
import java.util.LinkedList;
import compiler.abstree.AbsArrTyp;
import compiler.abstree.AbsAtomExpr;
import compiler.abstree.AbsAtomTyp;
import compiler.abstree.AbsBinExpr;
import compiler.abstree.AbsDecl;
import compiler.abstree.AbsDecls;
import compiler.abstree.AbsForStmt;
import compiler.abstree.AbsFunDecl;
import compiler.abstree.AbsFunName;
import compiler.abstree.AbsIfStmt;
import compiler.abstree.AbsLetExpr;
import compiler.abstree.AbsPtrTyp;
import compiler.abstree.AbsRecTyp;
import compiler.abstree.AbsStmt;
import compiler.abstree.AbsStmts;
import compiler.abstree.AbsTypDecl;
import compiler.abstree.AbsTypName;
import compiler.abstree.AbsUnExpr;
import compiler.abstree.AbsValStmt;
import compiler.abstree.AbsVarDecl;
import compiler.abstree.AbsVarName;
import compiler.abstree.AbsWhileStmt;
import compiler.abstree.Visitor;
public class FrameEvaluator implements Visitor
{
private LinkedList<Frame> callStack = new LinkedList<Frame>();
@Override
public Object visit(AbsArrTyp node)
{
node.base.accept(this);
return null;
}
@Override
public Object visit(AbsAtomExpr node)
{
return null;
}
@Override
public Object visit(AbsAtomTyp node)
{
return null;
}
@Override
public Object visit(AbsBinExpr node)
{
return null;
}
@Override
public Object visit(AbsDecls node)
{
// Entry point, check global variables first
for (AbsDecl decl : node.decls)
{
decl.accept(this);
}
return null;
}
@Override
public Object visit(AbsForStmt node)
{
node.stmts.accept(this);
return null;
}
@Override
public Object visit(AbsFunDecl node)
{
Frame funFrame = new Frame(node, callStack.size());
if (node.args != null)
{
for (AbsDecl arg : node.args.decls)
{
AbsVarDecl argument = (AbsVarDecl)arg;
argument.access = new ArgAccess(argument, funFrame);
}
funFrame.sizeArgs = Math.max(node.args.decls.size() * 4, funFrame.sizeArgs);
}
node.frame = funFrame;
callStack.push(funFrame);
node.val.accept(this);
callStack.poll();
return null;
}
@Override
public Object visit(AbsFunName node)
{
// Calculate size of arguments
int size = 0;
if (node.decl.args != null)
{
for (AbsDecl arg : node.decl.args.decls)
{
size += arg.semTyp.size();
}
}
// Add FP size
size += 4;
// Set current frame size to the largest call
callStack.getFirst().sizeArgs = Math.max(callStack.getFirst().sizeArgs, size);
return null;
}
@Override
public Object visit(AbsIfStmt node)
{
node.then_stmts.accept(this);
if (node.else_stmts != null)
{
node.else_stmts.accept(this);
}
return null;
}
@Override
public Object visit(AbsLetExpr node)
{
if (node.stmts != null)
node.stmts.accept(this);
if (node.defs != null)
node.defs.accept(this);
node.expr.accept(this);
return null;
}
@Override
public Object visit(AbsPtrTyp node)
{
return null;
}
@Override
public Object visit(AbsRecTyp node)
{
int i = 0;
for (AbsVarDecl compDecl : node.comps)
{
compDecl.typ.accept(this);
compDecl.access = new CmpAccess(compDecl, i);
i += compDecl.semTyp.size();
}
return null;
}
@Override
public Object visit(AbsStmts node)
{
for (AbsStmt stmt : node.stmts)
{
stmt.accept(this);
}
return null;
}
@Override
public Object visit(AbsTypDecl node)
{
node.typ.accept(this);
return null;
}
@Override
public Object visit(AbsTypName node)
{
return null;
}
@Override
public Object visit(AbsUnExpr node)
{
return null;
}
@Override
public Object visit(AbsValStmt node)
{
node.expr.accept(this);
return null;
}
@Override
public Object visit(AbsVarDecl node)
{
// Global variables
if (callStack.size() == 0)
{
node.access = new VarAccess(node);
}
else
{
node.access = new LocAccess(node, callStack.getFirst());
// Add local variable to frame
callStack.getFirst().locVars.add((LocAccess) node.access);
}
return null;
}
@Override
public Object visit(AbsVarName node)
{
return null;
}
@Override
public Object visit(AbsWhileStmt node)
{
node.stmts.accept(this);
return null;
}
}