/** * <copyright> * </copyright> * * $Id$ */ package tefkat.engine.runtime.impl; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import tefkat.engine.runtime.Binding; import tefkat.engine.runtime.Context; import tefkat.engine.runtime.NotGroundException; import tefkat.engine.runtime.PatternDefn; import tefkat.engine.runtime.ResolutionException; import tefkat.engine.runtime.Tree; import tefkat.engine.runtime.TreeListener; import tefkat.engine.runtime.NotTerm; import tefkat.engine.runtime.RuntimePackage; import tefkat.engine.runtime.Var; import tefkat.engine.runtime.VarUse; /** * <!-- begin-user-doc --> * An implementation of the model object '<em><b>Not Term</b></em>'. * <!-- end-user-doc --> * <p> * </p> * * @generated */ public class NotTermImpl extends CompoundTermImpl implements NotTerm { /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public static final String copyright = "Copyright michael lawley 2004"; private EList nonLocalVars = null; /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ protected NotTermImpl() { super(); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ protected EClass eStaticClass() { return RuntimePackage.Literals.NOT_TERM; } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated NOT */ public EList getNonLocalVars() { if (null == nonLocalVars) { nonLocalVars = new BasicEList(); Set notVars = new HashSet(); Set usages = new HashSet(); // Find the Vars and VarUses that occur in the NOT for (Iterator itr = eAllContents(); itr.hasNext(); ) { Object obj = itr.next(); if (obj instanceof VarUse) { notVars.add(((VarUse) obj).getVar()); usages.add(obj); } } // Find just those Vars that are NOT only referenced in the NOT for (Iterator varItr = notVars.iterator(); varItr.hasNext(); ) { Var var = (Var) varItr.next(); if (var.getScope() instanceof PatternDefn && ((PatternDefn) var.getScope()).getParameterVar().contains(var)) { // Pattern parameters are non-local vars nonLocalVars.add(var); } else if (!usages.containsAll(var.getUsages())) { nonLocalVars.add(var); } } } return nonLocalVars; } public void match(final Context context) throws ResolutionException, NotGroundException { // Ensure that all non-local variables are already ground // (WrappedVars are handled by the Expander) for (final Iterator itr = getNonLocalVars().iterator(); itr.hasNext(); ) { Var var = (Var) itr.next(); Object value = context.lookup(var); if (null == value) { context.delay("Non-local variable " + var + " is not bound."); } } final VarExpander.Function f = new VarExpander.Function() { public void call(Context context, Binding unifier) throws ResolutionException { evalNegatedGoal(context, unifier, new ArrayList(getTerm())); } }; new VarExpander(context, getNonLocalVars(), f, context.getBindings()); } /** * Coupling to RuleEvakluator needs to be broken. * Probably the best approach is to make Tree "active" - evaluation should be a * behaviour of Tree rather than just using Tree as a passive data structure. * * @param context * @param unifier * @param negGoal * @return * @throws ResolutionException */ private void evalNegatedGoal(final Context context, final Binding unifier, final Collection negGoal) throws ResolutionException { // cannot pass node as context here or delayed terms will get pushed into the "NOT" // leading to possible spurious flounderings -- see also resolveIfTerm final Tree newTree = context.createTree(negGoal, unifier, true, true); newTree.addTreeListener(new TreeListener() { public void solution(Binding answer) { } public void completed(Tree theTree) { if (theTree.isSuccess()) { newTree.removeTreeListener(this); context.fail(); } else { // Negation tree finitely failed, regard as true. // context.createBranch(new Binding(unifier)); } } public void floundered(Tree theTree) { } }); } } //NotTermImpl