Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
50 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Testing Commands

To properly test this new implementation, we will need a simple example system to bind with a virtual machine. The system I provide is simply used to illustrate the processes of binding and using. The functionality provided by it will be essentially trivial. The class doesn't even make use of any data members. One command will draw a certain number of asterisks (stars) with a defined spacing between each. The next will compute a factorial (Another factorial test! Yay!) hard-coded. Notice that the number of functions provided to the virtual machine as an interface is enumerated. This is simply one dirty way of ensuring that a proper number of function pointers are passed:

class System
{
public:
    enum { num_commands = 2 };
    // vm interface
    int DrawStars(const std::vector<int>& argv)
        { if (argv.size() < 2) return -1; OutputStars(argv[0], argv[1]); return 0; }
    int CalcFactorial(const std::vector<int>& argv)
        { if (argv.size() < 1) return -1; return Factorial(argv[0]); }
private:
    void OutputStars(size_t numStars, size_t padding)
    {
        std::string padString;
        size_t i;
        for (i = 0; i < padding; ++i)
            padString += ' ';
        for (i = 0; i < numStars; ++i)
            std::cout << '*' << padString;
        std::cout << std::endl;
    }
    int Factorial(size_t input)
    {
        // initialize
        int counter = input;
        int result = 1;
        // iterative loop
        while (counter > 1)
        {
            result *= counter;
            --counter;
        }
        // output
        return result;
    }
};

The only changes necessary in the main.cpp to make use of a system is to instantiate one, provide an array of function pointers to its interface, and alter the declaration of the virtual machine:

// typedef for simplification
typedef Callback<System, int, int>::Func SystemFunc;
SystemFunc commandList[System::num_commands] =
{
    &System::DrawStars,
    &System::CalcFactorial
};

System system;
VirtualMachine<System> vm(system, commandList, System::num_commands);

Two example scripts follow, one to test each of the system commands.

Starcommand:

// draws 7 stars with a spacing of 2
pusharg_const 7
pusharg_const 2
call_command 0
end

Factorialcommand:

// computes the factorial of 9 and displays the result (which should be 362880)
pusharg_const 9
call_command 1
load
output
end

Conclusion

The most important parts of our run-time system have now been completed. Our virtual machine's capability for binding with other systems is very powerful, and has lots of avenues that can be explored.

Inlining of script functions is a topic that I would eventually like to cover, but in a part related to compiler optimizations. It doesn't really make sense to cover it yet, as writing a function to be inline itself in a script is trivial, and we've been doing it all along. The interesting things come when compiling code from a higher-level language.

The callback solution introduced in this part of the series could have made use of implementations found in other libraries, such as the popular boost. Such a route was not taken as such generic libraries often take into account everything under the sun, which would have certainly obfuscated the topic being conveyed.

Currently, the utilities for binding a virtual machine to an external system are a bit unwieldy, and require a bit of diligence to make sure the system's interface is passed appropriately. Perhaps we can improve upon this a little bit in the future.

The next article will probably begin dealing with creating a compiler. To reduce the learning curve of this series, the language to be compiled will probably be very C-like. Further development of the virtual machine itself may be continued at a later time, though the emphasis of the next wave of articles will be primarily on the compilation process.

As always, feel free to use the forum discussion, or contact me by email: glr9940@rit.edu


Contents
  Introduction
  Page 2
  Page 3
  Page 4

  Source code
  Printable version
  Discuss this article

The Series
  An Introduction
  Data Manipulation
  Dynamic Loading
  The Stack and Program Flow
  Functionality