package models.algebra; import java.util.List; public class Symbol { protected String name; protected String implName; protected int arity = 0; // -1: variable number protected Type operatorType = Type.PREFIX; protected Type implOperatorType = Type.PREFIX; protected Symbol[] inverses = null; protected models.algebra.Type[] signature = null; protected int[] implParamOrder = null; protected IImplGenerator generator = null; protected ICalculator calculator = null; public Symbol(String name) { this.name = name; this.implName = name; this.arity = 0; } public Symbol(String name, int arity) { this.name = name; this.implName = name; this.arity = arity; } public Symbol(String name, int arity, Type operatorType) { this(name, arity); this.operatorType = operatorType; this.implOperatorType = operatorType; } public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType) { this.name = name; this.implName = implName; this.arity = arity; this.operatorType = operatorType; this.implOperatorType = implOperatorType; } public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, int[] implParamOrder) { this.name = name; this.implName = implName; this.arity = arity; this.operatorType = operatorType; this.implOperatorType = implOperatorType; this.implParamOrder = implParamOrder; } public Symbol(String name, int arity, Type operatorType, IImplGenerator generator) { this.name = name; this.implName = name; this.arity = arity; this.operatorType = operatorType; this.generator = generator; this.implOperatorType = Type.GENERATIVE; } public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, boolean bSideEffect) { this.name = name; this.implName = name; this.arity = arity; this.operatorType = operatorType; this.generator = generator; if (!bSideEffect) { this.implOperatorType = Type.GENERATIVE; } else { this.implOperatorType = Type.GENERATIVE_WITH_SIDE_EFFECT; } } public Symbol(String name, int arity, ICalculator calculator) { this.name = name; this.implName = name; this.arity = arity; this.calculator = calculator; } public Symbol(String name, int arity, Type operatorType, ICalculator calculator) { this.name = name; this.implName = name; this.arity = arity; this.operatorType = operatorType; this.implOperatorType = operatorType; this.calculator = calculator; } public Symbol(String name, int arity, Type operatorType, IImplGenerator generator, ICalculator calculator) { this.name = name; this.implName = name; this.arity = arity; this.operatorType = operatorType; this.generator = generator; this.implOperatorType = Type.GENERATIVE; this.calculator = calculator; } public Symbol(String name, int arity, Type operatorType, String implName, Type implOperatorType, ICalculator calculator) { this.name = name; this.implName = implName; this.arity = arity; this.operatorType = operatorType; this.implOperatorType = implOperatorType; this.calculator = calculator; } public void setArity(int arity) { this.arity = arity; } public int getArity() { return arity; } public String getName() { return 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 implName; } public void setImplName(String implName) { this.implName = implName; } public Type getImplOperatorType() { return implOperatorType; } public boolean isImplInfix() { return (implOperatorType == Type.INFIX); } public boolean isImplMethod() { return (implOperatorType == Type.METHOD || implOperatorType == Type.METHOD_WITH_SIDE_EFFECT); } public boolean isImplLambda() { return (implOperatorType == Type.LAMBDA || implOperatorType == Type.LAMBDA_WITH_SIDE_EFFECT); } public boolean isImplGenerative() { return (implOperatorType == Type.GENERATIVE || implOperatorType == Type.GENERATIVE_WITH_SIDE_EFFECT); } public boolean isImplWithSideEffect() { return (implOperatorType == Type.METHOD_WITH_SIDE_EFFECT || implOperatorType == Type.LAMBDA_WITH_SIDE_EFFECT || implOperatorType == Type.GENERATIVE_WITH_SIDE_EFFECT); } public void setImplOperatorType(Type implOperatorType) { this.implOperatorType = implOperatorType; } public int[] getImplParamOrder() { return implParamOrder; } public void setGenerator(IImplGenerator generator) { this.generator = 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 (generator != null) { return generator.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 implName; } public enum Type { PREFIX, INFIX, METHOD, METHOD_WITH_SIDE_EFFECT, LAMBDA, LAMBDA_WITH_SIDE_EFFECT, GENERATIVE, GENERATIVE_WITH_SIDE_EFFECT } public Memento createMemento() { return new Memento(implName, implOperatorType); } public void setMemento(Memento memento) { this.implName = memento.implName; this.implOperatorType = 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); } }