ChaiScript / ChaiScript
Showing 60 of 237 files from the diff.
Other files ignored by Codecov
LICENSE has changed.
releasenotes.md has changed.
.clang-format has changed.
cheatsheet.md has changed.
.travis.yml has changed.
license.txt has changed.
CMakeLists.txt has changed.
src/sha3.cpp has changed.
appveyor.yml has changed.
readme.md has changed.

@@ -2,17 +2,13 @@
Loading
2 2
3 3
#include "multifile_test_module.hpp"
4 4
5 -
Multi_Test_Module::Multi_Test_Module()
6 -
{
7 -
}
5 +
Multi_Test_Module::Multi_Test_Module() noexcept = default;
8 6
9 -
int Multi_Test_Module::get_module_value()
10 -
{
7 +
int Multi_Test_Module::get_module_value() {
11 8
  return 0;
12 9
}
13 10
14 -
chaiscript::ModulePtr Multi_Test_Module::get_module()
15 -
{
11 +
chaiscript::ModulePtr Multi_Test_Module::get_module() {
16 12
  chaiscript::ModulePtr module(new chaiscript::Module());
17 13
18 14
  module->add(chaiscript::fun(&Multi_Test_Module::get_module_value), "get_module_value");

@@ -1,244 +1,210 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8 8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9 9
10 -
11 10
#ifndef CHAISCRIPT_TYPE_INFO_HPP_
12 11
#define CHAISCRIPT_TYPE_INFO_HPP_
13 12
14 13
#include <memory>
14 +
#include <string>
15 15
#include <type_traits>
16 16
#include <typeinfo>
17 -
#include <string>
18 17
19 -
namespace chaiscript
20 -
{
21 -
22 -
  namespace detail
23 -
  {
18 +
namespace chaiscript {
19 +
  namespace detail {
24 20
    template<typename T>
25 -
      struct Bare_Type
26 -
      {
27 -
        typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
28 -
      };
29 -
  }
30 -
21 +
    struct Bare_Type {
22 +
      using type = typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type;
23 +
    };
24 +
  } // namespace detail
31 25
32 26
  /// \brief Compile time deduced information about a type
33 -
  class Type_Info
34 -
  {
35 -
    public:
36 -
      constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void, 
37 -
          const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
38 -
        : m_type_info(t_ti), m_bare_type_info(t_bare_ti),
39 -
          m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
40 -
                + (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
41 -
                + (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag)
42 -
                + (static_cast<unsigned int>(t_is_void) << is_void_flag)
43 -
                + (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag))
44 -
      {
45 -
      }
46 -
47 -
      constexpr Type_Info() = default;
48 -
49 -
      bool operator<(const Type_Info &ti) const noexcept
50 -
      {
51 -
        return m_type_info->before(*ti.m_type_info);
52 -
      }
53 -
54 -
      constexpr bool operator!=(const Type_Info &ti) const noexcept
55 -
      {
56 -
        return !(operator==(ti));
57 -
      }
58 -
59 -
      constexpr bool operator!=(const std::type_info &ti) const noexcept
60 -
      {
61 -
        return !(operator==(ti));
62 -
      }
63 -
64 -
      constexpr bool operator==(const Type_Info &ti) const noexcept
65 -
      {
66 -
        return ti.m_type_info == m_type_info
67 -
           || *ti.m_type_info == *m_type_info;
68 -
      }
69 -
70 -
      constexpr bool operator==(const std::type_info &ti) const noexcept
71 -
      {
72 -
        return !is_undef() && (*m_type_info) == ti;
27 +
  class Type_Info {
28 +
  public:
29 +
    constexpr Type_Info(const bool t_is_const,
30 +
                        const bool t_is_reference,
31 +
                        const bool t_is_pointer,
32 +
                        const bool t_is_void,
33 +
                        const bool t_is_arithmetic,
34 +
                        const std::type_info *t_ti,
35 +
                        const std::type_info *t_bare_ti) noexcept
36 +
        : m_type_info(t_ti)
37 +
        , m_bare_type_info(t_bare_ti)
38 +
        , m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag) + (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
39 +
                  + (static_cast<unsigned int>(t_is_pointer) << is_pointer_flag) + (static_cast<unsigned int>(t_is_void) << is_void_flag)
40 +
                  + (static_cast<unsigned int>(t_is_arithmetic) << is_arithmetic_flag)) {
41 +
    }
42 +
43 +
    constexpr Type_Info() noexcept = default;
44 +
45 +
    bool operator<(const Type_Info &ti) const noexcept { return m_type_info->before(*ti.m_type_info); }
46 +
47 +
    constexpr bool operator!=(const Type_Info &ti) const noexcept { return !(operator==(ti)); }
48 +
49 +
    constexpr bool operator!=(const std::type_info &ti) const noexcept { return !(operator==(ti)); }
50 +
51 +
    constexpr bool operator==(const Type_Info &ti) const noexcept {
52 +
      return ti.m_type_info == m_type_info || *ti.m_type_info == *m_type_info;
53 +
    }
54 +
55 +
    constexpr bool operator==(const std::type_info &ti) const noexcept { return !is_undef() && (*m_type_info) == ti; }
56 +
57 +
    constexpr bool bare_equal(const Type_Info &ti) const noexcept {
58 +
      return ti.m_bare_type_info == m_bare_type_info || *ti.m_bare_type_info == *m_bare_type_info;
59 +
    }
60 +
61 +
    constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept { return !is_undef() && (*m_bare_type_info) == ti; }
62 +
63 +
    constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
64 +
    constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
65 +
    constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
66 +
    constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
67 +
    constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
68 +
    constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
69 +
70 +
    const char *name() const noexcept {
71 +
      if (!is_undef()) {
72 +
        return m_type_info->name();
73 +
      } else {
74 +
        return "";
73 75
      }
76 +
    }
74 77
75 -
      constexpr bool bare_equal(const Type_Info &ti) const noexcept
76 -
      {
77 -
        return ti.m_bare_type_info == m_bare_type_info
78 -
           || *ti.m_bare_type_info == *m_bare_type_info;
78 +
    const char *bare_name() const noexcept {
79 +
      if (!is_undef()) {
80 +
        return m_bare_type_info->name();
81 +
      } else {
82 +
        return "";
79 83
      }
80 -
81 -
      constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
82 -
      {
83 -
        return !is_undef() && (*m_bare_type_info) == ti;
84 -
      }
85 -
86 -
      constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
87 -
      constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; }
88 -
      constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; }
89 -
      constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; }
90 -
      constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
91 -
      constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
92 -
93 -
      std::string name() const
94 -
      {
95 -
        if (!is_undef())
96 -
        {
97 -
          return m_type_info->name();
98 -
        } else {
99 -
          return "";
100 -
        }
101 -
      }
102 -
103 -
      std::string bare_name() const
104 -
      {
105 -
        if (!is_undef())
106 -
        {
107 -
          return m_bare_type_info->name();
108 -
        } else {
109 -
          return "";
110 -
        }
111 -
      }
112 -
113 -
      constexpr const std::type_info *bare_type_info() const
114 -
      {
115 -
        return m_bare_type_info;
116 -
      }
117 -
118 -
    private:
119 -
      struct Unknown_Type {};
120 -
121 -
      const std::type_info *m_type_info = &typeid(Unknown_Type);
122 -
      const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
123 -
      static const int is_const_flag = 0;
124 -
      static const int is_reference_flag = 1;
125 -
      static const int is_pointer_flag = 2;
126 -
      static const int is_void_flag = 3;
127 -
      static const int is_arithmetic_flag = 4;
128 -
      static const int is_undef_flag = 5;
129 -
      unsigned int m_flags = (1 << is_undef_flag);
84 +
    }
85 +
86 +
    constexpr const std::type_info *bare_type_info() const noexcept { return m_bare_type_info; }
87 +
88 +
  private:
89 +
    struct Unknown_Type {
90 +
    };
91 +
92 +
    const std::type_info *m_type_info = &typeid(Unknown_Type);
93 +
    const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
94 +
    static const int is_const_flag = 0;
95 +
    static const int is_reference_flag = 1;
96 +
    static const int is_pointer_flag = 2;
97 +
    static const int is_void_flag = 3;
98 +
    static const int is_arithmetic_flag = 4;
99 +
    static const int is_undef_flag = 5;
100 +
    unsigned int m_flags = (1 << is_undef_flag);
130 101
  };
131 102
132 -
  namespace detail
133 -
  {
103 +
  namespace detail {
134 104
    /// Helper used to create a Type_Info object
135 105
    template<typename T>
136 -
      struct Get_Type_Info
137 -
      {
138 -
        static constexpr Type_Info get()
139 -
        {
140 -
          return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, 
141 -
              std::is_reference<T>::value, std::is_pointer<T>::value, 
142 -
              std::is_void<T>::value,
143 -
              (std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
144 -
                && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
145 -
              &typeid(T),
146 -
              &typeid(typename Bare_Type<T>::type));
147 -
        }
148 -
      };
106 +
    struct Get_Type_Info {
107 +
      constexpr static Type_Info get() noexcept {
108 +
        return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
109 +
                         std::is_reference<T>::value,
110 +
                         std::is_pointer<T>::value,
111 +
                         std::is_void<T>::value,
112 +
                         (std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
113 +
                             && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
114 +
                         &typeid(T),
115 +
                         &typeid(typename Bare_Type<T>::type));
116 +
      }
117 +
    };
149 118
150 119
    template<typename T>
151 -
      struct Get_Type_Info<std::shared_ptr<T> >
152 -
      {
153 -
//        typedef T type;
154 -
155 -
        static constexpr Type_Info get()
156 -
        {
157 -
          return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value, 
158 -
              std::is_void<T>::value,
159 -
              std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
160 -
              &typeid(std::shared_ptr<T> ), 
161 -
              &typeid(typename Bare_Type<T>::type));
162 -
        }
163 -
      };
120 +
    struct Get_Type_Info<std::shared_ptr<T>> {
121 +
      constexpr static Type_Info get() noexcept {
122 +
        return Type_Info(std::is_const<T>::value,
123 +
                         std::is_reference<T>::value,
124 +
                         std::is_pointer<T>::value,
125 +
                         std::is_void<T>::value,
126 +
                         std::is_arithmetic<T>::value
127 +
                             && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
128 +
                         &typeid(std::shared_ptr<T>),
129 +
                         &typeid(typename Bare_Type<T>::type));
130 +
      }
131 +
    };
164 132
165 133
    template<typename T>
166 -
      struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>>
167 -
      {
168 -
      };
134 +
    struct Get_Type_Info<std::shared_ptr<T> &> : Get_Type_Info<std::shared_ptr<T>> {
135 +
    };
169 136
170 137
    template<typename T>
171 -
      struct Get_Type_Info<const std::shared_ptr<T> &>
172 -
      {
173 -
        static constexpr Type_Info get()
174 -
        {
175 -
          return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value, 
176 -
              std::is_void<T>::value,
177 -
              std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
178 -
              &typeid(const std::shared_ptr<T> &), 
179 -
              &typeid(typename Bare_Type<T>::type));
180 -
        }
181 -
      };
138 +
    struct Get_Type_Info<const std::shared_ptr<T> &> {
139 +
      constexpr static Type_Info get() noexcept {
140 +
        return Type_Info(std::is_const<T>::value,
141 +
                         std::is_reference<T>::value,
142 +
                         std::is_pointer<T>::value,
143 +
                         std::is_void<T>::value,
144 +
                         std::is_arithmetic<T>::value
145 +
                             && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
146 +
                         &typeid(const std::shared_ptr<T> &),
147 +
                         &typeid(typename Bare_Type<T>::type));
148 +
      }
149 +
    };
182 150
183 151
    template<typename T>
184 -
      struct Get_Type_Info<std::reference_wrapper<T> >
185 -
      {
186 -
        static constexpr Type_Info get()
187 -
        {
188 -
          return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value, 
189 -
              std::is_void<T>::value,
190 -
              std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
191 -
              &typeid(std::reference_wrapper<T> ), 
192 -
              &typeid(typename Bare_Type<T>::type));
193 -
        }
194 -
      };
152 +
    struct Get_Type_Info<std::reference_wrapper<T>> {
153 +
      constexpr static Type_Info get() noexcept {
154 +
        return Type_Info(std::is_const<T>::value,
155 +
                         std::is_reference<T>::value,
156 +
                         std::is_pointer<T>::value,
157 +
                         std::is_void<T>::value,
158 +
                         std::is_arithmetic<T>::value
159 +
                             && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
160 +
                         &typeid(std::reference_wrapper<T>),
161 +
                         &typeid(typename Bare_Type<T>::type));
162 +
      }
163 +
    };
195 164
196 165
    template<typename T>
197 -
      struct Get_Type_Info<const std::reference_wrapper<T> &>
198 -
      {
199 -
        static constexpr Type_Info get()
200 -
        {
201 -
          return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value, 
202 -
              std::is_void<T>::value,
203 -
              std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
204 -
              &typeid(const std::reference_wrapper<T> &), 
205 -
              &typeid(typename Bare_Type<T>::type));
206 -
        }
207 -
      };
166 +
    struct Get_Type_Info<const std::reference_wrapper<T> &> {
167 +
      constexpr static Type_Info get() noexcept {
168 +
        return Type_Info(std::is_const<T>::value,
169 +
                         std::is_reference<T>::value,
170 +
                         std::is_pointer<T>::value,
171 +
                         std::is_void<T>::value,
172 +
                         std::is_arithmetic<T>::value
173 +
                             && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
174 +
                         &typeid(const std::reference_wrapper<T> &),
175 +
                         &typeid(typename Bare_Type<T>::type));
176 +
      }
177 +
    };
208 178
209 -
  }
179 +
  } // namespace detail
210 180
211 181
  /// \brief Creates a Type_Info object representing the type passed in
212 182
  /// \tparam T Type of object to get a Type_Info for, derived from the passed in parameter
213 183
  /// \return Type_Info for T
214 -
  /// 
184 +
  ///
215 185
  /// \b Example:
216 186
  /// \code
217 187
  /// int i;
218 188
  /// chaiscript::Type_Info ti = chaiscript::user_type(i);
219 189
  /// \endcode
220 190
  template<typename T>
221 -
  constexpr Type_Info user_type(const T &/*t*/)
