Index: compiled/bindings/generator.cpp |
=================================================================== |
--- a/compiled/bindings/generator.cpp |
+++ b/compiled/bindings/generator.cpp |
@@ -18,16 +18,44 @@ |
#include <cstdio> |
#include "generator.h" |
#include "library.h" |
namespace |
{ |
std::vector<bindings_internal::ClassInfo> classes; |
+ std::vector<bindings_internal::NamespaceInfo> namespaces; |
+ |
+ void printProperties(const bindings_internal::Properties& properties) |
+ { |
+ for (const auto& property : properties) |
+ { |
+ if (property.jsValue.empty()) |
+ { |
+ printf("get %s%s,\n", property.name.c_str(), |
+ wrapCall(property.getter, false).c_str()); |
+ if (!property.setter.empty()) |
+ { |
+ printf("set %s%s,\n", property.name.c_str(), |
+ wrapCall(property.setter, false).c_str()); |
+ } |
+ } |
+ else |
+ printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str()); |
+ } |
+ } |
+ |
+ void printMethods(const bindings_internal::Methods& methods, |
+ bool instanceOnly = true) |
+ { |
+ for (const auto& method : methods) |
+ if (!instanceOnly || method.call.instance_function) |
+ printf("%s: %s,\n", method.name.c_str(), wrapCall(method.call).c_str()); |
+ } |
} |
namespace bindings_internal |
{ |
FunctionInfo::FunctionInfo() |
{ |
} |
@@ -185,16 +213,61 @@ namespace bindings_internal |
throw std::runtime_error("More than one subclass differentiator defined for class " + classInfo->name); |
DifferentiatorInfo differentiatorInfo; |
differentiatorInfo.offset = offset; |
differentiatorInfo.mapping = mapping; |
classInfo->subclass_differentiator = differentiatorInfo; |
} |
+ NamespaceInfo* find_namespace(const char* namespaceName) |
+ { |
+ for (auto& namespaceInfo : namespaces) |
+ if (namespaceInfo.name == namespaceName) |
+ return &namespaceInfo; |
+ return nullptr; |
+ } |
+ |
+ void register_namespace(const char* name) |
+ { |
+ if (find_namespace(name)) |
+ throw std::runtime_error(std::string("Duplicate definition for namespace ") + name); |
+ |
+ NamespaceInfo namespaceInfo; |
+ namespaceInfo.name = name; |
+ namespaces.push_back(namespaceInfo); |
+ } |
+ |
+ void register_namespace_property(const char* namespaceName, const char* name, |
+ const FunctionInfo& getter, const FunctionInfo& setter) |
+ { |
+ NamespaceInfo* namespaceInfo = find_namespace(namespaceName); |
+ if (!namespaceInfo) |
+ throw std::runtime_error(std::string("Property defined on unknown namespace: ") + name); |
+ |
+ PropertyInfo propertyInfo; |
+ propertyInfo.name = name; |
+ propertyInfo.getter = getter; |
+ propertyInfo.setter = setter; |
+ namespaceInfo->properties.push_back(propertyInfo); |
+ } |
+ |
+ void register_namespace_method(const char* namespaceName, const char* name, |
+ const FunctionInfo& call) |
+ { |
+ NamespaceInfo* namespaceInfo = find_namespace(namespaceName); |
+ if (!namespaceInfo) |
+ throw std::runtime_error(std::string("Method defined on unknown namespace: ") + name); |
+ |
+ MethodInfo methodInfo; |
+ methodInfo.name = name; |
+ methodInfo.call = call; |
+ namespaceInfo->methods.push_back(methodInfo); |
+ } |
+ |
std::string generateCall(const FunctionInfo& call, |
std::vector<std::string>& params) |
{ |
if (call.returnType == TypeCategory::DEPENDENT_STRING || |
call.returnType == TypeCategory::OWNED_STRING) |
{ |
params.insert(params.begin(), "string"); |
} |
@@ -278,17 +351,17 @@ namespace bindings_internal |
prefix += argName; |
if (call.args[i] == TypeCategory::STRING_REF) |
{ |
hasStringArgs = true; |
params.push_back(std::string("createString(") + argName + ")"); |
} |
else if (call.args[i] == TypeCategory::CLASS_PTR) |
- params.push_back(argName + "._pointer"); |
+ params.push_back(argName + " ? " + argName + "._pointer : 0"); |
else if (call.args[i] == TypeCategory::INT64) |
{ |
// 64-bit integers are passed as two integer parameters |
params.push_back(argName + " >>> 0"); |
params.push_back(argName + " / 0x100000000 >>> 0"); |
} |
else |
params.push_back(argName); |
@@ -362,50 +435,29 @@ namespace bindings_internal |
return result; |
} |
)"); |
} |
void printClass(const ClassInfo& cls) |
{ |
// Begin class definition |
- |
ClassInfo* baseClass = find_class(cls.baseClass); |
printf("exports.%s = createClass(%s, %i, {\n", cls.name.c_str(), |
(baseClass ? ("exports." + baseClass->name).c_str() : "null"), |
cls.ref_counted_offset); |
// Print prototype members |
- |
- for (const auto& property : cls.properties) |
- { |
- if (property.jsValue.empty()) |
- { |
- printf("get %s%s,\n", property.name.c_str(), |
- wrapCall(property.getter, false).c_str()); |
- if (!property.setter.empty()) |
- { |
- printf("set %s%s,\n", property.name.c_str(), |
- wrapCall(property.setter, false).c_str()); |
- } |
- } |
- else |
- printf("%s: %s,\n", property.name.c_str(), property.jsValue.c_str()); |
- } |
- |
- for (const auto& method : cls.methods) |
- if (method.call.instance_function) |
- printf("%s: %s,\n", method.name.c_str(), wrapCall(method.call).c_str()); |
+ printProperties(cls.properties); |
+ printMethods(cls.methods); |
// End class definition |
- |
printf("});\n"); |
// Print static members |
- |
DifferentiatorInfo differentiator = cls.subclass_differentiator; |
if (differentiator.offset != SIZE_MAX) |
{ |
printf("var %s_mapping = \n", cls.name.c_str()); |
puts("{"); |
for (const auto& item : differentiator.mapping) |
printf(" %i: '%s',\n", item.first, item.second.c_str()); |
puts("};"); |
@@ -430,17 +482,27 @@ namespace bindings_internal |
{ |
if (!method.call.instance_function) |
{ |
printf("exports.%s.%s = %s;\n", cls.name.c_str(), method.name.c_str(), |
wrapCall(method.call).c_str()); |
} |
} |
} |
+ |
+ void printNamespace(const NamespaceInfo& namespaceInfo) |
+ { |
+ printf("exports.%s = {\n", namespaceInfo.name.c_str()); |
+ printProperties(namespaceInfo.properties); |
+ printMethods(namespaceInfo.methods, false); |
+ puts("};"); |
+ } |
} |
void printBindings() |
{ |
bindings_internal::printHelpers(); |
for (const auto& item : classes) |
bindings_internal::printClass(item); |
+ for (const auto& item : namespaces) |
+ bindings_internal::printNamespace(item); |
} |