package org.overture.interpreter.utilities.definition;
import org.overture.ast.analysis.AnalysisException;
import org.overture.ast.analysis.QuestionAnswerAdaptor;
import org.overture.ast.definitions.AAssignmentDefinition;
import org.overture.ast.definitions.AEqualsDefinition;
import org.overture.ast.definitions.AExplicitFunctionDefinition;
import org.overture.ast.definitions.AExplicitOperationDefinition;
import org.overture.ast.definitions.AImplicitFunctionDefinition;
import org.overture.ast.definitions.AImplicitOperationDefinition;
import org.overture.ast.definitions.AImportedDefinition;
import org.overture.ast.definitions.AInheritedDefinition;
import org.overture.ast.definitions.AInstanceVariableDefinition;
import org.overture.ast.definitions.ALocalDefinition;
import org.overture.ast.definitions.ARenamedDefinition;
import org.overture.ast.definitions.AThreadDefinition;
import org.overture.ast.definitions.ATypeDefinition;
import org.overture.ast.definitions.AUntypedDefinition;
import org.overture.ast.definitions.AValueDefinition;
import org.overture.ast.definitions.PDefinition;
import org.overture.ast.lex.Dialect;
import org.overture.ast.node.INode;
import org.overture.config.Settings;
import org.overture.interpreter.assistant.IInterpreterAssistantFactory;
import org.overture.interpreter.runtime.Context;
import org.overture.interpreter.runtime.PatternMatchException;
import org.overture.interpreter.runtime.ValueException;
import org.overture.interpreter.runtime.VdmRuntime;
import org.overture.interpreter.runtime.VdmRuntimeError;
import org.overture.interpreter.values.FunctionValue;
import org.overture.interpreter.values.NameValuePair;
import org.overture.interpreter.values.NameValuePairList;
import org.overture.interpreter.values.OperationValue;
import org.overture.interpreter.values.Value;
import org.overture.interpreter.values.ValueList;
import org.overture.interpreter.values.ValueSet;
/***************************************
* @author gkanos
****************************************/
public class NamedValueLister extends
QuestionAnswerAdaptor<Context, NameValuePairList>
{
protected IInterpreterAssistantFactory af;
public NamedValueLister(IInterpreterAssistantFactory af)
{
this.af = af;
}
@Override
public NameValuePairList caseAAssignmentDefinition(
AAssignmentDefinition def, Context initialContext)
throws AnalysisException
{
try
{
Value v = def.getExpression().apply(VdmRuntime.getExpressionEvaluator(), initialContext);
if (!v.isUndefined())
{
v = v.convertTo(def.getType(), initialContext);
}
return new NameValuePairList(new NameValuePair(def.getName(), v.getUpdatable(null)));
} catch (AnalysisException e)
{
if (e instanceof ValueException)
{
VdmRuntimeError.abort(def.getLocation(), (ValueException) e);
}
return null;
}
}
@Override
public NameValuePairList caseAEqualsDefinition(AEqualsDefinition def,
Context initialContext) throws AnalysisException
{
Value v;
try
{
v = def.getTest().apply(VdmRuntime.getExpressionEvaluator(), initialContext);
} catch (AnalysisException e1)
{
if (e1 instanceof ValueException)
{
VdmRuntimeError.abort(def.getLocation(), (ValueException) e1);
}
return null;
}
NameValuePairList nvpl = null;
if (def.getPattern() != null)
{
try
{
nvpl = af.createPPatternAssistant().getNamedValues(def.getPattern(), v, initialContext);
} catch (PatternMatchException e)
{
VdmRuntimeError.abort(e, initialContext);
}
}
else if (def.getTypebind() != null)
{
try
{
Value converted = v.convertTo(def.getTypebind().getType(), initialContext);
nvpl = af.createPPatternAssistant().getNamedValues(def.getTypebind().getPattern(), converted, initialContext);
} catch (PatternMatchException e)
{
VdmRuntimeError.abort(e, initialContext);
} catch (ValueException e)
{
VdmRuntimeError.abort(def.getLocation(), e);
}
}
else if (def.getSetbind() != null)
{
try
{
ValueSet set = def.getSetbind().getSet().apply(VdmRuntime.getExpressionEvaluator(), initialContext).setValue(initialContext);
if (!set.contains(v))
{
VdmRuntimeError.abort(def.getLocation(), 4002, "Expression value is not in set bind", initialContext);
}
nvpl = af.createPPatternAssistant().getNamedValues(def.getSetbind().getPattern(), v, initialContext);
}
catch (AnalysisException e)
{
if (e instanceof PatternMatchException)
{
VdmRuntimeError.abort((PatternMatchException) e, initialContext);
}
if (e instanceof ValueException)
{
VdmRuntimeError.abort(def.getLocation(), (ValueException) e);
}
}
}
else if (def.getSeqbind() != null)
{
try
{
ValueList seq = def.getSeqbind().getSeq().apply(VdmRuntime.getExpressionEvaluator(), initialContext).seqValue(initialContext);
if (!seq.contains(v))
{
VdmRuntimeError.abort(def.getLocation(), 4002, "Expression value is not in seq bind", initialContext);
}
nvpl = af.createPPatternAssistant().getNamedValues(def.getSeqbind().getPattern(), v, initialContext);
}
catch (AnalysisException e)
{
if (e instanceof PatternMatchException)
{
VdmRuntimeError.abort((PatternMatchException) e, initialContext);
}
if (e instanceof ValueException)
{
VdmRuntimeError.abort(def.getLocation(), (ValueException) e);
}
}
}
return nvpl;
}
@Override
public NameValuePairList caseAExplicitFunctionDefinition(
AExplicitFunctionDefinition def, Context initialContext)
throws AnalysisException
{
NameValuePairList nvl = new NameValuePairList();
Context free = initialContext.getVisibleVariables();
FunctionValue prefunc = def.getPredef() == null ? null
: new FunctionValue(def.getPredef(), null, null, free);
FunctionValue postfunc = def.getPostdef() == null ? null
: new FunctionValue(def.getPostdef(), null, null, free);
FunctionValue func = new FunctionValue(def, prefunc, postfunc, free);
func.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
func.uninstantiated = !def.getTypeParams().isEmpty();
nvl.add(new NameValuePair(def.getName(), func));
if (def.getPredef() != null)
{
nvl.add(new NameValuePair(def.getPredef().getName(), prefunc));
prefunc.uninstantiated = !def.getTypeParams().isEmpty();
}
if (def.getPostdef() != null)
{
nvl.add(new NameValuePair(def.getPostdef().getName(), postfunc));
postfunc.uninstantiated = !def.getTypeParams().isEmpty();
}
if (Settings.dialect == Dialect.VDM_SL)
{
// This is needed for recursive local functions
free.putList(nvl);
}
return nvl;
}
@Override
public NameValuePairList caseAExplicitOperationDefinition(
AExplicitOperationDefinition def, Context initialContext)
throws AnalysisException
{
NameValuePairList nvl = new NameValuePairList();
FunctionValue prefunc = def.getPredef() == null ? null
: new FunctionValue(def.getPredef(), null, null, null);
FunctionValue postfunc = def.getPostdef() == null ? null
: new FunctionValue(def.getPostdef(), null, null, null);
OperationValue op = new OperationValue(def, prefunc, postfunc, def.getState(), af);
op.isConstructor = def.getIsConstructor();
op.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
nvl.add(new NameValuePair(def.getName(), op));
if (def.getPredef() != null)
{
prefunc.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
nvl.add(new NameValuePair(def.getPredef().getName(), prefunc));
}
if (def.getPostdef() != null)
{
postfunc.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
nvl.add(new NameValuePair(def.getPostdef().getName(), postfunc));
}
return nvl;
}
@Override
public NameValuePairList caseAImplicitFunctionDefinition(
AImplicitFunctionDefinition def, Context initialContext)
throws AnalysisException
{
NameValuePairList nvl = new NameValuePairList();
Context free = initialContext.getVisibleVariables();
FunctionValue prefunc = def.getPredef() == null ? null
: new FunctionValue(def.getPredef(), null, null, free);
FunctionValue postfunc = def.getPostdef() == null ? null
: new FunctionValue(def.getPostdef(), null, null, free);
// Note, body may be null if it is really implicit. This is caught
// when the function is invoked. The value is needed to implement
// the pre_() expression for implicit functions.
FunctionValue func = new FunctionValue(def, prefunc, postfunc, free);
func.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
func.uninstantiated = !def.getTypeParams().isEmpty();
nvl.add(new NameValuePair(def.getName(), func));
if (def.getPredef() != null)
{
nvl.add(new NameValuePair(def.getPredef().getName(), prefunc));
prefunc.uninstantiated = !def.getTypeParams().isEmpty();
}
if (def.getPostdef() != null)
{
nvl.add(new NameValuePair(def.getPostdef().getName(), postfunc));
postfunc.uninstantiated = !def.getTypeParams().isEmpty();
}
if (Settings.dialect == Dialect.VDM_SL)
{
// This is needed for recursive local functions
free.putList(nvl);
}
return nvl;
}
@Override
public NameValuePairList caseAImplicitOperationDefinition(
AImplicitOperationDefinition def, Context initialContext)
throws AnalysisException
{
NameValuePairList nvl = new NameValuePairList();
FunctionValue prefunc = def.getPredef() == null ? null
: new FunctionValue(def.getPredef(), null, null, null);
FunctionValue postfunc = def.getPostdef() == null ? null
: new FunctionValue(def.getPostdef(), null, null, null);
// Note, body may be null if it is really implicit. This is caught
// when the function is invoked. The value is needed to implement
// the pre_() expression for implicit functions.
OperationValue op = new OperationValue(def, prefunc, postfunc, def.getState(), af);
op.isConstructor = def.getIsConstructor();
op.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
nvl.add(new NameValuePair(def.getName(), op));
if (def.getPredef() != null)
{
prefunc.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
nvl.add(new NameValuePair(def.getPredef().getName(), prefunc));
}
if (def.getPostdef() != null)
{
postfunc.isStatic = af.createPAccessSpecifierAssistant().isStatic(def.getAccess());
nvl.add(new NameValuePair(def.getPostdef().getName(), postfunc));
}
return nvl;
}
@Override
public NameValuePairList caseAImportedDefinition(AImportedDefinition def,
Context initialContext) throws AnalysisException
{
NameValuePairList renamed = new NameValuePairList();
for (NameValuePair nv : af.createPDefinitionAssistant().getNamedValues(def.getDef(), initialContext))
{
if (nv.name.equals(def.getDef().getName())) // NB. excludes pre/post/inv functions
{
renamed.add(new NameValuePair(def.getName(), nv.value));
}
}
return renamed;
}
@Override
public NameValuePairList caseAInheritedDefinition(AInheritedDefinition def,
Context initialContext) throws AnalysisException
{
NameValuePairList renamed = new NameValuePairList();
if (def.getSuperdef() instanceof AUntypedDefinition)
{
if (def.getClassDefinition() != null)
{
def.setSuperdef(af.createPDefinitionAssistant().findName(def.getClassDefinition(), def.getSuperdef().getName(), def.getNameScope()));
}
}
for (NameValuePair nv : af.createPDefinitionAssistant().getNamedValues(def.getSuperdef(), initialContext))
{
renamed.add(new NameValuePair(nv.name.getModifiedName(def.getName().getModule()), nv.value));
}
return renamed;
}
@Override
public NameValuePairList caseAInstanceVariableDefinition(
AInstanceVariableDefinition def, Context initialContext)
throws AnalysisException
{
try
{
Value v = def.getExpression().apply(VdmRuntime.getExpressionEvaluator(), initialContext);
if (!v.isUndefined())
{
v = v.convertTo(def.getType(), initialContext);
}
return new NameValuePairList(new NameValuePair(def.getName(), v.getUpdatable(null)));
} catch (ValueException e)
{
VdmRuntimeError.abort(def.getLocation(), e);
return null;
} catch (AnalysisException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
@Override
public NameValuePairList caseALocalDefinition(ALocalDefinition def,
Context initialContext) throws AnalysisException
{
NameValuePair nvp = new NameValuePair(def.getName(), initialContext.lookup(def.getName()));
return new NameValuePairList(nvp);
}
@Override
public NameValuePairList caseARenamedDefinition(ARenamedDefinition def,
Context initialContext) throws AnalysisException
{
NameValuePairList renamed = new NameValuePairList();
for (NameValuePair nv : af.createPDefinitionAssistant().getNamedValues(def.getDef(), initialContext))
{
// We exclude any name from the definition other than the one
// explicitly renamed. Otherwise, generated names like pre_f
// come through and are not renamed.
if (nv.name.equals(def.getDef().getName()))
{
renamed.add(new NameValuePair(def.getName(), nv.value));
}
}
return renamed;
}
@Override
public NameValuePairList caseAThreadDefinition(AThreadDefinition def,
Context initialContext) throws AnalysisException
{
return def.getOperationDef().apply(THIS, initialContext);
}
@Override
public NameValuePairList caseATypeDefinition(ATypeDefinition def,
Context initialContext) throws AnalysisException
{
NameValuePairList nvl = new NameValuePairList();
if (def.getInvdef() != null)
{
FunctionValue invfunc = new FunctionValue(def.getInvdef(), null, null, initialContext);
nvl.add(new NameValuePair(def.getInvdef().getName(), invfunc));
}
return nvl;
}
@Override
public NameValuePairList caseAUntypedDefinition(AUntypedDefinition def,
Context initialContext) throws AnalysisException
{
assert false : "Can't get name/values of untyped definition?";
return null;
}
@Override
public NameValuePairList caseAValueDefinition(AValueDefinition def,
Context initialContext) throws AnalysisException
{
Value v = null;
try
{
// UpdatableValues are constantized as they cannot be updated.
v = def.getExpression().apply(VdmRuntime.getExpressionEvaluator(), initialContext).convertTo(af.createPDefinitionAssistant().getType(def), initialContext).getConstant();
return af.createPPatternAssistant().getNamedValues(def.getPattern(), v, initialContext);
} catch (ValueException e)
{
VdmRuntimeError.abort(def.getLocation(), e);
} catch (PatternMatchException e)
{
VdmRuntimeError.abort(e, initialContext);
} catch (AnalysisException e)
{
}
return null;
}
@Override
public NameValuePairList defaultPDefinition(PDefinition def,
Context initialContext) throws AnalysisException
{
return new NameValuePairList(); // Overridden
}
@Override
public NameValuePairList createNewReturnValue(INode node, Context question)
throws AnalysisException
{
// TODO Auto-generated method stub
return null;
}
@Override
public NameValuePairList createNewReturnValue(Object node, Context question)
throws AnalysisException
{
// TODO Auto-generated method stub
return null;
}
}