0xekez / lisp Goto Github PK
View Code? Open in Web Editor NEWA lisp JIT compiler and interpreter built with cranelift.
A lisp JIT compiler and interpreter built with cranelift.
Having a JIT is nice and makes testing pretty easy but at the end of the day the ability to compile to native object files is very important to me because it opens up the possibility of writing a self hosting version of Lust (this is very far down the line though.)
A branch of the simple jit demo shows approximately how this is done. Based on this I don't believe that doing this will require too much additional work as the architecture seems to be similar enough.
The program
(let cons cons)
(cons 1 2)
yields
error: internal error: use of undeclared variable (0_cons)
Changed strings so that they no longer need the quote in front of them
Here is a nice write up of roughly what I'd imagine. Doing this would serve two purposes:
I think it would be fine to keep the byte code very high level. Environments could remain roughly how they are now and we could possibly avoid typing by still keeping things in an enum. The goal wouldn't be performance so much as it would be to lower the Lust code into a simpler form more for executing and catch some additional errors along the way.
At the moment there is no way to test that errors are being displayed properly because they print to stdout and don't leave much of a trace. As time goes on and there is more need for this sort of thing we should consider adding some sort of btest like unit test framework so that we can compare the output of lust programs to a baseline.
Currently panics on the cleanup branch. Something to do with locations being one past the end I suspect. Not high priority right now.
Recently in lustc we modified let
semantics and added a set
expression. Docs here.
Varadic functions require that we heap allocate function arguments. This is slow. Most existing Lust programs do not use varadic functions - in that situation we don't need to heap allocate arguments.
Trouble with doing this is that it adds a lot of code complexity (two implementations of function calls) and once there is a standard library which will use varadic functions most Lust programs are liable to use varadic functions.
Most operations on lists in Lust occur at the beginning. car
, cdr
, and cons
all operate on the first item in the list. Meanwhile, Rust's vector class is designed for things to change at the end. As a result we're abusing the data structure when we're constantly popping and inserting data at the front.
One way to get around this would be to represent Lust lists as a reversed vector. Under the hood, lists would be represented by Vec
still, but the first item in a Lust list would correspond to the last item in the corresponding vector. I believe this would be markedly more performant.
Last night I tried to see if this would be a simple change, but I don't think it will. There are quite a few places where indexing the complex with varadic functions and etc. It also makes code really ugly to be constantly using the reverse of the index you want. We'd probably be well served to wrap Vec
in some sort of LustVec
class and then use that instead of Vec
.
This would be a good learning experience working with more complex data types in Lust as well.
See docs/grammar.md
for what this ought to look like.
Right now our import function is liable to get caught in a loop if files import each other. This isn't so good. I'd like to change import
to require
like Emacs Lisp. This way we could more clearly indicate that we're just requiring that the file is loaded. import
gives the idea that you're actively evaluating the file when you import it.
lust> -'hello
=> (fn (& args) (fold (fn (a i) (sub a i)) (cdr args) (car args)))
=> hello
I guess this makes sense if we're letting multiple expressions be on a line in the repl but it's not the most straightforward thing.
Reasonably low priority but needs to be done before this can properly parse files and as a precursor for a decent REPL
Currently type checks are inlined for every primitive. This leads to a lot of code being generated. We should likely move this into a function.
We now have heap allocation wired up in lustc
. This means that its time to start thinking about garbage collection. For now I have wrapped malloc
in an alloc
function. In 164 Hilfinger uses a similar method and I believe that later we ought to be able to add some machinery to alloc
to track allocations and later garbage collect.
Is it ok to reuse this under the MIT license? I don't see a license file anywhere
In the interpreter (car ())
and (cdr ())
yield ()
whereas in the compiler both calls result in a type error.
Currently, my preference is for the compilers behavior. It seems like if you ask for the second item of an empty list that is indeed an error. Right now it can be a little confusing but once we get around to improving the compiler's error messages I suspect we can make that error more obvious.
Most environments are small. Vec is lighter than hash map.
The link there to the reference guide gives me 404.
(Also does Lust work running in WASM?)
cargo install
Should evaluate a file and then merge its global symbol table with ours.
Should follow along with Emacs:
https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html
Would make a lot of macros a lot easier and some that were impossible possible.
Optionally we could use ~
to indicate negation, but that seems like a lot of confusion for a little bit of saved time on the tokenizer.
The following program panics because the return value (result of last expression compiled) is a closure:
(let printf (fn (list & args) 1))
Right now at the beginning of compilation we emit all of the primitive functions into the JIT. We don't need to do this. We should add a pass to the compiler that locates primitives that appear in non-head positions of lists and only compiles those ones.
>> (cons 1 1)
(cons 1 1)
^----
| error: expected list, got 1
*--> repl:0:0
Currently errors but should not.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.