Programming-Language-Design / src / visitor / codegeneration / OffsetVisitor.java
OffsetVisitor.java
Raw
package visitor.codegeneration;

import ast.Program;
import ast.definition.Definition;
import ast.definition.classes.FuncDefinition;
import ast.definition.classes.VarDefinition;
import ast.statement.Statement;
import ast.type.RecordField;
import ast.type.classes.FunctionType;
import ast.type.classes.RecordType;
import visitor.AbstractVisitor;

public class OffsetVisitor extends AbstractVisitor<Void, Void> {


    @Override
    public Void visit(Program ast, Void param) {
        int globalBytesSum = 0;
        for (Definition def : ast.getDefinitions()) {
            if (def instanceof VarDefinition) {
                ((VarDefinition) def).setOffset(globalBytesSum);
                globalBytesSum += def.getType().numberOfBytes();
            }
        }
        super.visit(ast, param);
        return null;
    }

    @Override
    public Void visit(FuncDefinition ast, Void param) {
        int sumOfBytes = 0;
        for (Statement localVar : ast.getFunctionStmts()) {
            if (localVar instanceof VarDefinition) {
                sumOfBytes += ((VarDefinition) localVar).getType().numberOfBytes();
                ((VarDefinition) localVar).setOffset(-sumOfBytes);
            }
        }
        super.visit(ast, param);
        return null;
    }


    @Override
    public Void visit(FunctionType ast, Void param) {
        int sumOfBytes = 4;
        for (int i = ast.getParameters().size() - 1; i >= 0; i--) {
            ast.getParameters().get(i).setOffset(sumOfBytes);
            sumOfBytes += ast.getParameters().get(i).getType().numberOfBytes();
        }
        super.visit(ast, param);
        return null;
    }

    @Override
    public Void visit(RecordType ast, Void param) {
        int sumOfBytes = 0;
        for (RecordField rf : ast.getFields()) {
            rf.setOffset(sumOfBytes);
            sumOfBytes += rf.getFieldType().numberOfBytes();
            rf.accept(this, null);  //pre-order traversal
        }
        super.visit(ast, param);
        return null;
    }
}