 
 flatten_pkg = (pkg) ->
   result = {}
-  for pkg_name, inner_pkg of pkg
-    if inner_pkg instanceof Array
-      for method in inner_pkg
-        {fn_name, fn} = method
-        result["#{pkg_name}::#{fn_name}"] = fn
-    else
-      flattened_inner = flatten_pkg inner_pkg
-      for name, method of flattened_inner
-        fullname = "#{pkg_name}/#{name}"
-        result[fullname] = method
+  pkg_name_arr = []
+  rec_flatten = (pkg) ->
+    for pkg_name, inner_pkg of pkg
+      pkg_name_arr.push pkg_name
+      if inner_pkg instanceof Array
+        for method in inner_pkg
+          {fn_name, fn} = method
+          # expand out the '!'s in the method names
+          fn_name = fn_name.replace /!|;/g, (->
+            depth = 0
+            (c) ->
+              if c == '!' then pkg_name_arr[depth++]
+              else if c == ';' then depth = 0; c
+              else c
+          )()
+          full_name = "#{pkg_name_arr.join '/'}::#{fn_name}"
+          result[full_name] = fn
+      else
+        flattened_inner = rec_flatten inner_pkg
+      pkg_name_arr.pop pkg_name
+  rec_flatten pkg
   result
   
 trapped_methods = flatten_pkg trapped_methods

  java:
    lang:
      Class: [
        o 'newInstance0()Ljava/lang/Object;', (rs) -> #implemented here to avoid reflection
            classname = rs.get_obj(rs.curr_frame().locals[0]).obj.name
            rs.push (oref = rs.init_object(classname))
            rs.method_lookup({'class':classname,'sig':{'name':'<init>'}}).run(rs)

  java:
    lang:
      Class: [
        o 'getPrimitiveClass(L!/!/String;)L!/!/!;', (rs) ->
            str = rs.get_obj(rs.curr_frame().locals[0])
            carr = rs.get_obj(str.obj.value).obj.array
            name = (String.fromCharCode(c) for c in carr).join('') # XXX convert to unicode
            rs.push rs.set_obj 'java/lang/Class', { name: name }
        o 'getClassLoader0()L!/!/ClassLoader;', (rs) -> rs.push 0  # we don't need no stinkin classloaders
        o 'desiredAssertionStatus0(L!/!/!;)Z', (rs) -> rs.push 0 # we don't need no stinkin asserts
        o 'getName0()L!/!/String;', (rs) -> rs.push rs.init_string(rs.get_obj(rs.curr_frame().locals[0]).obj.name)
        o 'forName0(L!/!/String;ZL!/!/ClassLoader;)L!/!/!;', (rs) ->
            jvm_str = rs.get_obj(rs.curr_frame().locals[0])
            classname = rs.jvm2js_str(jvm_str).replace(/\./g,'/')
            throw "Class.forName0: Failed to load #{classname}" unless rs.class_lookup(classname)
            rs.push rs.set_obj 'java/lang/Class', { name:classname }
        o 'getComponentType()L!/!/!;', (rs) ->
            type = rs.get_obj(rs.curr_frame().locals[0]).obj.name
            component_type = /\[+(.*)/.exec(type)[1]
            rs.push rs.set_obj 'java/lang/Class', name:component_type
