コード例 #1
0
def trans_ty(tname):
  _tname = util.sanitize_ty(tname.strip())
  array_regex = r"([^ \[\]]+)((\[\])+)"
  m = re.match(array_regex, _tname)

  global _ty
  r_ty = _tname
  # to avoid primitive types that Sketch doesn't support
  if _tname == C.J.z: r_ty = C.SK.z
  elif _tname in [C.J.b, C.J.s, C.J.j]: r_ty = C.J.i
  # unboxing primitive Classes, e.g., Character -> char
  elif _tname in C.autoboxing: r_ty = util.unboxing(_tname)
  # TODO: parameterize len?
  elif _tname in [C.J.c+"[]"]: r_ty = u"{}[51]".format(C.J.c)
  elif _tname in [C.J.B, C.J.S, C.J.J, C.J.I]: r_ty = C.J.i
  # array bounds
  elif m:
    r_ty = trans_ty(m.group(1)) + \
        "[{}]".format(len(methods())) * len(re.findall(r"\[\]", m.group(2)))
  # use memoized type conversion
  elif _tname in _ty: r_ty = _ty[_tname]
  # convert Java collections into an appropriate struct name
  # Map<K,V> / List<T> / ... -> Map_K_V / List_T / ...
  elif util.is_collection(_tname):
    r_ty = '_'.join(util.of_collection(_tname))
    logging.debug("{} => {}".format(_tname, r_ty))
    _ty[_tname] = r_ty

  return r_ty
コード例 #2
0
ファイル: encoder.py プロジェクト: chubbymaggie/java-sketch
def trans_ty(tname):
  _tname = util.sanitize_ty(tname.strip())
  array_regex = r"([^ \[\]]+)((\[\])+)"
  m = re.match(array_regex, _tname)

  global _ty
  r_ty = _tname
  # to avoid primitive types that Sketch doesn't support
  if _tname == C.J.z: r_ty = C.SK.z
  elif _tname in [C.J.b, C.J.s, C.J.j]: r_ty = C.J.i
  # unboxing primitive Classes, e.g., Character -> char
  elif _tname in C.autoboxing: r_ty = util.unboxing(_tname)
  # TODO: parameterize len?
  elif _tname in [C.J.c+"[]"]: r_ty = u"{}[51]".format(C.J.c)
  elif _tname in [C.J.B, C.J.S, C.J.J, C.J.I]: r_ty = C.J.i
  # array bounds
  elif m:
    r_ty = trans_ty(m.group(1)) + \
        "[{}]".format(len(methods())) * len(re.findall(r"\[\]", m.group(2)))
  # use memoized type conversion
  elif _tname in _ty: r_ty = _ty[_tname]
  # convert Java collections into an appropriate struct name
  # Map<K,V> / List<T> / ... -> Map_K_V / List_T / ...
  elif util.is_collection(_tname):
    r_ty = '_'.join(util.of_collection(_tname))
    logging.debug("{} => {}".format(_tname, r_ty))
    _ty[_tname] = r_ty

  return r_ty
コード例 #3
0
ファイル: web.py プロジェクト: gpelipas/adobopy
      def __call__(self, environ, start_response):
          try:
              # create http request
              request = HttpRequest(environ)

              (re_url, url, func_callback) = self.__find_mapped_func(request)

              resp_mimetype = func_callback.produces
              if "application/json" == resp_mimetype.lower():
                 response = HttpJSonResponse(output = {}, content_type = resp_mimetype)
              else:
                 response = HttpResponse(content_type = resp_mimetype)

              opt_func_out = func_callback(request, response) # call the web-mapped-function
              # developer can directly manipulate the response, or return objects|string as ouput

              if opt_func_out is not None and opt_func_out:
                 if isinstance(opt_func_out, basestring):
                    response.set_output_body( str(opt_func_out) )

                 elif util.is_collection(opt_func_out): # is collection
                    response.set_output_body( util.to_json(str(opt_func_out)) )

              return response.send(start_response)

          except (KeyboardInterrupt, SystemExit, MemoryError):
              raise InternalServerError("Request failed due to an Internal Server Error.")

          except Exception, e:
              return self.__handle_error(e, (environ, start_response))
