private void RunInferenceRulesOn(ClueId next) { if (_clueErrors[next].Any()) { // If it errored out, we'll only be making it worse return; } var targets = (new[] { next }.Concat(_clueDependsOn[next])).ToArray(); // 0 is always the next, 1 and on are its dependencies foreach (var t in targets) { if (_clueErrors[t].Any()) { // TODO: We can't really deduce anything _clueErrors[next].Add(new InferenceError($"depended-on clue had an error: {t}")); } } if (_clueErrors[next].Any()) { // If it errored out, we'll only be making it worse return; } foreach (var rule in _rules) { var tools = new Tools(this, targets); rule(tools); if (tools.Error != null) { if (tools.PreconditionsSatisfied) { _clueErrors[next].Add(tools.Error); // if one inference rule failed, others surely will too! return; } // it's fine, that rule just doesn't apply here apparently continue; } for (var i = 0; i < targets.Length; i++) { var clue = targets[i]; var oldType = _clueBestKnownType[clue]; var newType = free.Of(tools.Instantiate(i)); if (oldType.Equivalent(newType)) { continue; } // if we're updating to a genuinely new type, rerun rules depending on us _clueBestKnownType[clue] = newType; foreach (var depender in _cluesDependingOn[clue]) { _cluesToUpdate.Add(depender); } } } }
public IEnumerable <string> Errors(ClueId c) { return(from e in _clueErrors[c] select e.Message); // TODO: Include source }
public free <type> Type(ClueId cval) { return(_clueBestKnownType[cval]); }