this.protomap = new HashMap<Class<?>, SizzleType>();
this.protomap.put(int.class, new SizzleInt());
this.protomap.put(long.class, new SizzleInt());
this.protomap.put(float.class, new SizzleFloat());
this.protomap.put(double.class, new SizzleFloat());
this.protomap.put(boolean.class, new SizzleBool());
this.protomap.put(byte[].class, new SizzleBytes());
this.protomap.put(String.class, new SizzleString());
// this maps scalar Sizzle scalar types names to their classes
// TODO: do this via reflection
this.idmap = new HashMap<String, SizzleType>();
this.idmap.put("any", new SizzleAny());
this.idmap.put("none", null);
this.idmap.put("bool", new SizzleBool());
this.idmap.put("int", new SizzleInt());
this.idmap.put("float", new SizzleFloat());
this.idmap.put("time", new SizzleTime());
this.idmap.put("fingerprint", new SizzleFingerprint());
this.idmap.put("string", new SizzleString());
this.idmap.put("bytes", new SizzleBytes());
// does the same for arrays
// for (final String key : new HashSet<String>(this.idmap.keySet())) {
// final SizzleType value = this.idmap.get(key);
// if (value instanceof SizzleScalar)
// this.idmap.put("array of " + key, new SizzleArray((SizzleScalar)
// value));
// }
// variables with a global scope
this.globals = new HashMap<String, SizzleType>();
// set the type of the input
this.globals.put("input", input);
this.globals.put("true", new SizzleBool());
this.globals.put("false", new SizzleBool());
this.globals.put("PI", new SizzleFloat());
this.globals.put("Inf", new SizzleFloat());
this.globals.put("inf", new SizzleFloat());
this.globals.put("NaN", new SizzleFloat());
this.globals.put("nan", new SizzleFloat());
// variables with a local scope
this.locals = new HashMap<String, SizzleType>();
this.aggregators = new HashMap<String, Class<?>>();
this.functions = new FunctionTrie();
// these generic functions require more finagling than can currently be
// (easily) done with a static method, so they are handled with macros
this.setFunction("def", new SizzleFunction(new SizzleBool(), new SizzleType[] { new SizzleAny() }, "${0} != null"));
this.setFunction("len", new SizzleFunction(new SizzleInt(), new SizzleType[] { new SizzleArray(new SizzleScalar()) }, "${0}.length"));
this.setFunction("len", new SizzleFunction(new SizzleInt(), new SizzleType[] { new SizzleString() }, "${0}.length()"));
this.setFunction("len", new SizzleFunction(new SizzleInt(), new SizzleType[] { new SizzleBytes() }, "${0}.length"));
this.setFunction("len", new SizzleFunction(new SizzleInt(), new SizzleType[] { new SizzleMap(new SizzleScalar(), new SizzleScalar()) },
"${0}.keySet().size()"));
this.setFunction("haskey", new SizzleFunction(new SizzleBool(), new SizzleType[] { new SizzleMap(new SizzleScalar(), new SizzleScalar()),
new SizzleScalar() }, "${0}.containsKey(${1})"));
this.setFunction("keys", new SizzleFunction(new SizzleArray(new SizzleScalar()), new SizzleType[] { new SizzleMap(new SizzleScalar(),
new SizzleScalar()) }, "${0}.keySet().toArray()"));
this.setFunction("lookup", new SizzleFunction(new SizzleScalar(), new SizzleType[] { new SizzleMap(new SizzleScalar(), new SizzleScalar()),
new SizzleScalar(), new SizzleScalar() }, "(${0}.containsKey(${1}) ? ${0}.get(${1}) : ${2})"));
this.setFunction("regex", new SizzleFunction(new SizzleString(), new SizzleType[] { new SizzleName(new SizzleScalar()), new SizzleInt() },
"sizzle.functions.SizzleSpecialIntrinsics.regex(\"${0}\", ${1})"));
this.setFunction("regex", new SizzleFunction(new SizzleString(), new SizzleType[] { new SizzleName(new SizzleScalar()) },
"sizzle.functions.SizzleSpecialIntrinsics.regex(\"${0}\")"));
// these fingerprints are identity functions
this.setFunction("fingerprintof", new SizzleFunction(new SizzleFingerprint(), new SizzleScalar[] { new SizzleInt() }));
this.setFunction("fingerprintof", new SizzleFunction(new SizzleFingerprint(), new SizzleScalar[] { new SizzleTime() }));
/* expose all the casting constructors to Sawzall */
// string to bool
this.setFunction("bool",
new SizzleFunction("sizzle.functions.SizzleCasts.stringToBoolean", new SizzleBool(), new SizzleScalar[] { new SizzleString() }));
// bool to int
this.setFunction("int", new SizzleFunction("sizzle.functions.SizzleCasts.booleanToLong", new SizzleInt(), new SizzleScalar[] { new SizzleBool() }));
// float to int
this.setFunction("int", new SizzleFunction(new SizzleInt(), new SizzleScalar[] { new SizzleFloat() }, "(long)${0}"));
// time to int
this.setFunction("int", new SizzleFunction(new SizzleInt(), new SizzleScalar[] { new SizzleTime() }));
// fingerprint to int
this.setFunction("int", new SizzleFunction(new SizzleInt(), new SizzleScalar[] { new SizzleFingerprint() }));
// string to int
this.setFunction("int", new SizzleFunction("java.lang.Long.decode", new SizzleInt(), new SizzleScalar[] { new SizzleString() }));
// string to int with param base
this.setFunction("int", new SizzleFunction(new SizzleInt(), new SizzleScalar[] { new SizzleString(), new SizzleInt() },
"java.lang.Long.parseLong(${0}, (int)${1})"));
// bytes to int with param encoding format
this.setFunction("int", new SizzleFunction("sizzle.functions.SizzleCasts.bytesToLong", new SizzleInt(), new SizzleScalar[] { new SizzleBytes(),
new SizzleString() }));
// int to float
this.setFunction("float", new SizzleFunction(new SizzleFloat(), new SizzleScalar[] { new SizzleInt() }, "(double)${0}"));
// string to float
this.setFunction("float", new SizzleFunction("java.lang.Double.parseDouble", new SizzleFloat(), new SizzleScalar[] { new SizzleString() }));
// int to time
this.setFunction("time", new SizzleFunction(new SizzleTime(), new SizzleScalar[] { new SizzleInt() }));
// string to time
this.setFunction("time", new SizzleFunction("sizzle.functions.SizzleCasts.stringToTime", new SizzleTime(), new SizzleScalar[] { new SizzleString() }));
// string to time
this.setFunction("time", new SizzleFunction("sizzle.functions.SizzleCasts.stringToTime", new SizzleTime(), new SizzleScalar[] { new SizzleString(),
new SizzleString() }));
// int to fingerprint
this.setFunction("fingerprint", new SizzleFunction(new SizzleFingerprint(), new SizzleScalar[] { new SizzleInt() }));
// string to fingerprint
this.setFunction("fingerprint", new SizzleFunction("java.lang.Long.parseLong", new SizzleInt(), new SizzleScalar[] { new SizzleString() }));
// string to fingerprint with param base
this.setFunction("fingerprint", new SizzleFunction("java.lang.Long.parseLong", new SizzleInt(), new SizzleScalar[] { new SizzleString(),
new SizzleInt() }));
// bytes to fingerprint
this.setFunction("fingerprint", new SizzleFunction("sizzle.functions.SizzleCasts.bytesToFingerprint", new SizzleFingerprint(),
new SizzleScalar[] { new SizzleBytes() }));
// bool to string
this.setFunction("string", new SizzleFunction("java.lang.Boolean.toString", new SizzleString(), new SizzleScalar[] { new SizzleBool() }));
// int to string
this.setFunction("string", new SizzleFunction("java.lang.Long.toString", new SizzleString(), new SizzleScalar[] { new SizzleInt() }));
// int to string with parameter base
this.setFunction("string", new SizzleFunction("sizzle.functions.SizzleCasts.longToString", new SizzleString(), new SizzleScalar[] { new SizzleInt(),
new SizzleInt() }));