Esempio n. 1
0
def remove_cls(smpls, tmpl):
    cnames = sample.decls(smpls).keys() + tmpl.events.keys() + get_artifacts()

    def marker(cname):
        cls = class_lookup(cname)
        if not cls: return
        if is_marked(cls): return
        mark(cls)

        if cls.sup: marker(cls.sup)
        for itf in cls.itfs:
            marker(itf)
        for fld in cls.flds:
            marker(fld.typ)
        for mtd in cls.mtds:
            marker(mtd.typ)
            for ty, _ in mtd.params:
                marker(ty)

    # primitive types
    marker(C.J.OBJ)
    # interfaces with constants
    clss = util.flatten_classes(tmpl.classes, "inners")
    for itf in ifilter(op.attrgetter("is_itf"), clss):
        if itf.flds: mark(itf)

    map(marker, cnames)
    marked = filter(lambda cls: is_marked(cls), tmpl.classes)
    diff = list(set(tmpl.classes) - set(marked))
    if diff:
        logging.debug("unnecessary class(es): {}: {}".format(len(diff), diff))
    tmpl.classes = marked
    map(lambda cls: unmark(cls), tmpl.classes)
Esempio n. 2
0
def remove_cls(smpls, tmpl):
  cnames = sample.decls(smpls).keys() + tmpl.events.keys() + get_artifacts()

  def marker(cname):
    cls = class_lookup(cname)
    if not cls: return
    if is_marked(cls): return
    mark(cls)

    if cls.sup: marker(cls.sup)
    for itf in cls.itfs: marker(itf)
    for fld in cls.flds: marker(fld.typ)
    for mtd in cls.mtds:
      marker(mtd.typ)
      for ty, _ in mtd.params: marker(ty)

  # primitive types
  marker(C.J.OBJ)
  # interfaces with constants
  clss = util.flatten_classes(tmpl.classes, "inners")
  for itf in ifilter(op.attrgetter("is_itf"), clss):
    if itf.flds: mark(itf)

  map(marker, cnames)
  marked = filter(lambda cls: is_marked(cls), tmpl.classes)
  diff = list(set(tmpl.classes) - set(marked))
  if diff:
    logging.debug("unnecessary class(es): {}: {}".format(len(diff), diff))
  tmpl.classes = marked
  map(lambda cls: unmark(cls), tmpl.classes)
Esempio n. 3
0
def reduce_anno(smpls, tmpl):
    for cls in util.flatten_classes(tmpl.classes, "inners"):
        for fld in cls.flds:
            reduce_anno_fld(smpls, tmpl, cls, fld)
        for mtd in cls.mtds:
            reduce_anno_mtd(smpls, tmpl, cls, mtd)
            red_s = map(partial(reduce_anno_s, tmpl, cls, mtd), mtd.body)
            mtd.body = util.flatten(red_s)
Esempio n. 4
0
def reduce_anno(smpls, tmpl):
  for cls in util.flatten_classes(tmpl.classes, "inners"):
    for fld in cls.flds:
      reduce_anno_fld(smpls, tmpl, cls, fld)
    for mtd in cls.mtds:
      reduce_anno_mtd(smpls, tmpl, cls, mtd)
      red_s = map(partial(reduce_anno_s, tmpl, cls, mtd), mtd.body)
      mtd.body = util.flatten(red_s)
Esempio n. 5
0
def to_func(mtd):
  buf = cStringIO.StringIO()
  if C.mod.GN in mtd.mods: buf.write(C.mod.GN + ' ')
  elif C.mod.HN in mtd.mods: buf.write(C.mod.HN + ' ')
  ret_ty = trans_ty(mtd.typ)
  cname = unicode(repr(mtd.clazz))
  mname = mtd.name
  arg_typs = mtd.param_typs
  buf.write(ret_ty + ' ' + trans_mname(cname, mname, arg_typs) + '(')

  @takes(tuple_of(unicode))
  @returns(unicode)
  def trans_param( (ty, nm) ):
    return ' '.join([trans_ty(ty), nm])

  # for instance methods, add "this" pointer into parameters
  if mtd.is_static:
    params = mtd.params[:]
  else:
    self_ty = trans_ty(unicode(repr(mtd.clazz)))
    params = [ (self_ty, C.SK.self) ] + mtd.params[:]

  if len(params) > 0:
    buf.write(", ".join(map(trans_param, params)))
  buf.write(") {\n")

  clss = util.flatten_classes([mtd.clazz], "subs")
  mid = unicode(repr(mtd))
  m_ent = mid + "_ent()"
  m_ext = mid + "_ext()"

  is_void = C.J.v == mtd.typ
  if mtd.body:
    buf.write('\n'.join(map(partial(trans_s, mtd), mtd.body)))

  if mtd.is_init:
    buf.write("\nreturn {};".format(C.SK.self))

  buf.write("\n}\n")
  return buf.getvalue()
