More Javascript module documentation.
This commit is contained in:
parent
02c55fc52f
commit
fa8b350cd6
1 changed files with 193 additions and 232 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
% SWIG and Javascript
|
# SWIG and Javascript
|
||||||
|
|
||||||
This chapter describes SWIG's support of Javascript.
|
This chapter describes SWIG's support of Javascript.
|
||||||
It does not cover SWIG basics only information that is specific to this module.
|
It does not cover SWIG basics only information that is specific to this module.
|
||||||
|
|
||||||
# Overview
|
## Overview
|
||||||
|
|
||||||
JavaScript is a prototype-based scripting language that is dynamic, weakly typed
|
JavaScript is a prototype-based scripting language that is dynamic, weakly typed
|
||||||
and has first-class functions. Its arguably the most popular language for web development.
|
and has first-class functions. Its arguably the most popular language for web development.
|
||||||
|
|
@ -14,42 +14,36 @@ Native Javascript extensions can be used for applications that embed a web-brows
|
||||||
that embed a Javascript engine (such as *node.js*).
|
that embed a Javascript engine (such as *node.js*).
|
||||||
Extending a general purpose web-browser is not possible as this would be severe security issue.
|
Extending a general purpose web-browser is not possible as this would be severe security issue.
|
||||||
|
|
||||||
With [WebKit](http://www.webkit.org/) there is an modern and open-source browser
|
|
||||||
implementations available which can be embedded into an application.
|
|
||||||
At the moment, [Chromium Embedded Framework](http://code.google.com/p/chromiumembedded/)
|
|
||||||
can not be extended as CEF does not provide access to the V8 engine, but instead comes with
|
|
||||||
its own extension mechanism.
|
|
||||||
|
|
||||||
SWIG Javasript currently supports **JavascriptCore**, the Javascript engine used by `Safari`,
|
SWIG Javasript currently supports **JavascriptCore**, the Javascript engine used by `Safari`,
|
||||||
and **v8**, which is used by `Chromium` and `node.js`.
|
and **v8**, which is used by `Chromium` and `node.js`.
|
||||||
|
|
||||||
# Preliminaries
|
With [WebKit](http://www.webkit.org/) there is a modern browser
|
||||||
|
implementation available as open-source which can be embedded into an application.
|
||||||
|
Unfortunately, [Chromium Embedded Framework](http://code.google.com/p/chromiumembedded/)
|
||||||
|
does not provide access to the native V8 engine, making it impossible to extend the engine
|
||||||
|
using the Javascript module.
|
||||||
|
|
||||||
# Running SWIG
|
## Preliminaries
|
||||||
|
|
||||||
|
### Running SWIG
|
||||||
|
|
||||||
Suppose that you defined a SWIG module such as the following:
|
Suppose that you defined a SWIG module such as the following:
|
||||||
|
|
||||||
```code
|
%module example
|
||||||
%module example
|
%{
|
||||||
%{
|
#include "example.h"
|
||||||
#include "example.h"
|
%}
|
||||||
%}
|
int gcd(int x, int y);
|
||||||
int gcd(int x, int y);
|
extern double Foo;
|
||||||
extern double Foo;
|
|
||||||
```
|
|
||||||
|
|
||||||
To build a Javascript module, run SWIG using the `-javascript` option
|
To build a Javascript module, run SWIG using the `-javascript` option
|
||||||
and a desired target engine `-jsc` or `-v8`.
|
and a desired target engine `-jsc` or `-v8`.
|
||||||
|
|
||||||
```shell
|
$ swig -javascript -jsc example.i
|
||||||
$ swig -javascript -jsc example.i
|
|
||||||
```
|
|
||||||
|
|
||||||
If building a C++ extension, add the -c++ option:
|
If building a C++ extension, add the -c++ option:
|
||||||
|
|
||||||
```shell
|
$ swig -c++ -javascript -jsc example.i
|
||||||
$ swig -c++ -javascript -jsc example.i
|
|
||||||
```
|
|
||||||
|
|
||||||
This creates a C/C++ source file example_wrap.c or example_wrap.cxx. The generated C source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application to create an extension module.
|
This creates a C/C++ source file example_wrap.c or example_wrap.cxx. The generated C source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application to create an extension module.
|
||||||
|
|
||||||
|
|
@ -59,15 +53,11 @@ To change this, you can use the -o option.
|
||||||
The wrapped module will export one function which must be called to register the module with the Javascript interpreter.
|
The wrapped module will export one function which must be called to register the module with the Javascript interpreter.
|
||||||
For example, if your module is named `example` the corresponding initializer for JavascriptCore would be
|
For example, if your module is named `example` the corresponding initializer for JavascriptCore would be
|
||||||
|
|
||||||
```code
|
bool example_initialize(JSGlobalContextRef context, JSObjectRef *exports)
|
||||||
bool example_initialize(JSGlobalContextRef context, JSObjectRef *exports)
|
|
||||||
```
|
|
||||||
|
|
||||||
and for v8:
|
and for v8:
|
||||||
|
|
||||||
```code
|
void example_initialize (v8::Handle<v8::Object> exports)
|
||||||
void example_initialize (v8::Handle<v8::Object> exports)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Missing features
|
## Missing features
|
||||||
|
|
||||||
|
|
@ -75,26 +65,22 @@ The Javascript module is not yet as mature as other modules and some things are
|
||||||
As it makes use of Swigs Unified typemap library (UTL), many typemaps are inherited.
|
As it makes use of Swigs Unified typemap library (UTL), many typemaps are inherited.
|
||||||
|
|
||||||
- Director support
|
- Director support
|
||||||
- TODO: there is more
|
- TODO: hmpf... I suppose there is more
|
||||||
|
|
||||||
|
## Compilation and Linking
|
||||||
|
|
||||||
# Compilation and Linking
|
### Installation
|
||||||
|
|
||||||
## Installation
|
### Dealing with `v8` version incompatibilities
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Dealing with `v8` version incompatibilities
|
|
||||||
|
|
||||||
Unfortunately, v8 does not provide pre-processor macros do detect which version you link to.
|
Unfortunately, v8 does not provide pre-processor macros do detect which version you link to.
|
||||||
Therefore, you have to provide this information manually.
|
Therefore, you have to provide this information manually.
|
||||||
|
|
||||||
|
## Integration
|
||||||
# Integration
|
|
||||||
|
|
||||||
This should give a short overview how to integrate your module in different environments: as a `node.js` module, and as an extension for an embedded Chromium.
|
This should give a short overview how to integrate your module in different environments: as a `node.js` module, and as an extension for an embedded Chromium.
|
||||||
|
|
||||||
## Creating `node.js` Extensions
|
### Creating `node.js` Extensions
|
||||||
|
|
||||||
As `v8` is written in C++ and comes as a C++ library it is crucial to compile your module using the
|
As `v8` is written in C++ and comes as a C++ library it is crucial to compile your module using the
|
||||||
same compiler flags as used for building v8. To make things easier, `node.js` provides a build tool called `node-gyp`.
|
same compiler flags as used for building v8. To make things easier, `node.js` provides a build tool called `node-gyp`.
|
||||||
|
|
@ -103,138 +89,132 @@ This expects configuration file named `binding.gyp` which is basically in JSON f
|
||||||
conforms to the same format that is used with Google's build-tool `gyp`.
|
conforms to the same format that is used with Google's build-tool `gyp`.
|
||||||
|
|
||||||
`binding.gyp`:
|
`binding.gyp`:
|
||||||
```code
|
|
||||||
{
|
|
||||||
"targets": [
|
|
||||||
{
|
{
|
||||||
"target_name": "example",
|
"targets": [
|
||||||
"sources": [ "example.cxx", "example_wrap.cxx" ]
|
{
|
||||||
|
"target_name": "example",
|
||||||
|
"sources": [ "example.cxx", "example_wrap.cxx" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
First you would create the wrapper using SWIG:
|
First you would create the wrapper using SWIG:
|
||||||
|
|
||||||
```shell
|
|
||||||
|
|
||||||
```
|
### Embedded Webkit
|
||||||
|
|
||||||
## Embedded Webkit
|
|
||||||
|
|
||||||
TODO: Here a minimal example of how to implement
|
TODO: Here a minimal example of how to implement
|
||||||
|
|
||||||
# Implementation
|
## Implementation
|
||||||
|
|
||||||
The Javascript Module implementation has take a very different approach than other modules
|
The Javascript Module implementation has take a very different approach than other modules
|
||||||
to be able to generate code for different Javascript interpreters.
|
to be able to generate code for different Javascript interpreters.
|
||||||
|
|
||||||
|
|
||||||
## Module Source Code
|
### Module Source Code
|
||||||
|
|
||||||
The Javascript module is implemented in `Source/Modules/javascript.cxx`.
|
The Javascript module is implemented in `Source/Modules/javascript.cxx`.
|
||||||
It dispatches the code generation to a `JSEmitter` instance, `V8Emitter` or `JSCEmitter`. Additionally there are some helpers: `Template`, for templated code generation, and `JSEmitterState`, which is used to manage state information during AST traversal.
|
It dispatches the code generation to a `JSEmitter` instance, `V8Emitter` or `JSCEmitter`. Additionally there are some helpers: `Template`, for templated code generation, and `JSEmitterState`, which is used to manage state information during AST traversal.
|
||||||
This is a rough map shall make it easier to find a way through this huge source file:
|
This is a rough map shall make it easier to find a way through this huge source file:
|
||||||
|
|
||||||
```code
|
// module wide defines
|
||||||
// module wide defines
|
|
||||||
|
|
||||||
#define NAME "name"
|
#define NAME "name"
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
// Helper class declarations
|
// Helper class declarations
|
||||||
class JSEmitterState { ... };
|
class JSEmitterState { ... };
|
||||||
|
|
||||||
class Template { ... };
|
class Template { ... };
|
||||||
|
|
||||||
|
|
||||||
// JSEmitter declaration
|
// JSEmitter declaration
|
||||||
|
|
||||||
class JSEmitter { ... };
|
class JSEmitter { ... };
|
||||||
|
|
||||||
|
|
||||||
// Emitter factory declarations
|
// Emitter factory declarations
|
||||||
|
|
||||||
JSEmitter *swig_javascript_create_JSCEmitter();
|
JSEmitter *swig_javascript_create_JSCEmitter();
|
||||||
JSEmitter *swig_javascript_create_V8Emitter();
|
JSEmitter *swig_javascript_create_V8Emitter();
|
||||||
|
|
||||||
|
|
||||||
// Javascript module class declaration
|
// Javascript module class declaration
|
||||||
|
|
||||||
class JAVASCRIPT:public Language { ... };
|
class JAVASCRIPT:public Language { ... };
|
||||||
|
|
||||||
|
|
||||||
// Javascript module function definitions
|
// Javascript module function definitions
|
||||||
|
|
||||||
int JAVASCRIPT::functionWrapper(Node *n) { ... }
|
int JAVASCRIPT::functionWrapper(Node *n) { ... }
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
// Module factory implementations
|
// Module factory implementations
|
||||||
|
|
||||||
static Language *new_swig_javascript() { ... }
|
static Language *new_swig_javascript() { ... }
|
||||||
|
|
||||||
extern "C" Language *swig_javascript(void) { ... }
|
extern "C" Language *swig_javascript(void) { ... }
|
||||||
|
|
||||||
|
|
||||||
// JSEmitter implementation
|
// JSEmitter implementation
|
||||||
|
|
||||||
JSEmitter::JSEmitter() { ... }
|
JSEmitter::JSEmitter() { ... }
|
||||||
|
|
||||||
Template JSEmitter::getTemplate(const String *name) { ... }
|
Template JSEmitter::getTemplate(const String *name) { ... }
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
// JSCEmitter declaration
|
// JSCEmitter declaration
|
||||||
|
|
||||||
class JSCEmitter: public JSEmitter { ... };
|
class JSCEmitter: public JSEmitter { ... };
|
||||||
|
|
||||||
|
|
||||||
// JSCEmitter implementation
|
// JSCEmitter implementation
|
||||||
|
|
||||||
JSCEmitter::JSCEmitter() { ... }
|
JSCEmitter::JSCEmitter() { ... }
|
||||||
|
|
||||||
void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { ... }
|
void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { ... }
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
// JSCEmitter factory
|
// JSCEmitter factory
|
||||||
|
|
||||||
JSEmitter *swig_javascript_create_JSCEmitter() { ... }
|
JSEmitter *swig_javascript_create_JSCEmitter() { ... }
|
||||||
|
|
||||||
|
|
||||||
// V8Emitter declaration
|
// V8Emitter declaration
|
||||||
|
|
||||||
class V8Emitter: public JSEmitter { ... };
|
class V8Emitter: public JSEmitter { ... };
|
||||||
|
|
||||||
|
|
||||||
// V8Emitter implementation
|
// V8Emitter implementation
|
||||||
|
|
||||||
V8Emitter::V8Emitter() { ... }
|
V8Emitter::V8Emitter() { ... }
|
||||||
|
|
||||||
int V8Emitter::initialize(Node *n) { ... }
|
int V8Emitter::initialize(Node *n) { ... }
|
||||||
|
|
||||||
|
|
||||||
// V8Emitter factory
|
// V8Emitter factory
|
||||||
|
|
||||||
JSEmitter *swig_javascript_create_V8Emitter() { ... }
|
JSEmitter *swig_javascript_create_V8Emitter() { ... }
|
||||||
|
|
||||||
|
|
||||||
// Helper implementation (JSEmitterState, Template)
|
// Helper implementation (JSEmitterState, Template)
|
||||||
|
|
||||||
JSEmitterState::JSEmitterState() { ... }
|
JSEmitterState::JSEmitterState() { ... }
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
Template::Template(const String *code_) { ... }
|
Template::Template(const String *code_) { ... }
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Code Templates
|
### Code Templates
|
||||||
|
|
||||||
All generated code is created on the basis of code templates.
|
All generated code is created on the basis of code templates.
|
||||||
The templates for *JavascriptCore* can be found in `Lib/javascript/jsc/javascriptcode.swg`,
|
The templates for *JavascriptCore* can be found in `Lib/javascript/jsc/javascriptcode.swg`,
|
||||||
|
|
@ -242,213 +222,194 @@ for *v8* in `Lib/javascript/v8/javascriptcode.swg`.
|
||||||
|
|
||||||
To track the originating code template for generated code you can run
|
To track the originating code template for generated code you can run
|
||||||
|
|
||||||
```shell
|
$ swig -javascript -jsc -debug-codetemplates
|
||||||
swig -javascript -jsc -debug-codetemplates
|
|
||||||
```
|
|
||||||
|
|
||||||
which wraps generated code with a descriptive comment
|
which wraps generated code with a descriptive comment
|
||||||
|
|
||||||
```code
|
/* begin fragment("temlate_name") */
|
||||||
/* begin fragment("temlate_name") */
|
|
||||||
|
|
||||||
...generated code ...
|
...generated code ...
|
||||||
|
|
||||||
/* end fragment("temlate_name") */
|
/* end fragment("temlate_name") */
|
||||||
```
|
|
||||||
|
|
||||||
The Template class is used like this:
|
The Template class is used like this:
|
||||||
|
|
||||||
```code
|
Template t_register = getTemplate("jsv8_register_static_variable");
|
||||||
Template t_register = getTemplate("jsv8_register_static_variable");
|
t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
|
||||||
t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
|
.replace("$jsname", state.variable(NAME))
|
||||||
.replace("$jsname", state.variable(NAME))
|
.replace("$jsgetter", state.variable(GETTER))
|
||||||
.replace("$jsgetter", state.variable(GETTER))
|
.replace("$jssetter", state.variable(SETTER))
|
||||||
.replace("$jssetter", state.variable(SETTER))
|
.trim().
|
||||||
.trim().
|
print(f_init_static_wrappers);
|
||||||
print(f_init_static_wrappers);
|
|
||||||
```
|
|
||||||
|
|
||||||
A code template is registered with the *JSEmitter* via `fragment(name, "template")`, e.g.,
|
A code template is registered with the *JSEmitter* via `fragment(name, "template")`, e.g.,
|
||||||
|
|
||||||
```code
|
%fragment ("jsc_variable_declaration", "templates")
|
||||||
%fragment ("jsc_variable_declaration", "templates")
|
%{
|
||||||
%{
|
{"$jsname", $jsgetter, $jssetter, kJSPropertyAttributeNone},
|
||||||
{"$jsname", $jsgetter, $jssetter, kJSPropertyAttributeNone},
|
%}
|
||||||
%}
|
|
||||||
```
|
|
||||||
|
|
||||||
`Template` creates a copy of that string and `Template::replace` uses Swig's `Replaceall`
|
`Template` creates a copy of that string and `Template::replace` uses Swig's `Replaceall`
|
||||||
to replace variables in the template. `Template::trim` can be used to eliminate
|
to replace variables in the template. `Template::trim` can be used to eliminate
|
||||||
leading and trailing whitespaces. `Template::print` is used to write the final template string
|
leading and trailing whitespaces. `Template::print` is used to write the final template string
|
||||||
to a Swig `DOH` (based on `Printv`). All methods allow chaining.
|
to a Swig `DOH` (based on `Printv`). All methods allow chaining.
|
||||||
|
|
||||||
|
### Emitter
|
||||||
## Emitter
|
|
||||||
|
|
||||||
The Javascript module delegates code generation to a `JSEmitter` instance.
|
The Javascript module delegates code generation to a `JSEmitter` instance.
|
||||||
The following extract shows the essential interface:
|
The following extract shows the essential interface:
|
||||||
|
|
||||||
```code
|
class JSEmitter {
|
||||||
class JSEmitter {
|
...
|
||||||
...
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens output files and temporary output DOHs.
|
* Opens output files and temporary output DOHs.
|
||||||
*/
|
*/
|
||||||
virtual int initialize(Node *n);
|
virtual int initialize(Node *n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes all collected code into the output file(s).
|
* Writes all collected code into the output file(s).
|
||||||
*/
|
*/
|
||||||
virtual int dump(Node *n) = 0;
|
virtual int dump(Node *n) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up all open output DOHs.
|
* Cleans up all open output DOHs.
|
||||||
*/
|
*/
|
||||||
virtual int close() = 0;
|
virtual int close() = 0;
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked at the beginning of the classHandler.
|
* Invoked at the beginning of the classHandler.
|
||||||
*/
|
*/
|
||||||
virtual int enterClass(Node *);
|
virtual int enterClass(Node *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked at the end of the classHandler.
|
* Invoked at the end of the classHandler.
|
||||||
*/
|
*/
|
||||||
virtual int exitClass(Node *) {
|
virtual int exitClass(Node *) {
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked at the beginning of the variableHandler.
|
* Invoked at the beginning of the variableHandler.
|
||||||
*/
|
*/
|
||||||
virtual int enterVariable(Node *);
|
virtual int enterVariable(Node *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked at the end of the variableHandler.
|
* Invoked at the end of the variableHandler.
|
||||||
*/
|
*/
|
||||||
virtual int exitVariable(Node *) {
|
virtual int exitVariable(Node *) {
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked at the beginning of the functionHandler.
|
* Invoked at the beginning of the functionHandler.
|
||||||
*/
|
*/
|
||||||
virtual int enterFunction(Node *);
|
virtual int enterFunction(Node *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked at the end of the functionHandler.
|
* Invoked at the end of the functionHandler.
|
||||||
*/
|
*/
|
||||||
virtual int exitFunction(Node *) {
|
virtual int exitFunction(Node *) {
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked by functionWrapper callback after call to Language::functionWrapper.
|
* Invoked by functionWrapper callback after call to Language::functionWrapper.
|
||||||
*/
|
*/
|
||||||
virtual int emitWrapperFunction(Node *n);
|
virtual int emitWrapperFunction(Node *n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked from constantWrapper after call to Language::constantWrapper.
|
* Invoked from constantWrapper after call to Language::constantWrapper.
|
||||||
**/
|
**/
|
||||||
virtual int emitConstant(Node *n);
|
virtual int emitConstant(Node *n);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a given code snippet for a given key name.
|
* Registers a given code snippet for a given key name.
|
||||||
*
|
*
|
||||||
* This method is called by the fragmentDirective handler
|
* This method is called by the fragmentDirective handler
|
||||||
* of the JAVASCRIPT language module.
|
* of the JAVASCRIPT language module.
|
||||||
**/
|
**/
|
||||||
int registerTemplate(const String *name, const String *code);
|
int registerTemplate(const String *name, const String *code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the code template registered for a given name.
|
* Retrieve the code template registered for a given name.
|
||||||
*/
|
*/
|
||||||
Template getTemplate(const String *name);
|
Template getTemplate(const String *name);
|
||||||
|
|
||||||
State &getState();
|
State &getState();
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
The module calls `initialize`, `dump`, and `close` from within the `top` method:
|
The module calls `initialize`, `dump`, and `close` from within the `top` method:
|
||||||
|
|
||||||
```code
|
int JAVASCRIPT::top(Node *n) {
|
||||||
int JAVASCRIPT::top(Node *n) {
|
emitter->initialize(n);
|
||||||
emitter->initialize(n);
|
|
||||||
|
|
||||||
Language::top(n);
|
Language::top(n);
|
||||||
|
|
||||||
emitter->dump(n);
|
emitter->dump(n);
|
||||||
emitter->close();
|
emitter->close();
|
||||||
|
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
The methods `enterClass` and `exitClass` are called from within the `classHandler` method:
|
The methods `enterClass` and `exitClass` are called from within the `classHandler` method:
|
||||||
|
|
||||||
```code
|
int JAVASCRIPT::classHandler(Node *n) {
|
||||||
int JAVASCRIPT::classHandler(Node *n) {
|
|
||||||
|
|
||||||
emitter->enterClass(n);
|
emitter->enterClass(n);
|
||||||
Language::classHandler(n);
|
Language::classHandler(n);
|
||||||
emitter->exitClass(n);
|
emitter->exitClass(n);
|
||||||
|
|
||||||
return SWIG_OK;
|
return SWIG_OK;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
In `enterClass` the emitter stores state information that is necessary when processing class members. In `exitClass` the wrapper code for the whole class is generated.
|
In `enterClass` the emitter stores state information that is necessary when processing class members. In `exitClass` the wrapper code for the whole class is generated.
|
||||||
|
|
||||||
|
|
||||||
## Emitter states
|
### Emitter states
|
||||||
|
|
||||||
For storing information during the AST traversal the emitter provides a `JSEmitterState` with
|
For storing information during the AST traversal the emitter provides a `JSEmitterState` with
|
||||||
different slots to store data representing the scopes global, class, function, and variable.
|
different slots to store data representing the scopes global, class, function, and variable.
|
||||||
|
|
||||||
```code
|
class JSEmitterState {
|
||||||
class JSEmitterState {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
JSEmitterState();
|
JSEmitterState();
|
||||||
|
|
||||||
~JSEmitterState();
|
~JSEmitterState();
|
||||||
|
|
||||||
DOH *global();
|
DOH *global();
|
||||||
|
|
||||||
DOH *global(const char* key, DOH *initial = 0);
|
DOH *global(const char* key, DOH *initial = 0);
|
||||||
|
|
||||||
DOH *clazz(bool reset = false);
|
DOH *clazz(bool reset = false);
|
||||||
|
|
||||||
DOH *clazz(const char* key, DOH *initial = 0);
|
DOH *clazz(const char* key, DOH *initial = 0);
|
||||||
|
|
||||||
DOH *function(bool reset = false);
|
DOH *function(bool reset = false);
|
||||||
|
|
||||||
DOH *function(const char* key, DOH *initial = 0);
|
DOH *function(const char* key, DOH *initial = 0);
|
||||||
|
|
||||||
DOH *variable(bool reset = false);
|
DOH *variable(bool reset = false);
|
||||||
|
|
||||||
DOH *variable(const char* key, DOH *initial = 0);
|
DOH *variable(const char* key, DOH *initial = 0);
|
||||||
|
|
||||||
static int IsSet(DOH *val);
|
static int IsSet(DOH *val);
|
||||||
|
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
```
|
|
||||||
|
|
||||||
When entering a scope, such as in `enterClass`, the corresponding state is reset and new data
|
When entering a scope, such as in `enterClass`, the corresponding state is reset and new data
|
||||||
is stored:
|
is stored:
|
||||||
|
|
||||||
```code
|
state.clazz(RESET);
|
||||||
state.clazz(RESET);
|
state.clazz(NAME, Getattr(n, "sym:name"));
|
||||||
state.clazz(NAME, Getattr(n, "sym:name"));
|
|
||||||
```
|
|
||||||
|
|
||||||
State information can be retrieved using `state.clazz(NAME)` or
|
State information can be retrieved using `state.clazz(NAME)` or
|
||||||
with `Getattr` on `state.clazz()` which actually returns a `Hash` instance.
|
with `Getattr` on `state.clazz()` which actually returns a `Hash` instance.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue