diff --git a/website/guide/gettingstarted.html b/website/guide/gettingstarted.html index 3ad62252..da25bf45 100644 --- a/website/guide/gettingstarted.html +++ b/website/guide/gettingstarted.html @@ -39,24 +39,7 @@ Hello world!
You can also run Ecmascript code from a file which is useful for playing with features and algorithms. As an example, create fib.js:
--// fib.js -function fib(n) { - if (n == 0) { return 0; } - if (n == 1) { return 1; } - return fib(n-1) + fib(n-2); -} - -function test() { - var res = []; - for (i = 0; i < 20; i++) { - res.push(fib(i)); - } - print(res.join(' ')); -} - -test(); -+
Test the script from the command line:
@@ -114,72 +97,12 @@ without recompiling the C program. line processing function converts a plain text line into HTML, and automatically bolds text between stars: --// process.js -function processLine(line) { - return line.trim() - .replace(/[<>&"'\u0000-\u001F\u007E-\uFFFF]/g, function(x) { - // escape HTML characters - return '&#' + x.charCodeAt(0) + ';' - }) - .replace(/\*(.*?)\*/g, function(x, m) { - // automatically bold text between stars - return '<b>' + m + '</b>'; - }); -} -+The C code, processlines.c initializes a Duktape context, compiles the script, then proceeds to process lines from stdin, calling processLine() for every line:
--/* processlines.c */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "duktape.h" - -int main(int argc, const char *argv[]) { - duk_context *ctx = NULL; - char line[4096]; - char idx; - int ch; - - ctx = duk_create_heap_default(); - if (!ctx) { exit(1); } - - duk_eval_file(ctx, "process.js"); - duk_pop(ctx); /* pop eval result */ - - memset(line, 0, sizeof(line)); - idx = 0; - for (;;) { - if (idx >= sizeof(line)) { exit(1); } - - ch = fgetc(stdin); - if (ch == 0x0a) { - line[idx++] = '\0'; - - duk_push_global_object(ctx); - duk_get_prop_string(ctx, -1 /*index*/, "processLine"); - duk_push_string(ctx, line); - duk_call(ctx, 1 /*nargs*/); - printf("%s\n", duk_to_string(ctx, -1)); - duk_pop(ctx); - - idx = 0; - } else if (ch == EOF) { - break; - } else { - line[idx++] = (char) ch; - } - } - - duk_destroy_heap(ctx); - - exit(0); -} -+Let's look at the Duktape specific parts of the example code line by line. Here we need to gloss over some details for brevity, see @@ -349,37 +272,7 @@ See Programming model for more details. up Ecmascript algorithms. More specifically, our test program searches for primes under 1000000 which end with the digits '9999'. The Ecmascript version of the program is:
--// Pure Ecmascript version of low level helper -function primeCheckEcmascript(val, limit) { - for (var i = 2; i <= limit; i++) { - if ((val % i) == 0) { return false; } - } - return true; -} - -// Select available helper at load time -var primeCheckHelper = (this.primeCheckNative || primeCheckEcmascript); - -// Check 'val' for primality -function primeCheck(val) { - if (val == 1 || val == 2) { return true; } - var limit = Math.ceil(Math.sqrt(val)); - while (limit * limit < val) { limit += 1; } - return primeCheckHelper(val, limit); -} - -// Find primes below one million ending in '9999'. -function primeTest() { - var res = []; - - print('Have native helper: ' + (primeCheckHelper !== primeCheckEcmascript)); - for (var i = 1; i < 1000000; i++) { - if (primeCheck(i) && (i % 10000) == 9999) { res.push(i); } - } - print(res.join(' ')); -} -+Note that the program uses the native helper if it's available but falls back to an Ecmascript version if it's not. This allows the Ecmascript code @@ -393,52 +286,9 @@ which is more flexible.
A native helper with functionality equivalent to primeCheckEcmascript is quite straightforward to implement. Adding a program main we get primecheck.c:
--#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "duktape.h" - -static int native_prime_check(duk_context *ctx) { - int val = duk_require_int(ctx, 0); - int lim = duk_require_int(ctx, 1); - int i; - - for (i = 2; i <= lim; i++) { - if (val % i == 0) { - duk_push_false(ctx); - return 1; - } - } - - duk_push_true(ctx); - return 1; -} - -int main(int argc, const char *argv[]) { - duk_context *ctx = NULL; - - ctx = duk_create_heap_default(); - if (!ctx) { exit(1); } - - duk_push_global_object(ctx); - duk_push_c_function(ctx, native_prime_check, 2 /*nargs*/); - duk_put_prop_string(ctx, -2, "primeCheckNative"); - - duk_eval_file(ctx, "prime.js"); - duk_pop(ctx); /* pop eval result */ - - duk_get_prop_string(ctx, -1, "primeTest"); - duk_call(ctx, 0); - duk_pop(ctx); - - duk_destroy_heap(ctx); - - exit(0); -} -+ -The new steps here, line by line:
+The new steps here are, line by line:
Finalization and Coroutines discuss invididual technical topics separately from the basic programming model. -(These are also very much in flux.)
+(These are also very much under work.)Limitations discusses currently known limitations and provides possible workarounds.
diff --git a/website/guide/programming.html b/website/guide/programming.html index 0040fa80..f0ddc80a 100644 --- a/website/guide/programming.html +++ b/website/guide/programming.html @@ -1,7 +1,7 @@(This section is under work.)
Heap objects can reference each other, creating a reachability graph from +mark-and-sweep garbage collection, object finalization, etc. +Heap objects can reference each other, creating a reachability graph from a garbage collection perspective. For instance, the properties of an Ecmascript object reference both the keys and values of the object's property set. You can have multiple heaps, but objects in different heaps cannot reference each other directly; you need to use serialization to pass values between heaps.
-A Duktape context is an Ecmascript "thread of execution" which "lives" +
A Duktape context is an Ecmascript "thread of execution" which lives in a certain Duktape heap. A context is represented by a duk_context * in the Duktape API, and is associated with an internal Duktape coroutine (a form of a co-operative thread). The context handle is given to almost every Duktape @@ -105,6 +104,12 @@ point of view.
duk_destroy_heap(ctx); +This frees all heap objects allocated, and invalidates any pointers to +such objects. In particular, if the calling program holds string pointers +to values which resided on the value stack of a context associated with the +heap, such pointers are invalidated and must never be dereferenced after +the heap destruction call returns.
+The call stack of a context is not directly visible to the caller. @@ -124,7 +129,7 @@ caller than the call stack.
accurately represent the true call chain: tail calls will be "squashed" together in the call stack. -FIXME.
+At any time, the value stack of a context is allocated for a certain +maximum number of entries. Attempt to push values beyond the allocated +size will cause an error to be thrown, it will not cause the value +stack to be automatically extended. This simplifies the internal +implementation and also improves performance by minimizing reallocations +when you know, beforehand, that a certain number of entries will be needed +during a function.
+ +When a value stack is created or a Duktape/C function is entered, the +value stack is always guaranteed up to size XXX. In the typical case this +is more than sufficient so that the majority of Duktape/C functions don't +need to extend the value stack. Only functions that need more space or +perhaps need an input-dependent amount of space need to grow the value +stack.
+ +You can extend the stack allocation explicitly with duk_check_stack() +or (usually more preferably) duk_require_stack(). Once successfully +extended, you are again guaranteed that the specified number of elements can +be pushed to the stack. There is no way to shrink the allocation except by +returning from a Duktape/C function.
+ +Consider, for instance, the following function which will uppercase an +input ASCII string by pushing uppercased characters one-by-one on the stack +and then concatenating the result. This example illustrates how the number +of value stack entries required may depend on the input (otherwise this is +not a very good approach for uppercasing a string):
+ + + +In addition to user reserved elements, Duktape keeps an automatic internal +value stack reserve to ensure all API calls have enough value stack space to +work without further allocations. The value stack is also extended in somewhat +large steps to minimize memory reallocation activity. As a result the internal +number of value stack elements available beyond the caller specified extra +varies considerably. The caller does not need to take this into account and +should never rely on any additional elements being available.
Duktape API is the collection of user callable API calls defined in +duktape.h and documented in the +API reference.
+The Duktape API calls are generally error tolerant and will check all arguments for errors (such as NULL pointers). However, to minimize footprint, the ctx argument is not checked, and the caller MUST NOT call any Duktape API calls with a NULL context.
-For details on the available API calls, please see the -API reference.
-A C function with a Duktape/C API signature can be associated with an