package nars.operator;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import nars.storage.Memory;
import nars.config.Parameters;
import nars.entity.Task;
import nars.io.Symbols;
import nars.language.CompoundTerm;
import nars.language.ImageExt;
import nars.language.Inheritance;
import nars.language.Product;
import nars.language.Term;
import nars.language.Variable;
import nars.operator.misc.Javascript;
/**
* Superclass of functions that execute synchronously (blocking, in thread) and take
* N input parameters and one variable argument (as the final argument), generating a new task
* with the result of the function substituted in the variable's place.
*/
public abstract class SynchronousFunctionOperator extends Operator {
protected SynchronousFunctionOperator(String name) {
super(name);
}
/** y = function(x)
* @return y, or null if unsuccessful
*/
abstract protected Term function(Memory memory, Term[] x);
/** the term that the output will inherit from; analogous to the 'Range' of a function in mathematical terminology */
@Deprecated abstract protected Term getRange();
//abstract protected int getMinArity();
//abstract protected int getMaxArity();
@Override
protected ArrayList<Task> execute(Operation operation, Term[] args, Memory m) {
//TODO make memory access optional by constructor argument
//TODO allow access to NAR instance?
int numArgs = args.length;
if (args[args.length-1].equals(Term.SELF))
numArgs--;
if (numArgs < 1) {
throw new RuntimeException("Requires at least 1 arguments");
}
if (numArgs < 2 && !(this instanceof Javascript)) {
throw new RuntimeException("Requires at least 2 arguments");
}
//last argument a variable?
Term lastTerm = args[numArgs-1];
boolean variable = lastTerm instanceof Variable;
if(!variable && !(this instanceof Javascript)) {
throw new RuntimeException("output can not be specified");
}
int numParam = numArgs-1;
if(this instanceof Javascript && !variable) {
numParam++;
}
Term[] x = new Term[numParam];
System.arraycopy(args, 0, x, 0, numParam);
Term y;
//try {
y = function(m, x);
if (y == null) {
return null;
}
if(!variable && this instanceof Javascript) {
return null;
}
//m.emit(SynchronousFunctionOperator.class, Arrays.toString(x) + " | " + y);
/*}
catch (Exception e) {
throw e;
}*/
Variable var=new Variable("$1");
// Term actual_part = Similarity.make(var, y);
// Variable vardep=new Variable("#1");
//Term actual_dep_part = Similarity.make(vardep, y);
operation=(Operation) operation.setComponent(0,
((CompoundTerm)operation.getSubject()).setComponent(
numArgs-1, y, m), m);
//<3 --> (/,^add,1,2,_,SELF)>.
//transform to image for perception variable introduction rule (is more efficient representation
ImageExt ing=(ImageExt) ImageExt.make((Product)operation.getSubject(),operation.getPredicate(), (short)(numArgs-1));
Inheritance inh=Inheritance.make(y, ing);
Term actual=inh; //Implication.make(operation, actual_part, TemporalRules.ORDER_FORWARD);
float confidence = 0.99f;
if (variable) {
return Lists.newArrayList(
m.newTask(actual, Symbols.JUDGMENT_MARK,
1f, confidence,
Parameters.DEFAULT_JUDGMENT_PRIORITY,
Parameters.DEFAULT_JUDGMENT_DURABILITY, operation.getTask()
));
}
else {
/*float equal = equals(lastTerm, y);
ArrayList<Task> rt = Lists.newArrayList(
m.newTask(actual, Symbols.JUDGMENT_MARK,
1.0f, confidence,
Parameters.DEFAULT_JUDGMENT_PRIORITY,
Parameters.DEFAULT_JUDGMENT_DURABILITY,
operation.getTask()));
if (equal < 1.0f) {
rt.add(m.newTask(operation, Symbols.JUDGMENT_MARK,
equal, confidence,
Parameters.DEFAULT_JUDGMENT_PRIORITY,
Parameters.DEFAULT_JUDGMENT_DURABILITY,
operation.getTask()));
}
return rt;
*/
return null;
}
}
/** (can be overridden in subclasses) the extent to which it is truth
* that the 2 given terms are equal. in other words, a distance metric
*/
public float equals(Term a, Term b) {
//default: Term equality
return a.equals(b) ? 1.0f : 0.0f;
}
}