Not sure where to post this, but I've needed something like it several times and never found one, so I created it.
nutshell is this: I need to be able to execute scripts, small custom scripts that end-users will be creating, without having to teach them arcane language concepts.
Tried lua, wren, squirrel, etc, etc.. none work for the same reason, the interpreter fits into the available space but they all require massive amounts of ram to actually do anything, ram the SAMD21 doesn't have.
wrench:
- - can execute bytecode from ROM, or dynamically load it with a callback (like an I2C EEPROM)
- has a very small RAM footprint when running, on the order of 500 bytes is the base it requires.
- execute speed is on par with lua for the basic profiling I've done so far
- interpreter fits into around 32k of program space (currently, project is still in motion)
- compiler+interpreter takes double that, all of 64k
- supports everything a good interpreter should: if/then/else/do/while/for/functions/operators/etc..
- bytecode is very compact, endian-neutral, compile anywhere run anywhere else (the command-line tool will generate byte-code headers for #include in the actual project)
- handles char/int/float/array types
- can operate directly on native data arrays, no thunking required
- quickly and easily call c from script and vice-versa
- memory is garbage-collection model but only used for arrays and very sparingly
- MIT license, share and enjoy.
Still a work in progress but functioning now and driving my board! Thought I'd post it now and get the ball rolling on feedback.
I'm attaching the current snapshot but I'll be iterating on it a lot, latest will always be on: http://northarc.com/wrench-current.zip
Please forgive my spartan documentation, its hard to be polished when there is no audience.
Here is a complete example:
Code: Select all
#include <Arduino.h>
#include "wrench.h"
void log( WRState* w, const WRValue* argv, const int argn, WRValue& retVal, void* usr )
{
char buf[512];
for( int i=0; i<argn; ++i )
{
Serial.print( wr_valueToString(argv[i], buf) );
}
}
const char* wrenchCode =
"log( \"Hello World!\\n\" ); "
"for( i=0; i<10; i++ ) "
"{ "
" log( i ); "
"} ";
void setup()
{
Serial.begin( 115200 );
delay( 2000 ); // wait for link to come up for sample
WRState* w = wr_newState(); // create the state
wr_registerFunction( w, "log", log ); // bind a function
unsigned char* outBytes; // compiled code is alloc'ed
int outLen;
int err = wr_compile( wrenchCode, strlen(wrenchCode), &outBytes, &outLen ); // compile it
if ( err == 0 )
{
wr_run( w, outBytes, outLen ); // load and run the code!
delete[] outBytes; // clean up
}
wr_destroyState( w );
}
void loop()
{}