Esempio n. 6
0
def collect_decls(cls, attr):
  clss = util.flatten_classes([cls], "inners")
  declss = map(op.attrgetter(attr), clss)
  return util.flatten(declss)
Esempio n. 7
0
def to_struct(cls):

  # make mappings from static fields to corresponding accessors
  def gen_s_flds_accessors(cls):
    s_flds = filter(op.attrgetter("is_static"), cls.flds)
    global _s_flds
    for fld in ifilterfalse(op.attrgetter("is_private"), s_flds):
      cname = fld.clazz.name
      fid = '.'.join([cname, fld.name])
      fname = unicode(repr(fld))
      logging.debug("{} => {}".format(fid, fname))
      _s_flds[fid] = fname

  cname = util.sanitize_ty(cls.name)
  global _ty
  # if this is an interface, merge this into another family of classes
  # as long as classes that implement this interface are in the same family
  if cls.is_itf:
    # interface may have static constants
    gen_s_flds_accessors(cls)
    subss = util.flatten_classes(cls.subs, "subs")
    bases = util.rm_dup(map(lambda sub: find_base(sub), subss))
    # filter out interfaces that extend other interfaces, e.g., Action
    base_clss, _ = util.partition(op.attrgetter("is_class"), bases)
    if not base_clss:
      logging.debug("no implementer of {}".format(cname))
    elif len(base_clss) > 1:
      logging.debug("ambiguous inheritance of {}: {}".format(cname, base_clss))
    else: # len(base_clss) == 1
      base = base_clss[0]
      base_name = base.name
      logging.debug("{} => {}".format(cname, base_name))
      _ty[cname] = base_name
      if cls.is_inner: # to handle inner interface w/ outer class name
        logging.debug("{} => {}".format(repr(cls), base_name))
        _ty[unicode(repr(cls))] = base_name

    return ''

  # if this is the base class having subclasses,
  # make a virtual struct first
  if cls.subs:
    cls = to_v_struct(cls)
    cname = cls.name

  # cls can be modified above, thus generate static fields accessors here
  gen_s_flds_accessors(cls)

  # for unique class numbering, add an identity mapping
  if cname not in _ty: _ty[cname] = cname

  buf = cStringIO.StringIO()
  buf.write("struct " + cname + " {\n  int hash;\n")

  # to avoid static fields, which will be bound to a class-representing package
  _, i_flds = util.partition(op.attrgetter("is_static"), cls.flds)
  buf.write('\n'.join(map(trans_fld, i_flds)))
  if len(i_flds) > 0: buf.write('\n')
  buf.write("}\n")

  return buf.getvalue()
