From: <ne...@us...> - 2012-08-20 18:31:27
|
Revision: 13687 http://swig.svn.sourceforge.net/swig/?rev=13687&view=rev Author: neha1 Date: 2012-08-20 18:31:19 +0000 (Mon, 20 Aug 2012) Log Message: ----------- Converted five source files into one monster. Modified Paths: -------------- branches/gsoc2012-javascript/Source/Modules/javascript.cxx Removed Paths: ------------- branches/gsoc2012-javascript/Source/Modules/javascript_emitter.cxx branches/gsoc2012-javascript/Source/Modules/javascript_emitter.h branches/gsoc2012-javascript/Source/Modules/javascript_jsc.cxx branches/gsoc2012-javascript/Source/Modules/javascript_jsc.h Modified: branches/gsoc2012-javascript/Source/Modules/javascript.cxx =================================================================== --- branches/gsoc2012-javascript/Source/Modules/javascript.cxx 2012-08-20 18:30:43 UTC (rev 13686) +++ branches/gsoc2012-javascript/Source/Modules/javascript.cxx 2012-08-20 18:31:19 UTC (rev 13687) @@ -4,8 +4,1282 @@ #include <parser.h> #include <ctype.h> -#include "javascript_emitter.h" +/** + * A class that wraps a code snippet used as template for code generation. + */ + class Template { + public: + Template(const String *code); + + Template(const String *code, const String *templateName, bool debug); + + ~Template(); + + String *str(); + + Template & replace(const String *pattern, const String *repl); + + private: + String *code; + String *templateName; + bool debug; + }; + + 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 switchNamespace(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the beginning of the classHandler. + */ + virtual int enterClass(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the end of the classHandler. + */ + virtual int exitClass(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the beginning of the variableHandler. + */ + virtual int enterVariable(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the end of the variableHandler. + */ + virtual int exitVariable(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the beginning of the functionHandler. + */ + virtual int enterFunction(Node *) { + return SWIG_OK; + }; + + /** + * Invoked at the end of the functionHandler. + */ + virtual int exitFunction(Node *) { + return SWIG_OK; + }; + + /** + * Invoked by functionWrapper callback after call to Language::functionWrapper. + */ + virtual int emitWrapperFunction(Node *n); + + /** + * Invoked from constantWrapper after call to Language::constantWrapper. + **/ + virtual int emitConstant(Node *n) = 0; + + /** + * 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. + */ + Template getTemplate(const String *name); + + void enableDebug(); + + void setStaticFlag(bool is_static); + + 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); + + void enableDebugTemplates(); + + protected: + + // empty string used at different places in the code + String *empty_string; + + Hash *templates; + + Wrapper *current_wrapper; + + bool is_static; + + bool debug; + }; + +class JSCEmitter:public JSEmitter { + + private: + + enum MarshallingMode { + Setter, + Getter, + Ctor, + Function + }; + + public: + + JSCEmitter(); + + virtual ~ JSCEmitter(); + + virtual int initialize(Node *n); + + virtual int dump(Node *n); + + virtual int close(); + + + protected: + + virtual int emitCtor(Node *n); + + virtual int emitDtor(Node *n); + + virtual int enterVariable(Node *n); + + virtual int exitVariable(Node *n); + + virtual int enterFunction(Node *n); + + virtual int exitFunction(Node *n); + + virtual int enterClass(Node *n); + + virtual int exitClass(Node *n); + + virtual int emitFunction(Node *n, bool is_member); + + virtual int emitFunctionDispatcher(Node *n, bool is_member); + + virtual int emitGetter(Node *n, bool is_member); + + virtual int emitSetter(Node *n, bool is_member); + + void marshalInputArgs(ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static = false); + + void marshalOutput(Node *n, String *actioncode, Wrapper *wrapper); + + Parm *skipIgnoredArgs(Parm *p); + + virtual int switchNamespace(Node *n); + + virtual int createNamespace(String *scope); + + virtual Hash *createNamespaceEntry(const char *name, const char *parent); + + virtual int emitNamespaces(); + + virtual int emitConstant(Node *n); + +private: + + File *f_wrap_cpp; + File *f_runtime; + File *f_header; + File *f_wrappers; + File *f_init; + + String *NULL_STR; + const char *GLOBAL_STR; + + // contains context specific structs + // to allow generation different class definition tables + // which are switched on namespace change + Hash *namespaces; + Hash *current_namespace; + + // dynamically filled code parts + + String *create_namespaces_code; + String *register_namespaces_code; + + String *current_class_functions; + String *class_variables_code; + String *class_static_functions_code; + String *class_static_variables_code; + + String *ctor_wrappers; + String *ctor_dispatcher_code; + + String *initializer_code; + String *function_dispatcher_code; + + // state variables + String* current_propertyname; + String* current_getter; + String* current_setter; + bool is_immutable; + + String* current_classname; + String* current_classname_mangled; + String* current_classtype; + String* current_classtype_mangled; + String *current_functionwrapper; + String *current_functionname; + }; + +/* ----------------------------------------------------------------------------- + * JSEmitter() + * ----------------------------------------------------------------------------- */ + +JSEmitter::JSEmitter() +: empty_string(NewString("")), debug(false) { + templates = NewHash(); +} + +/* ----------------------------------------------------------------------------- + * ~JSEmitter() + * ----------------------------------------------------------------------------- */ + +JSEmitter::~JSEmitter() { + Delete(empty_string); + Delete(templates); +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::RegisterTemplate() : Registers a code template + * ----------------------------------------------------------------------------- */ + +int JSEmitter::registerTemplate(const String *name, const String *code) { + return Setattr(templates, name, code); +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::GetTemplate() : Retrieves a registered a code template + * ----------------------------------------------------------------------------- */ + +Template JSEmitter::getTemplate(const String *name) { + String *templ = Getattr(templates, name); + + if (!templ) { + Printf(stderr, "Could not find template %s\n.", name); + SWIG_exit(EXIT_FAILURE); + } + + Template t(templ, name, debug); + + return t; +} + +void JSEmitter::enableDebug() { + debug = true; +} + +void JSEmitter::setStaticFlag(bool _is_static) { + is_static = _is_static; +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::typemapLookup() + * + * n - for input only and must contain info for Getfile(n) and Getline(n) to work + * tmap_method - typemap method name + * type - typemap type to lookup + * warning - warning number to issue if no typemaps found + * typemap_attributes - the typemap attributes are attached to this node and will + * also be used for temporary storage if non null + * return is never NULL, unlike Swig_typemap_lookup() + * ----------------------------------------------------------------------------- */ + +const String *JSEmitter::typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes) { + Node *node = !typemap_attributes ? NewHash() : typemap_attributes; + Setattr(node, "type", type); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); + if (!tm) { + tm = empty_string; + if (warning != WARN_NONE) { + Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); + } + } + if (!typemap_attributes) { + Delete(node); + } + return tm; +} + +/* ----------------------------------------------------------------------------- + * JSEmitter::getBaseClass() : the node of the base class or NULL + * ----------------------------------------------------------------------------- */ + +Node *JSEmitter::getBaseClass(Node *n) { + // retrieve the first base class that is not %ignored + List *baselist = Getattr(n, "bases"); + if (baselist) { + Iterator base = First(baselist); + while (base.item && GetFlag(base.item, "feature:ignore")) { + base = Next(base); + } + + return base.item; + } + + return NULL; +} + + /* ----------------------------------------------------------------------------- + * JSEmitter::emitWrapperFunction() : dispatches emitter functions + * ----------------------------------------------------------------------------- */ + +int JSEmitter::emitWrapperFunction(Node *n) { + int ret = SWIG_OK; + + current_wrapper = NewWrapper(); + Setattr(n, "wrap:name", Getattr(n, "sym:name")); + + String *kind = Getattr(n, "kind"); + + if (kind) { + bool is_member = GetFlag(n, "ismember"); + if (Cmp(kind, "function") == 0) { + ret = emitFunction(n, is_member); + + } else if (Cmp(kind, "variable") == 0) { + if (isSetterMethod(n)) { + ret = emitSetter(n, is_member); + + } else { + ret = emitGetter(n, is_member); + + } + } else { + Printf(stderr, "Warning: unsupported wrapper function type\n"); + Swig_print_node(n); + + ret = SWIG_ERROR; + } + } else { + String *view = Getattr(n, "view"); + + 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); + ret = SWIG_ERROR; + } + } + + DelWrapper(current_wrapper); + current_wrapper = 0; + + return ret; +} + +/* ----------------------------------------------------------------------------- + * __swigjs_str_ends_with() : c string helper to check suffix match + * ----------------------------------------------------------------------------- */ + +int __swigjs_str_ends_with(const char *str, const char *suffix) { + + if (str == NULL || suffix == NULL) + return 0; + + size_t str_len = strlen(str); + size_t suffix_len = strlen(suffix); + + if (suffix_len > str_len) + return 0; + + return 0 == strncmp(str + str_len - suffix_len, suffix, suffix_len); +} + + +/* ----------------------------------------------------------------------------- + * JSEmitter::isSetterMethod() : helper to check if a method is a setter function + * ----------------------------------------------------------------------------- */ + +bool JSEmitter::isSetterMethod(Node *n) { + String *symname = Getattr(n, "sym:name"); + return (__swigjs_str_ends_with((char *) Data(symname), "_set") != 0); +} + +/* ----------------------------------------------------------------------------- + * Template::Template() : creates a Template class for given template code + * ----------------------------------------------------------------------------- */ + +Template::Template(const String *code_) { + + if (!code_) { + Printf(stdout, "Template code was null. Illegal input for template."); + SWIG_exit(EXIT_FAILURE); + } + + code = NewString(code_); + templateName = NewString(""); +} + +Template::Template(const String *code_, const String *templateName_, bool debug_) { + + if (!code_) { + Printf(stdout, "Template code was null. Illegal input for template."); + SWIG_exit(EXIT_FAILURE); + } + + code = NewString(code_); + templateName = NewString(templateName_); + debug = debug_; +} + + +/* ----------------------------------------------------------------------------- + * Template::~Template() : cleans up of Template. + * ----------------------------------------------------------------------------- */ + +Template::~Template() { + Delete(code); + Delete(templateName); +} + +/* ----------------------------------------------------------------------------- + * String* Template::str() : retrieves the current content of the template. + * ----------------------------------------------------------------------------- */ + +String *Template::str() { + if (debug) { + String *pre_code = NewString(""); + String *post_code = NewString(""); + String *debug_code = NewString(""); + Printf(pre_code, "//begin fragment(\"%s\")\n", templateName); + Printf(post_code, "//end fragment(\"%s\")\n", templateName); + Printf(debug_code, "%s\n%s\n%s", pre_code, code, post_code); + + Delete(code); + Delete(pre_code); + Delete(post_code); + + code = debug_code; + } + return code; +} + +/* ----------------------------------------------------------------------------- + * Template& Template::replace(const String* pattern, const String* repl) : + * + * replaces all occurances of a given pattern with a given replacement. + * + * - pattern: the pattern to be replaced + * - repl: the replacement string + * - returns a reference to the Template to allow chaining of methods. + * ----------------------------------------------------------------------------- */ + +Template & Template::replace(const String *pattern, const String *repl) { + ::Replaceall(code, pattern, repl); + return *this; +} + +JSCEmitter::JSCEmitter() +: JSEmitter(), NULL_STR(NewString("NULL")) { +} + +JSCEmitter::~JSCEmitter() { + Delete(NULL_STR); +} + +/* --------------------------------------------------------------------- + * skipIgnoredArgs() + * --------------------------------------------------------------------- */ + +Parm *JSCEmitter::skipIgnoredArgs(Parm *p) { + while (checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + } + return p; +} + +/* --------------------------------------------------------------------- + * marshalInputArgs() + * + * Process all of the arguments passed into the argv array + * and convert them into C/C++ function arguments using the + * supplied typemaps. + * --------------------------------------------------------------------- */ + +void JSCEmitter::marshalInputArgs(ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { + String *tm; + Parm *p; + + int startIdx = 0; + if (is_member && !is_static) + startIdx = 1; + + + int i = 0; + for (p = parms; p; p = nextSibling(p), i++) { + SwigType *pt = Getattr(p, "type"); + String *arg = NewString(""); + + switch (mode) { + case Getter: + case Function: + if (is_member && !is_static && i == 0) { + Printv(arg, "thisObject", 0); + } else { + Printf(arg, "argv[%d]", i - startIdx); + } + + break; + case Setter: + if (is_member && !is_static && i == 0) { + Printv(arg, "thisObject", 0); + } else { + Printv(arg, "value", 0); + } + break; + case Ctor: + Printf(arg, "argv[%d]",i); + break; + default: + throw "Illegal state."; + } + + tm = Getattr(p, "tmap:in"); // Get typemap for this argument + if ( tm != NULL ) + { + Replaceall(tm, "$input", arg); + Setattr(p, "emit:input", arg); + + if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) { + Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); + } else { + Replaceall(tm, "$disown", "0"); + } + + Printf(wrapper->code, "%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); + } + Delete(arg); + } +} + +/* --------------------------------------------------------------------- +* marshalOutput() +* +* Process the return value of the C/C++ function call +* and convert them into the Javascript types using the +* supplied typemaps. +* --------------------------------------------------------------------- */ + +void JSCEmitter::marshalOutput(Node *n, String *actioncode, Wrapper *wrapper) { + SwigType *type = Getattr(n, "type"); + Setattr(n, "type", type); + String *tm; + if ((tm = Swig_typemap_lookup_out("out", n, "result", wrapper, actioncode))) { + Replaceall(tm, "$result", "jsresult"); + // TODO: May not be the correct way + Replaceall(tm, "$objecttype", Swig_scopename_last(SwigType_str(SwigType_strip_qualifiers(type), 0))); + + if (GetFlag(n, "feature:new")) { + Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); + } else { + Replaceall(tm, "$owner", "0"); + } + + Printf(wrapper->code, "%s", tm); + if (Len(tm)) + Printf(wrapper->code, "\n"); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), Getattr(n, "name")); + } + emit_return_variable(n, type, wrapper); +} + +int JSCEmitter::initialize(Node *n) { + + /* Get the output file name */ + String *outfile = Getattr(n, "outfile"); + + /* Initialize I/O */ + f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files()); + if (!f_wrap_cpp) { + FileErrorDisplay(outfile); + SWIG_exit(EXIT_FAILURE); + } + + /* Initialization of members */ + f_runtime = NewString(""); + f_init = NewString(""); + f_header = NewString(""); + f_wrappers = NewString(""); + + create_namespaces_code = NewString(""); + register_namespaces_code = NewString(""); + initializer_code = NewString(""); + + + namespaces = NewHash(); + Hash *global_namespace = createNamespaceEntry(Char(Getattr(n, "name")), "global"); + Setattr(namespaces, "::", global_namespace); + current_namespace = global_namespace; + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("begin", f_wrap_cpp); + Swig_register_filebyname("header", f_header); + Swig_register_filebyname("wrapper", f_wrappers); + Swig_register_filebyname("runtime", f_runtime); + Swig_register_filebyname("init", f_init); + + return SWIG_OK; +} + +int JSCEmitter::dump(Node *n) { + /* Get the module name */ + String *module = Getattr(n, "name"); + + // write the swig banner + Swig_banner(f_wrap_cpp); + + SwigType_emit_type_table(f_runtime, f_wrappers); + + Printv(f_wrap_cpp, f_runtime, "\n", 0); + Printv(f_wrap_cpp, f_header, "\n", 0); + Printv(f_wrap_cpp, f_wrappers, "\n", 0); + + + emitNamespaces(); + + // compose the initializer function using a template + Template initializer(getTemplate("JS_initializer")); + initializer.replace("${modulename}", module) + .replace("${initializercode}", initializer_code) + .replace("${create_namespaces}", create_namespaces_code) + .replace("${register_namespaces}", register_namespaces_code); + Wrapper_pretty_print(initializer.str(), f_init); + + Printv(f_wrap_cpp, f_init, "\n", 0); + + return SWIG_OK; +} + + +int JSCEmitter::close() { + /* strings */ + Delete(f_runtime); + Delete(f_header); + Delete(f_wrappers); + Delete(f_init); + + Delete(create_namespaces_code); + Delete(register_namespaces_code); + Delete(initializer_code); + + Delete(namespaces); + + /* files */ + ::Close(f_wrap_cpp); + Delete(f_wrap_cpp); + + return SWIG_OK; +} + +int JSCEmitter::enterFunction(Node *n) { + + bool is_overloaded = GetFlag(n, "sym:overloaded"); + + current_functionname = Getattr(n, "sym:name"); + + if(is_overloaded && function_dispatcher_code == 0) { + function_dispatcher_code = NewString(""); + } + + return SWIG_OK; +} + +int JSCEmitter::exitFunction(Node *n) { + Template t_function = getTemplate("JS_functiondecl"); + + String *functionname = current_functionname; + String *functionwrapper = current_functionwrapper; + + bool is_member = GetFlag(n, "ismember"); + + // handle overloaded functions + // Note: wrappers for overloaded functions are currently + // not made available (e.g., foo_double, foo_int) + // maybe this could be enabled by an extra feature flag + bool is_overloaded = GetFlag(n, "sym:overloaded"); + + if(is_overloaded) { + if(!Getattr(n, "sym:nextSibling")) { + + functionwrapper = Swig_name_wrapper(Getattr(n, "name")); + // note: set this attribute to transfer ownership + Setattr(n, "wrap:dispatcher", functionwrapper); + + // create dispatcher + emitFunctionDispatcher(n, is_member); + + Delete(function_dispatcher_code); + function_dispatcher_code = 0; + + } else { + + //don't register wrappers of overloaded functions in function tables + return SWIG_OK; + } + } + + t_function.replace("${functionname}", functionname) + .replace("${functionwrapper}", functionwrapper); + + if (is_member) { + + if (Equal(Getattr(n, "storage"), "static")) { + Printv(class_static_functions_code, t_function.str(), 0); + + } else { + Printv(current_class_functions, t_function.str(), 0); + } + + } else { + Printv(Getattr(current_namespace, "functions"), t_function.str(), 0); + } + + return SWIG_OK; +} + +int JSCEmitter::enterVariable(Node *n) { + current_getter = NULL_STR; + current_setter = NULL_STR; + current_propertyname = Swig_scopename_last(Getattr(n, "name")); + is_immutable = GetFlag(n, "wrap:immutable"); + + return SWIG_OK; +} + + +int JSCEmitter::exitVariable(Node *n) { + Template t_variable(getTemplate("JS_variabledecl")); + t_variable.replace("${setname}", current_setter) + .replace("${getname}", current_getter) + .replace("${propertyname}", current_propertyname); + + + if (GetFlag(n, "ismember")) { + if (Equal(Getattr(n, "storage"), "static") || (Equal(Getattr(n, "nodeType"), "enumitem"))) { + + Printv(class_static_variables_code, t_variable.str(), 0); + + } else { + Printv(class_variables_code, t_variable.str(), 0); + } + } else { + Printv(Getattr(current_namespace, "values"), t_variable.str(), 0); + } + + return SWIG_OK; +} + +int JSCEmitter::enterClass(Node *n) { + + current_classname = Getattr(n, "sym:name"); + current_classname_mangled = SwigType_manglestr(Getattr(n, "name")); + current_classtype = NewString(Getattr(n, "classtype")); + + String *type = SwigType_manglestr(Getattr(n, "classtypeobj")); + current_classtype_mangled = NewString(""); + Printf(current_classtype_mangled, "p%s", type); + Delete(type); + + Template t_class_defn = getTemplate("JS_class_definition"); + t_class_defn.replace("${classname_mangled}", current_classname_mangled); + Wrapper_pretty_print(t_class_defn.str(), f_wrappers); + + class_variables_code = NewString(""); + current_class_functions = NewString(""); + class_static_variables_code = NewString(""); + class_static_functions_code = NewString(""); + ctor_wrappers = NewString(""); + ctor_dispatcher_code = NewString(""); + + return SWIG_OK; +} + +int JSCEmitter::exitClass(Node *n) { + + String *mangled_name = SwigType_manglestr(Getattr(n, "name")); + + Template t_class_tables(getTemplate("JS_class_tables")); + t_class_tables.replace("${classname_mangled}", mangled_name) + .replace("${jsclassvariables}", class_variables_code) + .replace("${jsclassfunctions}", current_class_functions) + .replace("${jsstaticclassfunctions}", class_static_functions_code) + .replace("${jsstaticclassvariables}", class_static_variables_code); + Wrapper_pretty_print(t_class_tables.str(), f_wrappers); + + /* adds the ctor wrappers at this position */ + // Note: this is necessary to avoid extra forward declarations. + Printv(f_wrappers, ctor_wrappers, 0); + + /* adds the main constructor wrapper function */ + Template t_mainctor(getTemplate("JS_mainctordefn")); + t_mainctor.replace("${classname_mangled}", mangled_name) + .replace("${DISPATCH_CASES}", ctor_dispatcher_code); + Wrapper_pretty_print(t_mainctor.str(), f_wrappers); + + /* adds a class template statement to initializer function */ + Template t_classtemplate(getTemplate("JS_create_class_template")); + + /* prepare registration of base class */ + String *base_name_mangled = NewString("_SwigObject"); + Node* base_class = getBaseClass(n); + if(base_class!=NULL) { + Delete(base_name_mangled); + base_name_mangled = SwigType_manglestr(Getattr(base_class, "name")); + } + + t_classtemplate.replace("${classname_mangled}", mangled_name) + .replace("${classtype_mangled}", current_classtype_mangled) + .replace("${base_classname}", base_name_mangled); + Wrapper_pretty_print(t_classtemplate.str(), initializer_code); + +/* + String *clientdata = NewString(""); + Printv(clientdata, mangled_name, "_classRef", 0); + SwigType_remember_clientdata(current_classtype_mangled, clientdata); +*/ + + SwigType_remember_clientdata(current_classtype_mangled, NewString("0")); + + /* adds a class registration statement to initializer function */ + Template t_registerclass(getTemplate("JS_register_class")); + t_registerclass.replace("${classname}", current_classname) + .replace("${classname_mangled}", current_classname_mangled) + .replace("${namespace_mangled}", Getattr(current_namespace, "name_mangled")); + + Wrapper_pretty_print(t_registerclass.str(), initializer_code); + + /* clean up all DOHs */ + Delete(class_variables_code); + Delete(current_class_functions); + Delete(class_static_variables_code); + Delete(class_static_functions_code); + Delete(ctor_wrappers); + Delete(mangled_name); + Delete(ctor_dispatcher_code); + class_variables_code = 0; + current_class_functions = 0; + class_static_variables_code = 0; + class_static_functions_code = 0; + ctor_wrappers = 0; + ctor_dispatcher_code = 0; + + Delete(current_classname); + Delete(current_classname_mangled); + Delete(current_classtype); + Delete(current_classtype_mangled); + + return SWIG_OK; +} + +int JSCEmitter::emitCtor(Node *n) { + + Template t_ctor(getTemplate("JS_ctordefn")); + String *mangled_name = SwigType_manglestr(Getattr(n, "name")); + + String *name = (Getattr(n, "wrap:name")); + String *overname = Getattr(n, "sym:overname"); + String *wrap_name = Swig_name_wrapper(name); + Setattr(n, "wrap:name", wrap_name); + + ParmList *params = Getattr(n, "parms"); + emit_parameter_variables(params, current_wrapper); + emit_attach_parmmaps(params, current_wrapper); + + Printf(current_wrapper->locals, "%sresult;", SwigType_str(Getattr(n, "type"), 0)); + + int num_args = emit_num_arguments(params); + String *action = emit_action(n); + marshalInputArgs(params, current_wrapper, Ctor, true); + + Printv(current_wrapper->code, action, "\n", 0); + t_ctor.replace("${classname_mangled}", mangled_name) + .replace("${overloadext}", overname) + .replace("${LOCALS}", current_wrapper->locals) + .replace("${CODE}", current_wrapper->code) + .replace("${type_mangled}", current_classtype_mangled); + + Wrapper_pretty_print(t_ctor.str(), ctor_wrappers); + + String *argcount = NewString(""); + Printf(argcount, "%d", num_args); + + Template t_ctor_case(getTemplate("JS_ctor_dispatch_case")); + t_ctor_case.replace("${classname_mangled}", mangled_name) + .replace("${overloadext}", overname) + .replace("${argcount}", argcount); + Printv(ctor_dispatcher_code, t_ctor_case.str(), 0); + Delete(argcount); + + return SWIG_OK; + +} + +int JSCEmitter::emitDtor(Node *) { + + Template t_dtor = getTemplate("JS_destructordefn"); + t_dtor.replace("${classname_mangled}", current_classname_mangled) + .replace("${type}", current_classtype); + Wrapper_pretty_print(t_dtor.str(), f_wrappers); + + return SWIG_OK; +} + +int JSCEmitter::emitGetter(Node *n, bool is_member) { + Template t_getter(getTemplate("JS_getproperty")); + bool is_static = Equal(Getattr(n, "storage"), "static"); + + String *name = Getattr(n, "wrap:name"); + String *wrap_name = Swig_name_wrapper(name); + current_getter = wrap_name; + Setattr(n, "wrap:name", wrap_name); + + ParmList *params = Getattr(n, "parms"); + emit_parameter_variables(params, current_wrapper); + emit_attach_parmmaps(params, current_wrapper); + Wrapper_add_local(current_wrapper, "jsresult", "JSValueRef jsresult"); + + String *action = emit_action(n); + marshalInputArgs(params, current_wrapper, Getter, is_member, is_static); + marshalOutput(n, action, current_wrapper); + + t_getter.replace("${getname}", wrap_name) + .replace("${LOCALS}", current_wrapper->locals) + .replace("${CODE}", current_wrapper->code); + + Wrapper_pretty_print(t_getter.str(), f_wrappers); + + return SWIG_OK; +} + +int JSCEmitter::emitSetter(Node *n, bool is_member) { + + // skip variable that are immutable + if(is_immutable) return SWIG_OK; + + Template t_setter(getTemplate("JS_setproperty")); + bool is_static = Equal(Getattr(n, "storage"), "static"); + + String *name = Getattr(n, "wrap:name"); + String *wrap_name = Swig_name_wrapper(name); + current_setter = wrap_name; + Setattr(n, "wrap:name", wrap_name); + + ParmList *params = Getattr(n, "parms"); + emit_parameter_variables(params, current_wrapper); + emit_attach_parmmaps(params, current_wrapper); + Wrapper_add_local(current_wrapper, "jsresult", "JSValueRef jsresult"); + + String *action = emit_action(n); + marshalInputArgs(params, current_wrapper, Setter, is_member, is_static); + marshalOutput(n, action, current_wrapper); + + t_setter.replace("${setname}", wrap_name) + .replace("${LOCALS}", current_wrapper->locals) + .replace("${CODE}", current_wrapper->code); + + Wrapper_pretty_print(t_setter.str(), f_wrappers); + + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * swig::JSEmitter::emitConstant() : triggers code generation for constants + * ----------------------------------------------------------------------------- */ + +int JSCEmitter::emitConstant(Node *n) { + + // call the variable methods as a constants are + // registred in same way + enterVariable(n); + + current_wrapper = NewWrapper(); + + String* action = NewString(""); + + String *name = Getattr(n, "name"); + String *wrap_name = Swig_name_wrapper(name); + String *value = Getattr(n, "rawval"); + if(value == NULL) { + value = Getattr(n, "rawvalue"); + } + if(value == NULL) { + value = Getattr(n, "value"); + } + + Template t_getter(getTemplate("JS_getproperty")); + + current_getter = wrap_name; + Setattr(n, "wrap:name", wrap_name); + + Printf(action, "result = %s;\n", value); + Setattr(n, "wrap:action", action); + + Wrapper_add_local(current_wrapper, "jsresult", "JSValueRef jsresult"); + marshalOutput(n, action, current_wrapper); + + t_getter.replace("${getname}", wrap_name) + .replace("${LOCALS}", current_wrapper->locals) + .replace("${CODE}", current_wrapper->code); + + Wrapper_pretty_print(t_getter.str(), f_wrappers); + + DelWrapper(current_wrapper); + current_wrapper = 0; + + exitVariable(n); + + return SWIG_OK; +} + +int JSCEmitter::emitFunction(Node *n, bool is_member) { + 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 = JSEmitter::is_static || Equal(Getattr(n, "storage"), "static"); + + bool is_overloaded = GetFlag(n, "sym:overloaded"); + String *name = Getattr(n, "sym:name"); + String *wrap_name = Swig_name_wrapper(name); + + if(is_overloaded) { + Append(wrap_name, Getattr(n, "sym:overname")); + } + + current_functionwrapper = wrap_name; + Setattr(n, "wrap:name", wrap_name); + + ParmList *params = Getattr(n, "parms"); + emit_parameter_variables(params, current_wrapper); + emit_attach_parmmaps(params, current_wrapper); + Wrapper_add_local(current_wrapper, "jsresult", "JSValueRef jsresult"); + + String *action = emit_action(n); + marshalInputArgs(params, current_wrapper, Function, is_member, is_static); + marshalOutput(n, action, current_wrapper); + + t_function.replace("${functionname}", wrap_name) + .replace("${LOCALS}", current_wrapper->locals) + .replace("${CODE}", current_wrapper->code); + Wrapper_pretty_print(t_function.str(), f_wrappers); + + if(is_overloaded) { + 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("${functionwrapper}", wrap_name) + .replace("${argcount}", argcount); + + Printv(function_dispatcher_code, t_dispatch_case.str(), 0); + + Delete(argcount); + } + + return SWIG_OK; +} + +int JSCEmitter::emitFunctionDispatcher(Node *n, bool /*is_member*/) { + + Template t_function(getTemplate("JS_functionwrapper")); + + Wrapper *wrapper = NewWrapper(); + String *wrap_name = Swig_name_wrapper(Getattr(n, "name")); + Setattr(n, "wrap:name", wrap_name); + + Wrapper_add_local(wrapper, "jsresult", "JSValueRef jsresult"); + + Append(wrapper->code, function_dispatcher_code); + Append(wrapper->code, getTemplate("JS_function_dispatch_case_default").str()); + + t_function.replace("${functionname}", wrap_name) + .replace("${LOCALS}", wrapper->locals) + .replace("${CODE}", wrapper->code); + + Wrapper_pretty_print(t_function.str(), f_wrappers); + + DelWrapper(wrapper); + + return SWIG_OK; +} + +int JSCEmitter::switchNamespace(Node *n) { + if (!GetFlag(n, "feature:nspace")) { + current_namespace = Getattr(namespaces, "::"); + + } else { + + String *scope = Swig_scopename_prefix(Getattr(n, "name")); + + if (scope) { + // if the scope is not yet registered + // create all scopes/namespaces recursively + if (!Getattr(namespaces, scope)) { + createNamespace(scope); + } + + current_namespace = Getattr(namespaces, scope); + + } else { + current_namespace = Getattr(namespaces, "::"); + } + } + + return SWIG_OK; +} + +int JSCEmitter::createNamespace(String *scope) { + + String *parent_scope = Swig_scopename_prefix(scope); + + Hash *parent_namespace; + + if (parent_scope == 0) { + parent_namespace = Getattr(namespaces, "::"); + } else if (!Getattr(namespaces, parent_scope)) { + createNamespace(parent_scope); + parent_namespace = Getattr(namespaces, parent_scope); + } else { + parent_namespace = Getattr(namespaces, parent_scope); + } + + assert(parent_namespace != 0); + + Hash *new_namespace = createNamespaceEntry(Char(scope), Char(Getattr(parent_namespace, "name"))); + Setattr(namespaces, scope, new_namespace); + + Delete(parent_scope); + + return SWIG_OK; +} + +Hash *JSCEmitter::createNamespaceEntry(const char *name, const char *parent) { + Hash *entry = NewHash(); + String *_name = NewString(name); + Setattr(entry, "name", Swig_scopename_last(_name)); + Setattr(entry, "name_mangled", Swig_name_mangle(_name)); + Setattr(entry, "parent", NewString(parent)); + Setattr(entry, "functions", NewString("")); + Setattr(entry, "values", NewString("")); + + Delete(_name); + + return entry; +} + +int JSCEmitter::emitNamespaces() { + Iterator it; + for (it = First(namespaces); it.item; it = Next(it)) { + Hash *entry = it.item; + + String *name = Getattr(entry, "name"); + String *parent = Getattr(entry, "parent"); + String *functions = Getattr(entry, "functions"); + String *variables = Getattr(entry, "values"); + String *name_mangled = Getattr(entry, "name_mangled"); + String *parent_mangled = Swig_name_mangle(parent); + + Template namespace_definition(getTemplate("JS_globaldefn")); + namespace_definition.replace("${jsglobalvariables}", variables) + .replace("${jsglobalfunctions}", functions) + .replace("${namespace}", name_mangled); + Wrapper_pretty_print(namespace_definition.str(), f_wrap_cpp); + + Template t_createNamespace(getTemplate("JS_create_namespace")); + t_createNamespace.replace("${namespace}", name_mangled); + Printv(create_namespaces_code, t_createNamespace.str(), 0); + + Template t_registerNamespace(getTemplate("JS_register_namespace")); + t_registerNamespace.replace("${namespace_mangled}", name_mangled) + .replace("${namespace}", name) + .replace("${parent_namespace}", parent_mangled); + Printv(register_namespaces_code, t_registerNamespace.str(), 0); + } + + return SWIG_OK; +} + +JSEmitter* swig_javascript_create_JSC_emitter() +{ + return new JSCEmitter(); +} + extern JSEmitter * swig_javascript_create_JSC_emitter(); /* ******************************************************************** Deleted: branches/gsoc2012-javascript/Source/Modules/javascript_emitter.cxx =================================================================== --- branches/gsoc2012-javascript/Source/Modules/javascript_emitter.cxx 2012-08-20 18:30:43 UTC (rev 13686) +++ branches/gsoc2012-javascript/Source/Modules/javascript_emitter.cxx 2012-08-20 18:31:19 UTC (rev 13687) @@ -1,258 +0,0 @@ -#include "javascript_emitter.h" - -#include "swigmod.h" - -/* ----------------------------------------------------------------------------- - * JSEmitter() - * ----------------------------------------------------------------------------- */ - -JSEmitter::JSEmitter() -: empty_string(NewString("")), debug(false) { - templates = NewHash(); -} - -/* ----------------------------------------------------------------------------- - * ~JSEmitter() - * ----------------------------------------------------------------------------- */ - -JSEmitter::~JSEmitter() { - Delete(empty_string); - Delete(templates); -} - -/* ----------------------------------------------------------------------------- - * JSEmitter::RegisterTemplate() : Registers a code template - * ----------------------------------------------------------------------------- */ - -int JSEmitter::registerTemplate(const String *name, const String *code) { - return Setattr(templates, name, code); -} - -/* ----------------------------------------------------------------------------- - * JSEmitter::GetTemplate() : Retrieves a registered a code template - * ----------------------------------------------------------------------------- */ - -Template JSEmitter::getTemplate(const String *name) { - String *templ = Getattr(templates, name); - - if (!templ) { - Printf(stderr, "Could not find template %s\n.", name); - SWIG_exit(EXIT_FAILURE); - } - - Template t(templ, name, debug); - - return t; -} - -void JSEmitter::enableDebug() { - debug = true; -} - -void JSEmitter::setStaticFlag(bool _is_static) { - is_static = _is_static; -} - -/* ----------------------------------------------------------------------------- - * JSEmitter::typemapLookup() - * - * n - for input only and must contain info for Getfile(n) and Getline(n) to work - * tmap_method - typemap method name - * type - typemap type to lookup - * warning - warning number to issue if no typemaps found - * typemap_attributes - the typemap attributes are attached to this node and will - * also be used for temporary storage if non null - * return is never NULL, unlike Swig_typemap_lookup() - * ----------------------------------------------------------------------------- */ - -const String *JSEmitter::typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes) { - Node *node = !typemap_attributes ? NewHash() : typemap_attributes; - Setattr(node, "type", type); - Setfile(node, Getfile(n)); - Setline(node, Getline(n)); - const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); - if (!tm) { - tm = empty_string; - if (warning != WARN_NONE) { - Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); - } - } - if (!typemap_attributes) { - Delete(node); - } - return tm; -} - -/* ----------------------------------------------------------------------------- - * JSEmitter::getBaseClass() : the node of the base class or NULL - * ----------------------------------------------------------------------------- */ - -Node *JSEmitter::getBaseClass(Node *n) { - // retrieve the first base class that is not %ignored - List *baselist = Getattr(n, "bases"); - if (baselist) { - Iterator base = First(baselist); - while (base.item && GetFlag(base.item, "feature:ignore")) { - base = Next(base); - } - - return base.item; - } - - return NULL; -} - - /* ----------------------------------------------------------------------------- - * JSEmitter::emitWrapperFunction() : dispatches emitter functions - * ----------------------------------------------------------------------------- */ - -int JSEmitter::emitWrapperFunction(Node *n) { - int ret = SWIG_OK; - - current_wrapper = NewWrapper(); - Setattr(n, "wrap:name", Getattr(n, "sym:name")); - - String *kind = Getattr(n, "kind"); - - if (kind) { - bool is_member = GetFlag(n, "ismember"); - if (Cmp(kind, "function") == 0) { - ret = emitFunction(n, is_member); - - } else if (Cmp(kind, "variable") == 0) { - if (isSetterMethod(n)) { - ret = emitSetter(n, is_member); - - } else { - ret = emitGetter(n, is_member); - - } - } else { - Printf(stderr, "Warning: unsupported wrapper function type\n"); - Swig_print_node(n); - - ret = SWIG_ERROR; - } - } else { - String *view = Getattr(n, "view"); - - 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); - ret = SWIG_ERROR; - } - } - - DelWrapper(current_wrapper); - current_wrapper = 0; - - return ret; -} - -/* ----------------------------------------------------------------------------- - * __swigjs_str_ends_with() : c string helper to check suffix match - * ----------------------------------------------------------------------------- */ - -int __swigjs_str_ends_with(const char *str, const char *suffix) { - - if (str == NULL || suffix == NULL) - return 0; - - size_t str_len = strlen(str); - size_t suffix_len = strlen(suffix); - - if (suffix_len > str_len) - return 0; - - return 0 == strncmp(str + str_len - suffix_len, suffix, suffix_len); -} - - -/* ----------------------------------------------------------------------------- - * JSEmitter::isSetterMethod() : helper to check if a method is a setter function - * ----------------------------------------------------------------------------- */ - -bool JSEmitter::isSetterMethod(Node *n) { - String *symname = Getattr(n, "sym:name"); - return (__swigjs_str_ends_with((char *) Data(symname), "_set") != 0); -} - -/* ----------------------------------------------------------------------------- - * Template::Template() : creates a Template class for given template code - * ----------------------------------------------------------------------------- */ - -Template::Template(const String *code_) { - - if (!code_) { - Printf(stdout, "Template code was null. Illegal input for template."); - SWIG_exit(EXIT_FAILURE); - } - - code = NewString(code_); - templateName = NewString(""); -} - -Template::Template(const String *code_, const String *templateName_, bool debug_) { - - if (!code_) { - Printf(stdout, "Template code was null. Illegal input for template."); - SWIG_exit(EXIT_FAILURE); - } - - code = NewString(code_); - templateName = NewString(templateName_); - debug = debug_; -} - - -/* ----------------------------------------------------------------------------- - * Template::~Template() : cleans up of Template. - * ----------------------------------------------------------------------------- */ - -Template::~Template() { - Delete(code); - Delete(templateName); -} - -/* ----------------------------------------------------------------------------- - * String* Template::str() : retrieves the current content of the template. - * ----------------------------------------------------------------------------- */ - -String *Template::str() { - if (debug) { - String *pre_code = NewString(""); - String *post_code = NewString(""); - String *debug_code = NewString(""); - Printf(pre_code, "//begin fragment(\"%s\")\n", templateName); - Printf(post_code, "//end fragment(\"%s\")\n", templateName); - Printf(debug_code, "%s\n%s\n%s", pre_code, code, post_code); - - Delete(code); - Delete(pre_code); - Delete(post_code); - - code = debug_code; - } - return code; -} - -/* ----------------------------------------------------------------------------- - * Template& Template::replace(const String* pattern, const String* repl) : - * - * replaces all occurances of a given pattern with a given replacement. - * - * - pattern: the pattern to be replaced - * - repl: the replacement string - * - returns a reference to the Template to allow chaining of methods. - * ----------------------------------------------------------------------------- */ - -Template & Template::replace(const String *pattern, const String *repl) { - ::Replaceall(code, pattern, repl); - return *this; -} Deleted: branches/gsoc2012-javascript/Source/Modules/javascript_emitter.h =================================================================== --- branches/gsoc2012-javascript/Source/Modules/javascript_emitter.h 2012-08-20 18:30:43 UTC (rev 13686) +++ branches/gsoc2012-javascript/Source/Modules/javascript_emitter.h 2012-08-20 18:31:19 UTC (rev 13687) @@ -1,172 +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(const String *code, const String *templateName, bool debug); - - ~Template(); - - String *str(); - - Template & replace(const String *pattern, const String *repl); - - private: - String *code; - String *templateName; - bool debug; - }; - - 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 switchNamespace(Node *) { - return SWIG_OK; - }; - - /** - * Invoked at the beginning of the classHandler. - */ - virtual int enterClass(Node *) { - return SWIG_OK; - }; - - /** - * Invoked at the end of the classHandler. - */ - virtual int exitClass(Node *) { - return SWIG_OK; - }; - - /** - * Invoked at the beginning of the variableHandler. - */ - virtual int enterVariable(Node *) { - return SWIG_OK; - }; - - /** - * Invoked at the end of the variableHandler. - */ - virtual int exitVariable(Node *) { - return SWIG_OK; - }; - - /** - * Invoked at the beginning of the functionHandler. - */ - virtual int enterFunction(Node *) { - return SWIG_OK; - }; - - /** - * Invoked at the end of the functionHandler. - */ - virtual int exitFunction(Node *) { - return SWIG_OK; - }; - - /** - * Invoked by functionWrapper callback after call to Language::functionWrapper. - */ - virtual int emitWrapperFunction(Node *n); - - /** - * Invoked from constantWrapper after call to Language::constantWrapper. - **/ - virtual int emitConstant(Node *n) = 0; - - /** - * 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. - */ - Template getTemplate(const String *name); - - void enableDebug(); - - void setStaticFlag(bool is_static); - - 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); - - void enableDebugTemplates(); - - protected: - - // empty string used at different places in the code - String *empty_string; - - Hash *templates; - - Wrapper *current_wrapper; - - bool is_static; - - bool debug; - }; - - -#endif // JAVASCRIPT_EMITTER_H Deleted: branches/gsoc2012-javascript/Source/Modules/javascript_jsc.cxx =================================================================== --- branches/gsoc2012-javascript/Source/Modules/javascript_jsc.cxx 2012-08-20 18:30:43 UTC (rev 13686) +++ branches/gsoc2012-javascript/Source/Modules/javascript_jsc.cxx 2012-08-20 18:31:19 UTC (rev 13687) @@ -1,745 +0,0 @@ -#include "javascript_jsc.h" -#include "swigmod.h" - -JSCEmitter::JSCEmitter() -: JSEmitter(), NULL_STR(NewString("NULL")) { -} - -JSCEmitter::~JSCEmitter() { - Delete(NULL_STR); -} - -/* --------------------------------------------------------------------- - * skipIgnoredArgs() - * --------------------------------------------------------------------- */ - -Parm *JSCEmitter::skipIgnoredArgs(Parm *p) { - while (checkAttribute(p, "tmap:in:numinputs", "0")) { - p = Getattr(p, "tmap:in:next"); - } - return p; -} - -/* --------------------------------------------------------------------- - * marshalInputArgs() - * - * Process all of the arguments passed into the argv array - * and convert them into C/C++ function arguments using the - * supplied typemaps. - * --------------------------------------------------------------------- */ - -void JSCEmitter::marshalInputArgs(ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { - String *tm; - Parm *p; - - int startIdx = 0; - if (is_member && !is_static) - startIdx = 1; - - - int i = 0; - for (p = parms; p; p = nextSibling(p), i++) { - SwigType *pt = Getattr(p, "type"); - String *arg = NewString(""); - - switch (mode) { - case Getter: - case Function: - if (is_member && !is_static && i == 0) { - Printv(arg, "thisObject", 0); - } else { - Printf(arg, "argv[%d]", i - startIdx); - } - - break; - case Setter: - if (is_member && !is_static && i == 0) { - Printv(arg, "thisObject", 0); - } else { - Printv(arg, "value", 0); - } - break; - case Ctor: - Printf(arg, "argv[%d]",i); - break; - default: - throw "Illegal state."; - } - - tm = Getattr(p, "tmap:in"); // Get typemap for this argument - if ( tm != NULL ) - { - Replaceall(tm, "$input", arg); - Setattr(p, "emit:input", arg); - - if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) { - Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); - } else { - Replaceall(tm, "$disown", "0"); - } - - Printf(wrapper->code, "%s\n", tm); - } else { - Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); - } - Delete(arg); - } -} - -/* --------------------------------------------------------------------- -* marshalOutput() -* -* Process the return value of the C/C++ function call -* and convert them into the Javascript types using the -* supplied typemaps. -* --------------------------------------------------------------------- */ - -void JSCEmitter::marshalOutput(Node *n, String *actioncode, Wrapper *wrapper) { - SwigType *type = Getattr(n, "type"); - Setattr(n, "type", type); - String *tm; - if ((tm = Swig_typemap_lookup_out("out", n, "result", wrapper, actioncode))) { - Replaceall(tm, "$result", "jsresult"); - // TODO: May not be the correct way - Replaceall(tm, "$objecttype", Swig_scopename_last(SwigType_str(SwigType_strip_qualifiers(type), 0))); - - if (GetFlag(n, "feature:new")) { - Replaceall(tm, "$owner", "SWIG_POINTER_OWN"); - } else { - Replaceall(tm, "$owner", "0"); - } - - Printf(wrapper->code, "%s", tm); - if (Len(tm)) - Printf(wrapper->code, "\n"); - } else { - Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), Getattr(n, "name")); - } - emit_return_variable(n, type, wrapper); -} - -int JSCEmitter::initialize(Node *n) { - - /* Get the output file name */ - String *outfile = Getattr(n, "outfile"); - - /* Initialize I/O */ - f_wrap_cpp = NewFile(outfile, "w", SWIG_output_files()); - if (!f_wrap_cpp) { - FileErrorDisplay(outfile); - SWIG_exit(EXIT_FAILURE); - } - - /* Initialization of members */ - f_runtime = NewString(""); - f_init = NewString(""); - f_header = NewString(""); - f_wrappers = NewString(""); - - create_namespaces_code = NewString(""); - register_namespaces_code = NewString(""); - initializer_code = NewString(""); - - - namespaces = NewHash(); - Hash *global_namespace = createNamespaceEntry(Char(Getattr(n, "name")), "global"); - Setattr(namespaces, "::", global_namespace); - current_namespace = global_namespace; - - /* Register file targets with the SWIG file handler */ - Swig_register_filebyname("begin", f_wrap_cpp); - Swig_register_filebyname("header", f_header); - Swig_register_filebyname("wrapper", f_wrappers); - Swig_register_filebyname("runtime", f_runtime); - Swig_register_filebyname("init", f_init); - - return SWIG_OK; -} - -int JSCEmitter::dump(Node *n) { - /* Get the module name */ - String *module = Getattr(n, "name"); - - // write the swig banner - Swig_banner(f_wrap_cpp); - - SwigType_emit_type_table(f_runtime, f_wrappers); - - Printv(f_wrap_cpp, f_runtime, "\n", 0); - Printv(f_wrap_cpp, f_header, "\n", 0); - Printv(f_wrap_cpp, f_wrappers, "\n", 0); - - - emitNamespaces(); - - // compose the initializer function using a template - Template initializer(getTemplate("JS_initializer")); - initializer.replace("${modulename}", module) - .replace("${initializercode}", initializer_code) - .replace("${create_namespaces}", create_namespaces_code) - .replace("${register_namespaces}", register_namespaces_code); - Wrapper_pretty_print(initializer.str(), f_init); - - Printv(f_wrap_cpp, f_init, "\n", 0); - - return SWIG_OK; -} - - -int JSCEmitter::close() { - /* strings */ - Delete(f_runtime); - Delete(f_header); - Delete(f_wrappers); - Delete(f_init); - - Delete(create_namespaces_code); - Delete(register_namespaces_code); - Delete(initializer_code); - - Delete(namespaces); - - /* files */ - ::Close(f_wrap_cpp); - Delete(f_wrap_cpp); - - return SWIG_OK; -} - -int JSCEmitter::enterFunction(Node *n) { - - bool is_overloaded = GetFlag(n, "sym:overloaded"); - - current_functionname = Getattr(n, "sym:name"); - - if(is_overloaded && function_dispatcher_code == 0) { - function_dispatcher_code = NewString(""); - } - - return SWIG_OK; -} - -int JSCEmitter::exitFunction(Node *n) { - Template t_function = getTemplate("JS_functiondecl"); - - String *functionname = current_functionname; - String *functionwrapper = current_functionwrapper; - - bool is_member = GetFlag(n, "ismember"); - - // handle overloaded functions - // Note: wrappers for overloaded functions are currently - // not made available (e.g., foo_double, foo_int) - // maybe this could be enabled by an extra feature flag - bool is_overloaded = GetFlag(n, "sym:overloaded"); - - if(is_overloaded) { - if(!Getattr(n, "sym:nextSibling")) { - - functionwrapper = Swig_name_wrapper(Getattr(n, "name")); - // note: set this attribute to transfer ownership - Setattr(n, "wrap:dispatcher", functionwrapper); - - // create dispatcher - emitFunctionDispatcher(n, is_member); - - Delete(function_dispatcher_code); - function_dispatcher_code = 0; - - } else { - - //don't register wrappers of overloaded functions in function tables - return SWIG_OK; - } - } - - t_function.replace("${functionname}", functionname) - .replace("${functionwrapper}", functionwrapper); - - if (is_member) { - - if (Equal(Getattr(n, "storage"), "static")) { - Printv(class_static_functions_code, t_function.str(), 0); - - } else { - Printv(current_class_functions, t_function.str(), 0); - } - - } else { - Printv(Getattr(current_namespace, "functions"), t_function.str(), 0); - } - - return SWIG_OK; -} - -int JSCEmitter::enterVariable(Node *n) { - current_getter = NULL_STR; - current_setter = NULL_STR; - current_propertyname = Swig_scopename_last(Getattr(n, "name")); - is_immutable = GetFlag(n, "wrap:immutable"); - - return SWIG_OK; -} - - -int JSCEmitter::exitVariable(Node *n) { - Template t_variable(getTemplate("JS_variabledecl")); - t_variable.replace("${setname}", current_setter) - .replace("${getname}", current_getter) - .replace("${propertyname}", current_propertyname); - - - if (GetFlag(n, "ismember")) { - if (Equal(Getattr(n, "storage"), "static") || (Equal(Getattr(n, "nodeType"), "enumitem"))) { - - Printv(class_static_variables_code, t_variable.str(), 0); - - } else { - Printv(class_variables_code, t_variable.str(), 0); - } - } else { - Printv(Getattr(current_namespace, "values"), t_variable.str(), 0); - } - - return SWIG_OK; -} - -int JSCEmitter::enterClass(Node *n) { - - current_classname = Getattr(n, "sym:name"); - c... [truncated message content] |