feat: add await syntax for direct async function calls and new generator/phonebook apps
Add compiler support for calling async functions directly with `await fn(args)` syntax, automatically translating to `await fn.call(args)`. Introduce `create_merge` Makefile target for merging Wren source files. Include new `apps/generator.wren` source code generator using OpenRouter API, `apps/phonebook.wren` CLI phonebook with SQLite backend, and `apps/minitut.md` Wren tutorial reference. Update `example/await_demo.wren` with parameterized async functions, nested awaits, and expression usage. Fix JSON parsing in `example/openrouter_demo.wren` to strip markdown code fences. Document new await syntax in `manual/api/scheduler.html`.
This commit is contained in:
@@ -126,6 +126,99 @@
|
||||
</div>
|
||||
<p>Resumes a fiber with a result value.</p>
|
||||
|
||||
<h2 id="await-syntax">Await Syntax</h2>
|
||||
|
||||
<p>Wren-CLI provides a convenient syntax for awaiting async functions. Instead of using <code>.call()</code>, you can call async functions directly after <code>await</code>:</p>
|
||||
|
||||
<h3>Before and After</h3>
|
||||
<pre><code>// Old syntax (still works)
|
||||
var result = await asyncFn.call(arg1, arg2)
|
||||
|
||||
// New syntax (recommended)
|
||||
var result = await asyncFn(arg1, arg2)</code></pre>
|
||||
|
||||
<p>The compiler automatically translates <code>await fn(args)</code> to <code>await fn.call(args)</code>.</p>
|
||||
|
||||
<h3>Supported Patterns</h3>
|
||||
|
||||
<table class="params-table">
|
||||
<thead>
|
||||
<tr><th>Pattern</th><th>Example</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td>No arguments</td><td><code>await getValue()</code></td></tr>
|
||||
<tr><td>Single argument</td><td><code>await double(21)</code></td></tr>
|
||||
<tr><td>Multiple arguments</td><td><code>await add(3, 4, 5)</code></td></tr>
|
||||
<tr><td>Nested awaits</td><td><code>await outer(await inner(x))</code></td></tr>
|
||||
<tr><td>In expressions</td><td><code>var x = 1 + await fn(2)</code></td></tr>
|
||||
<tr><td>In conditions</td><td><code>if (await check(x)) { }</code></td></tr>
|
||||
<tr><td>Block argument</td><td><code>await map(list) { |x| x * 2 }</code></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="admonition note">
|
||||
<div class="admonition-title">Note</div>
|
||||
<p>Method chaining after <code>await fn(args)</code> requires assigning the result first:</p>
|
||||
<pre><code>var list = await getList(5)
|
||||
System.print(list.count)</code></pre>
|
||||
</div>
|
||||
|
||||
<h3>Examples</h3>
|
||||
|
||||
<pre><code>import "scheduler" for Scheduler, Future
|
||||
|
||||
var double = async { |x| x * 2 }
|
||||
var add = async { |a, b| a + b }
|
||||
|
||||
// Basic usage
|
||||
System.print(await double(21)) // 42
|
||||
System.print(await add(3, 4)) // 7
|
||||
|
||||
// Nested awaits
|
||||
var result = await double(await add(5, 5)) // 20
|
||||
|
||||
// Method chaining
|
||||
var getList = async { |n| [1, 2, 3, n] }
|
||||
System.print(await getList(4).count) // 4
|
||||
|
||||
// In expressions
|
||||
var total = await add(10, 20) + await double(5) // 40</code></pre>
|
||||
|
||||
<h3>Class-Based Async Patterns</h3>
|
||||
|
||||
<p>Static getters that return async functions must first be assigned to a variable:</p>
|
||||
|
||||
<pre><code>import "scheduler" for Scheduler, Future
|
||||
|
||||
class Calculator {
|
||||
static add { async { |a, b| a + b } }
|
||||
static multiply { async { |a, b| a * b } }
|
||||
static square { async { |x| x * x } }
|
||||
|
||||
static compute(a, b) {
|
||||
var addFn = Calculator.add
|
||||
var multiplyFn = Calculator.multiply
|
||||
var sum = await addFn(a, b)
|
||||
var product = await multiplyFn(a, b)
|
||||
return [sum, product]
|
||||
}
|
||||
}
|
||||
|
||||
// Assign getter to variable first, then await
|
||||
var add = Calculator.add
|
||||
System.print(await add(3, 4)) // 7
|
||||
|
||||
var multiply = Calculator.multiply
|
||||
System.print(await multiply(5, 6)) // 30
|
||||
|
||||
var square = Calculator.square
|
||||
System.print(await square(8)) // 64</code></pre>
|
||||
|
||||
<div class="admonition note">
|
||||
<div class="admonition-title">Note</div>
|
||||
<p>The <code>fn(args)</code> syntax only works directly after <code>await</code>. Outside of <code>await</code>, use <code>fn.call(args)</code> to invoke async functions.</p>
|
||||
</div>
|
||||
|
||||
<h2>How Async Works</h2>
|
||||
|
||||
<p>Wren-CLI uses an event loop (libuv) for non-blocking I/O. Here is how async operations work:</p>
|
||||
|
||||
Reference in New Issue
Block a user