def _inspect_node(node, t): if isinstance(node, Structured): dtform, appTs = match(t, ("TData(dt, apps)", tuple2)) # Collect instantiations apps = app_map(dtform, appTs) adt = extrinsic(TrueRepresentation, dtform) assert isinstance(node, adt), "%s %r is not a %s" % ( type(node), node, adt) # If this is not a value type, record its index if not dtform.opts.valueType: assert not has_extrinsic(Location, node), \ "Multiply used %r" % (node,) state = env(Inspection) state.count += 1 add_extrinsic(Location, node, Pos(state.module, state.count)) # Inspect fields form = dtform.ctors[node._ctor_ix if len(dtform.ctors) > 1 else 0] ctor = extrinsic(TrueRepresentation, form) assert isinstance(node, ctor), "%r is not a %s" % (node, ctor) for field in form.fields: sub = getattr(node, extrinsic(Name, field)) ft = subst(apps, field.type) if not isinstance(ft, TWeak): _inspect_node(sub, ft) elif isinstance(node, list): assert isinstance(t, TArray), "Unexpected array:\n%s\nfor:\n%s" % ( node, t) et = t.elemType if not isinstance(et, TWeak): for item in node: _inspect_node(item, et)
def clone_structured(src, apps=None): ctor = instance_ctor(src) fs = [] for field in ctor.fields: fnm = extrinsic(Name, field) ft = field.type if apps: ft = subst(apps, ft) fs.append(clone_by_type(getattr(src, fnm), ft)) ctor_cls = extrinsic(TrueRepresentation, ctor) vat = env(VAT) if vat.transmute: destData = vat.transmute.get(extrinsic(FormSpec, SUPERS[ctor_cls])) if destData is not None: ctor = transmuted_ctor(src, destData) ctor_cls = extrinsic(TrueRepresentation, ctor) o = ctor_cls(*fs) for extr in vat.copiedExtrinsics: if has_extrinsic(extr, src): add_extrinsic(extr, o, extrinsic(extr, src)) if in_extrinsic_scope(Original): set_orig(o, src) vat.replacements[src] = o return o
def rewrite_by_type(obj, t): cls = t.__class__ if cls is TVar: assert isinstance(Structured, obj), "Can't rewrite unstructured %r without type info" % (obj,) rewrite_by_type(obj, t_DT(type(obj))) elif cls in (TPrim, TFunc): pass elif cls is TTuple: assert isinstance(obj, tuple) for v, tt in ezip(obj, t.tupleTypes): assert not isinstance(tt, TWeak), "TODO" rewrite_by_type(v, tt) elif cls is TData: assert isinstance(obj, extrinsic(TrueRepresentation, t.data)), "Expected %s, found %s %s" % ( t.data, type(obj), obj, ) apps = t.appTypes and app_map(t.data, t.appTypes) ctor = instance_ctor(obj) repls = env(VAT).replacements for field in ctor.fields: fnm = extrinsic(Name, field) ft = field.type if apps: ft = subst(apps, ft) val = getattr(obj, fnm) if isinstance(ft, TWeak): if val in repls: setattr(obj, fnm, repls[val]) else: rewrite_by_type(val, ft) elif cls is TArray: et = t.elemType assert isinstance(obj, list) if isinstance(et, TWeak): repls = env(VAT).replacements for i, w in enumerate(obj): if w in repls: obj[i] = repls[w] else: for s in obj: rewrite_by_type(s, et) elif cls is TWeak: assert False, "Shouldn't get here (should be rewritten in other cases)" else: assert False, "Bad type to rewrite: %r" % (t,)
def mutate_by_type(obj, t, customMutators=True): cls = t.__class__ if cls in (TVar, TPrim, TFunc, TWeak): return obj elif cls is TTuple: assert isinstance(obj, tuple) return tuple(rewrite_by_type(v, tt) for v, tt in ezip(obj, t.tupleTypes)) elif cls is TData: data = t.data assert isinstance(obj, extrinsic(TrueRepresentation, data)), "Expected %s, got %r: %r" % (data, type(obj), obj) apps = t.appTypes and app_map(data, t.appTypes) mutator = env(MUTATE) ctor = extrinsic(FormSpec, type(obj)) fts = dict((extrinsic(Name, f), subst(apps, f.type) if apps else f.type) for f in ctor.fields) if customMutators: custom = getattr(mutator, extrinsic(Name, ctor), None) if custom is None: custom = getattr(mutator, "t_" + extrinsic(Name, data), None) if custom is not None: # Scope field types for recursive mutatino old = mutator.obj, mutator.t, mutator.fts mutator.obj, mutator.t, mutator.fts = obj, t, fts obj = custom(obj) mutator.obj, mutator.t, mutator.fts = old return obj # Default to recursive mutation for field in ctor.fields: fnm = extrinsic(Name, field) ft = fts[fnm] if not isinstance(ft, TWeak): val = getattr(obj, fnm) setattr(obj, fnm, mutate_by_type(val, ft)) return obj elif cls is TArray: et = t.elemType assert isinstance(obj, list) if isinstance(et, TWeak): return obj return [mutate_by_type(o, et) for o in obj] else: assert False, "Bad type to mutate: %r" % (t,)
def visit_by_type(obj, t, customVisitors=True): cls = t.__class__ if cls in (TVar, TPrim, TFunc, TWeak): pass elif cls is TTuple: assert isinstance(obj, tuple) for v, tt in ezip(obj, t.tupleTypes): visit_by_type(v, tt) elif cls is TData: data = t.data assert isinstance(obj, extrinsic(TrueRepresentation, data)), "Expected %s, got %s %s" % (data, type(obj), obj) apps = t.appTypes and app_map(data, t.appTypes) visitor = env(VISIT) ctor = extrinsic(FormSpec, type(obj)) fts = dict((extrinsic(Name, f), subst(apps, f.type) if apps else f.type) for f in ctor.fields) if customVisitors: custom = getattr(visitor, extrinsic(Name, ctor), None) if custom is None: custom = getattr(visitor, "t_" + extrinsic(Name, data), None) if custom is not None: # Scope field types for recursive visiting old = visitor.obj, visitor.t, visitor.fts visitor.obj, visitor.t, visitor.fts = obj, t, fts custom(obj) visitor.obj, visitor.t, visitor.fts = old return # Default to recursive visits for field in ctor.fields: fnm = extrinsic(Name, field) ft = fts[fnm] if not isinstance(ft, TWeak): visit_by_type(getattr(obj, fnm), ft) elif cls is TArray: assert isinstance(obj, list) if not isinstance(t.elemType, TWeak): for o in obj: visit_by_type(o, t.elemType) else: assert False, "Bad type to visit: %r" % (t,)
def _serialize_node(node, t): # debugging if not have_env(SerialContext): in_env(SerialContext, DumpList(), lambda: _serialize_node(node, t)) return if isinstance(node, Structured): ctxt = env(SerialContext) nm = extrinsic(Name, node) if has_extrinsic(Name, node) else type(node) ctxt.append((nm, t)) assert isinstance(t, TData), "%r is not a datatype" % (t,) if not t.data.opts.valueType: env(Serialize).count += 1 # Collect instantiations apps = app_map(t.data, t.appTypes) adt = extrinsic(TrueRepresentation, t.data) assert isinstance(node, adt), "%s %r is not a %s" % ( type(node), node, adt) # Possibly write discriminator if len(t.data.ctors) > 1: ix = node._ctor_ix _write(_encode_int(ix)) form = t.data.ctors[node._ctor_ix] else: form = t.data.ctors[0] # Dump fields ctor = extrinsic(TrueRepresentation, form) assert isinstance(node, ctor), "%r is not a %s" % (node, ctor) for field in form.fields: sub = getattr(node, extrinsic(Name, field)) ft = subst(apps, field.type) if isinstance(ft, TWeak): _write_ref(sub, ft.refType) else: _serialize_node(sub, ft) ctxt.pop() elif isinstance(node, basestring): assert isinstance(t, TPrim) and isinstance(t.primType, PStr) _write(_encode_str(node)) elif isinstance(node, bool): assert isinstance(t, TPrim) and isinstance(t.primType, PBool) _write(_encode_int(1 if node else 0)) elif isinstance(node, int): assert isinstance(t, TPrim) and isinstance(t.primType, PInt) _write(_encode_int(node)) elif isinstance(node, float): assert isinstance(t, TPrim) and isinstance(t.primType, PFloat) _write(_encode_float(node)) elif isinstance(node, list): assert isinstance(t, TArray), "Unexpected array:\n%s\nfor:\n%s" % ( node, t) _write(_encode_int(len(node))) et = t.elemType if isinstance(et, TWeak): for item in node: _write_ref(item, et.refType) else: for item in node: _serialize_node(item, et) else: assert False, "Can't serialize %r" % (node,)
def read_node(t, path): if isinstance(t, TData): state = env(Deserialize) assert type(t.data) is DataType, "Bad TData containing %r" % (t.data,) apps = app_map(t.data, t.appTypes) ctors = t.data.ctors if len(ctors) > 1: form = ctors[read_int()] else: form = ctors[0] assert isinstance(form, Ctor), "Unexpected form %s" % (form,) ctor = extrinsic(TrueRepresentation, form) # Bleh. val = ctor(*[None for f in form.fields]) if not t.data.opts.valueType: state.index += 1 state.ownMap[state.index] = val add_extrinsic(Location, val, Pos(state.module, state.index)) for field in form.fields: fnm = extrinsic(Name, field) ft = subst(apps, field.type) child = read_node(ft, (val, fnm)) setattr(val, fnm, child) return val elif isinstance(t, TPrim): return match(t.primType, ("PInt()", read_int), ("PFloat()", read_float), ("PStr()", read_str), ("PBool()", read_bool)) elif isinstance(t, TWeak): state = env(Deserialize) depIndex = read_int() if depIndex == 0: index = read_int() if index == 0: return state.module elif index in state.ownMap: return state.ownMap[index] else: # Resolve later state.forwardRefs.setdefault(index, []).append(path) return 'forward ref' else: if depIndex > state.depsSeen: assert depIndex == state.depsSeen+1, "skipped a dep?!" depHash = state.file.read(64) assert depHash == extrinsic(ModDigest, state.deps[depIndex-1]) state.depsSeen += 1 depMod = state.deps[depIndex-1] index = read_int() if index == 0: return depMod else: dest = extrinsic(ModIndex, depMod)[index-1] return dest elif isinstance(t, TArray): elemT = t.elemType n = read_int() elems = [] for i in xrange(n): elems.append(read_node(elemT, (elems, i))) return elems else: assert False, "%r is not a type" % (t,)