コード例 #4
0
def trans_init(cls_name, arg_typs, args):
  buf = cStringIO.StringIO()
  cls = class_lookup(cls_name)
  if util.is_collection(cls_name) or not cls:
    buf.write(trans_ty(cls_name) + "()")
  elif is_replaced(cls_name):
    buf.write(trans_ty(cls_name) + "(hash=nonce())")
  else:
    add_on = []
    if args:
      # NOTE: assume the order of arguments is same as that of fields
      # NOTE: for missing fields, just call default constructors
      # TODO: use template.sig_match
      kwargs = zip(cls.flds, args)
      if kwargs: assigned, _ = zip(*kwargs)
      else: assigned = []
      not_assigned = [fld for fld in cls.flds if fld not in assigned]
      if not_assigned:
        def default_init(fld):
          if util.is_class_name(fld.typ):
            return C.J.NEW + ' ' + trans_init(fld.typ, [], [])
          else: return '0'
        add_on = map(default_init, not_assigned)
    # else: # means, default constructor

    flds = ["hash"] + map(op.attrgetter("name"), cls.flds)
    vals = ["nonce()"] + args + add_on
    kwargs = map(lambda (f, v): "{}={}".format(f, v), zip(flds, vals))
    buf.write('_'.join([cls_name] + arg_typs))
    buf.write('(' + ", ".join(kwargs) + ')')

  return buf.getvalue()
コード例 #5
0
def trans_mname(cname, mname, arg_typs=[]):
  global _mtds
  r_mtd = mname
  mid = u'_'.join([cname, mname] + arg_typs)
  # use memoized method name conversion
  if mid in _mtds:
    return _mtds[mid]
  # methods of Java collections
  elif util.is_collection(cname):
    _arg_typs = map(trans_ty, arg_typs)
    r_mtd = u'_'.join([mname, trans_ty(cname)] + _arg_typs)
  else:
    if is_replaced(cname):
      tr_name = trans_ty(cname)
      cls = class_lookup(tr_name)
      if cls and cls.is_aux: cname = tr_name
    mtds = find_mtds_by_sig(cname, mname, arg_typs)
    if mtds and 1 == len(mtds):
      r_mtd = unicode(repr(mtds[0]))
    else: # ambiguous or not found
      r_mtd = '_'.join([mname, util.sanitize_ty(cname)])

  r_mtd = sanitize_mname(r_mtd)
  _mtds[mid] = r_mtd
  return r_mtd
コード例 #6
0
    def trans_call(callee, rcv_ty, rcv):
      if callee.is_static: rcv = None
      logging = None
      if not util.is_collection(callee.clazz.name):
        logging = str(check_logging(mtd, callee)).lower()

      args = util.rm_none([rcv] + map(curried, e.a) + [logging])
      mid = trans_mname(rcv_ty, callee.name, arg_typs)
      return u"{}({})".format(mid, ", ".join(args))
コード例 #7
0
ファイル: encoder.py プロジェクト: chubbymaggie/java-sketch
def gen_log_sk(sk_dir, pgr):
  buf = cStringIO.StringIO()
  buf.write("package log;\n")
  buf.write(_const)

  buf.write("""
    // distinct hash values for runtime objects
    int obj_cnt = 0;
    int nonce () {
      return obj_cnt++;
    }
  """)

  # factory of Object
  buf.write("""
    // factory of Object
    Object alloc(int ty) {{
      Object {0} = new Object(hash=nonce(), __cid=ty);
      return {0};
    }}
  """.format(C.SK.self))

  global _ty;
  _clss = []
  for ty in _ty.keys():
    if util.is_collection(ty): continue
    if util.is_array(ty): continue
    cls = class_lookup(ty)
    if not cls: continue # to avoid None definition
    # inner class may appear twice: w/ and w/o outer class name
    if cls not in _clss: _clss.append(cls)

  buf.write("\n// distinct class IDs\n")
  for cls in _clss:
    buf.write("int {cls!r} () {{ return {cls.id}; }}\n".format(**locals()))

  buf.write("\n// distinct method IDs\n")
  for cls in pgr.classes:
    mtds = collect_decls(cls, "mtds")
    if not mtds: continue

    for mtd in mtds:
      mname = sanitize_mname(unicode(repr(mtd)))
      buf.write("""
        int {mname}_ent () {{ return  {mtd.id}; }}
        int {mname}_ext () {{ return -{mtd.id}; }}
      """.format(**locals()))

  with open(os.path.join(sk_dir, "log.sk"), 'w') as f:
    f.write(buf.getvalue())
    logging.info("encoding " + f.name)
  buf.close()
