9 ms·
Elk: A low footprint JavaScript engine for embedded systems
- stathibus 5y agoWhy?
- laurent123456 5y ago> Instead of writing firmware code in C/C++, Elk allows to develop in JavaScript. Another use case is providing customers with a secure, protected scripting environment for product customisation.
- stathibus 5y agoRight, but why would anyone want to do that? Who thinks that JavaScript is a good choice for this?
- umvi 5y agoWhy is JavaScript a bad choice for this?
- wyager 5y agoMany reasons occur to me, but the top few would be: * Lua already exists and is better suited to this * JS is a relatively complicated language to evaluate * JS requires a large amount of dynamic allocation * JS isn't really the first thing (or in the top 25 things) I would pick when developing on a platform where I wasn't already stuck with it
- kennywinker 5y ago- JS requires a large amount of dynamic allocation One of the top listed features of this interpreter is a fixed memory footprint - JS is a relatively complicated language to evaluate In developing this interpreter they eliminated some of the languages features to make it simpler.
- q-rews 5y ago> In developing this interpreter they eliminated some of the languages features to make it simpler. That means you can't run general-purpose code safely, which means you should probably write/rewrite/adapt it, which means you might as well use a different language. I'm a JS developer, but the parent might have a point here. Why run something like this in production when you're likely to end up in unexpected situations? Either a runtime is compliant, or you're going to have a bad time. The project is cool, but I wouldn't use it as an example for what JS can do.
- raxxorrax 5y ago> One of the top listed features of this interpreter is a fixed memory footprint In embedded systems that is often a necessity but calling it a feature instead of a constraint is a good idea.
- thisismyaccpunt 5y agoThat's just like your opinion man. It would be my first choice.
- tyingq 5y agoI imagine it's nice for things like a product that allows some amount of scripted control by end users.
- kennywinker 5y agoPeople who know javascript
- edoceo 5y agoAnd can now run in a tiny engine!
- pjmlp 5y agoPeople that grew up with BASIC, z80 and 6502 Assembly and know C isn't the answer for everything. The example with ESP32 is quite, the hardware is much more powerful than pre-Windows PCs, so why pretend it is something where C and Assembly are the only answer, when MS-DOS had plenty of languages to chose from.
- stathibus 5y agoOk that's an argument for other languages, but not for JavaScript. JS is not good.
- _448 5y agoJust out of curiousity, how is Pike[0] for this type of use-case? [0] https://pike.lysator.liu.se/development/git/ https://pike.lysator.liu.se/development/git/
- BoorishBears 5y agoLook up how many Js basics tutorials there are, then check how many Pike basics tutorials there are
- jlund-molfese 5y agoPrototyping and hobby use are the two obvious use cases I can think of.
- bArray 5y agoI can imagine this would be great if you want to have multiple tiny apps running on a small embedded device - even with some basic multi-tasking! This is actually super cool. Literally just yesterday I was trying to find the equivalent for Java, byte code or otherwise. I want to attempt to run several nano JVM apps on an ESP32, but I'm starting to think that it might not be possible. Many years ago now I ran a custom 'script runner' that fit into 512 bytes of assembly language for a custom kernel (that was also 512 bytes) [1]. I would really like to play with something like Elk and see what can be done! [1] https://bitbucket.org/danielbarry/saxoperatingsystem/src/master/PROGRAMS/RUN/RUN.ASM https://bitbucket.org/danielbarry/saxoperatingsystem/src/mas...
- wyager 5y agoIt seems to me that embedded Lua would be a more appropriate choice, and barring that, there is already a quite robust embedded Python implementation. Don't get me wrong, this is a cool project, but I don't see why you would ever choose to use JS in an embedded context except for fun. The arguments for using lua or micropython are already very narrowly applicable.
- afavour 5y agoSeems inarguable to me that JavaScript is much more widely known and adopted than Lua. So it makes sense to use JS in 'toy' like environments where someone is learning an embedded platform.
- CameronNemo 5y agoJS is more common, but this is not a complete implementation. So those skills may not transfer 100%.
- saagarjha 5y agoBut they certainly will more than they would to a completely new language…
- 5y ago
- deleted 5y ago[deleted]
- edoceo 5y ago> Anything that good hackers would find interesting. Totally on topic. I dislike JS but this is rad. And like upthread said, clean understandable implementation. Very educational.
- bsder 5y agoBecause "20KB on flash/disk, about 100 bytes RAM" is smaller than practically anything out there in the space. Forth is at that size. Tcl implementations are at least triple that. As are all the Schemes I have seen. Lua similarly. Anything I've missed?
- seabird 5y agoBecause your system may require that you can change code at runtime without reflashing your micro. I very, very much dislike JavaScript, but it's not an outlandish requirement and there's not a lot of (what I would consider) great options in that arena with expansive C interop (which you would need for a "real" application). There's basically JavaScript, Python, and Lua. There's plenty of other stuff out there, but none with the same amount of backing as those three. Embedded development is the bat country of software. You will definitely have to do some unsavory things to get where you're trying to go.
- hatch_q 5y agoWouldn't there be better options for that? python, lua, tcl, perl, ... ?
- eatonphil 5y agoThis implementation is nuts. A decent chunk (but still very small subset) of ES5 in a single file, under 1400 lines of very readable C code. It includes a mark-and-sweep GC and an FFI. It doesn't have an AST or a bytecode VM. It just interprets directly off of source code. Take a look: https://github.com/cesanta/elk/blob/master/elk.c https://github.com/cesanta/elk/blob/master/elk.c. The first time I scanned through the file and thought there was nothing there. It does an entire implementation in the same amount of code that most implementations do a parser alone (but yes, it implements way less than a 100% spec compliant parser does). This implementation really sets a new bar for me in terms of compact-but-readable language implementations. Separately, this isn't even Cesanta's only embedded JavaScript implementation. They also have: https://github.com/cesanta/mjs https://github.com/cesanta/mjs. mjs is a bit more complete and does have a bytecode VM and thus the source has many more lines of code and files.
- armchairhacker 5y agoWhy JavaScript? Why not some other DSL, and if you need you can convert a subset of ES6 to that DSL? JS has some features that wouldn't make it ideal (e.g. no difference between ints and floats). I don't think it would be hard for developers to learn slightly different syntax. If it's a big subset or the full language, I can see the benefits of using existing JS apps. But with a small subset and presumably for a small computer, I don't think most of those apps would work anyways.
- raxxorrax 5y agoJS certainly isn't ideal for µC, but it can work as shown here. A problem in the embedded world is finding developers as it is, maybe this could help? I believe Arduino has a C++ transpiler. I would almost prefer Javascript here, although you could just use C as a subset.
- pjmlp 5y agoArduino has a C++ compiler, whatever the scripts are called, they are a plain C++ library. Plenty of modern µC, e.g. ESP32, are more powerful than computers like these ones, https://en.wikipedia.org/wiki/PC1512 https://en.wikipedia.org/wiki/PC1512 As exercise for the reader check the programming languages available up to MS-DOS 6.22. It is about time to move on from the mindset that µC are only PICs with 4 KB.
- raxxorrax 5y agoIt has never been a question of computing power or memory, that was already solved decades ago. It is a question of fitting the µC to the application. Price and power consumption are usually the qestions to be answered. 0,50$ or 2$ chip still makes a difference. I think ESPXXXs usually have < 500kb ram. Still quite tight.
- pjmlp 5y agoThe ESP32 has more memory than the PC linked above. COM executables were 64KB, and EXE could use as much as they wanted from 512 - 640 KB in multiples of 64 KB, minus the MS-DOS resident size. Naturally stuff like HMA came later into play with MS-DOS 5, which wasn't something that MS-DOS 3.3, again from the PC above, was capable of. Or if you prefer, I refer to what was possible with 64 - 128 KB on Timex 2068, Spectrum 128 +3A (with CP/M), Commodore 64 with GeOS,... Which, yes games would be coded in Assembly, there was business stuff being sold and coded in BASIC, Pascal, Forth,...
- rsiqueira 5y agoThere is also QuickJS (by Fabrice Bellard) that I use and it's very fast to start and run js programs. QuickJS is a small and embeddable Javascript engine. It supports the ES2020 specification. https://bellard.org/quickjs/ https://bellard.org/quickjs/
- tyingq 5y agoQuickJS is also fantastic, but not anywhere near Elk in terms of size. Elk is ~59k (1300 lines) of C code, and has some limitations (like no for loops, for example) that I assume were traded off so it could run on things like the 2K RAM / 30K flash Atmel shown in the article. QuickJS is small compared to say, V8, but quite a lot larger than Elk. Just the main C source file for QuickJS is ~1.7MB, and there's several other source files. Just saying they seem to be in different niches.
- unwind 5y agoThis part of the code hints at what else is left unimplemented: case TOK_CASE: case TOK_CATCH: case TOK_CLASS: case TOK_CONST: case TOK_DEFAULT: case TOK_DELETE: case TOK_DO: case TOK_FINALLY: case TOK_FOR: case TOK_IN: case TOK_INSTANCEOF: case TOK_NEW: case TOK_SWITCH: case TOK_THIS: case TOK_THROW: case TOK_TRY: case TOK_VAR: case TOK_VOID: case TOK_WITH: case TOK_YIELD: res = js_err(js, "'%.*s' not implemented", (int) js->tlen, js->code + js->toff); break; So that's quite a lot of the language I guess, but it does say that it's a sub-set so of course that's fine. Very impressive code, it really shows that the developer has an eye to minimizing the memory footprint. I was fooled for a couple of seconds by the init call: char mem[200]; struct js *js = js_create(mem, sizeof(mem)); Since it really "feels" like a function that creates a struct instance on the heap, but of course it does not: it's created inside the working memory passed in (so if it works, js == mem).
- BoorishBears 5y agoI write embedded code and the moment I see (data, sizeof(data)) in any kind of initialization method, I immediately expect it not to allocate. Trust but verify, but also I'll feel mislead if it does since it's an extremely common pattern
- quickthrower2 5y agoELK is also used to refer to the logging stack of ElasticSearch, Logstash, Kibana. Just FYI
- CameronNemo 5y agoIt also refers to a species of deer.
- jeffreygoesto 5y agoOh, and https://www.eclipse.org/elk https://www.eclipse.org/elk, the Eclipse Layout Kernel
- scoopertrooper 5y agoLet's not forget the Benevolent and Protective Order of Elks. Pretty big oversight of the author not to call out their lack of association with the 153 year old fraternal order.
- tingletech 5y agoalso https://en.wikipedia.org/wiki/Extension_Language_Kit https://en.wikipedia.org/wiki/Extension_Language_Kit
- Daegalus 5y agoYou know, I'm seeing a lot of "why JS and not X" in threads like this. and as much as I'm anti-js, there is a simple answer that's not all that technical: It's what the author likes and wanted, so they built it. At the end of the day, that's all that matters for it to become reality. if you want something like this but X language, I'm sure there are similar projects, or you can build one yourself. I have no use for this and don't like JS, but I appreciate and respect the efforts put into this project, especially with the clean implementation.
- FractalHQ 5y agoI love JavaScript and Typescript. They’re fun and easy to read and write, and there is little they can’t accomplish for the average use case. I haven’t dug nearly as deep into other languages, but I’ve dabbled with dozens, and Ecmascript 2020 is still my favorite language to code with. The ecosystem is gargantuan, npm is great with pnpm, and all of the annoying parts of client side JS is made fun and easy with Svelte. With TS, CSS, and HTML (and Svelte bringing out their full potential), I can quickly make almost any app I want with incredible DX, comprehensive tooling, and next to no boilerplate. Every year it gets faster and faster, and when it’s not fast enough, there is WASM. I would genuinely love to know what is so bad about it, and what I’m missing out on!
- Daegalus 5y agoPersonally, some of it is the language. the need to triple equals and all the type coercion. it's harder to get those wrong with typescript I agree. another is the ecosystem. pnpm feels like a bandaid to a bad package management system . the whole 'node_modules' folder ends up being a polluted mess very quickly. I import a small library and I feel like I download half of npm registry with it. any time I've wanted to do anything in the JS world, I have to download 30 different frameworks, that don't quite mesh well together. svelte+tailwind a year ago was a disaster to setup with rollup. had to switch to webpack which pulled in a bunch of other stuff and svelte broke. I think the biggest problem is interop and all the translators and transpilers in a standard application. between Babylon, es6/7/8/next/jsx/TS/tsx transpilers. the scss, css, transpilers. media pipelines and converters. and half the time if you don't set them up just right. they don't play well together. maybe it's just not my world. I'm a backend/DevOps/systems dev. and while many languages have similar problems, rarely do they have ALL of these at the same time. back to the language, I feel like early on all the prototype overriding/monkeypatching/etc made for a very very messy language. I'm familiar it's gotten better, but all that cruft is there and still used often. finally, while all the WebApps have been good, I hate how EVERYTHING is using JS on the web, even for useless things, or things that don't need to be JS. I hate how many sites literally are blank I'd you don't have JS enabled. it's also slowed down the web a lot. things take forever to load. so I have many factors that contribute to make having a disdain for JS, both social and technical.
- tonyg 5y agoNames are (not-so-) strange attractors. To me, "Elk" in this kind of a setting is "Elk Scheme - the Extension Language Kit"! [1, 2] [1]: http://sam.zoy.org/elk/ http://sam.zoy.org/elk/ [2]: http://www-rn.informatik.uni-bremen.de/software/elk/ http://www-rn.informatik.uni-bremen.de/software/elk/ Elk Scheme has been around since nineteen eighty seven. Given the power of embeddedish devices these days, I wonder if Elk Scheme would be a useful embedded language implementation in 2021? Sadly I don't have the cycles to experiment.
- esprehn 5y agoThe set of features not supported is quite extensive: https://github.com/cesanta/elk#not-supported-features https://github.com/cesanta/elk#not-supported-features * No var, no const. Use let (strict mode only) * No do, switch, for. Use while * No => functions. Use let f = function(...) {...}; * No arrays, closures, prototypes, this, new, delete * No standard library: no Date, Regexp, Function, String, Number Seems more "JS inspired" than actual JavaScript.
- thefr0g 5y agoHas anyone here used scripting languages on a microcontroller? And if so why? For user-scripting? I can't really think of another practical use case but there are multiple implementations of pretty high-level languages out there so someone must be using them. You'd have to build some hardware abstraction to use with the scripting language anyways at which point you could just use the language you wrote the abstraction in imo. Is it so you can have inexperienced (cheaper?) devs do the maintainence? For all the embedded projects I worked on the high level program logic wasn't the thing that took the most effort.
- zenron 5y agoThat is like asking a Spring Framework developer using all those juicy annotations the reason they do it vs rolling their own in pure 2006 Java code. Knowing how to do it vs using a higher DSL is always going to be nicer especially to gain new users. Look at the sega genesis/mega drive SDK. Many 2020+ Sega Genesis/Megadrive games are built using it. It is C. Why not use 68000 assembler like every developer before now? Documentation, ease of use, community, cross domain developers can pick it up easier... Same thing applies here.
- password4321 5y agoAs mentioned a few days back: Enumerating and analyzing 40 non-V8 JavaScript implementations https://news.ycombinator.com/item?id=28613673 https://news.ycombinator.com/item?id=28613673
- UltraViolence 5y agoToo bad they didn't write it in Rust. I believe C is much too fragile for interpreters to be written in them, especially for high-usage scenarios like the web.