0
# Embedded Compiler
1
2
Streaming compilation interface optimized for web browsers and embedded environments. Provides incremental compilation with state preservation, making it ideal for REPL-style applications and dynamic code execution.
3
4
## Capabilities
5
6
### Embedded Compiler Factory
7
8
Creates an embedded compiler instance that maintains compilation state across multiple operations.
9
10
```javascript { .api }
11
/**
12
* Create an embedded compiler instance
13
* @param compiler - Main compiler instance from create_compiler()
14
* @param baselib - Base library code as string
15
* @param runjs - JavaScript execution function (default: eval)
16
* @param name - Module name for compiled code (default: '__embedded__')
17
* @returns Embedded compiler interface
18
*/
19
function create_embedded_compiler(
20
compiler: CompilerInstance,
21
baselib: string,
22
runjs?: Function,
23
name?: string
24
): EmbeddedCompiler;
25
26
interface EmbeddedCompiler {
27
/** Compile RapydScript code to JavaScript with state preservation */
28
compile(code: string, options?: EmbeddedCompileOptions): string;
29
/** Current top-level AST node maintaining compilation state */
30
toplevel: AST_Toplevel | null;
31
}
32
```
33
34
**Usage Example:**
35
36
```javascript
37
const { create_compiler } = require("rapydscript-ng");
38
const embedded_compiler = require("rapydscript-ng/tools/embedded_compiler");
39
const fs = require("fs");
40
41
// Create main compiler and load base library
42
const RapydScript = create_compiler();
43
const baselib = fs.readFileSync("path/to/baselib.js", "utf-8");
44
45
// Create embedded compiler
46
const embeddedCompiler = embedded_compiler(
47
RapydScript,
48
baselib,
49
eval,
50
"my_module"
51
);
52
53
// Compile code incrementally
54
const js1 = embeddedCompiler.compile(`
55
def greet(name):
56
return "Hello, " + name
57
`);
58
59
const js2 = embeddedCompiler.compile(`
60
print(greet("World"))
61
`);
62
```
63
64
### Streaming Compilation
65
66
Compile RapydScript source code with incremental state management and flexible output options.
67
68
```javascript { .api }
69
/**
70
* Compile RapydScript code to JavaScript
71
* @param code - RapydScript source code
72
* @param options - Compilation options
73
* @returns Generated JavaScript code
74
*/
75
compile(code: string, options?: EmbeddedCompileOptions): string;
76
77
interface EmbeddedCompileOptions {
78
/** Source filename for error reporting */
79
filename?: string;
80
/** Include base library in output */
81
keep_baselib?: boolean;
82
/** Preserve docstrings as __doc__ attributes */
83
keep_docstrings?: boolean;
84
/** Target JavaScript version (5 or 6) */
85
js_version?: number;
86
/** Wrap output in private scope */
87
private_scope?: boolean;
88
/** Include __name__ assignment */
89
write_name?: boolean;
90
/** Remove assert statements */
91
discard_asserts?: boolean;
92
}
93
```
94
95
**Advanced Usage:**
96
97
```javascript
98
// Configure compilation options
99
const options = {
100
filename: "repl_input.pyj",
101
keep_baselib: false, // Don't repeat baselib
102
keep_docstrings: true, // Preserve documentation
103
js_version: 6, // Use ES6 features
104
private_scope: true, // Wrap in function scope
105
write_name: false, // Skip __name__ assignment
106
discard_asserts: false // Keep assert statements
107
};
108
109
const javascript = embeddedCompiler.compile(`
110
class Calculator:
111
"""A simple calculator class."""
112
113
def add(self, a, b):
114
"""Add two numbers."""
115
assert isinstance(a, (int, float))
116
assert isinstance(b, (int, float))
117
return a + b
118
119
def multiply(self, a, b):
120
"""Multiply two numbers."""
121
return a * b
122
123
calc = Calculator()
124
result = calc.add(5, 3)
125
print("Result:", result)
126
`, options);
127
```
128
129
### State Management
130
131
The embedded compiler maintains compilation state across multiple compile calls, enabling:
132
133
- **Class persistence**: Classes defined in earlier compilations remain available
134
- **Scope preservation**: Variable scopes and flags are maintained
135
- **Export tracking**: Module exports accumulate across compilations
136
- **Incremental compilation**: Build complex applications piece by piece
137
138
**Example - Building an Application Incrementally:**
139
140
```javascript
141
const embeddedCompiler = embedded_compiler(RapydScript, baselib);
142
143
// Step 1: Define utility functions
144
embeddedCompiler.compile(`
145
def utils_multiply(a, b):
146
return a * b
147
148
def utils_format(value):
149
return "Result: " + str(value)
150
`);
151
152
// Step 2: Define main class (can use previously defined functions)
153
embeddedCompiler.compile(`
154
class MathApp:
155
def calculate(self, x, y):
156
result = utils_multiply(x, y)
157
return utils_format(result)
158
`);
159
160
// Step 3: Create and use application
161
const finalJS = embeddedCompiler.compile(`
162
app = MathApp()
163
output = app.calculate(6, 7)
164
print(output) # Prints: Result: 42
165
`);
166
167
// All previous definitions are preserved and available
168
console.log(finalJS);
169
```
170
171
### Web Browser Integration
172
173
The embedded compiler is designed for browser environments and can be integrated into web-based development tools:
174
175
**HTML Integration:**
176
177
```html
178
<!DOCTYPE html>
179
<html>
180
<head>
181
<script src="rapydscript-compiler.js"></script>
182
<script src="rapydscript-baselib.js"></script>
183
</head>
184
<body>
185
<textarea id="code">
186
def fibonacci(n):
187
if n <= 1:
188
return n
189
return fibonacci(n-1) + fibonacci(n-2)
190
191
print(fibonacci(10))
192
</textarea>
193
<button onclick="compileAndRun()">Run</button>
194
<pre id="output"></pre>
195
196
<script>
197
// Create embedded compiler
198
const RapydScript = window.create_compiler();
199
const embeddedCompiler = window.create_embedded_compiler(
200
RapydScript,
201
window.baselib_code,
202
function(code) {
203
// Custom execution function
204
try {
205
return eval(code);
206
} catch(e) {
207
document.getElementById('output').textContent = 'Error: ' + e.message;
208
}
209
}
210
);
211
212
function compileAndRun() {
213
const code = document.getElementById('code').value;
214
try {
215
const js = embeddedCompiler.compile(code);
216
eval(js);
217
} catch(e) {
218
document.getElementById('output').textContent = 'Compilation error: ' + e.message;
219
}
220
}
221
</script>
222
</body>
223
</html>
224
```
225
226
### Error Handling
227
228
The embedded compiler provides detailed error information for debugging:
229
230
```javascript
231
try {
232
const result = embeddedCompiler.compile(`
233
def broken_function(:
234
return "missing parenthesis"
235
`);
236
} catch (error) {
237
if (error instanceof RapydScript.SyntaxError) {
238
console.error(`Syntax error in ${error.filename || '<embedded>'}: ${error.message}`);
239
if (error.line) console.error(`Line ${error.line}, Column ${error.col || 0}`);
240
} else {
241
console.error('Compilation failed:', error.message);
242
}
243
}
244
```