コード例 #8
0
ファイル: encoder.py プロジェクト: chubbymaggie/java-sketch
def rm_subs(clss):
  # { cname: Clazz(cname, ...), ... }
  decls = { cls.name: cls for cls in clss }

  # remove subclasses
  for cname in decls.keys():
    if util.is_collection(cname): continue
    cls = class_lookup(cname)
    if not cls.is_class: continue
    for sub in cls.subs:
      if sub.name in decls:
        logging.debug("{} < {}".format(sub.name, cname))
        del decls[sub.name]
    for sup in util.ffilter([cls.sup]):
      if sup in decls and cname in decls:
        logging.debug("{} < {}".format(cname, sup))
        del decls[cname]

  return decls.values()
コード例 #9
0
def rm_subs(clss):
  # { cname: Clazz(cname, ...), ... }
  decls = { cls.name: cls for cls in clss }

  # remove subclasses
  for cname in decls.keys():
    if util.is_collection(cname): continue
    cls = class_lookup(cname)
    if not cls.is_class: continue
    if cls.is_aux: continue # virtual relations; don't remove sub classes
    for sub in cls.subs:
      if sub.name in decls:
        logging.debug("{} < {}".format(sub.name, cname))
        del decls[sub.name]
    for sup in util.ffilter([cls.sup]):
      if sup in decls and cname in decls:
        logging.debug("{} < {}".format(cname, sup))
        del decls[cname]

  return decls.values()
コード例 #10
0
ファイル: encoder.py プロジェクト: chubbymaggie/java-sketch
def gen_type_sk(sk_dir, bases):
  buf = cStringIO.StringIO()
  buf.write("package type;\n")
  buf.write(_const)

  cols, decls = util.partition(lambda c: util.is_collection(c.name), bases)
  decls = filter(lambda c: not util.is_array(c.name), decls)
  itfs, clss = util.partition(op.attrgetter("is_itf"), decls)
  logging.debug("# interface(s): {}".format(len(itfs)))
  logging.debug("# class(es): {}".format(len(clss)))
  # convert interfaces first, then usual classes
  buf.write('\n'.join(util.ffilter(map(to_struct, itfs))))
  buf.write('\n'.join(util.ffilter(map(to_struct, clss))))

  # convert collections at last
  logging.debug("# collection(s): {}".format(len(cols)))
  buf.write('\n'.join(map(col_to_struct, cols)))

  # argument number of methods
  arg_num = map(lambda mtd: len(mtd.params), methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id) {{
      return _{0}[id];
    }}
  """.format(C.typ.argNum, ", ".join(map(str, arg_num))))

  # argument types of methods
  def get_args_typ(mtd):
    def get_arg_typ(param): return str(class_lookup(param[0]).id)
    return '{' + ", ".join(map(get_arg_typ, mtd.params)) + '}'
  args_typ = map(get_args_typ, methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id, int idx) {{
      return _{0}[id][idx];
    }}
  """.format(C.typ.argType, ", ".join(args_typ)))

  # return type of methods
  def get_ret_typ(mtd):
    cls = class_lookup(mtd.typ)
    if cls: return cls.id
    else: return -1
  ret_typ = map(get_ret_typ, methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id) {{
      return _{0}[id];
    }}
  """.format(C.typ.retType, ", ".join(map(str, ret_typ))))

  # belonging class of methods
  belongs = map(lambda mtd: mtd.clazz.id, methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id) {{
      return _{0}[id];
    }}
  """.format(C.typ.belongsTo, ", ".join(map(str, belongs))))

  subcls = \
      map(lambda cls_i: '{' + ", ".join( \
          map(lambda cls_j: str(cls_i <= cls_j).lower(), classes()) \
      ) + '}', classes())
  buf.write("""
    #define _{0} {{ {1} }}
    bit {0}(int i, int j) {{
      return _{0}[i][j];
    }}
  """.format(C.typ.subcls, ", ".join(subcls)))

  ## sub type relations
  #subcls = []
  #for cls_i in classes():
  #  row = []
  #  for cls_j in classes():
  #    row.append(int(cls_i <= cls_j))
  #  subcls.append(row)

  ## sub type relations in yale format 
  #_, IA, JA = util.yale_format(subcls)
  #li, lj = len(IA), len(JA)
  #si = ", ".join(map(str, IA))
  #sj = ", ".join(map(str, JA))
  #buf.write("""
  #  #define _iA {{ {si} }}
  #  #define _jA {{ {sj} }}
  #  int iA(int i) {{
  #    return _iA[i];
  #  }}
  #  int jA(int j) {{
  #    return _jA[j];
  #  }}
  #  bit subcls(int i, int j) {{
  #    int col_i = iA(i);
  #    int col_j = iA(i+1);
  #    for (int col = col_i; col < col_j; col++) {{
  #      if (j == jA(col)) return true;
  #    }}
  #    return false;
  #  }}
  #""".format(**locals()))

  with open(os.path.join(sk_dir, "type.sk"), 'w') as f:
    f.write(buf.getvalue())
    logging.info("encoding " + f.name)
  buf.close()
