private term(term t1, term t2) { Kind = TermKind.Apply; _atom = default(atom); _applyF = new Box <term>(t1); _applyX = new Box <term>(t2); }
public term InstantiateWithoutConstraints(term term) { if (Failed) { throw new Exception("this Vars failed and is in an invalid state"); } switch (term.Kind) { case TermKind.Atom: return(term); case TermKind.Apply: return(term.Apply(InstantiateWithoutConstraints(term.ApplyF), InstantiateWithoutConstraints(term.ApplyX))); case TermKind.Var: term value; if (_bindings.TryGetValue(term.VarName, out value)) { return(InstantiateWithoutConstraints(value)); } return(term); } throw new Exception("unreachable code"); }
public term Key(term constraint) { foreach (var k in _keyFinders) { var key = k(constraint); if (key.HasValue) { return(key.Value); } } return(constraint); // by default, overlapping constraints are fine }
private term Unfree(term term) { switch (term.Kind) { case TermKind.Atom: return(term); case TermKind.Apply: return(term.Apply(Unfree(term.ApplyF), Unfree(term.ApplyX))); case TermKind.Var: return(Generate(term.VarName, (a, x, y) => term.Var(new atom(a.Value + "_" + x)))); // TODO: This should be a utility op in atom } throw new Exception("unreachable case"); }
public bool Equals(term other) { if (Kind != other.Kind) { return(false); } switch (Kind) { case TermKind.Atom: return(AtomAtom == other.AtomAtom); case TermKind.Apply: return(ApplyF == other.ApplyF && ApplyX == other.ApplyX); case TermKind.Var: return(VarName == other.VarName); } throw new Exception("unreachable code path"); }
internal term Canonicalize(term term) { switch (term.Kind) { case TermKind.Atom: return(term); case TermKind.Apply: return(term.Apply(Canonicalize(term.ApplyF), Canonicalize(term.ApplyX))); case TermKind.Var: atom existing; if (_canonicalName.TryGetValue(term.VarName, out existing)) { return(term.Var(existing)); } return(term.Var(_canonicalName[term.VarName] = new atom("var_" + (++_counter)))); } throw new Exception("unreachable path"); }
// true: occurs check passed (meaning var doesn't occur) // doesn't produce output beyond "occurs check failed" to avoid generating loads of garbage // *except when it follows a variable* private bool OccursCheck(atom var, term t2) { if (Failed) { throw new Exception("this Vars failed and is in an invalid state"); } switch (t2.Kind) { case TermKind.Atom: return(true); case TermKind.Apply: OccursCheck(var, t2.ApplyF); if (Failed) { return(false); } OccursCheck(var, t2.ApplyX); if (Failed) { return(false); } return(true); case TermKind.Var: if (var == t2.VarName) { FailMessage(() => "occurs check failed"); return(false); } term bound; if (_bindings.TryGetValue(t2.VarName, out bound)) { OccursCheck(var, bound); FailMessage(() => $"when resolving {t2.VarName} to {bound}"); return(false); } return(true); } throw new Exception("unreachable case"); }
public type InstantiateWithConstraints(term term) { if (Failed) { throw new Exception("this Vars failed and is in an invalid state"); } var termBase = InstantiateWithoutConstraints(term); var variables = termBase.Variables(); var salientConstraints = new List <term>(); foreach (var c in _constraints) { var instantiated = InstantiateWithoutConstraints(c); if (instantiated.Variables().Intersect(variables).Any()) { salientConstraints.Add(c); } } return(new type(salientConstraints, termBase)); }
public bool Constrain(term constraint) { var key = _constraintFundeps.Key(constraint); var constraints2 = new List <term>(); foreach (var existingConstraint in _constraints) { var theirKey = _constraintFundeps.Key(constraint); var decoy = this.Duplicate(); // create a savestate in case this fails if (decoy.Unify(key, theirKey)) { Unify(key, theirKey); // commit to this instance if (Failed) { throw new Exception( "failure was supposed to be impossible because we used a decoy, but it happened anyways"); } // the terms have matching keys so now // we have to be able to unify the terms Unify(constraint, existingConstraint); if (Failed) { FailMessage(() => $"while unifying new constraint {constraint} with existing matching-fundep constraint {existingConstraint}"); return(false); } } else { constraints2.Add(existingConstraint); // pass through unchanged } } _constraints = constraints2; return(true); }
public bool Unify(term t1, term t2) { if (Failed) { throw new Exception("this Vars failed and is in an invalid state"); } switch (t1.Kind) { case TermKind.Atom: switch (t2.Kind) { case TermKind.Atom: if (t1.AtomAtom != t2.AtomAtom) { FailMessage(() => $"mismatching atoms: {t1.AtomAtom} and {t2.AtomAtom}"); return(false); } return(true); case TermKind.Apply: FailMessage(() => $"could not match atom {t1.AtomAtom} with application {t2}"); return(false); case TermKind.Var: return(Unify(t2, t1)); // only t1 may be a var unless both are } throw new Exception("unreachable case"); case TermKind.Apply: switch (t2.Kind) { case TermKind.Atom: FailMessage(() => $"could not match application {t1} with atom {t2.AtomAtom}"); return(false); case TermKind.Apply: Unify(t1.ApplyF, t2.ApplyF); if (Failed) { FailMessage(() => $"while unifying term {t1} with {t2}"); return(false); } Unify(t1.ApplyX, t2.ApplyX); if (Failed) { FailMessage(() => $"while unifying term {t1} with {t2}"); return(false); } return(true); case TermKind.Var: return(Unify(t2, t1)); // only t1 may be a var unless both are } throw new Exception("unreachable case"); case TermKind.Var: term bound; OccursCheck(t1.VarName, t2); if (Failed) { FailMessage(() => $"{t1.VarName} occurs in {t2}, so it can't match with it"); FailMessage(() => $"while unifying term {t1} with {t2}"); return(false); } if (_bindings.TryGetValue(t1.VarName, out bound)) { Unify(bound, t2); if (Failed) { FailMessage(() => $"while unifying term {t1} with {t2}"); return(false); } return(true); } // unifying passes trivial _bindings[t1.VarName] = t2; return(true); } throw new Exception("unreachable case"); }
public static term Apply(term t1, term t2) => new term(t1, t2);
public static type Apply(term a, term b) => new type(new term[0], term.Apply(a, b));
public type(IEnumerable <term> constraints, term term) { _constraints = constraints.ToArray(); Array.Sort(_constraints, new ConstraintComparer()); Term = term; }