Esempio n. 8
0
def to_func(smpls, mtd):
  buf = cStringIO.StringIO()
  if C.mod.GN in mtd.mods: buf.write(C.mod.GN + ' ')
  elif C.mod.HN in mtd.mods: buf.write(C.mod.HN + ' ')
  ret_ty = trans_ty(mtd.typ)
  cname = unicode(repr(mtd.clazz))
  mname = mtd.name
  arg_typs = mtd.param_typs
  buf.write(ret_ty + ' ' + trans_mname(cname, mname, arg_typs) + '(')

  @takes(tuple_of(unicode))
  @returns(unicode)
  def trans_param( (ty, nm) ):
    return ' '.join([trans_ty(ty), nm])

  # for instance methods, add "this" pointer into parameters
  if mtd.is_static:
    params = mtd.params[:]
  else:
    self_ty = trans_ty(unicode(repr(mtd.clazz)))
    params = [ (self_ty, C.SK.self) ] + mtd.params[:]

  # add "logging" flag into parameters
  # to check log conformity only if invocations cross the boundary
  if not mtd.is_init and not mtd.is_clinit:
    params.append( (C.SK.z, u"logging") )

  if len(params) > 0:
    buf.write(", ".join(map(trans_param, params)))
  buf.write(") {\n")

  # once function signature is dumped out, remove "logging" flag
  if not mtd.is_init and not mtd.is_clinit:
    params.pop()

  clss = util.flatten_classes([mtd.clazz], "subs")
  logged = (not mtd.is_init) and sample.mtd_appears(smpls, clss, mtd.name)
  mid = unicode(repr(mtd))
  m_ent = mid + "_ent()"
  m_ext = mid + "_ext()"
  if logged:
    global _mids
    _mids.add(mid)

  if logged: # logging method entry (>)
    _log_params = map(log_param, params)
    _retrievals, _hashes = util.split([(u'', m_ent)] + _log_params)
    ent_retrievals = util.ffilter(_retrievals)
    ent_hashes = util.ffilter(_hashes)
    buf.write("""{}
      int[P] __params = {{ {} }};
      if (logging) check_log@log(__params);
    """.format(u''.join(ent_retrievals), u", ".join(ent_hashes)))

  is_void = C.J.v == mtd.typ
  if mtd.body:
    if not is_void and not mtd.is_init:
      bodies = mtd.body[:-1] # exclude the last 'return' statement
    else: bodies = mtd.body
    buf.write('\n'.join(map(partial(trans_s, mtd), bodies)))

  if logged: # logging method exit (<)
    _log_params = []
    if mtd.body and not is_void and not mtd.is_init:
      ret_v = mtd.body[-1].e
      ret_u = unicode(trans_e(mtd, ret_v))
      # retrieve the return value to a temporary variable
      buf.write(u"""
        {} __ret = {};
      """.format(ret_ty, ret_u))
      # then, try to obtain a hash from that temporary variable
      _log_params.append(log_param( (ret_ty, u"__ret") ))

    _retrievals, _hashes = util.split([(u'', m_ext)] + _log_params)
    ext_retrievals = util.ffilter(_retrievals)
    ext_hashes = util.ffilter(_hashes)
    buf.write("""{}
      __params = {{ {} }};
      if (logging) check_log@log(__params);
    """.format(u''.join(ext_retrievals), u", ".join(ext_hashes)))

  if mtd.body and not is_void and not mtd.is_init:
    buf.write(os.linesep)
    if logged:
      # return the return value stored at the temporary variable
      buf.write("return __ret;")
    else:
      buf.write(trans_s(mtd, mtd.body[-1]))

  if mtd.is_init:
    evt_srcs = map(util.sanitize_ty, sample.evt_sources(smpls))
    cname = unicode(repr(mtd.clazz))
    if cname in evt_srcs:
      global _inits
      _inits.add(cname)
    buf.write("\nreturn {};".format(C.SK.self))

  buf.write("\n}\n")
  return buf.getvalue()
Esempio n. 9
0
def collect_decls(cls, attr):
  clss = util.flatten_classes([cls], "inners")
  declss = map(op.attrgetter(attr), clss)
  return util.flatten(declss)
Esempio n. 10
0
def to_struct(cls):

  # make mappings from static fields to corresponding accessors
  def gen_s_flds_accessors(cls):
    s_flds = filter(op.attrgetter("is_static"), cls.flds)
    global _s_flds
    for fld in ifilterfalse(op.attrgetter("is_private"), s_flds):
      cname = fld.clazz.name
      fid = '.'.join([cname, fld.name])
      fname = unicode(repr(fld))
      logging.debug("{} => {}".format(fid, fname))
      _s_flds[fid] = fname

  cname = util.sanitize_ty(cls.name)
  global _ty
  # if this is an interface, merge this into another family of classes
  # as long as classes that implement this interface are in the same family
  if cls.is_itf:
    # interface may have static constants
    gen_s_flds_accessors(cls)
    subss = util.flatten_classes(cls.subs, "subs")
    bases = util.rm_dup(map(lambda sub: find_base(sub), subss))
    # filter out interfaces that extend other interfaces, e.g., Action
    base_clss, _ = util.partition(op.attrgetter("is_class"), bases)
    if not base_clss:
      logging.debug("no implementer of {}".format(cname))
    elif len(base_clss) > 1:
      logging.debug("ambiguous inheritance of {}: {}".format(cname, base_clss))
    else: # len(base_clss) == 1
      base = base_clss[0]
      base_name = base.name
      logging.debug("{} => {}".format(cname, base_name))
      _ty[cname] = base_name
      if cls.is_inner: # to handle inner interface w/ outer class name
        logging.debug("{} => {}".format(repr(cls), base_name))
        _ty[unicode(repr(cls))] = base_name

    return ''

  # if this is the base class having subclasses,
  # make a virtual struct first
  if cls.subs and not cls.is_aux:
    cls = to_v_struct(cls)
    cname = cls.name

  # cls can be modified above, thus generate static fields accessors here
  gen_s_flds_accessors(cls)

  # for unique class numbering, add an identity mapping
  if cname not in _ty: _ty[cname] = cname

  buf = cStringIO.StringIO()
  buf.write("struct " + cname + " {\n  int hash;\n")

  # to avoid static fields, which will be bound to a class-representing package
  _, i_flds = util.partition(op.attrgetter("is_static"), cls.flds)
  buf.write('\n'.join(map(trans_fld, i_flds)))
  if len(i_flds) > 0: buf.write('\n')
  buf.write("}\n")

  return buf.getvalue()
