Cromon

Untitled

Sep 3rd, 2013
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.91 KB | None | 0 0
  1. #pragma once
  2.  
  3. class Scope;
  4.  
  5. #include "ObjectWrap.h"
  6. #include "Utils/TypeTraitsExt.h"
  7. #include "JSFunction.h"
  8. #include "JSObject.h"
  9.  
  10. class Function
  11. {
  12.     enum class ArgumentMatch
  13.     {
  14.         Exact,
  15.         CanConvertImplicit,
  16.         CanConvertExplicit,
  17.         None
  18.     };
  19.  
  20.     template<typename T>
  21.     class Argument
  22.     {
  23.     public:
  24.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  25.             return ArgumentMatch::Exact;
  26.         }
  27.  
  28.         static T convert(const v8::Handle<v8::Value>& value) {
  29.             return ObjectWrap::unwrap<T>(value);
  30.         }
  31.     };
  32.  
  33.     template<>
  34.     class Argument<int>
  35.     {
  36.     public:
  37.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  38.             if (value->IsInt32()) {
  39.                 return ArgumentMatch::Exact;
  40.             }
  41.  
  42.             if (value->IsNumber()) {
  43.                 return ArgumentMatch::CanConvertImplicit;
  44.             }
  45.  
  46.             return ArgumentMatch::None;
  47.         }
  48.  
  49.         static int convert(const v8::Handle<v8::Value>& value) {
  50.             return value->Int32Value();
  51.         }
  52.     };
  53.  
  54.     template<>
  55.     class Argument<short>
  56.     {
  57.     public:
  58.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  59.             if (value->IsInt32()) {
  60.                 return ArgumentMatch::Exact;
  61.             }
  62.  
  63.             if (value->IsNumber()) {
  64.                 return ArgumentMatch::CanConvertImplicit;
  65.             }
  66.  
  67.             return ArgumentMatch::None;
  68.         }
  69.  
  70.         static short convert(const v8::Handle<v8::Value>& value) {
  71.             return (short) value->Int32Value();
  72.         }
  73.     };
  74.  
  75.     template<>
  76.     class Argument<char>
  77.     {
  78.     public:
  79.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  80.             if (value->IsInt32()) {
  81.                 return ArgumentMatch::Exact;
  82.             }
  83.  
  84.             if (value->IsNumber()) {
  85.                 return ArgumentMatch::CanConvertImplicit;
  86.             }
  87.  
  88.             return ArgumentMatch::None;
  89.         }
  90.  
  91.         static char convert(const v8::Handle<v8::Value>& value) {
  92.             return (char) value->Int32Value();
  93.         }
  94.     };
  95.  
  96.     template<>
  97.     class Argument<unsigned int>
  98.     {
  99.     public:
  100.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  101.             if (value->IsInt32()) {
  102.                 return ArgumentMatch::Exact;
  103.             }
  104.  
  105.             if (value->IsNumber()) {
  106.                 return ArgumentMatch::CanConvertImplicit;
  107.             }
  108.  
  109.             return ArgumentMatch::None;
  110.         }
  111.  
  112.         static unsigned int convert(const v8::Handle<v8::Value>& value) {
  113.             return value->Uint32Value();
  114.         }
  115.     };
  116.  
  117.     template<>
  118.     class Argument<unsigned short>
  119.     {
  120.     public:
  121.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  122.             if (value->IsInt32()) {
  123.                 return ArgumentMatch::Exact;
  124.             }
  125.  
  126.             if (value->IsNumber()) {
  127.                 return ArgumentMatch::CanConvertImplicit;
  128.             }
  129.  
  130.             return ArgumentMatch::None;
  131.         }
  132.  
  133.         static unsigned short convert(const v8::Handle<v8::Value>& value) {
  134.             return (unsigned short) value->Uint32Value();
  135.         }
  136.     };
  137.  
  138.     template<>
  139.     class Argument<unsigned char>
  140.     {
  141.     public:
  142.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  143.             if (value->IsInt32()) {
  144.                 return ArgumentMatch::Exact;
  145.             }
  146.  
  147.             if (value->IsNumber()) {
  148.                 return ArgumentMatch::CanConvertImplicit;
  149.             }
  150.  
  151.             return ArgumentMatch::None;
  152.         }
  153.  
  154.         static unsigned char convert(const v8::Handle<v8::Value>& value) {
  155.             return (unsigned char) value->Uint32Value();
  156.         }
  157.     };
  158.  
  159.     template<>
  160.     class Argument<float>
  161.     {
  162.     public:
  163.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  164.             if (value->IsInt32()) {
  165.                 return ArgumentMatch::CanConvertImplicit;
  166.             }
  167.  
  168.             if (value->IsNumber()) {
  169.                 return ArgumentMatch::Exact;
  170.             }
  171.  
  172.             return ArgumentMatch::None;
  173.         }
  174.  
  175.         static float convert(const v8::Handle<v8::Value>& value) {
  176.             return (float) value->NumberValue();
  177.         }
  178.     };
  179.  
  180.     template<>
  181.     class Argument<double>
  182.     {
  183.     public:
  184.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  185.             if (value->IsInt32()) {
  186.                 return ArgumentMatch::CanConvertImplicit;
  187.             }
  188.  
  189.             if (value->IsNumber()) {
  190.                 return ArgumentMatch::Exact;
  191.             }
  192.  
  193.             return ArgumentMatch::None;
  194.         }
  195.  
  196.         static double convert(const v8::Handle<v8::Value>& value) {
  197.             return (double) value->NumberValue();
  198.         }
  199.     };
  200.  
  201.     template<>
  202.     class Argument<std::string>
  203.     {
  204.     public:
  205.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  206.             if (value->IsString()) {
  207.                 return ArgumentMatch::Exact;
  208.             }
  209.  
  210.             return ArgumentMatch::CanConvertExplicit;
  211.         }
  212.  
  213.         static std::string convert(const v8::Handle<v8::Value>& value) {
  214.             return ObjectWrap::unwrap<std::string>(value);
  215.         }
  216.     };
  217.  
  218.     template<>
  219.     class Argument<std::wstring>
  220.     {
  221.     public:
  222.         static ArgumentMatch matches(const v8::Handle<v8::Value>& value) {
  223.             if (value->IsString()) {
  224.                 return ArgumentMatch::Exact;
  225.             }
  226.  
  227.             return ArgumentMatch::CanConvertExplicit;
  228.         }
  229.  
  230.         static std::wstring convert(const v8::Handle<v8::Value>& value) {
  231.             v8::Local<v8::String> str = value->ToString();
  232.             if (str->Utf8Length() == 0) {
  233.                 return L"";
  234.             }
  235.  
  236.             std::vector<wchar_t> utf16Buffer(str->Utf8Length());
  237.             str->Write(reinterpret_cast<uint16_t*>(utf16Buffer.data()), 0, utf16Buffer.size());
  238.             return std::wstring(utf16Buffer.begin(), utf16Buffer.end());
  239.         }
  240.     };
  241.  
  242.     class GenericFunctionOverload
  243.     {
  244.     public:
  245.         virtual int getOverloadScore(const v8::Arguments& args, Function* fun) = 0;
  246.         virtual v8::Handle<v8::Value> execute(const v8::Arguments& args, Function* fun) const = 0;
  247.     };
  248.  
  249.     template<typename T, typename... Args>
  250.     class FunctionOverload : public GenericFunctionOverload
  251.     {
  252.     private:
  253.         std::function < T(Args...) > mCallback;
  254.  
  255.         template<int numArgs, int curArg>
  256.         void parseArgScore(int& curScore, const v8::Arguments& args) const {
  257.  
  258.         }
  259.  
  260.         template<int numArgs, int curArg, typename _Cur, typename... Args>
  261.         void parseArgScore(int& curScore, const v8::Arguments& args) const {
  262.             auto match = Argument<_Cur>::matches(args[curArg]);
  263.             if (match == ArgumentMatch::None) {
  264.                 curScore = 0;
  265.             } else if (match == ArgumentMatch::CanConvertImplicit) {
  266.                 curScore -= (int) (99.0f / (2 * numArgs));
  267.             } else if (match == ArgumentMatch::CanConvertExplicit) {
  268.                 curScore -= (int) (99.0f / numArgs);
  269.             }
  270.  
  271.             if (curScore <= 0) {
  272.                 curScore = 0;
  273.                 return;
  274.             }
  275.  
  276.             parseArgScore<numArgs, curArg + 1, Args...>(curScore, args);
  277.         }
  278.  
  279.         template<typename Res, int _curArgNum, typename _curArgType, typename... _remArgs, typename... _prevArgs>
  280.         v8::Handle<v8::Value> _expand_invoke(const v8::Arguments& args, const _prevArgs&... curArgs) const {
  281.             _curArgType curArg = Argument<_curArgType>::convert(args[_curArgNum]);
  282.  
  283.             return _expand_invoke<Res, _curArgNum + 1, _remArgs...>(args, curArgs..., curArg);
  284.         }
  285.  
  286.         template<typename Res, int _curArgNum, typename... _cArgs>
  287.         typename std::enable_if<!std::is_void<Res>::value, v8::Handle<v8::Value>>::type _expand_invoke(const v8::Arguments& args, const Args&... curArgs) const {
  288.             return ObjectWrap::wrap<T>(mCallback(curArgs...));
  289.         }
  290.  
  291.         template<typename Res, int _curArgNum, typename... _cArgs>
  292.         typename std::enable_if<std::is_void<Res>::value, v8::Handle<v8::Value>>::type _expand_invoke(const v8::Arguments& args, const Args&... curArgs) const {
  293.             mCallback(curArgs...);
  294.             return v8::Undefined();
  295.         }
  296.  
  297.     public:
  298.         FunctionOverload(std::function < T(Args...) > callback) {
  299.             mCallback = callback;
  300.         }
  301.  
  302.         template<typename _thisType, typename... Args>
  303.         int getMemberOverloadScore(const v8::Arguments& args, Function* fun) {
  304.             if (args.This().IsEmpty() == true) {
  305.                 return 0;
  306.             }
  307.  
  308.             if (args.Length() != sizeof...(Args)) {
  309.                 return 0;
  310.             }
  311.  
  312.             int score = 100;
  313.             parseArgScore<sizeof...(Args), 0, Args...>(score, args);
  314.             return score;
  315.         }
  316.  
  317.         template<typename ...Args>
  318.         int getOverloadScore(const v8::Arguments& args, Function* fun) {
  319.             if (fun->isMemberFunction()) {
  320.                 return getMemberOverloadScore<Args...>(args, fun);
  321.             }
  322.  
  323.             if (args.Length() != sizeof...(Args)) {
  324.                 return 0;
  325.             }
  326.  
  327.             int score = 100;
  328.             parseArgScore < sizeof...(Args), 0, Args...>(score, args);
  329.             return score;
  330.         }
  331.  
  332.         template<>
  333.         int getOverloadScore<>(const v8::Arguments& args, Function* fun) {
  334.             v8::Handle<v8::External> dataParam = v8::Handle<v8::External>::Cast(args.Data());
  335.  
  336.             if (fun->isMemberFunction() == true) {
  337.                 return 0;
  338.             }
  339.  
  340.             if (args.Length() != 0) {
  341.                 return 0;
  342.             }
  343.  
  344.             return 100;
  345.         }
  346.  
  347.         int getOverloadScore(const v8::Arguments& args, Function* fun) {
  348.             return getOverloadScore<Args...>(args, fun);
  349.         }
  350.  
  351.         template<typename _thisType, typename... Args>
  352.         v8::Handle<v8::Value> execute_member(const v8::Arguments& args, Function* fun) const {
  353.             return _expand_invoke<T, 0, Args...>(args, Argument<_thisType>::convert(args.This()));
  354.         }
  355.  
  356.         template<typename... Args>
  357.         v8::Handle<v8::Value> _execute(const v8::Arguments& args, Function* fun) const {
  358.             if (fun->isMemberFunction()) {
  359.                 return execute_member<Args...>(args, fun);
  360.             }
  361.  
  362.             return _expand_invoke<T, 0, Args...>(args);
  363.         }
  364.  
  365.         template<>
  366.         v8::Handle<v8::Value> _execute<>(const v8::Arguments& args, Function* fun) const {
  367.             return ObjectWrap::wrap<T>(mCallback());
  368.         }
  369.  
  370.         v8::Handle<v8::Value> execute(const v8::Arguments& args, Function* fun) const {
  371.             return _execute<Args...>(args, fun);
  372.         }
  373.     };
  374.  
  375.     typedef std::shared_ptr<GenericFunctionOverload> GenericFunctionOverloadPtr;
  376.  
  377.     int mClassMagic;
  378.     std::list<GenericFunctionOverloadPtr> mOverloads;
  379.     mutable v8::Handle<v8::FunctionTemplate> mTemplate;
  380.     std::string mName;
  381.     bool mIsMemberFunction;
  382.  
  383. private:
  384.     v8::Handle<v8::Value> __functionCallback(const v8::Arguments& args) {
  385.         GenericFunctionOverloadPtr bestMatch = nullptr;
  386.         int maxScore = 0;
  387.         bool hasDuplicate = false;
  388.  
  389.         for (auto& overload : mOverloads) {
  390.             int score = overload->getOverloadScore(args, this);
  391.  
  392.             if (score == 0) {
  393.                 continue;
  394.             }
  395.  
  396.             if (score > maxScore) {
  397.                 bestMatch = overload;
  398.                 maxScore = score;
  399.                 hasDuplicate = false;
  400.             } else if (score == maxScore) {
  401.                 hasDuplicate = true;
  402.             }
  403.         }
  404.  
  405.         if (bestMatch == nullptr) {
  406.             std::stringstream errStrm;
  407.             errStrm << "Unable to match function overload for function '" << mName << "'.";
  408.             v8::ThrowException(v8::Exception::Error(v8::String::New(errStrm.str().c_str())));
  409.             return v8::Undefined();
  410.         }
  411.  
  412.         if (hasDuplicate == true) {
  413.             std::stringstream errStrm;
  414.             errStrm << "Unable to match function overload for function '" << mName << "'. Ambigous function call.";
  415.             v8::ThrowException(v8::Exception::Error(v8::String::New(errStrm.str().c_str())));
  416.             return v8::Undefined();
  417.         }
  418.  
  419.         auto res = bestMatch->execute(args, this);
  420.         return res;
  421.     }
  422.  
  423.     static v8::Handle<v8::Value> __cdecl __staticCallback(const v8::Arguments& args) {
  424.         v8::Handle<v8::External> dataParam = v8::Handle<v8::External>::Cast(args.Data());
  425.         Function* pFunction = reinterpret_cast<Function*>(dataParam->Value());
  426.         if (pFunction->getMagic() != ClassMagic) {
  427.             v8::ThrowException(v8::String::New("Unknown error. Invalid function object."));
  428.             return v8::Undefined();
  429.         }
  430.  
  431.         return pFunction->__functionCallback(args);
  432.     }
  433.  
  434. public:
  435.     Function(const std::string& name) : mName(name) {
  436.         mClassMagic = ClassMagic;
  437.         mIsMemberFunction = false;
  438.     }
  439.  
  440.     //void addToScope(ScopePtr scope) const;
  441.  
  442.     template<typename Res, typename... Args>
  443.     void addOverload(const std::function < Res(Args...) >& function) {
  444.         GenericFunctionOverloadPtr overload = std::dynamic_pointer_cast<GenericFunctionOverload>(
  445.             std::make_shared < FunctionOverload<Res, Args...> >(function)
  446.             );
  447.  
  448.         mOverloads.push_back(overload);
  449.     }
  450.  
  451.     v8::Handle<v8::Value> externalInvoke(const v8::Arguments& cbInfo) { return __functionCallback(cbInfo); }
  452.  
  453.     v8::Handle<v8::FunctionTemplate> getTemplate() const {
  454.         if (mTemplate.IsEmpty() == false) {
  455.             return mTemplate;
  456.         }
  457.  
  458.         mTemplate = v8::FunctionTemplate::New(&Function::__staticCallback, v8::External::New(const_cast<Function*>(this)));
  459.  
  460.         return mTemplate;
  461.     }
  462.  
  463.     int getMagic() const { return mClassMagic; }
  464.  
  465.     void setMemberFunction(bool memberFunction) { mIsMemberFunction = memberFunction; }
  466.     bool isMemberFunction() const { return mIsMemberFunction; }
  467.  
  468.     static const int ClassMagic = 363078014;
  469. };
  470.  
  471. typedef std::shared_ptr<::Function> FunctionPtr;
Advertisement
Add Comment
Please, Sign In to add comment