Archive for the 'Voodoo' Category

Voodoo Features

I thought I would do a feature list for voodoo. This is to keep my head straight about what I’m doing, and also act as the reason I’m making voodoo, because no other language has the features I want.

Simple Syntax
The general constructs should be obvious, and there will be no obscure symbols.

Static Typed
This means that variables always have a type and the compiler does the type checking. This is good because if a program compiles, it has a higher chance of working at runtime. This also helps with programming because small mistakes will be picked up at the compilation stage. Also the typing information can be used in an editor and other programming aids.

Tabbed Block
No more braces and only one type of if statement. This means that the code after a statement that takes a block of code, such as a for loop, just needs to be indented. In other languages it’s a requirement to have curly braces around the code block, and indentation is optional. I think tab-blocked languages look nicer and are easier to read.

File independant
Any file can add prototype definitions to any editable class. The same file that defines an interface can define which classes implement the interface and declare the methods and implementations needed for the implementation. This way separate functionality can be grouped together independently of object. This is great for source control because multiple people can work on one object at once. Whole functionality can be included or excluded just by including or excluding a single file.

Exception Handling
Simplified exception handling, you can either have a handler for the entire method, or have a block of code that handles exceptions for a certain method call. I’ve found that these are the most common (if not only) cases where exceptions are used. Try blocks are messyâ„¢.

Pure Object Oriented
This means that all type and data structures are objects. This simplifies the virtual machine but complicates other aspects. All objects inherit from the class named “Type”. All objects that can be subclassed inherit from the class “Object” which itself inherits from “Type”. Methods and classes are also objects and have methods and properties themselves. Classes behave in a similar way to Objective-C classes where they exist as a standalone instance with separate methods to instances of the class. Each class actually has two definitions, one for the class ‘owner’ object, and another for the actual instances of the class.

Single Inheritance
Multiple inheritance is too complicated and unnecessary for most situations. By having a inheritance tree dependancies are simple and method overlap makes sense.

Interfaces
To allow a type of multiple inheritance, interfaces are used and will function the same as Java Interfaces. They can be thought of as a ‘protocol’ that every class that implements the interface must adhere to. An interface will define methods that the classes that implement the interface must also have with the same name and equal or broader variable types. This means that if something is more ‘generic’ it’s okay.

Code Blocks
A method can be called with an attached code block, that resides in the calling method. While the method is executing it can call this block of code any number of times with different arguments. This will be how for loops, if loops and other block structures will be implemented. The code is fixed in place, and so can reference variables from outside it’s scope.

Native Code
To extend and develop functionality for voodoo, C++ is used. A single C++ class is responsible for native methods introduced at that class level. So an integer will have three classes, one will be the C++ native class responsible for the implementation of the “Type” class, one for the native implementation of the “Object” class and another for the implementation of the “Integer” class. Static methods are called when the class is loaded and unloaded. Member methods of the C++ object are called for initialisation (init) and when the object is going to be deleted. A method is either implemented by voodoo code, or a single method in the C++ object that handles that voodoo class.

States
A class can have many sub-classes called ’states’. States can’t add any new properties, constants, implemented interfaces or methods, but they can have alternate implementations of existing methods. The special thing about states is that because they are the same size and have the same offsets as their sibling states, an object can have it’s class changed at runtime. This is great for game development because they tend to have state like actions and events within the game world. A simple example would be an elevator, it could have 3 states: going down, going up and stopped. Three classes would be interchanged for any given elevator object as it’s used in-game. Each game ‘tick’ would call a method, the going up elevator would add something to it’s height value incrementally until it reaches a certain point where it would change itself into the stopped state. Each tick the stopped state would do nothing but check if the button is pressed and if so it would change it’s self into whatever state is appropriate. The going down would be similar to the going up state. The great thing about this implementation is that the code is so simple. An implementation in a language without states would either require a enum, or some sort of wrapper class.

In the actual implementation there would be an event system, so only objects that need to be called every tick are notified. The button would call the method and the elevator would register itself with the event system so it’s called every tick.

Data - Code crossover
XML data for other information including 3d information, level data and other game content can refer to objects and methods of voodoo code. Objects of a certain class can be linked to a game asset and instantiated whenever an instance of that asset is spawned in the game world. Method delegates are called for various events concerning the object.

Search paths and soft class referencing
Multiple search paths can be setup for both the compilation stage, and the running stage. References to classes go through a cascade of search locations for their definition.

Network Proxy Objects
Objects can be created as a network proxy for another object residing on another computer. These are transparent to other classes and programming. If fine control of the interaction is needed (for optimising) the same system of control that is used in a threaded environment is used in a network environment. Execution on another machine is modeled as another thread so method calls can be synchronous or asynchronous.

