Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / models / dataConstraintModel / DataConstraintModel.java
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;
	}
}