You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

159 lines
5.7 KiB

name: duk_compile
proto: |
void duk_compile(duk_context *ctx, duk_uint_t flags);
stack: |
[ ... source! filename! ] -> [ ... function! ]
summary: |
<p>Compile ECMAScript source code and replace it with a compiled function
object (the code is not executed). The <code>filename</code> argument is stored
as the <code>fileName</code> property of the resulting function, and is the name
used in e.g. tracebacks to identify the function. May throw a <code>SyntaxError</code>
for any compile-time errors (in addition to the usual internal errors like out-of-memory,
internal limit errors, etc).</p>
<p>The following flags may be given:</p>
<table>
<tr>
<td>DUK_COMPILE_EVAL</td>
<td>Compile the input as eval code instead of as an ECMAScript program</td>
</tr>
<tr>
<td>DUK_COMPILE_FUNCTION</td>
<td>Compile the input as a function instead of as an ECMAScript program</td>
</tr>
<tr>
<td>DUK_COMPILE_STRICT</td>
<td>Force the input to be compiled in strict mode</td>
</tr>
<tr>
<td>DUK_COMPILE_SHEBANG</td>
<td>Allow non-standard shebang comment (<code>#! ...</code>) on first line
of the input</td>
</tr>
</table>
<p>The source code being compiled may be:</p>
<ul>
<li>Global code: compiles into a function with zero arguments, which
executes like a top level ECMAScript program (default)</li>
<li>Eval code: compiles into a function with zero arguments, which
executes like an ECMAScript <code>eval</code> call
(flag <code>DUK_COMPILE_EVAL</code>)</li>
<li>Function code: compiles into a function with zero or more arguments
(flag <code>DUK_COMPILE_FUNCTION</code>)</li>
</ul>
<p>All of these have slightly different semantics in ECMAScript. See
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-10.4">Establishing an Execution Context</a>
for a detailed discussion.
One major difference is that global and eval contexts have an implicit
return value: the last <i>non-empty</i> statement value is an automatic
return value for the program or eval code, whereas functions don't have
an automatic return value.
</p>
<p>Global and eval code don't have an explicit <code>function</code> syntax.
For instance, the following can be compiled both as a global and as an
eval expression:</p>
<pre class="ecmascript-code">
print("Hello world!");
123; // implicit return value
</pre>
<p>Function code follows the ECMAScript <code>function</code> syntax
(the function name is optional):</p>
<pre class="ecmascript-code">
function adder(x,y) {
return x+y;
}
</pre>
<p>Compiling a function is equivalent to compiling eval code which contains
a function expression. Note that the outermost parentheses are required,
otherwise the eval code will register a global function named "adder" instead
of returning a plain function value:</p>
<pre class="ecmascript-code">
(function adder(x,y) {
return x+y;
})
</pre>
<p>The bytecode generated for global and eval code is currently slower
than that generated for functions: a "slow path" is used for all variable
accesses in program and eval code, and the implicit return value handling
of program and eval code generates some unnecessary bytecode. From a
performance point of view (both memory and execution performance) it is
thus preferable to have as much code inside functions as possible.</p>
<p>When compiling eval and global expressions, be careful to avoid the
usual ECMAScript gotchas, such as:</p>
<pre class="ecmascript-code">
/* Function at top level is a function declaration which registers a global
* function, and is different from a function expression. Use parentheses
* around the top level expression.
*/
eval("function adder(x,y) { return x+y; }"); /* registers 'adder' to global */
eval("function (x,y) { return x+y; }"); /* not allowed */
eval("(function (x,y) { return x+y; })"); /* function expression (anonymous) */
eval("(function adder(x,y) { return x+y; })"); /* function expression (named) */
/* Opening curly brace at top level is interpreted as start of a block
* expression, not an object literal. Use parentheses around the top
* level expression.
*/
eval("{ myfunc: 1 }"); /* block with -label- "myfunc" and statement "1" (!) */
eval("({ myfunc: 1 })"; /* object literal { myfunc: 1 } */
</pre>
example: |
/* Global code. Note that the hello() function is a function
* declaration which gets registered into the global object when
* executed. Implicit return value is 123.
*/
duk_push_string(ctx, "print('global');\n"
"function hello() { print('Hello world!'); }\n"
"123;");
duk_push_string(ctx, "hello");
duk_compile(ctx, 0); /* [ source filename ] -> [ func ] */
duk_call(ctx, 0); /* [ func ] -> [ result ] */
printf("program result: %lf\n", (double) duk_get_number(ctx, -1));
duk_pop(ctx);
/* Eval code */
duk_push_string(ctx, "2+3");
duk_push_string(ctx, "eval");
duk_compile(ctx, DUK_COMPILE_EVAL);
duk_call(ctx, 0); /* [ func ] -> [ result ] */
printf("eval result: %lf\n", (double) duk_get_number(ctx, -1));
duk_pop(ctx);
/* Function code */
duk_push_string(ctx, "function (x,y) { return x+y; }");
duk_push_string(ctx, "function");
duk_compile(ctx, DUK_COMPILE_FUNCTION);
duk_push_int(ctx, 5);
duk_push_int(ctx, 6);
duk_call(ctx, 2); /* [ func 5 6 ] -> [ result ] */
printf("function result: %lf\n", (double) duk_get_number(ctx, -1));
duk_pop(ctx);
tags:
- compile
seealso:
- duk_pcompile
- duk_compile_string
- duk_compile_string_filename
- duk_compile_lstring
- duk_compile_lstring_filename
introduced: 1.0.0