Fix former workaround by concerning static member functions.

"storage" attribute is removed by Language::staticmemberfunctionHandler
which was resolved by a workaround before.
Now, the implementation relies completely on state flags retrieved at
a proper point.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/oliverb-javascript-v8@13772 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Oliver Buchtala 2012-09-08 00:59:18 +00:00
commit 16077503c8
3 changed files with 40 additions and 274 deletions

View file

@ -202,17 +202,17 @@ protected:
/**
* Generates code for a function.
*/
virtual int emitFunction(Node *n, bool is_member) = 0;
virtual int emitFunction(Node *n, bool is_member, bool is_static) = 0;
/**
* Generates code for a getter function.
*/
virtual int emitGetter(Node *n, bool is_member) = 0;
virtual int emitGetter(Node *n, bool is_member, bool is_static) = 0;
/**
* Generates code for a setter function.
*/
virtual int emitSetter(Node *n, bool is_member) = 0;
virtual int emitSetter(Node *n, bool is_member, bool is_static) = 0;
/**
* Helper function to find out if a function is a setter or not.
@ -315,6 +315,7 @@ int JAVASCRIPT::functionHandler(Node *n) {
int JAVASCRIPT::globalfunctionHandler(Node *n) {
emitter->switchNamespace(n);
Language::globalfunctionHandler(n);
return SWIG_OK;
}
@ -326,13 +327,11 @@ int JAVASCRIPT::globalfunctionHandler(Node *n) {
int JAVASCRIPT::staticmemberfunctionHandler(Node *n) {
/*
* Note: storage=static is not set for static member functions.
* It also is not working to set that attribute here.
* Instead the according state variable is set directly.
* Note: storage=static is removed by Language::staticmemberfunctionHandler.
* So, don't rely on that after here. Instead use the state variable which is
* set by JSEmitter::enterFunction().
*/
SetFlag(emitter->getState().function(), IS_STATIC);
Language::staticmemberfunctionHandler(n);
Setattr(emitter->getState().function(), IS_STATIC, 0);
Language::staticmemberfunctionHandler(n);
return SWIG_OK;
}
@ -344,14 +343,7 @@ int JAVASCRIPT::staticmemberfunctionHandler(Node *n) {
int JAVASCRIPT::variableHandler(Node *n) {
if (!is_assignable(n)
// FIXME: test "arrays_global" does not compile with that as it is not allowed to assign to char[]
// probably some error in char[] typemap
|| Equal(Getattr(n, "type"), "a().char")) {
SetFlag(n, "wrap:immutable");
}
emitter->enterVariable(n);
emitter->enterVariable(n);
Language::variableHandler(n);
emitter->exitVariable(n);
@ -622,20 +614,18 @@ int JSEmitter::emitWrapperFunction(Node *n) {
if (kind) {
bool is_member = GetFlag(n, "ismember");
if (Cmp(kind, "function") == 0) {
ret = emitFunction(n, is_member);
bool is_static = GetFlag(state.function(), IS_STATIC);
ret = emitFunction(n, is_member, is_static);
} else if (Cmp(kind, "variable") == 0) {
bool is_static = GetFlag(state.variable(), IS_STATIC);
if (isSetterMethod(n)) {
ret = emitSetter(n, is_member);
ret = emitSetter(n, is_member, is_static);
} else {
ret = emitGetter(n, is_member);
ret = emitGetter(n, is_member, is_static);
}
} else {
Printf(stderr, "Warning: unsupported wrapper function type\n");
Swig_print_node(n);
ret = SWIG_ERROR;
}
} else {
@ -643,10 +633,8 @@ int JSEmitter::emitWrapperFunction(Node *n) {
if (Cmp(view, "constructorHandler") == 0) {
ret = emitCtor(n);
} else if (Cmp(view, "destructorHandler") == 0) {
ret = emitDtor(n);
} else {
Printf(stderr, "Warning: unsupported wrapper function type");
Swig_print_node(n);
@ -677,14 +665,29 @@ int JSEmitter::enterFunction(Node *n) {
state.function(true);
state.function(NAME, Getattr(n, "sym:name"));
if(Equal(Getattr(n, "storage"), "static")) {
SetFlag(state.function(), IS_STATIC);
}
return SWIG_OK;
}
int JSEmitter::enterVariable(Node *n) {
state.variable(true);
state.variable(NAME, Swig_scopename_last(Getattr(n, "name")));
state.variable(IS_IMMUTABLE, Getattr(n, "wrap:immutable"));
if(Equal(Getattr(n, "storage"), "static")) {
SetFlag(state.variable(), IS_STATIC);
}
if (!Language::instance()->is_assignable(n)
// FIXME: test "arrays_global" does not compile with that as it is not allowed to assign to char[]
// probably some error in char[] typemap
|| Equal(Getattr(n, "type"), "a().char")) {
SetFlag(state.variable(), IS_IMMUTABLE);
}
return SWIG_OK;
}
@ -763,13 +766,13 @@ protected:
virtual int exitClass(Node *n);
virtual int emitFunction(Node *n, bool is_member);
virtual int emitFunction(Node *n, bool is_member, bool is_static);
virtual int emitFunctionDispatcher(Node *n, bool is_member);
virtual int emitGetter(Node *n, bool is_member);
virtual int emitGetter(Node *n, bool is_member, bool is_static);
virtual int emitSetter(Node *n, bool is_member);
virtual int emitSetter(Node *n, bool is_member, bool is_static);
virtual int emitConstant(Node *n);
@ -1069,7 +1072,7 @@ int JSCEmitter::exitFunction(Node *n) {
.replace("${functionwrapper}", state.function(WRAPPER_NAME));
if (is_member) {
if (Equal(Getattr(n, "storage"), "static")) {
if (GetFlag(state.function(), IS_STATIC)) {
Append(state.clazz(STATIC_FUNCTIONS), t_function.str());
} else {
Append(state.clazz(MEMBER_FUNCTIONS), t_function.str());
@ -1098,7 +1101,8 @@ int JSCEmitter::exitVariable(Node *n) {
.replace("${propertyname}", state.variable(NAME));
if (GetFlag(n, "ismember")) {
if (Equal(Getattr(n, "storage"), "static") || (Equal(Getattr(n, "nodeType"), "enumitem"))) {
if (GetFlag(state.function(), IS_STATIC)
|| Equal(Getattr(n, "nodeType"), "enumitem")) {
Append(state.clazz(STATIC_VARIABLES), t_variable.str());
} else {
Append(state.clazz(MEMBER_VARIABLES), t_variable.str());
@ -1229,12 +1233,10 @@ int JSCEmitter::emitDtor(Node *) {
return SWIG_OK;
}
int JSCEmitter::emitGetter(Node *n, bool is_member) {
int JSCEmitter::emitGetter(Node *n, bool is_member, bool is_static) {
Wrapper *wrapper = NewWrapper();
Template t_getter(getTemplate("JS_getproperty"));
bool is_static = Equal(Getattr(n, "storage"), "static");
// prepare wrapper name
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
Setattr(n, "wrap:name", wrap_name);
@ -1261,7 +1263,7 @@ int JSCEmitter::emitGetter(Node *n, bool is_member) {
return SWIG_OK;
}
int JSCEmitter::emitSetter(Node *n, bool is_member) {
int JSCEmitter::emitSetter(Node *n, bool is_member, bool is_static) {
// skip variables that are immutable
if (State::IsSet(state.variable(IS_IMMUTABLE))) {
@ -1271,7 +1273,6 @@ int JSCEmitter::emitSetter(Node *n, bool is_member) {
Wrapper *wrapper = NewWrapper();
Template t_setter(getTemplate("JS_setproperty"));
bool is_static = Equal(Getattr(n, "storage"), "static");
// prepare wrapper name
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
@ -1345,18 +1346,12 @@ int JSCEmitter::emitConstant(Node *n) {
return SWIG_OK;
}
int JSCEmitter::emitFunction(Node *n, bool is_member) {
int JSCEmitter::emitFunction(Node *n, bool is_member, bool is_static) {
Wrapper *wrapper = NewWrapper();
Template t_function(getTemplate("JS_functionwrapper"));
// Note: there is an inconsistency in SWIG with static member functions
// that do not have storage:static
// in these cases the context (staticmemberfunctionHandler) is
// exploited and a flag is set temporarily
// TODO: this could be done in general with is_member and is_static
bool is_static = State::IsSet(state.function(IS_STATIC)) || Equal(Getattr(n, "storage"), "static");
bool is_overloaded = GetFlag(n, "sym:overloaded");
// prepare the function wrapper name

View file

@ -1,139 +0,0 @@
#ifndef JAVASCRIPT_EMITTER_H
#define JAVASCRIPT_EMITTER_H
#include "swigmod.h"
/**
* A class that wraps a code snippet used as template for code generation.
*/
class Template {
public:
Template(const String* code);
~Template();
String* str();
Template& Replace(const String* pattern, const String* repl);
private:
String* m_code;
};
class JSEmitter {
public:
enum JSEmitterType {
JavascriptCore,
V8,
QtScript
};
JSEmitter();
virtual ~JSEmitter();
/**
* Opens output files and temporary output DOHs.
*/
virtual int Initialize(Node *n) = 0;
/**
* Writes all collected code into the output file(s).
*/
virtual int Dump(Node *n) = 0;
/**
* Cleans up all open output DOHs.
*/
virtual int Close() = 0;
/**
* Switches the context for code generation.
*
* Classes, global variables and global functions may need to
* be registered in certain static tables.
* This method should be used to switch output DOHs correspondingly.
*/
virtual int SwitchContext(Node *n) { return SWIG_OK; };
/**
* Invoked at the beginning of the classHandler.
*/
virtual int EnterClass(Node *n) { return SWIG_OK; };
/**
* Invoked at the end of the classHandler.
*/
virtual int ExitClass(Node *n) { return SWIG_OK; };
/**
* Invoked at the beginning of the variableHandler.
*/
virtual int EnterVariable(Node *n) { return SWIG_OK; };
/**
* Invoked at the end of the variableHandler.
*/
virtual int ExitVariable(Node *n) { return SWIG_OK; };
/**
* Invoked at the beginning of the functionHandler.
*/
virtual int EnterFunction(Node *n) { return SWIG_OK; };
/**
* Invoked at the end of the functionHandler.
*/
virtual int ExitFunction(Node *n) { return SWIG_OK; };
/**
* Invoked by functionWrapper callback after call to Language::functionWrapper.
*/
virtual int EmitWrapperFunction(Node *n);
/**
* Registers a given code snippet for a given key name.
*
* This method is called by the fragmentDirective handler
* of the JAVASCRIPT language module.
*/
int RegisterTemplate(const String *name, const String *code);
/**
* Retrieve the code template registered for a given name.
*/
const String* GetTemplate(const String *name);
protected:
virtual int EmitCtor(Node *n) = 0;
virtual int EmitDtor(Node *n) = 0;
virtual int EmitFunction(Node *n, bool is_member) = 0;
virtual int EmitGetter(Node *n, bool is_member) = 0;
virtual int EmitSetter(Node *n, bool is_member) = 0;
bool IsSetterMethod(Node *n);
Node* GetBaseClass(Node *n);
const String* typemapLookup(Node *n, const_String_or_char_ptr tmap_method,
SwigType *type, int warning, Node *typemap_attributes = 0);
protected:
// empty string used at different places in the code
String *empty_string;
Hash *templates;
Wrapper* current_wrapper;
};
#endif // JAVASCRIPT_EMITTER_H

View file

@ -1,90 +0,0 @@
#ifndef JAVASCRIPT_V8_H
#define JAVASCRIPT_V8_H
#include "javascript_emitter.h"
class V8Emitter: public JSEmitter {
public:
V8Emitter();
virtual ~V8Emitter();
virtual int Initialize(Node *n);
virtual int Dump(Node *n);
virtual int Close();
virtual int SwitchContext(Node *n);
virtual int EnterClass(Node *n);
virtual int ExitClass(Node *n);
virtual int EnterVariable(Node *n);
virtual int ExitVariable(Node *n);
virtual int EnterFunction(Node *n);
virtual int ExitFunction(Node *n);
protected:
int CreateNamespace(String* scope);
virtual int EmitCtor(Node *n);
virtual int EmitDtor(Node *n);
virtual int EmitFunction(Node *n, bool is_member);
virtual int EmitGetter(Node *n, bool is_member);
virtual int EmitSetter(Node *n, bool is_member);
void marshalInputArgs(Node *n, ParmList *parms, int numarg, Wrapper *wrapper);
void marshalOutput(Node *n, String *actioncode, Wrapper *wrapper);
Parm *skipIgnoredArgs(Parm *p);
private:
File *f_runtime;
File *f_header;
File *f_class_templates;
File *f_wrapper;
File *f_init_namespaces;
File *f_init_class_templates;
File *f_init_wrappers;
File *f_init_inheritance;
File *f_init_class_instances;
File *f_init_static_wrappers;
File *f_init_register_classes;
File *f_init_register_namespaces;
// the output cpp file
File *f_wrap_cpp;
// state variables
String* current_context;
String* current_class_type;
String* current_classname_mangled;
String* current_classname_unqualified;
String* current_variable_mangled;
String* current_variable_unqualified;
String* current_getter;
String* current_setter;
String* current_function_mangled;
String* current_function_unqualified;
String* GLOBAL;
String* NULL_STR;
Hash* namespaces;
};
#endif // JAVASCRIPT_V8_H