170 lines
6.4 KiB
Markdown
170 lines
6.4 KiB
Markdown
|
---
|
||
|
title: "pa'i: hello world!"
|
||
|
date: 2020-02-22
|
||
|
series: olin
|
||
|
tags:
|
||
|
- rust
|
||
|
- wasm
|
||
|
- dhall
|
||
|
---
|
||
|
|
||
|
# pa'i: hello world!
|
||
|
|
||
|
It's been a while since I gave an update on the Olin ecosystem (which now
|
||
|
exists, apparently). Not much has really gone on with it for the last few
|
||
|
months. However, recently I've decided to tackle one of the core problems of
|
||
|
Olin's implementation in Go: execution speed.
|
||
|
|
||
|
Originally I was going to try and handle this with
|
||
|
["hyperjit"](https://innative.dev), but support for linking C++ programs into Go
|
||
|
is always questionable at best. All of the WebAssembly compiling and
|
||
|
running tooling has been written in Rust, and as far as I know I was the only
|
||
|
holdout still using Go. This left me kinda stranded and on my own, seeing as the
|
||
|
libraries that I was using were starting to die.
|
||
|
|
||
|
I have been following the [wasmer][wasmer] project for a while and thanks to
|
||
|
their recent [custom ABI sample][wasmercustomabisample], I was able to start
|
||
|
re-implementing the Olin API in it. Wasmer uses a JIT for handling WebAssembly,
|
||
|
so I'm able to completely destroy the original Go implementation in terms of
|
||
|
performance. I call this newer, faster runtime pa'i (/pa.hi/, paw-hee), which
|
||
|
is a [Lojban][lojban] [rafsi][rafsi] for the word prami which means love.
|
||
|
|
||
|
[wasmer]: https://wasmer.io
|
||
|
[wasmercustomabisample]: https://github.com/wasmerio/wasmer-rust-customabi-example
|
||
|
[lojban]: https://mw.lojban.org/papri/Lojban
|
||
|
[rafsi]: http://lojban.org/publications/cll/cll_v1.1_xhtml-section-chunks/section-rafsi.html
|
||
|
|
||
|
[pa'i][pahi] is written in [Rust][rust]. It is built with [Nix][nix]. It
|
||
|
requires a nightly version of Rust because the WebAssembly code it compiles
|
||
|
requires it. However, because it is built with Nix, this quickly becomes a
|
||
|
non-issue. You can build pa'i by doing the following:
|
||
|
|
||
|
[pahi]: https://github.com/Xe/pahi
|
||
|
[rust]: https://www.rust-lang.org
|
||
|
[nix]: https://nixos.org/nix/
|
||
|
|
||
|
```console
|
||
|
$ git clone git@github.com:Xe/pahi
|
||
|
$ cd pahi
|
||
|
$ nix-build
|
||
|
```
|
||
|
|
||
|
and then `nix-build` will take care of:
|
||
|
|
||
|
- downloading the pinned nightly version of the rust compiler
|
||
|
- building the reference Olin interpreter
|
||
|
- building the pa'i runtime
|
||
|
- building a small suite of sample programs
|
||
|
- building the documentation from [dhall][dhall] files
|
||
|
- building a small test runner
|
||
|
|
||
|
[dhall]: https://dhall-lang.org
|
||
|
|
||
|
If you want to try this out in a more predictable environment, you can also
|
||
|
`nix-build docker.nix`. This will create a Docker image as the result of the Nix
|
||
|
build. This docker image includes [the pa'i composite package][pahidefaultnix],
|
||
|
bash, coreutils and `dhall-to-json` (which is required by the test runner).
|
||
|
|
||
|
[pahidefaultnix]: https://github.com/Xe/pahi/blob/master/default.nix
|
||
|
|
||
|
I'm actually really proud of how the documentation generation works. The
|
||
|
[cwa-spec folder in Olin][cwaspecolin] was done very ad-hoc and was only
|
||
|
consistent because there was a template. This time functions, types, errors,
|
||
|
namespaces and the underlying WebAssembly types they boil down to are all
|
||
|
implemented as Dhall records. For example, here's the definition of a
|
||
|
[namespace][cwans] [in Dhall][nsdhall]:
|
||
|
|
||
|
[cwaspecolin]: https://github.com/Xe/olin/tree/master/docs/cwa-spec
|
||
|
[cwans]: https://github.com/Xe/pahi/tree/master/olin-spec#namespaces
|
||
|
[nsdhall]: https://github.com/Xe/pahi/blob/5ea1184c09df4e657524f9d5e77941cda5560d9a/olin-spec/types/ns.dhall
|
||
|
|
||
|
```
|
||
|
let func = ./func.dhall
|
||
|
|
||
|
in { Type = { name : Text, desc : Text, funcs : List func.Type }
|
||
|
, default =
|
||
|
{ name = "unknown"
|
||
|
, desc = "please fill in the desc field"
|
||
|
, funcs = [] : List func.Type
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
which gets rendered to [Markdown][markdown] using
|
||
|
[`renderNSToMD.dhall`][shownsasmd]:
|
||
|
|
||
|
[markdown]: https://github.github.com/gfm/
|
||
|
[shownsasmd]: https://github.com/Xe/pahi/blob/5ea1184c09df4e657524f9d5e77941cda5560d9a/olin-spec/types/renderNSToMD.dhall
|
||
|
|
||
|
```
|
||
|
let ns = ./ns.dhall
|
||
|
|
||
|
let func = ./func.dhall
|
||
|
|
||
|
let type = ./type.dhall
|
||
|
|
||
|
let showFunc = ./renderFuncToMD.dhall
|
||
|
|
||
|
let Prelude = ../Prelude.dhall
|
||
|
|
||
|
let toList = Prelude.Text.concatMapSep "\n" func.Type showFunc
|
||
|
|
||
|
let show
|
||
|
: ns.Type → Text
|
||
|
= λ(namespace : ns.Type)
|
||
|
→ ''
|
||
|
# ${namespace.name}
|
||
|
|
||
|
${namespace.desc}
|
||
|
|
||
|
${toList namespace.funcs}
|
||
|
''
|
||
|
|
||
|
in show
|
||
|
```
|
||
|
|
||
|
This would render [the logging namespace][logns] as [this markdown][lognsmd].
|
||
|
|
||
|
[logns]: https://github.com/Xe/pahi/blob/5ea1184c09df4e657524f9d5e77941cda5560d9a/olin-spec/ns/log.dhall
|
||
|
[lognsmd]: https://github.com/Xe/pahi/blob/5ea1184c09df4e657524f9d5e77941cda5560d9a/olin-spec/ns/log.md
|
||
|
|
||
|
It seems like overkill to document things like this (and at some level it is),
|
||
|
but I plan to take advantage of this later when I need to do things like
|
||
|
generate C/Rust/Go/TinyGo bindings for the entire specification at once. I also
|
||
|
have always wanted to document something so precisely like this, and now I get
|
||
|
the chance.
|
||
|
|
||
|
pa'i is just over a week old at this point, and as such it is NOT
|
||
|
[feature-complete with the reference Olin interpreter][compattodo]. I'm working
|
||
|
on it though. I'm kinda burnt out from work, and even though working on this
|
||
|
project helps me relax (don't ask me how, I don't understand either) I have
|
||
|
limits and will take this slowly and carefully to ensure that it stays
|
||
|
compatible with all of the code I have already written in Olin's repo. Thanks to
|
||
|
[go-flag][goflags], I might actually be able to get it mostly flag-compatible.
|
||
|
We'll see though.
|
||
|
|
||
|
[compattodo]: https://github.com/Xe/pahi/issues/1
|
||
|
[goflags]: https://crates.io/crates/go-flag
|
||
|
|
||
|
I have also designed a placeholder logo for pa'i. Here it is:
|
||
|
|
||
|
<center>![the logo for pa'i](/static/blog/pahi-logo.png)</center>
|
||
|
|
||
|
It might be changed in the future, but this is what I am going with for now. The
|
||
|
circuit traces all spell out messages of love (inspired from the Senzar runes of
|
||
|
the [WingMakers][wingmakers]). The text on top of the microprocessor reads pa'i
|
||
|
in [zbalermorna][zbalermorna], a constructed writing script for Lojban. The text
|
||
|
on the side probably needs to be revised, but it says something along the lines
|
||
|
of "a future after programs".
|
||
|
|
||
|
[wingmakers]: https://www.wingmakers.us/wingmakersorig/wingmakers/ancient_arrow_project.shtml
|
||
|
[zbalermorna]: https://mw.lojban.org/images/b/b3/ZLM4_Writeup_v2.pdf
|
||
|
|
||
|
pa'i is chugging along. When I have closed the [compatibility todo
|
||
|
list][compattodo] for all of the Olin API calls, I'll write more. For now, pa'i
|
||
|
is a very complicated tool that lets you print "Hello, world" in new and
|
||
|
exciting ways (this will change once I get resource calls into it), but it's
|
||
|
getting there.
|
||
|
|
||
|
I hope this was interesting. Be well.
|