/*
* #%~
* VDM Code Generator
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.codegen.visitor;
import java.util.LinkedList;
import java.util.List;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.intf.lex.ILexNameToken;
import org.overture.ast.types.ABooleanBasicType;
import org.overture.ast.types.ABracketType;
import org.overture.ast.types.ACharBasicType;
import org.overture.ast.types.AClassType;
import org.overture.ast.types.AFunctionType;
import org.overture.ast.types.AInMapMapType;
import org.overture.ast.types.AIntNumericBasicType;
import org.overture.ast.types.AMapMapType;
import org.overture.ast.types.ANamedInvariantType;
import org.overture.ast.types.ANatNumericBasicType;
import org.overture.ast.types.ANatOneNumericBasicType;
import org.overture.ast.types.AOperationType;
import org.overture.ast.types.AOptionalType;
import org.overture.ast.types.AParameterType;
import org.overture.ast.types.AProductType;
import org.overture.ast.types.AQuoteType;
import org.overture.ast.types.ARationalNumericBasicType;
import org.overture.ast.types.ARealNumericBasicType;
import org.overture.ast.types.ARecordInvariantType;
import org.overture.ast.types.ASeq1SeqType;
import org.overture.ast.types.ASeqSeqType;
import org.overture.ast.types.ATokenBasicType;
import org.overture.ast.types.AUnionType;
import org.overture.ast.types.AUnknownType;
import org.overture.ast.types.AUnresolvedType;
import org.overture.ast.types.AVoidType;
import org.overture.ast.types.PType;
import org.overture.ast.types.SMapType;
import org.overture.ast.types.SSeqType;
import org.overture.ast.types.SSetType;
import org.overture.codegen.ir.IRInfo;
import org.overture.codegen.ir.IRNamedTypeInvariantTag;
import org.overture.codegen.ir.STypeIR;
import org.overture.codegen.ir.declarations.ANamedTypeDeclIR;
import org.overture.codegen.ir.name.ATypeNameIR;
import org.overture.codegen.ir.types.ABoolBasicTypeIR;
import org.overture.codegen.ir.types.ACharBasicTypeIR;
import org.overture.codegen.ir.types.AClassTypeIR;
import org.overture.codegen.ir.types.AIntNumericBasicTypeIR;
import org.overture.codegen.ir.types.ANat1NumericBasicTypeIR;
import org.overture.codegen.ir.types.ANatNumericBasicTypeIR;
import org.overture.codegen.ir.types.AQuoteTypeIR;
import org.overture.codegen.ir.types.ARatNumericBasicTypeIR;
import org.overture.codegen.ir.types.ARealNumericBasicTypeIR;
import org.overture.codegen.ir.types.ARecordTypeIR;
import org.overture.codegen.ir.types.ASetSetTypeIR;
import org.overture.codegen.ir.types.ATemplateTypeIR;
import org.overture.codegen.ir.types.ATokenBasicTypeIR;
import org.overture.codegen.ir.types.ATupleTypeIR;
import org.overture.codegen.ir.types.AUnionTypeIR;
import org.overture.codegen.ir.types.AUnknownTypeIR;
import org.overture.codegen.ir.types.AVoidTypeIR;
import org.overture.typechecker.assistant.type.PTypeAssistantTC;
public class TypeVisitorIR extends AbstractVisitorIR<IRInfo, STypeIR>
{
@Override
public STypeIR caseAUnresolvedType(AUnresolvedType node, IRInfo question)
throws AnalysisException
{
log.error("Found unresolved type in the VDM AST");
// To guard against unresolved type in the type checker
return new AUnknownTypeIR();
}
@Override
public STypeIR caseAUnionType(AUnionType node, IRInfo question)
throws AnalysisException
{
List<PType> types = node.getTypes();
question.getTypeAssistant().removeIllegalQuoteTypes(types);
PTypeAssistantTC typeAssistant = question.getTcFactory().createPTypeAssistant();
if (question.getTypeAssistant().isUnionOfType(node, SSetType.class, typeAssistant))
{
SSetType setType = typeAssistant.getSet(node);
return setType.apply(question.getTypeVisitor(), question);
} else if (question.getTypeAssistant().isUnionOfType(node, SSeqType.class, typeAssistant))
{
SSeqType seqType = typeAssistant.getSeq(node);
return seqType.apply(question.getTypeVisitor(), question);
} else if (question.getTypeAssistant().isUnionOfType(node, SMapType.class, typeAssistant))
{
SMapType mapType = typeAssistant.getMap(node);
return mapType.apply(question.getTypeVisitor(), question);
} else if (question.getTypeAssistant().isProductOfSameSize(node, typeAssistant))
{
AProductType productType = typeAssistant.getProduct(node);
return productType.apply(question.getTypeVisitor(), question);
} else
{
if (types.size() <= 1)
{
return types.get(0).apply(question.getTypeVisitor(), question);
} else
{
AUnionTypeIR unionTypeCg = new AUnionTypeIR();
for (PType type : types)
{
STypeIR typeCg = type.apply(question.getTypeVisitor(), question);
if (typeCg != null)
{
unionTypeCg.getTypes().add(typeCg);
} else
{
return null;
}
}
return unionTypeCg;
}
}
}
@Override
public STypeIR caseABracketType(ABracketType node, IRInfo question)
throws AnalysisException
{
PType type = node.getType();
return type.apply(question.getTypeVisitor(), question);
}
@Override
public STypeIR caseAUnknownType(AUnknownType node, IRInfo question)
throws AnalysisException
{
return new AUnknownTypeIR(); // '?' Indicates an unknown type
}
@Override
public STypeIR caseATokenBasicType(ATokenBasicType node, IRInfo question)
throws AnalysisException
{
return new ATokenBasicTypeIR();
}
@Override
public STypeIR defaultSSetType(SSetType node, IRInfo question)
throws AnalysisException
{
PType setOf = node.getSetof();
STypeIR typeCg = setOf.apply(question.getTypeVisitor(), question);
boolean empty = node.getEmpty();
ASetSetTypeIR setType = new ASetSetTypeIR();
setType.setSetOf(typeCg);
setType.setEmpty(empty);
return setType;
}
@Override
public STypeIR caseAMapMapType(AMapMapType node, IRInfo question)
throws AnalysisException
{
return question.getExpAssistant().handleMapType(node, question, false);
}
@Override
public STypeIR caseAInMapMapType(AInMapMapType node, IRInfo question)
throws AnalysisException
{
return question.getExpAssistant().handleMapType(node, question, true);
}
@Override
public STypeIR caseAProductType(AProductType node, IRInfo question)
throws AnalysisException
{
ATupleTypeIR tuple = new ATupleTypeIR();
LinkedList<PType> types = node.getTypes();
for (PType type : types)
{
STypeIR typeCg = type.apply(question.getTypeVisitor(), question);
if (typeCg != null)
{
tuple.getTypes().add(typeCg);
} else
{
return null;
}
}
return tuple;
}
@Override
public STypeIR caseAParameterType(AParameterType node, IRInfo question)
throws AnalysisException
{
String name = node.getName().getName();
ATemplateTypeIR templateType = new ATemplateTypeIR();
templateType.setName(name);
return templateType;
}
@Override
public STypeIR caseAOptionalType(AOptionalType node, IRInfo question)
throws AnalysisException
{
STypeIR typeCg = node.getType().apply(question.getTypeVisitor(), question);
if (typeCg != null)
{
typeCg.setOptional(true);
}
return typeCg;
}
@Override
public STypeIR caseANamedInvariantType(ANamedInvariantType node,
IRInfo question) throws AnalysisException
{
PType type = node.getType();
STypeIR underlyingType = type.apply(question.getTypeVisitor(), question);
// TODO: Morten initially requested some way of knowing whether a type originates
// from a named invariant type. With the NamedInvTypeInfo being introduced, using
// IR tags for this is redundant. Check if the IR tagging can be removed.
underlyingType.setTag(new IRNamedTypeInvariantTag(node.getName().getName()));
ATypeNameIR typeName = new ATypeNameIR();
typeName.setDefiningClass(node.getName().getModule());
typeName.setName(node.getName().getName());
ANamedTypeDeclIR typeDecl = new ANamedTypeDeclIR();
typeDecl.setName(typeName);
if (underlyingType != null)
{
typeDecl.setType(underlyingType.clone());
}
underlyingType.setNamedInvType(typeDecl);
return underlyingType;
}
@Override
public STypeIR caseAQuoteType(AQuoteType node, IRInfo question)
throws AnalysisException
{
String value = node.getValue().getValue();
AQuoteTypeIR quoteTypeCg = new AQuoteTypeIR();
quoteTypeCg.setValue(value);
question.registerQuoteValue(value);
return quoteTypeCg;
}
@Override
public STypeIR caseARecordInvariantType(ARecordInvariantType node,
IRInfo question) throws AnalysisException
{
ILexNameToken name = node.getName();
ARecordTypeIR recordType = new ARecordTypeIR();
ATypeNameIR typeName = new ATypeNameIR();
typeName.setName(name.getName());
typeName.setDefiningClass(name.getModule());
recordType.setName(typeName);
return recordType;
}
@Override
public STypeIR caseASeqSeqType(ASeqSeqType node, IRInfo question)
throws AnalysisException
{
return question.getTypeAssistant().constructSeqType(node, question);
}
@Override
public STypeIR caseASeq1SeqType(ASeq1SeqType node, IRInfo question)
throws AnalysisException
{
return question.getTypeAssistant().constructSeqType(node, question);
}
@Override
public STypeIR caseAOperationType(AOperationType node, IRInfo question)
throws AnalysisException
{
return question.getTypeAssistant().consMethodType(node, node.getParameters(), node.getResult(), question);
}
@Override
public STypeIR caseAFunctionType(AFunctionType node, IRInfo question)
throws AnalysisException
{
return question.getTypeAssistant().consMethodType(node, node.getParameters(), node.getResult(), question);
}
@Override
public STypeIR caseAClassType(AClassType node, IRInfo question)
throws AnalysisException
{
String typeName = node.getClassdef().getName().getName();
AClassTypeIR classType = new AClassTypeIR();
classType.setName(typeName);
return classType;
}
@Override
public STypeIR caseAVoidType(AVoidType node, IRInfo question)
throws AnalysisException
{
return new AVoidTypeIR();
}
@Override
public STypeIR caseAIntNumericBasicType(AIntNumericBasicType node,
IRInfo question) throws AnalysisException
{
return new AIntNumericBasicTypeIR();
}
@Override
public STypeIR caseANatOneNumericBasicType(ANatOneNumericBasicType node,
IRInfo question) throws AnalysisException
{
return new ANat1NumericBasicTypeIR();
}
@Override
public STypeIR caseANatNumericBasicType(ANatNumericBasicType node,
IRInfo question) throws AnalysisException
{
return new ANatNumericBasicTypeIR();
}
@Override
public STypeIR caseARealNumericBasicType(ARealNumericBasicType node,
IRInfo question) throws AnalysisException
{
return new ARealNumericBasicTypeIR();
}
@Override
public STypeIR caseARationalNumericBasicType(ARationalNumericBasicType node,
IRInfo question) throws AnalysisException
{
return new ARatNumericBasicTypeIR();
}
@Override
public STypeIR caseACharBasicType(ACharBasicType node, IRInfo question)
throws AnalysisException
{
return new ACharBasicTypeIR();
}
@Override
public STypeIR caseABooleanBasicType(ABooleanBasicType node,
IRInfo question) throws AnalysisException
{
return new ABoolBasicTypeIR();
}
}