···1212 let parse: (string, ~scope: array<string>, ~gen: ref<int>=?) => result<(t, string), string>
1313 let substitute: (t, subst) => t
1414 let upshift: (t, int, ~from: int=?) => t
1515- // used for when trying to substitute a variable of the wrong type
1616- let lowerVar: int => option<t>
1717- let lowerSchematic: (int, array<int>) => option<t>
1815 let substDeBruijn: (t, array<option<t>>, ~from: int=?) => t
1916 let concrete: t => bool
2017}
···2522 let liftHValue: hValue => option<t>
2623 let getHValue: t => hValue
2724}
2525+2626+type loweredSExp = Var({idx: int}) | Schematic({schematic: int, allowed: array<int>})
2727+type atomTag<_> += SExpTag: atomTag<loweredSExp>
2828+let tagEqSExp = (type a, tag: atomTag<a>): option<eq<loweredSExp, a>> =>
2929+ switch tag {
3030+ | SExpTag => Some(Refl)
3131+ | _ => None
3232+ }
28332934// coercion<t> represents a coercion from some type 'a to t,
3035// along with a function that effectively checks whether its argument is
···5560 type rec base =
5661 | Left(Left.t)
5762 | Right(Right.t)
5858- // used strictly for SExp -> Atom coercions
5959- // should not be parsed or otherwise appear organically
6060- | Both(option<Left.t>, option<Right.t>)
6161- // likewise, strictly for Atom <-> Atom coercions
6262- // occurs only when passed from some sibling part of the tree
6363+ // strictly for coercions
6464+ // occurs when passed from some relative in the tree
6565+ // or when SExp values are lowered into loweredSExp
6366 | Foreign(hValue)
6467 include COERCIBLE_ATOM with type t = base
6568 let match: (t, Left.t => 'a, Right.t => 'a) => 'a
···6770 type rec base =
6871 | Left(Left.t)
6972 | Right(Right.t)
7070- | Both(option<Left.t>, option<Right.t>)
7173 | Foreign(hValue)
7274 type t = base
7375 type subst = Map.t<int, t>
···8385 switch t {
8486 | Left(s) => leftBranch(s)
8587 | Right(s) => rightBranch(s)
8686- | Both(_) => throw(MatchCombineAtomBoth)
8788 | Foreign(_) => throw(MatchCombineAtomForeign)
8889 }
8990 let getHValue = t => t->match(Left.getHValue, Right.getHValue)
···107108 let coerceToLeft = (t): option<Left.t> =>
108109 switch t {
109110 | Left(s) => Some(s)
110110- | Both(os, _) => os
111111 | Right(s) => s->Right.getHValue->Left.liftHValue
112112 | Foreign(v) => Left.liftHValue(v)
113113 }
114114 let coerceToRight = (t): option<Right.t> =>
115115 switch t {
116116 | Right(s) => Some(s)
117117- | Both(_, os) => os
118117 | Left(s) => s->Left.getHValue->Right.liftHValue
119118 | Foreign(v) => Right.liftHValue(v)
120119 }
···135134 left => Left(left->Left.upshift(amount, ~from?)),
136135 right => Right(right->Right.upshift(amount, ~from?)),
137136 )
138138- let lowerVar = idx => Some(Both(Left.lowerVar(idx), Right.lowerVar(idx)))
139139- let lowerSchematic = (schematic, allowed) => Some(
140140- Both(Left.lowerSchematic(schematic, allowed), Right.lowerSchematic(schematic, allowed)),
141141- )
142137 let substDeBruijn = (s, substs: array<option<t>>, ~from=?) =>
143138 s->match(
144139 left => {