コード例 #11
0
ファイル: encoder.py プロジェクト: chubbymaggie/java-sketch
def trans_s(mtd, s):
  curried_e = partial(trans_e, mtd)
  curried_s = partial(trans_s, mtd)
  buf = cStringIO.StringIO()

  if s.kind == C.S.IF:
    e = curried_e(s.e)
    t = '\n'.join(map(curried_s, s.t))
    f = '\n'.join(map(curried_s, s.f))
    buf.write("if (" + e + ") {\n" + t + "\n}")
    if f: buf.write("\nelse {\n" + f + "\n}")

  elif s.kind == C.S.WHILE:
    e = curried_e(s.e)
    b = '\n'.join(map(curried_s, s.b))
    buf.write("while (" + e + ") {\n" + b + "\n}")

  elif s.kind == C.S.REPEAT:
    e = curried_e(s.e)
    b = '\n'.join(map(curried_s, s.b))
    if e == "??": buf.write("minrepeat {\n" + b + "\n}")
    else: buf.write("repeat (" + e + ") {\n" + b + "\n}")

  elif s.kind == C.S.MINREPEAT:
    b = '\n'.join(map(curried_s, s.b))
    buf.write("minrepeat {\n" + b + "\n}")

  elif s.kind == C.S.FOR:
    # assume "for" is used for List<T> and LinkedList<T> only
    col = mtd.vars[s.init.id]
    if not util.is_collection(col) or \
        util.of_collection(col)[0] not in [C.J.LST, C.J.LNK]:
      raise Exception("not iterable type", col)

    # if this is about observers, let sketch choose iteration direction
    is_obs = hasattr(class_lookup(util.of_collection(col)[1]), "obs")
    s_init = curried_e(s.init)

    if is_obs: init = "{{| 0 | {}.idx - 1 |}}".format(s_init)
    else: init = '0'
    buf.write("  int idx = {};".format(init))

    s_i_typ = trans_ty(s.i.ty)
    buf.write("""
      while (0 <= idx && idx < S && {s_init}.elts[idx] != null) {{
        {s_i_typ} {s.i.id} = {s_init}.elts[idx];
    """.format(**locals()))

    buf.write('\n'.join(map(curried_s, s.b)))

    if is_obs: upd = "{| idx (+ | -) 1 |}"
    else: upd = "idx + 1"
    buf.write("""
        idx = {};
      }}
    """.format(upd))

  elif s.kind == C.S.TRY:
    # NOTE: no idea how to handle catch blocks
    # at this point, just walk through try/finally blocks
    buf.write('\n'.join(map(curried_s, s.b + s.fs)))

  else: buf.write(s.__str__(curried_e))
  return buf.getvalue()
