public static Shrub <T> FromBinary <T>(BinaryTree <T> tree) { return(tree.Match <Shrub <T> >((l, r) => { var(ll, rr) = (FromBinary <T>(l), FromBinary <T>(r)); return ll.Match <Shrub <T> >( ls => rr.Match(rs => Shrub <T> .Node(ls.Append(Shrub <T> .Node(rs)).ToList()), xr => Shrub <T> .Node(ls.Append(Shrub <T> .Leaf(xr)).ToList())), xl => rr.Match(rs => Shrub <T> .Node(rs.Prepend(Shrub <T> .Leaf(xl)).ToList()), xr => Shrub <T> .Node(new List <Shrub <T> > { Shrub <T> .Leaf(xl), Shrub <T> .Leaf(xr) }) )); }, Shrub <T> .Leaf)); }
Tuple <Shrub <float>, float> findLeftSides(Term term, float leftOffset) { return(term.Match <Tuple <Shrub <float>, float> >(l => { List <Shrub <float> > acc = new List <Shrub <float> >(); float widths = 0; foreach (var shrub in l) { (var s, float width) = findLeftSides(shrub, leftOffset + widths); widths += width; acc.Add(s); } return Tuple.Create(Shrub <float> .Node(acc), widths); }, v => Tuple.Create(Shrub <float> .Leaf(leftOffset), lookup_width[v]))); }
public Shrub <T> evaluate <T>(Shrub <T> Term) { (var debuijn, var arity) = Util.ParseCombinator(c) .Match( pi => pi, u => throw new Exception(u.ToString()) ); return(Term.ApplyAt( t => { var args = t.Match(l => l, v => throw new Exception()); var result = Shrub <T> .Collapse(debuijn.Map(i => i + 1).Map(i => args[i])); return result.Match( l => Shrub <T> .Node(l.Concat(args.Skip(arity + 1)).ToList()), u => Shrub <T> .Node(new List <Shrub <T> >().Append(Shrub <T> .Leaf(u)).Concat(args.Skip(arity + 1)).ToList())); }, path)); }
public static Tuple <List <Shrub <T> >, List <T> > ParseParens <T>(List <T> l, Func <T, bool> is_left_paren, Func <T, bool> is_right_paren) { if (l.Count() != 0) { if (is_right_paren(l[0])) { return(Tuple.Create(new List <Shrub <T> >(), l.Skip(1).ToList())); } if (is_left_paren(l[0])) { (List <Shrub <T> > child, List <T> k) = ParseParens <T>(l.Skip(1).ToList(), is_left_paren, is_right_paren); (List <Shrub <T> > parent, List <T> kk) = ParseParens <T>(k, is_left_paren, is_right_paren); return(Tuple.Create(parent.Prepend(Shrub <T> .Node(child)).ToList(), kk)); } (List <Shrub <T> > toplevel, List <T> rest) = ParseParens <T>(l.Skip(1).ToList(), is_left_paren, is_right_paren); return(Tuple.Create(toplevel.Prepend(Shrub <T> .Leaf(l[0])).ToList(), rest)); } else { return(Tuple.Create(new List <Shrub <T> >(), l)); } }
public static Sum <Term, Unit> BackApply(Term term, Combinator C, List <int> path) { if (path.Count > 0) { Debug.Log($"path: {path.Select(i => i.ToString()).Aggregate((a,b) => $"{a}, {b}")}\n term: {show(term)}"); } var target = term.Access(path); var(debruijn, arity) = Lambda.Util.ParseCombinator(C).Match(p => p, _ => throw new ArgumentException()); Sum <Term, Unit> UnifyMeta(Term t1, Term t2) { return(t1.Match <Sum <Term, Unit> >(l1 => t2.Match <Sum <Term, Unit> >(l2 => { if (l1.Count != l2.Count) { return Sum <Term, Unit> .Inr(new Unit()); } List <Term> result = new List <Term>(); for (int i = 0; i < l1.Count; i++) { if (UnifyMeta(l1[i], l2[i]).Match(t => { result.Add(t); return false; }, _ => true)) { return Sum <Term, Unit> .Inr(new Unit()); } } return Sum <Term, Unit> .Inl(Term.Node(result)); } , x2 => x2.Match(c2 => Sum <Term, Unit> .Inr(new Unit()), v2 => { if (((int)v2) == -1) { return Sum <Term, Unit> .Inl(t1); } else { return Sum <Term, Unit> .Inr(new Unit()); } }) ), x1 => t2.Match <Sum <Term, Unit> >(l2 => x1.Match(c1 => Sum <Term, Unit> .Inr(new Unit()), v1 => { if (((int)v1) == -1) { return Sum <Term, Unit> .Inl(t2); } else { return Sum <Term, Unit> .Inr(new Unit()); } }), x2 => x1.Match <Sum <Term, Unit> >( c1 => x2.Match <Sum <Term, Unit> >( c2 => c1.Equals(c2) ? Sum <Term, Unit> .Inl(t1) : Sum <Term, Unit> .Inr(new Unit()), v2 => (int)v2 == -1 ? Sum <Term, Unit> .Inl(t1) : Sum <Term, Unit> .Inr(new Unit())) , v1 => (int)v1 == -1 ? Sum <Term, Unit> .Inl(t2) : x2.Match <Sum <Term, Unit> >( c2 => Sum <Term, Unit> .Inr(new Unit()), v2 => (int)v2 == -1 ? Sum <Term, Unit> .Inl(t1) : (v1 == v2 ? Sum <Term, Unit> .Inl(t1) : Sum <Term, Unit> .Inr(new Unit())))) ))); } bool UnifyDebruijn(Shrub <int> d, Term t, Term[] subst) { //true if unification works return(d.Match <bool>( ds => t.Match <bool>(ts => { if (ds.Count != ts.Count) { return false; } for (int i = 0; i < ds.Count; i++) { if (!UnifyDebruijn(ds[i], ts[i], subst)) { return false; } } return true; } , xt => { return xt.Match <bool>(c => false, v => (int)v == -1); }), //unification with metavariable unnecessary xd => t.Match <bool>(ts => { return UnifyMeta(subst[xd], t).Match( unified => { subst[xd] = unified; return true; }, _ => false); //can't apply duplicator }, xt => { return xt.Match <bool>(c => UnifyMeta(subst[xd], t).Match( unified => { subst[xd] = unified; return true; }, _ => false) //can't apply duplicator , v => { if ((int)v == -1) { return true; //unification unnecessary } else { return UnifyMeta(subst[xd], t).Match( unified => { subst[xd] = unified; return true; }, _ => false); //unify } } ); }))); } //Extend Combinator to fit the whole term target.Match(l => { debruijn.Match(d => { d = d.ToList(); for (int i = d.Count; i < l.Count; i++) { d.Add(Shrub <int> .Leaf(arity)); arity++; } debruijn = Shrub <int> .Node(d); }, x => { var d = new List <Shrub <int> >(); d.Add(Shrub <int> .Leaf(x)); for (int i = d.Count; i < l.Count; i++) { d.Add(Shrub <int> .Leaf(arity)); arity++; } debruijn = Shrub <int> .Node(d); }); }, _ => {}); Term[] sub = new Term[arity]; for (int i = 0; i < arity; i++) { sub[i] = Term.Leaf(Sum <Combinator, Variable> .Inr((Variable)(-1))); } if (UnifyDebruijn(debruijn, target, sub)) { return(Sum <Term, Unit> .Inl(term.Update(Term.Node(sub.Prepend(Term.Leaf(Sum <Combinator, Variable> .Inl(C))).ToList()), path))); } return(Sum <Term, Unit> .Inr(new Unit())); //binarify everything TODO don't do this or return a List<Term> //unify -- negative variables are metavariables (can be substituted by anything) //if unification fails retry with degenerate arity extensions until we hit the left depth of target //apply the unification to debruijn adding metavariablese // \xyz => (y z) backapplied to ([X]) (where [X] is a metavariable) becomes [Y] [X_1] [X_2] // [Y] is created because of the dropped argument and [X_i] gets created as we unify for [X] ~ (y z) //unification returns an array of shrubs where each cell holds what needs to be subst in (initialized to new metavariables), and deals with replaces metavariables in the target which might be bad }
public IEnumerator _UnTransition(Term newTerm, LayoutTracker lt, Combinator C, List <int> path, LayoutTracker TopSymbol) { forwardUndoStack.Push(new ForwardData(Sum <ElimRule, AddParenRule> .Inl(new CombinatorElim(C, path)), TopSymbol)); /* * REMEMBER, you've already "typechecked" this operation, you can assume that everything fits * Get transform at path * Grab transforms at the first occurence of each debruijn index * Delete everything else * spawn metavariables * order everything appropriately */ Transform target = AccessTransfrom(TopSymbol.transform, path); (var debruijn, var arity) = Util.ParseCombinator(C) .Match( pi => pi, u => throw new Exception(u.ToString()) ); debruijn.Match(d => { d = d.ToList(); for (int i = d.Count; i < target.childCount; i++) { d.Add(Shrub <int> .Leaf(arity)); arity++; } debruijn = Shrub <int> .Node(d); }, x => { var d = new List <Shrub <int> >(); d.Add(Shrub <int> .Leaf(x)); for (int i = d.Count; i < target.childCount; i++) { d.Add(Shrub <int> .Leaf(arity)); arity++; } debruijn = Shrub <int> .Node(d); }); Transform[] children = new Transform[arity]; debruijn.IterateI(new List <int>(), (i, p) => { children[i] = AccessTransfrom(target, p, t => t, () => null); }); var canvas = GetComponentInParent <Canvas>(); foreach (var child in children) { child?.SetParent(canvas.transform, true); } foreach (Transform t in target) { Destroy(t.gameObject); } lt.LockDown(.1f); lt.transform.SetParent(target, true); foreach (var child in children) { if (!child) { var meta = Instantiate(GetSymbol(Sum <Combinator, Variable> .Inr((Variable)(-1))), target); meta.root = skeletonRoot; } else { child.SetParent(target, true); } } foreach (Transform t in skeletonRoot) { Destroy(t.gameObject); } CreateSkeleton(newTerm, skeletonRoot); yield return(new WaitUntil(() => { bool moving = false; IterateTransform(TopSymbol.transform, t => { if (t.GetComponent <LayoutTracker>()) { moving |= t.GetComponent <LayoutTracker>().Moving(); } }); return !moving; })); }
private Sum <Action, PreviewInfo> MakeDrop(SpawnTarget spawnTarget, Transform target) //left is on failure, right is on success { var parenTracker = target.GetComponent <LayoutTracker>(); List <int> index = parenTracker.index; var my_term = myCombinator == null ? Shrub <Sum <Combinator, Variable> > .Node(new List <Shrub <Sum <Combinator, Variable> > >()) : Shrub <Sum <Combinator, Variable> > .Leaf(Sum <Combinator, Variable> .Inl(myCombinator)); if (!target.GetComponentInParent <DraggableHolder>()) { return(Sum <Action, PreviewInfo> .Inl(DestroyMe)); } if (spawnTarget && !spawnTarget.NoBackApplication.val) //Back application { if (myCombinator == null) { //You are a parenthesis int my_index; for (my_index = 0; my_index < target.childCount; my_index++) { if (transform.position.x < target.GetChild(my_index).position.x - target.GetChild(my_index).localScale.x / 4f) { break; } } if (true /*my_index != target.childCount*/) { return(Util.BackApplyParen(spawnTarget.goal, index.Skip(1).ToList(), my_index).Match(t => { List <IHighlightable> selected = new List <IHighlightable>(); for (int i = 0; i < my_index; i++) { selected = selected.Concat(target.GetChild(i).GetComponentsInChildren <IHighlightable>()).ToList(); } PreviewRedundantParenInfo prp = new PreviewRedundantParenInfo(index, my_index, () => { spawnTarget.addParens(index.Skip(1).ToList(), my_index, GetComponent <LayoutTracker>(), t); foreach (IHighlightable highlightable in selected) { highlightable.unselect(); } PlaceMe(); myDraggableType = DraggableHolder.DraggableType.RedundantParens; }, () => { foreach (IHighlightable highlightable in selected) { highlightable.select(); } }, () => { foreach (IHighlightable highlightable in selected) { highlightable.unselect(); } }); return Sum <Action, PreviewInfo> .Inr(PreviewInfo.In2(prp)); }, _ => { return Sum <Action, PreviewInfo> .Inl(DestroyMe); })); } else { return(Sum <Action, PreviewInfo> .Inl(DestroyMe)); } } else { //You not are a parenthesis HighlightParen hightligher = parenTracker.GetComponent <HighlightParen>(); return(Util.BackApply(spawnTarget.goal, myCombinator, index.Skip(1).ToList()).Match(t => Sum <Action, PreviewInfo> .Inr(PreviewInfo.In1(new PreviewBackCombinatorInfo(spawnTarget, parenTracker, index, () => { pushUndoGoalTerm.Invoke(spawnTarget.goal); spawnTarget.unApply(t, GetComponent <LayoutTracker>(), myCombinator, index.Skip(1).ToList()); PlaceMe(); hightligher.unselect(); myDraggableType = DraggableHolder.DraggableType.NoDragging; }, hightligher.select, hightligher.unselect))) , _ => Sum <Action, PreviewInfo> .Inl(DestroyMe))); } } else if (!spawnTarget && !NoForwardMode.val && target.GetComponentInParent <DraggableHolder>() && target.GetComponentInParent <DraggableHolder>().myType == DraggableHolder.DraggableType.Proposal) //forward application { if (evaluationMode.val) { return(Sum <Action, PreviewInfo> .Inl(DestroyMe)); } int my_index; for (my_index = 0; my_index < target.childCount; my_index++) { if (transform.position.x < target.GetChild(my_index).position.x) { break; } } var sm = target.GetComponentInParent <SymbolManager>(); return(Sum <Action, PreviewInfo> .Inr( PreviewInfo.In0(new PreviewForwardInfo(sm, index, target, my_index, () => { //if (pushUndoProposalTerm) { // pushUndoProposalTerm.Invoke(sm.readTerm()); //} else { // Debug.LogError("pushUndoProposalTerm is null in DraggableSpell: " + this); //} sm.Insert(index.Skip(1).Append(my_index).ToList(), my_term); // paren = AccessTransfrom(topTracker, paren_index); transform.SetParent(target, true); transform.SetSiblingIndex(my_index); PlaceMe(); myDraggableType = DraggableHolder.DraggableType.Proposal; }, UnPlace)) )); } return(Sum <Action, PreviewInfo> .Inl(DestroyMe)); }