From 487a70388fc4befe8c683640ce1b7a850dd4bcfb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 28 Jun 2010 19:20:45 +0200 Subject: [PATCH] added interpreter framework --- CMakeLists.txt | 13 +++++-- apps/mwinterpreter/main.cpp | 49 ++++++++++++++++++++++++++ components/interpreter/context.hpp | 14 ++++++++ components/interpreter/interpreter.cpp | 22 ++++++++++++ components/interpreter/interpreter.hpp | 28 +++++++++++++++ components/interpreter/opcodes.hpp | 40 +++++++++++++++++++++ components/interpreter/runtime.cpp | 22 ++++++++++++ components/interpreter/runtime.hpp | 31 ++++++++++++++++ 8 files changed, 217 insertions(+), 2 deletions(-) create mode 100644 apps/mwinterpreter/main.cpp create mode 100644 components/interpreter/context.hpp create mode 100644 components/interpreter/interpreter.cpp create mode 100644 components/interpreter/interpreter.hpp create mode 100644 components/interpreter/opcodes.hpp create mode 100644 components/interpreter/runtime.cpp create mode 100644 components/interpreter/runtime.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ffaca5908..17d54e241f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,10 +76,12 @@ set(COMPILER components/compiler/errorhandler.cpp file(GLOB COMPILER_HEADER components/compiler/*.hpp) source_group(compiler FILES ${COMPILER} ${COMPILER_HEADER}) +set(INTERPRETER components/interpreter/runtime.cpp components/interpreter/interpreter.cpp) file(GLOB INTERPRETER_HEADER components/interpreter/*.hpp) -source_group(interpreter FILES ${INTERPRETER_HEADER}) +source_group(interpreter FILES ${INTERPRETER} ${INTERPRETER_HEADER}) -set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${OGRE} ${INPUT} ${MISC} ${COMPILER}) +set(COMPONENTS ${BSA} ${NIF} ${NIFOGRE} ${ESM_STORE} ${OGRE} ${INPUT} ${MISC} ${COMPILER} + ${INTERPRETER}) set(COMPONENTS_HEADER ${BSA_HEADER} ${NIF_HEADER} ${NIFOGRE_HEADER} ${ESM_STORE_HEADER} ${ESM_HEADER} ${OGRE_HEADER} ${INPUT_HEADER} ${MISC_HEADER} ${COMPILER_HEADER} ${INTERPRETER_HEADER}) @@ -183,3 +185,10 @@ set(TOOLS_MWCOMPILER ${COMPILER} apps/mwcompiler/main.cpp apps/mwcompiler/contex add_executable(mwcompiler ${TOOLS_MWCOMPILER}) endif() +option(BUILD_MWINTERPRETER "build standalone Morrowind script code interpreter" ON) + +if (BUILD_MWINTERPRETER) +set(TOOLS_MWINTERPRETER ${INTERPRETER} apps/mwinterpreter/main.cpp) + +add_executable(mwinterpreter ${TOOLS_MWINTERPRETER}) +endif() diff --git a/apps/mwinterpreter/main.cpp b/apps/mwinterpreter/main.cpp new file mode 100644 index 0000000000..c0b0b47182 --- /dev/null +++ b/apps/mwinterpreter/main.cpp @@ -0,0 +1,49 @@ +// Stand-alone MW-script code interpreter + +#include +#include +#include +#include + +#include +#include +#include + +int main (int argc, char **argv) +{ + try + { + Interpreter::Context context; + Interpreter::Interpreter interpreter (context); + + std::string filename = argc>1 ? argv[1] : "test.mwscript"; + + std::string codefilename = filename + ".code"; + + std::ifstream codefile (codefilename.c_str()); + + if (!codefile.is_open()) + { + std::cout << "can't open code file: " << codefilename << std::endl; + return 1; + } + + std::vector code (4); + + codefile.read (reinterpret_cast (&code[0]), 4 * sizeof (Interpreter::Type_Code)); + + unsigned int size = code[0] + code[1] + code[2] + code[3]; + + code.resize (4+size); + + codefile.read (reinterpret_cast (&code[4]), size * sizeof (Interpreter::Type_Code)); + + interpreter.run (&code[0], size+4); + } + catch (const std::exception &e) + { + std::cout << "\nERROR: " << e.what() << std::endl; + return 1; + } +} + diff --git a/components/interpreter/context.hpp b/components/interpreter/context.hpp new file mode 100644 index 0000000000..922dc0c700 --- /dev/null +++ b/components/interpreter/context.hpp @@ -0,0 +1,14 @@ +#ifndef INTERPRETER_CONTEXT_H_INCLUDED +#define INTERPRETER_CONTEXT_H_INCLUDED + +namespace Interpreter +{ + class Context + { + + }; +} + +#endif + + diff --git a/components/interpreter/interpreter.cpp b/components/interpreter/interpreter.cpp new file mode 100644 index 0000000000..1db683e3cc --- /dev/null +++ b/components/interpreter/interpreter.cpp @@ -0,0 +1,22 @@ + +#include "interpreter.hpp" + +namespace Interpreter +{ + Interpreter::Interpreter (Context& context) + : mRuntime (context) + {} + + Interpreter::~Interpreter() + { + + } + + void Interpreter::run (const Type_Code *code, int codeSize) + { + mRuntime.configure (code, codeSize); + + + mRuntime.clear(); + } +} diff --git a/components/interpreter/interpreter.hpp b/components/interpreter/interpreter.hpp new file mode 100644 index 0000000000..fb26aaecee --- /dev/null +++ b/components/interpreter/interpreter.hpp @@ -0,0 +1,28 @@ +#ifndef INTERPRETER_INTERPRETER_H_INCLUDED +#define INTERPRETER_INTERPRETER_H_INCLUDED + +#include "runtime.hpp" +#include "types.hpp" + +namespace Interpreter +{ + class Interpreter + { + Runtime mRuntime; + + // not implemented + Interpreter (const Interpreter&); + Interpreter& operator= (const Interpreter&); + + public: + + Interpreter (Context& context); + + ~Interpreter(); + + void run (const Type_Code *code, int codeSize); + }; +} + +#endif + diff --git a/components/interpreter/opcodes.hpp b/components/interpreter/opcodes.hpp new file mode 100644 index 0000000000..d24e8c62ce --- /dev/null +++ b/components/interpreter/opcodes.hpp @@ -0,0 +1,40 @@ +#ifndef INTERPRETER_OPCODES_H_INCLUDED +#define INTERPRETER_OPCODES_H_INCLUDED + +namespace Interpreter +{ + class Runtime; + + /// opcode for 0 arguments + class Opcode0 + { + public: + + virtual void execute (Runtime& runtime) = 0; + + virtual ~Opcode0() {} + }; + + /// opcode for 1 argument + class Opcode1 + { + public: + + virtual void execute (Runtime& runtime, unsigned int arg0) = 0; + + virtual ~Opcode0() {} + }; + + /// opcode for 2 arguments + class Opcode2 + { + public: + + virtual void execute (Runtime& runtime, unsigned int arg1, unsigned int arg2) = 0; + + virtual ~Opcode0() {} + }; + +} + +#endif diff --git a/components/interpreter/runtime.cpp b/components/interpreter/runtime.cpp new file mode 100644 index 0000000000..33f1e37800 --- /dev/null +++ b/components/interpreter/runtime.cpp @@ -0,0 +1,22 @@ + +#include "runtime.hpp" + +namespace Interpreter +{ + Runtime::Runtime (Context& context) : mContext (context), mCode (0) {} + + void Runtime::configure (const Interpreter::Type_Code *code, int codeSize) + { + clear(); + + mCode = code; + mCodeSize = codeSize; + } + + void Runtime::clear() + { + mCode = 0; + mCodeSize = 0; + } +} + diff --git a/components/interpreter/runtime.hpp b/components/interpreter/runtime.hpp new file mode 100644 index 0000000000..2166e3cc7b --- /dev/null +++ b/components/interpreter/runtime.hpp @@ -0,0 +1,31 @@ +#ifndef INTERPRETER_RUNTIME_H_INCLUDED +#define INTERPRETER_RUNTIME_H_INCLUDED + +#include "types.hpp" + +namespace Interpreter +{ + class Context; + + /// Runtime data and engine interface + + class Runtime + { + Context& mContext; + const Interpreter::Type_Code *mCode; + int mCodeSize; + + public: + + Runtime (Context& context); + + void configure (const Interpreter::Type_Code *code, int codeSize); + ///< \a context and \a code must exist as least until either configure, clear or + /// the destructor is called. \a codeSize is given in 32-bit words. + + void clear(); + + }; +} + +#endif