diff --git a/Doc/Devel/Javascript/V8_CodeGeneratorSpecification.md b/Doc/Devel/Javascript/V8_CodeGeneratorSpecification.md index b7d06e220..891b46b17 100644 --- a/Doc/Devel/Javascript/V8_CodeGeneratorSpecification.md +++ b/Doc/Devel/Javascript/V8_CodeGeneratorSpecification.md @@ -41,12 +41,12 @@ The generated code consists of the following blocks: Static references to class templates which are (should be) read-only and can be reused. ~~~~ -v8::Persistent SWIGV8_$CLASSNAME; +v8::Persistent SWIGV8_${NAME_MANGLED}; ~~~~ Notes: - it is very important to consider namespaces from the beginning. - `CLASSNAME` should be the mangled qualified class name, e.g., `foo_bar_MyClass` for `foo::bar::MyClass`, + `NAME_MANGLED` is the mangled qualified class name, e.g., `foo_bar_MyClass` for `foo::bar::MyClass`, which is retrieved ny `Swig_string_mangle(Getattr(n, "name"))` - namespaces do not need a function template, as they will not be instantiated @@ -67,115 +67,96 @@ TODO ## Constructors ~~~~ -v8::Handle $CLASSNAME_new(const v8::Arguments& args) { +v8::Handle ${NAME_MANGLED}_new(const v8::Arguments& args) { v8::HandleScope scope; - - // retrieve the instance v8::Handle self = args.Holder(); - - // TODO: declare arguments - - //convert JS arguments to C++ - // TODO: apply input typemaps - - $CLASS_LVAL* ptr = new $CLASS_LVAL($ARGS); + ${LOCALS} + ${MARSHAL_INPUT} + ${ACTION} self->SetInternalField(0, v8::External::New(ptr)); - return self; } ~~~~ -- `$CLASS_LVAL`: should be the canonical name of the class, e.g. `ns1::ns2::MyClass`, - which can be retrieved using `Getattr(n, "name")` -- `$ARGS`: arguments should be declared at the beginning and checked and set in the - input typemap block +- `LOCALS`: declaration and marshalling for input arguments +- `MARSHAL_INPUT`: code is generated by applying input typemaps +- `ACTION`: the C/C++ ctor to be executed ## Destructors -TODO +TODO: I haven't found out yet how a descrtuctor can be registered ## Getters ~~~~ -v8::Handle $CLASSNAME_get$VARNAME(v8::Local property, const v8::AccessorInfo& info) { +v8::Handle ${NAME_MANGLED}_get(v8::Local property, const v8::AccessorInfo& info) { v8::HandleScope scope; - - // retrieve pointer to C++-this - $CLASS_LVAL* self = SWIGV8_UnwrapThisPointer<$CLASS_LVAL>(info.Holder()); - $RET_LVAL retval = self->$VARNAME; - - v8::Handle ret = ; + v8::Handle ret; + ${LOCALS} + ${ACTION} + ${MARSHAL_OUTPUT} return scope.Close(ret); } ~~~~ -- TODO: output typemapping +- `NAME_MANGLED`: the qualified mangled name of the variable, E.g., `foo::x -> foo_x`, `A.x -> A_x` +- `LOCALS`: declare C return variable +- `MARSHAL_OUTPUT`: code is generated by applying output typemaps ## Setters ~~~~ -void $CLASSNAME_set$VARNAME(v8::Local property, v8::Local value, const v8::AccessorInfo& info) { - v8::HandleScope scope; - - // retrieve pointer to this - $CLASS_LVAL* self = SWIGV8_UnwrapThisPointer<$CLASS_LVAL>(info.Holder()); - - // TODO: declare input arg - - // map java-script type to C++ type - self->$VARNAME = ; - +void ${NAME_MANGLED}_set(v8::Local property, v8::Local value, const v8::AccessorInfo& info) { + ${LOCALS} + ${MARSHAL_INPUT} + ${ACTION} } ~~~~ +- `NAME_MANGLED`: the qualified mangled name of the variable, E.g., `foo::x -> foo_x`, `A.x -> A_x` +- `LOCALS`: declarations for input arguments +- `MARSHAL_INPUT`: code is generated by applying input typemaps -TODO: - - input type mapping should be addressed in extra step, together with type check - -## Member functions +## Functions ~~~~ -v8::Handle $CLASSNAME_$FUNCTIONNAME(const v8::Arguments& args) -{ +v8::Handle ${NAME_MANGLED}(const Arguments &args) { v8::HandleScope scope; - - $CLASS_LVAL* self = SWIGV8_UnwrapThisPointer<$CLASS_LVAL>(args.Holder()); - - // TODO: declare input args - - //convert JS arguments to C++ - // TODO: input typemappings and type checking - - //call C++ method - $RET_LTYPE result = self->$FUNCTIONNAME($ARGS); - - //convert C++ JS arguments to C++ - v8::Handle ret = ; - + v8::Handle ret; + ${LOCALS} + ${MARSHAL_INPUT} + ${ACTION} + ${MARSHAL_OUTPUT} return scope.Close(ret); } ~~~~ - if the function does not have a return value, return v8::Undefined +## Overloading + +TODO: if a function or a ctor is overloaded, a dispatcher function +must be generated which calls overloading wrappers depending on number +and type of input arguments. + ## Initializer ~~~~ -void $MODULENAME_Initialize(v8::Handle context) +void ${MODULE}_Initialize(v8::Handle context) { v8::HandleScope scope; // register the module in globale context v8::Local global = context->Global(); - - - + ${PART_NAMESPACES} - + ${PART_CLASS_TEMPLATES} - + ${PART_WRAPPERS} - + ${PART_INHERITANCE} + + ${PART_REGISTER} } ~~~~ @@ -188,11 +169,10 @@ in the according parent contexts. ## Create Class Template ~~~~ - SWIGV8_$CLASSNAME = SWIGV8_CreateClassTemplate("$LOCAL_CLASSNAME" , $CLASSNAME_new); +SWIGV8_${NAME_MANGLED} = SWIGV8_CreateClassTemplate("${NAME_UNQUALIFIED}" , ${NAME_MANGLED}_new); ~~~~ -- `LOCAL_CLASSNAME`: the class name without context, i.e., namespaces, - which is retrieved by `Getattr(n, "sym:name")` +- `NAME_UNQUALIFIED`: the class name without context, i.e., namespaces ## Add Member Function @@ -216,7 +196,7 @@ in the according parent contexts. ## Inheritance ~~~~ - SWIGV8_$CLASSNAME->Inherit(SWIGV8_$SUPERCLASS); +SWIGV8_${NAME_MANGLED}->Inherit(SWIGV8_${BASE_CLASS}); ~~~~ - Note: multiple inheritance is not possible; thus we will always take the first parent class @@ -224,7 +204,7 @@ in the according parent contexts. ## Register class ~~~~ - $CONTEXT->Set(v8::String::NewSymbol("$LOCAL_CLASSNAME"), SWIGV8_$CLASSNAME->GetFunction()); +${CONTEXT}->Set(v8::String::NewSymbol("${NAME_UNQUALIFIED}", SWIGV8_${NAME_MANGLED}->GetFunction())); ~~~~ - Note: every class template has an associated ctor function wrapper, which is registered here diff --git a/Lib/javascript/v8/javascriptcode.swg b/Lib/javascript/v8/javascriptcode.swg index 1b6d33662..2671fc117 100644 --- a/Lib/javascript/v8/javascriptcode.swg +++ b/Lib/javascript/v8/javascriptcode.swg @@ -35,6 +35,7 @@ v8::Handle ${NAME_MANGLED}_new(const v8::Arguments& args) { v8::HandleScope scope; v8::Handle self = args.Holder(); ${LOCALS} + ${MARSHAL_INPUT} ${ACTION} self->SetInternalField(0, v8::External::New(ptr)); return self;