コード例 #12
0
def gen_type_sk(sk_dir, bases):
  buf = cStringIO.StringIO()
  buf.write("package type;\n")
  buf.write(_const)

  buf.write(trans_lib())
  buf.write('\n')

  cols, decls = util.partition(lambda c: util.is_collection(c.name), bases)
  decls = filter(lambda c: not util.is_array(c.name), decls)
  itfs, clss = util.partition(op.attrgetter("is_itf"), decls)
  logging.debug("# interface(s): {}".format(len(itfs)))
  logging.debug("# class(es): {}".format(len(clss)))
  # convert interfaces first, then usual classes
  buf.write('\n'.join(util.ffilter(map(to_struct, itfs))))
  buf.write('\n'.join(util.ffilter(map(to_struct, clss))))

  # convert collections at last
  logging.debug("# collection(s): {}".format(len(cols)))
  buf.write('\n'.join(map(col_to_struct, cols)))

  # argument number of methods
  arg_num = map(lambda mtd: len(mtd.params), methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id) {{
      return _{0}[id];
    }}
  """.format(C.typ.argNum, ", ".join(map(str, arg_num))))

  # argument types of methods
  def get_args_typ(mtd):
    def get_arg_typ(param): return str(class_lookup(param[0]).id)
    return '{' + ", ".join(map(get_arg_typ, mtd.params)) + '}'
  args_typ = map(get_args_typ, methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id, int idx) {{
      return _{0}[id][idx];
    }}
  """.format(C.typ.argType, ", ".join(args_typ)))

  # return type of methods
  def get_ret_typ(mtd):
    cls = class_lookup(mtd.typ)
    if cls: return cls.id
    else: return -1
  ret_typ = map(get_ret_typ, methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id) {{
      return _{0}[id];
    }}
  """.format(C.typ.retType, ", ".join(map(str, ret_typ))))

  # belonging class of methods
  belongs = map(lambda mtd: mtd.clazz.id, methods())
  buf.write("""
    #define _{0} {{ {1} }}
    int {0}(int id) {{
      return _{0}[id];
    }}
  """.format(C.typ.belongsTo, ", ".join(map(str, belongs))))

  subcls = \
      map(lambda cls_i: '{' + ", ".join( \
          map(lambda cls_j: str(cls_i <= cls_j).lower(), classes()) \
      ) + '}', classes())
  buf.write("""
    #define _{0} {{ {1} }}
    bit {0}(int i, int j) {{
      return _{0}[i][j];
    }}
  """.format(C.typ.subcls, ", ".join(subcls)))

  ## sub type relations
  #subcls = []
  #for cls_i in classes():
  #  row = []
  #  for cls_j in classes():
  #    row.append(int(cls_i <= cls_j))
  #  subcls.append(row)

  ## sub type relations in yale format 
  #_, IA, JA = util.yale_format(subcls)
  #li, lj = len(IA), len(JA)
  #si = ", ".join(map(str, IA))
  #sj = ", ".join(map(str, JA))
  #buf.write("""
  #  #define _iA {{ {si} }}
  #  #define _jA {{ {sj} }}
  #  int iA(int i) {{
  #    return _iA[i];
  #  }}
  #  int jA(int j) {{
  #    return _jA[j];
  #  }}
  #  bit subcls(int i, int j) {{
  #    int col_i = iA(i);
  #    int col_j = iA(i+1);
  #    for (int col = col_i; col < col_j; col++) {{
  #      if (j == jA(col)) return true;
  #    }}
  #    return false;
  #  }}
  #""".format(**locals()))

  with open(os.path.join(sk_dir, "type.sk"), 'w') as f:
    f.write(buf.getvalue())
    logging.info("encoding " + f.name)
  buf.close()
コード例 #13
0
def trans_s(mtd, s):
  curried_e = partial(trans_e, mtd)
  curried_s = partial(trans_s, mtd)
  buf = cStringIO.StringIO()

  if s.kind == C.S.IF:
    e = curried_e(s.e)
    t = '\n'.join(map(curried_s, s.t))
    f = '\n'.join(map(curried_s, s.f))
    buf.write("if (" + e + ") {\n" + t + "\n}")
    if f: buf.write("\nelse {\n" + f + "\n}")

  elif s.kind == C.S.WHILE:
    e = curried_e(s.e)
    b = '\n'.join(map(curried_s, s.b))
    buf.write("while (" + e + ") {\n" + b + "\n}")

  elif s.kind == C.S.REPEAT:
    e = curried_e(s.e)
    b = '\n'.join(map(curried_s, s.b))
    if e == "??": buf.write("minrepeat {\n" + b + "\n}")
    else: buf.write("repeat (" + e + ") {\n" + b + "\n}")

  elif s.kind == C.S.MINREPEAT:
    b = '\n'.join(map(curried_s, s.b))
    buf.write("minrepeat {\n" + b + "\n}")

  elif s.kind == C.S.FOR:
    # assume "for" is used for List<T> and LinkedList<T> only
    col = mtd.vars[s.init.id]
    if not util.is_collection(col) or \
        util.of_collection(col)[0] not in [C.J.LST, C.J.LNK]:
      raise Exception("not iterable type", col)

    # if this is about observers, let sketch choose iteration direction
    is_obs = hasattr(class_lookup(util.of_collection(col)[1]), "obs")
    s_init = curried_e(s.init)

    if is_obs: init = "{{| 0 | {}.idx - 1 |}}".format(s_init)
    else: init = '0'
    buf.write("  int idx = {};".format(init))

    s_i_typ = trans_ty(s.i.ty)
    buf.write("""
      while (0 <= idx && idx < S && {s_init}.elts[idx] != null) {{
        {s_i_typ} {s.i.id} = {s_init}.elts[idx];
    """.format(**locals()))

    buf.write('\n'.join(map(curried_s, s.b)))

    if is_obs: upd = "{| idx (+ | -) 1 |}"
    else: upd = "idx + 1"
    buf.write("""
        idx = {};
      }}
    """.format(upd))

  elif s.kind == C.S.TRY:
    # NOTE: no idea how to handle catch blocks
    # at this point, just walk through try/finally blocks
    buf.write('\n'.join(map(curried_s, s.b + s.fs)))

  else: buf.write(s.__str__(curried_e))
  return buf.getvalue()
