package org.jactr.core.module.procedural.six.learning;
/*
* default logging
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javolution.util.FastList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.buffer.IActivationBuffer;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunktype.IChunkType;
import org.jactr.core.module.procedural.IProceduralModule;
import org.jactr.core.module.procedural.five.learning.ICompilableBuffer;
import org.jactr.core.module.procedural.five.learning.IProductionCompiler;
import org.jactr.core.production.IInstantiation;
import org.jactr.core.production.IProduction;
import org.jactr.core.production.VariableBindings;
import org.jactr.core.production.action.AddAction;
import org.jactr.core.production.action.IAction;
import org.jactr.core.production.action.IBufferAction;
import org.jactr.core.production.action.ModifyAction;
import org.jactr.core.production.action.OutputAction;
import org.jactr.core.production.action.RemoveAction;
import org.jactr.core.production.action.SetAction;
import org.jactr.core.production.condition.ChunkTypeCondition;
import org.jactr.core.production.condition.IBufferCondition;
import org.jactr.core.production.condition.ICondition;
import org.jactr.core.production.condition.QueryCondition;
import org.jactr.core.production.condition.VariableCondition;
import org.jactr.core.production.request.ChunkRequest;
import org.jactr.core.production.request.ChunkTypeRequest;
import org.jactr.core.production.request.IRequest;
import org.jactr.core.production.request.SlotBasedRequest;
import org.jactr.core.slot.BasicSlot;
import org.jactr.core.slot.DefaultMutableSlot;
import org.jactr.core.slot.IMutableSlot;
import org.jactr.core.slot.IMutableVariableNameSlot;
import org.jactr.core.slot.ISlot;
import org.jactr.core.slot.ISlotContainer;
public class DefaultProductionCompiler6 implements IProductionCompiler
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(DefaultProductionCompiler6.class);
private IInstantiation _lastInstantiation;
//private ICodeGenerator _codeGenerator = new JACTRCodeGenerator();
private ProductionCompilerEvaluator evaluator;
FastList<ISlot> __slotList = new FastList<ISlot>(); // for fast iterating through slot lists
public DefaultProductionCompiler6() {
evaluator = new ProductionCompilerEvaluator();
}
public IProduction productionFired(IInstantiation instantiation,
IProceduralModule proceduralModule)
{
LOGGER.debug("Got that production " + instantiation + " fired; last fired was " + _lastInstantiation);
IProduction compiled = null;
Map<ICompilableBuffer, BufferStruct> compilationMapOne = new HashMap<ICompilableBuffer, BufferStruct>();
Map<ICompilableBuffer, BufferStruct> compilationMapTwo = new HashMap<ICompilableBuffer, BufferStruct>();
try {
if (_lastInstantiation != null && canCompile(_lastInstantiation, instantiation, compilationMapOne, compilationMapTwo))
{
compiled = doCompilation(_lastInstantiation, instantiation, compilationMapOne, compilationMapTwo);
if(compiled != null) {
LOGGER.info("Compiled ");
LOGGER.info(_lastInstantiation.getSymbolicProduction().getName() + ":");
for(ICondition condition : _lastInstantiation.getSymbolicProduction().getConditions())
LOGGER.info(condition.toString());
LOGGER.info("===>");
for(IAction action : _lastInstantiation.getSymbolicProduction().getActions())
LOGGER.info(action.toString());
//for (StringBuilder line : _codeGenerator.generate(ASTResolver.toAST(_lastInstantiation.getProduction()), false))
// {
// LOGGER.info(line.toString());
// line.delete(0, line.length());
// }
//for (BufferStruct s : compilationMapOne.values()) {
// LOGGER.info(s.bufferName + ": " + s.bindingsToString());
//}
LOGGER.info(" and ");
LOGGER.info(instantiation.getSymbolicProduction().getName() + ":");
for(ICondition condition : instantiation.getSymbolicProduction().getConditions())
LOGGER.info(condition.toString());
LOGGER.info("===>");
for(IAction action : instantiation.getSymbolicProduction().getActions())
LOGGER.info(action.toString());
// for (StringBuilder line : _codeGenerator.generate(ASTResolver.toAST(instantiation.getProduction()), false))
// {
// LOGGER.info(line.toString());
// line.delete(0, line.length());
// }
// for (BufferStruct s : compilationMapTwo.values()) {
// LOGGER.info(s.bufferName + ": " + s.bindingsToString());
// }
LOGGER.info(" into ");
LOGGER.info(compiled.getSymbolicProduction().getName() + ":");
for(ICondition condition : compiled.getSymbolicProduction().getConditions())
LOGGER.info(condition.toString());
LOGGER.info("===>");
for(IAction action : compiled.getSymbolicProduction().getActions())
LOGGER.info(action.toString());
// for (StringBuilder line : _codeGenerator.generate(ASTResolver.toAST(compiled), false))
// {
// LOGGER.info(line.toString());
// line.delete(0, line.length());
// }
}
}
} catch (Exception e) {
LOGGER.warn("got an exception: ", e);
}
_lastInstantiation = instantiation;
return compiled; // for now, for testing
}
protected boolean canCompile(IInstantiation instantiationOne, IInstantiation instantiationTwo, Map<ICompilableBuffer, BufferStruct> compilationMapOne, Map<ICompilableBuffer, BufferStruct> compilationMapTwo) {
HashSet<ICompilableBuffer> buffers = new HashSet<ICompilableBuffer>();
//check individually; return false if buffers involved aren't ICompilableBuffers
if(!(checkBuffers(instantiationOne, compilationMapOne) && checkBuffers(instantiationTwo, compilationMapTwo))) return false;
//LOGGER.debug("Checking to see whether productions can be compiled (via Evaluators)...");
//now check the maps
buffers.addAll(compilationMapOne.keySet());
buffers.addAll(compilationMapTwo.keySet());
for(ICompilableBuffer buffer : buffers) {
if(compilationMapOne.get(buffer) == null) {
compilationMapOne.put(buffer, new BufferStruct(buffer.getName(), buffer.isStrictHarvestingEnabled(), instantiationOne.getVariableBindings()));
}
if(compilationMapTwo.get(buffer) == null) {
compilationMapTwo.put(buffer, new BufferStruct(buffer.getName(), buffer.isStrictHarvestingEnabled(), instantiationTwo.getVariableBindings()));
}
if(!evaluator.canCompile(compilationMapOne.get(buffer), compilationMapTwo.get(buffer), buffer)) {
LOGGER.info("Cannot compile because not the right conditions/actions for buffer " + buffer);
return false;
}
}
//LOGGER.debug("can compile!");
return true;
}
protected IProduction doCompilation(IInstantiation instantiationOne, IInstantiation instantiationTwo, Map<ICompilableBuffer, BufferStruct> compilationMapOne, Map<ICompilableBuffer, BufferStruct> compilationMapTwo)
throws InterruptedException, ExecutionException {
ArrayList<ICondition> tempTwoConditions = new ArrayList<ICondition>();
ArrayList<IAction> tempTwoActions = new ArrayList<IAction>();
//FIRST: Unification
//Step 1: rename duplicate variables
HashMap<String, Object> mapping = findDuplicateVariableMapping(compilationMapOne, compilationMapTwo);
if(mapping == null) return null;
if(!renameVariables(compilationMapTwo, mapping)) return null;
//Step 2: do buffer mappings
HashMap<ICompilableBuffer, Map<String, Object> > bufferMappings = new HashMap<ICompilableBuffer, Map<String, Object> >();
if(!extractBufferMappings(bufferMappings, compilationMapOne, compilationMapTwo, instantiationOne, tempTwoConditions, tempTwoActions)) return null;
//Step 3: Merge Mappings
Map<String, Object> mergedMapping = mergeBufferMappings(bufferMappings);
if(mergedMapping == null) return null;
//SECOND: Substitution - just reuse earlier code.
if(!renameVariables(compilationMapOne, mergedMapping)) return null;
if(!renameVariables(compilationMapTwo, mergedMapping)) return null;
//THIRD: Collapsing
IProduction p = collapseProductions(compilationMapOne, compilationMapTwo, instantiationOne.getModel().getProceduralModule().createProduction(instantiationOne.getSymbolicProduction().getName() + "-" + instantiationTwo.getSymbolicProduction().getName()).get());
if(p == null) return null;
return bindFreeVariables(p, compilationMapTwo, instantiationTwo);
}
private IProduction bindFreeVariables(IProduction p, Map<ICompilableBuffer, BufferStruct> compilationMapTwo, IInstantiation instantiation) {
HashSet<String> boundVariables = new HashSet<String>();
//LOGGER.debug("production is " + p);
if(!getConditionVariables(p.getSymbolicProduction().getConditions(), boundVariables)) return null;
for (IAction action : p.getSymbolicProduction().getActions()) {
if(action instanceof AddAction && ((AddAction)action).getChunkName() != null) {
if(!boundVariables.contains(((AddAction)action).getChunkName())) {
LOGGER.warn("Should never be here where AddAction's chunk name isn't resolved " + action);
return null;
}
} else if(action instanceof ISlotContainer) {
__slotList.clear();
for(ISlot s : ((ISlotContainer) action).getSlots(__slotList)) {
if(s.getName().startsWith("=") && !boundVariables.contains(s.getName())) {
LOGGER.warn("Variable name in condition slot name... we don't currently handle this. " + s);
return null;
}
if(s.getValue().toString().startsWith("=") && !boundVariables.contains(s.getValue().toString())) {
// LOGGER.debug("found an unbound variable..." + s);
//get value from second instantiation
((ISlotContainer)action).removeSlot(s);
IMutableSlot newSlot = ((DefaultMutableSlot)s).clone();
newSlot.setValue(compilationMapTwo.get(instantiation.getModel().getActivationBuffer(((IBufferAction)action).getBufferName())).bindings.get(s.getValue().toString()));
((ISlotContainer)action).addSlot(newSlot);
}
}
} //ignoring here Add production chunk name variables
}
return p;
}
private IProduction collapseProductions(Map<ICompilableBuffer, BufferStruct> compilationMapOne, Map<ICompilableBuffer, BufferStruct> compilationMapTwo, IProduction newProduction) {
HashSet<ICompilableBuffer> buffers = new HashSet<ICompilableBuffer>();
buffers.addAll(compilationMapOne.keySet());
buffers.addAll(compilationMapTwo.keySet());
BufferStruct result;
for(ICompilableBuffer buffer : buffers) {
result = evaluator.collapseBuffer(compilationMapOne.get(buffer), compilationMapTwo.get(buffer), buffer);
if(result == null) {
LOGGER.info("Couldn't compile productions for " + buffer + " so stopping compilation process. If your Evaluator/Mapper/Collapser tables were consistent, and all your Collapser functions were being called correctly, you probably wouldn't be here.");
return null;
}
else {
for(ICondition condition : result.conditions)
newProduction.getSymbolicProduction().addCondition(condition);
for(IAction action : result.actions) {
//if(action instanceof ISlotContainer) LOGGER.debug("adding action " + action + ((ISlotContainer)action).getSlots());
newProduction.getSymbolicProduction().addAction(action);
}
}
}
return newProduction;
}
private Map<String, Object> mergeBufferMappings(Map<ICompilableBuffer, Map<String, Object> > bufferMappings) {
Map<String, Object> mergedMappings = new HashMap<String, Object>();
for(Map<String, Object> bufferMap : bufferMappings.values()) {
for(String s : bufferMap.keySet()) {
if(mergedMappings.containsKey(s)) {
LOGGER.debug("merged mappings contains " + s);
Object val1 = mergedMappings.get(s);
Object val2 = bufferMap.get(s);
if(val1.equals(val2)) {
//they are the same; just move on.
continue;
} else if(val1.toString().startsWith("=")) {
if(val2.toString().startsWith("=")) {
LOGGER.warn("can't merge mappings because " + s + " maps to both " + val1 + " and " + val2);
return null;
} else {
//val1 is a variable and val2 is a value; update s entry so that these can be applied in any order.
mergedMappings.put(s, val2);
mergedMappings.put(val1.toString(), val2);
}
} else if(val2.toString().startsWith("=")) {
//val1 is a value and val2 is a variable
mergedMappings.put(val2.toString(), val1);
} else {
LOGGER.warn("can't merge mappings because " + s + " maps to both " + val1 + " and " + val2);
return null;
}
} else {
mergedMappings.put(s, bufferMap.get(s));
}
}
}
return mergedMappings;
}
private boolean extractBufferMappings(HashMap<ICompilableBuffer, Map<String, Object> > bufferMappings, Map<ICompilableBuffer, BufferStruct> compilationMapOne, Map<ICompilableBuffer, BufferStruct> compilationMapTwo, IInstantiation instantiationOne, ArrayList<ICondition> tempTwoConditions, ArrayList<IAction> tempTwoActions) {
HashSet<ICompilableBuffer> buffers = new HashSet<ICompilableBuffer>();
buffers.addAll(compilationMapOne.keySet());
buffers.addAll(compilationMapTwo.keySet());
for(ICompilableBuffer buffer : buffers) {
Map<String, Object> bufferMap = evaluator.extractMap(compilationMapOne.get(buffer), compilationMapTwo.get(buffer), buffer);
if(bufferMap == null) {
LOGGER.info("Couldn't extract buffer mappings for " + buffer + " so stopping compilation process. If your Evaluator/Mapper tables were consistent, and all your Mapper functions were being called correctly, you probably wouldn't be here.");
return false;
} else {
LOGGER.debug("got buffer mappings: " + bufferMap);
bufferMappings.put(buffer, bufferMap);
}
}
return true;
}
private boolean getConditionVariables(Collection<ICondition> conditions, HashSet<String> variables) {
for (ICondition condition : conditions) {
if(condition instanceof ChunkTypeCondition) {
for(ISlot s : ((ChunkTypeCondition) condition).getSlots(__slotList)) {
//LOGGER.debug("checking slot " + s + " while getting condition variables.");
if(s.getName().startsWith("=")) {
//oneVariables.add(s.getName()); //ALTHOUGH this should NEVER be the case...
LOGGER.warn("Variable name in condition slot name... we don't currently handle this. " + s);
return false;
}
if(s.getValue() != null && s.getValue().toString().startsWith("=")) variables.add(s.getValue().toString());
}
} else if(condition instanceof VariableCondition) { //here even though we don't handle this yet
variables.add(((VariableCondition)condition).getVariableName());
} //else - no variables. most likely.... hopefully.
}
return true;
}
//find variables that are in both production one and production 2; provide mapping for renaming variables in p2
//Hash second param is an object for compatibility with renameVariables.
private HashMap<String, Object> findDuplicateVariableMapping(Map<ICompilableBuffer, BufferStruct> compilationMapOne, Map<ICompilableBuffer, BufferStruct> compilationMapTwo) {
//Assumes (correctly?) that all variables are initially "declared" in the conditions
HashSet<String> oneVariables = new HashSet<String>();
HashSet<String> twoVariables = new HashSet<String>();
for(BufferStruct struct : compilationMapOne.values()) {
if(!getConditionVariables(struct.conditions, oneVariables)) return null;
}
for(BufferStruct struct : compilationMapTwo.values()) {
if(!getConditionVariables(struct.conditions, twoVariables)) return null;
}
//LOGGER.debug("variables one are " + oneVariables + " and two are " + twoVariables);
//Now find duplicates and rename them in production 2
HashSet<String> commonVariables = new HashSet<String>();
commonVariables.addAll(oneVariables);
commonVariables.retainAll(twoVariables);
//LOGGER.debug("common variables are " + commonVariables);
HashMap<String, Object> mapping = new HashMap<String, Object>();
String newS;
for(String s : commonVariables) {
newS = s + "-0";
while(oneVariables.contains(newS) || twoVariables.contains(newS))
newS = newS + "-0";
mapping.put(s, newS);
}
return mapping;
}
/**
*
* @param compilationMap - map of the production whose variables should be renamed
* @param mapping - mapping of old->new variable names
* @return
*/
private boolean renameVariables(Map<ICompilableBuffer, BufferStruct> compilationMap, Map<String, Object> mapping) {
if(mapping.size() > 0) {
ArrayList<ICondition> newConds = new ArrayList<ICondition>();
ArrayList<IAction> newActs = new ArrayList<IAction>();
String name;
Object value;
for(BufferStruct struct : compilationMap.values()) {
newConds.clear();
newActs.clear();
ArrayList<ISlot> newSlots = new ArrayList<ISlot>();
//First do in conditions
for (ICondition condition : struct.conditions) {
newSlots.clear();
if(condition instanceof ChunkTypeCondition) {
__slotList.clear();
for(ISlot s : ((ChunkTypeCondition) condition).getSlots(__slotList)) {
if(mapping.containsKey(s.getName())) {
//name = mapping.get(s.getName()); //Should NEVER be the case for conditions.
LOGGER.warn("Variable name in condition slot name... we don't handle this. " + s);
return false;
} else name = s.getName();
if(mapping.containsKey(s.getValue())) value = mapping.get(s.getValue());
else value = s.getValue();
//don't handle the first case for conditions.
//if(s instanceof IMutableVariableNameSlot && s instanceof IMutableSlot && s instanceof BasicSlot) {
// IMutableVariableNameSlot newSlot = (IMutableVariableNameSlot) ((BasicSlot)s).clone();
// newSlot.setName(name);
// ((IMutableSlot)newSlot).setValue(value);
// newSlots.add(newSlot);
//} else
if (s instanceof IMutableSlot && s instanceof BasicSlot) {
IMutableSlot newSlot = (IMutableSlot) ((BasicSlot)s).clone();
newSlot.setValue(value);
newSlots.add(newSlot);
} else {
LOGGER.warn("Slot " + s + " is not the type expected (IMutableSlot and BasicSlot), but is " + s.getClass());
return false;
}
}
newConds.add(new ChunkTypeCondition(struct.bufferName, ((ChunkTypeCondition)condition).getChunkType(), newSlots));
} else if(condition instanceof VariableCondition) {
if(mapping.containsKey(((VariableCondition)condition).getVariableName())) {
if(mapping.get(((VariableCondition)condition).getVariableName()) instanceof String) {
newConds.add(new VariableCondition(struct.bufferName, (String) mapping.get(((VariableCondition)condition).getVariableName())));
} else {
LOGGER.warn("Can't map a variable condition variable name to a non-string object: " + condition);
return false;
}
} else newConds.add(new VariableCondition(struct.bufferName, ((VariableCondition)condition).getVariableName()));
} else newConds.add(condition); //else - no variables. most likely.... hopefully.
}
struct.conditions.clear();
struct.conditions.addAll(newConds);
//Now do for actions
for (IAction action : struct.actions){
newSlots.clear();
if((action instanceof ModifyAction && !(action instanceof RemoveAction)) ||
(action instanceof AddAction)) {
__slotList.clear();
for(ISlot s : ((org.jactr.core.slot.ISlotContainer) action).getSlots(__slotList)) {
if(mapping.containsKey(s.getName())) {
if(mapping.get(s.getName()).toString().startsWith("=")) {
//name = (String) mapping.get(s.getName());
LOGGER.warn("Variable name in action slot name... we don't currently handle this. " + s);
return false;
} else {
LOGGER.warn("Can't map a slot name to a non-string object (and don't currently handle string object anyway): " + s);
return false;
}
}
else name = s.getName();
if(mapping.containsKey(s.getValue())) value = mapping.get(s.getValue());
else value = s.getValue();
if(s instanceof IMutableVariableNameSlot && s instanceof IMutableSlot && s instanceof BasicSlot) {
IMutableVariableNameSlot newSlot = (IMutableVariableNameSlot) ((BasicSlot)s).clone();
newSlot.setName(name);
((IMutableSlot)newSlot).setValue(value);
newSlots.add(newSlot);
} else if (s instanceof IMutableSlot && s instanceof BasicSlot) {
IMutableSlot newSlot = (IMutableSlot) ((BasicSlot)s).clone();
newSlot.setValue(value);
newSlots.add(newSlot);
} else {
LOGGER.warn("Slot " + s + " is not the type expected (IMutableSlot and BasicSlot), but is " + s.getClass());
return false;
}
}
if(action instanceof ModifyAction) newActs.add(new ModifyAction(struct.bufferName, newSlots));
else newActs.add(new AddAction(struct.bufferName, ((AddAction)action).getReferant(), newSlots));
} else {
//nothing to do for the others; Remove doesn't refer to anything and Set is excluded from compilation
newActs.add(action);
}
}
struct.actions.clear();
struct.actions.addAll(newActs);
//LOGGER.debug("updating bindings " + struct.bindings + " with " + mapping);
//Now do for variable bindings
Collection<String> vars = new ArrayList<String>();
vars.addAll(struct.bindings.getVariables());
for(String s : vars) {
if(mapping.containsKey(s)) {
if(mapping.get(s).toString().startsWith("=")) {
struct.bindings.bind(mapping.get(s).toString(), struct.bindings.get(s), struct.bindings.getSource(s));
} else {
//otherwise, might be a different value so update. doesn't really matter though since we're getting rid of this variable anyway.
struct.bindings.bind(s, mapping.get(s));
}
}
}
}
}
return true;
}
protected boolean checkBuffers(IInstantiation instantiation, Map<ICompilableBuffer, BufferStruct> compilationMap)
{
for (ICondition condition : instantiation.getProduction().getSymbolicProduction().getConditions()) {
if (condition instanceof IBufferCondition) {
IActivationBuffer buffer = instantiation.getModel().getActivationBuffer((((IBufferCondition) condition).getBufferName()));
if(!(buffer instanceof ICompilableBuffer) || ((ICompilableBuffer) buffer).getCompilableContext() == null) {
LOGGER.debug("returning false because condition " + condition + " has a non-compilable buffer " + buffer);
return false; //definitely can't compile
}
ICompilableBuffer cBuffer = (ICompilableBuffer) buffer;
if(!compilationMap.containsKey(cBuffer)) {
compilationMap.put(cBuffer, new BufferStruct(cBuffer.getName(), buffer.isStrictHarvestingEnabled(), instantiation.getVariableBindings()));
}
if (condition instanceof QueryCondition) compilationMap.put(cBuffer, compilationMap.get(cBuffer).update(ProductionCompilerEvaluator.query, condition));
else if (condition instanceof ChunkTypeCondition) compilationMap.put(cBuffer, compilationMap.get(cBuffer).update(ProductionCompilerEvaluator.match, condition));
else {
LOGGER.debug("returning false because don't currently handle conditions like " + condition);
return false;
}
} else {
LOGGER.debug("returning false because condition " + condition + " is not a buffer condition");
return false;
}
}
for (IAction action : instantiation.getProduction().getSymbolicProduction().getActions()) {
if (action instanceof IBufferAction) {
IActivationBuffer buffer = instantiation.getModel().getActivationBuffer((((IBufferAction) action).getBufferName()));
if(!(buffer instanceof ICompilableBuffer)) {
LOGGER.debug("returning false because action " + action + " has a non-compilable buffer " + buffer);
return false; //definitely can't compile
}
ICompilableBuffer cBuffer = (ICompilableBuffer) buffer;
if(!compilationMap.containsKey(cBuffer)) {
compilationMap.put(cBuffer, new BufferStruct(cBuffer.getName(), buffer.isStrictHarvestingEnabled(), instantiation.getVariableBindings()));
}
if (action instanceof RemoveAction) compilationMap.put(cBuffer, compilationMap.get(cBuffer).update(ProductionCompilerEvaluator.remove, action));
else if (action instanceof ModifyAction) compilationMap.put(cBuffer, compilationMap.get(cBuffer).update(ProductionCompilerEvaluator.modify, action));
else if (action instanceof AddAction && ((AddAction)action).getReferant() instanceof IChunkType) compilationMap.put(cBuffer, compilationMap.get(cBuffer).update(ProductionCompilerEvaluator.add, action));
else if (action instanceof SetAction) {
LOGGER.debug("returning false because not allowing set action" + action);
return false;
} else {
LOGGER.debug("returning false because don't currently handle actions like " + action);
return false;
}
} else if (action instanceof OutputAction) {
LOGGER.debug("found OutputAction, ignoring it for production compilation.");
} else {
LOGGER.debug("returning false because action " + action + " is not a buffer action");
return false;
}
}
return true;
}
/* private static Integer empty = 0;
private static Integer match = 8;
private static Integer query = 16;
private static Integer modify = 1;
private static Integer add = 4;
private static Integer remove = 2;
*/
/** helper struct to organize buffer-dependent knowledge **/
public static class BufferStruct
{
public Integer index; //hash of what types of actions/conditions this buffer has
public Collection<ICondition> conditions;
public Collection<IAction> actions;
public String bufferName; //just for good measure
public boolean strict_harvesting;
public VariableBindings bindings = null;
public BufferStruct(String name, Integer i, boolean sh, Collection<ICondition> conds, Collection<IAction> acts, VariableBindings vb) {
bufferName = name;
index = i;
conditions = conds;
actions = acts;
strict_harvesting = sh;
bindings = vb;
}
public BufferStruct(String name, boolean sh, VariableBindings vb) {
bufferName = name;
strict_harvesting = sh;
index = ProductionCompilerEvaluator.empty;
conditions = new ArrayList<ICondition>();
actions = new ArrayList<IAction>();
bindings = vb;
}
public BufferStruct update(int i, ICondition c) {
index = index + i;
conditions.add(c);
return this;
}
public BufferStruct update(int i, IAction a) {
index = index + i;
actions.add(a);
return this;
}
public String getName() {
return bufferName;
}
public Collection<ICondition> getConditions() {
return conditions;
}
public Collection<IAction> getActions() {
return actions;
}
public boolean hasStrictHarvesting() {
return strict_harvesting;
}
public VariableBindings getVariableBindings() {
return bindings;
}
public String bindingsToString() {
String result = "[";
for(String s : bindings.getVariables()) {
result += s + "," + bindings.get(s) + ";";
}
result += "]";
return result;
}
public IRequest getIRequest() {
for(IAction a : actions) {
if (a instanceof AddAction) {
//copied from AddAction
IRequest request = null;
Object referant = ((AddAction)a).getReferant();
if (referant instanceof IRequest)
request = (IRequest) referant;
else if (referant instanceof IChunk)
/*
* +buffer> chunk (or =chunk)
*/
request = new ChunkRequest((IChunk) referant, ((AddAction)a).getSlots());
else if (referant instanceof IChunkType) /*
* +buffer> isa chunk
*/
request = new ChunkTypeRequest((IChunkType) referant, ((AddAction)a).getSlots());
else
/*
* +buffer> slot value
*/
request = new SlotBasedRequest(((AddAction)a).getSlots());
return request;
}
}
return null;
}
}
}