···11---
22title: A Formal Grammar of h
33date: 2019-05-19
44-series: conlangs
44+series: h
55---
6677## Introduction
+1
blog/h-language-2019-06-30.markdown
···11---
22title: The h Programming Language
33date: 2019-06-30
44+series: h
45tags:
56 - wasm
67 - release
+269
blog/hlang-nguh.markdown
···11+---
22+title: "The Next-Generation Universal Hlang compiler"
33+date: 2022-12-31
44+series: h
55+tags:
66+ - hlang
77+ - wasm
88+vod:
99+ twitch: https://www.twitch.tv/videos/1693936831
1010+ youtube: https://youtu.be/QY1O2n4tOhE
1111+---
1212+1313+In a world where simple tasks have hundreds of dependencies and most of them are
1414+not documented, everything falls to chaos. The monolithigarchy dictates that
1515+your build times must be slow so that They (the dependocracy) can win over your
1616+hearts and minds with video games that you play during your compile times. One
1717+person gets mad about their string padding library being used by corporations
1818+without paying and then the entire internet explodes for a few days. This is
1919+unsustainable.
2020+2121+hlang is the sledgehammer that will break down this complexity and deliver you a
2222+truly uncompromised development experience.
2323+2424+<xeblog-conv name="Numa" mood="delet">You can't spell _sledgehammer_ without
2525+_h_!</xeblog-conv>
2626+2727+If none of this is making any sense, please read [the rest of the
2828+series](https://xeiaso.net/blog/series/h). This will hopefully help something
2929+make sense.
3030+3131+<xeblog-conv name="Numa" mood="delet">If you need even more context, check [this
3232+page](https://pkg.go.dev/context) for more information.</xeblog-conv>
3333+3434+There was one major flaw with hlang in the past though. It was a hollow shell of
3535+itself and had rot to the slains and arrows of time. The playground stopped
3636+working, so people could not understand the sheer might of hlang by playing with
3737+it.
3838+3939+Lo, behold, a new compiler was born. In this article, I will describe the nguh
4040+compiler and how it revolutionizes the ways that you use hlang for both
4141+professional and personal uses.
4242+4343+<xeblog-conv name="Mara" mood="wat">Wait, what, there _were_ professional users
4444+of hlang???</xeblog-conv>
4545+4646+<xeblog-conv name="Numa" mood="delet">Having 2 years of hlang on your resume
4747+will let you get hired by Google!</xeblog-conv>
4848+4949+## The Old Compiler
5050+5151+The old compiler was a HACK. The main way it worked was by feeding the program
5252+source code as a string to this [Go template](https://pkg.go.dev/text/template):
5353+5454+```
5555+(module
5656+ (import "h" "h" (func $h (param i32)))
5757+ (func $h_main
5858+ (local i32 i32 i32)
5959+ (local.set 0 (i32.const 10))
6060+ (local.set 1 (i32.const 104))
6161+ (local.set 2 (i32.const 39))
6262+ {{ range . -}}
6363+ {{ if eq . 32 -}}
6464+ (call $h (get_local 0))
6565+ {{ end -}}
6666+ {{ if eq . 104 -}}
6767+ (call $h (get_local 1))
6868+ {{ end -}}
6969+ {{ if eq . 39 -}}
7070+ (call $h (get_local 2))
7171+ {{ end -}}
7272+ {{ end -}}
7373+ (call $h (get_local 0))
7474+ )
7575+ (export "h" (func $h_main))
7676+)
7777+```
7878+7979+This template worked by taking the program input _as a string_ and looping over
8080+each character to decide what to do. If it was a space, it would print a
8181+newline. If it was an `h`, it would print `h`. If it was a `'`, it would print a
8282+`'`. Anything else is ignored.
8383+8484+However, this means that the parser was mostly ignored. And the parser spec
8585+compiles to 117 bytes when gzipped, which means that it can fit on a tshirt.
8686+8787+<xeblog-conv name="Numa" mood="delet">That's a savings of 0.8475%!</xeblog-conv>
8888+8989+Additionally, this would then use the command
9090+[`wat2wasm`](https://developer.mozilla.org/en-US/docs/WebAssembly/Text_format_to_wasm)
9191+to compile it to a WebAssembly file instead of doing it directly. This combined
9292+with the fact that the `get_local` instruction was renamed to `local.get` in the
9393+text format some time in the last 2 years means that not only was my compiler
9494+hacky, it didn't work anymore.
9595+9696+<xeblog-conv name="Mara" mood="hacker">Apparently that was renamed before WASM
9797+hit 1.0 and the legacy name was an alias they planned to remove. Guess who
9898+didn't get the memo!</xeblog-conv>
9999+100100+Needless to say, this could be fixed by doing a simple
101101+`s/get_local/local\.get/g` on the source file, but that's not fun. You know
102102+what's really fun? Reverse-engineering a binary file on stream and reassembling
103103+an identical replica in code. That's fun.
104104+105105+## The nguh compiler
106106+107107+On December 31st, 2022, I wrote the nguh compiler [on
108108+stream](https://twitch.tv/princessxen). The nguh (nguh gives u hlang or
109109+Next-Generation Universal Hlang compiler, whichever you prefer) compiler outputs
110110+WebAssembly bytecode directly instead of using `wat2wasm` as a middleman.
111111+112112+<xeblog-conv name="Mara" mood="happy">This means that hlang has even fewer
113113+dependencies!</xeblog-conv>
114114+115115+nguh is supposed to be pronounced with the final sound of `-ing` and `uh`
116116+smashed together. It is not phonetically valid in English. It will take some
117117+practice to say it correctly. I'm not sorry. If you can read IPA, it's
118118+pronounced /ŋə/. The name comes from the youtuber [Agma
119119+Schwa](https://www.youtube.com/@AgmaSchwa)'s show about conlangs named /ŋə/.
120120+121121+To help you understand the architecture of nguh, it will be helpful to get some
122122+context about how WebAssembly files work.
123123+124124+## How WebAssembly files work
125125+126126+<details>
127127+ <summary>What is WebAssembly?</summary>
128128+129129+WebAssembly is a standard that specifies a way to run programs on arbitrary
130130+hardware in a sandboxed way. It is used mainly in web browsers to power things
131131+like YouTube's player component, Twitch stream viewing, and by developers any
132132+time they need to put a block of code into a website without having to rewrite
133133+it in JavaScript.
134134+135135+I'm part of a slowly growing group of developers that want to run WebAssembly
136136+code on the server so that you can take the same `.wasm` file and run it on any
137137+hardware without having to have the source code and a working compiler setup.
138138+139139+hlang is compiled to WebAssembly for no reason in particular.
140140+</details>
141141+142142+At a high level, a WebAssembly module has a bunch of sections in it. Each
143143+section contains information for things like what functions the module exports,
144144+the types of imported fuctions, how much memory the module needs, what should be
145145+in memory by default, and the function bodies for your code. Here's an annotated
146146+disassembly of a hlang binary:
147147+148148+```
149149+0x00, 0x61, 0x73, 0x6d, // \0asm wasm magic number
150150+0x01, 0x00, 0x00, 0x00, // version 1
151151+152152+0x01, // type section
153153+0x08, // 8 bytes long
154154+0x02, // 2 entries
155155+0x60, 0x01, 0x7f, 0x00, // function type 0, 1 i32 param, 0 return
156156+0x60, 0x00, 0x00, // function type 1, 0 param, 0 return
157157+158158+0x02, // import section
159159+0x07, // 7 bytes long
160160+0x01, // 1 entry
161161+0x01, 0x68, // module h
162162+0x01, 0x68, // name h
163163+0x00, // type index
164164+0x00, // function number
165165+166166+0x03, // func section
167167+0x02, // 2 bytes long
168168+0x01, // function 1
169169+0x01, // type 1
170170+171171+0x07, // export section
172172+0x05, // 5 bytes long
173173+0x01, // 1 entry
174174+0x01, 0x68, // "h"
175175+0x00, 0x01, // function 1
176176+177177+0x0a, // code section
178178+0x1b, // 27 bytes long
179179+0x01, // 1 entry
180180+0x19, // 25 bytes long
181181+0x01, // 1 local declaration
182182+0x03, 0x7f, // 3 i32 values - (local i32 i32 i32)
183183+0x41, 0x0a, // i32.const 10 (newline)
184184+0x21, 0x00, // local.set 0
185185+0x41, 0xe8, 0x00, // i32.const 104 (h)
186186+0x21, 0x01, // local.set 1
187187+0x41, 0x27, // i32.const 39 (')
188188+0x21, 0x02, // local.set 2
189189+0x20, 0x01, // local.get 1 push h
190190+0x10, 0x00, // call 0 (putchar)
191191+0x20, 0x00, // local.get 0 push newline
192192+0x10, 0x00, // call 0 (putchar)
193193+0x0b // end of function
194194+```
195195+196196+At a high level, nguh just takes all the needed sections and [puts them in the
197197+target
198198+binary](https://github.com/Xe/x/blob/2fe527950512b97a544d2d59539026514ad59544/cmd/hlang/nguh/compile.go#L53).
199199+Most of the sections are copied verbatim from that disassembly I pasted above
200200+because they don't need any modification for the binary to work.
201201+202202+The exciting part happens when the individual nodes in the hlang syntax tree get
203203+compiled to WebAssembly bytecode. Each node in the tree has maybe its character
204204+to print and maybe a list of child nodes. A syntax tree for hlang could look
205205+like this if it has one character in the program:
206206+207207+```
208208+input: h
209209+H("h")
210210+```
211211+212212+Or it could look like this if there are multiple characters in the program:
213213+214214+```
215215+input: h h h
216216+H{
217217+ "h",
218218+ "h",
219219+ "h",
220220+}
221221+```
222222+223223+This means I need something like this:
224224+225225+```go
226226+// compile AST to wasm
227227+if len(tree.Kids) == 0 {
228228+ if err := compileOneNode(funcBuf, tree); err != nil {
229229+ return nil, err
230230+ }
231231+} else {
232232+ for _, node := range tree.Kids {
233233+ if err := compileOneNode(funcBuf, node); err != nil {
234234+ return nil, err
235235+ }
236236+ }
237237+}
238238+```
239239+240240+This will either read from the root of the tree or all of the tree's children in
241241+order to compile the entire program. The `compileOneNode` function will turn the
242242+text associated with the node into the correlating WASM bytecode (pushing the
243243+relevant character to the stack and then calling the `h.h` (`putchar`) function).
244244+245245+Finally it will generate the end of the function including a trailing newline
246246+and end the `.wasm` file.
247247+248248+<xeblog-conv name="Mara" mood="hacker">Fun fact: the generated binary for a
249249+hlang program that only prints `h` is 69 bytes.</xeblog-conv>
250250+251251+<xeblog-conv name="Numa" mood="delet">NICE!</xeblog-conv>
252252+253253+Here is a base-64 encoded hlang binary in case you find this interesting:
254254+255255+```
256256+AGFzbQEAAAABCAJgAX8AYAAAAgcBAWgBaAAAAwIB
257257+AQcFAQFoAAEKHQEbAQN/QQohAEHoACEBQSchAiAB
258258+EAAgABAAAQEL
259259+```
260260+261261+---
262262+263263+If you want to play with hlang, head to its new home at
264264+[h.within.lgbt](https://h.within.lgbt). If you want to witness things such as
265265+this being created live, follow me [on twitch](https://twitch.tv/princessxen) or
266266+on my VTuber business account at [@xe@vt.social](https://vt.social/@xe).
267267+268268+<xeblog-conv name="Cadey" mood="enby">Happy new year to those that
269269+celebrate!</xeblog-conv>
+1
blog/the-origin-of-h-2015-12-14.markdown
···11---
22title: The Origin of h
33date: 2015-12-14
44+series: h
45---
5667NOTE: There is a [second part](https://xeiaso.net/blog/formal-grammar-of-h-2019-05-19) to this article now with a formal grammar.
+5
dhall/package.dhall
···2323 , title = "Aura"
2424 , description = "PonyvilleFM live DJ recording bot"
2525 }
2626+ , Link::{
2727+ , url = "https://h.within.lgbt"
2828+ , title = "The h Programming Language"
2929+ , description = "An esoteric programming language that compiles to WebAssembly"
3030+ }
2631 , Link::{
2732 , url = "https://github.com/Xe/olin"
2833 , title = "Olin"