Generalize ctor overloading.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/oliverb-javascript-v8@13790 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Oliver Buchtala 2012-09-08 01:06:08 +00:00
commit d5c5f7ebee
2 changed files with 65 additions and 40 deletions

View file

@ -188,7 +188,7 @@ void _wrap_$jsmangledname_finalize(JSObjectRef thisObject)
%fragment ("JS_mainctordefn", "templates") %fragment ("JS_mainctordefn", "templates")
%{ %{
JSObjectRef _wrap_create_$jsmangledname(JSContextRef context, JSObjectRef ctorObject, JSObjectRef $jswrapper(JSContextRef context, JSObjectRef ctorObject,
size_t argc, const JSValueRef argv[], JSValueRef* exception) size_t argc, const JSValueRef argv[], JSValueRef* exception)
{ {
JSObjectRef thisObject = NULL; JSObjectRef thisObject = NULL;
@ -204,13 +204,23 @@ JSObjectRef _wrap_create_$jsmangledname(JSContextRef context, JSObjectRef ctorOb
} }
%} %}
%fragment ("JS_veto_ctor", "templates")
%{
JSObjectRef $jsctor(JSContextRef context, JSObjectRef ctorObject,
size_t argc, const JSValueRef argv[], JSValueRef* exception)
{
SWIG_exception(SWIG_ERROR, "Class $jsname can not be instantiated");
return 0;
}
%}
/************************************************************************************** /**************************************************************************************
ctor_dispatch_case: This template is used for the constructor which is overloaded ctor_dispatch_case: This template is used for the constructor which is overloaded
***************************************************************************************/ ***************************************************************************************/
%fragment ("JS_ctor_dispatch_case", "templates") %fragment ("JS_ctor_dispatch_case", "templates")
%{if(argc == $jsargcount) { %{if(argc == $jsargcount) {
thisObject = _wrap_create_$jsmangledname$jsoverloadext(context, NULL, argc, argv, exception); thisObject = $jswrapper(context, NULL, argc, argv, exception);
if(thisObject != NULL) { *exception=0; return thisObject; } /* reset exception and return */ if(thisObject != NULL) { *exception=0; return thisObject; } /* reset exception and return */
} }
%} %}
@ -218,7 +228,7 @@ ctor_dispatch_case: This template is used for the constructor which is overloade
%fragment ("JS_ctordefn", "templates") %fragment ("JS_ctordefn", "templates")
%{ %{
JSObjectRef _wrap_create_$jsmangledname$jsoverloadext(JSContextRef context, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) JSObjectRef $jswrapper(JSContextRef context, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception)
{ {
$jslocals $jslocals
$jscode $jscode
@ -275,7 +285,7 @@ bool $jsname_initialize(JSGlobalContextRef context) {
%fragment ("JS_create_class_template", "templates") %fragment ("JS_create_class_template", "templates")
%{ $jsmangledname_classDefinition.staticFunctions = $jsmangledname_staticFunctions; %{ $jsmangledname_classDefinition.staticFunctions = $jsmangledname_staticFunctions;
$jsmangledname_classDefinition.staticValues = $jsmangledname_staticValues; $jsmangledname_classDefinition.staticValues = $jsmangledname_staticValues;
$jsmangledname_classDefinition.callAsConstructor = _wrap_create_$jsmangledname; $jsmangledname_classDefinition.callAsConstructor = $jsctor;
$jsmangledname_objectDefinition.staticValues = $jsmangledname_values; $jsmangledname_objectDefinition.staticValues = $jsmangledname_values;
$jsmangledname_objectDefinition.staticFunctions = $jsmangledname_functions; $jsmangledname_objectDefinition.staticFunctions = $jsmangledname_functions;
$jsmangledname_objectDefinition.parentClass = $jsbaseclass_classRef; $jsmangledname_objectDefinition.parentClass = $jsbaseclass_classRef;

View file

@ -13,11 +13,14 @@ bool js_template_enable_debug = false;
#define WRAPPER_NAME "wrapper" #define WRAPPER_NAME "wrapper"
#define IS_IMMUTABLE "is_immutable" #define IS_IMMUTABLE "is_immutable"
#define IS_STATIC "is_static" #define IS_STATIC "is_static"
#define IS_ABSTRACT "is_abstract"
#define GETTER "getter" #define GETTER "getter"
#define SETTER "setter" #define SETTER "setter"
#define PARENT "parent" #define PARENT "parent"
#define CTORS "ctors" #define CTOR "ctor"
#define CTOR_WRAPPERS "ctor_wrappers"
#define CTOR_DISPATCHERS "ctor_dispatchers" #define CTOR_DISPATCHERS "ctor_dispatchers"
#define ARGCOUNT "wrap:argc"
// variables used in code templates // variables used in code templates
// ATTENTION: be aware of prefix collisions when defining those variables // ATTENTION: be aware of prefix collisions when defining those variables
@ -26,6 +29,7 @@ bool js_template_enable_debug = false;
#define T_TYPE "$jstype" #define T_TYPE "$jstype"
#define T_TYPE_MANGLED "$jsmangledtype" #define T_TYPE_MANGLED "$jsmangledtype"
#define T_WRAPPER "$jswrapper" #define T_WRAPPER "$jswrapper"
#define T_CTOR "$jsctor"
#define T_GETTER "$jsgetter" #define T_GETTER "$jsgetter"
#define T_SETTER "$jssetter" #define T_SETTER "$jssetter"
#define T_DISPATCH_CASES "$jsdispatchcases" #define T_DISPATCH_CASES "$jsdispatchcases"
@ -737,9 +741,15 @@ int JSEmitter::enterClass(Node *n) {
Delete(type); Delete(type);
state.clazz(TYPE_MANGLED, classtype_mangled); state.clazz(TYPE_MANGLED, classtype_mangled);
state.clazz(CTORS, NewString("")); String *ctor_wrapper = NewString("_wrap_new_veto_");
Append(ctor_wrapper, state.clazz(NAME));
state.clazz(CTOR, ctor_wrapper);
state.clazz(CTOR_DISPATCHERS, NewString("")); state.clazz(CTOR_DISPATCHERS, NewString(""));
// HACK: assume that a class is abstract
// this is resolved by emitCtor (which is only called for non abstract classes)
SetFlag(state.clazz(), IS_ABSTRACT);
return SWIG_OK; return SWIG_OK;
} }
@ -924,6 +934,11 @@ void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, Ma
String *tm; String *tm;
Parm *p; Parm *p;
int num_args = emit_num_arguments(parms);
String *argcount = NewString("");
Printf(argcount, "%d", num_args);
Setattr(n, ARGCOUNT, argcount);
int startIdx = 0; int startIdx = 0;
if (is_member && !is_static) { if (is_member && !is_static) {
startIdx = 1; startIdx = 1;
@ -1104,10 +1119,8 @@ int JSCEmitter::exitFunction(Node *n) {
int JSCEmitter::enterVariable(Node *n) { int JSCEmitter::enterVariable(Node *n) {
JSEmitter::enterVariable(n); JSEmitter::enterVariable(n);
state.variable(GETTER, NULL_STR); state.variable(GETTER, NULL_STR);
state.variable(SETTER, VETO_SET); state.variable(SETTER, VETO_SET);
return SWIG_OK; return SWIG_OK;
} }
@ -1134,7 +1147,6 @@ int JSCEmitter::exitVariable(Node *n) {
int JSCEmitter::enterClass(Node *n) { int JSCEmitter::enterClass(Node *n) {
JSEmitter::enterClass(n); JSEmitter::enterClass(n);
state.clazz(MEMBER_VARIABLES, NewString("")); state.clazz(MEMBER_VARIABLES, NewString(""));
state.clazz(MEMBER_FUNCTIONS, NewString("")); state.clazz(MEMBER_FUNCTIONS, NewString(""));
state.clazz(STATIC_VARIABLES, NewString("")); state.clazz(STATIC_VARIABLES, NewString(""));
@ -1148,7 +1160,6 @@ int JSCEmitter::enterClass(Node *n) {
} }
int JSCEmitter::exitClass(Node *n) { int JSCEmitter::exitClass(Node *n) {
Template t_class_tables(getTemplate("JS_class_tables")); Template t_class_tables(getTemplate("JS_class_tables"));
t_class_tables.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) t_class_tables.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED))
.replace("$jsclassvariables", state.clazz(MEMBER_VARIABLES)) .replace("$jsclassvariables", state.clazz(MEMBER_VARIABLES))
@ -1159,13 +1170,15 @@ int JSCEmitter::exitClass(Node *n) {
/* adds the ctor wrappers at this position */ /* adds the ctor wrappers at this position */
// Note: this is necessary to avoid extra forward declarations. // Note: this is necessary to avoid extra forward declarations.
Append(f_wrappers, state.clazz(CTORS)); //Append(f_wrappers, state.clazz(CTOR_WRAPPERS));
/* adds the main constructor wrapper function */ // for abstract classes add a vetoing ctor
Template t_mainctor(getTemplate("JS_mainctordefn")); if(GetFlag(state.clazz(), IS_ABSTRACT)) {
t_mainctor.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) Template t_veto_ctor(getTemplate("JS_veto_ctor"));
.replace(T_DISPATCH_CASES, state.clazz(CTOR_DISPATCHERS)) t_veto_ctor.replace(T_CTOR, state.clazz(CTOR))
.replace(T_NAME, state.clazz(NAME))
.pretty_print(f_wrappers); .pretty_print(f_wrappers);
}
/* adds a class template statement to initializer function */ /* adds a class template statement to initializer function */
Template t_classtemplate(getTemplate("JS_create_class_template")); Template t_classtemplate(getTemplate("JS_create_class_template"));
@ -1180,6 +1193,7 @@ int JSCEmitter::exitClass(Node *n) {
t_classtemplate.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED)) t_classtemplate.replace(T_NAME_MANGLED, state.clazz(NAME_MANGLED))
.replace(T_TYPE_MANGLED, state.clazz(TYPE_MANGLED)) .replace(T_TYPE_MANGLED, state.clazz(TYPE_MANGLED))
.replace(T_BASECLASS, base_name_mangled) .replace(T_BASECLASS, base_name_mangled)
.replace(T_CTOR, state.clazz(CTOR))
.pretty_print(state.global(INITIALIZER)); .pretty_print(state.global(INITIALIZER));
Delete(base_name_mangled); Delete(base_name_mangled);
@ -1197,15 +1211,18 @@ int JSCEmitter::exitClass(Node *n) {
} }
int JSEmitter::emitCtor(Node *n) { int JSEmitter::emitCtor(Node *n) {
Wrapper *wrapper = NewWrapper(); Wrapper *wrapper = NewWrapper();
Template t_ctor(getTemplate("JS_ctordefn")); Template t_ctor(getTemplate("JS_ctordefn"));
String *mangled_name = SwigType_manglestr(Getattr(n, "name"));
String *overname = Getattr(n, "sym:overname"); //String *mangled_name = SwigType_manglestr(Getattr(n, "name"));
String *wrap_name = Swig_name_wrapper(Getattr(n, "name")); String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
Append(wrap_name, Getattr(n, "sym:overname"));
Setattr(n, "wrap:name", wrap_name); Setattr(n, "wrap:name", wrap_name);
// note: removing the is_abstract flag, as this emitter
// is supposed to be called for non-abstract classes only.
Setattr(state.clazz(), IS_ABSTRACT, 0);
ParmList *params = Getattr(n, "parms"); ParmList *params = Getattr(n, "parms");
emit_parameter_variables(params, wrapper); emit_parameter_variables(params, wrapper);
@ -1213,29 +1230,35 @@ int JSEmitter::emitCtor(Node *n) {
Printf(wrapper->locals, "%sresult;", SwigType_str(Getattr(n, "type"), 0)); Printf(wrapper->locals, "%sresult;", SwigType_str(Getattr(n, "type"), 0));
int num_args = emit_num_arguments(params);
String *action = emit_action(n); String *action = emit_action(n);
marshalInputArgs(n, params, wrapper, Ctor, true, false); marshalInputArgs(n, params, wrapper, Ctor, true, false);
Printv(wrapper->code, action, "\n", 0); Printv(wrapper->code, action, "\n", 0);
t_ctor.replace(T_NAME_MANGLED, mangled_name) t_ctor.replace(T_WRAPPER, wrap_name)
.replace(T_OVERLOAD, overname) .replace(T_TYPE_MANGLED, state.clazz(TYPE_MANGLED))
.replace(T_LOCALS, wrapper->locals) .replace(T_LOCALS, wrapper->locals)
.replace(T_CODE, wrapper->code) .replace(T_CODE, wrapper->code)
.replace(T_TYPE_MANGLED, state.clazz(TYPE_MANGLED)) .pretty_print(f_wrappers);
.pretty_print(state.clazz(CTORS));
String *argcount = NewString("");
Printf(argcount, "%d", num_args);
Template t_ctor_case(getTemplate("JS_ctor_dispatch_case")); Template t_ctor_case(getTemplate("JS_ctor_dispatch_case"));
t_ctor_case.replace(T_NAME_MANGLED, mangled_name) t_ctor_case.replace(T_WRAPPER, wrap_name)
.replace(T_OVERLOAD, overname) .replace(T_ARGCOUNT, Getattr(n, ARGCOUNT));
.replace(T_ARGCOUNT, argcount);
Append(state.clazz(CTOR_DISPATCHERS), t_ctor_case.str()); Append(state.clazz(CTOR_DISPATCHERS), t_ctor_case.str());
Delete(argcount);
DelWrapper(wrapper); DelWrapper(wrapper);
// create a dispatching ctor (if necessary)
if (!Getattr(n, "sym:nextSibling")) {
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
Template t_mainctor(getTemplate("JS_mainctordefn"));
t_mainctor.replace(T_WRAPPER, wrap_name)
.replace(T_DISPATCH_CASES, state.clazz(CTOR_DISPATCHERS))
.pretty_print(f_wrappers);
state.clazz(CTOR, wrap_name);
} else {
state.clazz(CTOR, wrap_name);
}
return SWIG_OK; return SWIG_OK;
} }
@ -1392,17 +1415,9 @@ int JSEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
// handle function overloading // handle function overloading
if (is_overloaded) { if (is_overloaded) {
Template t_dispatch_case = getTemplate("JS_function_dispatch_case"); Template t_dispatch_case = getTemplate("JS_function_dispatch_case");
int argc = emit_num_arguments(params);
String *argcount = NewString("");
Printf(argcount, "%d", argc);
t_dispatch_case.replace(T_WRAPPER, wrap_name) t_dispatch_case.replace(T_WRAPPER, wrap_name)
.replace(T_ARGCOUNT, argcount); .replace(T_ARGCOUNT, Getattr(n, ARGCOUNT));
Append(state.global(FUNCTION_DISPATCHERS), t_dispatch_case.str()); Append(state.global(FUNCTION_DISPATCHERS), t_dispatch_case.str());
Delete(argcount);
} }
DelWrapper(wrapper); DelWrapper(wrapper);