package org.overture.codegen.traces; import java.util.IdentityHashMap; import org.apache.log4j.Logger; import org.overture.codegen.ir.IRInfo; import org.overture.codegen.ir.SPatternIR; import org.overture.codegen.ir.STypeIR; import org.overture.codegen.ir.analysis.AnalysisException; import org.overture.codegen.ir.analysis.QuestionAdaptor; import org.overture.codegen.ir.declarations.ARecordDeclIR; import org.overture.codegen.ir.patterns.ABoolPatternIR; import org.overture.codegen.ir.patterns.ACharPatternIR; import org.overture.codegen.ir.patterns.AIdentifierPatternIR; import org.overture.codegen.ir.patterns.AIgnorePatternIR; import org.overture.codegen.ir.patterns.AIntPatternIR; import org.overture.codegen.ir.patterns.ANullPatternIR; import org.overture.codegen.ir.patterns.AQuotePatternIR; import org.overture.codegen.ir.patterns.ARealPatternIR; import org.overture.codegen.ir.patterns.ARecordPatternIR; import org.overture.codegen.ir.patterns.AStringPatternIR; import org.overture.codegen.ir.patterns.ATuplePatternIR; import org.overture.codegen.ir.types.ABoolBasicTypeIR; import org.overture.codegen.ir.types.ACharBasicTypeIR; 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.ARealNumericBasicTypeIR; import org.overture.codegen.ir.types.ARecordTypeIR; import org.overture.codegen.ir.types.ATupleTypeIR; import org.overture.codegen.ir.types.AUnionTypeIR; import org.overture.codegen.ir.types.AUnknownTypeIR; public class PatternTypeFinder extends QuestionAdaptor<STypeIR> { private IRInfo info; private IdentityHashMap<SPatternIR, STypeIR> typeTable; private static Logger log = Logger.getLogger(PatternTypeFinder.class.getName()); public PatternTypeFinder(IRInfo info) { this.info = info; this.typeTable = new IdentityHashMap<>(); } @Override public void defaultSPatternIR(SPatternIR node, STypeIR question) throws AnalysisException { storeType(node, question); log.error("Got unexpected pattern: " + node); } @Override public void caseAIdentifierPatternIR(AIdentifierPatternIR node, STypeIR question) throws AnalysisException { storeType(node, question); } @Override public void caseAIgnorePatternIR(AIgnorePatternIR node, STypeIR question) throws AnalysisException { storeType(node, question); } @Override public void caseABoolPatternIR(ABoolPatternIR node, STypeIR question) throws AnalysisException { storeType(node, new ABoolBasicTypeIR()); } @Override public void caseACharPatternIR(ACharPatternIR node, STypeIR question) throws AnalysisException { storeType(node, new ACharBasicTypeIR()); } @Override public void caseAIntPatternIR(AIntPatternIR node, STypeIR question) throws AnalysisException { long value = node.getValue(); if (value > 0) { storeType(node, new ANat1NumericBasicTypeIR()); } else if (value >= 0) { storeType(node, new ANatNumericBasicTypeIR()); } else { storeType(node, new AIntNumericBasicTypeIR()); } } @Override public void caseANullPatternIR(ANullPatternIR node, STypeIR question) throws AnalysisException { storeType(node, new AUnknownTypeIR()); } @Override public void caseAQuotePatternIR(AQuotePatternIR node, STypeIR question) throws AnalysisException { AQuoteTypeIR quoteTypeCg = new AQuoteTypeIR(); quoteTypeCg.setValue(node.getValue()); storeType(node, quoteTypeCg); } @Override public void caseARealPatternIR(ARealPatternIR node, STypeIR question) throws AnalysisException { storeType(node, new ARealNumericBasicTypeIR()); } @Override public void caseAStringPatternIR(AStringPatternIR node, STypeIR question) throws AnalysisException { storeType(node, question); } @Override public void caseATuplePatternIR(ATuplePatternIR node, STypeIR question) throws AnalysisException { ATupleTypeIR tupType = null; if (question instanceof ATupleTypeIR) { tupType = (ATupleTypeIR) question; } else if (question instanceof AUnionTypeIR) { tupType = info.getPatternAssistant().getTupleType((AUnionTypeIR) question, node); } storeType(node, question); if (tupType != null) { if (tupType.getTypes().size() == node.getPatterns().size()) { for (int i = 0; i < node.getPatterns().size(); i++) { SPatternIR p = node.getPatterns().get(i); STypeIR t = tupType.getTypes().get(i); p.apply(this, t); } } else { log.error("Problem encountered when determining the type of a tuple pattern. Patterns and types do not match in terms of size"); } } else { log.error("Expected tuple type or union type. Got: " + question); } } @Override public void caseARecordPatternIR(ARecordPatternIR node, STypeIR question) throws AnalysisException { STypeIR type = node.getType(); storeType(node, type); if (type instanceof ARecordTypeIR) { ARecordTypeIR recType = (ARecordTypeIR) type; ARecordDeclIR rec = info.getDeclAssistant().findRecord(info.getClasses(), recType); if (rec.getFields().size() == node.getPatterns().size()) { for (int i = 0; i < node.getPatterns().size(); i++) { SPatternIR p = node.getPatterns().get(i); STypeIR t = rec.getFields().get(i).getType(); p.apply(this, t); } } else { log.error("Record patterns and record fields do not match in terms of size"); } } else { log.error("Expected record pattern to have a record type. Got: " + type); } } private void storeType(SPatternIR pattern, STypeIR type) { this.typeTable.put(pattern, type); } public STypeIR getPatternType(SPatternIR pattern) { return this.typeTable.get(pattern); } public static STypeIR getType(PatternTypeFinder typeFinder, AIdentifierPatternIR occ) { STypeIR occType = typeFinder.getPatternType(occ); if (occType == null) { log.error("Could not find type of identifier pattern " + occ); occType = new AUnknownTypeIR(); } else { occType = occType.clone(); } return occType; } }