Teaching Python to the Dogelog Runtime

We had that feeling that the full potential of the Dogelog runtime was not yet demonstrated. Although there was a lot of progress concerning the Dogelog runtime over the last weeks we 
![teach_doge.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416192/e0829a46-6aef-1490-257b-4aebff02a80c.jpeg)
were only working for the JavaScript platform. So we started a new side quest porting the Dogelog runtime to the Python language. This would demonstrate that cross compiling needs less work.

## Cross Compiling Python

For JavaScript Dogelog runtime consists of the cross compiled Prolog texts loader.p and compiler.p. And the handwritten JavaScript code machine.js and special.js. We use our Java based Prolog system Jekejeke Prolog to cross compile via the Prolog text main.p:

    +------------+   compiler.p +-------------+ 
    | loader.p   |   main.p     | loader.js   |
    | compiler.p | -----------> | compiler.js |
    +------------+              +-------------+
                                | machine.js  |
                                | special.js  |
                                +-------------+

We decided to make our hands dirty and embark into a new Python version of the Dogelog runtime. We only had to create a new Prolog text mainpy.p that does the cross compilation backed. But for cross compilation the Python version uses the same compiler frontend compiler.p:

    +------------+   compiler.p +-------------+ 
    | loader.p   |   mainpy.p   | loader.py   |
    | compiler.p | -----------> | compiler.py |
    +------------+              +-------------+
                                | machine.py  |
                                | special.py  |
                                +-------------+

What we then had to manually write was machine.py and special.py. What help writing this Python code is the closeness of Python and JavaScript. Both have arrays and even the array notation `[e1, .., en]`. And both have dicts and even the dict notation `{k1:v1, .., kn:en}`.

## String Escape
Writing the Python version took us a couple of weeks. Our small minded transpiler approach saw some limits concering Python strings. An enabling idea of the transpiler was to use `'$STR'/1` compounds to emit transpiled code. The `'$STR'/1` compound was developed for Jekejeke Prolog to
easily emit and recognize JSON. 

We had to abandon it and go new ways. The main trigger was some incompatibility of Python with JSON. Python didn't understand '\/' correctly and what our new Python version of the transpiler produced didn't work. The Python escape rules are only:

- **Escaping meta and control characters:** (Used)  
  `\'` etc.. and `\n` etc..
- **Escaping for byte characters:** (Used)    
  `\xHH`, for values <= 0xFF.
- **Escaping via basic plane unicode:** (Used)  
  `\uHHHH`, for values =< 0xFFFF
- **Escaping via full unicode:** (Used)  
  `\UHHHHHHHH`, no need for surrogate pairs.

We decided to abandon '$STR'/1 and simply created an atom that includes the double quotes '"' on both sides. The routine that does that reads as follows:

```prolog
escape_atom(X, Y) :-
   atom_codes(X, L),
   escape_codes(L, R, [0'"]),
   atom_codes(Y, [0'"|R]).
```

## Clause Indexing Benchmark

Basically we did not go with testing Prolog arithmetic but rather tested a Datalog-ish example. The problem is seen in this graphic, its deciding whether one node is ancestor to another node:

![graph_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416192/15334a85-8e03-20fa-dd63-9c56aa357a6b.png)

A tree topology is ideal for testing some clause indexing, since such clause indexing should return a clause set with zero or one member when going from child to parent, and return a clause set with zero or two members when going from parent to child. Without indexing the full edge clause set will be searched.

We were then running anc2/2 and anc/2 with clause indexing. We created a binary tree with 513 vertices and 512 edges and were then running the test 100 times. Results are in ms:
![ress_indexing.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416192/a7dfe63b-4e75-f9a4-0e6c-336c2ec1f480.png)
Both JavaScript and Python can utilize the clause indexes and digest a much larger tree and more iterations in a shorter time. But the JavaScript version clearly beats the Python version, is much faster.

## Conclusions

It could be that JavaScript has a better affinity to the Dogelog runtime. For example we could use JavaScript (===)/2 directly to realize the Prolog (==)/2 whereas for Python we had to define:

```python
def atomic_equal(alpha, beta):
    return type(alpha) is type(beta) and alpha == beta
```
Further factors could be better memory management in JavaScript and better JIT code generation in JavaScript. Also JavaScript does  code specialization for smallint during JIT compilation, which is important for the Dogelog runtime interpreter loop.

**Open Source: Python Version of the Dogelog runtime**
https://github.com/jburse/dogelog-moon/tree/main/devel/runtimepy

**Python Version of Dogelog Runtime clause indexing**
https://twitter.com/dogelogch/status/1428721071201660929

**Preview: String Escape in JavaScript and Python. (Jekejeke)**
https://www.facebook.com/groups/dogelog