package org.overture.pog.visitors; import java.util.List; import java.util.Vector; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.AnswerAdaptor; import org.overture.ast.definitions.ALocalDefinition; import org.overture.ast.expressions.ABooleanConstExp; import org.overture.ast.expressions.ACharLiteralExp; import org.overture.ast.expressions.AIntLiteralExp; import org.overture.ast.expressions.AMapEnumMapExp; import org.overture.ast.expressions.AMapUnionBinaryExp; import org.overture.ast.expressions.AMapletExp; import org.overture.ast.expressions.AMkTypeExp; import org.overture.ast.expressions.ANilExp; import org.overture.ast.expressions.AQuoteLiteralExp; import org.overture.ast.expressions.ARealLiteralExp; import org.overture.ast.expressions.ASeqConcatBinaryExp; import org.overture.ast.expressions.ASeqEnumSeqExp; import org.overture.ast.expressions.ASetEnumSetExp; import org.overture.ast.expressions.ASetUnionBinaryExp; import org.overture.ast.expressions.AStringLiteralExp; import org.overture.ast.expressions.ATupleExp; import org.overture.ast.expressions.AVariableExp; import org.overture.ast.expressions.PExp; import org.overture.ast.factory.AstFactory; import org.overture.ast.lex.LexKeywordToken; import org.overture.ast.lex.LexNameToken; import org.overture.ast.lex.VDMToken; import org.overture.ast.node.INode; import org.overture.ast.patterns.ABooleanPattern; import org.overture.ast.patterns.ACharacterPattern; import org.overture.ast.patterns.AConcatenationPattern; import org.overture.ast.patterns.AExpressionPattern; import org.overture.ast.patterns.AIdentifierPattern; import org.overture.ast.patterns.AIgnorePattern; import org.overture.ast.patterns.AIntegerPattern; import org.overture.ast.patterns.AMapPattern; import org.overture.ast.patterns.AMapUnionPattern; import org.overture.ast.patterns.AMapletPatternMaplet; import org.overture.ast.patterns.ANilPattern; import org.overture.ast.patterns.AQuotePattern; import org.overture.ast.patterns.ARealPattern; import org.overture.ast.patterns.ARecordPattern; import org.overture.ast.patterns.ASeqPattern; import org.overture.ast.patterns.ASetPattern; import org.overture.ast.patterns.AStringPattern; import org.overture.ast.patterns.ATuplePattern; import org.overture.ast.patterns.AUnionPattern; import org.overture.ast.patterns.PPattern; import org.overture.ast.typechecker.NameScope; import org.overture.ast.types.AUnknownType; import org.overture.ast.types.PType; import org.overture.pog.pub.IPogAssistantFactory; import org.overture.pog.utility.UniqueNameGenerator; public class PatternToExpVisitor extends AnswerAdaptor<PExp> { private final UniqueNameGenerator unique; private final IPogAssistantFactory af; public PatternToExpVisitor(UniqueNameGenerator unique, IPogAssistantFactory af) { this.af = af; this.unique = unique; } public PExp defaultPPattern(PPattern node) throws AnalysisException { throw new RuntimeException("Cannot convert pattern to Expression: " + node); } /** * First, literal patterns convert to expressions easily: * * @param node * @return * @throws AnalysisException */ public PExp caseABooleanPattern(ABooleanPattern node) throws AnalysisException { ABooleanConstExp b = new ABooleanConstExp(); b.setValue(node.getValue().clone()); addPossibleType(b, node); return b; } public PExp caseACharacterPattern(ACharacterPattern node) throws AnalysisException { ACharLiteralExp ch = new ACharLiteralExp(); ch.setValue(node.getValue().clone()); addPossibleType(ch, node); return ch; } public PExp caseAStringPattern(AStringPattern node) throws AnalysisException { AStringLiteralExp string = new AStringLiteralExp(); string.setValue(node.getValue().clone()); addPossibleType(string, node); return string; } public PExp caseAExpressionPattern(AExpressionPattern node) throws AnalysisException { return node.getExp(); } public PExp caseAIdentifierPattern(AIdentifierPattern node) throws AnalysisException { AVariableExp var = new AVariableExp(); var.setName(node.getName().clone()); var.setOriginal(var.getName().getFullName()); var.setVardef(pattern2DummyDef(node)); addPossibleType(var, node); return var; } public PExp caseAIgnorePattern(AIgnorePattern node) throws AnalysisException { AVariableExp var = new AVariableExp(); var.setName(unique.getUnique("any")); var.setOriginal(var.getName().getFullName()); var.setVardef(pattern2DummyDef(node)); addPossibleType(var, node); return var; } public PExp caseAIntegerPattern(AIntegerPattern node) throws AnalysisException { AIntLiteralExp exp = new AIntLiteralExp(); exp.setValue(node.getValue().clone()); addPossibleType(exp, node); return exp; } public PExp caseANilPattern(ANilPattern node) throws AnalysisException { return addPossibleType(new ANilExp(), node); } public PExp caseAQuotePattern(AQuotePattern node) throws AnalysisException { AQuoteLiteralExp quote = new AQuoteLiteralExp(); quote.setValue(node.getValue().clone()); addPossibleType(quote, node); return quote; } public PExp caseARealPattern(ARealPattern node) throws AnalysisException { ARealLiteralExp exp = new ARealLiteralExp(); exp.setValue(node.getValue().clone()); addPossibleType(exp, node); return exp; } /** * Now, compound patterns involve recursive calls to expand their pattern components to expressions. * * @param node * @return * @throws AnalysisException */ public PExp caseARecordPattern(ARecordPattern node) throws AnalysisException { AMkTypeExp mkExp = new AMkTypeExp(); mkExp.setTypeName(node.getTypename().clone()); List<PExp> args = new Vector<PExp>(); for (PPattern p : node.getPlist()) { args.add(p.apply(this).clone()); } addPossibleType(mkExp, node); mkExp.setArgs(args); return mkExp; } public PExp caseATuplePattern(ATuplePattern node) throws AnalysisException { ATupleExp tuple = new ATupleExp(); List<PExp> values = new Vector<PExp>(); for (PPattern p : node.getPlist()) { PExp e = p.apply(this); values.add(e.clone()); } addPossibleType(tuple, node); tuple.setArgs(values); return tuple; } public PExp caseASeqPattern(ASeqPattern node) throws AnalysisException { ASeqEnumSeqExp seq = new ASeqEnumSeqExp(); List<PExp> values = new Vector<PExp>(); for (PPattern p : node.getPlist()) { values.add(p.apply(this).clone()); } seq.setMembers(values); return addPossibleType(seq, node); } public PExp caseAConcatenationPattern(AConcatenationPattern node) throws AnalysisException { ASeqConcatBinaryExp conc = new ASeqConcatBinaryExp(); conc.setLeft(node.getLeft().apply(this).clone()); conc.setOp(new LexKeywordToken(VDMToken.CONCATENATE, null)); conc.setRight(node.getRight().apply(this).clone()); return addPossibleType(conc, node); } public PExp caseASetPattern(ASetPattern node) throws AnalysisException { ASetEnumSetExp set = new ASetEnumSetExp(); List<PExp> values = new Vector<PExp>(); for (PPattern p : node.getPlist()) { values.add(p.apply(this).clone()); } set.setMembers(values); return addPossibleType(set, node); } public PExp caseAUnionPattern(AUnionPattern node) throws AnalysisException { ASetUnionBinaryExp union = new ASetUnionBinaryExp(); union.setLeft(node.getLeft().apply(this).clone()); union.setOp(new LexKeywordToken(VDMToken.UNION, null)); union.setRight(node.getRight().apply(this).clone()); return addPossibleType(union, node); } public PExp caseAMapPattern(AMapPattern node) throws AnalysisException { AMapEnumMapExp map = new AMapEnumMapExp(); List<AMapletExp> values = new Vector<AMapletExp>(); for (AMapletPatternMaplet p : node.getMaplets()) { values.add((AMapletExp) p.apply(this).clone()); } map.setMembers(values); return addPossibleType(map, node); } public PExp caseAMapletPatternMaplet(AMapletPatternMaplet node) throws AnalysisException { AMapletExp maplet = new AMapletExp(); PExp from = node.getFrom().apply(this).clone(); maplet.setLeft(from); PExp to = node.getTo().apply(this).clone(); maplet.setRight(to); maplet.setType(AstFactory.newAMapMapType(null, from.getType().clone(), to.getType().clone())); return maplet; } public PExp caseAMapUnionPattern(AMapUnionPattern node) throws AnalysisException { AMapUnionBinaryExp union = new AMapUnionBinaryExp(); union.setLeft(node.getLeft().apply(this).clone()); union.setOp(new LexKeywordToken(VDMToken.MUNION, null)); union.setRight(node.getRight().apply(this).clone()); return addPossibleType(union, node); } @Override public PExp createNewReturnValue(INode node) { throw new RuntimeException("Cannot convert pattern to Expression: " + node); } @Override public PExp createNewReturnValue(Object node) { throw new RuntimeException("Cannot convert pattern to Expression: " + node); } /* * VarExps in the CGP need a corresponding vardef or it crashes. So we add dummy definitions to avoid the crash. The * definition is never needed for anything. */ private ALocalDefinition pattern2DummyDef(PPattern pat) { ALocalDefinition r = AstFactory.newALocalDefinition(null, new LexNameToken("", "", pat.getLocation().clone()), NameScope.LOCAL, new AUnknownType()); return r; } private PExp addPossibleType(PExp exp, PPattern node) { PType possibleType = af.createPPatternAssistant().getPossibleType(node); if (possibleType != null) { exp.setType(possibleType.clone()); } else { exp.setType(new AUnknownType()); } return exp; } }