package sizzle.compiler;
import java.util.Arrays;
import java.util.HashMap;
import sizzle.types.SizzleFunction;
import sizzle.types.SizzleType;
import sizzle.types.SizzleVarargs;
public class FunctionTrie {
@SuppressWarnings("rawtypes")
private final HashMap trie;
@SuppressWarnings("rawtypes")
public FunctionTrie() {
this.trie = new HashMap();
}
private SizzleFunction getFunction(final Object[] ids) {
if (this.trie.containsKey(ids[0])) {
if (ids[0].equals("")) {
return (SizzleFunction) this.trie.get("");
} else {
final SizzleFunction function = ((FunctionTrie) this.trie.get(ids[0])).getFunction(Arrays.copyOfRange(ids, 1, ids.length));
if (function != null)
return function;
}
} else {
for (final Object o : this.trie.keySet())
if (o instanceof SizzleVarargs && ((SizzleVarargs) o).accepts((SizzleType) ids[0])) {
return ((FunctionTrie) this.trie.get(o)).getFunction();
} else if (o instanceof SizzleType && ((SizzleType) o).accepts((SizzleType) ids[0])) {
final SizzleFunction function = ((FunctionTrie) this.trie.get(o)).getFunction(Arrays.copyOfRange(ids, 1, ids.length));
if (function != null)
return function;
}
}
return null;
}
private SizzleFunction getFunction() {
return (SizzleFunction) this.trie.get("");
}
public SizzleFunction getFunction(final String name, final SizzleType[] formalParameters) {
final Object[] ids = new Object[formalParameters.length + 2];
ids[0] = name;
for (int i = 0; i < formalParameters.length; i++)
ids[i + 1] = formalParameters[i];
ids[ids.length - 1] = "";
final SizzleFunction function = this.getFunction(ids);
if (function == null)
throw new TypeException("no such function " + name + "(" + Arrays.toString(formalParameters) + ")");
return function;
}
public boolean hasFunction(final String name, final SizzleType[] formalParameters) {
try {
this.getFunction(name, formalParameters);
return true;
} catch (final TypeException e) {
return false;
}
}
@SuppressWarnings("unchecked")
private void addFunction(final Object[] ids, final SizzleFunction sizzleFunction) {
if (this.trie.containsKey(ids[0])) {
if (ids[0].equals("")) {
throw new RuntimeException("function " + sizzleFunction + " already defined");
} else {
((FunctionTrie) this.trie.get(ids[0])).addFunction(Arrays.copyOfRange(ids, 1, ids.length), sizzleFunction);
}
} else {
if (ids[0].equals("")) {
this.trie.put("", sizzleFunction);
} else {
final FunctionTrie functionTrie = new FunctionTrie();
functionTrie.addFunction(Arrays.copyOfRange(ids, 1, ids.length), sizzleFunction);
this.trie.put(ids[0], functionTrie);
}
}
}
public void addFunction(final String name, final SizzleFunction sizzleFunction) {
final SizzleType[] formalParameters = sizzleFunction.getFormalParameters();
final Object[] ids = new Object[formalParameters.length + 2];
ids[0] = name;
for (int i = 0; i < formalParameters.length; i++)
ids[i + 1] = formalParameters[i];
ids[ids.length - 1] = "";
this.addFunction(ids, sizzleFunction);
}
}