package org.overture.interpreter.utilities.expression; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.QuestionAnswerAdaptor; import org.overture.ast.expressions.AApplyExp; import org.overture.ast.expressions.ACaseAlternative; import org.overture.ast.expressions.ACasesExp; import org.overture.ast.expressions.ADefExp; import org.overture.ast.expressions.AElseIfExp; import org.overture.ast.expressions.AExists1Exp; import org.overture.ast.expressions.AExistsExp; import org.overture.ast.expressions.AFieldExp; import org.overture.ast.expressions.AFieldNumberExp; import org.overture.ast.expressions.AForAllExp; import org.overture.ast.expressions.AFuncInstatiationExp; import org.overture.ast.expressions.AIfExp; import org.overture.ast.expressions.AIotaExp; import org.overture.ast.expressions.AIsExp; import org.overture.ast.expressions.AIsOfBaseClassExp; import org.overture.ast.expressions.AIsOfClassExp; import org.overture.ast.expressions.ALambdaExp; import org.overture.ast.expressions.ALetBeStExp; import org.overture.ast.expressions.ALetDefExp; import org.overture.ast.expressions.AMapCompMapExp; import org.overture.ast.expressions.AMapEnumMapExp; import org.overture.ast.expressions.AMapletExp; import org.overture.ast.expressions.AMkBasicExp; import org.overture.ast.expressions.AMkTypeExp; import org.overture.ast.expressions.AMuExp; import org.overture.ast.expressions.ANarrowExp; import org.overture.ast.expressions.ANewExp; import org.overture.ast.expressions.ARecordModifier; import org.overture.ast.expressions.ASameBaseClassExp; import org.overture.ast.expressions.ASameClassExp; import org.overture.ast.expressions.ASeqCompSeqExp; import org.overture.ast.expressions.ASeqEnumSeqExp; import org.overture.ast.expressions.ASetCompSetExp; import org.overture.ast.expressions.ASetEnumSetExp; import org.overture.ast.expressions.ASubseqExp; import org.overture.ast.expressions.ATupleExp; import org.overture.ast.expressions.AVariableExp; import org.overture.ast.expressions.PExp; import org.overture.ast.expressions.SBinaryExp; import org.overture.ast.expressions.SMapExp; import org.overture.ast.expressions.SSeqExp; import org.overture.ast.expressions.SSetExp; import org.overture.ast.expressions.SUnaryExp; import org.overture.ast.node.INode; import org.overture.ast.patterns.PMultipleBind; import org.overture.interpreter.assistant.IInterpreterAssistantFactory; import org.overture.interpreter.runtime.ContextException; import org.overture.interpreter.runtime.ObjectContext; import org.overture.interpreter.runtime.ValueException; import org.overture.interpreter.runtime.VdmRuntimeError; import org.overture.interpreter.values.UpdatableValue; import org.overture.interpreter.values.Value; import org.overture.interpreter.values.ValueList; /*************************************** * This method collects and returns the values of an expression. * * @author gkanos ****************************************/ public class ExpressionValueCollector extends QuestionAnswerAdaptor<ObjectContext, ValueList> { protected IInterpreterAssistantFactory af; public ExpressionValueCollector(IInterpreterAssistantFactory af) { this.af = af; } @Override public ValueList caseAApplyExp(AApplyExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = af.createPExpAssistant().getValues(exp.getArgs(), ctxt); list.addAll(exp.getRoot().apply(THIS, ctxt)); return list; } @Override public ValueList defaultSBinaryExp(SBinaryExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getLeft().apply(THIS, ctxt); list.addAll(exp.getRight().apply(THIS, ctxt)); return list; } @Override public ValueList caseACasesExp(ACasesExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getExpression().apply(THIS, ctxt); for (ACaseAlternative c : exp.getCases()) { list.addAll(c.apply(THIS, ctxt)); } if (exp.getOthers() != null) { list.addAll(exp.getOthers().apply(THIS, ctxt)); } return list; } @Override public ValueList caseADefExp(ADefExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = af.createPDefinitionListAssistant().getValues(exp.getLocalDefs(), ctxt); list.addAll(exp.getExpression().apply(THIS, ctxt)); return list; } @Override public ValueList caseAElseIfExp(AElseIfExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getElseIf().apply(THIS, ctxt); list.addAll(exp.getThen().apply(THIS, ctxt)); return list; } @Override public ValueList caseAExistsExp(AExistsExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = new ValueList(); for (PMultipleBind mb : exp.getBindList()) { list.addAll(ctxt.assistantFactory.createPMultipleBindAssistant().getValues(mb, ctxt)); } list.addAll(exp.getPredicate().apply(THIS, ctxt)); return list; } @Override public ValueList caseAExists1Exp(AExists1Exp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = af.createPBindAssistant().getValues(exp.getBind(), ctxt); list.addAll(exp.getPredicate().apply(THIS, ctxt)); return list; } @Override public ValueList caseAFieldExp(AFieldExp exp, ObjectContext ctxt) throws AnalysisException { ValueList values = exp.getObject().apply(THIS, ctxt); try { // This evaluation should not affect scheduling as we are trying to // discover the sync variables to listen to only. ctxt.threadState.setAtomic(true); Value r = af.createAFieldExpAssistant().evaluate(exp, ctxt); if (r instanceof UpdatableValue) { values.add(r); } return values; } catch (ContextException e) { if (e.number == 4034) { return values; // Non existent variable } else { throw e; } } catch (ValueException e) { if (e.number == 4097 || e.number == 4105) { return values; // Cannot get record/object value of ... } VdmRuntimeError.abort(exp.getLocation(), e); return null; } catch (AnalysisException e) { e.printStackTrace(); return null; } finally { ctxt.threadState.setAtomic(false); } } @Override public ValueList caseAFieldNumberExp(AFieldNumberExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getTuple().apply(THIS, ctxt); } @Override public ValueList caseAForAllExp(AForAllExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = new ValueList(); for (PMultipleBind mb : exp.getBindList()) { list.addAll(ctxt.assistantFactory.createPMultipleBindAssistant().getValues(mb, ctxt)); } list.addAll(exp.getPredicate().apply(THIS, ctxt)); return list; } @Override public ValueList caseAFuncInstatiationExp(AFuncInstatiationExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getFunction().apply(THIS, ctxt); } @Override public ValueList caseAIfExp(AIfExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getTest().apply(THIS, ctxt); list.addAll(exp.getThen().apply(THIS, ctxt)); for (AElseIfExp elif : exp.getElseList()) { list.addAll(elif.apply(THIS, ctxt)); } if (exp.getElse() != null) { list.addAll(exp.getElse().apply(THIS, ctxt)); } return list; } @Override public ValueList caseAIotaExp(AIotaExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = af.createPBindAssistant().getValues(exp.getBind(), ctxt); list.addAll(exp.getPredicate().apply(THIS, ctxt)); return list; } @Override public ValueList caseAIsExp(AIsExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getTest().apply(THIS, ctxt); } @Override public ValueList caseAIsOfBaseClassExp(AIsOfBaseClassExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getExp().apply(THIS, ctxt); } @Override public ValueList caseAIsOfClassExp(AIsOfClassExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getExp().apply(THIS, ctxt); } @Override public ValueList caseALambdaExp(ALambdaExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getExpression().apply(THIS, ctxt); } @Override public ValueList caseALetBeStExp(ALetBeStExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = ctxt.assistantFactory.createPMultipleBindAssistant().getValues(exp.getBind(), ctxt); if (exp.getSuchThat() != null) { list.addAll(exp.getSuchThat().apply(THIS, ctxt)); } list.addAll(exp.getValue().apply(THIS, ctxt)); return list; } @Override public ValueList caseALetDefExp(ALetDefExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = af.createPDefinitionListAssistant().getValues(exp.getLocalDefs(), ctxt); list.addAll(exp.getExpression().apply(THIS, ctxt)); return list; } @Override public ValueList caseAMapCompMapExp(AMapCompMapExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getFirst().apply(THIS, ctxt); for (PMultipleBind mb : exp.getBindings()) { list.addAll(ctxt.assistantFactory.createPMultipleBindAssistant().getValues(mb, ctxt)); } if (exp.getPredicate() != null) { list.addAll(exp.getPredicate().apply(THIS, ctxt)); } return list; } @Override public ValueList caseAMapEnumMapExp(AMapEnumMapExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = new ValueList(); for (AMapletExp maplet : exp.getMembers()) { list.addAll(maplet.apply(THIS, ctxt)); } return list; } @Override public ValueList defaultSMapExp(SMapExp exp, ObjectContext ctxt) throws AnalysisException { return new ValueList(); } @Override public ValueList caseAMapletExp(AMapletExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.apply(THIS, ctxt); list.addAll(exp.getRight().apply(THIS, ctxt)); return list; } @Override public ValueList caseAMkBasicExp(AMkBasicExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getArg().apply(THIS, ctxt); } @Override public ValueList caseAMkTypeExp(AMkTypeExp exp, ObjectContext ctxt) throws AnalysisException { return af.createPExpAssistant().getValues(exp.getArgs(), ctxt); } @Override public ValueList caseAMuExp(AMuExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getRecord().apply(THIS, ctxt); for (ARecordModifier rm : exp.getModifiers()) { list.addAll(rm.getValue().apply(THIS, ctxt)); } return list; } @Override public ValueList caseANarrowExp(ANarrowExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getTest().apply(THIS, ctxt); } @Override public ValueList caseANewExp(ANewExp exp, ObjectContext ctxt) throws AnalysisException { return af.createPExpAssistant().getValues(exp.getArgs(), ctxt); } @Override public ValueList caseASameBaseClassExp(ASameBaseClassExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getLeft().apply(THIS, ctxt); list.addAll(exp.getRight().apply(THIS, ctxt)); return list; } @Override public ValueList caseASameClassExp(ASameClassExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getLeft().apply(THIS, ctxt); list.addAll(exp.getRight().apply(THIS, ctxt)); return list; } @Override public ValueList caseASeqCompSeqExp(ASeqCompSeqExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getFirst().apply(THIS, ctxt); list.addAll(af.createPBindAssistant().getBindValues(exp.getSetBind(), ctxt, false)); if (exp.getPredicate() != null) { list.addAll(exp.getPredicate().apply(THIS, ctxt)); } return list; } @Override public ValueList caseASeqEnumSeqExp(ASeqEnumSeqExp exp, ObjectContext ctxt) throws AnalysisException { return af.createPExpAssistant().getValues(exp.getMembers(), ctxt); } @Override public ValueList defaultSSeqExp(SSeqExp exp, ObjectContext ctxt) throws AnalysisException { return new ValueList(); } @Override public ValueList caseASetCompSetExp(ASetCompSetExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getFirst().apply(THIS, ctxt); for (PMultipleBind mb : exp.getBindings()) { list.addAll(ctxt.assistantFactory.createPMultipleBindAssistant().getValues(mb, ctxt)); } if (exp.getPredicate() != null) { list.addAll(exp.getPredicate().apply(THIS, ctxt)); } return list; } @Override public ValueList caseASetEnumSetExp(ASetEnumSetExp exp, ObjectContext ctxt) throws AnalysisException { return af.createPExpAssistant().getValues(exp.getMembers(), ctxt); } @Override public ValueList defaultSSetExp(SSetExp exp, ObjectContext ctxt) throws AnalysisException { return new ValueList(); } @Override public ValueList caseASubseqExp(ASubseqExp exp, ObjectContext ctxt) throws AnalysisException { ValueList list = exp.getSeq().apply(THIS, ctxt); list.addAll(exp.getFrom().apply(THIS, ctxt)); list.addAll(exp.getTo().apply(THIS, ctxt)); return list; } @Override public ValueList caseATupleExp(ATupleExp exp, ObjectContext ctxt) throws AnalysisException { return af.createPExpAssistant().getValues(exp.getArgs(), ctxt); } @Override public ValueList defaultSUnaryExp(SUnaryExp exp, ObjectContext ctxt) throws AnalysisException { return exp.getExp().apply(THIS, ctxt); } @Override public ValueList caseAVariableExp(AVariableExp exp, ObjectContext ctxt) throws AnalysisException { Value v = ctxt.check(exp.getName()); if (v == null || !(v instanceof UpdatableValue)) { return new ValueList(); } else { return new ValueList(v); } } @Override public ValueList defaultPExp(PExp exp, ObjectContext ctxt) throws AnalysisException { return new ValueList(); // Default, for expressions with no variables } @Override public ValueList createNewReturnValue(INode node, ObjectContext question) throws AnalysisException { // TODO Auto-generated method stub return null; } @Override public ValueList createNewReturnValue(Object node, ObjectContext question) throws AnalysisException { // TODO Auto-generated method stub return null; } }