TypeBuilder.java
package edu.udel.cis.vsl.tass.ast2model.impl;
import java.util.HashMap;
import java.util.Map;
import edu.udel.cis.vsl.tass.ast.IF.ASTNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.AbstractSyntaxTreeIF;
import edu.udel.cis.vsl.tass.ast.IF.IdentifierNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.PairNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.SequenceNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.ArrayTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.BooleanTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.CharacterTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.CompositeTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.EnumerationTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.FunctionTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.IntegerTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.PointerTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.RealTypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.TypeNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.TypeReferenceNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.VoidTypeNodeIF;
import edu.udel.cis.vsl.tass.ast2model.IF.TypeBuilderIF;
import edu.udel.cis.vsl.tass.model.IF.ModelFactoryIF;
import edu.udel.cis.vsl.tass.model.IF.SyntaxException;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.type.ArrayTypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.PointerTypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF;
public class TypeBuilder implements TypeBuilderIF {
ModelFactoryIF factory;
Map<TypeNodeIF, TypeIF> typeMap = new HashMap<TypeNodeIF, TypeIF>();
/**
* A TypeBuilder is used by the ModelBuilder to create and keep track of
* model types associated with each AST type. The ModelFactoryIF argument
* should be the same ModelFactoryIF used by the ModelBuilder.
*/
public TypeBuilder(ModelFactoryIF factory) {
this.factory = factory;
}
@Override
public void buildTypes(AbstractSyntaxTreeIF ast) throws SyntaxException {
addTypes(ast.rootNode());
}
@Override
public TypeIF getModelType(TypeNodeIF astType) throws SyntaxException {
if (!typeMap.containsKey(astType))
processType(astType);
return typeMap.get(astType);
}
private void addTypes(ASTNodeIF node) throws SyntaxException {
if (node instanceof TypeNodeIF) {
processType((TypeNodeIF) node);
} else {
for (int i = 0; i < node.numChildren(); i++) {
addTypes(node.child(i));
}
}
}
/**
* Takes an AST type node and creates a new model node for the type. Should
* only be used on an AST type node that is not already in typeMap.
*
* @throws SyntaxException
* if the type is unknown.
*/
private void processType(TypeNodeIF node) throws SyntaxException {
// Already have this type, so return
if (typeMap.containsKey(node)) {
return;
}
if (node instanceof ArrayTypeNodeIF) {
ArrayTypeNodeIF astArrayType = (ArrayTypeNodeIF) node;
int dimensions = 1;
// "Flatten" the array to a single multi-dimensional array
while (astArrayType.elementType() instanceof ArrayTypeNodeIF) {
astArrayType = (ArrayTypeNodeIF) astArrayType.elementType();
dimensions++;
}
typeMap.put(node, factory.arrayType(
getModelType(astArrayType.elementType()), dimensions));
} else if (node instanceof BooleanTypeNodeIF) {
typeMap.put(node, factory.booleanType());
} else if (node instanceof CharacterTypeNodeIF) {
typeMap.put(node, factory.characterType());
} else if (node instanceof CompositeTypeNodeIF) {
CompositeTypeNodeIF compositeTypeNode = (CompositeTypeNodeIF) node;
String name = compositeTypeNode.name().name();
SequenceNodeIF<PairNodeIF<IdentifierNodeIF, TypeNodeIF>> fields = compositeTypeNode
.fields();
String[] fieldNames = new String[fields.numChildren()];
TypeIF[] fieldTypes = new TypeIF[fields.numChildren()];
ExpressionIF[][] dimensionExpressions = new ExpressionIF[fields
.numChildren()][];
for (int i = 0; i < fields.numChildren(); i++) {
fieldNames[i] = fields.getSequenceChild(i).left().name();
fieldTypes[i] = getModelType(fields.getSequenceChild(i).right());
if (fieldTypes[i] instanceof ArrayTypeIF) {
dimensionExpressions[i] = new ExpressionIF[((ArrayTypeIF) fieldTypes[i])
.dimension()];
// TODO: Do we need to figure out concrete dimension
// expressions? Where do these come from in the AST?
} else {
dimensionExpressions[i] = null;
}
}
typeMap.put(node, factory.recordType(name, fieldNames, fieldTypes, dimensionExpressions));
} else if (node instanceof EnumerationTypeNodeIF) {
} else if (node instanceof FunctionTypeNodeIF) {
} else if (node instanceof IntegerTypeNodeIF) {
// One of the integer types is CHAR. Use the model character type
// for this.
if (((IntegerTypeNodeIF) node).intType() == IntegerTypeNodeIF.IntType.CHAR) {
typeMap.put(node, factory.characterType());
} else {
typeMap.put(node, factory.integerType());
}
} else if (node instanceof PointerTypeNodeIF) {
TypeNodeIF astBaseType = ((PointerTypeNodeIF) node).baseType();
TypeIF baseType = typeMap.get(astBaseType);
TypeIF result;
if (baseType != null) {
result = factory.pointerType(baseType);
} else {
// cyclic resolution...
result = factory.newPointerType();
typeMap.put(node, result);
processType(astBaseType);
baseType = getModelType(astBaseType);
result = factory.setBaseType((PointerTypeIF) result, baseType);
}
typeMap.put(node, factory.pointerType(baseType));
} else if (node instanceof RealTypeNodeIF) {
typeMap.put(node, factory.rationalType());
} else if (node instanceof TypeReferenceNodeIF) {
processType(((TypeReferenceNodeIF) node).referent().type());
} else if (node instanceof VoidTypeNodeIF) {
typeMap.put(node, factory.voidType());
} else {
throw new SyntaxException(node, "Unknown type: " + node);
}
// TODO Auto-generated method stub
}
}