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:
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var delayed = async { |ms| ms }
|
||||
|
||||
System.print(await delayed(1)) // expect: 1
|
||||
System.print(await delayed(2)) // expect: 2
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var base = 100
|
||||
var addBase = async { |x| base + x }
|
||||
|
||||
var f = addBase.call(42)
|
||||
System.print(await f) // expect: 142
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
var order = []
|
||||
|
||||
var task = async { |name, ms|
|
||||
await Timer.sleep(ms)
|
||||
order.add(name)
|
||||
name
|
||||
}
|
||||
|
||||
var f1 = task.call("slow", 2)
|
||||
var f2 = task.call("fast", 1)
|
||||
|
||||
await f1
|
||||
await f2
|
||||
System.print(order) // expect: [fast, slow]
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var add = async { |a, b| a + b }
|
||||
|
||||
System.print(await add(3, 4)) // expect: 7
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var transform = async { |list, fn|
|
||||
var result = []
|
||||
for (item in list) {
|
||||
result.add(fn.call(item))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var doubled = await transform([1, 2, 3]) { |x| x * 2 }
|
||||
System.print(doubled) // expect: [2, 4, 6]
|
||||
|
||||
var squared = await transform([2, 3, 4]) { |x| x * x }
|
||||
System.print(squared) // expect: [4, 9, 16]
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var double = async { |x| x * 2 }
|
||||
|
||||
System.print(await double(21)) // expect: 42
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var getList = async { |x| [x, x * 2, x * 3] }
|
||||
var getString = async { |s| s }
|
||||
|
||||
var list = await getList(5)
|
||||
System.print(list.count) // expect: 3
|
||||
|
||||
var list2 = await getList(10)
|
||||
System.print(list2[1]) // expect: 20
|
||||
|
||||
var str = await getString("hello")
|
||||
System.print(str.count) // expect: 5
|
||||
|
||||
var str2 = await getString("world")
|
||||
System.print(str2.toList[0]) // expect: w
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
class MockApi {
|
||||
static fetchUser { async { |id|
|
||||
Timer.sleep(1)
|
||||
return {"id": id, "name": "User%(id)", "active": true}
|
||||
}}
|
||||
|
||||
static fetchPosts { async { |userId|
|
||||
Timer.sleep(1)
|
||||
return [
|
||||
{"id": 1, "userId": userId, "title": "Post 1"},
|
||||
{"id": 2, "userId": userId, "title": "Post 2"}
|
||||
]
|
||||
}}
|
||||
|
||||
static createPost { async { |userId, title|
|
||||
Timer.sleep(1)
|
||||
return {"id": 3, "userId": userId, "title": title, "created": true}
|
||||
}}
|
||||
|
||||
static getUserWithPosts(userId) {
|
||||
var fetchUser = MockApi.fetchUser
|
||||
var fetchPosts = MockApi.fetchPosts
|
||||
var user = await fetchUser(userId)
|
||||
var posts = await fetchPosts(userId)
|
||||
|
||||
user["posts"] = posts
|
||||
return user
|
||||
}
|
||||
}
|
||||
|
||||
var fetchUser = MockApi.fetchUser
|
||||
var user = await fetchUser(42)
|
||||
System.print(user["name"]) // expect: User42
|
||||
|
||||
var fetchPosts = MockApi.fetchPosts
|
||||
var posts = await fetchPosts(42)
|
||||
System.print(posts.count) // expect: 2
|
||||
|
||||
var createPost = MockApi.createPost
|
||||
var newPost = await createPost(42, "New Post")
|
||||
System.print(newPost["created"]) // expect: true
|
||||
|
||||
var fullUser = MockApi.getUserWithPosts(99)
|
||||
System.print(fullUser["name"]) // expect: User99
|
||||
System.print(fullUser["posts"].count) // expect: 2
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
class DataProcessor {
|
||||
static parse { async { |text| text.split(",") } }
|
||||
static filter { async { |list, fn|
|
||||
var result = []
|
||||
for (item in list) {
|
||||
if (fn.call(item)) result.add(item)
|
||||
}
|
||||
return result
|
||||
}}
|
||||
static transform { async { |list, fn|
|
||||
var result = []
|
||||
for (item in list) {
|
||||
result.add(fn.call(item))
|
||||
}
|
||||
return result
|
||||
}}
|
||||
static join { async { |list, sep| list.join(sep) } }
|
||||
|
||||
static pipeline(data) {
|
||||
var parse = DataProcessor.parse
|
||||
var filter = DataProcessor.filter
|
||||
var transform = DataProcessor.transform
|
||||
var join = DataProcessor.join
|
||||
var parsed = await parse(data)
|
||||
var filtered = await filter(parsed) { |s| s.count > 4 }
|
||||
var transformed = await transform(filtered) { |s| s.toList[0] }
|
||||
return await join(transformed, "-")
|
||||
}
|
||||
}
|
||||
|
||||
var data = "apple,banana,cherry,date"
|
||||
|
||||
var parse = DataProcessor.parse
|
||||
var parsed = await parse(data)
|
||||
System.print(parsed) // expect: [apple, banana, cherry, date]
|
||||
|
||||
var filter = DataProcessor.filter
|
||||
var filtered = await filter(parsed) { |s| s.count > 5 }
|
||||
System.print(filtered) // expect: [banana, cherry]
|
||||
|
||||
var transform = DataProcessor.transform
|
||||
var transformed = await transform(filtered) { |s| s.toList[0] }
|
||||
System.print(transformed) // expect: [b, c]
|
||||
|
||||
var join = DataProcessor.join
|
||||
var joined = await join(transformed, "-")
|
||||
System.print(joined) // expect: b-c
|
||||
|
||||
var result = DataProcessor.pipeline("one,two,three,four,five")
|
||||
System.print(result) // expect: t
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
class Counter {
|
||||
construct new(start) {
|
||||
_value = start
|
||||
}
|
||||
|
||||
value { _value }
|
||||
|
||||
add(n) {
|
||||
var op = async { |x|
|
||||
_value = _value + x
|
||||
return _value
|
||||
}
|
||||
return await op(n)
|
||||
}
|
||||
|
||||
subtract(n) {
|
||||
var op = async { |x|
|
||||
_value = _value - x
|
||||
return _value
|
||||
}
|
||||
return await op(n)
|
||||
}
|
||||
|
||||
reset() {
|
||||
var op = async {
|
||||
_value = 0
|
||||
return _value
|
||||
}
|
||||
return await op()
|
||||
}
|
||||
}
|
||||
|
||||
var counter = Counter.new(10)
|
||||
System.print(counter.value) // expect: 10
|
||||
|
||||
System.print(counter.add(5)) // expect: 15
|
||||
System.print(counter.value) // expect: 15
|
||||
|
||||
System.print(counter.subtract(3)) // expect: 12
|
||||
System.print(counter.value) // expect: 12
|
||||
|
||||
System.print(counter.reset()) // expect: 0
|
||||
System.print(counter.value) // expect: 0
|
||||
|
||||
System.print(counter.add(10)) // expect: 10
|
||||
System.print(counter.subtract(3)) // expect: 7
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
class CacheService {
|
||||
construct new() {
|
||||
_cache = {}
|
||||
}
|
||||
|
||||
get(key) {
|
||||
var op = async { |k|
|
||||
Timer.sleep(1)
|
||||
return _cache.containsKey(k) ? _cache[k] : null
|
||||
}
|
||||
return await op(key)
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
var op = async { |k, v|
|
||||
Timer.sleep(1)
|
||||
_cache[k] = v
|
||||
return true
|
||||
}
|
||||
return await op(key, value)
|
||||
}
|
||||
|
||||
has(key) {
|
||||
var op = async { |k|
|
||||
return _cache.containsKey(k)
|
||||
}
|
||||
return await op(key)
|
||||
}
|
||||
|
||||
clear() {
|
||||
var op = async {
|
||||
_cache = {}
|
||||
return true
|
||||
}
|
||||
return await op()
|
||||
}
|
||||
|
||||
getOrSet(key, defaultValue) {
|
||||
if (this.has(key)) {
|
||||
return this.get(key)
|
||||
}
|
||||
this.set(key, defaultValue)
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
var cache = CacheService.new()
|
||||
|
||||
System.print(cache.has("foo")) // expect: false
|
||||
System.print(cache.get("foo")) // expect: null
|
||||
|
||||
System.print(cache.set("foo", "bar")) // expect: true
|
||||
System.print(cache.has("foo")) // expect: true
|
||||
System.print(cache.get("foo")) // expect: bar
|
||||
|
||||
System.print(cache.clear()) // expect: true
|
||||
System.print(cache.has("foo")) // expect: false
|
||||
|
||||
System.print(cache.getOrSet("baz", "default")) // expect: default
|
||||
System.print(cache.get("baz")) // expect: default
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
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 constant { async { 42 } }
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
|
||||
var add = Calculator.add
|
||||
System.print(await add(3, 4)) // expect: 7
|
||||
|
||||
var multiply = Calculator.multiply
|
||||
System.print(await multiply(5, 6)) // expect: 30
|
||||
|
||||
var square = Calculator.square
|
||||
System.print(await square(8)) // expect: 64
|
||||
|
||||
var constant = Calculator.constant
|
||||
System.print(await constant()) // expect: 42
|
||||
|
||||
var results = Calculator.compute(2, 3)
|
||||
System.print(results) // expect: [5, 6]
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var multiplier = 10
|
||||
var scale = async { |x| x * multiplier }
|
||||
|
||||
System.print(await scale(5)) // expect: 50
|
||||
|
||||
multiplier = 100
|
||||
System.print(await scale(5)) // expect: 500
|
||||
|
||||
var prefix = "Result: "
|
||||
var format = async { |x| prefix + x.toString }
|
||||
System.print(await format(42)) // expect: Result: 42
|
||||
|
||||
var outer = "outer"
|
||||
var fn = Fn.new {
|
||||
var inner = "inner"
|
||||
var capture = async { |x| outer + "-" + inner + "-" + x }
|
||||
return await capture("arg")
|
||||
}
|
||||
System.print(fn.call()) // expect: outer-inner-arg
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var isPositive = async { |x| x > 0 }
|
||||
var getValue = async { |x| x }
|
||||
|
||||
if (await isPositive(5)) {
|
||||
System.print("positive") // expect: positive
|
||||
}
|
||||
|
||||
if (await isPositive(-5)) {
|
||||
System.print("unreachable")
|
||||
} else {
|
||||
System.print("negative") // expect: negative
|
||||
}
|
||||
|
||||
var result = await isPositive(10) ? "yes" : "no"
|
||||
System.print(result) // expect: yes
|
||||
|
||||
while (await getValue(false)) {
|
||||
System.print("unreachable")
|
||||
}
|
||||
System.print("after while") // expect: after while
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var getValue = async { |x| x }
|
||||
var double = async { |x| x * 2 }
|
||||
|
||||
System.print(1 + await getValue(2)) // expect: 3
|
||||
System.print(await double(3) + await double(4)) // expect: 14
|
||||
System.print(await getValue(10) * 5) // expect: 50
|
||||
System.print(100 - await getValue(30)) // expect: 70
|
||||
System.print((await getValue(4)) * (await getValue(5))) // expect: 20
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var double = async { |x| x * 2 }
|
||||
|
||||
var sum = 0
|
||||
for (i in [1, 2, 3, 4, 5]) {
|
||||
sum = sum + await double(i)
|
||||
}
|
||||
System.print(sum) // expect: 30
|
||||
|
||||
var results = []
|
||||
for (i in 1..3) {
|
||||
results.add(await double(i))
|
||||
}
|
||||
System.print(results) // expect: [2, 4, 6]
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
class Test {
|
||||
static run() {
|
||||
var localDouble = async { |x| x * 2 }
|
||||
var localAdd = async { |a, b| a + b }
|
||||
|
||||
System.print(await localDouble(5)) // expect: 10
|
||||
System.print(await localAdd(3, 4)) // expect: 7
|
||||
|
||||
var nested = Fn.new {
|
||||
var innerFn = async { |x| x * 100 }
|
||||
return await innerFn(3)
|
||||
}
|
||||
System.print(nested.call()) // expect: 300
|
||||
}
|
||||
}
|
||||
|
||||
Test.run()
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var sum4 = async { |a, b, c, d| a + b + c + d }
|
||||
var sum5 = async { |a, b, c, d, e| a + b + c + d + e }
|
||||
|
||||
System.print(await sum4(1, 2, 3, 4)) // expect: 10
|
||||
System.print(await sum5(1, 2, 3, 4, 5)) // expect: 15
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var double = async { |x| x * 2 }
|
||||
var triple = async { |x| x * 3 }
|
||||
|
||||
System.print(await double(5)) // expect: 10
|
||||
System.print(await double.call(5)) // expect: 10
|
||||
|
||||
var f1 = double.call(10)
|
||||
var f2 = triple.call(10)
|
||||
System.print(await f1) // expect: 20
|
||||
System.print(await f2) // expect: 30
|
||||
|
||||
System.print(await double(await triple.call(2))) // expect: 12
|
||||
System.print(await double.call(await triple(2))) // expect: 12
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var moduleDouble = async { |x| x * 2 }
|
||||
var moduleAdd = async { |a, b| a + b }
|
||||
|
||||
class Helper {
|
||||
static useModuleVar(x) {
|
||||
return await moduleDouble(x)
|
||||
}
|
||||
|
||||
static combineModuleVars(a, b) {
|
||||
return await moduleAdd(await moduleDouble(a), await moduleDouble(b))
|
||||
}
|
||||
}
|
||||
|
||||
System.print(await moduleDouble(10)) // expect: 20
|
||||
System.print(Helper.useModuleVar(15)) // expect: 30
|
||||
System.print(Helper.combineModuleVars(5, 10)) // expect: 30
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var double = async { |x| x * 2 }
|
||||
var addTen = async { |x| x + 10 }
|
||||
|
||||
System.print(await addTen(await double(5))) // expect: 20
|
||||
System.print(await double(await addTen(3))) // expect: 26
|
||||
System.print(await double(await double(await double(2)))) // expect: 16
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var getValue = async { 42 }
|
||||
|
||||
System.print(await getValue()) // expect: 42
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
var delayedValue = async { |ms, val|
|
||||
Timer.sleep(ms)
|
||||
return val
|
||||
}
|
||||
|
||||
var f1 = delayedValue.call(10, "first")
|
||||
var f2 = delayedValue.call(10, "second")
|
||||
var f3 = delayedValue.call(10, "third")
|
||||
|
||||
System.print(await f1) // expect: first
|
||||
System.print(await f2) // expect: second
|
||||
System.print(await f3) // expect: third
|
||||
|
||||
var compute = async { |x| x * x }
|
||||
|
||||
var futures = []
|
||||
for (i in 1..5) {
|
||||
futures.add(compute.call(i))
|
||||
}
|
||||
|
||||
var results = []
|
||||
for (f in futures) {
|
||||
results.add(await f)
|
||||
}
|
||||
System.print(results) // expect: [1, 4, 9, 16, 25]
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var getString = async { |x| x.toString }
|
||||
var getNum = async { |x| x * 2 }
|
||||
var getList = async { |x| [x, x, x] }
|
||||
var getMap = async { |k, v| {k: v} }
|
||||
var getNull = async { null }
|
||||
var getBool = async { |x| x > 0 }
|
||||
|
||||
System.print(await getString("hello")) // expect: hello
|
||||
System.print(await getNum(21)) // expect: 42
|
||||
System.print(await getList(7)) // expect: [7, 7, 7]
|
||||
System.print(await getMap("key", 123)) // expect: {key: 123}
|
||||
System.print(await getNull()) // expect: null
|
||||
System.print(await getBool(5)) // expect: true
|
||||
System.print(await getBool(-5)) // expect: false
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var step1 = async { |x| x + 10 }
|
||||
var step2 = async { |x| x * 2 }
|
||||
var step3 = async { |x| x - 5 }
|
||||
|
||||
var result = 5
|
||||
result = await step1(result)
|
||||
System.print(result) // expect: 15
|
||||
result = await step2(result)
|
||||
System.print(result) // expect: 30
|
||||
result = await step3(result)
|
||||
System.print(result) // expect: 25
|
||||
|
||||
var pipeline = async { |x|
|
||||
var r1 = await step1(x)
|
||||
var r2 = await step2(r1)
|
||||
var r3 = await step3(r2)
|
||||
return r3
|
||||
}
|
||||
|
||||
System.print(await pipeline(0)) // expect: 15
|
||||
System.print(await pipeline(10)) // expect: 35
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
|
||||
var makeMultiplier = Fn.new { |factor|
|
||||
var multiply = async { |x| x * factor }
|
||||
return multiply
|
||||
}
|
||||
|
||||
var times2 = makeMultiplier.call(2)
|
||||
var times10 = makeMultiplier.call(10)
|
||||
|
||||
System.print(await times2(5)) // expect: 10
|
||||
System.print(await times10(5)) // expect: 50
|
||||
|
||||
var counter = 0
|
||||
var makeCounter = Fn.new {
|
||||
var increment = async { |step|
|
||||
counter = counter + step
|
||||
return counter
|
||||
}
|
||||
return increment
|
||||
}
|
||||
|
||||
var inc = makeCounter.call()
|
||||
System.print(await inc(1)) // expect: 1
|
||||
System.print(await inc(5)) // expect: 6
|
||||
System.print(await inc(10)) // expect: 16
|
||||
Reference in New Issue
Block a user