Rename Type.* to type_java.*

We'll soon have type_cpp variations on these files, and a more
generic type.h

Bug: 24303749
Test: Compiles, unittests

Change-Id: I64f45efa3553f1a46d2d16d6652eedd6b324b2e4
diff --git a/type_java.cpp b/type_java.cpp
new file mode 100644
index 0000000..02988f9
--- /dev/null
+++ b/type_java.cpp
@@ -0,0 +1,1045 @@
+/*
+ * Copyright (C) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "type_java.h"
+
+#include <sys/types.h>
+
+namespace android {
+namespace aidl {
+
+Namespace NAMES;
+
+Type* VOID_TYPE;
+Type* BOOLEAN_TYPE;
+Type* BYTE_TYPE;
+Type* CHAR_TYPE;
+Type* INT_TYPE;
+Type* LONG_TYPE;
+Type* FLOAT_TYPE;
+Type* DOUBLE_TYPE;
+Type* STRING_TYPE;
+Type* OBJECT_TYPE;
+Type* CHAR_SEQUENCE_TYPE;
+Type* TEXT_UTILS_TYPE;
+Type* REMOTE_EXCEPTION_TYPE;
+Type* RUNTIME_EXCEPTION_TYPE;
+Type* IBINDER_TYPE;
+Type* IINTERFACE_TYPE;
+Type* BINDER_NATIVE_TYPE;
+Type* BINDER_PROXY_TYPE;
+Type* PARCEL_TYPE;
+Type* PARCELABLE_INTERFACE_TYPE;
+Type* CONTEXT_TYPE;
+Type* MAP_TYPE;
+Type* LIST_TYPE;
+Type* CLASSLOADER_TYPE;
+
+Expression* NULL_VALUE;
+Expression* THIS_VALUE;
+Expression* SUPER_VALUE;
+Expression* TRUE_VALUE;
+Expression* FALSE_VALUE;
+
+void register_base_types() {
+  VOID_TYPE = new BasicType("void", "XXX", "XXX", "XXX", "XXX", "XXX");
+  NAMES.Add(VOID_TYPE);
+
+  BOOLEAN_TYPE = new BooleanType();
+  NAMES.Add(BOOLEAN_TYPE);
+
+  BYTE_TYPE = new BasicType("byte", "writeByte", "readByte", "writeByteArray",
+                            "createByteArray", "readByteArray");
+  NAMES.Add(BYTE_TYPE);
+
+  CHAR_TYPE = new CharType();
+  NAMES.Add(CHAR_TYPE);
+
+  INT_TYPE = new BasicType("int", "writeInt", "readInt", "writeIntArray",
+                           "createIntArray", "readIntArray");
+  NAMES.Add(INT_TYPE);
+
+  LONG_TYPE = new BasicType("long", "writeLong", "readLong", "writeLongArray",
+                            "createLongArray", "readLongArray");
+  NAMES.Add(LONG_TYPE);
+
+  FLOAT_TYPE =
+      new BasicType("float", "writeFloat", "readFloat", "writeFloatArray",
+                    "createFloatArray", "readFloatArray");
+  NAMES.Add(FLOAT_TYPE);
+
+  DOUBLE_TYPE =
+      new BasicType("double", "writeDouble", "readDouble", "writeDoubleArray",
+                    "createDoubleArray", "readDoubleArray");
+  NAMES.Add(DOUBLE_TYPE);
+
+  STRING_TYPE = new StringType();
+  NAMES.Add(STRING_TYPE);
+
+  OBJECT_TYPE = new Type("java.lang", "Object", Type::BUILT_IN, false, false);
+  NAMES.Add(OBJECT_TYPE);
+
+  CHAR_SEQUENCE_TYPE = new CharSequenceType();
+  NAMES.Add(CHAR_SEQUENCE_TYPE);
+
+  MAP_TYPE = new MapType();
+  NAMES.Add(MAP_TYPE);
+
+  LIST_TYPE = new ListType();
+  NAMES.Add(LIST_TYPE);
+
+  TEXT_UTILS_TYPE =
+      new Type("android.text", "TextUtils", Type::BUILT_IN, false, false);
+  NAMES.Add(TEXT_UTILS_TYPE);
+
+  REMOTE_EXCEPTION_TYPE = new RemoteExceptionType();
+  NAMES.Add(REMOTE_EXCEPTION_TYPE);
+
+  RUNTIME_EXCEPTION_TYPE = new RuntimeExceptionType();
+  NAMES.Add(RUNTIME_EXCEPTION_TYPE);
+
+  IBINDER_TYPE = new IBinderType();
+  NAMES.Add(IBINDER_TYPE);
+
+  IINTERFACE_TYPE = new IInterfaceType();
+  NAMES.Add(IINTERFACE_TYPE);
+
+  BINDER_NATIVE_TYPE = new BinderType();
+  NAMES.Add(BINDER_NATIVE_TYPE);
+
+  BINDER_PROXY_TYPE = new BinderProxyType();
+  NAMES.Add(BINDER_PROXY_TYPE);
+
+  PARCEL_TYPE = new ParcelType();
+  NAMES.Add(PARCEL_TYPE);
+
+  PARCELABLE_INTERFACE_TYPE = new ParcelableInterfaceType();
+  NAMES.Add(PARCELABLE_INTERFACE_TYPE);
+
+  CONTEXT_TYPE =
+      new Type("android.content", "Context", Type::BUILT_IN, false, false);
+  NAMES.Add(CONTEXT_TYPE);
+
+  CLASSLOADER_TYPE = new ClassLoaderType();
+  NAMES.Add(CLASSLOADER_TYPE);
+
+  NULL_VALUE = new LiteralExpression("null");
+  THIS_VALUE = new LiteralExpression("this");
+  SUPER_VALUE = new LiteralExpression("super");
+  TRUE_VALUE = new LiteralExpression("true");
+  FALSE_VALUE = new LiteralExpression("false");
+
+  NAMES.AddGenericType("java.util", "List", 1);
+  NAMES.AddGenericType("java.util", "Map", 2);
+}
+
+static Type* make_generic_type(const string& package, const string& name,
+                               const vector<Type*>& args) {
+  if (package == "java.util" && name == "List") {
+    return new GenericListType("java.util", "List", args);
+  }
+  return NULL;
+  // return new GenericType(package, name, args);
+}
+
+// ================================================================
+
+Type::Type(const string& name, int kind, bool canWriteToParcel, bool canBeOut)
+    : m_package(),
+      m_name(name),
+      m_declFile(""),
+      m_declLine(-1),
+      m_kind(kind),
+      m_canWriteToParcel(canWriteToParcel),
+      m_canBeOut(canBeOut) {
+  m_qualifiedName = name;
+}
+
+Type::Type(const string& package, const string& name, int kind,
+           bool canWriteToParcel, bool canBeOut, const string& declFile,
+           int declLine)
+    : m_package(package),
+      m_name(name),
+      m_declFile(declFile),
+      m_declLine(declLine),
+      m_kind(kind),
+      m_canWriteToParcel(canWriteToParcel),
+      m_canBeOut(canBeOut) {
+  if (package.length() > 0) {
+    m_qualifiedName = package;
+    m_qualifiedName += '.';
+  }
+  m_qualifiedName += name;
+}
+
+Type::~Type() {}
+
+string Type::HumanReadableKind() const {
+  switch (Kind()) {
+    case INTERFACE:
+      return "an interface";
+    case USERDATA:
+      return "a user data";
+    default:
+      return "ERROR";
+  }
+}
+
+bool Type::CanBeArray() const { return false; }
+
+string Type::ImportType() const { return m_qualifiedName; }
+
+string Type::CreatorName() const { return ""; }
+
+string Type::InstantiableName() const { return QualifiedName(); }
+
+void Type::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel,
+                         int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%sn", __FILE__,
+          __LINE__, m_qualifiedName.c_str());
+  addTo->Add(new LiteralExpression("/* WriteToParcel error " + m_qualifiedName +
+                                   " */"));
+}
+
+void Type::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                            Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", __FILE__,
+          __LINE__, m_qualifiedName.c_str());
+  addTo->Add(new LiteralExpression("/* CreateFromParcel error " +
+                                   m_qualifiedName + " */"));
+}
+
+void Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel,
+                          Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", __FILE__,
+          __LINE__, m_qualifiedName.c_str());
+  addTo->Add(new LiteralExpression("/* ReadFromParcel error " +
+                                   m_qualifiedName + " */"));
+}
+
+void Type::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                              Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", __FILE__,
+          __LINE__, m_qualifiedName.c_str());
+  addTo->Add(new LiteralExpression("/* WriteArrayToParcel error " +
+                                   m_qualifiedName + " */"));
+}
+
+void Type::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                 Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", __FILE__,
+          __LINE__, m_qualifiedName.c_str());
+  addTo->Add(new LiteralExpression("/* CreateArrayFromParcel error " +
+                                   m_qualifiedName + " */"));
+}
+
+void Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                               Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n", __FILE__,
+          __LINE__, m_qualifiedName.c_str());
+  addTo->Add(new LiteralExpression("/* ReadArrayFromParcel error " +
+                                   m_qualifiedName + " */"));
+}
+
+void Type::SetQualifiedName(const string& qualified) {
+  m_qualifiedName = qualified;
+}
+
+Expression* Type::BuildWriteToParcelFlags(int flags) {
+  if (flags == 0) {
+    return new LiteralExpression("0");
+  }
+  if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
+    return new FieldVariable(PARCELABLE_INTERFACE_TYPE,
+                             "PARCELABLE_WRITE_RETURN_VALUE");
+  }
+  return new LiteralExpression("0");
+}
+
+// ================================================================
+
+BasicType::BasicType(const string& name, const string& marshallParcel,
+                     const string& unmarshallParcel,
+                     const string& writeArrayParcel,
+                     const string& createArrayParcel,
+                     const string& readArrayParcel)
+    : Type(name, BUILT_IN, true, false),
+      m_marshallParcel(marshallParcel),
+      m_unmarshallParcel(unmarshallParcel),
+      m_writeArrayParcel(writeArrayParcel),
+      m_createArrayParcel(createArrayParcel),
+      m_readArrayParcel(readArrayParcel) {}
+
+void BasicType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                              Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, m_marshallParcel, 1, v));
+}
+
+void BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                 Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, m_unmarshallParcel)));
+}
+
+bool BasicType::CanBeArray() const { return true; }
+
+void BasicType::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                                   Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, m_writeArrayParcel, 1, v));
+}
+
+void BasicType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                      Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, m_createArrayParcel)));
+}
+
+void BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                    Variable* parcel, Variable**) {
+  addTo->Add(new MethodCall(parcel, m_readArrayParcel, 1, v));
+}
+
+// ================================================================
+
+BooleanType::BooleanType() : Type("boolean", BUILT_IN, true, false) {}
+
+void BooleanType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(
+      parcel, "writeInt", 1,
+      new Ternary(v, new LiteralExpression("1"), new LiteralExpression("0"))));
+}
+
+void BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                   Variable* parcel, Variable**) {
+  addTo->Add(
+      new Assignment(v, new Comparison(new LiteralExpression("0"), "!=",
+                                       new MethodCall(parcel, "readInt"))));
+}
+
+bool BooleanType::CanBeArray() const { return true; }
+
+void BooleanType::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeBooleanArray", 1, v));
+}
+
+void BooleanType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                        Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "createBooleanArray")));
+}
+
+void BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                      Variable* parcel, Variable**) {
+  addTo->Add(new MethodCall(parcel, "readBooleanArray", 1, v));
+}
+
+// ================================================================
+
+CharType::CharType() : Type("char", BUILT_IN, true, false) {}
+
+void CharType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                             Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeInt", 1, new Cast(INT_TYPE, v)));
+}
+
+void CharType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "readInt"), this));
+}
+
+bool CharType::CanBeArray() const { return true; }
+
+void CharType::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                                  Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeCharArray", 1, v));
+}
+
+void CharType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "createCharArray")));
+}
+
+void CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                   Variable* parcel, Variable**) {
+  addTo->Add(new MethodCall(parcel, "readCharArray", 1, v));
+}
+
+// ================================================================
+
+StringType::StringType() : Type("java.lang", "String", BUILT_IN, true, false) {}
+
+string StringType::CreatorName() const {
+  return "android.os.Parcel.STRING_CREATOR";
+}
+
+void StringType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                               Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeString", 1, v));
+}
+
+void StringType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                  Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "readString")));
+}
+
+bool StringType::CanBeArray() const { return true; }
+
+void StringType::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                                    Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeStringArray", 1, v));
+}
+
+void StringType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                       Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "createStringArray")));
+}
+
+void StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, Variable**) {
+  addTo->Add(new MethodCall(parcel, "readStringArray", 1, v));
+}
+
+// ================================================================
+
+CharSequenceType::CharSequenceType()
+    : Type("java.lang", "CharSequence", BUILT_IN, true, false) {}
+
+string CharSequenceType::CreatorName() const {
+  return "android.os.Parcel.STRING_CREATOR";
+}
+
+void CharSequenceType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, int flags) {
+  // if (v != null) {
+  //     parcel.writeInt(1);
+  //     v.writeToParcel(parcel);
+  // } else {
+  //     parcel.writeInt(0);
+  // }
+  IfStatement* elsepart = new IfStatement();
+  elsepart->statements->Add(
+      new MethodCall(parcel, "writeInt", 1, new LiteralExpression("0")));
+  IfStatement* ifpart = new IfStatement;
+  ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
+  ifpart->elseif = elsepart;
+  ifpart->statements->Add(
+      new MethodCall(parcel, "writeInt", 1, new LiteralExpression("1")));
+  ifpart->statements->Add(new MethodCall(TEXT_UTILS_TYPE, "writeToParcel", 3, v,
+                                         parcel,
+                                         BuildWriteToParcelFlags(flags)));
+
+  addTo->Add(ifpart);
+}
+
+void CharSequenceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                        Variable* parcel, Variable**) {
+  // if (0 != parcel.readInt()) {
+  //     v = TextUtils.createFromParcel(parcel)
+  // } else {
+  //     v = null;
+  // }
+  IfStatement* elsepart = new IfStatement();
+  elsepart->statements->Add(new Assignment(v, NULL_VALUE));
+
+  IfStatement* ifpart = new IfStatement();
+  ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
+                                      new MethodCall(parcel, "readInt"));
+  ifpart->elseif = elsepart;
+  ifpart->statements->Add(new Assignment(
+      v, new MethodCall(TEXT_UTILS_TYPE,
+                        "CHAR_SEQUENCE_CREATOR.createFromParcel", 1, parcel)));
+
+  addTo->Add(ifpart);
+}
+
+// ================================================================
+
+RemoteExceptionType::RemoteExceptionType()
+    : Type("android.os", "RemoteException", BUILT_IN, false, false) {}
+
+void RemoteExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                        Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                           Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+RuntimeExceptionType::RuntimeExceptionType()
+    : Type("java.lang", "RuntimeException", BUILT_IN, false, false) {}
+
+void RuntimeExceptionType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                         Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                            Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+IBinderType::IBinderType()
+    : Type("android.os", "IBinder", BUILT_IN, true, false) {}
+
+void IBinderType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeStrongBinder", 1, v));
+}
+
+void IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                   Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "readStrongBinder")));
+}
+
+void IBinderType::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeBinderArray", 1, v));
+}
+
+void IBinderType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                        Variable* parcel, Variable**) {
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "createBinderArray")));
+}
+
+void IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                      Variable* parcel, Variable**) {
+  addTo->Add(new MethodCall(parcel, "readBinderArray", 1, v));
+}
+
+// ================================================================
+
+IInterfaceType::IInterfaceType()
+    : Type("android.os", "IInterface", BUILT_IN, false, false) {}
+
+void IInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                   Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                      Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+BinderType::BinderType()
+    : Type("android.os", "Binder", BUILT_IN, false, false) {}
+
+void BinderType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                               Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void BinderType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                  Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+BinderProxyType::BinderProxyType()
+    : Type("android.os", "BinderProxy", BUILT_IN, false, false) {}
+
+void BinderProxyType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                    Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void BinderProxyType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                       Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+ParcelType::ParcelType()
+    : Type("android.os", "Parcel", BUILT_IN, false, false) {}
+
+void ParcelType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                               Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                  Variable* parcel, Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+ParcelableInterfaceType::ParcelableInterfaceType()
+    : Type("android.os", "Parcelable", BUILT_IN, false, false) {}
+
+void ParcelableInterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                            Variable* parcel, int flags) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+void ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo,
+                                               Variable* v, Variable* parcel,
+                                               Variable**) {
+  fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
+}
+
+// ================================================================
+
+MapType::MapType() : Type("java.util", "Map", BUILT_IN, true, true) {}
+
+void MapType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                            Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeMap", 1, v));
+}
+
+static void EnsureClassLoader(StatementBlock* addTo, Variable** cl) {
+  // We don't want to look up the class loader once for every
+  // collection argument, so ensure we do it at most once per method.
+  if (*cl == NULL) {
+    *cl = new Variable(CLASSLOADER_TYPE, "cl");
+    addTo->Add(new VariableDeclaration(
+        *cl, new LiteralExpression("this.getClass().getClassLoader()"),
+        CLASSLOADER_TYPE));
+  }
+}
+
+void MapType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                               Variable* parcel, Variable** cl) {
+  EnsureClassLoader(addTo, cl);
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, *cl)));
+}
+
+void MapType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+                             Variable* parcel, Variable** cl) {
+  EnsureClassLoader(addTo, cl);
+  addTo->Add(new MethodCall(parcel, "readMap", 2, v, *cl));
+}
+
+// ================================================================
+
+ListType::ListType() : Type("java.util", "List", BUILT_IN, true, true) {}
+
+string ListType::InstantiableName() const { return "java.util.ArrayList"; }
+
+void ListType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                             Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeList", 1, v));
+}
+
+void ListType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                Variable* parcel, Variable** cl) {
+  EnsureClassLoader(addTo, cl);
+  addTo->Add(
+      new Assignment(v, new MethodCall(parcel, "readArrayList", 1, *cl)));
+}
+
+void ListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+                              Variable* parcel, Variable** cl) {
+  EnsureClassLoader(addTo, cl);
+  addTo->Add(new MethodCall(parcel, "readList", 2, v, *cl));
+}
+
+// ================================================================
+
+UserDataType::UserDataType(const string& package, const string& name,
+                           bool builtIn, bool canWriteToParcel,
+                           const string& declFile, int declLine)
+    : Type(package, name, builtIn ? BUILT_IN : USERDATA, canWriteToParcel, true,
+           declFile, declLine) {}
+
+string UserDataType::CreatorName() const {
+  return QualifiedName() + ".CREATOR";
+}
+
+void UserDataType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                 Variable* parcel, int flags) {
+  // if (v != null) {
+  //     parcel.writeInt(1);
+  //     v.writeToParcel(parcel);
+  // } else {
+  //     parcel.writeInt(0);
+  // }
+  IfStatement* elsepart = new IfStatement();
+  elsepart->statements->Add(
+      new MethodCall(parcel, "writeInt", 1, new LiteralExpression("0")));
+  IfStatement* ifpart = new IfStatement;
+  ifpart->expression = new Comparison(v, "!=", NULL_VALUE);
+  ifpart->elseif = elsepart;
+  ifpart->statements->Add(
+      new MethodCall(parcel, "writeInt", 1, new LiteralExpression("1")));
+  ifpart->statements->Add(new MethodCall(v, "writeToParcel", 2, parcel,
+                                         BuildWriteToParcelFlags(flags)));
+
+  addTo->Add(ifpart);
+}
+
+void UserDataType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                    Variable* parcel, Variable**) {
+  // if (0 != parcel.readInt()) {
+  //     v = CLASS.CREATOR.createFromParcel(parcel)
+  // } else {
+  //     v = null;
+  // }
+  IfStatement* elsepart = new IfStatement();
+  elsepart->statements->Add(new Assignment(v, NULL_VALUE));
+
+  IfStatement* ifpart = new IfStatement();
+  ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
+                                      new MethodCall(parcel, "readInt"));
+  ifpart->elseif = elsepart;
+  ifpart->statements->Add(new Assignment(
+      v, new MethodCall(v->type, "CREATOR.createFromParcel", 1, parcel)));
+
+  addTo->Add(ifpart);
+}
+
+void UserDataType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+                                  Variable* parcel, Variable**) {
+  // TODO: really, we don't need to have this extra check, but we
+  // don't have two separate marshalling code paths
+  // if (0 != parcel.readInt()) {
+  //     v.readFromParcel(parcel)
+  // }
+  IfStatement* ifpart = new IfStatement();
+  ifpart->expression = new Comparison(new LiteralExpression("0"), "!=",
+                                      new MethodCall(parcel, "readInt"));
+  ifpart->statements->Add(new MethodCall(v, "readFromParcel", 1, parcel));
+  addTo->Add(ifpart);
+}
+
+bool UserDataType::CanBeArray() const { return true; }
+
+void UserDataType::WriteArrayToParcel(StatementBlock* addTo, Variable* v,
+                                      Variable* parcel, int flags) {
+  addTo->Add(new MethodCall(parcel, "writeTypedArray", 2, v,
+                            BuildWriteToParcelFlags(flags)));
+}
+
+void UserDataType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                         Variable* parcel, Variable**) {
+  string creator = v->type->QualifiedName() + ".CREATOR";
+  addTo->Add(new Assignment(v, new MethodCall(parcel, "createTypedArray", 1,
+                                              new LiteralExpression(creator))));
+}
+
+void UserDataType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
+                                       Variable* parcel, Variable**) {
+  string creator = v->type->QualifiedName() + ".CREATOR";
+  addTo->Add(new MethodCall(parcel, "readTypedArray", 2, v,
+                            new LiteralExpression(creator)));
+}
+
+// ================================================================
+
+InterfaceType::InterfaceType(const string& package, const string& name,
+                             bool builtIn, bool oneway, const string& declFile,
+                             int declLine)
+    : Type(package, name, builtIn ? BUILT_IN : INTERFACE, true, false, declFile,
+           declLine),
+      m_oneway(oneway) {}
+
+bool InterfaceType::OneWay() const { return m_oneway; }
+
+void InterfaceType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                  Variable* parcel, int flags) {
+  // parcel.writeStrongBinder(v != null ? v.asBinder() : null);
+  addTo->Add(
+      new MethodCall(parcel, "writeStrongBinder", 1,
+                     new Ternary(new Comparison(v, "!=", NULL_VALUE),
+                                 new MethodCall(v, "asBinder"), NULL_VALUE)));
+}
+
+void InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, Variable**) {
+  // v = Interface.asInterface(parcel.readStrongBinder());
+  string type = v->type->QualifiedName();
+  type += ".Stub";
+  addTo->Add(new Assignment(
+      v, new MethodCall(NAMES.Find(type), "asInterface", 1,
+                        new MethodCall(parcel, "readStrongBinder"))));
+}
+
+// ================================================================
+
+GenericType::GenericType(const string& package, const string& name,
+                         const vector<Type*>& args)
+    : Type(package, name, BUILT_IN, true, true) {
+  m_args = args;
+
+  m_importName = package + '.' + name;
+
+  string gen = "<";
+  int N = args.size();
+  for (int i = 0; i < N; i++) {
+    Type* t = args[i];
+    gen += t->QualifiedName();
+    if (i != N - 1) {
+      gen += ',';
+    }
+  }
+  gen += '>';
+  m_genericArguments = gen;
+  SetQualifiedName(m_importName + gen);
+}
+
+const vector<Type*>& GenericType::GenericArgumentTypes() const {
+  return m_args;
+}
+
+string GenericType::GenericArguments() const { return m_genericArguments; }
+
+string GenericType::ImportType() const { return m_importName; }
+
+void GenericType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                Variable* parcel, int flags) {
+  fprintf(stderr, "implement GenericType::WriteToParcel\n");
+}
+
+void GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                   Variable* parcel, Variable**) {
+  fprintf(stderr, "implement GenericType::CreateFromParcel\n");
+}
+
+void GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+                                 Variable* parcel, Variable**) {
+  fprintf(stderr, "implement GenericType::ReadFromParcel\n");
+}
+
+// ================================================================
+
+GenericListType::GenericListType(const string& package, const string& name,
+                                 const vector<Type*>& args)
+    : GenericType(package, name, args), m_creator(args[0]->CreatorName()) {}
+
+string GenericListType::CreatorName() const {
+  return "android.os.Parcel.arrayListCreator";
+}
+
+string GenericListType::InstantiableName() const {
+  return "java.util.ArrayList" + GenericArguments();
+}
+
+void GenericListType::WriteToParcel(StatementBlock* addTo, Variable* v,
+                                    Variable* parcel, int flags) {
+  if (m_creator == STRING_TYPE->CreatorName()) {
+    addTo->Add(new MethodCall(parcel, "writeStringList", 1, v));
+  } else if (m_creator == IBINDER_TYPE->CreatorName()) {
+    addTo->Add(new MethodCall(parcel, "writeBinderList", 1, v));
+  } else {
+    // parcel.writeTypedListXX(arg);
+    addTo->Add(new MethodCall(parcel, "writeTypedList", 1, v));
+  }
+}
+
+void GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v,
+                                       Variable* parcel, Variable**) {
+  if (m_creator == STRING_TYPE->CreatorName()) {
+    addTo->Add(
+        new Assignment(v, new MethodCall(parcel, "createStringArrayList", 0)));
+  } else if (m_creator == IBINDER_TYPE->CreatorName()) {
+    addTo->Add(
+        new Assignment(v, new MethodCall(parcel, "createBinderArrayList", 0)));
+  } else {
+    // v = _data.readTypedArrayList(XXX.creator);
+    addTo->Add(
+        new Assignment(v, new MethodCall(parcel, "createTypedArrayList", 1,
+                                         new LiteralExpression(m_creator))));
+  }
+}
+
+void GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+                                     Variable* parcel, Variable**) {
+  if (m_creator == STRING_TYPE->CreatorName()) {
+    addTo->Add(new MethodCall(parcel, "readStringList", 1, v));
+  } else if (m_creator == IBINDER_TYPE->CreatorName()) {
+    addTo->Add(new MethodCall(parcel, "readBinderList", 1, v));
+  } else {
+    // v = _data.readTypedList(v, XXX.creator);
+    addTo->Add(new MethodCall(parcel, "readTypedList", 2, v,
+                              new LiteralExpression(m_creator)));
+  }
+}
+
+// ================================================================
+
+ClassLoaderType::ClassLoaderType()
+    : Type("java.lang", "ClassLoader", BUILT_IN, false, false) {}
+
+// ================================================================
+
+Namespace::Namespace() {}
+
+Namespace::~Namespace() {
+  int N = m_types.size();
+  for (int i = 0; i < N; i++) {
+    delete m_types[i];
+  }
+}
+
+void Namespace::Add(Type* type) {
+  Type* t = Find(type->QualifiedName());
+  if (t == NULL) {
+    m_types.push_back(type);
+  }
+}
+
+void Namespace::AddGenericType(const string& package, const string& name,
+                               int args) {
+  Generic g;
+  g.package = package;
+  g.name = name;
+  g.qualified = package + '.' + name;
+  g.args = args;
+  m_generics.push_back(g);
+}
+
+Type* Namespace::Find(const string& name) const {
+  int N = m_types.size();
+  for (int i = 0; i < N; i++) {
+    if (m_types[i]->QualifiedName() == name) {
+      return m_types[i];
+    }
+  }
+  return NULL;
+}
+
+Type* Namespace::Find(const char* package, const char* name) const {
+  string s;
+  if (package != nullptr && *package != '\0') {
+    s += package;
+    s += '.';
+  }
+  s += name;
+  return Find(s);
+}
+
+static string normalize_generic(const string& s) {
+  string r;
+  int N = s.size();
+  for (int i = 0; i < N; i++) {
+    char c = s[i];
+    if (!isspace(c)) {
+      r += c;
+    }
+  }
+  return r;
+}
+
+Type* Namespace::Search(const string& name) {
+  // an exact match wins
+  Type* result = Find(name);
+  if (result != NULL) {
+    return result;
+  }
+
+  // try the class names
+  // our language doesn't allow you to not specify outer classes
+  // when referencing an inner class.  that could be changed, and this
+  // would be the place to do it, but I don't think the complexity in
+  // scoping rules is worth it.
+  int N = m_types.size();
+  for (int i = 0; i < N; i++) {
+    if (m_types[i]->Name() == name) {
+      return m_types[i];
+    }
+  }
+
+  // we got to here and it's not a generic, give up
+  if (name.find('<') == name.npos) {
+    return NULL;
+  }
+
+  // remove any whitespace
+  string normalized = normalize_generic(name);
+
+  // find the part before the '<', find a generic for it
+  ssize_t baseIndex = normalized.find('<');
+  string base(normalized.c_str(), baseIndex);
+  const Generic* g = search_generic(base);
+  if (g == NULL) {
+    return NULL;
+  }
+
+  // For each of the args, do a recursive search on it.  We don't allow
+  // generics within generics like Java does, because we're really limiting
+  // them to just built-in container classes, at least for now.  Our syntax
+  // ensures this right now as well.
+  vector<Type*> args;
+  size_t start = baseIndex + 1;
+  size_t end = start;
+  while (normalized[start] != '\0') {
+    end = normalized.find(',', start);
+    if (end == normalized.npos) {
+      end = normalized.find('>', start);
+    }
+    string s(normalized.c_str() + start, end - start);
+    Type* t = this->Search(s);
+    if (t == NULL) {
+      // maybe we should print a warning here?
+      return NULL;
+    }
+    args.push_back(t);
+    start = end + 1;
+  }
+
+  // construct a GenericType, add it to our name set so they always get
+  // the same object, and return it.
+  result = make_generic_type(g->package, g->name, args);
+  if (result == NULL) {
+    return NULL;
+  }
+
+  this->Add(result);
+  return this->Find(result->QualifiedName());
+}
+
+const Namespace::Generic* Namespace::search_generic(const string& name) const {
+  int N = m_generics.size();
+
+  // first exact match
+  for (int i = 0; i < N; i++) {
+    const Generic& g = m_generics[i];
+    if (g.qualified == name) {
+      return &g;
+    }
+  }
+
+  // then name match
+  for (int i = 0; i < N; i++) {
+    const Generic& g = m_generics[i];
+    if (g.name == name) {
+      return &g;
+    }
+  }
+
+  return NULL;
+}
+
+void Namespace::Dump() const {
+  int n = m_types.size();
+  for (int i = 0; i < n; i++) {
+    Type* t = m_types[i];
+    printf("type: package=%s name=%s qualifiedName=%s\n", t->Package().c_str(),
+           t->Name().c_str(), t->QualifiedName().c_str());
+  }
+}
+
+}  // namespace aidl
+}  // namespace android