Remove a global variable from JSEmitter by making use of JSEmitterState.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/oliverb-javascript-v8@13768 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Oliver Buchtala 2012-09-08 00:58:23 +00:00
commit b778c4816b

View file

@ -8,27 +8,40 @@
* JAVASCRIPT: swig module implementation * JAVASCRIPT: swig module implementation
**********************************************************************/ **********************************************************************/
/* forward decl: Template is a convenience helper class for dealing with
* code fragments */
class Template;
/** /**
* Enables extra debugging information in typemaps. * Enables extra debugging information in typemaps.
*/ */
bool js_template_enable_debug = false; bool js_template_enable_debug = false;
class State { // keywords used for state variables
#undef NAME
#define NAME "name"
#define NAME_MANGLED "name_mangled"
#define TYPE "type"
#define TYPE_MANGLED "type_mangled"
#define WRAPPER_NAME "wrapper"
#define IS_IMMUTABLE "is_immutable"
#define IS_STATIC "is_static"
/**
* A convenience class to manage state variables for emitters.
* The implementation delegates to swig Hash DOHs and provides
* named sub-hashes for class, variable, and function states.
*/
class JSEmitterState {
public: public:
State(): _global(NewHash()) { JSEmitterState():
_global(NewHash()) {
// initialize sub-hashes // initialize sub-hashes
Setattr(_global, "class", NewHash()); Setattr(_global, "class", NewHash());
Setattr(_global, "function", NewHash()); Setattr(_global, "function", NewHash());
Setattr(_global, "variable", NewHash()); Setattr(_global, "variable", NewHash());
} }
~State() { Delete(_global); } ~JSEmitterState() { Delete(_global); }
DOH *getState(const char* key, bool _new = false) { DOH *getState(const char* key, bool _new = false) {
if (_new) { if (_new) {
@ -99,12 +112,20 @@ private:
Hash *_global; Hash *_global;
}; };
/* forward decl: Template is a convenience helper class for dealing with
* code fragments */
class Template;
/** /**
* JSEmitter represents an abstraction of javascript code generators * JSEmitter represents an abstraction of javascript code generators
* for different javascript engines. * for different javascript engines.
**/ **/
class JSEmitter { class JSEmitter {
protected:
typedef JSEmitterState State;
public: public:
enum JSEmitterType { enum JSEmitterType {
@ -202,7 +223,7 @@ public:
*/ */
Template getTemplate(const String *name); Template getTemplate(const String *name);
void setStaticFlag(bool is_static = false); State &getState();
protected: protected:
@ -259,8 +280,6 @@ protected:
Wrapper *current_wrapper; Wrapper *current_wrapper;
State state; State state;
bool is_static;
}; };
/* factory methods for concrete JSEmitters: */ /* factory methods for concrete JSEmitters: */
@ -351,9 +370,9 @@ int JAVASCRIPT::globalfunctionHandler(Node *n) {
int JAVASCRIPT::staticmemberfunctionHandler(Node *n) { int JAVASCRIPT::staticmemberfunctionHandler(Node *n) {
// workaround: storage=static is not set for static member functions // workaround: storage=static is not set for static member functions
emitter->setStaticFlag(true); emitter->getState().function(IS_STATIC, NewString("1"));
Language::staticmemberfunctionHandler(n); Language::staticmemberfunctionHandler(n);
emitter->setStaticFlag(false); emitter->getState().function(IS_STATIC, NULL);
return SWIG_OK; return SWIG_OK;
} }
@ -575,22 +594,13 @@ private:
bool debug; bool debug;
}; };
#define __NAME__ "name"
#define NAME_MANGLED "name_mangled"
#define TYPE "type"
#define TYPE_MANGLED "type_mangled"
#define WRAPPER_NAME "wrapper"
#define IS_IMMUTABLE "is_immutable"
#define IS_STATIC "is_static"
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* JSEmitter() * JSEmitter()
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
JSEmitter::JSEmitter() JSEmitter::JSEmitter()
: empty_string(NewString("")), : empty_string(NewString("")),
current_wrapper(NULL), current_wrapper(NULL)
is_static(false)
{ {
templates = NewHash(); templates = NewHash();
} }
@ -629,12 +639,12 @@ Template JSEmitter::getTemplate(const String *name) {
return t; return t;
} }
int JSEmitter::initialize(Node *) { JSEmitterState &JSEmitter::getState() {
return SWIG_OK; return state;
} }
void JSEmitter::setStaticFlag(bool _is_static) { int JSEmitter::initialize(Node *) {
is_static = _is_static; return SWIG_OK;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@ -753,7 +763,7 @@ int JSEmitter::emitWrapperFunction(Node *n) {
int JSEmitter::enterClass(Node *n) { int JSEmitter::enterClass(Node *n) {
state.clazz(true); state.clazz(true);
state.clazz(__NAME__, Getattr(n, "sym:name")); state.clazz(NAME, Getattr(n, "sym:name"));
state.clazz(NAME_MANGLED, SwigType_manglestr(Getattr(n, "name"))); state.clazz(NAME_MANGLED, SwigType_manglestr(Getattr(n, "name")));
state.clazz(TYPE, NewString(Getattr(n, "classtype"))); state.clazz(TYPE, NewString(Getattr(n, "classtype")));
@ -769,14 +779,14 @@ int JSEmitter::enterClass(Node *n) {
int JSEmitter::enterFunction(Node *n) { int JSEmitter::enterFunction(Node *n) {
state.function(true); state.function(true);
state.function(__NAME__, Getattr(n, "sym:name")); state.function(NAME, Getattr(n, "sym:name"));
return SWIG_OK; return SWIG_OK;
} }
int JSEmitter::enterVariable(Node *n) { int JSEmitter::enterVariable(Node *n) {
state.variable(true); state.variable(true);
state.variable(__NAME__, Swig_scopename_last(Getattr(n, "name"))); state.variable(NAME, Swig_scopename_last(Getattr(n, "name")));
state.variable(IS_IMMUTABLE, Getattr(n, "wrap:immutable")); state.variable(IS_IMMUTABLE, Getattr(n, "wrap:immutable"));
return SWIG_OK; return SWIG_OK;
} }
@ -1238,7 +1248,7 @@ int JSCEmitter::exitFunction(Node *n) {
} }
} }
t_function.replace("${functionname}", state.function(__NAME__)) t_function.replace("${functionname}", state.function(NAME))
.replace("${functionwrapper}", state.function(WRAPPER_NAME)); .replace("${functionwrapper}", state.function(WRAPPER_NAME));
if (is_member) { if (is_member) {
@ -1268,7 +1278,7 @@ int JSCEmitter::exitVariable(Node *n) {
Template t_variable(getTemplate("JS_variabledecl")); Template t_variable(getTemplate("JS_variabledecl"));
t_variable.replace("${setname}", state.variable(SETTER)) t_variable.replace("${setname}", state.variable(SETTER))
.replace("${getname}", state.variable(GETTER)) .replace("${getname}", state.variable(GETTER))
.replace("${propertyname}", state.variable(__NAME__)); .replace("${propertyname}", state.variable(NAME));
if (GetFlag(n, "ismember")) { if (GetFlag(n, "ismember")) {
if (Equal(Getattr(n, "storage"), "static") || (Equal(Getattr(n, "nodeType"), "enumitem"))) { if (Equal(Getattr(n, "storage"), "static") || (Equal(Getattr(n, "nodeType"), "enumitem"))) {
@ -1341,7 +1351,7 @@ int JSCEmitter::exitClass(Node *n) {
/* adds a class registration statement to initializer function */ /* adds a class registration statement to initializer function */
Template t_registerclass(getTemplate("JS_register_class")); Template t_registerclass(getTemplate("JS_register_class"));
t_registerclass.replace("${classname}", state.clazz(__NAME__)) t_registerclass.replace("${classname}", state.clazz(NAME))
.replace("${classname_mangled}", state.clazz(NAME_MANGLED)) .replace("${classname_mangled}", state.clazz(NAME_MANGLED))
.replace("${namespace_mangled}", Getattr(current_namespace, "name_mangled")) .replace("${namespace_mangled}", Getattr(current_namespace, "name_mangled"))
.pretty_print(state.global(INITIALIZER)); .pretty_print(state.global(INITIALIZER));
@ -1509,23 +1519,24 @@ int JSCEmitter::emitFunction(Node *n, bool is_member) {
// in these cases the context (staticmemberfunctionHandler) is // in these cases the context (staticmemberfunctionHandler) is
// exploited and a flag is set temporarily // exploited and a flag is set temporarily
// TODO: this could be done in general with is_member and is_static // TODO: this could be done in general with is_member and is_static
bool is_static = JSEmitter::is_static || Equal(Getattr(n, "storage"), "static"); bool is_static = State::IsSet(state.function(IS_STATIC)) || Equal(Getattr(n, "storage"), "static");
bool is_overloaded = GetFlag(n, "sym:overloaded"); bool is_overloaded = GetFlag(n, "sym:overloaded");
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
// prepare the function wrapper name
String *wrap_name = Swig_name_wrapper(Getattr(n, "sym:name"));
if (is_overloaded) { if (is_overloaded) {
Append(wrap_name, Getattr(n, "sym:overname")); Append(wrap_name, Getattr(n, "sym:overname"));
} }
Setattr(n, "wrap:name", wrap_name); Setattr(n, "wrap:name", wrap_name);
state.function(WRAPPER_NAME, wrap_name); state.function(WRAPPER_NAME, wrap_name);
// prepare local variables
ParmList *params = Getattr(n, "parms"); ParmList *params = Getattr(n, "parms");
emit_parameter_variables(params, current_wrapper); emit_parameter_variables(params, current_wrapper);
emit_attach_parmmaps(params, current_wrapper); emit_attach_parmmaps(params, current_wrapper);
Wrapper_add_local(current_wrapper, "jsresult", "JSValueRef jsresult"); Wrapper_add_local(current_wrapper, "jsresult", "JSValueRef jsresult");
// prepare code part
String *action = emit_action(n); String *action = emit_action(n);
marshalInputArgs(n, params, current_wrapper, Function, is_member, is_static); marshalInputArgs(n, params, current_wrapper, Function, is_member, is_static);
marshalOutput(n, action, current_wrapper); marshalOutput(n, action, current_wrapper);
@ -1535,6 +1546,7 @@ int JSCEmitter::emitFunction(Node *n, bool is_member) {
.replace("${CODE}", current_wrapper->code) .replace("${CODE}", current_wrapper->code)
.pretty_print(f_wrappers); .pretty_print(f_wrappers);
// 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");