https://home.workshopfriends.com/wrench/www
A full-featured compiler+interpreter that uses a bare minimum of ram and program space.
How little? The wrench Virtual Machine compiles to ~28k on an Arduino, and uses less than 700 Bytes of RAM to operate, it is fully functional on an Uno Mini.
Highlights:
Weakly typed, supporting native 32-bit int, float and string. Code is easy to write with familiar c-syntax
Optimizing compiler and very fast VM
Produces very compact endian-neutral bytecode: compile-anywhere-run-anywhere.
Can execute from ROM, no local copy of the code is made
Multiple concurrent contexts supported
Code is easy to write, imagine c with the typenames removed; that's pretty much it.
Supports everything a good interpreter should: if/then/else/do/while/for/switch/functions/operators/etc..
Yes structs too
Yes switch (and NO it's not if-else sugar)
Can operate directly on data and exposes all static values to be manipulated externally and directly.
Can call back and forth to native code with minimal overhead
API is designed to be easily extended, that's the whole point!
Memory is garbage-collected but only for dynamic arrays. Unless you are allocating/de-allocating arrays the gc never runs.
Includes a handy command-line tool
Easy to integrate, here is a complete example:
----- Step 1: The entire source tree is included, but is wrapped up in two files, src/wrench.h and src/wrench.cpp simply include these in your build and you have everything.
----- Step 2: Here is a complete source-code example:
void print( WRContext c, const WRValue argv, const int argn, WRValue& retVal, void* usr ) { char buf[1024]; for( int i=0; i<argn; ++i ) { printf( "%s", argv[i].asString(buf,1024) ); } }
const char* wrenchCode = "print( \"Hello World!\n\" );" "for( var i=0; i<10; i++ ) " "{ " " print( i ); " "} " "print(\"\n\"); ";
int main( int argn, char* argv ) { WRState w = wr_newState(); // create the state
wr_registerFunction( w, "print", print ); // 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!
free( outBytes ); // clean up
}
wr_destroyState( w );
return 0;
}
---- Step 3: compile the above with something like:
g++ -o example example.c wrench.cpp
---- Step 4: done!