Skip to content

jingoro2112/wrench

Repository files navigation

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:

#include <wrench.h>
#include <string.h>
#include <stdio.h>

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!