import std/typetraits, preserves, std/tables, std/tables type SturdyRef*[E = void] {.record: "ref".} = ref object ## ```` `oid`*: Preserve[E] `caveatChain`*: seq[Attenuation[E]] `sig`*: seq[byte] Attenuation*[E = void] = seq[Caveat[E]] ## ``[ Caveat ... ]`` CaveatKind* {.pure.} = enum `Rewrite`, `Alts` Caveat*[E = void] = ref object ## ``/ Rewrite / Alts`` case kind*: CaveatKind of CaveatKind.`Rewrite`: `rewrite`*: Rewrite[E] of CaveatKind.`Alts`: `alts`*: Alts[E] Rewrite*[E = void] {.record: "rewrite".} = ref object ## ```` `pattern`*: Pattern[E] `template`*: Template[E] Alts*[E = void] {.record: "or".} = ref object ## ```` `alternatives`*: seq[Rewrite[E]] Oid* = distinct BiggestInt ## ``int`` WirerefKind* {.pure.} = enum `mine`, `yours` WireRefmine* = tuple[`0`: BiggestInt, `oid`: Oid] WireRefyours*[E = void] = tuple[`1`: BiggestInt, `oid`: Oid, `attenuation`: seq[Caveat[E]]] WireRef*[E = void] = ref object ## ``/ @mine [0 @oid Oid] / @yours [1 @oid Oid @attenuation Caveat ...]`` case kind*: WirerefKind of WirerefKind.`mine`: `mine`*: WireRefmine of WirerefKind.`yours`: `yours`*: WireRefyours[E] ConstructorspecKind* {.pure.} = enum `Crec`, `Carr`, `Cdict` ConstructorSpec*[E = void] = ref object ## ``/ CRec / CArr / CDict`` case kind*: ConstructorspecKind of ConstructorspecKind.`Crec`: `crec`*: CRec[E] of ConstructorspecKind.`Carr`: `carr`*: CArr of ConstructorspecKind.`Cdict`: `cdict`*: CDict CRec*[E = void] {.record: "rec".} = ref object ## ```` `label`*: Preserve[E] `arity`*: BiggestInt CArr* {.record: "arr".} = ref object ## ```` `arity`*: BiggestInt CDict* {.record: "dict".} = object ## ```` discard Lit*[E = void] {.record: "lit".} = ref object ## ```` `value`*: Preserve[E] PatternKind* {.pure.} = enum `Pdiscard`, `Patom`, `Pembedded`, `Pbind`, `Pand`, `Pnot`, `Lit`, `Pcompound` Pattern*[E = void] = ref object ## ``/ PDiscard / PAtom / PEmbedded / PBind / PAnd / PNot / Lit / PCompound`` case kind*: PatternKind of PatternKind.`Pdiscard`: `pdiscard`*: PDiscard of PatternKind.`Patom`: `patom`*: PAtom of PatternKind.`Pembedded`: discard of PatternKind.`Pbind`: `pbind`*: PBind[E] of PatternKind.`Pand`: `pand`*: PAnd[E] of PatternKind.`Pnot`: `pnot`*: PNot[E] of PatternKind.`Lit`: `lit`*: Lit[E] of PatternKind.`Pcompound`: `pcompound`*: PCompound[E] PDiscard* {.record: "_".} = object ## ``<_>`` discard PAtom* {.pure.} = enum ## ``/ =<Boolean> / =<Float> / =<Double> / =<SignedInteger> / =<String> / =<ByteString> / =<Symbol>`` `Boolean`, `Float`, `Double`, `Signedinteger`, `String`, `Bytestring`, `Symbol` PBind*[E = void] {.record: "bind".} = ref object ## ```` `pattern`*: Pattern[E] PAnd*[E = void] {.record: "and".} = ref object ## ```` `patterns`*: seq[Pattern[E]] PNot*[E = void] {.record: "not".} = ref object ## ```` `pattern`*: Pattern[E] PCompound*[E = void] {.record: "compound".} = ref object ## ```` `ctor`*: ConstructorSpec[E] `members`*: PCompoundMembers[E] PCompoundMembers*[E = void] = TableRef[Preserve[E], Pattern[E]] ## ``{any : Pattern ...:...}`` TemplateKind* {.pure.} = enum `Tattenuate`, `Tref`, `Lit`, `Tcompound` Template*[E = void] = ref object ## ``/ TAttenuate / TRef / Lit / TCompound`` case kind*: TemplateKind of TemplateKind.`Tattenuate`: `tattenuate`*: TAttenuate[E] of TemplateKind.`Tref`: `tref`*: TRef of TemplateKind.`Lit`: `lit`*: Lit[E] of TemplateKind.`Tcompound`: `tcompound`*: TCompound[E] TAttenuate*[E = void] {.record: "attenuate".} = ref object ## ```` `template`*: Template[E] `attenuation`*: Attenuation[E] TRef* {.record: "ref".} = ref object ## ```` `binding`*: BiggestInt TCompound*[E = void] {.record: "compound".} = ref object ## ```` `ctor`*: ConstructorSpec[E] `members`*: TCompoundMembers[E] TCompoundMembers*[E = void] = TableRef[Preserve[E], Template[E]] ## ``{any : Template ...:...}`` proc `sturdyRef`*[E = void](`oid`: Preserve[E]; `caveatChain`: Preserve[E]; `sig`: seq[byte] | Preserve[E]): Preserve[E] = ## Preserves constructor for ``SturdyRef``. initRecord[E](symbol[E]("ref"), toPreserve(`oid`, E), toPreserve(`caveatChain`, E), toPreserve(`sig`, E)) proc toPreserveHook*(`sturdyref`: SturdyRef; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("ref"), toPreserve(`sturdyref`.`oid`, E), toPreserve(`sturdyref`.`caveatChain`, E), toPreserve(`sturdyref`.`sig`, E)) proc toPreserveHook*(v: Caveat; E: typedesc): Preserve[E] = case v.kind of CaveatKind.`Rewrite`: toPreserve(v.`rewrite`, E) of CaveatKind.`Alts`: toPreserve(v.`alts`, E) proc fromPreserveHook*[E](v: var Caveat; pr: Preserve[E]): bool = if isRecord(pr) and pr.label.isSymbol("Rewrite"): v = Caveat(kind: CaveatKind.`Rewrite`) result = fromPreserve(v.`rewrite`, pr) elif isRecord(pr) and pr.label.isSymbol("Alts"): v = Caveat(kind: CaveatKind.`Alts`) result = fromPreserve(v.`alts`, pr) proc `rewrite`*[E = void](`pattern`: Pattern | Preserve[E]; `template`: Template | Preserve[E]): Preserve[E] = ## Preserves constructor for ``Rewrite``. initRecord[E](symbol[E]("rewrite"), toPreserve(`pattern`, E), toPreserve(`template`, E)) proc toPreserveHook*(`rewrite`: Rewrite; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("rewrite"), toPreserve(`rewrite`.`pattern`, E), toPreserve(`rewrite`.`template`, E)) proc `alts`*[E = void](`alternatives`: Preserve[E]): Preserve[E] = ## Preserves constructor for ``Alts``. initRecord[E](symbol[E]("or"), toPreserve(`alternatives`, E)) proc toPreserveHook*(`alts`: Alts; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("or"), toPreserve(`alts`.`alternatives`, E)) proc toPreserveHook*(v: WireRef; E: typedesc): Preserve[E] = case v.kind of WireRefKind.`mine`: Preserve[E](kind: pkSequence, sequence: @[ Preserve[E](kind: pkSignedInteger, int: 0'i64), toPreserve(v.`mine`.`oid`, E)]) of WireRefKind.`yours`: Preserve[E](kind: pkSequence, sequence: @[ Preserve[E](kind: pkSignedInteger, int: 1'i64), toPreserve(v.`yours`.`oid`, E)] & toPreserve(v.`yours`.`attenuation`, E).sequence) proc fromPreserveHook*[E](v: var WireRef; pr: Preserve[E]): bool = if isSequence(pr) and len(pr) == 2 and (pr[0].kind == pkSignedInteger and pr[0].int == 0'i64): v = WireRef(kind: WireRefKind.`mine`) result = fromPreserve(v.`mine`, pr) elif isSequence(pr) and len(pr) >= 2 and (pr[0].kind == pkSignedInteger and pr[0].int == 1'i64): v = WireRef(kind: WireRefKind.`yours`) result = fromPreserve(v.`yours`, pr) proc toPreserveHook*(v: ConstructorSpec; E: typedesc): Preserve[E] = case v.kind of ConstructorSpecKind.`Crec`: toPreserve(v.`crec`, E) of ConstructorSpecKind.`Carr`: toPreserve(v.`carr`, E) of ConstructorSpecKind.`Cdict`: toPreserve(v.`cdict`, E) proc fromPreserveHook*[E](v: var ConstructorSpec; pr: Preserve[E]): bool = if isRecord(pr) and pr.label.isSymbol("CRec"): v = ConstructorSpec(kind: ConstructorSpecKind.`Crec`) result = fromPreserve(v.`crec`, pr) elif isRecord(pr) and pr.label.isSymbol("CArr"): v = ConstructorSpec(kind: ConstructorSpecKind.`Carr`) result = fromPreserve(v.`carr`, pr) elif isRecord(pr) and pr.label.isSymbol("CDict"): v = ConstructorSpec(kind: ConstructorSpecKind.`Cdict`) result = fromPreserve(v.`cdict`, pr) proc `cRec`*[E = void](`label`: Preserve[E]; `arity`: BiggestInt | Preserve[E]): Preserve[ E] = ## Preserves constructor for ``CRec``. initRecord[E](symbol[E]("rec"), toPreserve(`label`, E), toPreserve(`arity`, E)) proc toPreserveHook*(`crec`: CRec; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("rec"), toPreserve(`crec`.`label`, E), toPreserve(`crec`.`arity`, E)) proc `cArr`*[E = void](`arity`: BiggestInt | Preserve[E]): Preserve[E] = ## Preserves constructor for ``CArr``. initRecord[E](symbol[E]("arr"), toPreserve(`arity`, E)) proc toPreserveHook*(`carr`: CArr; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("arr"), toPreserve(`carr`.`arity`, E)) proc `cDict`*[E = void](): Preserve[E] = ## Preserves constructor for ``CDict``. initRecord[E](symbol[E]("dict")) proc toPreserveHook*(`cdict`: CDict; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("dict")) proc `lit`*[E = void](`value`: Preserve[E]): Preserve[E] = ## Preserves constructor for ``Lit``. initRecord[E](symbol[E]("lit"), toPreserve(`value`, E)) proc toPreserveHook*(`lit`: Lit; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("lit"), toPreserve(`lit`.`value`, E)) proc toPreserveHook*(v: Pattern; E: typedesc): Preserve[E] = case v.kind of PatternKind.`Pdiscard`: toPreserve(v.`pdiscard`, E) of PatternKind.`Patom`: toPreserve(v.`patom`, E) of PatternKind.`Pembedded`: Preserve[E](kind: pkSymbol, symbol: "Embedded") of PatternKind.`Pbind`: toPreserve(v.`pbind`, E) of PatternKind.`Pand`: toPreserve(v.`pand`, E) of PatternKind.`Pnot`: toPreserve(v.`pnot`, E) of PatternKind.`Lit`: toPreserve(v.`lit`, E) of PatternKind.`Pcompound`: toPreserve(v.`pcompound`, E) proc fromPreserveHook*[E](v: var Pattern; pr: Preserve[E]): bool = if isRecord(pr) and pr.label.isSymbol("PDiscard"): v = Pattern(kind: PatternKind.`Pdiscard`) result = fromPreserve(v.`pdiscard`, pr) elif false: ## snkOr - / =<Boolean> / =<Float> / =<Double> / =<SignedInteger> / =<String> / =<ByteString> / =<Symbol> discard elif pr.kind == pkSymbol and pr.symbol == "Embedded": v = Pattern(kind: PatternKind.`Pembedded`) result = true elif isRecord(pr) and pr.label.isSymbol("PBind"): v = Pattern(kind: PatternKind.`Pbind`) result = fromPreserve(v.`pbind`, pr) elif isRecord(pr) and pr.label.isSymbol("PAnd"): v = Pattern(kind: PatternKind.`Pand`) result = fromPreserve(v.`pand`, pr) elif isRecord(pr) and pr.label.isSymbol("PNot"): v = Pattern(kind: PatternKind.`Pnot`) result = fromPreserve(v.`pnot`, pr) elif isRecord(pr) and pr.label.isSymbol("Lit"): v = Pattern(kind: PatternKind.`Lit`) result = fromPreserve(v.`lit`, pr) elif isRecord(pr) and pr.label.isSymbol("PCompound"): v = Pattern(kind: PatternKind.`Pcompound`) result = fromPreserve(v.`pcompound`, pr) proc `pDiscard`*[E = void](): Preserve[E] = ## Preserves constructor for ``PDiscard``. initRecord[E](symbol[E]("_")) proc toPreserveHook*(`pdiscard`: PDiscard; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("_")) proc toPreserveHook*(v: PAtom; E: typedesc): Preserve[E] = case v of PAtom.`Boolean`: symbol[E]("Boolean") of PAtom.`Float`: symbol[E]("Float") of PAtom.`Double`: symbol[E]("Double") of PAtom.`Signedinteger`: symbol[E]("SignedInteger") of PAtom.`String`: symbol[E]("String") of PAtom.`Bytestring`: symbol[E]("ByteString") of PAtom.`Symbol`: symbol[E]("Symbol") proc fromPreserveHook*[E](v: var PAtom; pr: Preserve[E]): bool = if isSymbol(pr): case pr.symbol of "Boolean": v = PAtom.`Boolean` result = true of "Float": v = PAtom.`Float` result = true of "Double": v = PAtom.`Double` result = true of "SignedInteger": v = PAtom.`Signedinteger` result = true of "String": v = PAtom.`String` result = true of "ByteString": v = PAtom.`Bytestring` result = true of "Symbol": v = PAtom.`Symbol` result = true proc pEmbedded*[E = void](): Preserve[E] = ## ``<Embedded>`` symbol[E]("Embedded") proc `pBind`*[E = void](`pattern`: Pattern | Preserve[E]): Preserve[E] = ## Preserves constructor for ``PBind``. initRecord[E](symbol[E]("bind"), toPreserve(`pattern`, E)) proc toPreserveHook*(`pbind`: PBind; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("bind"), toPreserve(`pbind`.`pattern`, E)) proc `pAnd`*[E = void](`patterns`: Preserve[E]): Preserve[E] = ## Preserves constructor for ``PAnd``. initRecord[E](symbol[E]("and"), toPreserve(`patterns`, E)) proc toPreserveHook*(`pand`: PAnd; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("and"), toPreserve(`pand`.`patterns`, E)) proc `pNot`*[E = void](`pattern`: Pattern | Preserve[E]): Preserve[E] = ## Preserves constructor for ``PNot``. initRecord[E](symbol[E]("not"), toPreserve(`pattern`, E)) proc toPreserveHook*(`pnot`: PNot; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("not"), toPreserve(`pnot`.`pattern`, E)) proc `pCompound`*[E = void](`ctor`: ConstructorSpec | Preserve[E]; `members`: PCompoundMembers | Preserve[E]): Preserve[ E] = ## Preserves constructor for ``PCompound``. initRecord[E](symbol[E]("compound"), toPreserve(`ctor`, E), toPreserve(`members`, E)) proc toPreserveHook*(`pcompound`: PCompound; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("compound"), toPreserve(`pcompound`.`ctor`, E), toPreserve(`pcompound`.`members`, E)) proc toPreserveHook*(v: Template; E: typedesc): Preserve[E] = case v.kind of TemplateKind.`Tattenuate`: toPreserve(v.`tattenuate`, E) of TemplateKind.`Tref`: toPreserve(v.`tref`, E) of TemplateKind.`Lit`: toPreserve(v.`lit`, E) of TemplateKind.`Tcompound`: toPreserve(v.`tcompound`, E) proc fromPreserveHook*[E](v: var Template; pr: Preserve[E]): bool = if isRecord(pr) and pr.label.isSymbol("TAttenuate"): v = Template(kind: TemplateKind.`Tattenuate`) result = fromPreserve(v.`tattenuate`, pr) elif isRecord(pr) and pr.label.isSymbol("TRef"): v = Template(kind: TemplateKind.`Tref`) result = fromPreserve(v.`tref`, pr) elif isRecord(pr) and pr.label.isSymbol("Lit"): v = Template(kind: TemplateKind.`Lit`) result = fromPreserve(v.`lit`, pr) elif isRecord(pr) and pr.label.isSymbol("TCompound"): v = Template(kind: TemplateKind.`Tcompound`) result = fromPreserve(v.`tcompound`, pr) proc `tAttenuate`*[E = void](`template`: Template | Preserve[E]; `attenuation`: Attenuation | Preserve[E]): Preserve[ E] = ## Preserves constructor for ``TAttenuate``. initRecord[E](symbol[E]("attenuate"), toPreserve(`template`, E), toPreserve(`attenuation`, E)) proc toPreserveHook*(`tattenuate`: TAttenuate; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("attenuate"), toPreserve(`tattenuate`.`template`, E), toPreserve(`tattenuate`.`attenuation`, E)) proc `tRef`*[E = void](`binding`: BiggestInt | Preserve[E]): Preserve[E] = ## Preserves constructor for ``TRef``. initRecord[E](symbol[E]("ref"), toPreserve(`binding`, E)) proc toPreserveHook*(`tref`: TRef; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("ref"), toPreserve(`tref`.`binding`, E)) proc `tCompound`*[E = void](`ctor`: ConstructorSpec | Preserve[E]; `members`: TCompoundMembers | Preserve[E]): Preserve[ E] = ## Preserves constructor for ``TCompound``. initRecord[E](symbol[E]("compound"), toPreserve(`ctor`, E), toPreserve(`members`, E)) proc toPreserveHook*(`tcompound`: TCompound; E: typedesc): Preserve[E] = initRecord[E](symbol[E]("compound"), toPreserve(`tcompound`.`ctor`, E), toPreserve(`tcompound`.`members`, E)) proc `$`*[E](x: SturdyRef[E] | Attenuation[E] | Caveat[E] | Rewrite[E] | Alts[E] | Oid | WireRef[E] | ConstructorSpec[E] | CRec[E] | CArr | CDict | Lit[E] | Pattern[E] | PDiscard | PAtom | PBind[E] | PAnd[E] | PNot[E] | PCompound[E] | PCompoundMembers[E] | Template[E] | TAttenuate[E] | TRef | TCompound[E] | TCompoundMembers[E]): string = `$`(toPreserve(x, E)) proc `encode`*[E](x: SturdyRef[E] | Attenuation[E] | Caveat[E] | Rewrite[E] | Alts[E] | Oid | WireRef[E] | ConstructorSpec[E] | CRec[E] | CArr | CDict | Lit[E] | Pattern[E] | PDiscard | PAtom | PBind[E] | PAnd[E] | PNot[E] | PCompound[E] | PCompoundMembers[E] | Template[E] | TAttenuate[E] | TRef | TCompound[E] | TCompoundMembers[E]): seq[byte] = encode(toPreserve(x, E))