### BiMetaTrans 1.0

BiMetaTrans(Prolog, RuleML) is a bidirectional translator capable of
parsing and generating a well-formed sublanguage of RuleML/XML to/from
a metalogical encoding of our own design called Prolog/'$V'. For later
ease of reference:

* Prolog/'$V' stands for "Metalogic Prolog with variable-as-'$V'-term encoding"
* RuleML/XML stands for "RuleML in XML with any kind of rendering"
* RuleML/xmL stands for "RuleML in minified XML"
* RuleML/Xml stands for "RuleML in indented XML"

"Minified XML" refers to XML with only necessary whitespace, between
element names and attributes, and pairs of attributes, with all
indentation stripped out. "Indented XML" contains indentation and
newlines, and is usually formatted for human readers.

The specification of Prolog/'$V', and of the NafHornlogEq sublanguage
of RuleML/XML targeted by BiMetaTrans, is contained in the preprint
[Invertible Bidirectional Metalogical Translation Between Prolog and
RuleML/XML for Knowledge Representation and
Querying](http://ruleml.org/papers/RuleMLXMLBiDirTransScryer.pdf) and
its accompanying talk
[slides](http://ruleml.org/talks/RuleMLXMLBiDirTransScryer-talk.pdf). The
preprint and talk also describe the implementation of BiMetaTrans
found here, and outlines a strategy for proving the invertibility of
BiMetaTrans.

BiMetaTrans exports a single public predicate subsuming its user
API, `parse_ruleml/3`. It has two modes, each corresponding to a single
direction of translation:

```
parse_ruleml(+AssertItems, +QueryItems, ?XML)    (Prolog->RuleML)
parse_ruleml(?AssertItems, ?QueryItems, +XML)    (RuleML->Prolog)
```

The modes constrain the inputs to fit one of two patterns, the
first where AssertItems and QueryItems are instantiated and XML is
possibly a variable, and conversely for the second. Instantiated
inputs are expected to be ground, meaning they should not contain
free variables.

We explore several examples of its use in Scryer Prolog.

Loading BiMetaTrans from the Scryer REPL:

```
?- use_module('src/examples/bimetatrans/bimetatrans').
```

Using `write/1` to print the string to standard output, capturing the
`Prolog->RuleML` direction (`write/1` is used because it does not
print strings with escape characters, ie., `\"` for double quote):

```
?- parse_ruleml([people('Alex',male),people('Alex',female),people('Siri',female)], [], XML),
   write(XML).
"<Assert mapClosure="universal"><Atom><Rel>people</Rel><Ind>Alex</Ind><Data iso:type="symbol">male</Data></Atom><Atom><Rel>people</Rel><Ind>Alex</Ind><Data iso:type="symbol">female</Data></Atom><Atom><Rel>people</Rel><Ind>Siri</Ind><Data iso:type="symbol">female</Data></Atom></Assert>"   XML = "<Assert mapClosure= ...".
```

Note that the XML input can contain extraneous whitespace and
indentation while generated XML never does (ie., the XML generated by
BiMetaTrans is always Ruleml/xmL). `\` is used to continue ISO Prolog
strings to the next line but is never stored to the string by the
Prolog reader.

Performing the inverse translation of the previous example
(`RuleML->Prolog`), in RuleML/Xml:

```
?- parse_ruleml(AssertItems, QueryItems,
                "<Assert mapClosure=\"universal\">\
                   <Atom>\
                           <Rel>people</Rel>\
                           <Ind>Alex</Ind>\
                           <Data iso:type=\"symbol\">male</Data>\
                   </Atom>\
                   <Atom>\
                           <Rel>people</Rel>\
                           <Ind>Alex</Ind>\
                           <Data iso:type=\"symbol\">female</Data>\
                   </Atom>\
                   <Atom>\
                           <Rel>people</Rel>\
                           <Ind>Siri</Ind>\
                           <Data iso:type=\"symbol\">female</Data>\
                   </Atom>\
                </Assert>").
   AssertItems = [people('Alex',male),people('Alex',female),people('Siri',female)], QueryItems = [].
```

Double quote characters within strings must be escaped as in
`\"`. Non-empty AssertItems and QueryItems lists generated to
RuleML/xmL simultaneously:

```
?- parse_ruleml([a(item), b(item), c(item)], [(?- p, q, r(1), s(-2.222342432), t("attached")), (?- u, v('$V'(q)))], XML),
   write(XML).
"<Assert mapClosure="universal"><Atom><Rel>a</Rel><Data iso:type="symbol">item</Data></Atom><Atom><Rel>b</Rel><Data iso:type="symbol">item</Data></Atom><Atom><Rel>c</Rel><Data iso:type="symbol">item</Data></Atom></Assert><Query closure="existential"><And><Atom><Rel>p</Rel></Atom><Atom><Rel>q</Rel></Atom><Atom><Rel>r</Rel><Data iso:type="number">1</Data></Atom><Atom><Rel>s</Rel><Data iso:type="number">-2.222342432</Data></Atom><Atom><Rel>t</Rel><Data iso:type="string">"attached"</Data></Atom></And></Query><Query closure="existential"><And><Atom><Rel>u</Rel></Atom><Atom><Rel>v</Rel><Var>q</Var></Atom></And></Query>"   XML = "<Assert mapClosure= ...".
```

To insert escape characters into the printed RuleML/xmL, we use
`writeq/1` in place of `write/1`:

```
?- parse_ruleml([a(item), b(item), c(item)], [(?- p, q, r(1), s(-2.222342432), t("attached")), (?- u, v('$V'(q)))], XML),
   writeq(XML).
"<Assert mapClosure=\"universal\"><Atom><Rel>a</Rel><Data iso:type=\"symbol\">item</Data></Atom><Atom><Rel>b</Rel><Data iso:type=\"symbol\">item</Data></Atom><Atom><Rel>c</Rel><Data iso:type=\"symbol\">item</Data></Atom></Assert><Query closure=\"existential\"><And><Atom><Rel>p</Rel></Atom><Atom><Rel>q</Rel></Atom><Atom><Rel>r</Rel><Data iso:type=\"number\">1</Data></Atom><Atom><Rel>s</Rel><Data iso:type=\"number\">-2.222342432</Data></Atom><Atom><Rel>t</Rel><Data iso:type=\"string\">\"attached\"</Data></Atom></And></Query><Query closure=\"existential\"><And><Atom><Rel>u</Rel></Atom><Atom><Rel>v</Rel><Var>q</Var></Atom></And></Query>"   XML = "<Assert mapClosure= ...".
```

XML can be pretty printed using a [free online XML pretty
printer](https://codebeautify.org/xmlviewer), as here:

```
<Assert mapClosure=\"universal\">
	<Atom>
		<Rel>a</Rel>
		<Data iso:type=\"symbol\">item</Data>
	</Atom>
	<Atom>
		<Rel>b</Rel>
		<Data iso:type=\"symbol\">item</Data>
	</Atom>
	<Atom>
		<Rel>c</Rel>
		<Data iso:type=\"symbol\">item</Data>
	</Atom>
</Assert>
<Query closure=\"existential\">
	<And>
		<Atom>
			<Rel>p</Rel>
		</Atom>
		<Atom>
			<Rel>q</Rel>
		</Atom>
		<Atom>
			<Rel>r</Rel>
			<Data iso:type=\"number\">1</Data>
		</Atom>
		<Atom>
			<Rel>s</Rel>
			<Data iso:type=\"number\">-2.222342432</Data>
		</Atom>
		<Atom>
			<Rel>t</Rel>
			<Data iso:type=\"string\">\"attached\"</Data>
		</Atom>
	</And>
</Query>
<Query closure=\"existential\">
	<And>
		<Atom>
			<Rel>u</Rel>
		</Atom>
		<Atom>
			<Rel>v</Rel>
			<Var>q</Var>
		</Atom>
	</And>
</Query>
```

The AssertItems and QueryItems lists can then be recovered using this
RuleML/Xml string, with the `\` character added to the end of each
line:

```
?- parse_ruleml(AssertItems, QueryItems,
                "<Assert mapClosure=\"universal\">\
                    <Atom>\
                        <Rel>a</Rel>\
                        <Data iso:type=\"symbol\">item</Data>\
                    </Atom>\
                    <Atom>\
                        <Rel>b</Rel>\
                        <Data iso:type=\"symbol\">item</Data>\
                    </Atom>\
                    <Atom>\
                        <Rel>c</Rel>\
                        <Data iso:type=\"symbol\">item</Data>\
                    </Atom>\
                </Assert>\
                <Query closure=\"existential\">\
                    <And>\
                        <Atom>\
                            <Rel>p</Rel>\
                        </Atom>\
                        <Atom>\
                            <Rel>q</Rel>\
                        </Atom>\
                        <Atom>\
                            <Rel>r</Rel>\
                            <Data iso:type=\"number\">1</Data>\
                        </Atom>\
                        <Atom>\
                            <Rel>s</Rel>\
                            <Data iso:type=\"number\">-2.222342432</Data>\
                        </Atom>\
                        <Atom>\
                            <Rel>t</Rel>\
                            <Data iso:type=\"string\">\"attached\"</Data>\
                        </Atom>\
                    </And>\
                </Query>\
                <Query closure=\"existential\">\
                    <And>\
                        <Atom>\
                            <Rel>u</Rel>\
                        </Atom>\
                        <Atom>\
                            <Rel>v</Rel>\
                            <Var>q</Var>\
                        </Atom>\
                    </And>\
                </Query>").
   AssertItems = [a(item),b(item),c(item)], QueryItems = [(?-p,q,r(1),s(-2.222342432),t("attached")),(?-u,v('$V'(q)))].
```
