FIX: python import
[Tsunagari.git] / src / scriptinst.cpp
blobb0a6618e513ac9654db0dac027ce240fb6903184
1 /*********************************
2 ** Tsunagari Tile Engine **
3 ** scriptinst.cpp **
4 ** Copyright 2011-2012 OmegaSDG **
5 *********************************/
7 // "OmegaSDG" is defined as Michael D. Reiley and Paul Merrill.
9 // **********
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to
12 // deal in the Software without restriction, including without limitation the
13 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14 // sell copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 // IN THE SOFTWARE.
27 // **********
29 // from Python
30 #include <import.h>
32 #include "log.h"
33 #include "python.h"
34 #include "reader.h"
35 #include "scriptinst.h"
38 struct validate_visitor : public boost::static_visitor<bool>
40 bool operator()(BytecodeRef bc) const
42 if (!bc) {
43 Log::err("ScriptInst", "<null script>: script not valid");
44 return false;
46 if (!bc->valid()) {
47 Log::err("ScriptInst", bc->filename() +
48 ": script not valid");
49 return false;
51 return true;
54 bool operator()(boost::python::object) const
56 return true;
61 struct invoke_visitor : public boost::static_visitor<bool>
63 bool operator()(BytecodeRef bc) const
65 return (bc && bc->valid()) ? bc->execute() : false;
68 bool operator()(boost::python::object callable) const
70 try {
71 inPythonScript++;
72 callable();
73 inPythonScript--;
74 return true;
75 } catch (boost::python::error_already_set) {
76 inPythonScript--;
77 // XXX: How does this interact with a C++/Python callstack?
78 //Log::err("Python", "Originating from " + source + ":");
79 pythonErr();
80 return false;
87 ScriptInst::ScriptInst(const std::string& source)
88 : data(Reader::getBytecode(source))
90 if (!validate()) {
91 Log::err("ScriptInst", "Error loading " + source);
96 ScriptInst::ScriptInst(boost::python::object callable)
97 : data(callable)
102 bool ScriptInst::validate()
104 return boost::apply_visitor(validate_visitor(), data);
108 bool ScriptInst::invoke()
110 return boost::apply_visitor(invoke_visitor(), data);
114 struct topython_visitor : public boost::static_visitor<PyObject*>
116 PyObject* operator()(BytecodeRef bc) const
118 boost::python::object str;
119 if (bc)
120 str = boost::python::object(bc->filename());
121 else
122 str = boost::python::object("");
123 return boost::python::incref(str.ptr());
126 PyObject* operator()(boost::python::object callable) const
128 return boost::python::incref(callable.ptr());
133 struct scriptinst_to_python
135 static PyObject* convert(ScriptInst script)
137 return boost::apply_visitor(topython_visitor(), script.data);
142 struct scriptinst_from_python
144 scriptinst_from_python()
146 boost::python::converter::registry::push_back(
147 &convertible,
148 &construct,
149 boost::python::type_id<ScriptInst>());
152 // Can this be converted to a ScriptInst?
153 static void* convertible(PyObject* obj)
155 //bool callable = obj->ob_type->tp_call != NULL;
156 //const char* tp_name = obj->ob_type->tp_name;
157 // XXX: Return non-NULL only if string or
158 // callable (fn or lambda?).
159 return obj;
162 // Convert. boost::python provides us with a chunch of memory that we
163 // have to construct in-place.
164 static void construct(
165 PyObject* obj,
166 boost::python::converter::rvalue_from_python_stage1_data* data)
168 // Prevent compilation name collisions with "object" by making
169 // it "bp::object".
170 namespace bp = boost::python;
172 void* storage =
173 ((bp::converter::rvalue_from_python_storage<ScriptInst>*)data)
174 ->storage.bytes;
176 if (PyString_Check(obj)) {
177 const char* value = PyString_AsString(obj);
178 new (storage) ScriptInst(value);
180 else {
181 // By default, the PyObject is a borrowed reference,
182 // which means it hasn't been incref'd.
183 bp::handle<> hndl(bp::borrowed(obj));
184 new (storage) ScriptInst(bp::object(hndl));
187 data->convertible = storage;
192 void exportScriptInst()
194 using namespace boost::python;
196 to_python_converter<ScriptInst, scriptinst_to_python>();
197 scriptinst_from_python();