diff --git a/.gitignore b/.gitignore index 06565d0..7e5ed80 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ cw.tar .DS_Store /result-* /result +.#* diff --git a/blog/pahi-hello-world-2020-02-22.markdown b/blog/pahi-hello-world-2020-02-22.markdown new file mode 100644 index 0000000..a8db828 --- /dev/null +++ b/blog/pahi-hello-world-2020-02-22.markdown @@ -0,0 +1,169 @@ +--- +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: + +