diff --git a/control-flow.html b/control-flow.html index 598ffdec..188d4efa 100644 --- a/control-flow.html +++ b/control-flow.html @@ -263,6 +263,19 @@ for (i in [1, 2, 3, 4]) { } //> 3 +

Continue statements #

+

During the execution of a loop body, you might decide that you want to skip the +rest of this iteration and move on to the next one. You can use a continue +statement to do that. It’s just the continue keyword all by itself. Execution +will immediately jump to the beginning of the next loop iteration (and check the +loop conditions).

+
+for (i in [1, 2, 3, 4]) {
+  System.print(i)           //> 1
+  if (i == 2) continue      //> 3
+}                           //> 4
+
+

Numeric ranges #

Lists are one common use for for loops, but sometimes you want to walk over a sequence of numbers, or loop a number of times. For that, you can create a diff --git a/embedding/configuring-the-vm.html b/embedding/configuring-the-vm.html index a8c1c55b..28370da9 100644 --- a/embedding/configuring-the-vm.html +++ b/embedding/configuring-the-vm.html @@ -108,19 +108,49 @@ executed, it relies on the host application to locate and read the source code for a module.

The signature of this function is:

-char* loadModule(WrenVM* vm, const char* name)
+WrenLoadModuleResult loadModule(WrenVM* vm, const char* name)
 

When a module is imported, Wren calls this and passes in the module’s name. The -host should return the source code for that module. Memory for the source should -be allocated using the same allocator that the VM uses for other allocation (see -below). Wren will take ownership of the returned string and free it later.

+host should return the source code for that module in a WrenLoadModuleResult struct.

+
+WrenLoadModuleResult myLoadModule(WrenVM* vm, const char* name) {
+  WrenLoadModuleResult result = {0};
+    result.source = getSourceForModule(name);
+  return result;
+}
+
+

The module loader is only be called once for any given module name. Wren caches the result internally so subsequent imports of the same module use the previously loaded code.

If your host application isn’t able to load a module with some name, it should -return NULL and Wren will report that as a runtime error.

-

If you don’t use any import statements, you can leave this NULL.

+make sure the source value is NULL when returned. Wren will then report that as a runtime error.

+

If you don’t use any import statements, you can leave the loadModuleFn field in +the configuration set to NULL (the default).

+

Additionally, the WrenLoadModuleResult allows us to add a callback for when Wren is +done with the source, so we can free the memory if needed.

+
+
+static void loadModuleComplete(WrenVM* vm, 
+                               const char* module,
+                               WrenLoadModuleResult result) 
+{
+  if(result.source) {
+    //for example, if we used malloc to allocate
+    our source string, we use free to release it.
+    free((void*)result.source);
+  }
+}
+
+WrenLoadModuleResult myLoadModule(WrenVM* vm, const char* name) {
+  WrenLoadModuleResult result = {0};
+    result.onComplete = loadModuleComplete;
+    result.source = getSourceForModule(name);
+  return result;
+}
+
+

bindForeignMethodFn #

The callback Wren uses to find a foreign method and bind it to a class. See this page for details. If your application defines no foreign @@ -185,7 +215,7 @@ or function.

reallocateFn #

This lets you provide a custom memory allocation function. Its signature is:

-void* reallocate(void* memory, size_t newSize)
+void* reallocate(void* memory, size_t newSize, void* userData)
 

Wren uses this one function to allocate, grow, shrink, and deallocate memory. diff --git a/modularity.html b/modularity.html index f2ea3f57..abc9961c 100644 --- a/modularity.html +++ b/modularity.html @@ -149,6 +149,16 @@ if (thirsty) { } +

If you need to import a variable under a different name, you can use +import "..." for Name as OtherName. This looks up the top-level variable +Name in that module, but declares a variable called OtherName in this module +with its value.

+
+import "liquids" for Water //Water is now taken
+import "beverages" for Coffee, Water as H2O, Tea
+// var water = H2O.new()
+
+

If you want to load a module, but not bind any variables from it, you can omit the for clause:

@@ -182,16 +192,16 @@ WrenVM* vm = wrenNewVM(&config);
 
 

That function has this signature:

-char* WrenLoadModuleFn(WrenVM* vm, const char* name);
+WrenLoadModuleResult WrenLoadModuleFn(WrenVM* vm, const char* name);
 

Whenever a module is imported, the VM calls this and passes it the name of the module. The embedder is expected to return the source code contents of the -module. When you embed Wren in your app, you can handle this however you want: -reach out to the file system, look inside resources bundled into your app, -whatever.

-

You can return NULL from this function to indicate that a module couldn’t be -found. When you do this, Wren will report it as a runtime error.

+module in a WrenLoadModuleResult. When you embed Wren in your app, you can handle +this however you want: reach out to the file system, look inside resources bundled +into your app, whatever.

+

You can return the source field as NULL from this function to indicate that a module +couldn’t be found. When you do this, Wren will report it as a runtime error.

The command-line loader #

The Wren CLI command-line tool has a very simple lookup process. It appends the module name and “.wren” to the directory where diff --git a/modules/core/fiber.html b/modules/core/fiber.html index 651d183b..b36fe8cc 100644 --- a/modules/core/fiber.html +++ b/modules/core/fiber.html @@ -217,6 +217,22 @@ var error = fiber.try() System.print("Caught error: " + error)

+

If the called fiber raises an error, it can no longer be used.

+

try(value) #

+

