A lightweight Virtual Machine for dynamic, object-oriented languages.
TODO: Write a project description
$ git clone git://github.com/txus/terrorvm.git $ cd terrorvm $ make
To run the tests:
$ make dev
And to clean the mess:
$ make clean
.tvm bytecode files such as the
hello_world.tvm under the
$ ./bin/vm examples/hello_world.tvm
It ships with a simple compiler written in Ruby (Rubinius) that compiles a
tiny subset of Ruby to
.tvm files. Check out the
compiler directory, which
has its own Readme, and the
compiler/examples where we have the
hello_world.rb file used to produce the
TerrorVM doesn't need Ruby to run; even the example compiler is a proof of concept and could be written in any language (even in C obviously).
TerrorVM tries to implement as much as possible in its own code. You can find a
compiler/examples/prelude.rb, or in native format under
This prelude wires up the VM primitives to the real objects at runtime, so that your code can use them conveniently.
To recompile all examples and kernel files from Ruby to Tvm, do this:
$ make kernel $ make examples
TerrorVM is designed to run dynamic languages. You can easily implement a compiler of your own that compiles your favorite dynamic language down to TVM bytecode.
I've written a demo compiler in Ruby under the
compiler/ folder, just to
show how easy it is to write your own. This demo compiler compiles a subset of
Ruby down to TerrorVM bytecode, so you can easily peek at the source code or
just copy and modify it.
You can write your compiler in whatever language you prefer, of course.
(I rewrote it entirely so I have to write the new format here soon.)
- Hello world (Ruby code, TVM bytecode)
- Maps (Ruby code, TVM code)
- Vectors (Ruby code, TVM code)
- Numbers (Ruby code, TVM code)
- Objects with prototypal inheritance (Ruby code, TVM bytecode)
- Functions and closures (Ruby code, TVM bytecode)
- NOOP: no operation -- does nothing.
- PUSHSELF: pushes the current self to the stack.
PUSH A: pushes the literal at index
Ato the stack.
PUSHTRUE: pushes the
trueobject to the stack.
PUSHFALSE: pushes the
falseobject to the stack.
PUSHNIL: pushes the
nilobject to the stack.
PUSHLOCAL A: pushes the local at index
Ato the stack.
SETLOCAL A: sets the current top of the stack to the local variable
A. Does not consume any stack.
JMP A: Jumps forward as much as
JIF A: Jumps forward as much as
Ainstructions if the top of the stack is falsy (
JIT A: Jumps forward as much as
Ainstructions if the top of the stack is truthy (any value other than
GETSLOT A: Pops the object at the top of the stack and asks for its slot with name
A(a literal), pushing it to the stack if found -- if not, it'll raise an error.
SETSLOT A: Pops a value to be set, then pops the object at the top of the stack and sets its slot with name
A(a literal) to the value that was first popped. Then pushes that value back to the stack.
- POP: pops a value off the stack.
DEFN A: takes the closure with the name
A(a literal) and pushes it to the stack.
MAKEVEC A: Pops as much as
Aelements off the stack and pushes a vector with all of them in the order they were popped (the reverse order they were pushed in the first place).
SEND A, B: Pops as much as
Barguments off the stack, then the receiver, and sends it the message with the name
A(a literal) with those arguments.
- DUMP: Prints the contents of the value stack to the standard output.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature)
- Commit your changes (
git commit -am 'Added some feature')
- Push to the branch (
git push origin my-new-feature)
- Create new Pull Request