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*
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. Seemed to me it could be done without that.
wrench:
- can execute bytecode from ROM, or dynamically load it with a callback (like an I2C EEPROM)
- execute speed is on par with lua for the basic profiling I've done so far
- interpreter fits into around 32k (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
- 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 working on documentation, but It runs on win32 (visual studio) linux, arduino and Raspberry Pi, the platforms I have easy access to I have a test suite I run it through (included) and I generally valgrind it to catch my stupidity. I'm actually using this on a SAMD21 project and it's working! so I thought I'd post it now and get the ball rolling on feedback.
I'd attach a file but don't see how, here is a link to an archive: http://northarc.com/wrench-current.zip
code snapshot is here and includes a command-line utility. This is still early days
Here is a complete example:
#include <Arduino.h>
#include "wrench.h"
void log( WRState* w, WRValue* argv, 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()
{}
*yes really. it's a lighting board that allows custom effects to be written but must run stand-alone, so they will be uploaded into an on-board I2C EEPROM and executed from there.