Tries to run the fiber. If a runtime error occurs +in the called fiber, the error is captured and is returned as a string. +If the fiber is being +started for the first time, and its function takes a parameter, value is +passed to it.

+
+var fiber = Fiber.new {|value|
+  value.badMethod
+}
+
+var error = fiber.try("just a string")
+System.print("Caught error: " + error)
+
+

If the called fiber raises an error, it can no longer be used.

transfer() #

TODO

diff --git a/modules/core/list.html b/modules/core/list.html index 670aeeb8..efd02c04 100644 --- a/modules/core/list.html +++ b/modules/core/list.html @@ -97,6 +97,14 @@

Removes all elements from the list.

count #

The number of elements in the list.

+

indexOf(value) #

+

Returns the index of value in the list, if found. If not found, returns -1.

+
+var list = [0, 1, 2, 3, 4]
+System.print(list.indexOf(3)) //> 3
+System.print(list.indexOf(20)) //> -1
+
+

insert(index, item) #

Inserts the item at index in the list.

@@ -145,6 +153,32 @@ System.print(["a", "b", "c"].removeAt(1)) //> b
 

It is a runtime error if the index is not an integer or is out of bounds.

+

sort(), sort(comparer) #

+

Sorts the elements of a list in-place; altering the list. The default sort is implemented using the quicksort algorithm.

+
+var list = [4, 1, 3, 2].sort()
+System.print(list) //> [1, 2, 3, 4]
+
+ +

A comparison function comparer can be provided to customise the element sorting. The comparison function must return a boolean value specifying the order in which elements should appear in the list.

+

The comparison function accepts two arguments a and b, two values to compare, and must return a boolean indicating the inequality between the arguments. If the function returns true, the first argument a will appear before the second b in the sorted results.

+

A compare function like {|a, b| true } will always put a before b. The default compare function is {|a, b| a < b }.

+
+var list = [9, 6, 8, 7]
+list.sort {|a, b| a < b}
+System.print(list) //> [6, 7, 8, 9]
+
+ +

It is a runtime error if comparer is not a function.

+

swap(index0, index1) #

+

Swaps values inside the list around. Puts the value from index0 in index1, +and the value from index1 at index0 in the list.

+
+var list = [0, 1, 2, 3, 4]
+list.swap(0, 3)
+System.print(list) //> [3, 1, 2, 0, 4]
+
+

[index] operator #

Gets the element at index. If index is negative, it counts backwards from the end of the list where -1 is the last element.

diff --git a/modules/core/num.html b/modules/core/num.html index 06db4156..8f3a1ba1 100644 --- a/modules/core/num.html +++ b/modules/core/num.html @@ -87,8 +87,15 @@

Attempts to parse value as a decimal literal and return it as an instance of Num. If the number cannot be parsed null will be returned.

It is a runtime error if value is not a string.

+

Num.infinity #

+

The value of &infinity;.

+

Num.nan #

+

One value representing a NaN.

+

Provides a default sane NaN number suitable for the vm internal values.

Num.pi #

The value of π.

+

Num.tau #

+

The value of τ.

Num.largest #

The largest representable numeric value.

Num.smallest #

@@ -149,6 +156,14 @@ System.print(2.3.isInteger) //> false

The binary (base-2) logarithm of the number. Returns nan if the base is negative.

exp #

The exponential e (Euler’s number) raised to the number. This: eⁿ.

+

min(other) #

+

Returns the minimum value when comparing this number and other.

+

max(other) #

+

Returns the maximum value when comparing this number and other.

+

clamp(min, max) #

+

Clamps a number into the range of min and max. If this number is less than min, +min is returned. If bigger than max, max is returned. Otherwise, the number +itself is returned.

pow(power) #

Raises this number (the base) to power. Returns nan if the base is negative.

round #

diff --git a/prism.js b/prism.js index f6770127..9518ceca 100644 --- a/prism.js +++ b/prism.js @@ -3,4 +3,4 @@ https://prismjs.com/download.html#themes=prism&languages=clike+c+lua */ var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,C={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof _?new _(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/n.length)return;if(!(b instanceof _)){var x=1;if(d&&y!=t.tail.prev){g.lastIndex=k;var w=g.exec(n);if(!w)break;var A=w.index+(h&&w[1]?w[1].length:0),P=w.index+w[0].length,S=k;for(S+=y.value.length;S<=A;)y=y.next,S+=y.value.length;if(S-=y.value.length,k=S,y.value instanceof _)continue;for(var O=y;O!==t.tail&&(S"+a.content+""},!u.document)return u.addEventListener&&(C.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(C.highlight(r,C.languages[t],t)),a&&u.close()},!1)),C;var e=C.util.currentScript();function t(){C.manual||C.highlightAll()}if(e&&(C.filename=e.src,e.hasAttribute("data-manual")&&(C.manual=!0)),!C.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return C}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/[a-z_]\w*(?=\s*\()/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; -Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)|\/\/(?:.+)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while|class|construct|foreign|import|is|null|static|super|this|var)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; +Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)|\/\/(?:.+)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while|class|construct|as|foreign|import|is|null|static|super|this|var)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; diff --git a/syntax.html b/syntax.html index a76a000d..98b79dbf 100644 --- a/syntax.html +++ b/syntax.html @@ -142,7 +142,7 @@ even if the code already contains block comments.

One way to get a quick feel for a language’s style is to see what words it reserves. Here’s what Wren has:

-break class construct else false for foreign if import
+as break class construct else false for foreign if import
 in is null return static super this true var while