222 -
  {
191 +
  constexpr Type_Info user_type(const T & /*t*/) noexcept {
223 192
    return detail::Get_Type_Info<T>::get();
224 193
  }
225 194
226 -
227 195
  /// \brief Creates a Type_Info object representing the templated type
228 196
  /// \tparam T Type of object to get a Type_Info for
229 197
  /// \return Type_Info for T
230 -
  /// 
198 +
  ///
231 199
  /// \b Example:
232 200
  /// \code
233 201
  /// chaiscript::Type_Info ti = chaiscript::user_type<int>();
234 202
  /// \endcode
235 203
  template<typename T>
236 -
  constexpr Type_Info user_type()
237 -
  {
204 +
  constexpr Type_Info user_type() noexcept {
238 205
    return detail::Get_Type_Info<T>::get();
239 206
  }
240 207
241 -
}
208 +
} // namespace chaiscript
242 209
243 210
#endif
244 -

@@ -1,23 +1,61 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8 8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9 9
10 -
11 10
#ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_
12 11
#define CHAISCRIPT_REGISTER_FUNCTION_HPP_
13 12
14 13
#include <type_traits>
15 14
16 15
#include "bind_first.hpp"
16 +
#include "function_signature.hpp"
17 17
#include "proxy_functions.hpp"
18 18
19 -
namespace chaiscript
20 -
{
19 +
namespace chaiscript {
20 +
  namespace dispatch::detail {
21 +
    template<typename Obj, typename Param1, typename... Rest>
22 +
    Param1 get_first_param(Function_Params<Param1, Rest...>, Obj &&obj) {
23 +
      return static_cast<Param1>(std::forward<Obj>(obj));
24 +
    }
25 +
26 +
    template<typename Func, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject, bool Is_Object, typename Ret, typename... Param>
27 +
    auto make_callable_impl(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>) {
28 +
      if constexpr (Is_MemberObject) {
29 +
        // we now that the Param pack will have only one element, so we are safe expanding it here
30 +
        return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(
31 +
            std::forward<Func>(func)));
32 +
      } else if constexpr (Is_Member) {
33 +
        // TODO some kind of bug is preventing forwarding of this noexcept for the lambda
34 +
        auto call = [func = std::forward<Func>(func)](auto &&obj, auto &&...param) /* noexcept(Is_Noexcept) */ -> decltype(auto) {
35 +
          return ((get_first_param(Function_Params<Param...>{}, obj).*func)(std::forward<decltype(param)>(param)...));
36 +
        };
37 +
        return Proxy_Function(
38 +
            chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret(Param...), decltype(call)>>(
39 +
                std::move(call)));
40 +
      } else {
41 +
        return Proxy_Function(
42 +
            chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret(Param...), std::decay_t<Func>>>(
43 +
                std::forward<Func>(func)));
44 +
      }
45 +
    }
46 +
47 +
    // this version peels off the function object itself from the function signature, when used
48 +
    // on a callable object
49 +
    template<typename Func, typename Ret, typename Object, typename... Param, bool Is_Noexcept>
50 +
    auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Object, Param...>, Is_Noexcept, false, false, true>) {
51 +
      return make_callable_impl(std::forward<Func>(func), Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, false, false, true>{});
52 +
    }
53 +
54 +
    template<typename Func, typename Ret, typename... Param, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject>
55 +
    auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, false> fs) {
56 +
      return make_callable_impl(std::forward<Func>(func), fs);
57 +
    }
58 +
  } // namespace dispatch::detail
21 59
22 60
  /// \brief Creates a new Proxy_Function object from a free function, member function or data member
23 61
  /// \param[in] t Function / member to expose
@@ -31,95 +69,19 @@
Loading
31 69
  ///     void memberfunction();
32 70
  ///     int memberdata;
33 71
  /// };
34 -
  /// 
72 +
  ///
35 73
  /// chaiscript::ChaiScript chai;
36 74
  /// chai.add(fun(&myfunction), "myfunction");
37 75
  /// chai.add(fun(&MyClass::memberfunction), "memberfunction");
38 76
  /// chai.add(fun(&MyClass::memberdata), "memberdata");
39 77
  /// \endcode
40 -
  /// 
78 +
  ///
41 79
  /// \sa \ref adding_functions
42 80
  template<typename T>
43 -
    Proxy_Function fun(const T &t)
