From 32eafaa3013bc266e9971db258d97d16382807e5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 3 Jul 2010 10:43:55 +0200 Subject: [PATCH] added custom function handling (compiler) --- components/compiler/context.hpp | 11 ++- components/compiler/exprparser.cpp | 23 ++++++ components/compiler/extensions.cpp | 46 ++++++++++- components/compiler/extensions.hpp | 28 ++++++- components/compiler/generator.cpp | 122 ++++++++++------------------- components/compiler/generator.hpp | 39 +++++++++ 6 files changed, 186 insertions(+), 83 deletions(-) diff --git a/components/compiler/context.hpp b/components/compiler/context.hpp index e79416498d..6af0f9602f 100644 --- a/components/compiler/context.hpp +++ b/components/compiler/context.hpp @@ -18,8 +18,15 @@ namespace Compiler virtual bool canDeclareLocals() const = 0; ///< Is the compiler allowed to declare local variables? - void setExtensions (const Extensions *extensions = 0); - ///< Set compiler extensions. + void setExtensions (const Extensions *extensions = 0) + { + mExtensions = extensions; + } + + const Extensions *getExtensions() const + { + return mExtensions; + } }; } diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index 2d932bedef..bbeaf2c817 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -12,6 +12,8 @@ #include "errorhandler.hpp" #include "locals.hpp" #include "stringparser.hpp" +#include "extensions.hpp" +#include "context.hpp" namespace Compiler { @@ -279,6 +281,27 @@ namespace Compiler mNextOperand = false; return true; } + else + { + // check for custom extensions + if (const Extensions *extensions = getContext().getExtensions()) + { + char returnType; + std::string argumentType; + + if (extensions->isFunction (keyword, returnType, argumentType)) + { + mTokenLoc = loc; + parseArguments (argumentType, scanner); + + extensions->generateFunctionCode (keyword, mCode); + mOperands.push_back (returnType); + + mNextOperand = false; + return true; + } + } + } } else { diff --git a/components/compiler/extensions.cpp b/components/compiler/extensions.cpp index 31f530d9e1..d83f368482 100644 --- a/components/compiler/extensions.cpp +++ b/components/compiler/extensions.cpp @@ -1,9 +1,13 @@ #include "extensions.hpp" +#include +#include + +#include "generator.hpp" + namespace Compiler { - Extensions::Extensions() : mNextKeywordIndex (-1) {} int Extensions::searchKeyword (const std::string& keyword) const @@ -15,4 +19,44 @@ namespace Compiler return iter->second; } + + bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType) const + { + std::map::const_iterator iter = mFunctions.find (keyword); + + if (iter==mFunctions.end()) + return false; + + returnType = iter->second.mReturn; + argumentType = iter->second.mArguments; + return true; + } + + void Extensions::registerFunction (const std::string& keyword, char returnType, + const std::string& argumentType, int segment5code) + { + assert (segment5code>=33554432 && segment5code<=67108863); + + int code = mNextKeywordIndex--; + + mKeywords.insert (std::make_pair (keyword, code)); + + Function function; + function.mReturn = returnType; + function.mArguments = argumentType; + function.mCode = segment5code; + + mFunctions.insert (std::make_pair (code, function)); + } + + void Extensions::generateFunctionCode (int keyword, std::vector& code) + const + { + std::map::const_iterator iter = mFunctions.find (keyword); + + if (iter==mFunctions.end()) + throw std::logic_error ("unknown custom function keyword"); + + Generator::segment5 (iter->second.mCode); + } } diff --git a/components/compiler/extensions.hpp b/components/compiler/extensions.hpp index 7bf758b2e4..975abcef61 100644 --- a/components/compiler/extensions.hpp +++ b/components/compiler/extensions.hpp @@ -3,6 +3,9 @@ #include #include +#include + +#include namespace Compiler { @@ -10,9 +13,17 @@ namespace Compiler class Extensions { + struct Function + { + char mReturn; + std::string mArguments; + int mCode; + }; + int mNextKeywordIndex; std::map mKeywords; - + std::map mFunctions; + public: Extensions(); @@ -21,6 +32,21 @@ namespace Compiler ///< Return extension keyword code, that is assigned to the string \a keyword. /// - if no match is found 0 is returned. /// - keyword must be all lower case. + + bool isFunction (int keyword, char& returnType, std::string& argumentType) const; + ///< Is this keyword registered with a function? If yes, return return and argument + /// types. + + void registerFunction (const std::string& keyword, char returnType, + const std::string& argumentType, int segment5code); + ///< Register a custom function + /// - keyword must be all lower case. + /// - keyword must be unique + /// \note Currently only segment 5 opcodes are supported. + + void generateFunctionCode (int keyword, std::vector& code) + const; + ///< Append code for function to \a code. }; } diff --git a/components/compiler/generator.cpp b/components/compiler/generator.cpp index 0f5a9a4787..5fc60ef9f2 100644 --- a/components/compiler/generator.cpp +++ b/components/compiler/generator.cpp @@ -9,251 +9,215 @@ #include "literals.hpp" namespace -{ - Interpreter::Type_Code segment0 (unsigned int c, unsigned int arg0) - { - assert (c<64); - return (c<<24) | (arg0 & 0xffffff); - } - - Interpreter::Type_Code segment1 (unsigned int c, unsigned int arg0, unsigned int arg1) - { - assert (c<64); - return 0x40000000 | (c<<24) | ((arg0 & 0xfff)<<12) | (arg1 & 0xfff); - } - - Interpreter::Type_Code segment2 (unsigned int c, unsigned int arg0) - { - assert (c<1024); - return 0x80000000 | (c<<20) | (arg0 & 0xfffff); - } - - Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0) - { - assert (c<1024); - return 0xc0000000 | (c<<20) | (arg0 & 0xffff); - } - - Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0, unsigned int arg1) - { - assert (c<1024); - return 0xc4000000 | (c<<16) | ((arg0 & 0xff)<<8) | (arg1 & 0xff); - } - - Interpreter::Type_Code segment5 (unsigned int c) - { - assert (c<67108864); - return 0xc8000000 | c; - } - +{ void opPushInt (Compiler::Generator::CodeContainer& code, int value) { - code.push_back (segment0 (0, value)); + code.push_back (Compiler::Generator::segment0 (0, value)); } void opFetchIntLiteral (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (4)); + code.push_back (Compiler::Generator::segment5 (4)); } void opFetchFloatLiteral (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (5)); + code.push_back (Compiler::Generator::segment5 (5)); } void opIntToFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (3)); + code.push_back (Compiler::Generator::segment5 (3)); } void opFloatToInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (6)); + code.push_back (Compiler::Generator::segment5 (6)); } void opStoreLocalShort (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (0)); + code.push_back (Compiler::Generator::segment5 (0)); } void opStoreLocalLong (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (1)); + code.push_back (Compiler::Generator::segment5 (1)); } void opStoreLocalFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (2)); + code.push_back (Compiler::Generator::segment5 (2)); } void opNegateInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (7)); + code.push_back (Compiler::Generator::segment5 (7)); } void opNegateFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (8)); + code.push_back (Compiler::Generator::segment5 (8)); } void opAddInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (9)); + code.push_back (Compiler::Generator::segment5 (9)); } void opAddFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (10)); + code.push_back (Compiler::Generator::segment5 (10)); } void opSubInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (11)); + code.push_back (Compiler::Generator::segment5 (11)); } void opSubFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (12)); + code.push_back (Compiler::Generator::segment5 (12)); } void opMulInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (13)); + code.push_back (Compiler::Generator::segment5 (13)); } void opMulFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (14)); + code.push_back (Compiler::Generator::segment5 (14)); } void opDivInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (15)); + code.push_back (Compiler::Generator::segment5 (15)); } void opDivFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (16)); + code.push_back (Compiler::Generator::segment5 (16)); } void opIntToFloat1 (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (17)); + code.push_back (Compiler::Generator::segment5 (17)); } void opFloatToInt1 (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (18)); + code.push_back (Compiler::Generator::segment5 (18)); } void opSquareRoot (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (19)); + code.push_back (Compiler::Generator::segment5 (19)); } void opReturn (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (20)); + code.push_back (Compiler::Generator::segment5 (20)); } void opMessageBox (Compiler::Generator::CodeContainer& code, int buttons) { - code.push_back (segment3 (0, buttons)); + code.push_back (Compiler::Generator::segment3 (0, buttons)); } void opFetchLocalShort (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (21)); + code.push_back (Compiler::Generator::segment5 (21)); } void opFetchLocalLong (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (22)); + code.push_back (Compiler::Generator::segment5 (22)); } void opFetchLocalFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (23)); + code.push_back (Compiler::Generator::segment5 (23)); } void opJumpForward (Compiler::Generator::CodeContainer& code, int offset) { - code.push_back (segment0 (1, offset)); + code.push_back (Compiler::Generator::segment0 (1, offset)); } void opJumpBackward (Compiler::Generator::CodeContainer& code, int offset) { - code.push_back (segment0 (2, offset)); + code.push_back (Compiler::Generator::segment0 (2, offset)); } void opSkipOnZero (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (24)); + code.push_back (Compiler::Generator::segment5 (24)); } void opSkipOnNonZero (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (25)); + code.push_back (Compiler::Generator::segment5 (25)); } void opEqualInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (26)); + code.push_back (Compiler::Generator::segment5 (26)); } void opNonEqualInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (27)); + code.push_back (Compiler::Generator::segment5 (27)); } void opLessThanInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (28)); + code.push_back (Compiler::Generator::segment5 (28)); } void opLessOrEqualInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (29)); + code.push_back (Compiler::Generator::segment5 (29)); } void opGreaterThanInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (30)); + code.push_back (Compiler::Generator::segment5 (30)); } void opGreaterOrEqualInt (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (31)); + code.push_back (Compiler::Generator::segment5 (31)); } void opEqualFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (32)); + code.push_back (Compiler::Generator::segment5 (32)); } void opNonEqualFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (33)); + code.push_back (Compiler::Generator::segment5 (33)); } void opLessThanFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (34)); + code.push_back (Compiler::Generator::segment5 (34)); } void opLessOrEqualFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (35)); + code.push_back (Compiler::Generator::segment5 (35)); } void opGreaterThanFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (36)); + code.push_back (Compiler::Generator::segment5 (36)); } void opGreaterOrEqualFloat (Compiler::Generator::CodeContainer& code) { - code.push_back (segment5 (37)); + code.push_back (Compiler::Generator::segment5 (37)); } } diff --git a/components/compiler/generator.hpp b/components/compiler/generator.hpp index 708516cc71..e193902847 100644 --- a/components/compiler/generator.hpp +++ b/components/compiler/generator.hpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -14,6 +15,44 @@ namespace Compiler { typedef std::vector CodeContainer; + inline Interpreter::Type_Code segment0 (unsigned int c, unsigned int arg0) + { + assert (c<64); + return (c<<24) | (arg0 & 0xffffff); + } + + inline Interpreter::Type_Code segment1 (unsigned int c, unsigned int arg0, + unsigned int arg1) + { + assert (c<64); + return 0x40000000 | (c<<24) | ((arg0 & 0xfff)<<12) | (arg1 & 0xfff); + } + + inline Interpreter::Type_Code segment2 (unsigned int c, unsigned int arg0) + { + assert (c<1024); + return 0x80000000 | (c<<20) | (arg0 & 0xfffff); + } + + inline Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0) + { + assert (c<1024); + return 0xc0000000 | (c<<20) | (arg0 & 0xffff); + } + + inline Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0, + unsigned int arg1) + { + assert (c<1024); + return 0xc4000000 | (c<<16) | ((arg0 & 0xff)<<8) | (arg1 & 0xff); + } + + inline Interpreter::Type_Code segment5 (unsigned int c) + { + assert (c<67108864); + return 0xc8000000 | c; + } + void pushInt (CodeContainer& code, Literals& literals, int value); void pushFloat (CodeContainer& code, Literals& literals, float value);