Esempio n. 11
0
 def logged(mtd):
   if mtd.is_init: return False
   clss = util.flatten_classes([mtd.clazz], "subs")
   return sample.mtd_appears(smpls, clss, mtd.name)
Esempio n. 12
0
def gen_smpl_sk(sk_path, smpl, tmpl, main):
  buf = cStringIO.StringIO()
  buf.write("package {};\n".format(smpl.name))
  buf.write(_const)
  buf.write("harness void {} () {{\n".format(smpl.name))

  # insert call-return sequences
  buf.write("""
    clear_log@log();
    int[P] log = { 0 };
  """)
  global _mids
  obj_cnt = 0
  objs = { C.J.N: 0, C.J.FALSE: 0, C.J.TRUE: 1, } # { @Obj...aaa : 2, ... }
  for i in xrange(10):
    objs[str(i)] = i
    obj_cnt = obj_cnt + 1

  call_stack = []
  for io in smpl.IOs:
    # ignore <init>
    if io.is_init: continue
    elif isinstance(io, sample.CallExt):
      # ignore method exits whose counterparts are missed
      if not call_stack: continue
      mid = call_stack.pop()
      # ignore methods that are not declared in the template
      if not mid: continue
    else: # sample.CallEnt
      mid = None

      # TODO: retrieve arg types
      mtd = None # find_mtd_by_sig(io.cls, io.mtd, ...)
      if mtd: # found the method that matches the argument types
        mid = repr(mtd)
        if mid not in _mids: continue

      else: # try other possible methods
        mtds = find_mtds_by_name(io.cls, io.mtd)
        argn = len(io.vals)
        min_gap = argn
        for mtd in mtds:
          _gap = abs((argn - (0 if mtd.is_static else 1)) - len(mtd.params))
          if _gap <= min_gap: # eq is needed for zero parameter
            min_gap = _gap
            mid = repr(mtd)
            if mid not in _mids: mid = None

      call_stack.append(mid)
      # ignore methods that are not declared in the template
      if not mid: continue

    if isinstance(io, sample.CallEnt):
      mid = mid + "_ent()"
    else: # sample.CallExt
      mid = mid + "_ext()"

    vals = []
    for val in io.vals:
      kind = sample.kind(val)
      if type(kind) is type: val = str(val)

      # every occurrence of constant string will be uniquely allocated,
      # hence different hash => assign unique obj_cnt
      # also, primitive value doesn't have hash,
      # so we can't compare via obj array; just assign unique obj_cnt

      ## 1) primitive, including string
      # 2) this object never occurs
      #if type(kind) is type or val not in objs:
      if val not in objs:
        obj_cnt = obj_cnt + 1
        objs[val] = obj_cnt
      vals.append(str(objs[val]))

    buf.write("""
      log = (int[P]){{ {} }};
      write_log@log(log);
    """.format(", ".join([mid] + vals)))

  buf.write("""
    int len_log = get_log_cnt@log();
    reset_log_cnt@log();
  """)
  global max_objs
  max_objs = max(max_objs, obj_cnt)

  # invoke class initializers
  for cls in util.flatten_classes(tmpl.classes, "inners"):
    clinit = cls.mtd_by_sig(C.J.CLINIT)
    if not clinit: continue
    # to only call the base class's <clinit>
    if clinit.clazz != cls: continue
    buf.write("  {}();\n".format(trans_mname(unicode(repr(cls)), clinit.name)))

  # execute template's *main*
  cname = unicode(repr(main.clazz))
  mname = main.name
  arg_typs = main.param_typs
  params = main.params + [ (C.J.z, u"logging") ]
  args = ", ".join(sig_match(params, []))
  buf.write("\n  {}({});\n".format(trans_mname(cname, mname, arg_typs), args))

  buf.write("assert len_log == get_log_cnt@log();")
  buf.write("\n}\n")
  with open(sk_path, 'w') as f:
    f.write(buf.getvalue())
    logging.info("encoding " + f.name)
  buf.close()