44 -
    {
45 -
      typedef typename dispatch::detail::Callable_Traits<T>::Signature Signature;
46 -
47 -
      return Proxy_Function(
48 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
49 -
    }
50 -
51 -
52 -
  template<typename Ret, typename ... Param>
53 -
    Proxy_Function fun(Ret (*func)(Param...))
54 -
    {
55 -
      auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
56 -
57 -
      return Proxy_Function(
58 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
59 -
60 -
    }
61 -
62 -
  template<typename Ret, typename Class, typename ... Param>
63 -
    Proxy_Function fun(Ret (Class::*t_func)(Param...) const)
64 -
    {
65 -
      auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
66 -
67 -
      return Proxy_Function(
68 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
69 -
    }
70 -
71 -
  template<typename Ret, typename Class, typename ... Param>
72 -
    Proxy_Function fun(Ret (Class::*t_func)(Param...))
73 -
    {
74 -
      auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
75 -
76 -
      return Proxy_Function(
77 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
78 -
79 -
    }
80 -
81 -
  template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
82 -
    Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
83 -
    {
84 -
      return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<T, Class>>(m));
85 -
    }
86 -
87 -
// only compile this bit if noexcept is part of the type system
88 -
//
89 -
#if (defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510) || (defined(_NOEXCEPT_TYPES_SUPPORTED) && _MSC_VER >= 1912)
90 -
  template<typename Ret, typename ... Param>
91 -
    Proxy_Function fun(Ret (*func)(Param...) noexcept)
92 -
    {
93 -
      auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
94 -
95 -
      return Proxy_Function(
96 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
97 -
98 -
    }
99 -
100 -
  template<typename Ret, typename Class, typename ... Param>
101 -
    Proxy_Function fun(Ret (Class::*t_func)(Param...) const noexcept)
102 -
    {
103 -
      auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
104 -
105 -
      return Proxy_Function(
106 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
107 -
    }
108 -
109 -
  template<typename Ret, typename Class, typename ... Param>
110 -
    Proxy_Function fun(Ret (Class::*t_func)(Param...) noexcept)
111 -
    {
112 -
      auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
113 -
114 -
      return Proxy_Function(
115 -
          chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
81 +
  Proxy_Function fun(T &&t) {
82 +
    return dispatch::detail::make_callable(std::forward<T>(t), dispatch::detail::function_signature(t));
83 +
  }
116 84
117 -
    }
118 -
#endif
119 -
120 -
121 -
122 -
  
123 85
  /// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
124 86
  /// \param[in] t Function / member to expose
125 87
  /// \param[in] q Value to bind to first parameter
@@ -130,23 +92,19 @@
Loading
130 92
  /// {
131 93
  ///   void memberfunction(int);
132 94
  /// };
133 -
  /// 
95 +
  ///
134 96
  /// MyClass obj;
135 97
  /// chaiscript::ChaiScript chai;
136 98
  /// // Add function taking only one argument, an int, and permanently bound to "obj"
137 -
  /// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction"); 
99 +
  /// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction");
138 100
  /// \endcode
139 -
  /// 
101 +
  ///
140 102
  /// \sa \ref adding_functions
141 103
  template<typename T, typename Q>
142 -
    Proxy_Function fun(T &&t, const Q &q)
143 -
    {
144 -
      return fun(detail::bind_first(std::forward<T>(t), q));
145 -
    }
146 -
147 -
148 -
}
104 +
  Proxy_Function fun(T &&t, const Q &q) {
105 +
    return fun(detail::bind_first(std::forward<T>(t), q));
106 +
  }
149 107
108 +
} // namespace chaiscript
150 109
151 110
#endif
152 -

@@ -11,34 +11,27 @@
Loading
11 11
#pragma GCC diagnostic ignored "-Wparentheses"
12 12
#endif
13 13
14 -
15 14
#include <chaiscript/chaiscript_defines.hpp>
16 15
#include <chaiscript/dispatchkit/type_info.hpp>
17 -
#include <iostream>
18 16
#include <cstdlib>
19 -
20 -
21 -
17 +
#include <iostream>
22 18
23 19
#define CATCH_CONFIG_MAIN
24 20
25 21
#include "catch.hpp"
26 22
27 -
28 -
TEST_CASE("Type_Info objects generate expected results")
29 -
{
30 -
  const auto test_type = [](const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void,
31 -
    bool t_is_undef, bool t_is_arithmetic)
32 -
  {
33 -
    CHECK(ti.is_const() == t_is_const);
34 -
    CHECK(ti.is_pointer() == t_is_pointer);
35 -
    CHECK(ti.is_reference() == t_is_reference);
36 -
    CHECK(ti.is_void() == t_is_void);
37 -
    CHECK(ti.is_undef() == t_is_undef);
38 -
    CHECK(ti.is_arithmetic() == t_is_arithmetic);
39 -
  };
40 -
41 -
  SECTION("void") {  test_type(chaiscript::user_type<void>(), false, false, false, true, false, false); }
23 +
TEST_CASE("Type_Info objects generate expected results") {
24 +
  const auto test_type
25 +
      = [](const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void, bool t_is_undef, bool t_is_arithmetic) {
26 +
          CHECK(ti.is_const() == t_is_const);
27 +
          CHECK(ti.is_pointer() == t_is_pointer);
28 +
          CHECK(ti.is_reference() == t_is_reference);
29 +
          CHECK(ti.is_void() == t_is_void);
30 +
          CHECK(ti.is_undef() == t_is_undef);
31 +
          CHECK(ti.is_arithmetic() == t_is_arithmetic);
32 +
        };
33 +
34 +
  SECTION("void") { test_type(chaiscript::user_type<void>(), false, false, false, true, false, false); }
42 35
  SECTION("const int") { test_type(chaiscript::user_type<const int>(), true, false, false, false, false, true); }
43 36
  SECTION("const int &") { test_type(chaiscript::user_type<const int &>(), true, false, true, false, false, true); }
44 37
  SECTION("int") { test_type(chaiscript::user_type<int>(), false, false, false, false, false, true); }
@@ -49,6 +42,3 @@
Loading
49 42
50 43
  std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
51 44
}
52 -
53 -
54 -

@@ -0,0 +1,149 @@
Loading
1 +
#ifndef CHAISCRIPT_FUNCTION_SIGNATURE_HPP
2 +
#define CHAISCRIPT_FUNCTION_SIGNATURE_HPP
3 +
4 +
#include <type_traits>
5 +
6 +
namespace chaiscript::dispatch::detail {
7 +
  template<typename... Param>
8 +
  struct Function_Params {
9 +
  };
10 +
11 +
  template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
12 +
  struct Function_Signature {
13 +
    using Param_Types = Params;
14 +
    using Return_Type = Ret;
15 +
    constexpr static const bool is_object = IsObject;
16 +
    constexpr static const bool is_member_object = IsMemberObject;
17 +
    constexpr static const bool is_noexcept = IsNoExcept;
18 +
    template<typename T>
19 +
    constexpr Function_Signature(T &&) noexcept {
20 +
    }
21 +
    constexpr Function_Signature() noexcept = default;
22 +
  };
23 +
24 +
  // Free functions
25 +
26 +
  template<typename Ret, typename... Param>
27 +
  Function_Signature(Ret (*f)(Param...)) -> Function_Signature<Ret, Function_Params<Param...>>;
28 +
29 +
  template<typename Ret, typename... Param>
30 +
  Function_Signature(Ret (*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Param...>, true>;
31 +
32 +
  // no reference specifier
33 +
34 +
  template<typename Ret, typename Class, typename... Param>
35 +
  Function_Signature(Ret (Class::*f)(Param...) volatile) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
36 +
37 +
  template<typename Ret, typename Class, typename... Param>
38 +
  Function_Signature(Ret (Class::*f)(Param...) volatile noexcept)
39 +
      -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
40 +
41 +
  template<typename Ret, typename Class, typename... Param>
42 +
  Function_Signature(Ret (Class::*f)(Param...) volatile const)
43 +
      -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
44 +
45 +
  template<typename Ret, typename Class, typename... Param>
46 +
  Function_Signature(Ret (Class::*f)(Param...) volatile const noexcept)
47 +
      -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
48 +
49 +
  template<typename Ret, typename Class, typename... Param>
50 +
  Function_Signature(Ret (Class::*f)(Param...)) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
51 +
52 +
  template<typename Ret, typename Class, typename... Param>
53 +
  Function_Signature(Ret (Class::*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
54 +
55 +
  template<typename Ret, typename Class, typename... Param>
56 +
  Function_Signature(Ret (Class::*f)(Param...) const) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
57 +
58 +
  template<typename Ret, typename Class, typename... Param>
59 +
  Function_Signature(Ret (Class::*f)(Param...) const noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
60 +
61 +
  // & reference specifier
62 +
63 +
  template<typename Ret, typename Class, typename... Param>
64 +
  Function_Signature(Ret (Class::*f)(Param...) volatile &) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
65 +
66 +
  template<typename Ret, typename Class, typename... Param>
67 +
  Function_Signature(Ret (Class::*f)(Param...) volatile &noexcept)
68 +
      -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
69 +
70 +
  template<typename Ret, typename Class, typename... Param>
71 +
  Function_Signature(Ret (Class::*f)(Param...) volatile const &)
72 +
      -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
73 +
74 +
  template<typename Ret, typename Class, typename... Param>
75 +
  Function_Signature(Ret (Class::*f)(Param...) volatile const &noexcept)
76 +
      -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
77 +
78 +
  template<typename Ret, typename Class, typename... Param>
79 +
  Function_Signature(Ret (Class::*f)(Param...) &) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
80 +
81 +
  template<typename Ret, typename Class, typename... Param>
82 +
  Function_Signature(Ret (Class::*f)(Param...) &noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
83 +
84 +
  template<typename Ret, typename Class, typename... Param>
85 +
  Function_Signature(Ret (Class::*f)(Param...) const &) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
86 +
87 +
  template<typename Ret, typename Class, typename... Param>
88 +
  Function_Signature(Ret (Class::*f)(Param...) const &noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
89 +
90 +
  // && reference specifier
91 +
92 +
  template<typename Ret, typename Class, typename... Param>
93 +
  Function_Signature(Ret (Class::*f)(Param...) volatile &&) -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
94 +
95 +
  template<typename Ret, typename Class, typename... Param>
96 +
  Function_Signature(Ret (Class::*f)(Param...) volatile &&noexcept)
97 +
      -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, true, true>;
98 +
99 +
  template<typename Ret, typename Class, typename... Param>
100 +
  Function_Signature(Ret (Class::*f)(Param...) volatile const &&)
101 +
      -> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, false, true>;
102 +
103 +
  template<typename Ret, typename Class, typename... Param>
104 +
  Function_Signature(Ret (Class::*f)(Param...) volatile const &&noexcept)
105 +
      -> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, true, true>;
106 +
107 +
  template<typename Ret, typename Class, typename... Param>
108 +
  Function_Signature(Ret (Class::*f)(Param...) &&) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
109 +
110 +
  template<typename Ret, typename Class, typename... Param>
111 +
  Function_Signature(Ret (Class::*f)(Param...) &&noexcept) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
112 +
113 +
  template<typename Ret, typename Class, typename... Param>
114 +
  Function_Signature(Ret (Class::*f)(Param...) const &&) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
115 +
116 +
  template<typename Ret, typename Class, typename... Param>
117 +
  Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)
118 +
      -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>;
119 +
120 +
  template<typename Ret, typename Class>
121 +
  Function_Signature(Ret Class::*f) -> Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
122 +
123 +
  // primary template handles types that have no nested ::type member:
124 +
  template<class, class = std::void_t<>>
125 +
  struct has_call_operator : std::false_type {
126 +
  };
127 +
128 +
  // specialization recognizes types that do have a nested ::type member:
129 +
  template<class T>
130 +
  struct has_call_operator<T, std::void_t<decltype(&T::operator())>> : std::true_type {
131 +
  };
132 +
133 +
  template<typename Func>
134 +
  auto function_signature(const Func &f) {
135 +
    if constexpr (has_call_operator<Func>::value) {
136 +
      return Function_Signature<typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Return_Type,
137 +
                                typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Param_Types,
138 +
                                decltype(Function_Signature{&std::decay_t<Func>::operator()})::is_noexcept,
139 +
                                false,
140 +
                                false,
141 +
                                true>{};
142 +
    } else {
143 +
      return Function_Signature{f};
144 +
    }
145 +
  }
146 +
147 +
} // namespace chaiscript::dispatch::detail
148 +
149 +
#endif

@@ -1,46 +1,37 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
#ifndef CHAISCRIPT_TRACER_HPP_
8 8
#define CHAISCRIPT_TRACER_HPP_
9 9
10 -
namespace chaiscript {
11 -
  namespace eval {
10 +
namespace chaiscript::eval {
11 +
  struct Noop_Tracer_Detail {
12 +
    template<typename T>
13 +
    constexpr void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *) noexcept {
14 +
    }
15 +
  };
12 16
17 +
  template<typename... T>
18 +
  struct Tracer : T... {
19 +
    Tracer() = default;
20 +
    constexpr explicit Tracer(T... t)
21 +
        : T(std::move(t))... {
22 +
    }
13 23
14 -
    struct Noop_Tracer_Detail
15 -
    {
16 -
      template<typename T>
17 -
        void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
18 -
        {
19 -
        }
20 -
    };
24 +
    void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
25 +
      (static_cast<T &>(*this).trace(ds, node), ...);
26 +
    }
21 27
22 -
    template<typename ... T>
23 -
      struct Tracer : T...
24 -
    {
25 -
      Tracer() = default;
26 -
      explicit Tracer(T ... t)
27 -
        : T(std::move(t))...
28 -
      {
29 -
      }
28 +
    static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
29 +
      ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
30 +
    }
31 +
  };
30 32
31 -
      void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
32 -
        (void)std::initializer_list<int>{ (static_cast<T&>(*this).trace(ds, node), 0)... };
33 -
      }
33 +
  using Noop_Tracer = Tracer<Noop_Tracer_Detail>;
34 34
35 -
      static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
36 -
        ds->get_parser().get_tracer<Tracer<T...>>().do_trace(ds, node);
37 -
      }
38 -
    };
39 -
40 -
    typedef Tracer<Noop_Tracer_Detail> Noop_Tracer;
41 -
42 -
  }
43 -
}
35 +
} // namespace chaiscript::eval
44 36
45 37
#endif
46 -

@@ -1,21 +1,16 @@
Loading
1 -
#include <chaiscript/chaiscript_basic.hpp>
2 1
#include "../static_libs/chaiscript_parser.hpp"
3 2
#include "../static_libs/chaiscript_stdlib.hpp"
3 +
#include <chaiscript/chaiscript_basic.hpp>
4 4
5 -
6 -
extern "C"
7 -
{
8 -
  int do_something(int i)
9 -
  {
10 -
    return i % 2;
11 -
  }
5 +
extern "C" {
6 +
int do_something(int i) {
7 +
  return i % 2;
8 +
}
12 9
}
13 10
14 -
int main()
15 -
{
16 -
  chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
11 +
int main() {
12 +
  chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
17 13
  chai.add(chaiscript::fun(&do_something), "do_something");
18 14
19 -
  return chai.eval<int>("do_something(101)") == 101 % 2?EXIT_SUCCESS:EXIT_FAILURE;
20 -
15 +
  return chai.eval<int>("do_something(101)") == 101 % 2 ? EXIT_SUCCESS : EXIT_FAILURE;
21 16
}

@@ -1,8 +1,6 @@
Loading
1 1
#include "../include/chaiscript/chaiscript_stdlib.hpp"
2 2
#include "chaiscript_stdlib.hpp"
3 3
4 -
std::shared_ptr<chaiscript::Module> create_chaiscript_stdlib()
5 -
{
4 +
std::shared_ptr<chaiscript::Module> create_chaiscript_stdlib() {
6 5
  return chaiscript::Std_Lib::library();
7 6
}
8 -

@@ -0,0 +1,133 @@
Loading
1 +
#ifndef CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
2 +
#define CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
3 +
4 +
namespace chaiscript::utility {
5 +
  template<typename Key, typename Value, typename Comparator = std::equal_to<>>
6 +
  struct QuickFlatMap {
7 +
    Comparator comparator;
8 +
9 +
    template<typename Lookup>
10 +
    auto find(const Lookup &s) noexcept {
11 +
      return std::find_if(std::begin(data), std::end(data), [&s, this](const auto &d) { return comparator(d.first, s); });
12 +
    }
13 +
14 +
    template<typename Lookup>
15 +
    auto find(const Lookup &s) const noexcept {
16 +
      return std::find_if(std::cbegin(data), std::cend(data), [&s, this](const auto &d) { return comparator(d.first, s); });
17 +
    }
18 +
19 +
    template<typename Lookup>
20 +
    auto find(const Lookup &s, const std::size_t t_hint) const noexcept {
21 +
      if (data.size() > t_hint && comparator(data[t_hint].first, s)) {
22 +
        const auto begin = std::cbegin(data);
23 +
        return std::next(begin, static_cast<typename std::iterator_traits<std::decay_t<decltype(begin)>>::difference_type>(t_hint));
24 +
      } else {
25 +
        return find(s);
26 +
      }
27 +
    }
28 +
29 +
    auto size() const noexcept { return data.size(); }
30 +
31 +
    auto begin() const noexcept { return data.begin(); }
32 +
33 +
    auto end() const noexcept { return data.end(); }
34 +
35 +
    auto begin() noexcept { return data.begin(); }
36 +
37 +
    auto end() noexcept { return data.end(); }
38 +
39 +
    auto &back() noexcept { return data.back(); }
40 +
41 +
    const auto &back() const noexcept { return data.back(); }
42 +
43 +
    Value &operator[](const Key &s) {
44 +
      const auto itr = find(s);
45 +
      if (itr != data.end()) {
46 +
        return itr->second;
47 +
      } else {
48 +
        grow();
49 +
        return data.emplace_back(s, Value()).second;
50 +
      }
51 +
    }
52 +
53 +
    Value &at_index(const std::size_t idx) noexcept { return data[idx].second; }
54 +
55 +
    const Value &at_index(const std::size_t idx) const noexcept { return data[idx].second; }
56 +
57 +
    bool empty() const noexcept { return data.empty(); }
58 +
59 +
    template<typename Itr>
60 +
    void assign(Itr begin, Itr end) {
61 +
      data.assign(begin, end);
62 +
    }
63 +
64 +
    Value &at(const Key &s) {
65 +
      const auto itr = find(s);
66 +
      if (itr != data.end()) {
67 +
        return itr->second;
68 +
      } else {
69 +
        throw std::out_of_range("Unknown key: " + s);
70 +
      }
71 +
    }
72 +
73 +
    template<typename M>
74 +
    auto insert_or_assign(Key &&key, M &&m) {
75 +
      if (auto itr = find(key); itr != data.end()) {
76 +
        *itr = std::forward<M>(m);
77 +
        return std::pair{itr, false};
78 +
      } else {
79 +
        grow();
80 +
        return std::pair{data.emplace(data.end(), std::move(key), std::forward<M>(m)), true};
81 +
      }
82 +
    }
83 +
84 +
    template<typename M>
85 +
    auto insert_or_assign(const Key &key, M &&m) {
86 +
      if (auto itr = find(key); itr != data.end()) {
87 +
        itr->second = std::forward<M>(m);
88 +
        return std::pair{itr, false};
89 +
      } else {
90 +
        grow();
91 +
        return std::pair{data.emplace(data.end(), key, std::forward<M>(m)), true};
92 +
      }
93 +
    }
94 +
95 +
    const Value &at(const Key &s) const {
96 +
      const auto itr = find(s);
97 +
      if (itr != data.end()) {
98 +
        return itr->second;
99 +
      } else {
100 +
        throw std::out_of_range("Unknown key: " + s);
101 +
      }
102 +
    }
103 +
104 +
    template<typename Lookup>
105 +
    size_t count(const Lookup &s) const noexcept {
106 +
      return (find(s) != data.end()) ? 1 : 0;
107 +
    }
108 +
109 +
    std::vector<std::pair<Key, Value>> data;
110 +
111 +
    using value_type = std::pair<Key, Value>;
112 +
    using iterator = typename decltype(data)::iterator;
113 +
    using const_iterator = typename decltype(data)::const_iterator;
114 +
115 +
    std::pair<iterator, bool> insert(value_type &&value) {
116 +
      if (const auto itr = find(value.first); itr != data.end()) {
117 +
        return std::pair{itr, false};
118 +
      } else {
119 +
        grow();
120 +
        return std::pair{data.insert(data.end(), std::move(value)), true};
121 +
      }
122 +
    }
123 +
124 +
    void grow() {
125 +
      if ((data.capacity() - data.size()) == 0) {
126 +
        data.reserve(data.size() + 2);
127 +
      }
128 +
    }
129 +
  };
130 +
131 +
} // namespace chaiscript::utility
132 +
133 +
#endif

@@ -1,13 +1,12 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8 8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9 9
10 -
11 10
#ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
12 11
#define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_
13 12
@@ -20,152 +19,79 @@
Loading
20 19
#include "boxed_cast.hpp"
21 20
#include "boxed_number.hpp"
22 21
#include "boxed_value.hpp"
23 -
#include "type_conversions.hpp"
24 22
#include "proxy_functions.hpp"
23 +
#include "type_conversions.hpp"
25 24
26 -
namespace chaiscript
27 -
{
28 -
  namespace dispatch
29 -
  {
30 -
    namespace detail
31 -
    {
32 -
      /// Internal helper class for handling the return
33 -
      /// value of a build_function_caller
34 -
      template<typename Ret, bool is_arithmetic>
35 -
        struct Function_Caller_Ret
36 -
        {
37 -
          static Ret call(const std::vector<Const_Proxy_Function> &t_funcs, 
38 -
              const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
39 -
          {
40 -
            if (t_conversions != nullptr) {
41 -
              return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
42 -
            } else {
43 -
              Type_Conversions conv;
44 -
              Type_Conversions_State state(conv, conv.conversion_saves());
45 -
              return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
46 -
            }
47 -
          }
48 -
        };
49 -
50 -
      /**
51 -
       * Specialization for arithmetic return types
52 -
       */
53 -
      template<typename Ret>
54 -
        struct Function_Caller_Ret<Ret, true>
55 -
        {
56 -
          static Ret call(const std::vector<Const_Proxy_Function> &t_funcs, 
57 -
              const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
58 -
          {
59 -
            if (t_conversions != nullptr) {
60 -
              return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
61 -
            } else {
62 -
              Type_Conversions conv;
63 -
              Type_Conversions_State state(conv, conv.conversion_saves());
64 -
              return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
65 -
            }
66 -
          }
67 -
        };
68 -
69 -
70 -
      /**
71 -
       * Specialization for void return types
72 -
       */
73 -
      template<>
74 -
        struct Function_Caller_Ret<void, false>
75 -
        {
76 -
          static void call(const std::vector<Const_Proxy_Function> &t_funcs, 
77 -
              const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
78 -
          {
79 -
            if (t_conversions != nullptr) {
80 -
              dispatch::dispatch(t_funcs, params, *t_conversions);
81 -
            } else {
82 -
              Type_Conversions conv;
83 -
              Type_Conversions_State state(conv, conv.conversion_saves());
84 -
              dispatch::dispatch(t_funcs, params, state);
85 -
            }
86 -
          }
87 -
        };
88 -
89 -
      /**
90 -
       * used internally for unwrapping a function call's types
91 -
       */
92 -
      template<typename Ret, typename ... Param>
93 -
        struct Build_Function_Caller_Helper
94 -
        {
95 -
          Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions *t_conversions)
96 -
            : m_funcs(std::move(t_funcs)),
97 -
              m_conversions(t_conversions)
98 -
          {
99 -
          }
100 -
101 -
          template<typename ... P>
102 -
          Ret operator()(P&&  ...  param)
103 -
          {
104 -
            if (m_conversions) {
105 -
              Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
106 -
              return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, { 
107 -
                  box<P>(std::forward<P>(param))...
108 -
                  }, &state
109 -
                  );
110 -
            } else {
111 -
              return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, { 
112 -
                  box<P>(std::forward<P>(param))...
113 -
                  }, nullptr
114 -
                  );
115 -
            }
116 -
117 -
          }
118 -
119 -
          template<typename P, typename Q>
120 -
          static auto box(Q&& q) -> typename std::enable_if<std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
121 -
          {
122 -
            return Boxed_Value(std::ref(std::forward<Q>(q)));
123 -
          }
124 -
125 -
          template<typename P, typename Q>
126 -
          static auto box(Q&& q) -> typename std::enable_if<!std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
127 -
          {
128 -
            return Boxed_Value(std::forward<Q>(q));
129 -
          }
130 -
131 -
          template<typename P>
132 -
          static Boxed_Value box(Boxed_Value bv)
133 -
          {
134 -
            return bv;
135 -
          }
136 -
137 -
138 -
          std::vector<Const_Proxy_Function> m_funcs;
139 -
          const Type_Conversions *m_conversions;
140 -
        };
25 +
namespace chaiscript::dispatch::detail {
26 +
  /// used internally for unwrapping a function call's types
27 +
  template<typename Ret, typename... Param>
28 +
  struct Build_Function_Caller_Helper {
29 +
    Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions *t_conversions)
30 +
        : m_funcs(std::move(t_funcs))
31 +
        , m_conversions(t_conversions) {
32 +
    }
141 33
34 +
    Ret call(const chaiscript::Function_Params &params, const Type_Conversions_State &t_state) {
35 +
      if constexpr (std::is_arithmetic_v<Ret> && !std::is_same_v<std::remove_cv_t<std::remove_reference_t<Ret>>, bool>) {
36 +
        return Boxed_Number(dispatch::dispatch(m_funcs, params, t_state)).get_as<Ret>();
37 +
      } else if constexpr (std::is_same_v<void, Ret>) {
38 +
        dispatch::dispatch(m_funcs, params, t_state);
39 +
      } else {
40 +
        return boxed_cast<Ret>(dispatch::dispatch(m_funcs, params, t_state), &t_state);
41 +
      }
42 +
    }
142 43
44 +
    template<typename... P>
45 +
    Ret operator()(P &&...param) {
46 +
      std::array<Boxed_Value, sizeof...(P)> params{box<P>(std::forward<P>(param))...};
47 +
48 +
      if (m_conversions) {
49 +
        Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
50 +
        return call(chaiscript::Function_Params{params}, state);
51 +
      } else {
52 +
        Type_Conversions conv;
53 +
        Type_Conversions_State state(conv, conv.conversion_saves());
54 +
        return call(chaiscript::Function_Params{params}, state);
55 +
      }
56 +
    }
143 57
144 -
      /// \todo what happens if t_conversions is deleted out from under us?!
145 -
      template<typename Ret, typename ... Params>
146 -
        std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
147 -
        {
148 -
          /*
149 -
          if (funcs.size() == 1)
150 -
          {
151 -
            std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi = 
152 -
              std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
153 -
                (funcs[0]);
58 +
    template<typename P, typename Q>
59 +
    static Boxed_Value box(Q &&q) {
60 +
      if constexpr (std::is_same_v<chaiscript::Boxed_Value, std::decay_t<Q>>) {
61 +
        return std::forward<Q>(q);
62 +
      } else if constexpr (std::is_reference_v<P>) {
63 +
        return Boxed_Value(std::ref(std::forward<Q>(q)));
64 +
      } else {
65 +
        return Boxed_Value(std::forward<Q>(q));
66 +
      }
67 +
    }
154 68
155 -
            if (pfi)
156 -
            {
157 -
              return pfi->internal_function();
158 -
            } 
159 -
            // looks like this either wasn't a Proxy_Function_Impl or the types didn't match
160 -
            // we cannot make any other guesses or assumptions really, so continuing
161 -
          }
162 -
*/
69 +
    std::vector<Const_Proxy_Function> m_funcs;
70 +
    const Type_Conversions *m_conversions;
71 +
  };
163 72
164 -
          return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?t_conversions->get():nullptr));
165 -
        }
73 +
  /// \todo what happens if t_conversions is deleted out from under us?!
74 +
  template<typename Ret, typename... Params>
75 +
  std::function<Ret(Params...)>
76 +
  build_function_caller_helper(Ret(Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions) {
77 +
    /*
78 +
    if (funcs.size() == 1)
79 +
    {
80 +
      std::shared_ptr<const Proxy_Function_Impl<Ret (Params...)>> pfi =
81 +
        std::dynamic_pointer_cast<const Proxy_Function_Impl<Ret (Params...)> >
82 +
          (funcs[0]);
83 +
84 +
      if (pfi)
85 +
      {
86 +
        return pfi->internal_function();
87 +
      }
88 +
      // looks like this either wasn't a Proxy_Function_Impl or the types didn't match
89 +
      // we cannot make any other guesses or assumptions really, so continuing
166 90
    }
91 +
  */
92 +
93 +
    return std::function<Ret(Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions ? t_conversions->get() : nullptr));
167 94
  }
168 -
}
95 +
} // namespace chaiscript::dispatch::detail
169 96
170 97
#endif
171 -

@@ -1,13 +1,12 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8 8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9 9
10 -
11 10
#ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_
12 11
#define CHAISCRIPT_DYNAMIC_OBJECT_HPP_
13 12
@@ -18,21 +17,17 @@
Loading
18 17
#include "boxed_value.hpp"
19 18
20 19
namespace chaiscript {
21 -
class Type_Conversions;
22 -
namespace dispatch {
23 -
class Proxy_Function_Base;
24 -
}  // namespace dispatch
25 -
}  // namespace chaiscript
26 -
27 -
namespace chaiscript
28 -
{
29 -
  namespace dispatch
30 -
  {
20 +
  class Type_Conversions;
21 +
  namespace dispatch {
22 +
    class Proxy_Function_Base;
23 +
  } // namespace dispatch
24 +
} // namespace chaiscript
25 +
26 +
namespace chaiscript {
27 +
  namespace dispatch {
31 28
    struct option_explicit_set : std::runtime_error {
32 29
      explicit option_explicit_set(const std::string &t_param_name)
33 -
        : std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist")
34 -
      {
35 -
30 +
          : std::runtime_error("option explicit set and parameter '" + t_param_name + "' does not exist") {
36 31
      }
37 32
38 33
      option_explicit_set(const option_explicit_set &) = default;
@@ -40,92 +35,64 @@
Loading
40 35
      ~option_explicit_set() noexcept override = default;
41 36
    };
42 37
43 -
    class Dynamic_Object
44 -
    {
45 -
      public:
46 -
        explicit Dynamic_Object(std::string t_type_name)
47 -
          : m_type_name(std::move(t_type_name)), m_option_explicit(false)
48 -
        {
49 -
        }
50 -
51 -
        Dynamic_Object() = default;
38 +
    class Dynamic_Object {
39 +
    public:
40 +
      explicit Dynamic_Object(std::string t_type_name)
41 +
          : m_type_name(std::move(t_type_name))
42 +
          , m_option_explicit(false) {
43 +
      }
52 44
53 -
        bool is_explicit() const
54 -
        {
55 -
          return m_option_explicit;
56 -
        }
45 +
      Dynamic_Object() = default;
57 46
58 -
        void set_explicit(const bool t_explicit)
59 -
        {
60 -
          m_option_explicit = t_explicit;
61 -
        }
47 +
      bool is_explicit() const noexcept { return m_option_explicit; }
62 48
63 -
        std::string get_type_name() const
64 -
        {
65 -
          return m_type_name;
66 -
        }
49 +
      void set_explicit(const bool t_explicit) noexcept { m_option_explicit = t_explicit; }
67 50
68 -
        const Boxed_Value &operator[](const std::string &t_attr_name) const
69 -
        {
70 -
          return get_attr(t_attr_name);
71 -
        }
51 +
      const std::string &get_type_name() const noexcept { return m_type_name; }
72 52
73 -
        Boxed_Value &operator[](const std::string &t_attr_name)
74 -
        {
75 -
          return get_attr(t_attr_name);
76 -
        }
53 +
      const Boxed_Value &operator[](const std::string &t_attr_name) const { return get_attr(t_attr_name); }
77 54
78 -
        const Boxed_Value &get_attr(const std::string &t_attr_name) const
79 -
        {
80 -
          auto a = m_attrs.find(t_attr_name);
55 +
      Boxed_Value &operator[](const std::string &t_attr_name) { return get_attr(t_attr_name); }
81 56
82 -
          if (a != m_attrs.end()) {
83 -
            return a->second;
84 -
          } else {
85 -
            throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
86 -
          }
87 -
        }
57 +
      const Boxed_Value &get_attr(const std::string &t_attr_name) const {
58 +
        auto a = m_attrs.find(t_attr_name);
88 59
89 -
        bool has_attr(const std::string &t_attr_name) const {
90 -
          return m_attrs.find(t_attr_name) != m_attrs.end();
60 +
        if (a != m_attrs.end()) {
61 +
          return a->second;
62 +
        } else {
63 +
          throw std::range_error("Attr not found '" + t_attr_name + "' and cannot be added to const obj");
91 64
        }
65 +
      }
92 66
93 -
        Boxed_Value &get_attr(const std::string &t_attr_name)
94 -
        {
95 -
          return m_attrs[t_attr_name];
96 -
        }
67 +
      bool has_attr(const std::string &t_attr_name) const { return m_attrs.find(t_attr_name) != m_attrs.end(); }
97 68
98 -
        Boxed_Value &method_missing(const std::string &t_method_name)
99 -
        {
100 -
          if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
101 -
            throw option_explicit_set(t_method_name);
102 -
          }
69 +
      Boxed_Value &get_attr(const std::string &t_attr_name) { return m_attrs[t_attr_name]; }
103 70
104 -
          return get_attr(t_method_name);
71 +
      Boxed_Value &method_missing(const std::string &t_method_name) {
72 +
        if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
73 +
          throw option_explicit_set(t_method_name);
105 74
        }
106 75
107 -
        const Boxed_Value &method_missing(const std::string &t_method_name) const
108 -
        {
109 -
          if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
110 -
            throw option_explicit_set(t_method_name);
111 -
          }
76 +
        return get_attr(t_method_name);
77 +
      }
112 78
113 -
          return get_attr(t_method_name);
79 +
      const Boxed_Value &method_missing(const std::string &t_method_name) const {
80 +
        if (m_option_explicit && m_attrs.find(t_method_name) == m_attrs.end()) {
81 +
          throw option_explicit_set(t_method_name);
114 82
        }
115 83
116 -
        std::map<std::string, Boxed_Value> get_attrs() const
117 -
        {
118 -
          return m_attrs;
119 -
        }
84 +
        return get_attr(t_method_name);
85 +
      }
120 86
121 -
      private:
122 -
        const std::string m_type_name = "";
123 -
        bool m_option_explicit = false;
87 +
      std::map<std::string, Boxed_Value> get_attrs() const { return m_attrs; }
124 88
125 -
        std::map<std::string, Boxed_Value> m_attrs;
89 +
    private:
90 +
      const std::string m_type_name = "";
91 +
      bool m_option_explicit = false;
92 +
93 +
      std::map<std::string, Boxed_Value> m_attrs;
126 94
    };
127 95
128 -
  }
129 -
}
96 +
  } // namespace dispatch
97 +
} // namespace chaiscript
130 98
#endif
131 -

@@ -0,0 +1,94 @@
Loading
1 +
// This file is distributed under the BSD License.
2 +
// See "license.txt" for details.
3 +
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 +
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
5 +
// http://www.chaiscript.com
6 +
7 +
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
8 +
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
9 +
10 +
#include "../chaiscript_defines.hpp"
11 +
#include <cstdint>
12 +
13 +
namespace chaiscript {
14 +
  namespace utility {
15 +
    namespace fnv1a {
16 +
      template<typename Itr>
17 +
      static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
18 +
#ifdef __GNUC__
19 +
#pragma GCC diagnostic push
20 +
#pragma GCC diagnostic ignored "-Wsign-conversion"
21 +
#endif
22 +
23 +
#ifdef CHAISCRIPT_MSVC
24 +
#pragma warning(push)
25 +
#pragma warning(disable : 4307)
26 +
#endif
27 +
        std::uint32_t h = 0x811c9dc5;
28 +
29 +
        while (begin != end) {
30 +
          h = (h ^ (*begin)) * 0x01000193;
31 +
          ++begin;
32 +
        }
33 +
        return h;
34 +
35 +
#ifdef CHAISCRIPT_MSVC
36 +
#pragma warning(pop)
37 +
#endif
38 +
39 +
#ifdef __GNUC__
40 +
#pragma GCC diagnostic pop
41 +
#endif
42 +
      }
43 +
44 +
      template<size_t N>
45 +
      static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
46 +
        return hash(std::begin(str), std::end(str) - 1);
47 +
      }
48 +
49 +
      static constexpr std::uint32_t hash(std::string_view sv) noexcept {
50 +
        return hash(sv.begin(), sv.end());
51 +
      }
52 +
53 +
      static inline std::uint32_t hash(const std::string &s) noexcept {
54 +
        return hash(s.begin(), s.end());
55 +
      }
56 +
    } // namespace fnv1a
57 +
58 +
    namespace jenkins_one_at_a_time {
59 +
      template<typename Itr>
60 +
      static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
61 +
        std::uint32_t hash = 0;
62 +
63 +
        while (begin != end) {
64 +
          hash += std::uint32_t(*begin);
65 +
          hash += hash << 10;
66 +
          hash ^= hash >> 6;
67 +
          ++begin;
68 +
        }
69 +
70 +
        hash += hash << 3;
71 +
        hash ^= hash >> 11;
72 +
        hash += hash << 15;
73 +
        return hash;
74 +
      }
75 +
76 +
      template<size_t N>
77 +
      static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
78 +
        return hash(std::begin(str), std::end(str) - 1);
79 +
      }
80 +
81 +
      static constexpr std::uint32_t hash(std::string_view sv) noexcept {
82 +
        return hash(sv.begin(), sv.end());
83 +
      }
84 +
85 +
      static inline std::uint32_t hash(const std::string &s) noexcept {
86 +
        return hash(s.begin(), s.end());
87 +
      }
88 +
    } // namespace jenkins_one_at_a_time
89 +
90 +
    using fnv1a::hash;
91 +
  } // namespace utility
92 +
} // namespace chaiscript
93 +
94 +
#endif

@@ -1,7 +1,7 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
#ifndef CHAISCRIPT_OPTIMIZER_HPP_
@@ -9,76 +9,68 @@
Loading
9 9
10 10
#include "chaiscript_eval.hpp"
11 11
12 -
13 12
namespace chaiscript {
14 13
  namespace optimizer {
15 -
16 -
    template<typename ... T>
17 -
      struct Optimizer : T...
18 -
    {
14 +
    template<typename... T>
15 +
    struct Optimizer : T... {
19 16
      Optimizer() = default;
20 -
      explicit Optimizer(T ... t)
21 -
        : T(std::move(t))...
22 -
      {
17 +
      explicit Optimizer(T... t)
18 +
          : T(std::move(t))... {
23 19
      }
24 20
25 21
      template<typename Tracer>
26 22
      auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
27 -
        (void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(std::move(p)), 0)... };
23 +
        ((p = static_cast<T &>(*this).optimize(std::move(p))), ...);
28 24
        return p;
29 25
      }
30 26
    };
31 27
32 28
    template<typename T>
33 -
      eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) {
34 -
        if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
35 -
          return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
36 -
        } else {
37 -
          return *node.children[offset];
38 -
        }
29 +
    eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
30 +
      if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
31 +
        return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
32 +
      } else {
33 +
        return *node.children[offset];
39 34
      }
35 +
    }
40 36
41 37
    template<typename T>
42 -
      const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) {
43 -
        if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
44 -
          return *(dynamic_cast<const eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
45 -
        } else {
46 -
          return *node.children[offset];
47 -
        }
48 -
49 -
50 -
        /*
51 -
        if (node->identifier == AST_Node_Type::Compiled) {
52 -
          return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
53 -
        } else {
54 -
          return node->children[offset];
55 -
        }
56 -
        */
38 +
    const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
39 +
      if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
40 +
        return *(dynamic_cast<const eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
41 +
      } else {
42 +
        return *node.children[offset];
57 43
      }
58 44
45 +
      /*
46 +
    if (node->identifier == AST_Node_Type::Compiled) {
47 +
      return dynamic_cast<const eval::Compiled_AST_Node<T>&>(*node).m_original_node->children[offset];
48 +
    } else {
49 +
      return node->children[offset];
50 +
    }
51 +
    */
52 +
    }
53 +
59 54
    template<typename T>
60 -
      auto child_count(const eval::AST_Node_Impl<T> &node) {
61 -
        if (node.identifier == AST_Node_Type::Compiled) {
62 -
          return dynamic_cast<const eval::Compiled_AST_Node<T>&>(node).m_original_node->children.size();
63 -
        } else {
64 -
          return node.children.size();
65 -
        }
55 +
    auto child_count(const eval::AST_Node_Impl<T> &node) noexcept {
56 +
      if (node.identifier == AST_Node_Type::Compiled) {
57 +
        return dynamic_cast<const eval::Compiled_AST_Node<T> &>(node).m_original_node->children.size();
58 +
      } else {
59 +
        return node.children.size();
66 60
      }
61 +
    }
67 62
68 63
    template<typename T, typename Callable>
69 -
      auto make_compiled_node(eval::AST_Node_Impl_Ptr<T> original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable)
70 -
      {
71 -
        return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node), std::move(children), std::move(callable));
72 -
      }
73 -
64 +
    auto make_compiled_node(eval::AST_Node_Impl_Ptr<T> original_node, std::vector<eval::AST_Node_Impl_Ptr<T>> children, Callable callable) {
65 +
      return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Compiled_AST_Node<T>>(std::move(original_node),
66 +
                                                                                         std::move(children),
67 +
                                                                                         std::move(callable));
68 +
    }
74 69
75 70
    struct Return {
76 71
      template<typename T>
77 -
      auto optimize(eval::AST_Node_Impl_Ptr<T> p)
78 -
      {
79 -
        if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda)
80 -
            && !p->children.empty())
81 -
        {
72 +
      auto optimize(eval::AST_Node_Impl_Ptr<T> p) {
73 +
        if ((p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda) && !p->children.empty()) {
82 74
          auto &last_child = p->children.back();
83 75
          if (last_child->identifier == AST_Node_Type::Block) {
84 76
            auto &block_last_child = last_child->children.back();
@@ -95,9 +87,9 @@
Loading
95 87
    };
96 88
97 89
    template<typename T>
98 -
    bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node)
99 -
    {
100 -
      if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl || node.identifier == AST_Node_Type::Reference) {
90 +
    bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node) noexcept {
91 +
      if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl
92 +
          || node.identifier == AST_Node_Type::Reference) {
101 93
        return true;
102 94
      }
103 95
@@ -105,10 +97,8 @@
Loading
105 97
106 98
      for (size_t i = 0; i < num; ++i) {
107 99
        const auto &child = child_at(node, i);
108 -
        if (child.identifier != AST_Node_Type::Block
109 -
            && child.identifier != AST_Node_Type::For
110 -
            && child.identifier != AST_Node_Type::Ranged_For
111 -
            && contains_var_decl_in_scope(child)) {
100 +
        if (child.identifier != AST_Node_Type::Block && child.identifier != AST_Node_Type::For
101 +
            && child.identifier != AST_Node_Type::Ranged_For && contains_var_decl_in_scope(child)) {
112 102
          return true;
113 103
        }
114 104
      }
@@ -119,15 +109,14 @@
Loading
119 109
    struct Block {
120 110
      template<typename T>
121 111
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
122 -
        if (node->identifier == AST_Node_Type::Block)
123 -
        {
124 -
          if (!contains_var_decl_in_scope(*node))
125 -
          {
112 +
        if (node->identifier == AST_Node_Type::Block) {
113 +
          if (!contains_var_decl_in_scope(*node)) {
126 114
            if (node->children.size() == 1) {
127 115
              return std::move(node->children[0]);
128 116
            } else {
129 -
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text, node->location, 
130 -
                  std::move(node->children));
117 +
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Scopeless_Block_AST_Node<T>>(node->text,
118 +
                                                                                                        node->location,
119 +
                                                                                                        std::move(node->children));
131 120
            }
132 121
          }
133 122
        }
@@ -138,105 +127,91 @@
Loading
138 127
139 128
    struct Dead_Code {
140 129
      template<typename T>
141 -
        auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
142 -
          if (node->identifier == AST_Node_Type::Block)
143 -
          {
144 -
            std::vector<size_t> keepers;
145 -
            const auto num_children = node->children.size();
146 -
            keepers.reserve(num_children);
147 -
148 -
            for (size_t i = 0; i < num_children; ++i) {
149 -
              const auto &child = *node->children[i];
150 -
              if ( (child.identifier != AST_Node_Type::Id
151 -
                    && child.identifier != AST_Node_Type::Constant
152 -
                    && child.identifier != AST_Node_Type::Noop)
153 -
                  || i == num_children - 1) {
154 -
                keepers.push_back(i);
155 -
              }
130 +
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
131 +
        if (node->identifier == AST_Node_Type::Block) {
132 +
          std::vector<size_t> keepers;
133 +
          const auto num_children = node->children.size();
134 +
          keepers.reserve(num_children);
135 +
136 +
          for (size_t i = 0; i < num_children; ++i) {
137 +
            const auto &child = *node->children[i];
138 +
            if ((child.identifier != AST_Node_Type::Id && child.identifier != AST_Node_Type::Constant
139 +
                 && child.identifier != AST_Node_Type::Noop)
140 +
                || i == num_children - 1) {
141 +
              keepers.push_back(i);
156 142
            }
143 +
          }
157 144
158 -
            if (keepers.size() == num_children) {
159 -
              return node;
160 -
            } else {
161 -
              const auto new_children = [&](){
162 -
                std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
163 -
                for (const auto x : keepers)
164 -
                {
165 -
                  retval.push_back(std::move(node->children[x]));
166 -
                }
167 -
                return retval;
168 -
              };
169 -
170 -
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children());
171 -
            }
172 -
          } else {
145 +
          if (keepers.size() == num_children) {
173 146
            return node;
147 +
          } else {
148 +
            const auto new_children = [&]() {
149 +
              std::vector<eval::AST_Node_Impl_Ptr<T>> retval;
150 +
              for (const auto x : keepers) {
151 +
                retval.push_back(std::move(node->children[x]));
152 +
              }
153 +
              return retval;
154 +
            };
155 +
156 +
            return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Block_AST_Node<T>>(node->text, node->location, new_children());
174 157
          }
158 +
        } else {
159 +
          return node;
175 160
        }
161 +
      }
176 162
    };
177 163
178 164
    struct Unused_Return {
179 165
      template<typename T>
180 -
        auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
181 -
          if ((node->identifier == AST_Node_Type::Block
182 -
              || node->identifier == AST_Node_Type::Scopeless_Block)
183 -
              && !node->children.empty())
184 -
          {
185 -
            for (size_t i = 0; i < node->children.size()-1; ++i) {
186 -
              auto child = node->children[i].get();
187 -
              if (child->identifier == AST_Node_Type::Fun_Call) {
188 -
                node->children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text, child->location, 
189 -
                    std::move(child->children));
190 -
              }
166 +
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
167 +
        if ((node->identifier == AST_Node_Type::Block || node->identifier == AST_Node_Type::Scopeless_Block) && !node->children.empty()) {
168 +
          for (size_t i = 0; i < node->children.size() - 1; ++i) {
169 +
            auto child = node->children[i].get();
170 +
            if (child->identifier == AST_Node_Type::Fun_Call) {
171 +
              node->children[i]
172 +
                  = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(child->text,
173 +
                                                                                                              child->location,
174 +
                                                                                                              std::move(child->children));
191 175
            }
192 -
          } else if ((node->identifier == AST_Node_Type::For
193 -
                      || node->identifier == AST_Node_Type::While)
194 -
                     && child_count(*node) > 0) {
195 -
            auto &child = child_at(*node, child_count(*node) - 1);
196 -
            if (child.identifier == AST_Node_Type::Block
197 -
                || child.identifier == AST_Node_Type::Scopeless_Block)
198 -
            {
199 -
              auto num_sub_children = child_count(child);
200 -
              for (size_t i = 0; i < num_sub_children; ++i) {
201 -
                auto &sub_child = child_at(child, i);
202 -
                if (sub_child.identifier == AST_Node_Type::Fun_Call) {
203 -
                  child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(sub_child.text, sub_child.location, std::move(sub_child.children));
204 -
                }
176 +
          }
177 +
        } else if ((node->identifier == AST_Node_Type::For || node->identifier == AST_Node_Type::While) && child_count(*node) > 0) {
178 +
          auto &child = child_at(*node, child_count(*node) - 1);
179 +
          if (child.identifier == AST_Node_Type::Block || child.identifier == AST_Node_Type::Scopeless_Block) {
180 +
            auto num_sub_children = child_count(child);
181 +
            for (size_t i = 0; i < num_sub_children; ++i) {
182 +
              auto &sub_child = child_at(child, i);
183 +
              if (sub_child.identifier == AST_Node_Type::Fun_Call) {
184 +
                child.children[i] = chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Unused_Return_Fun_Call_AST_Node<T>>(
185 +
                    sub_child.text, sub_child.location, std::move(sub_child.children));
205 186
              }
206 187
            }
207 188
          }
208 -
          return node;
209 189
        }
190 +
        return node;
191 +
      }
210 192
    };
211 193
212 194
    struct Assign_Decl {
213 195
      template<typename T>
214 196
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
215 -
        if ((node->identifier == AST_Node_Type::Equation)
216 -
             && node->text == "="
217 -
             && node->children.size() == 2
218 -
             && node->children[0]->identifier == AST_Node_Type::Var_Decl
219 -
           )
220 -
        {
197 +
        if ((node->identifier == AST_Node_Type::Equation) && node->text == "=" && node->children.size() == 2
198 +
            && node->children[0]->identifier == AST_Node_Type::Var_Decl) {
221 199
          std::vector<eval::AST_Node_Impl_Ptr<T>> new_children;
222 200
          new_children.push_back(std::move(node->children[0]->children[0]));
223 201
          new_children.push_back(std::move(node->children[1]));
224 -
          return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Assign_Decl_AST_Node<T>>(node->text, 
225 -
              node->location, std::move(new_children) );
202 +
          return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Assign_Decl_AST_Node<T>>(node->text,
203 +
                                                                                                node->location,
204 +
                                                                                                std::move(new_children));
226 205
        }
227 206
228 207
        return node;
229 208
      }
230 209
    };
231 210
232 -
233 211
    struct If {
234 212
      template<typename T>
235 213
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
236 -
        if ((node->identifier == AST_Node_Type::If)
237 -
             && node->children.size() >= 2
238 -
             && node->children[0]->identifier == AST_Node_Type::Constant)
239 -
        {
214 +
        if ((node->identifier == AST_Node_Type::If) && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) {
240 215
          const auto condition = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[0].get())->m_value;
241 216
          if (condition.get_type_info().bare_equal_type_info(typeid(bool))) {
242 217
            if (boxed_cast<bool>(condition)) {
@@ -254,25 +229,21 @@
Loading
254 229
    struct Partial_Fold {
255 230
      template<typename T>
256 231
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
257 -
258 232
        // Fold right side
259 -
        if (node->identifier == AST_Node_Type::Binary
260 -
            && node->children.size() == 2
261 -
            && node->children[0]->identifier != AST_Node_Type::Constant
262 -
            && node->children[1]->identifier == AST_Node_Type::Constant)
263 -
        {
233 +
        if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2
234 +
            && node->children[0]->identifier != AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) {
264 235
          try {
265 236
            const auto &oper = node->text;
266 237
            const auto parsed = Operators::to_operator(oper);
267 238
            if (parsed != Operators::Opers::invalid) {
268 239
              const auto rhs = dynamic_cast<eval::Constant_AST_Node<T> *>(node->children[1].get())->m_value;
269 240
              if (rhs.get_type_info().is_arithmetic()) {
270 -
                return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(node->text, node->location, 
271 -
                    std::move(node->children), rhs);
241 +
                return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Fold_Right_Binary_Operator_AST_Node<T>>(
242 +
                    node->text, node->location, std::move(node->children), rhs);
272 243
              }
273 244
            }
274 245
          } catch (const std::exception &) {
275 -
            //failure to fold, that's OK
246 +
            // failure to fold, that's OK
276 247
          }
277 248
        }
278 249
@@ -283,11 +254,7 @@
Loading
283 254
    struct Constant_Fold {
284 255
      template<typename T>
285 256
      auto optimize(eval::AST_Node_Impl_Ptr<T> node) {
286 -
287 -
        if (node->identifier == AST_Node_Type::Prefix
288 -
            && node->children.size() == 1
289 -
            && node->children[0]->identifier == AST_Node_Type::Constant)
290 -
        {
257 +
        if (node->identifier == AST_Node_Type::Prefix && node->children.size() == 1 && node->children[0]->identifier == AST_Node_Type::Constant) {
291 258
          try {
292 259
            const auto &oper = node->text;
293 260
            const auto parsed = Operators::to_operator(oper, true);
@@ -295,39 +262,43 @@
Loading
295 262
            const auto match = oper + node->children[0]->text;
296 263
297 264
            if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) {
298 -
              const auto val  = Boxed_Number::do_oper(parsed, lhs);
299 -
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
265 +
              const auto val = Boxed_Number::do_oper(parsed, lhs);
266 +
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
267 +
                                                                                                 node->location,
268 +
                                                                                                 std::move(val));
300 269
            } else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") {
301 -
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, Boxed_Value(!boxed_cast<bool>(lhs)));
270 +
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
271 +
                                                                                                 node->location,
272 +
                                                                                                 Boxed_Value(!boxed_cast<bool>(lhs)));
302 273
            }
303 274
          } catch (const std::exception &) {
304 -
            //failure to fold, that's OK
275 +
            // failure to fold, that's OK
305 276
          }
306 277
        } else if ((node->identifier == AST_Node_Type::Logical_And || node->identifier == AST_Node_Type::Logical_Or)
307 -
            && node->children.size() == 2
308 -
            && node->children[0]->identifier == AST_Node_Type::Constant
309 -
            && node->children[1]->identifier == AST_Node_Type::Constant)
310 -
        {
278 +
                   && node->children.size() == 2 && node->children[0]->identifier == AST_Node_Type::Constant
279 +
                   && node->children[1]->identifier == AST_Node_Type::Constant) {
311 280
          try {
312 281
            const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
313 282
            const auto rhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]).m_value;
314 283
            if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) {
315 284
              const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text;
316 285
              const auto val = [lhs_val = boxed_cast<bool>(lhs), rhs_val = boxed_cast<bool>(rhs), id = node->identifier] {
317 -
                if (id == AST_Node_Type::Logical_And) { return Boxed_Value(lhs_val && rhs_val); }
318 -
                else { return Boxed_Value(lhs_val || rhs_val); }
286 +
                if (id == AST_Node_Type::Logical_And) {
287 +
                  return Boxed_Value(lhs_val && rhs_val);
288 +
                } else {
289 +
                  return Boxed_Value(lhs_val || rhs_val);
290 +
                }
319 291
              }();
320 292
321 -
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
293 +
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
294 +
                                                                                                 node->location,
295 +
                                                                                                 std::move(val));
322 296
            }
323 297
          } catch (const std::exception &) {
324 -
            //failure to fold, that's OK
298 +
            // failure to fold, that's OK
325 299
          }
326 -
        } else if (node->identifier == AST_Node_Type::Binary
327 -
            && node->children.size() == 2
328 -
            && node->children[0]->identifier == AST_Node_Type::Constant
329 -
            && node->children[1]->identifier == AST_Node_Type::Constant)
330 -
        {
300 +
        } else if (node->identifier == AST_Node_Type::Binary && node->children.size() == 2
301 +
                   && node->children[0]->identifier == AST_Node_Type::Constant && node->children[1]->identifier == AST_Node_Type::Constant) {
331 302
          try {
332 303
            const auto &oper = node->text;
333 304
            const auto parsed = Operators::to_operator(oper);
@@ -335,28 +306,28 @@
Loading
335 306
              const auto lhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[0]).m_value;
336 307
              const auto rhs = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]).m_value;
337 308
              if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) {
338 -
                const auto val  = Boxed_Number::do_oper(parsed, lhs, rhs);
309 +
                const auto val = Boxed_Number::do_oper(parsed, lhs, rhs);
339 310
                const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text;
340 -
                return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, std::move(val));
311 +
                return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
312 +
                                                                                                   node->location,
313 +
                                                                                                   std::move(val));
341 314
              }
342 315
            }
343 316
          } catch (const std::exception &) {
344 -
            //failure to fold, that's OK
317 +
            // failure to fold, that's OK
345 318
          }
346 -
        } else if (node->identifier == AST_Node_Type::Fun_Call
347 -
                   && node->children.size() == 2
348 -
                   && node->children[0]->identifier == AST_Node_Type::Id
349 -
                   && node->children[1]->identifier == AST_Node_Type::Arg_List
350 -
                   && node->children[1]->children.size() == 1
351 -
                   && node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
352 -
319 +
        } else if (node->identifier == AST_Node_Type::Fun_Call && node->children.size() == 2
320 +
                   && node->children[0]->identifier == AST_Node_Type::Id && node->children[1]->identifier == AST_Node_Type::Arg_List
321 +
                   && node->children[1]->children.size() == 1 && node->children[1]->children[0]->identifier == AST_Node_Type::Constant) {
353 322
          const auto arg = dynamic_cast<const eval::Constant_AST_Node<T> &>(*node->children[1]->children[0]).m_value;
354 323
          if (arg.get_type_info().is_arithmetic()) {
355 324
            const auto &fun_name = node->children[0]->text;
356 325
357 -
            const auto make_constant = [&node, &fun_name](auto val){
326 +
            const auto make_constant = [&node, &fun_name](auto val) {
358 327
              const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")";
359 -
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match), node->location, const_var(val));
328 +
              return chaiscript::make_unique<eval::AST_Node_Impl<T>, eval::Constant_AST_Node<T>>(std::move(match),
329 +
                                                                                                 node->location,
330 +
                                                                                                 const_var(val));
360 331
            };
361 332
362 333
            if (fun_name == "double") {
@@ -370,10 +341,7 @@
Loading
370 341
            } else if (fun_name == "size_t") {
371 342
              return make_constant(Boxed_Number(arg).get_as<size_t>());
372 343
            }
373 -
374 -
375 344
          }
376 -
377 345
        }
