Skip to content
Permalink
Browse files
This is hard....
  • Loading branch information
ThePhD committed Feb 17, 2016
1 parent 8a7f4e6 commit 0ee92c0
Show file tree
Hide file tree
Showing 13 changed files with 483 additions and 554 deletions.
@@ -24,6 +24,7 @@

#include "function_types_core.hpp"
#include "function_types_static.hpp"
#include "function_types_allocator.hpp"
#include "function_types_member.hpp"
#include "function_types_usertype.hpp"
#include "function_types_overload.hpp"
@@ -0,0 +1,30 @@
// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz and contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_FUNCTION_TYPES_ALLOCATOR_HPP
#define SOL_FUNCTION_TYPES_ALLOCATOR_HPP

#include "stack.hpp"

namespace sol {
} // sol

#endif // SOL_FUNCTION_TYPES_ALLOCATOR_HPP
@@ -24,7 +24,6 @@

#include "stack.hpp"
#include <memory>
#include <unordered_map>

namespace sol {
namespace detail {
@@ -187,17 +186,6 @@ struct base_function {
return r;
}

static int ref_base_call(lua_State* L, void* inheritancedata) {
if(inheritancedata == nullptr) {
throw error("call from Lua to C++ function has null data");
}

base_function* pfx = static_cast<base_function*>(inheritancedata);
base_function& fx = *pfx;
int r = fx(L, detail::ref_call);
return r;
}

static int base_gc(lua_State*, void* udata) {
if(udata == nullptr) {
throw error("call from lua to C++ gc function with null data");
@@ -223,11 +211,7 @@ struct base_function {
struct usertype {
static int call(lua_State* L) {
// Zero-based template parameter, but upvalues start at 1
return ref_base_call(L, stack::get<upvalue>(L, I + 1));
}

static int ref_call(lua_State* L) {
return ref_base_call(L, stack::get<upvalue>(L, I + 1));
return base_call(L, stack::get<upvalue>(L, I + 1));
}

template <std::size_t limit>
@@ -257,10 +241,6 @@ struct base_function {
throw error("failure to call specialized wrapped C++ function from Lua");
}

virtual int operator()(lua_State*, detail::ref_call_t) {
throw error("failure to call reference specialized wrapped C++ function from Lua");
}

virtual ~base_function() {}
};

@@ -54,10 +54,6 @@ struct functor_function : public base_function {
virtual int operator()(lua_State* L) override {
return (*this)(types<return_type>(), args_type(), L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return (*this)(types<return_type>(), args_type(), L);
}
};

template<typename Function, typename T>
@@ -85,10 +81,6 @@ struct member_function : public base_function {
virtual int operator()(lua_State* L) override {
return stack::typed_call(tuple_types<return_type>(), args_types(), fx, L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return (*this)(L);
}
};
} // sol

@@ -76,10 +76,6 @@ struct overloaded_function : base_function {
virtual int operator()(lua_State* L) override {
return match_arity(L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return match_arity(L);
}
};

template <typename T, typename... Functions>
@@ -133,80 +129,6 @@ struct usertype_overloaded_function : base_function {
virtual int operator()(lua_State* L) override {
return match_arity(L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return match_arity(L);
}
};

template<typename... Functions, typename T>
struct usertype_indexing_function<overload_set<Functions...>, T> : base_function {
typedef std::tuple<std::pair<int, detail::functor<T, Functions>>...> overloads_t;
overloads_t overloads;
std::string name;
std::unordered_map<std::string, std::pair<std::unique_ptr<base_function>, bool>> functions;

usertype_indexing_function(std::string name, overload_set<Functions...> set)
: usertype_indexing_function(std::index_sequence_for<Functions...>(), std::move(name), set) {}

template <std::size_t... In>
usertype_indexing_function(std::index_sequence<In...>, std::string name, overload_set<Functions...> set)
: usertype_indexing_function(std::move(name), std::get<In>(set)...) {}

usertype_indexing_function(std::string name, Functions... fxs)
: overloads({static_cast<int>(function_traits<Functions>::arity), fxs}...), name(std::move(name)) {}

int match_arity(std::index_sequence<>, lua_State*, std::ptrdiff_t) {
throw error("no matching function call takes this number of arguments");
}

template <std::size_t I, std::size_t... In>
int match_arity(std::index_sequence<I, In...>, lua_State* L, std::ptrdiff_t x ) {
// TODO:
// propogate changes from above down here too when they get figured out
auto& package = std::get<I>(overloads);
auto arity = package.first;
if (arity != x) {
return match_arity(std::index_sequence<In...>(), L, x);
}
auto& func = package.second;
typedef Unqualified<decltype(func)> fx_t;
typedef tuple_types<typename fx_t::return_type> return_type;
typedef typename fx_t::args_type args_type;
typedef typename args_type::indices args_indices;
if (!detail::check_types(args_type(), args_indices(), L, 2)) {
return match_arity(std::index_sequence<In...>(), L, x);
}
func.item = ptr(stack::get<T>(L, 1));
return stack::typed_call<false>(return_type(), args_type(), func, L);
}

int match_arity(lua_State* L) {
std::ptrdiff_t x = lua_gettop(L) - 1;
return match_arity(std::make_index_sequence<std::tuple_size<overloads_t>::value>(), L, x);
}

int prelude(lua_State* L) {
std::string accessor = stack::get<std::string>(L, 1 - lua_gettop(L));
auto function = functions.find(accessor);
if(function != functions.end()) {
if(function->second.second) {
stack::push<upvalue>(L, function->second.first.get());
stack::push(L, &base_function::usertype<0>::ref_call, 1);
return 1;
}
return (*function->second.first)(L);
}
return match_arity(L);
}

virtual int operator()(lua_State* L) override {
return prelude(L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return prelude(L);
}
};
} // sol

@@ -24,6 +24,7 @@

#include "overload.hpp"
#include "function_types_core.hpp"
#include <map>

namespace sol {
template<typename Function, typename Tp>
@@ -102,10 +103,6 @@ struct usertype_function : public usertype_function_core<Function, Tp> {
virtual int operator()(lua_State* L) override {
return prelude(L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return prelude(L);
}
};

template<typename Function, typename Tp>
@@ -124,7 +121,6 @@ struct usertype_variable_function : public usertype_function_core<Function, Tp>
if(this->fx.item == nullptr) {
throw error("userdata for member variable is null");
}

int argcount = lua_gettop(L);
switch(argcount) {
case 2:
@@ -134,57 +130,34 @@ struct usertype_variable_function : public usertype_function_core<Function, Tp>
default:
throw error("cannot get/set userdata member variable with inappropriate number of arguments");
}

}

virtual int operator()(lua_State* L) override {
return prelude(L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return prelude(L);
}
};

template<typename Function, typename Tp>
struct usertype_indexing_function : public usertype_function_core<Function, Tp> {
typedef usertype_function_core<Function, Tp> base_t;
typedef std::remove_pointer_t<Tp> T;
typedef typename base_t::traits_type traits_type;
typedef typename base_t::args_type args_type;
typedef typename base_t::return_type return_type;

struct usertype_indexing_function : base_function {
std::string name;
std::unordered_map<std::string, std::pair<std::unique_ptr<base_function>, bool>> functions;
base_function* original;
std::map<std::string, base_function*> functions;

template<typename... Args>
usertype_indexing_function(std::string name, Args&&... args): base_t(std::forward<Args>(args)...), name(std::move(name)) {}
usertype_indexing_function(std::string name, base_function* original, Args&&... args): name(std::move(name)), original(original), functions(std::forward<Args>(args)...) {}

int prelude(lua_State* L) {
std::string accessor = stack::get<std::string>(L, 1 - lua_gettop(L));
const char* accessor = stack::get<const char*>(L, 1 - lua_gettop(L));
auto function = functions.find(accessor);
if(function != functions.end()) {
if(function->second.second) {
stack::push<upvalue>(L, function->second.first.get());
stack::push(L, &base_function::usertype<0>::ref_call, 1);
return 1;
}
return (*function->second.first)(L);
}
if (!this->fx.check()) {
throw error("invalid indexing \"" + accessor + "\" on type: " + name);
if (function != functions.end()) {
return (*function->second)(L);
}
this->fx.item = ptr(stack::get<T>(L, 1));
return static_cast<base_t&>(*this)(tuple_types<return_type>(), args_type(), L);
base_function& core = *original;
return core(L);
}

virtual int operator()(lua_State* L) override {
return prelude(L);
}

virtual int operator()(lua_State* L, detail::ref_call_t) override {
return prelude(L);
}
};
} // sol

@@ -42,32 +42,21 @@ class object : public reference {

template<typename T>
bool is() const {
if (!reference::valid())
return false;
auto expected = type_of<T>();
auto actual = get_type();
return (expected == actual) || (expected == type::poly);
}

bool valid() const {
if (!reference::valid())
return false;
return !this->is<nil_t>();
}

operator const char* () const {
return this->as<const char*>();
}

template<typename T, EnableIf<Not<std::is_same<Unqualified<T>, const char*>>, Not<std::is_same<Unqualified<T>, char>>, Not<std::is_same<Unqualified<T>, std::string>>, Not<std::is_same<Unqualified<T>, std::initializer_list<char>>>> = 0>
operator T () const {
return this->as<T>();
}

template<typename... Ret, typename... Args>
decltype(auto) call( Args&&... args ) {
return this->as<function>()(types<Ret...>(), std::forward<Args>( args )...);
}

template<typename... Args>
function_result operator()( Args&&... args ) {
return this->as<function>()(std::forward<Args>( args )...);
explicit operator bool() {
return valid();
}
};

@@ -100,6 +100,10 @@ class reference {
return 1;
}

void pop(int n = 1) const noexcept {
lua_pop(lua_state( ), n);
}

int get_index() const {
return ref;
}

0 comments on commit 0ee92c0

Please sign in to comment.