It is an excellent book and one of the canonical texts on the subject. My only suggestion for the "Lox" language would be to include an implementation of arrays, and preferably also hash/dict arrays. Other than that, the book contains everything you need to know about implementing a programming language.
It's hard to say what "that hard" should be considered, but the book's first half involves Java reflection, which isn't obvious code to port to different languages in my opinion.
Does it? I know it uses metaprogramming (a Java program that outputs another Java program), but that’s probably easier in other languages than in Java. In my Python implementation I was able to significantly simplify that part of the code by using `eval`.
I understand. I wasn't a Java person when I read that book, yet I still prefer Java over more esoteric options. If Golang is easier for you to understand (no OOP), then I can recommend this one:
Wren, the topic of the post, is positioned as a descendant of Smalltalk, the most OOP language of them all. The author clearly finds the OOP paradigm important.
This is awesome. Thank you for sharing. I have been working on a small interpreted language for shell scripts with lots of help from Claude Code. The main idea is to automatically generate the cli interface for the scripts based on function definitions. However, I'm far from a programming languages expert, so I've been a bit hesitant to share my work. Going to give this book a read this week to see how far I am. Thank you!
Yeah, my understanding is that the bytecode interpreter in the second half of the book is essentially a stripped-down version of the Wren virtual machine.
I was working on a custom runtime for minimal wasm apps recently. I didn't want to have to write all apps in C or Rust, so I went looking for tiny scripting languages. Lua is pretty small, but I wasn't able to get it to compile to wasm IIRC due to POSIX dependencies. This turned out to be quite easy with Wren[0].
That's unusual that you struggled to build Lua. Lua is primarily C89, and used on non-POSIX microcontrollers for example. There are some optional bits of the standard library you would have to leave out - module loading uses dlopen(). This is done simply by defining the right feature macros for your target environment: https://www.lua.org/source/5.4/luaconf.h.html
Wow, I really went into a rabbithole after opening up your hackernews profile seeing indiebits and remembering my time scouring your github awesome tunneling page and then I went to discourse forum and somehow found new resources about self hosting and saw yunohost and others as well all in matter of minutes.
Thank you for your service in self-hosting. I had so much fun trying to break nats with awesome tunneling projects and I even created my own but it actually requires a custom patch of ssh with pinggy to work without nat (let me know if you are interested, as I had discovered this a year ago but I just am a little lazy haha)
I have created only one issue on the awesome tunneling but let me tell you some of them don't work in nat's/broke
Just created the bearblog post, not sure why the name but just wanted to say thank you and wanted to share any knowledge I have in the process as well to strengthen the hacking/tinkering community. Thanks once again
Also its just a bit of a coincidence that we are talking on a wren page as I was literally reading about wren once again and playing with it just yesterday and joined their discord server yesterday or day before that to tinker with it. Wren is really elegant and I feel like I want to write more software which integrates it instead of lua as a thought experiment as well and wasm seems a cool idea too in that regards.
I once considered Wren for a situation where I (to a first approximation) wanted to allow users to write 'plugins' that link against my internal C application symbols but using a language focusing more on ease of use (rather than C).
Unfortunately, neither Wren nor any of the other major 'embeddable scripting languages' (e.g., Lua) were really a good fit for this, because they commit fully to the 'all-numbers-are-floats' thing and generally don't seem to even try to provide a general equivalent to the C++ `extern "C" { ... }` thing.
Of course, I know this isn't really the target use case of Wren/Lua/etc., but if anyone knows of a good embeddable scripting language for this I'd love to hear about it. Eventually I went with CPython (which provides ctypes to solve my problem) but it's a huge pain to embed properly.
This seems like a nice alternative to Lua. I've always liked embedding Lua in other software, but I confess I have never really liked Lua as a language.
I really like the sound of Wren, but you may also want to look into Squirrel, it's basically Lua re-imagined/reimplemented but without all the Lua quirks and with C-style syntax (but it still has optional lua-style prototypes, which means it ends up very similar to Javascript). Its embedding API is largely a copy of Lua's. There is also an active fork called Quirrel that makes the language more like Python.
There are loads of scripting languages but very few of them have an embedding API as powerful as Lua or Squirrel's. (My benchmarks: what's the overhead of a userdata pointer? Is there a proper debug API? Can you suspend a co-routine from inside a called C function? Very few languages even have coroutines.) Last I looked at it years ago, Wren was one of the best.
Of course, the most featureful embedding API of all belongs to LuaJIT.
Most recent commit on the github[0] was only 11 months ago.
Also, it's not a javascript framework, a stable software doesn't have to update often. Look at Lua, most people still use Lua 5.1 and that was released in 2006.
It's not being actively developed but gets some occasional patches on Github. It's mature (e.g. was used for a number of Valve's games). If you want an actively improving language, look at Quirrel.
Yeah, Lua's implementation is fantastic - but the language is "quirky" at best.
Wren looks a bit more orthodox, although it's heavily built around class-based OOP - you can't even define and call a top-level function without extra syntax to (1) turn it into an object, and (2) call one of that object's methods:
var sayHello = Fn.new { System.print("hello") }
sayHello.call() //> hello
wren has that minimalism from lua and syntax familarity from js that i always want to have in a scripting language. I was playing with it to build a raylib binding for it using zig a while ago and the language experience was too nice. You can checkout some examples of what you can achieve with raylib + wren here. https://github.com/jossephus/talon
This looks super cool up until I got to the point where it says inherited classes don’t share the same metatable. Meaning if you want to provide the same method on your inherited classes, you have to write the same thing and do a super.method() which means a lot of work if you’re into OO design so I’m not sure if classes is the right construct here. Am I wrong or did I miss something from the documentation? Other than that it looks like fun to use as an embedded scripting engine.
you probably meant metaclass and according to the doc classes inheritance don't have surprising behaviors. And about the metaclass not being inherited here are the implication:
...In more prosaic terms, this means that static methods are not inherited.
I think I read that Wren's creator deliberately avoided "the metaclass hierarchy matches the class hierarchy" (as used in Smalltalk and taken to an extreme in Ruby [0]) because the authors of Smalltalk have come to regret that design?
I'd be interested to hear more details about the issues with that approach. I've not had any problems with it, and occasionally found it useful. For example, in one situation I needed a hierarchy of static constructors that matched the hierarchy of instance constructors.
[0] Ruby also has "the meta-metaclass hierarchy matches the metaclass hierarchy" and "the meta-meta-metaclass hierarchy..." ad infinitum. It's a beautiful design really - it means that in Ruby (unlike Smalltalk), it's always true that "the superclass of the metaclass is the metaclass of the superclass".
Edit: Here's the quote I was remembering:
> My hunch is that we don't want metaclass inheritance. From talking to a few old Smalltalkers, they generally consider it a mistake there. Also, Java, C++, C#, etc. have semantics more similar to not allowing metaclass inheritance (in other words, static methods aren't inherited), and it seems to work well there.
Static method inheritance is one thing. Member method inheritance (or lack there of) makes it long in the tooth to work with if you want to represent covariant classes that share methods.
Wren does have instance method inheritance. It's implemented differently from most scripting languages, though. The implementation is more like a statically-typed language, for performance reasons:
I would love to replace JS as the scripting language in one of my native macOS apps and I wonder if Wren would be suitable.
The two biggest questions I’d have are:
1) how easy it would be to bridge Obj-C objects to Wren-space and vice versa (a big win of using JavascriptCore)
2) how easy would it be to implement script debugging? This is not exactly a strength of Javascript core but it is at least possible by connecting the Safari web inspector.
There’s lots I don’t like about JS and JSCore but i’ve yet to find a better alternative.
The first time I saw Wren was as an option for programming inside TIC-80. It caught my attention. I recently saw it again being mentioned by Gustavo (from pikuma.com) in his compilers course. Neat language and the VM code in C is quite easy to understand.
[0] https://craftinginterpreters.com/
(There are fewer options for the second half, since you need more control over memory management.)
Does it? I know it uses metaprogramming (a Java program that outputs another Java program), but that’s probably easier in other languages than in Java. In my Python implementation I was able to significantly simplify that part of the code by using `eval`.
https://interpreterbook.com/
BTW, I'm not the author of either of those books, but I have read both of them.
https://github.com/codr7/shi
[0] https://gameprogrammingpatterns.com/
I thought his focus was Dart these days given being employed by Google.
[0]: https://github.com/wren-lang/wren/issues/1199
You may also be interested in this project: https://github.com/fengari-lua/fengari
Thank you for your service in self-hosting. I had so much fun trying to break nats with awesome tunneling projects and I even created my own but it actually requires a custom patch of ssh with pinggy to work without nat (let me know if you are interested, as I had discovered this a year ago but I just am a little lazy haha)
I have created only one issue on the awesome tunneling but let me tell you some of them don't work in nat's/broke
https://freedomhascost.bearblog.dev/
Just created the bearblog post, not sure why the name but just wanted to say thank you and wanted to share any knowledge I have in the process as well to strengthen the hacking/tinkering community. Thanks once again
Also its just a bit of a coincidence that we are talking on a wren page as I was literally reading about wren once again and playing with it just yesterday and joined their discord server yesterday or day before that to tinker with it. Wren is really elegant and I feel like I want to write more software which integrates it instead of lua as a thought experiment as well and wasm seems a cool idea too in that regards.
2020 (122 points, 54 comments) https://news.ycombinator.com/item?id=23660464
Unfortunately, neither Wren nor any of the other major 'embeddable scripting languages' (e.g., Lua) were really a good fit for this, because they commit fully to the 'all-numbers-are-floats' thing and generally don't seem to even try to provide a general equivalent to the C++ `extern "C" { ... }` thing.
Of course, I know this isn't really the target use case of Wren/Lua/etc., but if anyone knows of a good embeddable scripting language for this I'd love to hear about it. Eventually I went with CPython (which provides ctypes to solve my problem) but it's a huge pain to embed properly.
Ones that might be off interest to you are UMKA, tcl, and maybe berry.
That sounds a lot like what LuaJIT’s FFI provides: https://luajit.org/ext_ffi.html
There are loads of scripting languages but very few of them have an embedding API as powerful as Lua or Squirrel's. (My benchmarks: what's the overhead of a userdata pointer? Is there a proper debug API? Can you suspend a co-routine from inside a called C function? Very few languages even have coroutines.) Last I looked at it years ago, Wren was one of the best. Of course, the most featureful embedding API of all belongs to LuaJIT.
Is it still active? Last release was in 2022...
Also, it's not a javascript framework, a stable software doesn't have to update often. Look at Lua, most people still use Lua 5.1 and that was released in 2006.
[0] https://github.com/albertodemichelis/squirrel
Wren looks a bit more orthodox, although it's heavily built around class-based OOP - you can't even define and call a top-level function without extra syntax to (1) turn it into an object, and (2) call one of that object's methods:
[1] https://rosettacode.org/wiki/Rosetta_Code/Rank_languages_by_...
I'd be interested to hear more details about the issues with that approach. I've not had any problems with it, and occasionally found it useful. For example, in one situation I needed a hierarchy of static constructors that matched the hierarchy of instance constructors.
[0] Ruby also has "the meta-metaclass hierarchy matches the metaclass hierarchy" and "the meta-meta-metaclass hierarchy..." ad infinitum. It's a beautiful design really - it means that in Ruby (unlike Smalltalk), it's always true that "the superclass of the metaclass is the metaclass of the superclass".
Edit: Here's the quote I was remembering:
> My hunch is that we don't want metaclass inheritance. From talking to a few old Smalltalkers, they generally consider it a mistake there. Also, Java, C++, C#, etc. have semantics more similar to not allowing metaclass inheritance (in other words, static methods aren't inherited), and it seems to work well there.
https://groups.google.com/g/wren-lang/c/LkKg51fEUg4/m/0GOK0P...
https://wren.io/performance.html#copy-down-inheritance
The two biggest questions I’d have are:
1) how easy it would be to bridge Obj-C objects to Wren-space and vice versa (a big win of using JavascriptCore) 2) how easy would it be to implement script debugging? This is not exactly a strength of Javascript core but it is at least possible by connecting the Safari web inspector.
There’s lots I don’t like about JS and JSCore but i’ve yet to find a better alternative.