Merge branch 'master' into 2011-09-09-CxScript
Conflicts: include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp
This commit is contained in:
commit
a0f7c46cc9
@ -496,28 +496,24 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Swaps out the stack with a new stack
|
|
||||||
* \returns the old stack
|
|
||||||
* \param[in] s The new stack
|
|
||||||
*/
|
|
||||||
Stack set_stack(const Stack &s)
|
|
||||||
{
|
|
||||||
Stack old = m_stack_holder->stack;
|
|
||||||
m_stack_holder->stack = s;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stack new_stack() const
|
/// Pushes a new stack on to the list of stacks
|
||||||
|
void new_stack()
|
||||||
{
|
{
|
||||||
Stack s(new Stack::element_type());
|
Stack s(new Stack::element_type());
|
||||||
s->push_back(Scope());
|
s->push_back(Scope());
|
||||||
return s;
|
m_stack_holder->stacks.push_back(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pop_stack()
|
||||||
|
{
|
||||||
|
m_stack_holder->stacks.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \returns the current stack
|
||||||
Stack get_stack() const
|
Stack get_stack() const
|
||||||
{
|
{
|
||||||
return m_stack_holder->stack;
|
return m_stack_holder->stacks.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -566,8 +562,8 @@ namespace chaiscript
|
|||||||
if (funcs.size() == 1)
|
if (funcs.size() == 1)
|
||||||
{
|
{
|
||||||
// Return the first item if there is only one,
|
// Return the first item if there is only one,
|
||||||
// no reason to take the cast of the extra level of dispatch
|
// no reason to take the cost of the extra level of dispatch
|
||||||
return const_var(*funcs.begin());
|
return const_var(funcs.front());
|
||||||
} else {
|
} else {
|
||||||
return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
return Boxed_Value(Const_Proxy_Function(new Dispatch_Function(funcs)));
|
||||||
}
|
}
|
||||||
@ -668,6 +664,66 @@ namespace chaiscript
|
|||||||
return functions.find(name) != functions.end();
|
return functions.find(name) != functions.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Get a map of all objects that can be seen from the current scope in a scripting context
|
||||||
|
///
|
||||||
|
std::map<std::string, Boxed_Value> get_scripting_objects() const
|
||||||
|
{
|
||||||
|
// We don't want the current context, but one up if it exists
|
||||||
|
StackData &stack = (m_stack_holder->stacks.size()==1)?(*(m_stack_holder->stacks.back())):(*m_stack_holder->stacks[m_stack_holder->stacks.size()-2]);
|
||||||
|
|
||||||
|
std::map<std::string, Boxed_Value> retval;
|
||||||
|
|
||||||
|
// note: map insert doesn't overwrite existing values, which is why this works
|
||||||
|
|
||||||
|
for (StackData::reverse_iterator itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||||
|
{
|
||||||
|
retval.insert(itr->begin(), itr->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the global values
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||||
|
|
||||||
|
retval.insert(m_state.m_global_objects.begin(), m_state.m_global_objects.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Get a map of all functions that can be seen from a scripting context
|
||||||
|
///
|
||||||
|
std::map<std::string, Boxed_Value> get_scripting_functions() const
|
||||||
|
{
|
||||||
|
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, Proxy_Function> > rets;
|
||||||
|
|
||||||
|
const std::map<std::string, std::vector<Proxy_Function> > &functions = get_functions_int();
|
||||||
|
|
||||||
|
std::map<std::string, Boxed_Value> retval;
|
||||||
|
|
||||||
|
for (std::map<std::string, std::vector<Proxy_Function> >::const_iterator itr = functions.begin();
|
||||||
|
itr != functions.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
if (itr->second.size() == 1)
|
||||||
|
{
|
||||||
|
// Return the first item if there is only one,
|
||||||
|
// no reason to take the cost of the extra level of dispatch
|
||||||
|
retval.insert(std::make_pair(itr->first, const_var(itr->second.front())));
|
||||||
|
} else {
|
||||||
|
retval.insert(std::make_pair(itr->first, Boxed_Value(Const_Proxy_Function(new Dispatch_Function(itr->second)))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a vector of all registered functions
|
* Get a vector of all registered functions
|
||||||
*/
|
*/
|
||||||
@ -854,7 +910,7 @@ namespace chaiscript
|
|||||||
*/
|
*/
|
||||||
StackData &get_stack_data() const
|
StackData &get_stack_data() const
|
||||||
{
|
{
|
||||||
return *(m_stack_holder->stack);
|
return *(m_stack_holder->stacks.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
const std::map<std::string, std::vector<Proxy_Function> > &get_functions_int() const
|
||||||
@ -1016,12 +1072,13 @@ namespace chaiscript
|
|||||||
struct Stack_Holder
|
struct Stack_Holder
|
||||||
{
|
{
|
||||||
Stack_Holder()
|
Stack_Holder()
|
||||||
: stack(new StackData())
|
|
||||||
{
|
{
|
||||||
stack->push_back(Scope());
|
Stack s(new StackData());
|
||||||
|
s->push_back(Scope());
|
||||||
|
stacks.push_back(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack stack;
|
std::deque<Stack> stacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||||
|
@ -322,6 +322,29 @@ namespace chaiscript
|
|||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine &m_de;
|
chaiscript::detail::Dispatch_Engine &m_de;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Creates a new scope then pops it on destruction
|
||||||
|
struct Stack_Push_Pop
|
||||||
|
{
|
||||||
|
Stack_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
|
||||||
|
: m_de(t_de)
|
||||||
|
{
|
||||||
|
m_de.new_stack();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Stack_Push_Pop()
|
||||||
|
{
|
||||||
|
m_de.pop_stack();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// explicitly unimplemented copy and assignment
|
||||||
|
Stack_Push_Pop(const Scope_Push_Pop &);
|
||||||
|
Stack_Push_Pop& operator=(const Scope_Push_Pop &);
|
||||||
|
|
||||||
|
chaiscript::detail::Dispatch_Engine &m_de;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,6 +324,8 @@ namespace chaiscript
|
|||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::is_type, std::ref(m_engine)), "is_type");
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::type_name, std::ref(m_engine)), "type_name");
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
|
||||||
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_functions, std::ref(m_engine)), "get_functions");
|
||||||
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
|
||||||
|
|
||||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||||
|
|
||||||
|
@ -191,36 +191,28 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack prev_stack = t_ss.get_stack();
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack new_stack = t_ss.new_stack();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Boxed_Value fn = this->children[0]->eval(t_ss);
|
Boxed_Value fn = this->children[0]->eval(t_ss);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
t_ss.set_stack(new_stack);
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(params);
|
const Boxed_Value &retval = (*boxed_cast<const Const_Proxy_Function &>(fn))(params);
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss);
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss);
|
||||||
}
|
}
|
||||||
catch(detail::Return_Value &rv) {
|
catch(detail::Return_Value &rv) {
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
return rv.retval;
|
return rv.retval;
|
||||||
}
|
}
|
||||||
catch(...) {
|
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
catch(const exception::dispatch_error &e){
|
||||||
|
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
|
||||||
}
|
}
|
||||||
catch(exception::eval_error &) {
|
catch(detail::Return_Value &rv) {
|
||||||
t_ss.set_stack(prev_stack);
|
return rv.retval;
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -485,26 +477,17 @@ namespace chaiscript
|
|||||||
fun_name = this->children[i]->text;
|
fun_name = this->children[i]->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack prev_stack = t_ss.get_stack();
|
|
||||||
chaiscript::detail::Dispatch_Engine::Stack new_stack = t_ss.new_stack();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
t_ss.set_stack(new_stack);
|
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||||
retval = t_ss.call_function(fun_name, params);
|
retval = t_ss.call_function(fun_name, params);
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
}
|
}
|
||||||
catch(const exception::dispatch_error &e){
|
catch(const exception::dispatch_error &e){
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name, e.parameters, t_ss);
|
throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name, e.parameters, t_ss);
|
||||||
}
|
}
|
||||||
catch(detail::Return_Value &rv) {
|
catch(detail::Return_Value &rv) {
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
retval = rv.retval;
|
retval = rv.retval;
|
||||||
}
|
}
|
||||||
catch(...) {
|
|
||||||
t_ss.set_stack(prev_stack);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
if (this->children[i]->identifier == AST_Node_Type::Array_Call) {
|
if (this->children[i]->identifier == AST_Node_Type::Array_Call) {
|
||||||
for (size_t j = 1; j < this->children[i]->children.size(); ++j) {
|
for (size_t j = 1; j < this->children[i]->children.size(); ++j) {
|
||||||
try {
|
try {
|
||||||
|
18
unittests/system_introspection.chai
Normal file
18
unittests/system_introspection.chai
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
var funcs = get_functions();
|
||||||
|
|
||||||
|
assert_true(funcs.size() > 0);
|
||||||
|
assert_true(funcs["to_string"].get_type_info().bare_equal(Function_type));
|
||||||
|
|
||||||
|
|
||||||
|
var i = 1;
|
||||||
|
var objs = get_objects();
|
||||||
|
|
||||||
|
assert_true(objs.size() > 0);
|
||||||
|
assert_true(objs["i"].get_type_info().bare_equal(int_type));
|
||||||
|
assert_true(objs.count("j") == 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user