support global functions (no overload)
parent
74f80fea4f
commit
338c73669e
|
@ -0,0 +1,35 @@
|
|||
#include "FullyOverloadedFunction.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace wrap {
|
||||
const std::array<std::string, 2> FullyOverloadedFunction::pythonKeywords{
|
||||
{"print", "lambda"}};
|
||||
|
||||
/* ************************************************************************* */
|
||||
std::string FullyOverloadedFunction::pyx_functionCall(
|
||||
const std::string& caller,
|
||||
const std::string& funcName, size_t iOverload) const {
|
||||
|
||||
string ret;
|
||||
if (!returnVals_[iOverload].isPair && !returnVals_[iOverload].type1.isPtr &&
|
||||
returnVals_[iOverload].type1.isNonBasicType()) {
|
||||
ret = returnVals_[iOverload].type1.shared_pxd_class_in_pyx() + "(new " +
|
||||
returnVals_[iOverload].type1.pxd_class_in_pyx() + "(";
|
||||
}
|
||||
|
||||
// actual function call ...
|
||||
if (!caller.empty()) ret += caller + ".";
|
||||
ret += funcName;
|
||||
if (templateArgValue_) ret += "[" + templateArgValue_->pxd_class_in_pyx() + "]";
|
||||
//... with argument list
|
||||
ret += "(" + argumentList(iOverload).pyx_asParams() + ")";
|
||||
|
||||
if (!returnVals_[iOverload].isPair && !returnVals_[iOverload].type1.isPtr &&
|
||||
returnVals_[iOverload].type1.isNonBasicType())
|
||||
ret += "))";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "OverloadedFunction.h"
|
||||
#include <array>
|
||||
|
||||
namespace wrap {
|
||||
|
||||
|
@ -116,6 +117,19 @@ public:
|
|||
return first;
|
||||
}
|
||||
|
||||
// emit cython pyx function call
|
||||
std::string pyx_functionCall(const std::string& caller, const std::string& funcName,
|
||||
size_t iOverload) const;
|
||||
|
||||
/// Cython: Rename functions which names are python keywords
|
||||
static const std::array<std::string, 2> pythonKeywords;
|
||||
static std::string pyRename(const std::string& name) {
|
||||
if (std::find(pythonKeywords.begin(), pythonKeywords.end(), name) ==
|
||||
pythonKeywords.end())
|
||||
return name;
|
||||
else
|
||||
return name + "_";
|
||||
}
|
||||
};
|
||||
|
||||
// Templated checking functions
|
||||
|
|
|
@ -16,11 +16,12 @@ using namespace std;
|
|||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::addOverload(const Qualified& overload,
|
||||
const ArgumentList& args, const ReturnValue& retVal,
|
||||
const ArgumentList& args, const ReturnValue& retVal, const std::string& _includeFile,
|
||||
boost::optional<const Qualified> instName, bool verbose) {
|
||||
FullyOverloadedFunction::addOverload(overload.name(), args, retVal, instName,
|
||||
verbose);
|
||||
overloads.push_back(overload);
|
||||
includeFile = _includeFile;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
@ -131,6 +132,47 @@ void GlobalFunction::python_wrapper(FileWriter& wrapperFile) const {
|
|||
wrapperFile.oss << "def(\"" << name_ << "\", " << name_ << ");\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::emit_cython_pxd(FileWriter& file) const {
|
||||
file.oss << "cdef extern from \"" << includeFile << "\" namespace \""
|
||||
<< overloads[0].qualifiedNamespaces("::")
|
||||
<< "\":" << endl;
|
||||
for (size_t i = 0; i < nrOverloads(); ++i) {
|
||||
file.oss << "\t\t";
|
||||
returnVals_[i].emit_cython_pxd(file, "");
|
||||
file.oss << pyRename(name_) + " \"" + overloads[0].qualifiedName("::") +
|
||||
"\"(";
|
||||
argumentList(i).emit_cython_pxd(file, "");
|
||||
file.oss << ")";
|
||||
file.oss << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::emit_cython_pyx(FileWriter& file) const {
|
||||
string funcName = pyRename(name_);
|
||||
|
||||
// Function definition
|
||||
file.oss << "def " << funcName;
|
||||
// modify name of function instantiation as python doesn't allow overloads
|
||||
// e.g. template<T={A,B,C}> funcName(...) --> funcNameA, funcNameB, funcNameC
|
||||
if (templateArgValue_) file.oss << templateArgValue_->name();
|
||||
// funtion arguments
|
||||
file.oss << "(";
|
||||
argumentList(0).emit_cython_pyx(file);
|
||||
file.oss << "):\n";
|
||||
|
||||
/// Call cython corresponding function and return
|
||||
string ret = pyx_functionCall("pxd", funcName, 0);
|
||||
if (!returnVals_[0].isVoid()) {
|
||||
file.oss << "\tcdef " << returnVals_[0].pyx_returnType()
|
||||
<< " ret = " << ret << "\n";
|
||||
file.oss << "\treturn " << returnVals_[0].pyx_casting("ret") << "\n";
|
||||
} else {
|
||||
file.oss << "\t" << ret << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -28,10 +28,11 @@ namespace wrap {
|
|||
struct GlobalFunction: public FullyOverloadedFunction {
|
||||
|
||||
std::vector<Qualified> overloads; ///< Stack of qualified names
|
||||
std::string includeFile;
|
||||
|
||||
// adds an overloaded version of this function,
|
||||
void addOverload(const Qualified& overload, const ArgumentList& args,
|
||||
const ReturnValue& retVal, boost::optional<const Qualified> instName =
|
||||
const ReturnValue& retVal, const std::string& _includeFile = "", boost::optional<const Qualified> instName =
|
||||
boost::none, bool verbose = false);
|
||||
|
||||
void verifyArguments(const std::vector<std::string>& validArgs) const {
|
||||
|
@ -50,6 +51,10 @@ struct GlobalFunction: public FullyOverloadedFunction {
|
|||
// emit python wrapper
|
||||
void python_wrapper(FileWriter& wrapperFile) const;
|
||||
|
||||
// emit cython wrapper
|
||||
void emit_cython_pxd(FileWriter& pxdFile) const;
|
||||
void emit_cython_pyx(FileWriter& pyxFile) const;
|
||||
|
||||
private:
|
||||
|
||||
// Creates a single global function - all in same namespace
|
||||
|
@ -67,12 +72,15 @@ struct GlobalFunctionGrammar: public classic::grammar<GlobalFunctionGrammar> {
|
|||
|
||||
GlobalFunctions& global_functions_; ///< successful parse will be placed in here
|
||||
std::vector<std::string>& namespaces_;
|
||||
std::string& includeFile;
|
||||
|
||||
/// Construct type grammar and specify where result is placed
|
||||
GlobalFunctionGrammar(GlobalFunctions& global_functions,
|
||||
std::vector<std::string>& namespaces) :
|
||||
global_functions_(global_functions), namespaces_(namespaces) {
|
||||
}
|
||||
std::vector<std::string>& namespaces,
|
||||
std::string& includeFile)
|
||||
: global_functions_(global_functions),
|
||||
namespaces_(namespaces),
|
||||
includeFile(includeFile) {}
|
||||
|
||||
/// Definition of type grammar
|
||||
template<typename ScannerT>
|
||||
|
@ -101,16 +109,16 @@ struct GlobalFunctionGrammar: public classic::grammar<GlobalFunctionGrammar> {
|
|||
globalFunctionName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')];
|
||||
|
||||
// parse a global function
|
||||
global_function_p = (returnValue_g
|
||||
>> globalFunctionName_p[assign_a(globalFunction.name_)]
|
||||
>> argumentList_g >> ';' >> *comments_p) //
|
||||
[assign_a(globalFunction.namespaces_, self.namespaces_)][bl::bind(
|
||||
global_function_p = (returnValue_g >> globalFunctionName_p[assign_a(
|
||||
globalFunction.name_)] >>
|
||||
argumentList_g >> ';' >> *comments_p) //
|
||||
[assign_a(globalFunction.namespaces_, self.namespaces_)] //
|
||||
[bl::bind(
|
||||
&GlobalFunction::addOverload,
|
||||
bl::var(self.global_functions_)[bl::var(globalFunction.name_)],
|
||||
bl::var(globalFunction), bl::var(args), bl::var(retVal),
|
||||
boost::none, verbose)] //
|
||||
bl::var(globalFunction), bl::var(args), bl::var(retVal), bl::var(self.includeFile),
|
||||
boost::none, verbose)] //
|
||||
[assign_a(retVal, retVal0)][clear_a(globalFunction)][clear_a(args)];
|
||||
|
||||
}
|
||||
|
||||
classic::rule<ScannerT> const& start() const {
|
||||
|
|
|
@ -28,17 +28,6 @@
|
|||
using namespace std;
|
||||
using namespace wrap;
|
||||
|
||||
/* ************************************************************************* */
|
||||
/// Cython: Rename functions which names are python keywords
|
||||
static const std::array<std::string, 2> pythonKeywords{{"print", "lambda"}};
|
||||
static std::string pyRename(const std::string& name) {
|
||||
if (std::find(pythonKeywords.begin(), pythonKeywords.end(), name) ==
|
||||
pythonKeywords.end())
|
||||
return name;
|
||||
else
|
||||
return name + "_";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
bool Method::addOverload(Str name, const ArgumentList& args,
|
||||
const ReturnValue& retVal, bool is_const,
|
||||
|
|
|
@ -138,28 +138,3 @@ void MethodBase::python_wrapper(FileWriter& wrapperFile, Str className) const {
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
std::string MethodBase::pyx_functionCall(
|
||||
const std::string& caller,
|
||||
const std::string& funcName, size_t iOverload) const {
|
||||
|
||||
string ret;
|
||||
if (!returnVals_[iOverload].isPair && !returnVals_[iOverload].type1.isPtr &&
|
||||
returnVals_[iOverload].type1.isNonBasicType()) {
|
||||
ret = returnVals_[iOverload].type1.shared_pxd_class_in_pyx() + "(new " +
|
||||
returnVals_[iOverload].type1.pxd_class_in_pyx() + "(";
|
||||
}
|
||||
|
||||
// actual function call ...
|
||||
ret += caller + "." + funcName;
|
||||
if (templateArgValue_) ret += "[" + templateArgValue_->pxd_class_in_pyx() + "]";
|
||||
//... with argument list
|
||||
ret += "(" + argumentList(iOverload).pyx_asParams() + ")";
|
||||
|
||||
if (!returnVals_[iOverload].isPair && !returnVals_[iOverload].type1.isPtr &&
|
||||
returnVals_[iOverload].type1.isNonBasicType())
|
||||
ret += "))";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -54,10 +54,6 @@ struct MethodBase : public FullyOverloadedFunction {
|
|||
// emit python wrapper
|
||||
void python_wrapper(FileWriter& wrapperFile, Str className) const;
|
||||
|
||||
// emit cython pyx function call
|
||||
std::string pyx_functionCall(const std::string& caller, const std::string& funcName,
|
||||
size_t iOverload) const;
|
||||
|
||||
protected:
|
||||
virtual void proxy_header(FileWriter& proxyFile) const = 0;
|
||||
|
||||
|
|
|
@ -149,7 +149,8 @@ void Module::parseMarkup(const std::string& data) {
|
|||
bl::var(newType), bl::var(currentInclude))];
|
||||
|
||||
// Create grammar for global functions
|
||||
GlobalFunctionGrammar global_function_g(global_functions,namespaces);
|
||||
GlobalFunctionGrammar global_function_g(global_functions, namespaces,
|
||||
currentInclude);
|
||||
|
||||
Rule include_p = str_p("#include") >> ch_p('<') >>
|
||||
(*(anychar_p - '>'))[push_back_a(includes)]
|
||||
|
@ -364,6 +365,11 @@ void Module::emit_cython_pxd(FileWriter& pxdFile) const {
|
|||
}
|
||||
pxdFile.oss << "\n\n";
|
||||
}
|
||||
|
||||
//... wrap global functions
|
||||
for(const GlobalFunctions::value_type& p: global_functions)
|
||||
p.second.emit_cython_pxd(pxdFile);
|
||||
|
||||
pxdFile.emit(true);
|
||||
}
|
||||
|
||||
|
@ -387,6 +393,9 @@ void Module::emit_cython_pyx(FileWriter& pyxFile) const {
|
|||
for(const Class& cls: expandedClasses)
|
||||
cls.emit_cython_pyx(pyxFile, expandedClasses);
|
||||
pyxFile.oss << "\n";
|
||||
//... wrap global functions
|
||||
for(const GlobalFunctions::value_type& p: global_functions)
|
||||
p.second.emit_cython_pyx(pyxFile);
|
||||
pyxFile.emit(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@ struct ReturnType : public Qualified {
|
|||
throw DependencyMissing(key, "checking return type of " + s);
|
||||
}
|
||||
|
||||
/// @param className the actual class name to use when "This" is specified
|
||||
void emit_cython_pxd(FileWriter& file, const std::string& className) const;
|
||||
|
||||
std::string pyx_returnType(bool addShared = true) const;
|
||||
std::string pyx_casting(const std::string& var,
|
||||
bool isSharedVar = true) const;
|
||||
|
|
|
@ -71,6 +71,7 @@ struct ReturnValue {
|
|||
|
||||
void emit_matlab(FileWriter& proxyFile) const;
|
||||
|
||||
/// @param className the actual class name to use when "This" is specified
|
||||
void emit_cython_pxd(FileWriter& file, const std::string& className) const;
|
||||
std::string pyx_returnType() const;
|
||||
std::string pyx_casting(const std::string& var) const;
|
||||
|
|
Loading…
Reference in New Issue