def sanitize_id(dot_id): pkg, cls, mtd = util.explode_mname(dot_id) if cls and util.is_class_name(cls) and class_lookup(cls): clazz = class_lookup(cls) if clazz.pkg and pkg and clazz.pkg != pkg: # to avoid u'' != None raise Exception("wrong package", pkg, clazz.pkg) return '.'.join([cls, mtd]) return dot_id
def log_param( (ty, nm) ): ty = trans_ty(ty) if util.is_class_name(ty): if nm == C.J.N: return (u'', u'') else: nm_hash = nm + u"_hash" retrival = u""" int {nm_hash} = 0; if ({nm} != null) {{ {nm_hash} = {nm}.hash; }} """.format(**locals()) return (retrival, nm_hash) elif ty in [C.SK.z] + C.primitives: return (u'', nm) else: return (u'', u'')
def trans_e(mtd, e): curried = partial(trans_e, mtd) buf = cStringIO.StringIO() if e.kind == C.E.GEN: if e.es: buf.write("{| ") buf.write(" | ".join(map(curried, e.es))) buf.write(" |}") else: buf.write(C.T.HOLE) elif e.kind == C.E.ID: if hasattr(e, "ty"): buf.write(trans_ty(e.ty) + ' ') fld = None if mtd and e.id not in mtd.param_vars: fld = find_fld(mtd.clazz.name, e.id) if fld: # fname -> self.new_fname (unless the field is static) new_fname = trans_fname(fld.clazz.name, e.id, fld.is_static) if fld.is_static: # access to the static field inside the same class if fld.clazz.name == mtd.clazz.name: buf.write(e.id) # o.w., e.g., static constant in an interface, call the accessor else: buf.write(new_fname + "()") else: buf.write('.'.join([C.SK.self, new_fname])) elif e.id in [C.J.THIS, C.J.SUP]: buf.write(C.SK.self) elif util.is_str(e.id): # constant string, such as "Hello, World" str_init = trans_mname(C.J.STR, C.J.STR, [u"char[]", C.J.i, C.J.i]) s_hash = hash(e.id) % 256 # hash string value itself buf.write("{}(new Object(hash={}), {}, 0, {})".format(str_init, s_hash, e.id, len(e.id))) else: buf.write(e.id) elif e.kind == C.E.UOP: buf.write(' '.join([e.op, curried(e.e)])) elif e.kind == C.E.BOP: buf.write(' '.join([curried(e.le), e.op, curried(e.re)])) elif e.kind == C.E.DOT: # with package names, e.g., javax.swing.SwingUtilities if util.is_class_name(e.re.id) and class_lookup(e.re.id): buf.write(curried(e.re)) elif e.re.id == C.J.THIS: # ClassName.this buf.write(C.SK.self) else: rcv_ty = typ_of_e(mtd, e.le) fld = find_fld(rcv_ty, e.re.id) new_fname = trans_fname(rcv_ty, e.re.id, fld.is_static) if fld.is_static: # access to the static field inside the same class if mtd and rcv_ty == mtd.clazz.name: buf.write(e.re.id) # o.w., e.g., static constant in an interface, call the accessor else: buf.write(new_fname + "()") else: buf.write('.'.join([curried(e.le), new_fname])) elif e.kind == C.E.IDX: buf.write(curried(e.e) + '[' + curried(e.idx) + ']') elif e.kind == C.E.NEW: if e.e.kind == C.E.CALL: ty = typ_of_e(mtd, e.e.f) cls = class_lookup(ty) if cls and cls.has_init: arg_typs = map(partial(typ_of_e, mtd), e.e.a) mname = trans_mname(cls.name, cls.name, arg_typs) obj = "alloc@log({})".format(cls.id) args = [obj] + map(unicode, map(curried, e.e.a)) buf.write("{}({})".format(mname, ", ".join(args))) else: # collection or Object buf.write(C.J.NEW + ' ' + trans_ty(ty) + "()") else: # o.w., array initialization, e.g., new int[] { ... } buf.write(str(e.init)) elif e.kind == C.E.CALL: arg_typs = map(partial(typ_of_e, mtd), e.a) def trans_call(callee, rcv_ty, rcv): if callee.is_static: rcv = None args = util.rm_none([rcv] + map(curried, e.a)) mid = trans_mname(rcv_ty, callee.name, arg_typs) return u"{}({})".format(mid, ", ".join(args)) def dynamic_dispatch(rcv_ty, rcv, acc, callee): _dispatched = trans_call(callee, callee.clazz.name, rcv) _guarded = "{}.__cid == {} ? {}".format(rcv, callee.clazz.id, _dispatched) return "({} : {})".format(_guarded, acc) if e.f.kind == C.E.DOT: # rcv.mid rcv_ty = typ_of_e(mtd, e.f.le) rcv = curried(e.f.le) mname = e.f.re.id mtd_callees = find_mtds_by_sig(rcv_ty, mname, arg_typs) if mtd_callees and 1 < len(mtd_callees): # needs dynamic dispatch curried_dispatch = partial(dynamic_dispatch, rcv_ty, rcv) # TODO: use least upper bound? default_v = util.default_value(mtd_callees[0].typ) buf.write(reduce(curried_dispatch, mtd_callees, default_v)) elif mtd_callees and 1 == len(mtd_callees): mtd_callee = mtd_callees[0] buf.write(trans_call(mtd_callee, rcv_ty, rcv)) else: # unresolved, maybe library method mid = trans_mname(rcv_ty, mname, arg_typs) args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) else: # mid mname = e.f.id # pre-defined meta information or Sketch primitive functions if mname in C.typ_arrays + [u"minimize"]: mid = mname rcv = None args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) elif mname == C.J.SUP and mtd.is_init: # super(...) inside <init> sup = class_lookup(mtd.clazz.sup) mid = trans_mname(sup.name, sup.name, arg_typs) rcv = C.SK.self args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) else: # member methods mtd_callees = find_mtds_by_sig(mtd.clazz.name, mname, arg_typs) if mtd_callees and 1 < len(mtd_callees): # needs dynamic dispatch curried_dispatch = partial(dynamic_dispatch, mtd.clazz.name, C.SK.self) # TODO: use least upper bound? default_v = util.default_value(mtd_callees[0].typ) buf.write(reduce(curried_dispatch, mtd_callees, default_v)) elif mtd_callees and 1 == len(mtd_callees): mtd_callee = mtd_callees[0] buf.write(trans_call(mtd_callee, mtd.clazz.name, C.SK.self)) else: # unresolved, maybe library method mid = trans_mname(mtd.clazz.name, mname, arg_typs) args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) elif e.kind == C.E.CAST: # since a family of classes is merged, simply ignore the casting buf.write(curried(e.e)) elif e.kind == C.E.INS_OF: ty = typ_of_e(mtd, e.ty) cls = class_lookup(ty) if cls: buf.write(curried(e.e) + ".__cid == " + str(cls.id)) else: logging.debug("unknown type: {}".format(ty)) buf.write("0") else: buf.write(str(e)) return buf.getvalue()
def col_to_struct(cls): buf = cStringIO.StringIO() cname = cls.name sname = trans_ty(cname) global _collections if sname in _collections: logging.debug("collection: {} (duplicated)".format(cname)) return u'' else: _collections.add(sname) logging.debug("collection: " + cname) buf.write("struct ${sname} {\n int idx;\n") if C.J.MAP in cname: _, k, v = util.of_collection(cname) k = trans_ty(k) v = trans_ty(v) # Map<K,V> -> struct Map_K_V { int idx; K[S] key; V[S] val; } buf.write(" ${k}[S] key;\n ${v}[S] val;\n}\n") # Map<K,V>.containsKey -> containsKey_Map_K_V buf.write(""" bit {} (${{sname}} map, ${{k}} k) {{ int i; for (i = 0; map.val[i] != null && i < S; i++) {{ if (map.key[i] == k) return 1; }} return 0; }} """.format(trans_mname(cname, u"containsKey", [k]))) # Map<K,V>.get -> get_Map_K_V buf.write(""" ${{v}} {} (${{sname}} map, ${{k}} k) {{ int i; for (i = 0; map.val[i] != null && i < S; i++) {{ if (map.key[i] == k) return map.val[i]; }} return null; }} """.format(trans_mname(cname, u"get", [k]))) # Map<K,V>.put -> put_Map_K_V buf.write(""" void {} (${{sname}} map, ${{k}} k, ${{v}} v) {{ map.key[map.idx] = k; map.val[map.idx] = v; map.idx = (map.idx + 1) % S; }} """.format(trans_mname(cname, u"put", [k, v]))) # Map<K,V>.clear -> clear_Map_K_V if util.is_class_name(k): default_k = "null" else: default_k = "0" buf.write(""" void {} (${{sname}} map) {{ map.idx = 0; for (int i = 0; i < S; i++) {{ map.key[i] = {}; map.val[i] = null; }} }} """.format(trans_mname(cname, u"clear", []), default_k)) else: collection, t = util.of_collection(cname) t = trans_ty(t) if C.J.QUE in collection: buf.write(" int head;\n") # Collection<T> -> struct Collection_T { int idx; T[S] elts; } buf.write(" ${t}[S] elts;\n}\n") if C.J.STK in collection: # Stack<T>.peek -> peek_Stack_T buf.write(""" ${{t}} {} (${{sname}} stk) {{ if (stk.idx == 0) return null; ${{t}} top = stk.elts[stk.idx - 1]; return top; }} """.format(trans_mname(cname, u"peek", []))) # Stack<T>.push -> push_Stack_T buf.write(""" ${{t}} {} (${{sname}} stk, ${{t}} elt) {{ stk.elts[stk.idx] = elt; stk.idx = (stk.idx + 1) % S; return elt; }} """.format(trans_mname(cname, u"push", [t]))) # Stack<T>.pop -> pop_Stack_T buf.write(""" ${{t}} {} (${{sname}} stk) {{ if (stk.idx == 0) return null; stk.idx = stk.idx - 1; ${{t}} top = stk.elts[stk.idx]; stk.elts[stk.idx] = null; return top; }} """.format(trans_mname(cname, u"pop", []))) elif C.J.QUE in collection: # Queue<T>.add -> add_Queue_T buf.write(""" bit {} (${{sname}} que, ${{t}} elt) {{ que.elts[que.idx] = elt; que.idx = (que.idx + 1) % S; return true; }} """.format(trans_mname(cname, u"add", [t]))) # Queue<T>.remove -> remove_Queue_T buf.write(""" ${{t}} {} (${{sname}} que) {{ if (que.head == que.idx) return null; ${{t}} top = que.elts[que.head]; que.elts[que.head] = null; que.head = (que.head + 1) % S; return top; }} """.format(trans_mname(cname, u"remove", []))) # Queue<T>.isEmpty -> isEmpty_Queue_T buf.write(""" bit {} (${{sname}} que) {{ return que.head == que.idx; }} """.format(trans_mname(cname, u"isEmpty", []))) elif C.J.LST in collection: # List<T>.add -> add_List_T buf.write(""" bit {} (${{sname}} lst, ${{t}} elt) {{ lst.elts[lst.idx] = elt; lst.idx = (lst.idx + 1) % S; return true; }} """.format(trans_mname(cname, u"add", [t]))) # List<T>.remove(T) -> remove_List_T_T buf.write(""" bit {} (${{sname}} lst, ${{t}} elt) {{ int i; for (i = 0; lst.elts[i] != null && i < S; i++) {{ if (lst.elts[i] == elt) {{ lst.elts[i] = null; int j; for (j = i + 1; lst.elts[j] != null && j < lst.idx; j++) {{ lst.elts[j-1] = lst.elts[j]; }} lst.idx = (lst.idx - 1) % S; return true; }} }} return false; }} """.format(trans_mname(cname, u"remove", [t]))) # List<T>.remove(int) -> remove_List_T_int buf.write(""" ${{t}} {} (${{sname}} lst, int index) {{ ${{t}} res = null; if (0 <= index && index < lst.idx) {{ res = lst.elts[index]; lst.elts[index] = null; int i; for (i = index + 1; lst.elts[i] != null && i < lst.idx; i++) {{ lst.elts[i-1] = lst.elts[i]; }} lst.idx = (lst.idx - 1) % S; }} return res; }} """.format(trans_mname(cname, u"remove", [C.J.i]))) # List<T>.get -> get_List_T buf.write(""" ${{t}} {} (${{sname}} lst, int index) {{ ${{t}} res = null; if (0 <= index && index < lst.idx) {{ res = lst.elts[index]; }} return res; }} """.format(trans_mname(cname, u"get", [C.J.i]))) # List<T>.isEmpty -> isEmpty_List_T buf.write(""" bit {} (${{sname}} lst) {{ return lst.idx == 0; }} """.format(trans_mname(cname, u"isEmpty", []))) return T(buf.getvalue()).safe_substitute(locals())
def to_sk(pgr, sk_dir): # clean up result directory if os.path.isdir(sk_dir): util.clean_dir(sk_dir) else: os.makedirs(sk_dir) # reset global variables so that we can run this encoding phase per demo reset() # update global constants # TODO: conservative analysis of possible length of collections # TODO: counting .add() calls or something? magic_S = 7 global _const _const = u""" int S = {}; // length of arrays for Java collections """.format(magic_S) # type.sk logging.info("building class hierarchy") pgr.consist() # merge all classes and interfaces, except for primitive types clss, _ = util.partition(lambda c: util.is_class_name(c.name), classes()) bases = rm_subs(clss) gen_type_sk(sk_dir, bases) # cls.sk cls_sks = [] for cls in pgr.classes: # skip the collections, which will be encoded at type.sk if repr(cls).split('_')[0] in C.collections: continue cls_sk = gen_cls_sk(sk_dir, cls) if cls_sk: cls_sks.append(cls_sk) # log.sk gen_log_sk(sk_dir, pgr) # main.sk that imports all the other sketch files buf = cStringIO.StringIO() # --bnd-cbits: the number of bits for integer holes bits = max(5, int(math.ceil(math.log(len(methods()), 2)))) buf.write("pragma options \"--bnd-cbits {}\";\n".format(bits)) # --bnd-unroll-amnt: the unroll amount for loops unroll_amnt = None # use a default value if not set unroll_amnt = magic_S # TODO: other criteria? if unroll_amnt: buf.write("pragma options \"--bnd-unroll-amnt {}\";\n".format(unroll_amnt)) # --bnd-inline-amnt: bounds inlining to n levels of recursion inline_amnt = None # use a default value if not set # setting it 1 means there is no recursion if inline_amnt: buf.write("pragma options \"--bnd-inline-amnt {}\";\n".format(inline_amnt)) buf.write("pragma options \"--bnd-bound-mode CALLSITE\";\n") sks = ["log.sk", "type.sk"] + cls_sks for sk in sks: buf.write("include \"{}\";\n".format(sk)) # TODO: make harness (if not exists) with open(os.path.join(sk_dir, "main.sk"), 'w') as f: f.write(buf.getvalue()) logging.info("encoding " + f.name) buf.close()
def find_setter(smpls, typs, Fname): mtds_ent_typs = find_mtds_ent_typs(smpls, typs) mtds_w_fname = filter(lambda mtd: Fname in mtd, mtds_ent_typs) mtds = filter(lambda mtd: not util.is_class_name(mtd), mtds_w_fname) if any(mtds): return mtds.pop() else: return "set" + Fname
def find_getter(smpls, typs, Fname, prefix="get"): mtds_ext_typs = find_mtds_ext_typs(smpls, typs) mtds_w_fname = filter(lambda mtd: Fname in mtd, mtds_ext_typs) mtds = filter(lambda mtd: not util.is_class_name(mtd), mtds_w_fname) if any(mtds): return mtds.pop() else: return prefix + Fname
def trans_e(mtd, e): curried = partial(trans_e, mtd) buf = cStringIO.StringIO() if e.kind == C.E.ANNO: anno = e.anno if anno.name == C.A.NEW: pass # TODO elif anno.name == C.A.OBJ: buf.write("retrieve_{}@log({})".format(util.sanitize_ty(anno.typ), anno.idx)) # @Compare(exps) => {| exps[0] (< | <= | == | != | >= | >) exps[1] |} # @CompareString(exps) => exps[0].eqauls(exps[1]) elif anno.name in [C.A.CMP, C.A.CMP_STR]: le = curried(anno.exps[0]) re = curried(anno.exps[1]) if anno.name == C.A.CMP: buf.write("{| " + le + " (< | <= | == | != | >= | >) " + re + " |}") else: buf.write("{}({},{})".format(trans_mname(C.J.STR, u"equals"), le, re)) elif e.kind == C.E.GEN: if e.es: buf.write("{| ") buf.write(" | ".join(map(curried, e.es))) buf.write(" |}") else: buf.write(C.T.HOLE) elif e.kind == C.E.ID: if hasattr(e, "ty"): buf.write(trans_ty(e.ty) + ' ') fld = None if mtd and e.id not in mtd.param_vars: fld = find_fld(mtd.clazz.name, e.id) if fld: # fname -> self.new_fname (unless the field is static) new_fname = trans_fname(fld.clazz.name, e.id, fld.is_static) if fld.is_static: # access to the static field inside the same class if fld.clazz.name == mtd.clazz.name: buf.write(e.id) # o.w., e.g., static constant in an interface, call the accessor else: buf.write(new_fname + "()") else: buf.write('.'.join([C.SK.self, new_fname])) elif e.id in [C.J.THIS, C.J.SUP]: buf.write(C.SK.self) elif util.is_str(e.id): # constant string, such as "Hello, World" str_init = trans_mname(C.J.STR, C.J.STR, [u"char[]", C.J.i, C.J.i]) s_hash = hash(e.id) % 256 # hash string value itself buf.write("{}(new Object(hash={}), {}, 0, {})".format(str_init, s_hash, e.id, len(e.id))) else: buf.write(e.id) elif e.kind == C.E.UOP: buf.write(' '.join([e.op, curried(e.e)])) elif e.kind == C.E.BOP: buf.write(' '.join([curried(e.le), e.op, curried(e.re)])) elif e.kind == C.E.DOT: # with package names, e.g., javax.swing.SwingUtilities if util.is_class_name(e.re.id) and class_lookup(e.re.id): buf.write(curried(e.re)) elif e.re.id == C.J.THIS: # ClassName.this buf.write(C.SK.self) else: rcv_ty = typ_of_e(mtd, e.le) fld = find_fld(rcv_ty, e.re.id) new_fname = trans_fname(rcv_ty, e.re.id, fld.is_static) if fld.is_static: # access to the static field inside the same class if mtd and rcv_ty == mtd.clazz.name: buf.write(e.re.id) # o.w., e.g., static constant in an interface, call the accessor else: buf.write(new_fname + "()") else: buf.write('.'.join([curried(e.le), new_fname])) elif e.kind == C.E.IDX: buf.write(curried(e.e) + '[' + curried(e.idx) + ']') elif e.kind == C.E.NEW: if e.e.kind == C.E.CALL: ty = typ_of_e(mtd, e.e.f) cls = class_lookup(ty) if cls and cls.has_init: arg_typs = map(partial(typ_of_e, mtd), e.e.a) mname = trans_mname(cls.name, cls.name, arg_typs) obj = "alloc@log({})".format(cls.id) args = [obj] + map(unicode, map(curried, e.e.a)) buf.write("{}({})".format(mname, ", ".join(args))) else: # collection or Object buf.write(C.J.NEW + ' ' + trans_ty(ty) + "()") else: # o.w., array initialization, e.g., new int[] { ... } buf.write(str(e.init)) elif e.kind == C.E.CALL: arg_typs = map(partial(typ_of_e, mtd), e.a) 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)) def dynamic_dispatch(rcv_ty, rcv, acc, callee): _dispatched = trans_call(callee, callee.clazz.name, rcv) _guarded = "{}.__cid == {} ? {}".format(rcv, callee.clazz.id, _dispatched) return "({} : {})".format(_guarded, acc) if e.f.kind == C.E.DOT: # rcv.mid rcv_ty = typ_of_e(mtd, e.f.le) rcv = curried(e.f.le) mname = e.f.re.id mtd_callees = find_mtds_by_sig(rcv_ty, mname, arg_typs) if mtd_callees and 1 < len(mtd_callees): # needs dynamic dispatch curried_dispatch = partial(dynamic_dispatch, rcv_ty, rcv) # TODO: use least upper bound? default_v = util.default_value(mtd_callees[0].typ) buf.write(reduce(curried_dispatch, mtd_callees, default_v)) elif mtd_callees and 1 == len(mtd_callees): mtd_callee = mtd_callees[0] buf.write(trans_call(mtd_callee, rcv_ty, rcv)) else: # unresolved, maybe library method mid = trans_mname(rcv_ty, mname, arg_typs) args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) else: # mid mname = e.f.id # pre-defined meta information or Sketch primitive functions if mname in C.typ_arrays + [u"minimize"]: mid = mname rcv = None args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) elif mname == C.J.SUP and mtd.is_init: # super(...) inside <init> sup = class_lookup(mtd.clazz.sup) mid = trans_mname(sup.name, sup.name, arg_typs) rcv = C.SK.self args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) else: # member methods mtd_callees = find_mtds_by_sig(mtd.clazz.name, mname, arg_typs) if mtd_callees and 1 < len(mtd_callees): # needs dynamic dispatch curried_dispatch = partial(dynamic_dispatch, mtd.clazz.name, C.SK.self) # TODO: use least upper bound? default_v = util.default_value(mtd_callees[0].typ) buf.write(reduce(curried_dispatch, mtd_callees, default_v)) elif mtd_callees and 1 == len(mtd_callees): mtd_callee = mtd_callees[0] buf.write(trans_call(mtd_callee, mtd.clazz.name, C.SK.self)) else: # unresolved, maybe library method mid = trans_mname(mtd.clazz.name, mname, arg_typs) args = util.rm_none([rcv] + map(curried, e.a)) buf.write("{}({})".format(mid, ", ".join(args))) elif e.kind == C.E.CAST: # since a family of classes is merged, simply ignore the casting buf.write(curried(e.e)) elif e.kind == C.E.INS_OF: ty = typ_of_e(mtd, e.ty) cls = class_lookup(ty) if cls: buf.write(curried(e.e) + ".__cid == " + str(cls.id)) else: logging.debug("unknown type: {}".format(ty)) buf.write("0") else: buf.write(str(e)) return buf.getvalue()
def default_init(fld): if util.is_class_name(fld.typ): return C.J.NEW + ' ' + trans_init(fld.typ, [], []) else: return '0'
def to_sk(cmd, smpls, tmpl, sk_dir): # clean up result directory if os.path.isdir(sk_dir): util.clean_dir(sk_dir) else: os.makedirs(sk_dir) # reset global variables so that we can run this encoding phase per demo reset() # update global constants def logged(mtd): if mtd.is_init: return False clss = util.flatten_classes([mtd.clazz], "subs") return sample.mtd_appears(smpls, clss, mtd.name) mtds = filter(logged, methods()) if mtds: n_params = 2 + max(map(len, map(op.attrgetter("params"), mtds))) else: # no meaningful logs in the sample? n_params = 2 n_evts = sample.max_evts(smpls) if cmd == "android": n_views = sample.max_views(smpls) magic_S = max(3, n_evts + 1, n_views) else: magic_S = max(5, n_evts + 1) # at least 5, just in case n_ios = sample.max_IOs(smpls) global _const _const = u""" int P = {}; // length of parameters (0: (>|<)mid, 1: receiver, 2...) int S = {}; // length of arrays for Java collections int N = {}; // length of logs """.format(n_params, magic_S, n_ios) # type.sk logging.info("building class hierarchy") tmpl.consist() # merge all classes and interfaces, except for primitive types clss, _ = util.partition(lambda c: util.is_class_name(c.name), classes()) bases = rm_subs(clss) gen_type_sk(sk_dir, bases) # cls.sk cls_sks = [] for cls in tmpl.classes: # skip the collections, which will be encoded at type.sk if repr(cls).split('_')[0] in C.collections: continue cls_sk = gen_cls_sk(sk_dir, smpls, cls) if cls_sk: cls_sks.append(cls_sk) # sample_x.sk smpl_sks = [] for smpl in smpls: smpl_sk = "sample_" + smpl.name + ".sk" smpl_sks.append(smpl_sk) sk_path = os.path.join(sk_dir, smpl_sk) gen_smpl_sk(sk_path, smpl, tmpl, tmpl.harness(smpl.name)) # log.sk gen_log_sk(sk_dir, tmpl) # sample.sk that imports all the other sketch files buf = cStringIO.StringIO() # deprecated as we use regex generator for class/method roles ## --bnd-cbits: the number of bits for integer holes #bits = max(5, int(math.ceil(math.log(len(methods()), 2)))) #buf.write("pragma options \"--bnd-cbits {}\";\n".format(bits)) # --bnd-unroll-amnt: the unroll amount for loops unroll_amnt = max(n_params, magic_S) buf.write("pragma options \"--bnd-unroll-amnt {}\";\n".format(unroll_amnt)) # --bnd-inline-amnt: bounds inlining to n levels of recursion inline_amnt = None # use a default value if not set if cmd == "android": #inline_amnt = 2 # depth of View hierarchy (at findViewByTraversal) inline_amnt = 1 # no recursion for flat Views elif cmd == "gui": # setting it 1 means there is no recursion inline_amnt = 1 if inline_amnt: buf.write("pragma options \"--bnd-inline-amnt {}\";\n".format(inline_amnt)) buf.write("pragma options \"--bnd-bound-mode CALLSITE\";\n") sks = ["log.sk", "type.sk"] + cls_sks + smpl_sks for sk in sks: buf.write("include \"{}\";\n".format(sk)) with open(os.path.join(sk_dir, "sample.sk"), 'w') as f: f.write(buf.getvalue()) logging.info("encoding " + f.name) buf.close()