Browse Source

Finish blaze lisp article

master
Riyyi 2 weeks ago
parent
commit
5aa314e40e
  1. 77
      content/articles/blaze-lisp.md
  2. 2
      nuxt.config.ts
  3. BIN
      public/img/mal-steps.png

77
content/articles/blaze-lisp.md

@ -3,7 +3,7 @@ title: "blaze lisp"
description: "An implementation of the MAL (Make a Lisp) project."
navigation: false
date: "2023-03-18"
img: "/img/.png"
img: "/img/mal-steps.png"
tags:
- C++20
- CMake
@ -17,4 +17,77 @@ Repository at
[Gitea](https://git.riyyi.com/riyyi/blaze){target="_blank"}.
</small>
TODO
After having implemented the JSON serializer for my [utility
library](/articles/utility-library), I became interested in interpreters. The
utility library just has the `tokenization` step of an interpreter, so my tought
was, what's next? That's right, `parsing`.
Having used Emacs quite a bit, I wasn't shy of Lisp. Then, I came across the MAL
([Make a Lisp](https://github.com/kanaka/mal){target="_blank"}) project, and
decided to look into it. The project lays out the implementation steps of making
a Lisp programming language in 10 or so steps and also provides you with unit
tests that have to pass to proceed to the next step. There are also a bunch of
reference implementations to refer to, in case you get stuck.
Feeling like implementing a fully interpreted language was a bit of an
undertaking and realizing that in a Lisp `parsing` and `interpreting` is
basically combined into one step, it seemed achievable and I decided to give the
MAL project a go.
The final architechture that has to be implemented is pictured below.
<div class="row">
<div class="col-lg-9 col-xl-6">
![](/img/mal-steps.png "")
</div>
</div>
I managed to do a full implementation, including `variables`, `if` statements,
`loops`, `functions`, `try/catch` exceptions, `lists`, `arrays`, `hash-maps` and
even `macros`.
With the REPL you can try things out and play around easily.
```
./repl
Blaze [C++]
user>
```
```elisp
user> 123
123
user> (+ 1 2.5)
3.5
user> (- 10 (- 5 3))
8
user> "hello world"
"hello world"
user> (= 2 3)
true
user> (if (> 2 4) "yes" "no")
"no"
user> (count (list 3 6 2 9))
4
user> (count '(3 6 2 9)) ; list shorthand
4
user> (list? [2.1 nil "text"]) ; array / vector
false
user> {:a (+ 7 8)} ; hash-map
{"a" 15}
user> (def! mul (fn* [x y] (* x y))) ; defining a function
#<user-function>(0x5f35f38815d0)
user> (mul 4 5)
20
```
This project was really interesting and the language is quite powerful, powerful
enough to accomplish self-hosting! This means that an interpreter (or rather,
eval+apply) _for_ this language, can be written _in_ the language.
If you're curious about reading more examples, a good place is probably the
testsuite for the project, those have a bunch of unit tests and are available
[here](https://github.com/kanaka/mal/tree/master/impls/tests).

2
nuxt.config.ts

@ -15,7 +15,7 @@ export default defineNuxtConfig({
},
langs: [
// https://github.com/shikijs/shiki/blob/main/packages/langs/package.json
"c", "cpp", "css", "html", "js", "json", "lua", "md", "mdc", "php", "python", "shell", "ts", "vue", "yaml"
"c", "cpp", "css", "elisp", "html", "js", "json", "lua", "md", "mdc", "php", "python", "shell", "ts", "vue", "yaml"
]
},
toc: {

BIN
public/img/mal-steps.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Loading…
Cancel
Save