GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
dispatchkit.hpp
Go to the documentation of this file.
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// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9
10
11#ifndef CHAISCRIPT_DISPATCHKIT_HPP_
12#define CHAISCRIPT_DISPATCHKIT_HPP_
13
14#include <algorithm>
15#include <iostream>
16#include <list>
17#include <map>
18#include <memory>
19#include <set>
20#include <stdexcept>
21#include <string>
22#include <typeinfo>
23#include <utility>
24#include <vector>
25
28#include "bad_boxed_cast.hpp"
29#include "boxed_cast.hpp"
30#include "boxed_cast_helper.hpp"
31#include "boxed_value.hpp"
32#include "type_conversions.hpp"
33#include "dynamic_object.hpp"
35#include "proxy_functions.hpp"
36#include "type_info.hpp"
37#include "short_alloc.hpp"
38
39namespace chaiscript {
40class Boxed_Number;
41} // namespace chaiscript
42
43namespace chaiscript {
44 namespace parser {
46 }
47namespace dispatch {
48class Dynamic_Proxy_Function;
49class Proxy_Function_Base;
50struct Placeholder_Object;
51} // namespace dispatch
52} // namespace chaiscript
53
54
55
58
59namespace chaiscript
60{
61 namespace exception
62 {
64 class reserved_word_error : public std::runtime_error
65 {
66 public:
67 explicit reserved_word_error(const std::string &t_word) noexcept
68 : std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word)
69 {
70 }
71
73
74 ~reserved_word_error() noexcept override = default;
75
76 std::string word() const
77 {
78 return m_word;
79 }
80
81 private:
82 std::string m_word;
83 };
84
86 class illegal_name_error : public std::runtime_error
87 {
88 public:
89 explicit illegal_name_error(const std::string &t_name) noexcept
90 : std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
91 {
92 }
93
95
96 ~illegal_name_error() noexcept override = default;
97
98 std::string name() const
99 {
100 return m_name;
101 }
102
103 private:
104 std::string m_name;
105 };
106
107
109 class name_conflict_error : public std::runtime_error
110 {
111 public:
112 explicit name_conflict_error(const std::string &t_name) noexcept
113 : std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
114 {
115 }
116
118
119 ~name_conflict_error() noexcept override = default;
120
121 std::string name() const
122 {
123 return m_name;
124 }
125
126 private:
127 std::string m_name;
128
129 };
130
131
133 class global_non_const : public std::runtime_error
134 {
135 public:
137 : std::runtime_error("a global object must be const")
138 {
139 }
140
142 ~global_non_const() noexcept override = default;
143 };
144 }
145
146
149 class Module
150 {
151 public:
152 Module &add(Type_Info ti, std::string name)
153 {
154 m_typeinfos.emplace_back(ti, std::move(name));
155 return *this;
156 }
157
159 {
160 m_conversions.push_back(std::move(d));
161 return *this;
162 }
163
165 {
166 m_funcs.emplace_back(std::move(f), std::move(name));
167 return *this;
168 }
169
170 Module &add_global_const(Boxed_Value t_bv, std::string t_name)
171 {
172 if (!t_bv.is_const())
173 {
175 }
176
177 m_globals.emplace_back(std::move(t_bv), std::move(t_name));
178 return *this;
179 }
180
181
182 //Add a bit of ChaiScript to eval during module implementation
183 Module &eval(const std::string &str)
184 {
185 m_evals.push_back(str);
186 return *this;
187 }
188
189 template<typename Eval, typename Engine>
190 void apply(Eval &t_eval, Engine &t_engine) const
191 {
192 apply(m_typeinfos.begin(), m_typeinfos.end(), t_engine);
193 apply(m_funcs.begin(), m_funcs.end(), t_engine);
194 apply_eval(m_evals.begin(), m_evals.end(), t_eval);
195 apply_single(m_conversions.begin(), m_conversions.end(), t_engine);
196 apply_globals(m_globals.begin(), m_globals.end(), t_engine);
197 }
198
199 bool has_function(const Proxy_Function &new_f, const std::string &name)
200 {
201 return std::any_of(m_funcs.begin(), m_funcs.end(),
202 [&](const std::pair<Proxy_Function, std::string> &existing_f) {
203 return existing_f.second == name && *(existing_f.first) == *(new_f);
204 }
205 );
206 }
207
208
209 private:
210 std::vector<std::pair<Type_Info, std::string>> m_typeinfos;
211 std::vector<std::pair<Proxy_Function, std::string>> m_funcs;
212 std::vector<std::pair<Boxed_Value, std::string>> m_globals;
213 std::vector<std::string> m_evals;
214 std::vector<Type_Conversion> m_conversions;
215
216 template<typename T, typename InItr>
217 static void apply(InItr begin, const InItr end, T &t)
218 {
219 for_each(begin, end,
220 [&t](const auto &obj) {
221 try {
222 t.add(obj.first, obj.second);
226 }
227 }
228 );
229 }
230
231 template<typename T, typename InItr>
232 static void apply_globals(InItr begin, InItr end, T &t)
233 {
234 while (begin != end)
235 {
236 t.add_global_const(begin->first, begin->second);
237 ++begin;
238 }
239 }
240
241 template<typename T, typename InItr>
242 static void apply_single(InItr begin, InItr end, T &t)
243 {
244 while (begin != end)
245 {
246 t.add(*begin);
247 ++begin;
248 }
249 }
250
251 template<typename T, typename InItr>
252 static void apply_eval(InItr begin, InItr end, T &t)
253 {
254 while (begin != end)
255 {
256 t.eval(*begin);
257 ++begin;
258 }
259 }
260 };
261
263 typedef std::shared_ptr<Module> ModulePtr;
264
265 namespace detail
266 {
271 {
272 public:
273 explicit Dispatch_Function(std::vector<Proxy_Function> t_funcs)
274 : Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
275 m_funcs(std::move(t_funcs))
276 {
277 }
278
279 bool operator==(const dispatch::Proxy_Function_Base &rhs) const override
280 {
281 try {
282 const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
283 return m_funcs == dispatch_fun.m_funcs;
284 } catch (const std::bad_cast &) {
285 return false;
286 }
287 }
288
289 std::vector<Const_Proxy_Function> get_contained_functions() const override
290 {
291 return std::vector<Const_Proxy_Function>(m_funcs.begin(), m_funcs.end());
292 }
293
294
295 static int calculate_arity(const std::vector<Proxy_Function> &t_funcs)
296 {
297 if (t_funcs.empty()) {
298 return -1;
299 }
300
301 const auto arity = t_funcs.front()->get_arity();
302
303 for (const auto &func : t_funcs)
304 {
305 if (arity != func->get_arity())
306 {
307 // The arities in the list do not match, so it's unspecified
308 return -1;
309 }
310 }
311
312 return arity;
313 }
314
315 bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
316 {
317 return std::any_of(std::begin(m_funcs), std::end(m_funcs),
318 [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
319 }
320
321 protected:
322 Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
323 {
324 return dispatch::dispatch(m_funcs, params, t_conversions);
325 }
326
327 private:
328 std::vector<Proxy_Function> m_funcs;
329
330 static std::vector<Type_Info> build_type_infos(const std::vector<Proxy_Function> &t_funcs)
331 {
332 auto begin = t_funcs.cbegin();
333 const auto &end = t_funcs.cend();
334
335 if (begin != end)
336 {
337 std::vector<Type_Info> type_infos = (*begin)->get_param_types();
338
339 ++begin;
340
341 bool size_mismatch = false;
342
343 while (begin != end)
344 {
345 std::vector<Type_Info> param_types = (*begin)->get_param_types();
346
347 if (param_types.size() != type_infos.size())
348 {
349 size_mismatch = true;
350 }
351
352 for (size_t i = 0; i < type_infos.size() && i < param_types.size(); ++i)
353 {
354 if (!(type_infos[i] == param_types[i]))
355 {
357 }
358 }
359
360 ++begin;
361 }
362
363 assert(!type_infos.empty() && " type_info vector size is < 0, this is only possible if something else is broken");
364
365 if (size_mismatch)
366 {
367 type_infos.resize(1);
368 }
369
370 return type_infos;
371 }
372
373 return std::vector<Type_Info>();
374 }
375 };
376 }
377
378
379 namespace detail
380 {
382 {
383 //template <class T, std::size_t BufSize = sizeof(T)*20000>
384 // using SmallVector = std::vector<T, short_alloc<T, BufSize>>;
385
386 template <class T>
387 using SmallVector = std::vector<T>;
388
389
395
397 {
398 push_stack();
400 }
401
403 {
404 stacks.back().emplace_back();
405// stacks.back().emplace_back(Scope(scope_allocator));
406 }
407
409 {
410 stacks.emplace_back(1);
411// stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator));
412 }
413
415 {
416 call_params.emplace_back();
417// call_params.emplace_back(Call_Param_List(call_param_list_allocator));
418 }
419
420 //Scope::allocator_type::arena_type scope_allocator;
421 //StackData::allocator_type::arena_type stack_data_allocator;
422 //Stacks::allocator_type::arena_type stacks_allocator;
423 //Call_Param_List::allocator_type::arena_type call_param_list_allocator;
424 //Call_Params::allocator_type::arena_type call_params_allocator;
425
426// Stacks stacks = Stacks(stacks_allocator);
427// Call_Params call_params = Call_Params(call_params_allocator);
428
431
432 int call_depth = 0;
433 };
434
438 {
439
440 public:
441 typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
442 typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
444
445 struct State
446 {
447 std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> m_functions;
448 std::vector<std::pair<std::string, Proxy_Function>> m_function_objects;
449 std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
450 std::map<std::string, Boxed_Value> m_global_objects;
452 };
453
455 : m_stack_holder(),
456 m_parser(parser)
457 {
458 }
459
461 template<typename Type>
462 decltype(auto) boxed_cast(const Boxed_Value &bv) const
463 {
464 Type_Conversions_State state(m_conversions, m_conversions.conversion_saves());
465 return(chaiscript::boxed_cast<Type>(bv, &state));
466 }
467
469 void add(const Type_Conversion &d)
470 {
471 m_conversions.add_conversion(d);
472 }
473
475 void add(const Proxy_Function &f, const std::string &name)
476 {
478 }
479
482 void add(Boxed_Value obj, const std::string &name)
483 {
484 auto &stack = get_stack_data();
485
486 for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
487 {
488 auto itr = std::find_if(stack_elem->begin(), stack_elem->end(),
489 [&](const std::pair<std::string, Boxed_Value> &o) {
490 return o.first == name;
491 });
492
493 if (itr != stack_elem->end())
494 {
495 itr->second = std::move(obj);
496 return;
497 }
498 }
499
500 add_object(name, std::move(obj));
501 }
502
506 Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
507 {
508 auto &stack_elem = get_stack_data(t_holder).back();
509
510 if (std::any_of(stack_elem.begin(), stack_elem.end(),
511 [&](const std::pair<std::string, Boxed_Value> &o) {
512 return o.first == t_name;
513 }))
514 {
516 }
517
518 stack_elem.emplace_back(t_name, std::move(obj));
519 return stack_elem.back().second;
520 }
521
522
526 void add_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
527 {
528 auto &stack_elem = get_stack_data(t_holder).back();
529
530 if (std::any_of(stack_elem.begin(), stack_elem.end(),
531 [&](const std::pair<std::string, Boxed_Value> &o) {
532 return o.first == t_name;
533 }))
534 {
536 }
537
538 stack_elem.emplace_back(t_name, std::move(obj));
539 }
540
541
545 void add_object(const std::string &name, Boxed_Value obj)
546 {
547 add_object(name, std::move(obj), get_stack_holder());
548 }
549
551 void add_global_const(const Boxed_Value &obj, const std::string &name)
552 {
553 if (!obj.is_const())
554 {
556 }
557
559
560 if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
561 {
563 } else {
564 m_state.m_global_objects.insert(std::make_pair(name, obj));
565 }
566 }
567
569 Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
570 {
572
573 const auto itr = m_state.m_global_objects.find(name);
574 if (itr == m_state.m_global_objects.end())
575 {
576 m_state.m_global_objects.insert(std::make_pair(name, obj));
577 return obj;
578 } else {
579 return itr->second;
580 }
581 }
582
583
585 void add_global(const Boxed_Value &obj, const std::string &name)
586 {
588
589 if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
590 {
592 } else {
593 m_state.m_global_objects.insert(std::make_pair(name, obj));
594 }
595 }
596
598 void set_global(const Boxed_Value &obj, const std::string &name)
599 {
601
602 const auto itr = m_state.m_global_objects.find(name);
603 if (itr != m_state.m_global_objects.end())
604 {
605 itr->second.assign(obj);
606 } else {
607 m_state.m_global_objects.insert(std::make_pair(name, obj));
608 }
609 }
610
613 {
614 new_scope(*m_stack_holder);
615 }
616
619 {
620 pop_scope(*m_stack_holder);
621 }
622
624 static void new_scope(Stack_Holder &t_holder)
625 {
626 t_holder.push_stack_data();
627 t_holder.push_call_params();
628 }
629
631 static void pop_scope(Stack_Holder &t_holder)
632 {
633 t_holder.call_params.pop_back();
634 StackData &stack = get_stack_data(t_holder);
635
636 assert(!stack.empty());
637
638 stack.pop_back();
639 }
640
641
643 static void new_stack(Stack_Holder &t_holder)
644 {
645 // add a new Stack with 1 element
646 t_holder.push_stack();
647 }
648
649 static void pop_stack(Stack_Holder &t_holder)
650 {
651 t_holder.stacks.pop_back();
652 }
653
657 Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
658 {
659 enum class Loc : uint_fast32_t {
660 located = 0x80000000,
661 is_local = 0x40000000,
662 stack_mask = 0x0FFF0000,
663 loc_mask = 0x0000FFFF
664 };
665
666 uint_fast32_t loc = t_loc;
667
668 if (loc == 0)
669 {
670 auto &stack = get_stack_data(t_holder);
671
672 // Is it in the stack?
673 for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
674 {
675 for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s )
676 {
677 if (s->first == name) {
678 t_loc = static_cast<uint_fast32_t>(std::distance(stack.rbegin(), stack_elem) << 16)
679 | static_cast<uint_fast32_t>(std::distance(stack_elem->begin(), s))
680 | static_cast<uint_fast32_t>(Loc::located)
681 | static_cast<uint_fast32_t>(Loc::is_local);
682 return s->second;
683 }
684 }
685 }
686
687 t_loc = static_cast<uint_fast32_t>(Loc::located);
688 } else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) {
689 auto &stack = get_stack_data(t_holder);
690
691 return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
692 }
693
694 // Is the value we are looking for a global or function?
696
697 const auto itr = m_state.m_global_objects.find(name);
698 if (itr != m_state.m_global_objects.end())
699 {
700 return itr->second;
701 }
702
703 // no? is it a function object?
704 auto obj = get_function_object_int(name, loc);
705 if (obj.first != loc) { t_loc = uint_fast32_t(obj.first); }
706
707 return obj.second;
708
709 }
710
712 void add(const Type_Info &ti, const std::string &name)
713 {
714 add_global_const(const_var(ti), name + "_type");
715
717
718 m_state.m_types.insert(std::make_pair(name, ti));
719 }
720
722 Type_Info get_type(const std::string &name, bool t_throw = true) const
723 {
725
726 const auto itr = m_state.m_types.find(name);
727
728 if (itr != m_state.m_types.end())
729 {
730 return itr->second;
731 }
732
733 if (t_throw) {
734 throw std::range_error("Type Not Known: " + name);
735 } else {
736 return Type_Info();
737 }
738 }
739
743 std::string get_type_name(const Type_Info &ti) const
744 {
746
747 for (const auto & elem : m_state.m_types)
748 {
749 if (elem.second.bare_equal(ti))
750 {
751 return elem.first;
752 }
753 }
754
755 return ti.bare_name();
756 }
757
759 std::vector<std::pair<std::string, Type_Info> > get_types() const
760 {
762
763 return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
764 }
765
766 std::shared_ptr<std::vector<Proxy_Function>> get_method_missing_functions() const
767 {
768 uint_fast32_t method_missing_loc = m_method_missing_loc;
769 auto method_missing_funs = get_function("method_missing", method_missing_loc);
770 if (method_missing_funs.first != method_missing_loc) {
771 m_method_missing_loc = uint_fast32_t(method_missing_funs.first);
772 }
773
774 return std::move(method_missing_funs.second);
775 }
776
777
779 std::pair<size_t, std::shared_ptr<std::vector< Proxy_Function>>> get_function(const std::string &t_name, const size_t t_hint) const
780 {
782
783 const auto &funs = get_functions_int();
784
785 auto itr = find_keyed_value(funs, t_name, t_hint);
786
787 if (itr != funs.end())
788 {
789 return std::make_pair(std::distance(funs.begin(), itr), itr->second);
790 } else {
791 return std::make_pair(size_t(0), std::make_shared<std::vector<Proxy_Function>>());
792 }
793 }
794
797 Boxed_Value get_function_object(const std::string &t_name) const
798 {
800
801 return get_function_object_int(t_name, 0).second;
802 }
803
807 std::pair<size_t, Boxed_Value> get_function_object_int(const std::string &t_name, const size_t t_hint) const
808 {
809 const auto &funs = get_boxed_functions_int();
810
811 auto itr = find_keyed_value(funs, t_name, t_hint);
812
813 if (itr != funs.end())
814 {
815 return std::make_pair(std::distance(funs.begin(), itr), itr->second);
816 } else {
817 throw std::range_error("Object not found: " + t_name);
818 }
819 }
820
821
823 bool function_exists(const std::string &name) const
824 {
826
827 const auto &functions = get_functions_int();
828 return find_keyed_value(functions, name) != functions.end();
829 }
830
833 std::map<std::string, Boxed_Value> get_parent_locals() const
834 {
835 auto &stack = get_stack_data();
836 if (stack.size() > 1)
837 {
838 return std::map<std::string, Boxed_Value>(stack[1].begin(), stack[1].end());
839 } else {
840 return std::map<std::string, Boxed_Value>(stack[0].begin(), stack[0].end());
841 }
842 }
843
845 std::map<std::string, Boxed_Value> get_locals() const
846 {
847 auto &stack = get_stack_data();
848 auto &scope = stack.front();
849 return std::map<std::string, Boxed_Value>(scope.begin(), scope.end());
850 }
851
857 void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
858 {
859 auto &stack = get_stack_data();
860 auto &scope = stack.front();
861 scope.assign(t_locals.begin(), t_locals.end());
862 }
863
864
865
869 std::map<std::string, Boxed_Value> get_scripting_objects() const
870 {
871 const Stack_Holder &s = *m_stack_holder;
872
873 // We don't want the current context, but one up if it exists
874 const StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]);
875
876 std::map<std::string, Boxed_Value> retval;
877
878 // note: map insert doesn't overwrite existing values, which is why this works
879 for (auto itr = stack.rbegin(); itr != stack.rend(); ++itr)
880 {
881 retval.insert(itr->begin(), itr->end());
882 }
883
884 // add the global values
886 retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
887
888 return retval;
889 }
890
891
895 std::map<std::string, Boxed_Value> get_function_objects() const
896 {
898
899 const auto &funs = get_function_objects_int();
900
901 std::map<std::string, Boxed_Value> objs;
902
903 for (const auto & fun : funs)
904 {
905 objs.insert(std::make_pair(fun.first, const_var(fun.second)));
906 }
907
908 return objs;
909 }
910
911
913 std::vector<std::pair<std::string, Proxy_Function > > get_functions() const
914 {
916
917 std::vector<std::pair<std::string, Proxy_Function> > rets;
918
919 const auto &functions = get_functions_int();
920
921 for (const auto & function : functions)
922 {
923 for (const auto & internal_func : *function.second)
924 {
925 rets.emplace_back(function.first, internal_func);
926 }
927 }
928
929 return rets;
930 }
931
932
934 {
935 return m_conversions;
936 }
937
938 static bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
939 bool t_has_params, const Type_Conversions_State &t_conversions)
940 {
941 if (!t_has_params || t_params.empty()) {
942 return false;
943 }
944
945 return std::any_of(std::begin(t_funs), std::end(t_funs),
946 [&](const auto &fun) {
947 return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions);
948 }
949 );
950
951 }
952
953#ifdef CHAISCRIPT_MSVC
954// MSVC is unable to recognize that "rethrow_exception" causes the function to return
955// so we must disable it here.
956#pragma warning(push)
957#pragma warning(disable : 4715)
958#endif
959 Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params, bool t_has_params,
960 const Type_Conversions_State &t_conversions)
961 {
962 uint_fast32_t loc = t_loc;
963 const auto funs = get_function(t_name, loc);
964 if (funs.first != loc) { t_loc = uint_fast32_t(funs.first); }
965
966 const auto do_attribute_call =
967 [this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
968 {
969 std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
970 Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
971 if (l_num_params < int(l_params.size()) || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
972 struct This_Foist {
973 This_Foist(Dispatch_Engine &e, const Boxed_Value &t_bv) : m_e(e) {
974 m_e.get().new_scope();
975 m_e.get().add_object("__this", t_bv);
976 }
977
978 ~This_Foist() {
979 m_e.get().pop_scope();
980 }
981
982 std::reference_wrapper<Dispatch_Engine> m_e;
983 };
984
985 This_Foist fi(*this, l_params.front());
986
987 try {
989 try {
990 return (*func)({l_params.begin() + l_num_params, l_params.end()}, l_conversions);
991 } catch (const chaiscript::exception::bad_boxed_cast &) {
992 } catch (const chaiscript::exception::arity_error &) {
993 } catch (const chaiscript::exception::guard_error &) {
994 }
995 throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
996 std::vector<Const_Proxy_Function>{boxed_cast<Const_Proxy_Function>(bv)});
997 } catch (const chaiscript::exception::bad_boxed_cast &) {
998 // unable to convert bv into a Proxy_Function_Base
999 throw chaiscript::exception::dispatch_error({l_params.begin() + l_num_params, l_params.end()},
1000 std::vector<Const_Proxy_Function>(l_funs.begin(), l_funs.end()));
1001 }
1002 } else {
1003 return bv;
1004 }
1005 };
1006
1007 if (is_attribute_call(*funs.second, params, t_has_params, t_conversions)) {
1008 return do_attribute_call(1, params, *funs.second, t_conversions);
1009 } else {
1010 std::exception_ptr except;
1011
1012 if (!funs.second->empty()) {
1013 try {
1014 return dispatch::dispatch(*funs.second, params, t_conversions);
1016 except = std::current_exception();
1017 }
1018 }
1019
1020 // If we get here we know that either there was no method with that name,
1021 // or there was no matching method
1022
1023 const auto functions = [&]()->std::vector<Proxy_Function> {
1024 std::vector<Proxy_Function> fs;
1025
1026 const auto method_missing_funs = get_method_missing_functions();
1027
1028 for (const auto &f : *method_missing_funs)
1029 {
1030 if(f->compare_first_type(params[0], t_conversions)) {
1031 fs.push_back(f);
1032 }
1033 }
1034
1035 return fs;
1036 }();
1037
1038
1039
1040 const bool is_no_param = [&]()->bool{
1041 for (const auto &f : functions) {
1042 if (f->get_arity() != 2) {
1043 return false;
1044 }
1045 }
1046 return true;
1047 }();
1048
1049 if (!functions.empty()) {
1050 try {
1051 if (is_no_param) {
1052 std::vector<Boxed_Value> tmp_params(params);
1053 tmp_params.insert(tmp_params.begin() + 1, var(t_name));
1054 return do_attribute_call(2, tmp_params, functions, t_conversions);
1055 } else {
1056 return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, t_conversions);
1057 }
1058 } catch (const dispatch::option_explicit_set &e) {
1059 throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
1060 e.what());
1061 }
1062 }
1063
1064 // If we get all the way down here we know there was no "method_missing"
1065 // method at all.
1066 if (except) {
1067 std::rethrow_exception(except);
1068 } else {
1069 throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()));
1070 }
1071 }
1072 }
1073#ifdef CHAISCRIPT_MSVC
1074#pragma warning(pop)
1075#endif
1076
1077
1078
1079 Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params,
1080 const Type_Conversions_State &t_conversions) const
1081 {
1082 uint_fast32_t loc = t_loc;
1083 const auto funs = get_function(t_name, loc);
1084 if (funs.first != loc) { t_loc = uint_fast32_t(funs.first);
1085}
1086 return dispatch::dispatch(*funs.second, params, t_conversions);
1087 }
1088
1089
1091 void dump_object(const Boxed_Value &o) const
1092 {
1093 std::cout << (o.is_const()?"const ":"") << type_name(o) << '\n';
1094 }
1095
1097 void dump_type(const Type_Info &type) const
1098 {
1099 std::cout << (type.is_const()?"const ":"") << get_type_name(type);
1100 }
1101
1103 void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
1104 {
1105 std::vector<Type_Info> params = f.second->get_param_types();
1106
1107 dump_type(params.front());
1108 std::cout << " " << f.first << "(";
1109
1110 for (std::vector<Type_Info>::const_iterator itr = params.begin() + 1;
1111 itr != params.end();
1112 )
1113 {
1114 dump_type(*itr);
1115 ++itr;
1116
1117 if (itr != params.end())
1118 {
1119 std::cout << ", ";
1120 }
1121 }
1122
1123 std::cout << ") \n";
1124 }
1125
1128 Boxed_Value call_exists(const std::vector<Boxed_Value> &params) const
1129 {
1130 if (params.empty())
1131 {
1132 throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
1133 }
1134
1136 const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves());
1137
1138 return const_var(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
1139 }
1140
1142 void dump_system() const
1143 {
1144 std::cout << "Registered Types: \n";
1145 for (auto const &type: get_types())
1146 {
1147 std::cout << type.first << ": " << type.second.bare_name() << '\n';
1148 }
1149
1150 std::cout << '\n';
1151
1152 std::cout << "Functions: \n";
1153 for (auto const &func: get_functions())
1154 {
1156 }
1157 std::cout << '\n';
1158 }
1159
1161 bool is_type(const Boxed_Value &r, const std::string &user_typename) const
1162 {
1163 try {
1164 if (get_type(user_typename).bare_equal(r.get_type_info()))
1165 {
1166 return true;
1167 }
1168 } catch (const std::range_error &) {
1169 }
1170
1171 try {
1173 return d.get_type_name() == user_typename;
1174 } catch (const std::bad_cast &) {
1175 }
1176
1177 return false;
1178 }
1179
1180 std::string type_name(const Boxed_Value &obj) const
1181 {
1182 return get_type_name(obj.get_type_info());
1183 }
1184
1191
1192 void set_state(const State &t_state)
1193 {
1195
1196 m_state = t_state;
1197 }
1198
1199 static void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
1200 {
1201 t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params);
1202 }
1203
1204 static void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
1205 {
1206 for (auto &&param : t_params)
1207 {
1208 t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(param));
1209 }
1210 }
1211
1212 static void save_function_params(Stack_Holder &t_s, const std::vector<Boxed_Value> &t_params)
1213 {
1214 t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end());
1215 }
1216
1217 void save_function_params(std::initializer_list<Boxed_Value> t_params)
1218 {
1219 save_function_params(*m_stack_holder, t_params);
1220 }
1221
1222 void save_function_params(std::vector<Boxed_Value> &&t_params)
1223 {
1224 save_function_params(*m_stack_holder, std::move(t_params));
1225 }
1226
1227 void save_function_params(const std::vector<Boxed_Value> &t_params)
1228 {
1229 save_function_params(*m_stack_holder, t_params);
1230 }
1231
1233 {
1234 if (t_s.call_depth == 0)
1235 {
1236 m_conversions.enable_conversion_saves(t_saves, true);
1237 }
1238
1239 ++t_s.call_depth;
1240
1241 save_function_params(m_conversions.take_saves(t_saves));
1242 }
1243
1245 {
1246 --t_s.call_depth;
1247
1248 assert(t_s.call_depth >= 0);
1249
1250 if (t_s.call_depth == 0)
1251 {
1252 t_s.call_params.back().clear();
1253 m_conversions.enable_conversion_saves(t_saves, false);
1254 }
1255 }
1256
1258 {
1259 new_function_call(*m_stack_holder, m_conversions.conversion_saves());
1260 }
1261
1263 {
1264 pop_function_call(*m_stack_holder, m_conversions.conversion_saves());
1265 }
1266
1268 {
1269 return *m_stack_holder;
1270 }
1271
1275 {
1276 return m_stack_holder->stacks.back();
1277 }
1278
1280 {
1281 return t_holder.stacks.back();
1282 }
1283
1285 {
1286 return m_stack_holder->stacks.back();
1287 }
1288
1290 {
1291 return m_parser.get();
1292 }
1293
1294 private:
1295
1296 const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
1297 {
1298 return m_state.m_boxed_functions;
1299 }
1300
1301 std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int()
1302 {
1303 return m_state.m_boxed_functions;
1304 }
1305
1306 const std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() const
1307 {
1308 return m_state.m_function_objects;
1309 }
1310
1311 std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int()
1312 {
1313 return m_state.m_function_objects;
1314 }
1315
1316 const std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() const
1317 {
1318 return m_state.m_functions;
1319 }
1320
1321 std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int()
1322 {
1323 return m_state.m_functions;
1324 }
1325
1326 static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
1327 {
1328
1329 auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
1330 auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
1331
1332 if (dynamic_lhs && dynamic_rhs)
1333 {
1334 if (dynamic_lhs->get_guard())
1335 {
1336 return dynamic_rhs->get_guard() ? false : true;
1337 } else {
1338 return false;
1339 }
1340 }
1341
1342 if (dynamic_lhs && !dynamic_rhs)
1343 {
1344 return false;
1345 }
1346
1347 if (!dynamic_lhs && dynamic_rhs)
1348 {
1349 return true;
1350 }
1351
1352 const auto &lhsparamtypes = lhs->get_param_types();
1353 const auto &rhsparamtypes = rhs->get_param_types();
1354
1355 const auto lhssize = lhsparamtypes.size();
1356 const auto rhssize = rhsparamtypes.size();
1357
1358 static const auto boxed_type = user_type<Boxed_Value>();
1359 static const auto boxed_pod_type = user_type<Boxed_Number>();
1360
1361 for (size_t i = 1; i < lhssize && i < rhssize; ++i)
1362 {
1363 const Type_Info &lt = lhsparamtypes[i];
1364 const Type_Info &rt = rhsparamtypes[i];
1365
1366 if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
1367 {
1368 continue; // The first two types are essentially the same, next iteration
1369 }
1370
1371 // const is after non-const for the same type
1372 if (lt.bare_equal(rt) && lt.is_const() && !rt.is_const())
1373 {
1374 return false;
1375 }
1376
1377 if (lt.bare_equal(rt) && !lt.is_const())
1378 {
1379 return true;
1380 }
1381
1382 // boxed_values are sorted last
1383 if (lt.bare_equal(boxed_type))
1384 {
1385 return false;
1386 }
1387
1388 if (rt.bare_equal(boxed_type))
1389 {
1390 return true;
1391 }
1392
1393 if (lt.bare_equal(boxed_pod_type))
1394 {
1395 return false;
1396 }
1397
1398 if (rt.bare_equal(boxed_pod_type))
1399 {
1400 return true;
1401 }
1402
1403 // otherwise, we want to sort by typeid
1404 return lt < rt;
1405 }
1406
1407 return false;
1408 }
1409
1410
1411
1412 template<typename Container, typename Key, typename Value>
1413 static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
1414 {
1415 auto itr = find_keyed_value(t_c, t_key);
1416
1417 if (itr == t_c.end()) {
1418 t_c.reserve(t_c.size() + 1); // tightly control growth of memory usage here
1419 t_c.emplace_back(t_key, std::forward<Value>(t_value));
1420 } else {
1421 typedef typename Container::value_type value_type;
1422 *itr = value_type(t_key, std::forward<Value>(t_value));
1423 }
1424 }
1425
1426 template<typename Container, typename Key>
1427 static typename Container::iterator find_keyed_value(Container &t_c, const Key &t_key)
1428 {
1429 return std::find_if(t_c.begin(), t_c.end(),
1430 [&t_key](const typename Container::value_type &o) {
1431 return o.first == t_key;
1432 });
1433 }
1434
1435 template<typename Container, typename Key>
1436 static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key)
1437 {
1438 return std::find_if(t_c.begin(), t_c.end(),
1439 [&t_key](const typename Container::value_type &o) {
1440 return o.first == t_key;
1441 });
1442 }
1443
1444 template<typename Container, typename Key>
1445 static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
1446 {
1447 if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
1448 return std::next(t_c.begin(), static_cast<typename std::iterator_traits<typename Container::const_iterator>::difference_type>(t_hint));
1449 } else {
1450 return find_keyed_value(t_c, t_key);
1451 }
1452 }
1453
1454
1457 void add_function(const Proxy_Function &t_f, const std::string &t_name)
1458 {
1460
1461 auto &funcs = get_functions_int();
1462
1463 auto itr = find_keyed_value(funcs, t_name);
1464
1465 Proxy_Function new_func =
1466 [&]() -> Proxy_Function {
1467 if (itr != funcs.end())
1468 {
1469 auto vec = *itr->second;
1470 for (const auto &func : vec)
1471 {
1472 if ((*t_f) == *(func))
1473 {
1474 throw chaiscript::exception::name_conflict_error(t_name);
1475 }
1476 }
1477
1478 vec.reserve(vec.size() + 1); // tightly control vec growth
1479 vec.push_back(t_f);
1480 std::stable_sort(vec.begin(), vec.end(), &function_less_than);
1481 itr->second = std::make_shared<std::vector<Proxy_Function>>(vec);
1482 return std::make_shared<Dispatch_Function>(std::move(vec));
1483 } else if (t_f->has_arithmetic_param()) {
1484 // if the function is the only function but it also contains
1485 // arithmetic operators, we must wrap it in a dispatch function
1486 // to allow for automatic arithmetic type conversions
1487 std::vector<Proxy_Function> vec({t_f});
1488 funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(vec));
1489 return std::make_shared<Dispatch_Function>(std::move(vec));
1490 } else {
1491 funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(std::initializer_list<Proxy_Function>({t_f})));
1492 return t_f;
1493 }
1494 }();
1495
1496 add_keyed_value(get_boxed_functions_int(), t_name, const_var(new_func));
1497 add_keyed_value(get_function_objects_int(), t_name, std::move(new_func));
1498 }
1499
1501
1502
1503 Type_Conversions m_conversions;
1504 chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
1505 std::reference_wrapper<parser::ChaiScript_Parser_Base> m_parser;
1506
1507 mutable std::atomic_uint_fast32_t m_method_missing_loc = {0};
1508
1509 State m_state;
1510 };
1511
1513 {
1514 public:
1516 : m_engine(t_engine),
1517 m_stack_holder(t_engine.get_stack_holder()),
1518 m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves())
1519 {
1520 }
1521
1523 return &m_engine.get();
1524 }
1525
1527 return m_engine.get();
1528 }
1529
1531 return m_stack_holder.get();
1532 }
1533
1535 return m_conversions;
1536 }
1537
1539 return m_conversions.saves();
1540 }
1541
1542 Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj) const {
1543 return m_engine.get().add_get_object(t_name, std::move(obj), m_stack_holder.get());
1544 }
1545
1546 void add_object(const std::string &t_name, Boxed_Value obj) const {
1547 return m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
1548 }
1549
1550 Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const {
1551 return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get());
1552 }
1553
1554 private:
1555 std::reference_wrapper<Dispatch_Engine> m_engine;
1556 std::reference_wrapper<Stack_Holder> m_stack_holder;
1557 Type_Conversions_State m_conversions;
1558 };
1559 }
1560}
1561
1562#endif
1563
1564
P func(int c, EveryApi &ev)
Definition test.cpp:59
Env e
Definition Common.cc:2
GameApi::F add_function(GameApi::Env &e, FunctionImpl &f)
Definition GameApi_dep_add_find.cc:1131
std::vector< Item * > functions()
Definition accel.cc:335
Represents any numeric type, generically. Used internally for generic operations between POD values.
Definition boxed_number.hpp:66
A wrapper for holding any valid C++ type. All types in ChaiScript are Boxed_Value objects.
Definition boxed_value.hpp:28
bool is_const() const noexcept
Definition boxed_value.hpp:235
const chaiscript::detail::Any & get() const noexcept
Definition boxed_value.hpp:286
const Type_Info & get_type_info() const noexcept
Definition boxed_value.hpp:224
Holds a collection of ChaiScript settings which can be applied to the ChaiScript runtime....
Definition dispatchkit.hpp:150
Module & add_global_const(Boxed_Value t_bv, std::string t_name)
Definition dispatchkit.hpp:170
Module & add(Type_Info ti, std::string name)
Definition dispatchkit.hpp:152
Module & add(Type_Conversion d)
Definition dispatchkit.hpp:158
void apply(Eval &t_eval, Engine &t_engine) const
Definition dispatchkit.hpp:190
bool has_function(const Proxy_Function &new_f, const std::string &name)
Definition dispatchkit.hpp:199
Module & add(Proxy_Function f, std::string name)
Definition dispatchkit.hpp:164
Module & eval(const std::string &str)
Definition dispatchkit.hpp:183
Definition type_conversions.hpp:512
Definition type_conversions.hpp:321
Compile time deduced information about a type.
Definition type_info.hpp:34
constexpr bool is_const() const noexcept
Definition type_info.hpp:86
std::string bare_name() const
Definition type_info.hpp:103
constexpr bool bare_equal(const Type_Info &ti) const noexcept
Definition type_info.hpp:75
Definition dispatchkit.hpp:438
void add_global_const(const Boxed_Value &obj, const std::string &name)
Adds a new global shared object, between all the threads.
Definition dispatchkit.hpp:551
void new_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
Definition dispatchkit.hpp:1232
void set_locals(const std::map< std::string, Boxed_Value > &t_locals)
Sets all of the locals for the current thread state.
Definition dispatchkit.hpp:857
static void new_stack(Stack_Holder &t_holder)
Pushes a new stack on to the list of stacks.
Definition dispatchkit.hpp:643
static void save_function_params(Stack_Holder &t_s, const std::vector< Boxed_Value > &t_params)
Definition dispatchkit.hpp:1212
void pop_function_call()
Definition dispatchkit.hpp:1262
static void pop_stack(Stack_Holder &t_holder)
Definition dispatchkit.hpp:649
bool is_type(const Boxed_Value &r, const std::string &user_typename) const
return true if the Boxed_Value matches the registered type by name
Definition dispatchkit.hpp:1161
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector< Boxed_Value > &params, bool t_has_params, const Type_Conversions_State &t_conversions)
Definition dispatchkit.hpp:959
void add_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
Definition dispatchkit.hpp:526
decltype(auto) boxed_cast(const Boxed_Value &bv) const
casts an object while applying any Dynamic_Conversion available
Definition dispatchkit.hpp:462
std::map< std::string, Boxed_Value > get_scripting_objects() const
Definition dispatchkit.hpp:869
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector< Boxed_Value > &params, const Type_Conversions_State &t_conversions) const
Definition dispatchkit.hpp:1079
void dump_system() const
Dump all system info to stdout.
Definition dispatchkit.hpp:1142
static void save_function_params(Stack_Holder &t_s, std::vector< Boxed_Value > &&t_params)
Definition dispatchkit.hpp:1204
Boxed_Value get_function_object(const std::string &t_name) const
Definition dispatchkit.hpp:797
void new_scope()
Adds a new scope to the stack.
Definition dispatchkit.hpp:612
void dump_function(const std::pair< const std::string, Proxy_Function > &f) const
Dump function to stdout.
Definition dispatchkit.hpp:1103
State get_state() const
Definition dispatchkit.hpp:1185
std::pair< size_t, Boxed_Value > get_function_object_int(const std::string &t_name, const size_t t_hint) const
Definition dispatchkit.hpp:807
static StackData & get_stack_data(Stack_Holder &t_holder)
Definition dispatchkit.hpp:1279
void save_function_params(const std::vector< Boxed_Value > &t_params)
Definition dispatchkit.hpp:1227
parser::ChaiScript_Parser_Base & get_parser()
Definition dispatchkit.hpp:1289
Stack_Holder & get_stack_holder()
Definition dispatchkit.hpp:1267
std::pair< size_t, std::shared_ptr< std::vector< Proxy_Function > > > get_function(const std::string &t_name, const size_t t_hint) const
Return a function by name.
Definition dispatchkit.hpp:779
void new_function_call()
Definition dispatchkit.hpp:1257
std::shared_ptr< std::vector< Proxy_Function > > get_method_missing_functions() const
Definition dispatchkit.hpp:766
void add_object(const std::string &name, Boxed_Value obj)
Definition dispatchkit.hpp:545
Boxed_Value call_exists(const std::vector< Boxed_Value > &params) const
Definition dispatchkit.hpp:1128
Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
Definition dispatchkit.hpp:454
const StackData & get_stack_data() const
Definition dispatchkit.hpp:1274
std::string get_type_name(const Type_Info &ti) const
Definition dispatchkit.hpp:743
std::vector< std::pair< std::string, Type_Info > > get_types() const
Return all registered types.
Definition dispatchkit.hpp:759
std::vector< std::pair< std::string, Proxy_Function > > get_functions() const
Get a vector of all registered functions.
Definition dispatchkit.hpp:913
void add_global(const Boxed_Value &obj, const std::string &name)
Adds a new global (non-const) shared object, between all the threads.
Definition dispatchkit.hpp:585
void set_global(const Boxed_Value &obj, const std::string &name)
Updates an existing global shared object or adds a new global shared object if not found.
Definition dispatchkit.hpp:598
std::map< std::string, chaiscript::Type_Info > Type_Name_Map
Definition dispatchkit.hpp:441
Boxed_Value & add_get_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
Definition dispatchkit.hpp:506
std::vector< std::pair< std::string, Boxed_Value > > Scope
Definition dispatchkit.hpp:442
Type_Info get_type(const std::string &name, bool t_throw=true) const
Returns the type info for a named type.
Definition dispatchkit.hpp:722
void add(const Type_Conversion &d)
Add a new conversion for upcasting to a base class.
Definition dispatchkit.hpp:469
void set_state(const State &t_state)
Definition dispatchkit.hpp:1192
const Type_Conversions & conversions() const
Definition dispatchkit.hpp:933
void add(Boxed_Value obj, const std::string &name)
Definition dispatchkit.hpp:482
StackData & get_stack_data()
Definition dispatchkit.hpp:1284
static bool is_attribute_call(const std::vector< Proxy_Function > &t_funs, const std::vector< Boxed_Value > &t_params, bool t_has_params, const Type_Conversions_State &t_conversions)
Definition dispatchkit.hpp:938
static void new_scope(Stack_Holder &t_holder)
Adds a new scope to the stack.
Definition dispatchkit.hpp:624
std::map< std::string, Boxed_Value > get_parent_locals() const
Definition dispatchkit.hpp:833
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
Definition dispatchkit.hpp:657
bool function_exists(const std::string &name) const
Return true if a function exists.
Definition dispatchkit.hpp:823
void add(const Proxy_Function &f, const std::string &name)
Add a new named Proxy_Function to the system.
Definition dispatchkit.hpp:475
void save_function_params(std::initializer_list< Boxed_Value > t_params)
Definition dispatchkit.hpp:1217
void save_function_params(std::vector< Boxed_Value > &&t_params)
Definition dispatchkit.hpp:1222
std::string type_name(const Boxed_Value &obj) const
Definition dispatchkit.hpp:1180
void pop_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves)
Definition dispatchkit.hpp:1244
void dump_type(const Type_Info &type) const
Dump type info to stdout.
Definition dispatchkit.hpp:1097
void dump_object(const Boxed_Value &o) const
Dump object info to stdout.
Definition dispatchkit.hpp:1091
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
Adds a new global (non-const) shared object, between all the threads.
Definition dispatchkit.hpp:569
std::map< std::string, Boxed_Value > get_locals() const
Definition dispatchkit.hpp:845
void pop_scope()
Pops the current scope from the stack.
Definition dispatchkit.hpp:618
std::map< std::string, Boxed_Value > get_function_objects() const
Definition dispatchkit.hpp:895
Stack_Holder::StackData StackData
Definition dispatchkit.hpp:443
static void save_function_params(Stack_Holder &t_s, std::initializer_list< Boxed_Value > t_params)
Definition dispatchkit.hpp:1199
void add(const Type_Info &ti, const std::string &name)
Registers a new named type.
Definition dispatchkit.hpp:712
static void pop_scope(Stack_Holder &t_holder)
Pops the current scope from the stack.
Definition dispatchkit.hpp:631
std::vector< Const_Proxy_Function > get_contained_functions() const override
Definition dispatchkit.hpp:289
bool operator==(const dispatch::Proxy_Function_Base &rhs) const override
Definition dispatchkit.hpp:279
bool call_match(const std::vector< Boxed_Value > &vals, const Type_Conversions_State &t_conversions) const override
Definition dispatchkit.hpp:315
Dispatch_Function(std::vector< Proxy_Function > t_funcs)
Definition dispatchkit.hpp:273
Boxed_Value do_call(const std::vector< Boxed_Value > &params, const Type_Conversions_State &t_conversions) const override
Definition dispatchkit.hpp:322
static int calculate_arity(const std::vector< Proxy_Function > &t_funcs)
Definition dispatchkit.hpp:295
Dispatch_Engine & operator*() const
Definition dispatchkit.hpp:1526
Stack_Holder & stack_holder() const
Definition dispatchkit.hpp:1530
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const
Definition dispatchkit.hpp:1550
void add_object(const std::string &t_name, Boxed_Value obj) const
Definition dispatchkit.hpp:1546
const Type_Conversions_State & conversions() const
Definition dispatchkit.hpp:1534
Dispatch_State(Dispatch_Engine &t_engine)
Definition dispatchkit.hpp:1515
Dispatch_Engine * operator->() const
Definition dispatchkit.hpp:1522
Type_Conversions::Conversion_Saves & conversion_saves() const
Definition dispatchkit.hpp:1538
Boxed_Value & add_get_object(const std::string &t_name, Boxed_Value obj) const
Definition dispatchkit.hpp:1542
Definition dynamic_object.hpp:44
Definition proxy_functions.hpp:196
Proxy_Function_Base(std::vector< Type_Info > t_types, int t_arity)
Definition proxy_functions.hpp:279
Thrown in the event that a Boxed_Value cannot be cast to the desired type.
Definition bad_boxed_cast.hpp:34
Exception thrown in the case that a method dispatch fails because no matching function was found.
Definition proxy_functions.hpp:814
Exception thrown in the case that a non-const object was added as a shared object.
Definition dispatchkit.hpp:134
global_non_const() noexcept
Definition dispatchkit.hpp:136
~global_non_const() noexcept override=default
global_non_const(const global_non_const &)=default
Exception thrown if a function's guard fails.
Definition proxy_functions.hpp:327
illegal_name_error(const illegal_name_error &)=default
illegal_name_error(const std::string &t_name) noexcept
Definition dispatchkit.hpp:89
std::string name() const
Definition dispatchkit.hpp:98
~illegal_name_error() noexcept override=default
Exception thrown in the case that an object name is invalid because it already exists in current cont...
Definition dispatchkit.hpp:110
name_conflict_error(const std::string &t_name) noexcept
Definition dispatchkit.hpp:112
~name_conflict_error() noexcept override=default
name_conflict_error(const name_conflict_error &)=default
std::string name() const
Definition dispatchkit.hpp:121
reserved_word_error(const reserved_word_error &)=default
reserved_word_error(const std::string &t_word) noexcept
Definition dispatchkit.hpp:67
~reserved_word_error() noexcept override=default
std::string word() const
Definition dispatchkit.hpp:76
Definition chaiscript_common.hpp:623
void function(void)
Definition memory_leak_test.cpp:26
d
Definition meshpage.php:3895
iVBORw0KGgoAAAANSUhEUgAAANcAAAB5CAMAAACdtUQZAAAA51BMVEX</div ></div >< div style="padding: 0px 0px; width: 1324px;">< div style="height: 400px; width: 1324px;"></div >< div itemscope itemtype="https: </div><div itemscope itemtype="https:</div >< div itemscope itemtype="https: </div></div><p><div style="padding:0px 0px;width:1324px;"><div></div><div itemscope itemtype="https:< ul >< li >< b > Application name
8AkrcAgqgAs9wqQ0ey2tkAo8gAuuQfeI4hPUH09fXHy8z4+fng4uNKXF/Lz9BzfoAcgpkQMTUAKjAbOT4Qr9AXhJ8Rl7ktMCwTosA...
Definition meshpage.php:1610
str
Definition meshpage.php:1778
instead of< li > Displaying models works via URL t expect full length movie as the output of this process< li > Different animation models are very limited basically just translate rotate</ul >< h2 > What to do if your hosting location has no php</h2 >< ul >< li > comment out or remove display php lines at the beginning< li > you will lose threads too< li > every zip file distributed by meshpage org has one of those display php files with this issue</ul >< h2 > What should I do to serve the files via http</h2 > if I got display how do I embed it to my article</h2 > & lt
Definition meshpage_bootstrap.php:1019
not_this_one begin(...)
std::unique_lock< T > shared_lock
Definition chaiscript_threading.hpp:52
std::mutex shared_mutex
Definition chaiscript_threading.hpp:58
std::unique_lock< T > unique_lock
Definition chaiscript_threading.hpp:49
Classes and functions reserved for internal use. Items in this namespace are not supported.
Classes and functions specific to the runtime dispatch side of ChaiScript. Some items may be of use t...
Definition callable_traits.hpp:13
Boxed_Value dispatch(const Funcs &funcs, const std::vector< Boxed_Value > &plist, const Type_Conversions_State &t_conversions)
Definition proxy_functions.hpp:936
Classes which may be thrown during error cases when ChaiScript is executing.
Definition bad_boxed_cast.hpp:27
Classes and functions used during the parsing process.
Definition dispatchkit.hpp:44
Namespace chaiscript contains every API call that the average user will be concerned with.
std::shared_ptr< dispatch::Proxy_Function_Base > Proxy_Function
Common typedef used for passing of any registered function in ChaiScript.
Definition proxy_functions.hpp:317
std::shared_ptr< const dispatch::Proxy_Function_Base > Const_Proxy_Function
Const version of Proxy_Function. Points to a const Proxy_Function. This is how most registered functi...
Definition proxy_functions.hpp:321
constexpr Type_Info user_type(const T &)
Creates a Type_Info object representing the type passed in.
Definition type_info.hpp:221
decltype(auto) boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions=nullptr)
Function for extracting a value stored in a Boxed_Value object.
Definition boxed_cast.hpp:76
Proxy_Function fun(const T &t)
Creates a new Proxy_Function object from a free function, member function or data member.
Definition register_function.hpp:43
std::shared_ptr< chaiscript::detail::Type_Conversion_Base > Type_Conversion
Definition type_conversions.hpp:538
Boxed_Value var(T &&t)
Creates a Boxed_Value. If the object passed in is a value type, it is copied. If it is a pointer,...
Definition boxed_value.hpp:387
std::shared_ptr< Module > ModulePtr
Convenience typedef for Module objects to be added to the ChaiScript runtime.
Definition dispatchkit.hpp:263
Boxed_Value const_var(const T &t)
Takes an object and returns an immutable Boxed_Value. If the object is a std::reference or pointer ty...
Definition boxed_value.hpp:461
STL namespace.
double f(const std::string &, double, bool) noexcept
Definition profile_cpp_calls_2.cpp:4
Definition GameApi.h:42
Definition type_conversions.hpp:324
std::vector< Boxed_Value > saves
Definition type_conversions.hpp:326
Definition dispatchkit.hpp:446
Type_Name_Map m_types
Definition dispatchkit.hpp:451
std::vector< std::pair< std::string, Proxy_Function > > m_function_objects
Definition dispatchkit.hpp:448
std::map< std::string, Boxed_Value > m_global_objects
Definition dispatchkit.hpp:450
std::vector< std::pair< std::string, Boxed_Value > > m_boxed_functions
Definition dispatchkit.hpp:449
std::vector< std::pair< std::string, std::shared_ptr< std::vector< Proxy_Function > > > > m_functions
Definition dispatchkit.hpp:447
static constexpr Type_Info get()
Definition type_info.hpp:138
Definition dispatchkit.hpp:382
SmallVector< StackData > Stacks
Definition dispatchkit.hpp:392
SmallVector< Scope > StackData
Definition dispatchkit.hpp:391
SmallVector< Call_Param_List > Call_Params
Definition dispatchkit.hpp:394
void push_call_params()
Definition dispatchkit.hpp:414
void push_stack()
Definition dispatchkit.hpp:408
std::vector< T > SmallVector
Definition dispatchkit.hpp:387
SmallVector< Boxed_Value > Call_Param_List
Definition dispatchkit.hpp:393
SmallVector< std::pair< std::string, Boxed_Value > > Scope
Definition dispatchkit.hpp:390
void push_stack_data()
Definition dispatchkit.hpp:402
Call_Params call_params
Definition dispatchkit.hpp:430
Stacks stacks
Definition dispatchkit.hpp:429
int call_depth
Definition dispatchkit.hpp:432
Stack_Holder()
Definition dispatchkit.hpp:396
Definition dynamic_object.hpp:31
Definition proxy_functions_detail.hpp:42