378 346
379 347
        return node;
@@ -383,7 +351,6 @@
Loading
383 351
    struct For_Loop {
384 352
      template<typename T>
385 353
      auto optimize(eval::AST_Node_Impl_Ptr<T> for_node) {
386 -
387 354
        if (for_node->identifier != AST_Node_Type::For) {
388 355
          return for_node;
389 356
        }
@@ -392,66 +359,55 @@
Loading
392 359
        const auto &binary_node = child_at(*for_node, 1);
393 360
        const auto &prefix_node = child_at(*for_node, 2);
394 361
395 -
        if (child_count(*for_node) == 4
396 -
            && eq_node.identifier == AST_Node_Type::Assign_Decl
397 -
            && child_count(eq_node) == 2
398 -
            && child_at(eq_node, 0).identifier == AST_Node_Type::Id
399 -
            && child_at(eq_node, 1).identifier == AST_Node_Type::Constant
400 -
            && binary_node.identifier == AST_Node_Type::Binary
401 -
            && binary_node.text == "<"
402 -
            && child_count(binary_node) == 2
403 -
            && child_at(binary_node, 0).identifier == AST_Node_Type::Id
404 -
            && child_at(binary_node, 0).text == child_at(eq_node,0).text
405 -
            && child_at(binary_node, 1).identifier == AST_Node_Type::Constant
406 -
            && prefix_node.identifier == AST_Node_Type::Prefix
407 -
            && prefix_node.text == "++"
408 -
            && child_count(prefix_node) == 1
409 -
            && child_at(prefix_node, 0).identifier == AST_Node_Type::Id
410 -
            && child_at(prefix_node, 0).text == child_at(eq_node,0).text)
411 -
        {
362 +
        if (child_count(*for_node) == 4 && eq_node.identifier == AST_Node_Type::Assign_Decl && child_count(eq_node) == 2
363 +
            && child_at(eq_node, 0).identifier == AST_Node_Type::Id && child_at(eq_node, 1).identifier == AST_Node_Type::Constant
364 +
            && binary_node.identifier == AST_Node_Type::Binary && binary_node.text == "<" && child_count(binary_node) == 2
365 +
            && child_at(binary_node, 0).identifier == AST_Node_Type::Id && child_at(binary_node, 0).text == child_at(eq_node, 0).text
366 +
            && child_at(binary_node, 1).identifier == AST_Node_Type::Constant && prefix_node.identifier == AST_Node_Type::Prefix
367 +
            && prefix_node.text == "++" && child_count(prefix_node) == 1 && child_at(prefix_node, 0).identifier == AST_Node_Type::Id
368 +
            && child_at(prefix_node, 0).text == child_at(eq_node, 0).text) {
412 369
          const Boxed_Value &begin = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(eq_node, 1)).m_value;
413 370
          const Boxed_Value &end = dynamic_cast<const eval::Constant_AST_Node<T> &>(child_at(binary_node, 1)).m_value;
414 371
          const std::string &id = child_at(prefix_node, 0).text;
415 372
416 -
          if (begin.get_type_info().bare_equal(user_type<int>()) 
417 -
              && end.get_type_info().bare_equal(user_type<int>())) {
418 -
373 +
          if (begin.get_type_info().bare_equal(user_type<int>()) && end.get_type_info().bare_equal(user_type<int>())) {
419 374
            const auto start_int = boxed_cast<int>(begin);
420 375
            const auto end_int = boxed_cast<int>(end);
421 376
422 -
            // note that we are moving the last element out, then popping the empty shared_ptr 
377 +
            // note that we are moving the last element out, then popping the empty shared_ptr
423 378
            // from the vector
424 379
            std::vector<eval::AST_Node_Impl_Ptr<T>> body_vector;
425 380
            auto body_child = std::move(for_node->children[3]);
426 381
            for_node->children.pop_back();
427 382
            body_vector.emplace_back(std::move(body_child));
428 -
            
429 -
            return make_compiled_node(std::move(for_node), std::move(body_vector), 
430 -
                [id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children, const chaiscript::detail::Dispatch_State &t_ss) {
431 -
                  assert(children.size() == 1);
432 -
                  chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
433 -
434 -
                  int i = start_int;
435 -
                  t_ss.add_object(id, var(&i));
436 -
437 -
                  try {
438 -
                    for (; i < end_int; ++i) {
439 -
                      try {
440 -
                        // Body of Loop
441 -
                        children[0]->eval(t_ss);
442 -
                      } catch (eval::detail::Continue_Loop &) {
443 -
                        // we got a continue exception, which means all of the remaining 
444 -
                        // loop implementation is skipped and we just need to continue to
445 -
                        // the next iteration step
446 -
                      }
447 -
                    }
448 -
                  } catch (eval::detail::Break_Loop &) {
449 -
                    // loop broken
450 -
                  }
451 -
452 -
                  return void_var();
453 -
                }
454 -
            );
383 +
384 +
            return make_compiled_node(std::move(for_node),
385 +
                                      std::move(body_vector),
386 +
                                      [id, start_int, end_int](const std::vector<eval::AST_Node_Impl_Ptr<T>> &children,
387 +
                                                               const chaiscript::detail::Dispatch_State &t_ss) {
388 +
                                        assert(children.size() == 1);
389 +
                                        chaiscript::eval::detail::Scope_Push_Pop spp(t_ss);
390 +
391 +
                                        int i = start_int;
392 +
                                        t_ss.add_object(id, var(&i));
393 +
394 +
                                        try {
395 +
                                          for (; i < end_int; ++i) {
396 +
                                            try {
397 +
                                              // Body of Loop
398 +
                                              children[0]->eval(t_ss);
399 +
                                            } catch (eval::detail::Continue_Loop &) {
400 +
                                              // we got a continue exception, which means all of the remaining
401 +
                                              // loop implementation is skipped and we just need to continue to
402 +
                                              // the next iteration step
403 +
                                            }
404 +
                                          }
405 +
                                        } catch (eval::detail::Break_Loop &) {
406 +
                                          // loop broken
407 +
                                        }
408 +
409 +
                                        return void_var();
410 +
                                      });
455 411
          } else {
456 412
            return for_node;
457 413
          }
@@ -461,11 +417,17 @@
Loading
461 417
      }
462 418
    };
463 419
464 -
    typedef Optimizer<optimizer::Partial_Fold, optimizer::Unused_Return, optimizer::Constant_Fold, 
465 -
      optimizer::If, optimizer::Return, optimizer::Dead_Code, optimizer::Block, optimizer::For_Loop, optimizer::Assign_Decl> Optimizer_Default; 
466 -
467 -
  }
468 -
}
469 -
420 +
    using Optimizer_Default = Optimizer<optimizer::Partial_Fold,
