···11+// type level stuff to enable well-typed coercions
22+type atomTag<_> = ..
33+type rec anyValue = AnyValue(atomTag<'a>, 'a): anyValue
44+55+// to allow circular coercions, we declare base types
66+// separately from relevant implementation
77+module type BASE_ATOM = {
88+ type t
99+ type atomTag<_> += Tag: atomTag<t>
1010+ let wrap: t => anyValue
1111+}
1212+1313+module Make = (
1414+ T: {
1515+ type t
1616+ },
1717+): (BASE_ATOM with type t = T.t) => {
1818+ type t = T.t
1919+ type atomTag<_> += Tag: atomTag<t>
2020+ let wrap = t => AnyValue(Tag, t)
2121+}
2222+2323+module String = {
2424+ type piece =
2525+ | String(string)
2626+ | Var({idx: int})
2727+ | Schematic({schematic: int, allowed: array<int>})
2828+ include Make({type t = array<piece>})
2929+}
3030+3131+module VarBase = {
3232+ type varBase = Var({idx: int}) | Schematic({schematic: int, allowed: array<int>})
3333+ include Make({type t = varBase})
3434+}
+58-87
src/AtomDef.res
···11-// type level stuff to enable well-typed coercions
22-type atomTag<_> = ..
33-type rec anyValue = AnyValue(atomTag<'a>, 'a): anyValue
44-55-// to allow circular coercions, we declare base types
66-// separately from relevant implementation
77-module type BASE_ATOM = {
88- type t
99- type atomTag<_> += Tag: atomTag<t>
1010- let wrap: t => anyValue
1111-}
1212-1313-module MakeBaseAtom = (
1414- T: {
1515- type t
1616- },
1717-): (BASE_ATOM with type t = T.t) => {
1818- type t = T.t
1919- type atomTag<_> += Tag: atomTag<t>
2020- let wrap = t => AnyValue(Tag, t)
2121-}
11+open AtomBase
222233module type ATOM = {
2424- module BaseAtom: BASE_ATOM
2525- type t = BaseAtom.t
44+ module Base: BASE_ATOM
55+ type t = Base.t
266 type subst = Map.t<int, t>
277 let unify: (t, t, ~gen: ref<int>=?) => Seq.t<subst>
288 let prettyPrint: (t, ~scope: array<string>) => string
···3414 let coerce: anyValue => option<t>
3515}
36163737-type varBase = Var({idx: int}) | Schematic({schematic: int, allowed: array<int>})
3838-module VarBase = MakeBaseAtom({
3939- type t = varBase
4040-})
4141-4217exception AtomExpected
43184444-module AtomListBase = MakeBaseAtom({
1919+module AtomChoiceBase = Make({
4520 type t = anyValue
4621})
47224848-module type ATOM_LIST = {
4949- module HeadBase: BASE_ATOM
5050- include ATOM with module BaseAtom = AtomListBase
5151- let onHead: (t, HeadBase.t => 'a) => option<'a>
2323+module type ATOM_CHOICE = {
2424+ module LeftBase: BASE_ATOM
2525+ include ATOM with module Base = AtomChoiceBase
2626+ let onLeft: (t, LeftBase.t => 'a) => option<'a>
5227}
53285454-module NilAtomList: ATOM_LIST = {
5555- module HeadBase = MakeBaseAtom({
2929+module EmptyAtomChoice: ATOM_CHOICE = {
3030+ module LeftBase = AtomBase.Make({
5631 // empty
5732 type t = {.}
5833 })
5959- module BaseAtom = AtomListBase
6060- type t = BaseAtom.t
3434+ module Base = AtomChoiceBase
3535+ type t = Base.t
6136 type subst = Map.t<int, t>
6237 let parse = (_, ~scope as _, ~gen as _=?) => Error("expected atom")
6363- // ideally we could check that the tags
6464- // in each argument are the same before returning Seq.empty, otherwise throw
6565- // but building up a type-level witness to tag equality is not easy with the
6666- // extensible variant stuff
6738 let unify = (_, _, ~gen as _=?) => Seq.empty
6839 // this should probably throw too, but will be more
6940 // informative to have it appear wherever it's called from
7041 let prettyPrint = (_, ~scope as _) => "NIL (THIS IS AN ERROR!)"
7171- let onHead = (_, _) => throw(AtomExpected)
4242+ let onLeft = (_, _) => throw(AtomExpected)
7243 let coerce = _ => throw(AtomExpected)
7344 let substitute = (_, _) => throw(AtomExpected)
7445 let upshift = (_, _, ~from as _=?) => throw(AtomExpected)
···7647 let concrete = _ => throw(AtomExpected)
7748}
78497979-module CombineAtom = (Head: ATOM, Tail: ATOM_LIST): (
8080- ATOM_LIST with module HeadBase = Head.BaseAtom
5050+module MakeAtomChoice = (Left: ATOM, Right: ATOM_CHOICE): (
5151+ ATOM_CHOICE with module LeftBase = Left.Base
8152) => {
8282- module HeadBase = Head.BaseAtom
8383- module Tail = Tail
8484- module BaseAtom = AtomListBase
8585- type t = BaseAtom.t
5353+ module LeftBase = Left.Base
5454+ module Right = Right
5555+ module Base = AtomChoiceBase
5656+ type t = Base.t
8657 type subst = Map.t<int, t>
8758 type gen = ref<int>
8859 let getOrElse = Util.Option.getOrElse
8960 let coerce = v => Some(v)
9090- let onHead = (AnyValue(tag, val), f: Head.t => 'a): option<'a> =>
6161+ let onLeft = (AnyValue(tag, val), f: Left.t => 'a): option<'a> =>
9162 switch tag {
9292- | Head.BaseAtom.Tag => Some(f(val))
6363+ | Left.Base.Tag => Some(f(val))
9364 | _ => None
9465 }
9566 let parse = (s, ~scope, ~gen: option<gen>=?) => {
9696- Head.parse(s, ~scope, ~gen?)
9797- ->Result.map(((r, rest)) => (HeadBase.wrap(r), rest))
9898- ->Util.Result.or(() => Tail.parse(s, ~scope, ~gen?))
6767+ Left.parse(s, ~scope, ~gen?)
6868+ ->Result.map(((r, rest)) => (LeftBase.wrap(r), rest))
6969+ ->Util.Result.or(() => Right.parse(s, ~scope, ~gen?))
9970 }
10071 let prettyPrint = (atom, ~scope) =>
10172 atom
102102- ->onHead(val => Head.prettyPrint(val, ~scope))
103103- ->getOrElse(() => Tail.prettyPrint(atom, ~scope))
7373+ ->onLeft(val => Left.prettyPrint(val, ~scope))
7474+ ->getOrElse(() => Right.prettyPrint(atom, ~scope))
1047510576 let unify = (a1, a2, ~gen=?) => {
10677 let (AnyValue(tag1, val1), AnyValue(tag2, val2)) = (a1, a2)
10778 switch (tag1, tag2) {
108108- | (Head.BaseAtom.Tag, Head.BaseAtom.Tag) =>
109109- Head.unify(val1, val2)->Seq.map(subst => subst->Util.mapMapValues(HeadBase.wrap))
110110- | (_, _) => Tail.unify(a1, a2, ~gen?)
7979+ | (Left.Base.Tag, Left.Base.Tag) =>
8080+ Left.unify(val1, val2)->Seq.map(subst => subst->Util.mapMapValues(LeftBase.wrap))
8181+ | (_, _) => Right.unify(a1, a2, ~gen?)
11182 }
11283 }
113113- let coerceToHead = (atom): option<Head.t> =>
114114- atom->onHead(val => Some(val))->getOrElse(() => Head.coerce(atom))
8484+ let coerceToLeft = (atom): option<Left.t> =>
8585+ atom->onLeft(val => Some(val))->getOrElse(() => Left.coerce(atom))
11586 let substitute = (atom, subst: subst) =>
11687 atom
117117- ->onHead(val => {
118118- let leftSubs = subst->Util.Map.filterMap((_, v) => coerceToHead(v))
119119- Head.substitute(val, leftSubs)->HeadBase.wrap
8888+ ->onLeft(val => {
8989+ let leftSubs = subst->Util.Map.filterMap((_, v) => coerceToLeft(v))
9090+ Left.substitute(val, leftSubs)->LeftBase.wrap
12091 })
121121- ->getOrElse(() => Tail.substitute(atom, subst))
9292+ ->getOrElse(() => Right.substitute(atom, subst))
1229312394 let upshift = (atom, amount: int, ~from=?) =>
12495 atom
125125- ->onHead(val => Head.upshift(val, amount, ~from?)->HeadBase.wrap)
126126- ->getOrElse(() => Tail.upshift(atom, amount, ~from?))
9696+ ->onLeft(val => Left.upshift(val, amount, ~from?)->LeftBase.wrap)
9797+ ->getOrElse(() => Right.upshift(atom, amount, ~from?))
12798 let substDeBruijn = (atom, substs: array<option<t>>, ~from=?) =>
12899 atom
129129- ->onHead(val =>
130130- Head.substDeBruijn(
100100+ ->onLeft(val =>
101101+ Left.substDeBruijn(
131102 val,
132132- substs->Array.map(o => o->Option.flatMap(coerceToHead)),
103103+ substs->Array.map(o => o->Option.flatMap(coerceToLeft)),
133104 ~from?,
134134- )->HeadBase.wrap
105105+ )->LeftBase.wrap
135106 )
136136- ->getOrElse(() => Tail.substDeBruijn(atom, substs, ~from?))
137137- let concrete = atom => atom->onHead(Head.concrete)->getOrElse(() => Tail.concrete(atom))
107107+ ->getOrElse(() => Right.substDeBruijn(atom, substs, ~from?))
108108+ let concrete = atom => atom->onLeft(Left.concrete)->getOrElse(() => Right.concrete(atom))
138109}
139110140111module type ATOM_VIEW = {
141112 module Atom: ATOM
142142- type props = {name: Atom.t, scope: array<string>}
113113+ type props = {atom: Atom.t, scope: array<string>}
143114 let make: props => React.element
144115}
145116146146-module NilAtomListView: ATOM_VIEW with module Atom := NilAtomList = {
147147- type props = {name: NilAtomList.t, scope: array<string>}
117117+module EmptyAtomChoiceView: ATOM_VIEW with module Atom := EmptyAtomChoice = {
118118+ type props = {atom: EmptyAtomChoice.t, scope: array<string>}
148119 let make = _ => throw(AtomExpected)
149120}
150121151151-module MakeAtomView = (
122122+module MakeAtomChoiceView = (
152123 Left: ATOM,
153124 LeftView: ATOM_VIEW with module Atom := Left,
154154- Right: ATOM_LIST,
125125+ Right: ATOM_CHOICE,
155126 RightView: ATOM_VIEW with module Atom := Right,
156156- Combined: module type of CombineAtom(Left, Right),
127127+ Combined: module type of MakeAtomChoice(Left, Right),
157128): (ATOM_VIEW with module Atom := Combined) => {
158158- type props = {name: Combined.t, scope: array<string>}
159159- let make = ({name, scope}: props) =>
160160- name
161161- ->Combined.onHead(left => <LeftView name={left} scope />)
162162- ->Util.Option.getOrElse(() => <RightView name scope />)
129129+ type props = {atom: Combined.t, scope: array<string>}
130130+ let make = ({atom, scope}: props) =>
131131+ atom
132132+ ->Combined.onLeft(left => <LeftView atom={left} scope />)
133133+ ->Util.Option.getOrElse(() => <RightView atom scope />)
163134}
164135165165-module MakeAtomAndView = (
136136+module MakeAtomChoiceAndView = (
166137 Left: ATOM,
167138 LeftView: ATOM_VIEW with module Atom := Left,
168168- Right: ATOM_LIST,
139139+ Right: ATOM_CHOICE,
169140 RightView: ATOM_VIEW with module Atom := Right,
170141) => {
171171- module Atom = CombineAtom(Left, Right)
172172- module AtomView = MakeAtomView(Left, LeftView, Right, RightView, Atom)
142142+ module Atom = MakeAtomChoice(Left, Right)
143143+ module AtomView = MakeAtomChoiceView(Left, LeftView, Right, RightView, Atom)
173144}
+1-1
src/HOTerm.res
···66module type ATOM = AtomDef.ATOM
7788module DefaultAtom = {
99- module BaseAtom = AtomDef.MakeBaseAtom({
99+ module Base = AtomBase.Make({
1010 type t = string
1111 })
1212 type t = string
···33 let cmp = Pervasives.compare
44})
5566-type piece =
77- | String(string)
88- | Var({idx: int})
99- | Schematic({schematic: int, allowed: array<int>})
1010-type t = array<piece>
1111-type meta = string
1212-type schematic = int
66+module Base = AtomBase.String
77+type t = Base.t
88+type piece = Base.piece
1391414-module BaseAtom = AtomDef.MakeBaseAtom({
1515- type t = t
1616-})
1010+module Atom = {
1111+ module Base = Base
1212+ type t = Base.t
1313+ type schematic = int
1414+ type meta = string
17151818-module Atom = {
1919- module BaseAtom = BaseAtom
2020- type t = t
2116 type subst = Map.t<schematic, t>
2217 let substitute = (term: t, subst: subst) =>
2318 Array.flatMap(term, piece => {
···10196 | (_, _) => {
10297 let (s1, ss) = uncons(s)
10398 switch s1 {
104104- | Schematic({schematic, allowed}) =>
9999+ | Base.Schematic({schematic, allowed}) =>
105100 Belt.Array.range(0, Array.length(t))
106101 ->Array.map(i => {
107102 let subTerm = Array.slice(t, ~start=0, ~end=i)
···155150 let searchSub = (schematic: int, allowed: array<int>, edge: graphSub): array<
156151 array<(int, graphSub)>,
157152 > => {
158158- let piece = Schematic({schematic, allowed})
153153+ let piece = Base.Schematic({schematic, allowed})
159154 let sub = switch edge {
160155 | Eps => singletonSubst(schematic, [])
161156 | PieceLitSub(p) => singletonSubst(schematic, [p, piece])
···383378 switch execRe(identRegex)
384379 ->Option.orElse(execRe(symbolRegex))
385380 ->Option.orElse(execRe(numberRegex)) {
386386- | Some([match], l) => add(String(match), ~nAdvance=l)
381381+ | Some([match], l) => add(Base.String(match), ~nAdvance=l)
387382 | Some(_) => error("regex string lit error")
388383 | None => error("expected string")
389384 }
···462457 let concrete = t =>
463458 t->Array.every(p =>
464459 switch p {
465465- | Schematic(_) => false
460460+ | Base.Schematic(_) => false
466461 | _ => true
467462 }
468463 )
469469- let coerce = (AtomDef.AnyValue(tag, a)) =>
464464+ let coerce = (AtomBase.AnyValue(tag, a)) =>
470465 switch tag {
471471- | Symbolic.BaseAtom.Tag => Some([String(a)])
472472- | AtomDef.VarBase.Tag =>
466466+ | Symbolic.Base.Tag => Some([Base.String(a)])
467467+ | AtomBase.VarBase.Tag =>
473468 Some([
474469 switch a {
475470 | Var({idx}) => Var({idx: idx})
···481476}
482477483478module AtomView = {
484484- type props = {name: t, scope: array<string>}
479479+ type props = {atom: t, scope: array<string>}
485480 type idx_props = {idx: int, scope: array<string>}
486481 let viewVar = (props: idx_props) =>
487482 switch props.scope[props.idx] {
···527522 }
528523529524 @react.componentWithProps
530530- let make = ({name, scope}) =>
525525+ let make = ({atom, scope}) =>
531526 <span className="term-compound">
532527 {React.string("\"")}
533533- {name
528528+ {atom
534529 ->Array.mapWithIndex((piece, i) => {
535530 let key = Int.toString(i)
536531 <Piece piece scope key />
+3-7
src/StringA.resi
···11-type rec piece =
22- | String(string)
33- | Var({idx: int})
44- | Schematic({schematic: int, allowed: array<int>})
55-type t = array<piece>
11+type t = AtomBase.String.t
6277-module BaseAtom: AtomDef.BASE_ATOM with type t = t
88-module Atom: AtomDef.ATOM with module BaseAtom = BaseAtom
33+module Base: AtomBase.BASE_ATOM with type t = t
44+module Atom: AtomDef.ATOM with module Base = Base
95module AtomView: AtomDef.ATOM_VIEW with module Atom := Atom
···11-module BaseAtom = AtomDef.MakeBaseAtom({
11+module Base = AtomBase.Make({
22 type t = string
33})
4455module Atom = {
66- module BaseAtom = BaseAtom
66+ module Base = Base
77 type t = string
88 type subst = Map.t<int, string>
99 let unify = (a, b, ~gen as _=?) =>
···2727}
28282929module AtomView = {
3030- type props = {name: string, scope: array<string>}
3131- let make = (props: props) => React.string(props.name)
3030+ type props = {atom: string, scope: array<string>}
3131+ let make = (props: props) => React.string(props.atom)
3232}
+2-2
src/Symbolic.resi
···11-module BaseAtom: AtomDef.BASE_ATOM with type t = string
22-module Atom: AtomDef.ATOM with module BaseAtom = BaseAtom
11+module Base: AtomBase.BASE_ATOM with type t = string
22+module Atom: AtomDef.ATOM with module Base = Base
33module AtomView: AtomDef.ATOM_VIEW with module Atom := Atom