package models.dataConstraintModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import models.algebra.Symbol;
import models.algebra.Type;
import parser.Parser;
public class DataConstraintModel {
protected HashMap<String, IdentifierTemplate> identifierTemplates = null;
protected HashMap<String, ChannelGenerator> channelGenerators = null;
protected HashMap<String, ChannelGenerator> ioChannelGenerators = null;
protected HashMap<String, Type> types = null;
protected HashMap<String, Symbol> symbols = null;
public static final Type typeInt = new Type("Int", "int");
public static final Type typeLong = new Type("Long", "long");
public static final Type typeFloat = new Type("Float", "float");
public static final Type typeDouble = new Type("Double", "double");
public static final Type typeBoolean = new Type("Bool", "boolean");
public static final Type typeString = new Type("Str", "String");
public static final Type typeList = new Type("List", "ArrayList", "List");
public static final Type typeListInt = new Type("List", "ArrayList<>", "List<Integer>", typeList);
public static final Type typeListStr = new Type("List", "ArrayList<>", "List<String>", typeList);
public static final Type typeTuple = new Type("Tuple", "AbstractMap.SimpleEntry", "Map.Entry");
public static final Symbol add = new Symbol(Parser.ADD, 2, Symbol.Type.INFIX);
public static final Symbol mul = new Symbol(Parser.MUL, 2, Symbol.Type.INFIX);;
public static final Symbol sub = new Symbol(Parser.SUB, 2, Symbol.Type.INFIX);
public static final Symbol div = new Symbol(Parser.DIV, 2, Symbol.Type.INFIX);
public static final Symbol minus = new Symbol(Parser.MINUS, 1);
public static final Symbol cons = new Symbol("cons", 2, Symbol.Type.PREFIX, "($x,$y)->$x.add(0, $y)", Symbol.Type.LAMBDA_WITH_SIDE_EFFECT, new int[] {1, 0});
public static final Symbol head = new Symbol("head", 1, Symbol.Type.PREFIX, "($x)->$x.get(0)", Symbol.Type.LAMBDA);
public static final Symbol tail = new Symbol("tail", 1, Symbol.Type.PREFIX, "($x)->$x.subList(1, $x.size())", Symbol.Type.LAMBDA);
public static final Symbol get = new Symbol("get", 2, Symbol.Type.PREFIX, "get", Symbol.Type.METHOD);
public static final Symbol set = new Symbol("set", 3, Symbol.Type.PREFIX, "set", Symbol.Type.METHOD_WITH_SIDE_EFFECT);
public static final Symbol contains = new Symbol("contains", 2, Symbol.Type.PREFIX, "contains", Symbol.Type.METHOD);
public static final Symbol nil = new Symbol("nil", 0, Symbol.Type.PREFIX, new Symbol.IImplGenerator() {
@Override
public String generate(Type type, String[] children, String[] sideEffects) {
String compType = "";
if (type != null) {
String interfaceType = type.getInterfaceTypeName();
if (interfaceType.contains("<")) {
compType = interfaceType.substring(interfaceType.indexOf("<") + 1, interfaceType.lastIndexOf(">"));
}
}
return "new ArrayList<" + compType + ">()";
}
});
public static final Symbol cond = new Symbol("if", 3, Symbol.Type.PREFIX, "($x,$y,$z)->($x ? $y : $z)", Symbol.Type.LAMBDA);
public static final Symbol eq = new Symbol("eq", 2, Symbol.Type.PREFIX, "==", Symbol.Type.INFIX);
public static final Symbol neq = new Symbol("neq", 2, Symbol.Type.PREFIX, "!=", Symbol.Type.INFIX);
public static final Symbol gt = new Symbol("gt", 2, Symbol.Type.PREFIX, ">", Symbol.Type.INFIX);
public static final Symbol lt = new Symbol("lt", 2, Symbol.Type.PREFIX, "<", Symbol.Type.INFIX);
public static final Symbol tuple = new Symbol("tuple", -1, Symbol.Type.PREFIX, new Symbol.IImplGenerator() {
@Override
public String generate(Type type, String[] childrenImpl, String[] sideEffects) {
String impl = "new AbstractMap.SimpleEntry<>(" + childrenImpl[0] + "$x)";
for (int i = 1; i < childrenImpl.length - 1; i++) {
impl = impl.replace("$x", ", new AbstractMap.SimpleEntry<>(" + childrenImpl[i] + "$x)");
}
impl = impl.replace("$x", ", " + childrenImpl[childrenImpl.length - 1]);
return impl;
}
});
public static final Symbol fst = new Symbol("fst", 1, Symbol.Type.PREFIX, "getKey", Symbol.Type.METHOD);
public static final Symbol snd = new Symbol("snd", 1, Symbol.Type.PREFIX, "getValue", Symbol.Type.METHOD);
static {
add.setInverses(new Symbol[] {sub, sub});
mul.setInverses(new Symbol[] {div, div});
sub.setInverses(new Symbol[] {add});
div.setInverses(new Symbol[] {mul});
minus.setInverses(new Symbol[] {minus});
cons.setInverses(new Symbol[] {head, tail});
cons.setSignature(new Type[] {typeList, null, typeList});
contains.setSignature(new Type[] {typeBoolean, typeList, null});
get.setSignature(new Type[] {null, typeList, typeInt});
set.setSignature(new Type[] {typeList, typeList, typeInt, null});
tuple.setSignature(new Type[] {typeTuple, null, null});
tuple.setInverses(new Symbol[] {fst, snd});
fst.setSignature(new Type[] {null, typeTuple});
snd.setSignature(new Type[] {null, typeTuple});
}
public DataConstraintModel() {
identifierTemplates = new HashMap<>();
channelGenerators = new HashMap<>();
ioChannelGenerators = new HashMap<>();
types = new HashMap<>();
addType(typeInt);
addType(typeLong);
addType(typeFloat);
addType(typeDouble);
addType(typeBoolean);
addType(typeString);
addType(typeList);
addType(typeTuple);
symbols = new HashMap<>();
addSymbol(add);
addSymbol(mul);
addSymbol(sub);
addSymbol(div);
addSymbol(minus);
addSymbol(cons);
addSymbol(head);
addSymbol(tail);
addSymbol(contains);
addSymbol(get);
addSymbol(set);
addSymbol(nil);
addSymbol(cond);
addSymbol(eq);
addSymbol(neq);
addSymbol(gt);
addSymbol(lt);
addSymbol(tuple);
addSymbol(fst);
addSymbol(snd);
}
public Collection<IdentifierTemplate> getIdentifierTemplates() {
return identifierTemplates.values();
}
public IdentifierTemplate getIdentifierTemplate(String resourceName) {
return identifierTemplates.get(resourceName);
}
public void addIdentifierTemplates(IdentifierTemplate identifierTemplate) {
identifierTemplates.put(identifierTemplate.getResourceName(), identifierTemplate);
}
public void setIdentifierTemplates(HashMap<String, IdentifierTemplate> identifierTemplates) {
this.identifierTemplates = identifierTemplates;
}
public Collection<ChannelGenerator> getChannelGenerators() {
return channelGenerators.values();
}
public ChannelGenerator getChannelGenerator(String channelName) {
return channelGenerators.get(channelName);
}
public void setChannelGenerators(HashMap<String, ChannelGenerator> channelGenerators) {
this.channelGenerators = channelGenerators;
for (ChannelGenerator g: channelGenerators.values()) {
for (IdentifierTemplate id: g.getIdentifierTemplates()) {
identifierTemplates.put(id.getResourceName(), id);
}
}
}
public void addChannelGenerator(ChannelGenerator channelGenerator) {
channelGenerators.put(channelGenerator.getChannelName(), channelGenerator);
for (IdentifierTemplate id: channelGenerator.getIdentifierTemplates()) {
identifierTemplates.put(id.getResourceName(), id);
}
}
public Collection<ChannelGenerator> getIOChannelGenerators() {
return ioChannelGenerators.values();
}
public void setIOChannelGenerators(HashMap<String, ChannelGenerator> ioChannelGenerators) {
this.ioChannelGenerators = ioChannelGenerators;
for (ChannelGenerator g: ioChannelGenerators.values()) {
for (IdentifierTemplate id: g.getIdentifierTemplates()) {
identifierTemplates.put(id.getResourceName(), id);
}
}
}
public void addIOChannelGenerator(ChannelGenerator ioChannelGenerator) {
ioChannelGenerators.put(ioChannelGenerator.getChannelName(), ioChannelGenerator);
for (IdentifierTemplate id: ioChannelGenerator.getIdentifierTemplates()) {
identifierTemplates.put(id.getResourceName(), id);
}
}
public void addType(Type type) {
types.put(type.getTypeName(), type);
}
public Type getType(String name) {
return types.get(name);
}
public void addSymbol(Symbol symbol) {
symbols.put(symbol.getName(), symbol);
}
public Symbol getSymbol(String name) {
return symbols.get(name);
}
public static String getWrapperType(Type type) {
if (type == typeInt) {
return "Integer";
} else if (type == typeLong) {
return "Long";
} else if (type == typeFloat) {
return "Float";
} else if (type == typeDouble) {
return "Double";
} else if (type == typeBoolean) {
return "Boolean";
}
return null;
}
public static boolean isListType(Type type) {
return typeList.isAncestorOf(type);
}
@Override
public String toString() {
String out = "";
for (ChannelGenerator channelGenerator: ioChannelGenerators.values()) {
out += channelGenerator.toString();
}
for (ChannelGenerator channelGenerator: channelGenerators.values()) {
out += channelGenerator.toString();
}
return out;
}
}