421 +
                                        optimizer::Unused_Return,
422 +
                                        optimizer::Constant_Fold,
423 +
                                        optimizer::If,
424 +
                                        optimizer::Return,
425 +
                                        optimizer::Dead_Code,
426 +
                                        optimizer::Block,
427 +
                                        optimizer::For_Loop,
428 +
                                        optimizer::Assign_Decl>;
429 +
430 +
  } // namespace optimizer
431 +
} // namespace chaiscript
470 432
471 433
#endif

@@ -1,13 +1,12 @@
Loading
1 1
// This file is distributed under the BSD License.
2 2
// See "license.txt" for details.
3 3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4 -
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
4 +
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5 5
// http://www.chaiscript.com
6 6
7 7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8 8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9 9
10 -
11 10
#ifndef CHAISCRIPT_COMMON_HPP_
12 11
#define CHAISCRIPT_COMMON_HPP_
13 12
@@ -23,134 +22,172 @@
Loading
23 22
#include "../dispatchkit/dispatchkit.hpp"
24 23
#include "../dispatchkit/proxy_functions.hpp"
25 24
#include "../dispatchkit/type_info.hpp"
25 +
#include <unordered_set>
26 26
27 27
namespace chaiscript {
28 -
struct AST_Node;
29 -
}  // namespace chaiscript
28 +
  struct AST_Node;
