package models.algebra;
import java.util.List;
import models.algebra.Symbol.IImplGenerator;
import models.algebra.Symbol.Type;
public class Symbol {
protected String name;
protected int arity = 0; // -1: variable number
protected Type operatorType = Type.PREFIX;
protected Symbol[] inverses = null;
protected models.algebra.Type[] signature = null;
protected ICalculator calculator = null;
protected SymbolImpl symbolImpl = null;
public Symbol(String name) {
this.name = name;
this.arity = 0;
this.symbolImpl = new SymbolImpl(name);
}
public Symbol(String name, int arity) {
this.name = name;
this.arity = arity;
this.symbolImpl = new SymbolImpl(name, arity);
}
public Symbol(String name, int arity, Type operatorType) {
this.name = name;
this.arity = arity;
this.operatorType = operatorType;
this.symbolImpl = new SymbolImpl(name, arity, operatorType);
}
public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType) {
this.name = name;
this.arity = arity;
this.operatorType = operatorType;
this.symbolImpl = new SymbolImpl(implName, arity, implOperatorType);
}
public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, int[] implParamOrder) {
this(name, arity, operatorType, implName, implOperatorType);
this.symbolImpl.setImplParamOrder(implParamOrder);
}
public Symbol(String name, int arity, Type operatorType, IImplGenerator generator) {
this(name, arity, operatorType, name, Type.GENERATIVE);
this.symbolImpl.setGenerator(generator);
}
public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, boolean bSideEffect) {
this(name, arity, operatorType, name, Type.GENERATIVE);
this.symbolImpl.setGenerator(generator);
if (bSideEffect) {
this.symbolImpl.setImplOperatorType(Type.GENERATIVE_WITH_SIDE_EFFECT);
}
}
public Symbol(String name, int arity, ICalculator calculator) {
this(name, arity);
this.calculator = calculator;
}
public Symbol(String name, int arity, Type operatorType, ICalculator calculator) {
this(name, arity, operatorType, name, operatorType);
this.calculator = calculator;
}
public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, ICalculator calculator) {
this(name, arity, operatorType, name, Type.GENERATIVE);
this.calculator = calculator;
this.symbolImpl.setGenerator(generator);
}
public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, ICalculator calculator) {
this(name, arity, operatorType, implName, implOperatorType);
this.calculator = calculator;
}
public void setArity(int arity) {
this.arity = arity;
}
public int getArity() {
return arity;
}
public String getName() {
return name;
}
public void changeName(String name) {
this.name = name;
this.symbolImpl.setImplName(name);
}
public Type getOperatorType() {
return operatorType;
}
public boolean isInfix() {
return (operatorType == Type.INFIX);
}
public boolean isMethod() {
return (operatorType == Type.METHOD || operatorType == Type.METHOD_WITH_SIDE_EFFECT);
}
public boolean isLambda() {
return (operatorType == Type.LAMBDA);
}
public Symbol[] getInverses() {
return inverses;
}
public void setInverses(Symbol[] inverses) {
this.inverses = inverses;
}
public models.algebra.Type[] getSignature() {
return signature;
}
public void setSignature(models.algebra.Type[] signature) {
this.signature = signature;
}
public String getImplName() {
return symbolImpl.getImplName();
}
public void setImplName(String implName) {
this.symbolImpl.setImplName(implName);
}
public Type getImplOperatorType() {
return symbolImpl.getImplOperatorType();
}
public boolean isImplInfix() {
return (symbolImpl.getImplOperatorType() == Type.INFIX);
}
public boolean isImplMethod() {
return (symbolImpl.getImplOperatorType() == Type.METHOD || symbolImpl.getImplOperatorType() == Type.METHOD_WITH_SIDE_EFFECT);
}
public boolean isImplLambda() {
return (symbolImpl.getImplOperatorType() == Type.LAMBDA || symbolImpl.getImplOperatorType() == Type.LAMBDA_WITH_SIDE_EFFECT);
}
public boolean isImplGenerative() {
return (symbolImpl.getImplOperatorType() == Type.GENERATIVE || symbolImpl.getImplOperatorType() == Type.GENERATIVE_WITH_SIDE_EFFECT);
}
public boolean isImplWithSideEffect() {
return (symbolImpl.getImplOperatorType() == Type.METHOD_WITH_SIDE_EFFECT
|| symbolImpl.getImplOperatorType() == Type.LAMBDA_WITH_SIDE_EFFECT
|| symbolImpl.getImplOperatorType() == Type.GENERATIVE_WITH_SIDE_EFFECT);
}
public void setImplOperatorType(Type implOperatorType) {
this.symbolImpl.setImplOperatorType(implOperatorType);
}
public int[] getImplParamOrder() {
return symbolImpl.getImplParamOrder();
}
public void setGenerator(IImplGenerator generator) {
this.symbolImpl.setGenerator(generator);
}
/**
* Generate the implementation of this symbol
* @param type the type of this symbol
* @param childrenTypes
* @param childrenImpl the implementations of the children
* @param childrenSideEffects (input) an array of the side effects of the children
* @param sideEffect (output) an array of the side effect of this symbol
* @return the implementation
*/
public String generate(models.algebra.Type type, models.algebra.Type[] childrenTypes, String[] childrenImpl, String[] childrenSideEffects, String[] sideEffect) {
if (symbolImpl.getGenerator() != null) {
return symbolImpl.getGenerator().generate(type, childrenTypes, childrenImpl, childrenSideEffects, sideEffect);
}
return null;
}
public boolean isCalculatable() {
return (calculator != null);
}
public Expression calculate(List<Expression> args) {
if (calculator != null) {
return calculator.calculate(args);
}
return null;
}
public boolean equals(Object another) {
if (!(another instanceof Symbol)) return false;
return name.equals(((Symbol) another).name) && arity == ((Symbol) another).arity;
}
@Override
public int hashCode() {
return name.hashCode();
}
public String toString() {
return name;
}
public String toImplementation() {
return symbolImpl.getImplName();
}
public enum Type {
PREFIX,
INFIX,
METHOD,
METHOD_WITH_SIDE_EFFECT,
LAMBDA,
LAMBDA_WITH_SIDE_EFFECT,
GENERATIVE,
GENERATIVE_WITH_SIDE_EFFECT
}
public static class SymbolImpl {
private String implName;
protected int implArity = 0; // -1: variable number
private Type implOperatorType;
private int[] implParamOrder;
private IImplGenerator generator;
public SymbolImpl(String implName) {
this.implName = implName;
this.implArity = 0;
}
public SymbolImpl(String implName, int implArity) {
this.implName = implName;
this.implArity = implArity;
}
public SymbolImpl(String implName, int implArity, Type implOperatorType) {
this(implName, implArity);
this.implOperatorType = implOperatorType;
}
public SymbolImpl(String implName, int implArity, Type implOperatorType, int[] implParamOrder) {
this(implName, implArity, implOperatorType);
this.implParamOrder = implParamOrder;
}
public SymbolImpl(String implName, int implArity, Type implOperatorType, int[] implParamOrder, IImplGenerator generator) {
this(implName, implArity, implOperatorType, implParamOrder);
this.generator = generator;
}
public String getImplName() {
return implName;
}
public void setImplName(String implName) {
this.implName = implName;
}
public Type getImplOperatorType() {
return implOperatorType;
}
public void setImplOperatorType(Type implOperatorType) {
this.implOperatorType = implOperatorType;
}
public int[] getImplParamOrder() {
return implParamOrder;
}
public void setImplParamOrder(int[] implParamOrder) {
this.implParamOrder = implParamOrder;
}
public IImplGenerator getGenerator() {
return generator;
}
public void setGenerator(IImplGenerator generator) {
this.generator = generator;
}
}
public Memento createMemento() {
return new Memento(symbolImpl.getImplName(), symbolImpl.getImplOperatorType());
}
public void setMemento(Memento memento) {
this.symbolImpl.setImplName(memento.implName);
this.symbolImpl.setImplOperatorType(memento.implOperatorType);
}
public static class Memento {
private String implName;
private Type implOperatorType = Type.PREFIX;
public Memento(String implName, Type implOperatorType) {
this.implName = implName;
this.implOperatorType = implOperatorType;
}
}
public interface IImplGenerator {
/**
* Generate the implementation
* @param type the type of this expression
* @param childrenTypes
* @param children the implementations of the children
* @param childrenSideEffects (input) an array of the side effects of the children
* @param sideEffect (output) an array of the side effect of this generator
* @return the generated implementation
*/
public String generate(models.algebra.Type type, models.algebra.Type[] childrenTypes, String children[], String[] childrenSideEffects, String[] sideEffect);
}
public interface ICalculator {
public Expression calculate(List<Expression> args);
}
}