Threads
Threads are implemented by swapping between bits of script rather than creating OS based threads which means that there can be more executing at once without swamping resources. Because all the fundamental instructions are in C++ and have an indeterminate execution time C++ methods should be short. Execution will either be time based, or number of instructions (profiling needed). Methods can be called with a ‘async’ (asynchronous) modifier which means that the method will spawn a separate thread, and execution in the calling method will continue without waiting for it to return. The modifier syntax is object.method.async(param1, param2) compared to the normal call syntax which is object.method(param1, param2). Methods called asynchronously must return void (nothing).

C++ calling voodoo methods
The idea with C++ calling voodoo is that each method (or groups of methods - it doesn’t matter) has a voodoo method object. Each voodoo method object has a constant pool and a link pool, these are objects and constants that the virtual machine keeps track of and relinks when necessary. So the C++ calling method would access these objects in a similar way to voodoo bytecode, by offsets (or a hashmap or whatever). So when a C++ method wants to use a voodoo integer it just uses the one in the constant pool that it registered earlier. This way everything is linked together still and it will be faster than a lookup every method call.

There are two ways for C++ to call voodoo methods. One is the asynchronous method where the calling function waits in another thread until the voodoo thread that it created finishes. The other way is where the virtual machine runs a voodoo thread singularly until it has completed and returns back to the calling C++ code. The second option can only be used by the same thread that’s executing voodoo (unless I make voodoo thread safe) and should only be used for small calls or in a single voodoo thread environment.

I’ll add to this later…

Working

I’ve started working on voodoo again after a lengthy hiatus. I’m programming the part that takes the xml file and bytecode, generates all the class information, builds the link and constant pools and just basically gets everything up and running.

I’ve decided to leave the whole ‘groups’ idea alone for a while, I’ll revisit it when things are a bit more complete. It’s just a ‘tack on’ anyway, a few classes for information purposes. It should be quite easy to add it later.

Tinyxml is great!

Coroutines

I would like to support coroutines / generators in my virtual machine, even if I don’t decide to use them. I’ve heard that they are quite hard to implement. I’m planning on having a thread system anyway, coroutines seem just like an extension. I was thinking that a coroutine is a new thread that runs completely off a mutex of sorts, where the original thread doesn’t run until the coroutine ‘yeilds’ and the coroutine doesn’t run again until a thread calls it. While the resulting implementation might not use actual mutex’s (eg properly substitute threads) this sounds like a viable way to implement coroutines.

Sound like it will work? Something I’m missing? Should I be bothered anyway?

VM design, fundamental choices

While thinking and playing with a few ideas, I realised that my parameter stack isn’t going to be very big. Because I was only planning on having push and pops (no direct access) there isn’t a way to use much more than is required to complete an expression (eg a = a + b - c). So this means I will be using local variables a lot more. The parameters passed to a function were going to be popped off and put into local variables so they can be used.

All this got me thinking that I could use a register based machine instead. I’ve heard that they are faster, and possibly a bit easier to program in the compiler. Either a register based vm, or a stack based one that can address offsets from the stack - so I can use it for temp variables and leave the parameters on it.

Another question that popped up concerns the variable stack. I was planning to be able to increase and decrease the section of the variable stack that the current funciton is using. This is good because a function will only use up as much variable stack space as needed when it calls other functions.

My first impression is to have it stack based with the ability to access offsets, and keep the dynamic sized local variable stack.

Another thing to think about is that I want to implement static-closure code block things - the ability to come back to sections of code within a function from other funcitons higher up on the stack. These bits of code can access and modify the local variables that are in the original function as well as have their own variables. Nested static-closures as well. I was planning on having independant local variable stacks in each ‘frame’. The closure uses the parameter stack normally (it’s a function in it’s own right) but uses the original function’s variable stack for it’s variables.

Macromedia Flash is crap

I did a bit more ‘haxing’ to let the authors name come up for each post as we now have more than one author on this here blog.

I’m going through my stuff making it a bit less ‘me’ and a bit more ‘us’…

I’m not looking forward to finishing the flash game that we have been working on for a good part of this semester. Every minute spent in flash makes me more and more angry and crazed, how can an expensive and professional piece of software that is used by so many be so frustrating and hard to use? If flash is the introduction that budding animators and programmers get to the world of computer development I feel sorry for them.

I’m finding it hard to get things done with constant interruptions, uni assignments and other things I’m required to do. Again Voodoo hasn’t been worked on for a while. I’ve decided to restart a bit and use a slightly different paradigm for the parser. It’s more like flex and bison now, but the scanner only returns 4 different types of tokens. Identifier, Number, Symbol and Literal (for string literals). The parser class asks the scanner for the next token, it returns and the scanner can be asked questions about the location and indentation of that token. The scanner can also be told that the last token it returned was bad and it will be able to print out it’s location.

So each individual parse method will be a lot smaller which will be good, and I will still be able to use the cool parser errors that using flex and bison won’t give me.

Edit: I’ve also fixed a problem with the /author pages, the authors name wasn’t coming up. I used a bit of a hack, but it works. I want to submit the bug report but the signup email is taking yonks.