コード例 #14
0
def gen_log_sk(sk_dir, tmpl):
  buf = cStringIO.StringIO()
  buf.write("package log;\n")
  buf.write(_const)
  global max_objs
  buf.write("int O = {}; // # of objects\n".format(max_objs + 1))

  buf.write("""
    int log_cnt = 0;
    int[P][N] ev;
    int[O] obj;

    // to enforce the length of logs
    int get_log_cnt() {
      return log_cnt;
    }

    // after writing logs, reset the cursor in order to check logs in order
    void reset_log_cnt() {
      log_cnt = 0;
    }

    // to clean up the logs totally
    void clear_log() {
      reset_log_cnt();
      ev = {};
      obj = {};
    }

    // to write the log from samples
    void write_log (int[P] params) {
      ev[log_cnt++] = params;
    }

    // to check whether control-flow conforms to the samples
    @Native("{ std::cout << \\\"log::check_log::\\\" << params[0] << std::endl; }")
    void check_log (int[P] params) {
      assert params[0] == ev[log_cnt][0]; // check mid
      for (int i = 1; i < P; i++) {
        if (ev[log_cnt][i] != 0) {
          if (obj[ev[log_cnt][i]] == 0) { // not set yet
            obj[ev[log_cnt][i]] = params[i];
          }
          else { // o.w. check obj eq.
            assert obj[ev[log_cnt][i]] == params[i];
          }
        }
      }
      log_cnt++; // advance
    }

    // distinct hash values for runtime objects
    int obj_cnt = 0;
    int nonce () {
      return obj_cnt++;
    }
  """)

  global _inits
  reg_codes = []
  for ty in _inits:
    cls = class_lookup(ty)
    if not cls: continue

    buf.write("""
      int obj_{0}_cnt = 0;
      {1}[O] obj_{0};

      // to register runtime instances of {0}
      void register_{0} ({1} {2}) {{
        if (obj_{0}_cnt < O) {{
          obj_{0}[obj_{0}_cnt++] = {2};
        }}
      }}

      // to access to a certain instance of {0}
      {1} retrieve_{0} (int idx) {{
        if (0 <= idx && idx < obj_{0}_cnt) {{
          return obj_{0}[idx];
        }}
        else {{
          return null;
        }}
      }}
    """.format(ty, trans_ty(ty), ty.lower()))

    reg_code = "if (ty == {0}) register_{1}@log({2});".format(cls.id, repr(cls), C.SK.self)
    reg_codes.append(reg_code)

  # factory of Object
  buf.write("""
    // factory of Object
    Object alloc(int ty) {{
      Object {0} = new Object(hash=nonce(), __cid=ty);
      {1}
      return {0};
    }}
  """.format(C.SK.self, "\nelse ".join(reg_codes)))

  global _ty;
  _clss = []
  for ty in _ty.keys():
    if util.is_collection(ty): continue
    if util.is_array(ty): continue
    cls = class_lookup(ty)
    if not cls: continue # to avoid None definition
    # inner class may appear twice: w/ and w/o outer class name
    if cls not in _clss: _clss.append(cls)

  buf.write("\n// distinct class IDs\n")
  for cls in _clss:
    buf.write("int {cls!r} () {{ return {cls.id}; }}\n".format(**locals()))

  buf.write("\n// distinct method IDs\n")
  for cls in tmpl.classes:
    mtds = collect_decls(cls, "mtds")
    if not mtds: continue

    for mtd in mtds:
      mname = sanitize_mname(unicode(repr(mtd)))
      buf.write("""
        int {mname}_ent () {{ return  {mtd.id}; }}
        int {mname}_ext () {{ return -{mtd.id}; }}
      """.format(**locals()))

  with open(os.path.join(sk_dir, "log.sk"), 'w') as f:
    f.write(buf.getvalue())
    logging.info("encoding " + f.name)
  buf.close()