A single-file Prolog implementation of the IRS Fact Graph.
The purpose of this project is to strengthen my understanding the Fact Graph's semantics by reimplementing it. At this time, it can parse the entire Tax Withholding Estimator Fact Dictionary. It can also evaluate a variety of test cases, but some work remains before it can evaluate TWE's facts, mainly involving dates.
I recommend attempting to read factgraph.pl without syntax highlighting on, or at least syntax highlighting that is more restrained than GitHub's.
This implementation uses intermediate Prolog features, particularly DCGs with semicontext notation, but I am doing to my best to make is vibrationally accessible, so to speak;
it's worth at least taking a peak at the file even if you've never thought about Prolog before.
If you are unfamiliar with Prolog and would like to use this codebase as a reason to learn, I recommend "The Power of Prolog" by Markus Triska and the accompanying videos.
Setup
Requires Scryer Prolog, including a currently-unreleased fix to the XML parsing library. That means you have to install Scryer Prolog from source (which is very easy). With the Rust toolchain installed, navigate to a convenient directory and run the following commands:
git clone https://github.com/mthom/scryer-prolog/
cd scryer-prolog
cargo install --path .
Then, in a new shell, you should have the scryer-prolog command.
If you want to use the just command runner, you also need just.
Usage
Main commands:
just- open the top-level withfactgraph.plincludedjust test- run the tests
Key predicates:
load_dict(Fp, D)- load the Fact Dictionary at filepathFpload_graph(Fp, D, G)- load the Fact Graph at filepathFpwith dictionaryDeval_path(D, G, Path)- evaluate the factPathwith dictionaryDand graphG
Example:
% Evaluate the fact "/jobs" ?- load_dict("./test/collections.xml", D), load_graph("./test/collections.json", D, G), eval_path(D,G,"/jobs", V).
More example usages can be found in test.pl.
TODO
For TWE completeness
- Date types
- Including
/day,/month,/year, and/ordinal - Date arithmetic
<AddPayrollMonth>
- Including
- Rational math
- Testing against TWE scenarios
Optimizations
- Don't do fuzzy casting (dollar values become integers if they're used in a calculation that results in an integer)
- Remove cut from
<Switch>implementation (I think this can be modeled as "true and all previous conditions are false") <MultiEnum>(we don't use this in TWE but it should be implemented)
Out of scope
- Overly-specific FG types like TIN and Bank Account
- Semi-completeness
- i.e. Placeholder values working but being "incomplete"
- Although I suppose it could be easy to determine whether any placeholders are used in an evaluation