Beispiel #1
0
 private term(term t1, term t2)
 {
     Kind    = TermKind.Apply;
     _atom   = default(atom);
     _applyF = new Box <term>(t1);
     _applyX = new Box <term>(t2);
 }
Beispiel #2
0
        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");
        }
Beispiel #3
0
 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");
        }
Beispiel #5
0
        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");
        }
Beispiel #6
0
            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");
            }
Beispiel #7
0
        // 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");
        }
Beispiel #8
0
        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));
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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");
        }
Beispiel #11
0
 public static term Apply(term t1, term t2) => new term(t1, t2);
Beispiel #12
0
 public static type Apply(term a, term b) => new type(new term[0], term.Apply(a, b));
Beispiel #13
0
 public type(IEnumerable <term> constraints, term term)
 {
     _constraints = constraints.ToArray();
     Array.Sort(_constraints, new ConstraintComparer());
     Term = term;
 }