29 +
} // namespace chaiscript
30 30
31 -
namespace chaiscript
32 -
{
31 +
namespace chaiscript {
33 32
  struct Name_Validator {
34 -
    static bool is_reserved_word(const std::string &name)
35 -
    {
36 -
      static const std::set<std::string> m_reserved_words 
37 -
        = {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto", 
38 -
          "return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_",
39 -
          "__LINE__", "__FILE__", "__FUNC__", "__CLASS__"};
40 -
      return m_reserved_words.count(name) > 0;
33 +
    template<typename T>
34 +
    static bool is_reserved_word(const T &s) noexcept {
35 +
      const static std::unordered_set<std::uint32_t>
36 +
          words{utility::hash("def"), utility::hash("fun"), utility::hash("while"), utility::hash("for"), utility::hash("if"), utility::hash("else"), utility::hash("&&"), utility::hash("||"), utility::hash(","), utility::hash("auto"), utility::hash("return"), utility::hash("break"), utility::hash("true"), utility::hash("false"), utility::hash("class"), utility::hash("attr"), utility::hash("var"), utility::hash("global"), utility::hash("GLOBAL"), utility::hash("_"), utility::hash("__LINE__"), utility::hash("__FILE__"), utility::hash("__FUNC__"), utility::hash("__CLASS__")};
37 +
38 +
      return words.count(utility::hash(s)) == 1;
41 39
    }
42 40
43 -
    static bool valid_object_name(const std::string &name)
44 -
    {
41 +
    template<typename T>
42 +
    static bool valid_object_name(const T &name) noexcept {
45 43
      return name.find("::") == std::string::npos && !is_reserved_word(name);
46 44
    }
47 45
48 -
    static void validate_object_name(const std::string &name)
49 -
    {
46 +
    template<typename T>
47 +
    static void validate_object_name(const T &name) {
50 48
      if (is_reserved_word(name)) {
51 -
        throw exception::reserved_word_error(name);
49 +
        throw exception::reserved_word_error(std::string(name));
52 50
      }
53 51
54 52
      if (name.find("::") != std::string::npos) {
55 -
        throw exception::illegal_name_error(name);
53 +
        throw exception::illegal_name_error(std::string(name));
56 54
      }
57 55
    }
58 56
  };
59 57
60 58
  /// Signature of module entry point that all binary loadable modules must implement.
61 -
  typedef ModulePtr (*Create_Module_Func)();
62 -
59 +
  using Create_Module_Func = ModulePtr (*)();
63 60
64 61
  /// Types of AST nodes available to the parser and eval
65 -
  enum class AST_Node_Type { Id, Fun_Call, Unused_Return_Fun_Call, Arg_List, Equation, Var_Decl, Assign_Decl,
66 -
    Array_Call, Dot_Access,
67 -
    Lambda, Block, Scopeless_Block, Def, While, If, For, Ranged_For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
68 -
    Inline_Range, Try, Catch, Finally, Method, Attr_Decl,  
69 -
    Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
62 +
  enum class AST_Node_Type {
63 +
    Id,
64 +
    Fun_Call,
65 +
    Unused_Return_Fun_Call,
66 +
    Arg_List,
67 +
    Equation,
68 +
    Var_Decl,
69 +
    Assign_Decl,
70 +
    Array_Call,
71 +
    Dot_Access,
72 +
    Lambda,
73 +
    Block,
74 +
    Scopeless_Block,
75 +
    Def,
76 +
    While,
77 +
    If,
78 +
    For,
79 +
    Ranged_For,
80 +
    Inline_Array,
81 +
    Inline_Map,
82 +
    Return,
83 +
    File,
84 +
    Prefix,
85 +
    Break,
86 +
    Continue,
87 +
    Map_Pair,
88 +
    Value_Range,
89 +
    Inline_Range,
90 +
    Try,
91 +
    Catch,
92 +
    Finally,
93 +
    Method,
94 +
    Attr_Decl,
95 +
    Logical_And,
96 +
    Logical_Or,
97 +
    Reference,
98 +
    Switch,
99 +
    Case,
100 +
    Default,
101 +
    Noop,
102 +
    Class,
103 +
    Binary,
104 +
    Arg,
105 +
    Global_Decl,
106 +
    Constant,
107 +
    Compiled
70 108
  };
71 109
72 -
  enum class Operator_Precidence { Ternary_Cond, Logical_Or, 
73 -
    Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And, 
74 -
    Equality, Comparison, Shift, Addition, Multiplication, Prefix };
110 +
  enum class Operator_Precedence {
111 +
    Ternary_Cond,
112 +
    Logical_Or,
113 +
    Logical_And,
114 +
    Bitwise_Or,
115 +
    Bitwise_Xor,
116 +
    Bitwise_And,
117 +
    Equality,
118 +
    Comparison,
119 +
    Shift,
120 +
    Addition,
121 +
    Multiplication,
122 +
    Prefix
123 +
  };
75 124
76 -
  namespace
77 -
  {
125 +
  namespace {
78 126
    /// Helper lookup to get the name of each node type
79 -
    inline const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
80 -
      static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl",
81 -
                                    "Array_Call", "Dot_Access", 
82 -
                                    "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
83 -
                                    "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
84 -
                                    "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
127 +
    constexpr const char *ast_node_type_to_string(AST_Node_Type ast_node_type) noexcept {
128 +
      constexpr const char *const ast_node_types[] = {"Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"};
85 129
86 130
      return ast_node_types[static_cast<int>(ast_node_type)];
87 131
    }
88 -
  }
132 +
  } // namespace
89 133
90 134
  /// \brief Convenience type for file positions
91 135
  struct File_Position {
92 -
    int line;
93 -
    int column;
136 +
    int line = 0;
137 +
    int column = 0;
94 138
95 -
    File_Position(int t_file_line, int t_file_column)
96 -
      : line(t_file_line), column(t_file_column) { }
139 +
    constexpr File_Position(int t_file_line, int t_file_column) noexcept
140 +
        : line(t_file_line)
141 +
        , column(t_file_column) {
142 +
    }
97 143
98 -
    File_Position() : line(0), column(0) { }
144 +
    constexpr File_Position() noexcept = default;
99 145
  };
100 146
101 147
  struct Parse_Location {
102 -
    Parse_Location(std::string t_fname="", const int t_start_line=0, const int t_start_col=0,
103 -
        const int t_end_line=0, const int t_end_col=0)
104 -
      : start(t_start_line, t_start_col), 
105 -
        end(t_end_line, t_end_col),
106 -
        filename(std::make_shared<std::string>(std::move(t_fname)))
107 -
    {
148 +
    Parse_Location(std::string t_fname = "", const int t_start_line = 0, const int t_start_col = 0, const int t_end_line = 0, const int t_end_col = 0)
149 +
        : start(t_start_line, t_start_col)
150 +
        , end(t_end_line, t_end_col)
151 +
        , filename(std::make_shared<std::string>(std::move(t_fname))) {
108 152
    }
109 153
110 -
    Parse_Location(std::shared_ptr<std::string> t_fname, const int t_start_line=0, const int t_start_col=0,
111 -
        const int t_end_line=0, const int t_end_col=0)
112 -
      : start(t_start_line, t_start_col), 
113 -
        end(t_end_line, t_end_col),
114 -
        filename(std::move(t_fname))
115 -
    {
154 +
    Parse_Location(std::shared_ptr<std::string> t_fname,
155 +
                   const int t_start_line = 0,
156 +
                   const int t_start_col = 0,
157 +
                   const int t_end_line = 0,
158 +
                   const int t_end_col = 0)
159 +
        : start(t_start_line, t_start_col)
160 +
        , end(t_end_line, t_end_col)
161 +
        , filename(std::move(t_fname)) {
116 162
    }
117 163
118 -
119 -
120 164
    File_Position start;
121 165
    File_Position end;
122 166
    std::shared_ptr<std::string> filename;
123 167
  };
124 168
125 -
126 169
  /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
127 -
  typedef std::unique_ptr<AST_Node> AST_NodePtr;
128 -
  typedef std::unique_ptr<const AST_Node> AST_NodePtr_Const;
170 +
  using AST_NodePtr = std::unique_ptr<AST_Node>;
171 +
  using AST_NodePtr_Const = std::unique_ptr<const AST_Node>;
129 172
130 173
  struct AST_Node_Trace;
131 174
132 -
133 175
  /// \brief Classes which may be thrown during error cases when ChaiScript is executing.
134 -
  namespace exception
135 -
  {
176 +
  namespace exception {
136 177
    /// \brief Thrown if an error occurs while attempting to load a binary module
137 -
    struct load_module_error : std::runtime_error
138 -
    {
139 -
      explicit load_module_error(const std::string &t_reason) noexcept
140 -
        : std::runtime_error(t_reason)
141 -
      {
178 +
    struct load_module_error : std::runtime_error {
179 +
      explicit load_module_error(const std::string &t_reason)
180 +
          : std::runtime_error(t_reason) {
142 181
      }
143 182
144 183
      load_module_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
145 -
        : std::runtime_error(format_error(t_name, t_errors))
146 -
      {
184 +
          : std::runtime_error(format_error(t_name, t_errors)) {
147 185
      }
148 186
149 187
      load_module_error(const load_module_error &) = default;
150 188
      ~load_module_error() noexcept override = default;
151 189
152 -
      static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors)
153 -
      {
190 +
      static std::string format_error(const std::string &t_name, const std::vector<load_module_error> &t_errors) {
154 191
        std::stringstream ss;
155 192
        ss << "Error loading module '" << t_name << "'\n"
156 193
           << "  The following locations were searched:\n";
@@ -163,7 +200,6 @@
Loading
163 200
      }
164 201
    };
165 202
166 -
167 203
    /// Errors generated during parsing or evaluation
168 204
    struct eval_error : std::runtime_error {
169 205
      std::string reason;
@@ -172,48 +208,55 @@
Loading
172 208
      std::string detail;
173 209
      std::vector<AST_Node_Trace> call_stack;
174 210
175 -
      eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
176 -
          const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
177 -
          bool t_dot_notation,
178 -
          const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
179 -
        std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)),
180 -
        reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss)) 
181 -
      {}
182 -
183 -
      eval_error(const std::string &t_why, 
184 -
           const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
185 -
           bool t_dot_notation,
186 -
           const chaiscript::detail::Dispatch_Engine &t_ss) noexcept :
187 -
        std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)),
188 -
        reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss))
189 -
      {}
211 +
      eval_error(const std::string &t_why,
212 +
                 const File_Position &t_where,
213 +
                 const std::string &t_fname,
214 +
                 const std::vector<Boxed_Value> &t_parameters,
215 +
                 const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
216 +
                 bool t_dot_notation,
217 +
                 const chaiscript::detail::Dispatch_Engine &t_ss) noexcept
218 +
          : std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss))
219 +
          , reason(t_why)
220 +
          , start_position(t_where)
221 +
          , filename(t_fname)
222 +
          , detail(format_detail(t_functions, t_dot_notation, t_ss)) {
223 +
      }
190 224
225 +
      eval_error(const std::string &t_why,
226 +
                 const std::vector<Boxed_Value> &t_parameters,
227 +
                 const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
228 +
                 bool t_dot_notation,
229 +
                 const chaiscript::detail::Dispatch_Engine &t_ss) noexcept
230 +
          : std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss))
231 +
          , reason(t_why)
232 +
          , detail(format_detail(t_functions, t_dot_notation, t_ss)) {
233 +
      }
191 234
192 -
      eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept :
193 -
        std::runtime_error(format(t_why, t_where, t_fname)),
194 -
        reason(t_why), start_position(t_where), filename(t_fname)
195 -
      {}
235 +
      eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept
236 +
          : std::runtime_error(format(t_why, t_where, t_fname))
237 +
          , reason(t_why)
238 +
          , start_position(t_where)
239 +
          , filename(t_fname) {
240 +
      }
196 241
197 242
      explicit eval_error(const std::string &t_why) noexcept
198 -
        : std::runtime_error("Error: \"" + t_why + "\" "),
199 -
        reason(t_why) 
200 -
      {}
243 +
          : std::runtime_error("Error: \"" + t_why + "\" ")
244 +
          , reason(t_why) {
245 +
      }
201 246
202 247
      eval_error(const eval_error &) = default;
203 248
204 -
      std::string pretty_print() const
205 -
      {
249 +
      std::string pretty_print() const {
206 250
        std::ostringstream ss;
207 251
208 252
        ss << what();
209 253
        if (!call_stack.empty()) {
210 254
          ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
211 -
          ss << '\n' << detail << '\n';
255 +
          ss << '\n'
256 +
             << detail << '\n';
212 257
          ss << "  " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
213 258
          for (size_t j = 1; j < call_stack.size(); ++j) {
214 -
            if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
215 -
                && id(call_stack[j]) != chaiscript::AST_Node_Type::File)
216 -
            {
259 +
            if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block && id(call_stack[j]) != chaiscript::AST_Node_Type::File) {
217 260
              ss << '\n';
218 261
              ss << "  from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
219 262
            }
@@ -226,52 +269,39 @@
Loading
226 269
      ~eval_error() noexcept override = default;
227 270
228 271
    private:
229 -
230 272
      template<typename T>
231 -
        static AST_Node_Type id(const T& t)
232 -
        {
233 -
          return t.identifier;
234 -
        }
273 +
      static AST_Node_Type id(const T &t) noexcept {
274 +
        return t.identifier;
275 +
      }
235 276
236 277
      template<typename T>
237 -
        static std::string pretty(const T& t)
238 -
        {
239 -
          return t.pretty_print();
240 -
        }
278 +
      static std::string pretty(const T &t) {
279 +
        return t.pretty_print();
280 +
      }
241 281
242 282
      template<typename T>
243 -
        static const std::string &fname(const T& t)
244 -
        {
245 -
          return t.filename();
246 -
        }
283 +
      static const std::string &fname(const T &t) noexcept {
284 +
        return t.filename();
285 +
      }
247 286
248 287
      template<typename T>
249 -
        static std::string startpos(const T& t)
250 -
        {
251 -
          std::ostringstream oss;
252 -
          oss << t.start().line << ", " << t.start().column;
253 -
          return oss.str();
254 -
        }
255 -
256 -
      static std::string format_why(const std::string &t_why)
257 -
      {
258 -
        return "Error: \"" + t_why + "\"";
288 +
      static std::string startpos(const T &t) {
289 +
        std::ostringstream oss;
290 +
        oss << t.start().line << ", " << t.start().column;
291 +
        return oss.str();
259 292
      }
260 293
261 -
      static std::string format_types(const Const_Proxy_Function &t_func,
262 -
          bool t_dot_notation,
263 -
          const chaiscript::detail::Dispatch_Engine &t_ss)
264 -
      {
294 +
      static std::string format_why(const std::string &t_why) { return "Error: \"" + t_why + "\""; }
295 +
296 +
      static std::string format_types(const Const_Proxy_Function &t_func, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss) {
265 297
        assert(t_func);
266 298
        int arity = t_func->get_arity();
267 299
        std::vector<Type_Info> types = t_func->get_param_types();
268 300
269 301
        std::string retval;
270 -
        if (arity == -1)
271 -
        {
302 +
        if (arity == -1) {
272 303
          retval = "(...)";
273 -
          if (t_dot_notation)
274 -
          {
304 +
          if (t_dot_notation) {
275 305
            retval = "(Object)." + retval;
276 306
          }
277 307
        } else if (types.size() <= 1) {
@@ -282,18 +312,13 @@
Loading
282 312
283 313
          std::string paramstr;
284 314
285 -
          for (size_t index = 1;
286 -
               index != types.size();
287 -
               ++index)
288 -
          {
289 -
            paramstr += (types[index].is_const()?"const ":"");
315 +
          for (size_t index = 1; index != types.size(); ++index) {
316 +
            paramstr += (types[index].is_const() ? "const " : "");
290 317
            paramstr += t_ss.get_type_name(types[index]);
291 318
292 -
            if (index == 1 && t_dot_notation)
293 -
            {
319 +
            if (index == 1 && t_dot_notation) {
294 320
              paramstr += ").(";
295 -
              if (types.size() == 2)
296 -
              {
321 +
              if (types.size() == 2) {
297 322
                paramstr += ", ";
298 323
              }
299 324
            } else {
@@ -307,19 +332,15 @@
Loading
307 332
          retval = ss.str();
308 333
        }
309 334
335 +
        std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun
336 +
            = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
310 337
311 -
        std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynfun 
312 -
          = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_func);
313 -
314 -
        if (dynfun && dynfun->has_parse_tree())
315 -
        {
338 +
        if (dynfun && dynfun->has_parse_tree()) {
316 339
          Proxy_Function f = dynfun->get_guard();
317 340
318 -
          if (f)
319 -
          {
341 +
          if (f) {
320 342
            auto dynfunguard = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(f);
321 -
            if (dynfunguard && dynfunguard->has_parse_tree())
322 -
            {
343 +
            if (dynfunguard && dynfunguard->has_parse_tree()) {
323 344
              retval += " : " + format_guard(dynfunguard->get_parse_tree());
324 345
            }
325 346
          }
@@ -331,65 +352,50 @@
Loading
331 352
      }
332 353
333 354
      template<typename T>
334 -
        static std::string format_guard(const T &t)
335 -
        {
336 -
          return t.pretty_print();
337 -
        }
355 +
      static std::string format_guard(const T &t) {
356 +
        return t.pretty_print();
357 +
      }
338 358
339 359
      template<typename T>
340 -
        static std::string format_location(const T &t)
341 -
        {
342 -
          std::ostringstream oss;
343 -
          oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")"; 
344 -
          return oss.str();
345 -
        }
360 +
      static std::string format_location(const T &t) {
361 +
        std::ostringstream oss;
362 +
        oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")";
363 +
        return oss.str();
364 +
      }
346 365
347 366
      static std::string format_detail(const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
348 -
          bool t_dot_notation,
349 -
          const chaiscript::detail::Dispatch_Engine &t_ss)
350 -
      {
367 +
                                       bool t_dot_notation,
368 +
                                       const chaiscript::detail::Dispatch_Engine &t_ss) {
351 369
        std::stringstream ss;
352 -
        if (t_functions.size() == 1)
353 -
        {
370 +
        if (t_functions.size() == 1) {
354 371
          assert(t_functions[0]);
355 372
          ss << "  Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
356 373
        } else {
357 374
          ss << "  " << t_functions.size() << " overloads available:\n";
358 375
359 -
          for (const auto & t_function : t_functions)
360 -
          {
376 +
          for (const auto &t_function : t_functions) {
361 377
            ss << "      " << format_types((t_function), t_dot_notation, t_ss) << '\n';
362 378
          }
363 -
364 379
        }
365 380
366 381
        return ss.str();
367 -
368 382
      }
369 383
370 -
      static std::string format_parameters(const std::vector<Boxed_Value> &t_parameters,
371 -
          bool t_dot_notation,
372 -
          const chaiscript::detail::Dispatch_Engine &t_ss)
373 -
      {
384 +
      static std::string
385 +
      format_parameters(const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss) {
374 386
        std::stringstream ss;
375 387
        ss << "(";
376 388
377 -
        if (!t_parameters.empty())
378 -
        {
389 +
        if (!t_parameters.empty()) {
379 390
          std::string paramstr;
380 391
381 -
          for (auto itr = t_parameters.begin();
382 -
               itr != t_parameters.end();
383 -
               ++itr)
384 -
          {
385 -
            paramstr += (itr->is_const()?"const ":"");
392 +
          for (auto itr = t_parameters.begin(); itr != t_parameters.end(); ++itr) {
393 +
            paramstr += (itr->is_const() ? "const " : "");
386 394
            paramstr += t_ss.type_name(*itr);
387 395
388 -
            if (itr == t_parameters.begin() && t_dot_notation)
389 -
            {
396 +
            if (itr == t_parameters.begin() && t_dot_notation) {
390 397
              paramstr += ").(";
391 -
              if (t_parameters.size() == 1)
392 -
              {
398 +
              if (t_parameters.size() == 1) {
393 399
                paramstr += ", ";
394 400
              }
395 401
            } else {
@@ -404,12 +410,10 @@
Loading
404 410
        return ss.str();
405 411
      }
406 412
407 -
      static std::string format_filename(const std::string &t_fname)
408 -
      {
413 +
      static std::string format_filename(const std::string &t_fname) {
409 414
        std::stringstream ss;
410 415
411 -
        if (t_fname != "__EVAL__")
412 -
        {
416 +
        if (t_fname != "__EVAL__") {
413 417
          ss << "in '" << t_fname << "' ";
414 418
        } else {
415 419
          ss << "during evaluation ";
@@ -418,16 +422,18 @@
Loading
418 422
        return ss.str();
419 423
      }
420 424
421 -
      static std::string format_location(const File_Position &t_where)
422 -
      {
425 +
      static std::string format_location(const File_Position &t_where) {
423 426
        std::stringstream ss;
424 427
        ss << "at (" << t_where.line << ", " << t_where.column << ")";
425 428
        return ss.str();
426 429
      }
427 430
428 -
      static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
429 -
          const std::vector<Boxed_Value> &t_parameters, bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss)
430 -
      {
431 +
      static std::string format(const std::string &t_why,
432 +
                                const File_Position &t_where,
433 +
                                const std::string &t_fname,
434 +
                                const std::vector<Boxed_Value> &t_parameters,
435 +
                                bool t_dot_notation,
436 +
                                const chaiscript::detail::Dispatch_Engine &t_ss) {
431 437
        std::stringstream ss;
432 438
433 439
        ss << format_why(t_why);
@@ -444,11 +450,10 @@
Loading
444 450
        return ss.str();
445 451
      }
446 452
447 -
      static std::string format(const std::string &t_why, 
448 -
          const std::vector<Boxed_Value> &t_parameters, 
449 -
          bool t_dot_notation,
450 -
          const chaiscript::detail::Dispatch_Engine &t_ss)
451 -
      {
453 +
      static std::string format(const std::string &t_why,
454 +
                                const std::vector<Boxed_Value> &t_parameters,
455 +
                                bool t_dot_notation,
456 +
                                const chaiscript::detail::Dispatch_Engine &t_ss) {
452 457
        std::stringstream ss;
453 458
454 459
        ss << format_why(t_why);
@@ -460,8 +465,7 @@
Loading
460 465
        return ss.str();
461 466
      }
462 467
463 -
      static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname)
464 -
      {
468 +
      static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) {
465 469
        std::stringstream ss;
466 470
467 471
        ss << format_why(t_why);
@@ -476,13 +480,12 @@
Loading
476 480
      }
477 481
    };
478 482
479 -
480 483
    /// Errors generated when loading a file
481 484
    struct file_not_found_error : std::runtime_error {
482 -
      explicit file_not_found_error(const std::string &t_filename) noexcept
483 -
        : std::runtime_error("File Not Found: " + t_filename),
484 -
          filename(t_filename)
485 -
      { }
485 +
      explicit file_not_found_error(const std::string &t_filename)
486 +
          : std::runtime_error("File Not Found: " + t_filename)
487 +
          , filename(t_filename) {
488 +
      }
486 489
487 490
      file_not_found_error(const file_not_found_error &) = default;
488 491
      ~file_not_found_error() noexcept override = default;
@@ -490,265 +493,204 @@
Loading
490 493
      std::string filename;
491 494
    };
492 495
493 -
  }
496 +
  } // namespace exception
494 497
495 -
 
496 498
  /// \brief Struct that doubles as both a parser ast_node and an AST node.
497 499
  struct AST_Node {
498 -
    public:
499 -
      const AST_Node_Type identifier;
500 -
      const std::string text;
501 -
      Parse_Location location;
502 -
503 -
      const std::string &filename() const {
504 -
        return *location.filename;
505 -
      }
500 +
  public:
501 +
    const AST_Node_Type identifier;
502 +
    const std::string text;
503 +
    Parse_Location location;
506 504
507 -
      const File_Position &start() const {
508 -
        return location.start;
509 -
      }
505 +
    const std::string &filename() const noexcept { return *location.filename; }
510 506
511 -
      const File_Position &end() const {
512 -
        return location.end;
513 -
      }
507 +
    const File_Position &start() const noexcept { return location.start; }
514 508
515 -
      std::string pretty_print() const
516 -
      {
517 -
        std::ostringstream oss;
509 +
    const File_Position &end() const noexcept { return location.end; }
518 510
519 -
        oss << text;
511 +
    std::string pretty_print() const {
512 +
      std::ostringstream oss;
520 513
521 -
        for (auto & elem : get_children()) {
522 -
          oss << elem.get().pretty_print() << ' ';
523 -
        }
514 +
      oss << text;
524 515
525 -
        return oss.str();
516 +
      for (auto &elem : get_children()) {
517 +
        oss << elem.get().pretty_print() << ' ';
526 518
      }
527 519
528 -
      virtual std::vector<std::reference_wrapper<AST_Node>> get_children() const = 0;
529 -
      virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
530 -
531 -
532 -
      /// Prints the contents of an AST node, including its children, recursively
533 -
      std::string to_string(const std::string &t_prepend = "") const {
534 -
        std::ostringstream oss;
520 +
      return oss.str();
521 +
    }
535 522
536 -
        oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
537 -
            << this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n';
523 +
    virtual std::vector<std::reference_wrapper<AST_Node>> get_children() const = 0;
524 +
    virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0;
538 525
539 -
        for (auto & elem : get_children()) {
540 -
          oss << elem.get().to_string(t_prepend + "  ");
541 -
        }
542 -
        return oss.str();
543 -
      }
526 +
    /// Prints the contents of an AST node, including its children, recursively
527 +
    std::string to_string(const std::string &t_prepend = "") const {
528 +
      std::ostringstream oss;
544 529
530 +
      oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line
531 +
          << ", " << this->location.start.column << '\n';
545 532
546 -
      static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
547 -
        try {
548 -
          return t_ss->boxed_cast<bool>(t_bv);
549 -
        }
550 -
        catch (const exception::bad_boxed_cast &) {
551 -
          throw exception::eval_error("Condition not boolean");
552 -
        }
533 +
      for (auto &elem : get_children()) {
534 +
        oss << elem.get().to_string(t_prepend + "  ");
553 535
      }
536 +
      return oss.str();
537 +
    }
554 538
555 -
556 -
      virtual ~AST_Node() = default;
557 -
      AST_Node(AST_Node &&) = default;
558 -
      AST_Node &operator=(AST_Node &&) = default;
559 -
      AST_Node(const AST_Node &) = delete;
560 -
      AST_Node& operator=(const AST_Node &) = delete;
561 -
562 -
563 -
    protected:
564 -
      AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc)
565 -
        : identifier(t_id), text(std::move(t_ast_node_text)),
566 -
          location(std::move(t_loc))
567 -
      {
539 +
    static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) {
540 +
      try {
541 +
        return t_ss->boxed_cast<bool>(t_bv);
542 +
      } catch (const exception::bad_boxed_cast &) {
543 +
        throw exception::eval_error("Condition not boolean");
568 544
      }
545 +
    }
569 546
570 -
547 +
    virtual ~AST_Node() noexcept = default;
548 +
    AST_Node(AST_Node &&) = default;
549 +
    AST_Node &operator=(AST_Node &&) = delete;
550 +
    AST_Node(const AST_Node &) = delete;
551 +
    AST_Node &operator=(const AST_Node &) = delete;
552 +
553 +
  protected:
554 +
    AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc)
555 +
        : identifier(t_id)
556 +
        , text(std::move(t_ast_node_text))
557 +
        , location(std::move(t_loc)) {
558 +
    }
571 559
  };
572 560
573 -
  struct AST_Node_Trace
574 -
  {
561 +
  struct AST_Node_Trace {
575 562
    const AST_Node_Type identifier;
576 563
    const std::string text;
577 564
    Parse_Location location;
578 565
579 -
    const std::string &filename() const {
580 -
      return *location.filename;
581 -
    }
566 +
    const std::string &filename() const noexcept { return *location.filename; }
582 567
583 -
    const File_Position &start() const {
584 -
      return location.start;
585 -
    }
568 +
    const File_Position &start() const noexcept { return location.start; }
586 569
587 -
    const File_Position &end() const {
588 -
      return location.end;
589 -
    }
570 +
    const File_Position &end() const noexcept { return location.end; }
590 571
591 -
    std::string pretty_print() const
592 -
    {
572 +
    std::string pretty_print() const {
593 573
      std::ostringstream oss;
594 574
595 575
      oss << text;
596 576
597 -
      for (const auto & elem : children) {
577 +
      for (const auto &elem : children) {
598 578
        oss << elem.pretty_print() << ' ';
599 579
      }
600 580
601 581
      return oss.str();
602 582
    }
603 583
604 -
    std::vector<AST_Node_Trace> get_children(const AST_Node &node)
605 -
    {
584 +
    std::vector<AST_Node_Trace> get_children(const AST_Node &node) {
606 585
      const auto node_children = node.get_children();
607 586
      return std::vector<AST_Node_Trace>(node_children.begin(), node_children.end());
608 587
    }
609 588
610 589
    AST_Node_Trace(const AST_Node &node)
611 -
      : identifier(node.identifier), text(node.text),
612 -
      location(node.location), children(get_children(node))
613 -
    {
590 +
        : identifier(node.identifier)
591 +
        , text(node.text)
592 +
        , location(node.location)
593 +
        , children(get_children(node)) {
614 594
    }
615 595
616 -
617 596
    std::vector<AST_Node_Trace> children;
618 -
619 597
  };
620 598
621 599
  namespace parser {
622 -
    class ChaiScript_Parser_Base
623 -
    {
624 -
      public:
625 -
        virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
626 -
        virtual void debug_print(const AST_Node &t, std::string prepend = "") const = 0;
627 -
        virtual void *get_tracer_ptr() = 0;
628 -
        virtual ~ChaiScript_Parser_Base() = default;
629 -
        ChaiScript_Parser_Base() = default;
630 -
        ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
631 -
        ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
632 -
        ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
633 -
634 -
        template<typename T>
635 -
        T &get_tracer()
636 -
        {
637 -
          // to do type check this somehow?
638 -
          return *static_cast<T*>(get_tracer_ptr());
639 -
        }
600 +
    class ChaiScript_Parser_Base {
601 +
    public:
602 +
      virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0;
603 +
      virtual void debug_print(const AST_Node &t, std::string prepend = "") const = 0;
604 +
      virtual void *get_tracer_ptr() = 0;
605 +
      virtual ~ChaiScript_Parser_Base() = default;
606 +
      ChaiScript_Parser_Base() = default;
607 +
      ChaiScript_Parser_Base(ChaiScript_Parser_Base &&) = default;
608 +
      ChaiScript_Parser_Base &operator=(ChaiScript_Parser_Base &&) = delete;
609 +
      ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
640 610
641 -
      protected:
642 -
        ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
611 +
      template<typename T>
612 +
      T &get_tracer() noexcept {
613 +
        // to do type check this somehow?
614 +
        return *static_cast<T *>(get_tracer_ptr());
615 +
      }
616 +
617 +
    protected:
618 +
      ChaiScript_Parser_Base(const ChaiScript_Parser_Base &) = default;
643 619
    };
644 -
  }
620 +
  } // namespace parser
645 621
646 -
  namespace eval
647 -
  {
648 -
    namespace detail
649 -
    {
622 +
  namespace eval {
623 +
    namespace detail {
650 624
      /// Special type for returned values
651 625
      struct Return_Value {
652 626
        Boxed_Value retval;
653 627
      };
654 628
655 -
656