/*
* tuProlog - Copyright (C) 2001-2002 aliCE team at deis.unibo.it
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alice.tuprolog;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Administration of primitive predicates.
* @author Alex Benini
*/
public class PrimitiveManager {
private Map<IPrimitives, List<PrimitiveInfo>> libHashMap;
private Map<String, PrimitiveInfo> directiveHashMap;
private Map<String, PrimitiveInfo> predicateHashMap;
private Map<String, PrimitiveInfo> functorHashMap;
private Prolog engine;
public PrimitiveManager() {
libHashMap = new IdentityHashMap<IPrimitives, List<PrimitiveInfo>>();
directiveHashMap = new HashMap<String, PrimitiveInfo>();
predicateHashMap = new HashMap<String, PrimitiveInfo>();
functorHashMap = new HashMap<String, PrimitiveInfo>();
}
/**
* Configure this Manager
*/
void initialize(Prolog vm) {
engine = vm;
createPrimitiveInfo(new BuiltIn(vm));
}
void createPrimitiveInfo(IPrimitives src) {
Map<PrimitiveInfo.Type, List<PrimitiveInfo>> primitives = src.getPrimitives();
List<PrimitiveInfo> libraryPrimitives = new LinkedList<PrimitiveInfo>();
for (PrimitiveInfo p : primitives.get(PrimitiveInfo.Type.DIRECTIVE)) {
directiveHashMap.put(p.getKey(), p);
libraryPrimitives.add(p);
}
for (PrimitiveInfo p : primitives.get(PrimitiveInfo.Type.PREDICATE)) {
predicateHashMap.put(p.getKey(), p);
libraryPrimitives.add(p);
}
for (PrimitiveInfo p : primitives.get(PrimitiveInfo.Type.FUNCTOR)) {
functorHashMap.put(p.getKey(), p);
libraryPrimitives.add(p);
}
libHashMap.put(src, libraryPrimitives);
}
void deletePrimitiveInfo(IPrimitives src) {
for (PrimitiveInfo p : libHashMap.remove(src)) {
String k = p.invalidate();
directiveHashMap.remove(k);
predicateHashMap.remove(k);
functorHashMap.remove(k);
}
}
/**
* Identifies the term passed as argument.
*
* This involves identifying structs representing built-in
* predicates and functors, and setting up related structures
* and links.
*
* @param term the term to be identified
* @return term with the identified built-in directive
*/
public Term identifyDirective(Term term) {
identify(term, PrimitiveInfo.Type.DIRECTIVE);
return term;
}
public boolean evalAsDirective(Struct d) {
PrimitiveInfo pd = ((Struct) identifyDirective(d)).getPrimitive();
if (pd != null) {
try {
return pd.evalAsDirective(d);
} catch (InvocationTargetException ite) {
Throwable t = ite.getTargetException();
engine.warn("An exception occurred during the execution of the " +
d.getPredicateIndicator() + " directive:\n" + t.getMessage());
return false;
} catch (IllegalAccessException e) {
engine.warn("Cannot access the method defining the" +
d.getPredicateIndicator() + " directive.\n");
return false;
}
} else {
engine.warn("The directive " + d.getPredicateIndicator() + " is unknown.");
return false;
}
}
public void identifyPredicate(Term term) {
identify(term, PrimitiveInfo.Type.PREDICATE);
}
public void identifyFunctor(Term term) {
identify(term, PrimitiveInfo.Type.FUNCTOR);
}
private void identify(Term term, PrimitiveInfo.Type typeOfPrimitive) {
if (term == null)
return;
term = term.getTerm();
if (!(term instanceof Struct))
return;
Struct t = (Struct) term;
int arity = t.getArity();
String name = t.getName();
//------------------------------------------
if (name.equals(",") || name.equals("':-'") || name.equals(":-")) {
for (int c = 0; c < arity; c++)
identify(t.getArg(c), PrimitiveInfo.Type.PREDICATE);
} else
for (int c = 0; c < arity; c++)
identify(t.getArg(c), PrimitiveInfo.Type.FUNCTOR);
//------------------------------------------
//log.debug("Identification "+t);
PrimitiveInfo prim = null;
String key = name + "/" + arity;
switch (typeOfPrimitive) {
case DIRECTIVE :
prim = (PrimitiveInfo) directiveHashMap.get(key);
//log.debug("Assign predicate "+prim+" to "+t);
break;
case PREDICATE :
prim = (PrimitiveInfo) predicateHashMap.get(key);
//log.debug("Assign predicate "+prim+" to "+t);
break;
case FUNCTOR :
prim = (PrimitiveInfo) functorHashMap.get(key);
//log.debug("Assign functor "+prim+" to "+t);
break;
}
t.setPrimitive(prim);
}
Library getLibraryDirective(String name, int nArgs) {
try {
return (Library) ((PrimitiveInfo) directiveHashMap.get(name + "/" + nArgs)).getSource();
} catch (NullPointerException e) {
return null;
}
}
Library getLibraryPredicate(String name, int nArgs) {
try {
return (Library) ((PrimitiveInfo) predicateHashMap.get(name + "/" + nArgs)).getSource();
} catch (NullPointerException e) {
return null;
}
}
Library getLibraryFunctor(String name, int nArgs) {
try {
return (Library) ((PrimitiveInfo) functorHashMap.get(name + "/" + nArgs)).getSource();
} catch (NullPointerException e) {
return null;
}
}
}