1 /***************************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 # include <stdio.h> // Mac needs ssize_t defined for pyport.h
41 #include "scriptinst.h"
44 struct validate_visitor
: public boost::static_visitor
<bool>
46 bool operator()(BytecodeRef bc
) const
49 Log::err("ScriptInst", "<null script>: script not valid");
53 Log::err("ScriptInst", bc
->filename() +
54 ": script not valid");
60 bool operator()(boost::python::object
) const
67 struct invoke_visitor
: public boost::static_visitor
<bool>
69 bool operator()(BytecodeRef bc
) const
71 return (bc
&& bc
->valid()) ? bc
->execute() : false;
74 bool operator()(boost::python::object callable
) const
81 } catch (boost::python::error_already_set
) {
83 // XXX: How does this interact with a C++/Python callstack?
84 //Log::err("Python", "Originating from " + source + ":");
93 ScriptInst::ScriptInst(const std::string
& source
)
94 : data(Reader::getBytecode(source
))
97 Log::err("ScriptInst", "Error loading " + source
);
102 ScriptInst::ScriptInst(boost::python::object callable
)
108 bool ScriptInst::validate()
110 return boost::apply_visitor(validate_visitor(), data
);
114 bool ScriptInst::invoke()
116 return boost::apply_visitor(invoke_visitor(), data
);
120 struct topython_visitor
: public boost::static_visitor
<PyObject
*>
122 PyObject
* operator()(BytecodeRef bc
) const
124 boost::python::object str
;
126 str
= boost::python::object(bc
->filename());
128 str
= boost::python::object("");
129 return boost::python::incref(str
.ptr());
132 PyObject
* operator()(boost::python::object callable
) const
134 return boost::python::incref(callable
.ptr());
139 struct scriptinst_to_python
141 static PyObject
* convert(ScriptInst script
)
143 return boost::apply_visitor(topython_visitor(), script
.data
);
148 struct scriptinst_from_python
150 scriptinst_from_python()
152 boost::python::converter::registry::push_back(
155 boost::python::type_id
<ScriptInst
>());
158 // Can this be converted to a ScriptInst?
159 static void* convertible(PyObject
* obj
)
161 //bool callable = obj->ob_type->tp_call != NULL;
162 //const char* tp_name = obj->ob_type->tp_name;
163 // XXX: Return non-NULL only if string or
164 // callable (fn or lambda?).
168 // Convert. boost::python provides us with a chunch of memory that we
169 // have to construct in-place.
170 static void construct(
172 boost::python::converter::rvalue_from_python_stage1_data
* data
)
174 // Prevent compilation name collisions with "object" by making
176 namespace bp
= boost::python
;
179 ((bp::converter::rvalue_from_python_storage
<ScriptInst
>*)data
)
182 if (PyString_Check(obj
)) {
183 const char* value
= PyString_AsString(obj
);
184 new (storage
) ScriptInst(value
);
187 // By default, the PyObject is a borrowed reference,
188 // which means it hasn't been incref'd.
189 bp::handle
<> hndl(bp::borrowed(obj
));
190 new (storage
) ScriptInst(bp::object(hndl
));
193 data
->convertible
= storage
;
198 void exportScriptInst()
200 using namespace boost::python
;
202 to_python_converter
<ScriptInst
, scriptinst_to_python
>();
203 scriptinst_from_python();