Skip to content

Commit 7fe5216

Browse files
committed
docs: add async examples and clarify queueMicrotask
Add code examples for async function translation based on the async_basic integration test. Clarify that `go` statements are translated using `queueMicrotask`. Signed-off-by: Christian Stewart <christian@aperture.us>
1 parent 8e1e66e commit 7fe5216

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

design/DESIGN.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,12 +487,73 @@ To determine which functions need to be marked `async` in TypeScript, the compil
487487

488488
### TypeScript Generation
489489

490+
## Functions
491+
490492
- **Async Functions:** Go functions colored as **Asynchronous** are generated as TypeScript `async function`s. Their return type `T` is wrapped in a `Promise<T>`. If the function has no return value, the TypeScript return type is `Promise<void>`.
491493
- **Sync Functions:** Go functions colored as **Synchronous** are generated as regular TypeScript `function`s with their corresponding return types.
492494
- **Function Calls:** When a Go function call targets an **Asynchronous** function, the generated TypeScript call expression is prefixed with the `await` keyword. Calls to **Synchronous** functions are generated directly without `await`.
493495

494496
This coloring approach ensures that asynchronous operations propagate correctly through the call stack in the generated TypeScript code.
495497

498+
### Async Example
499+
500+
Consider the following Go code using a channel:
501+
502+
```go
503+
package main
504+
505+
// This function receives from a channel, making it async.
506+
func receiveFromChan(ch chan int) int {
507+
val := <-ch // This operation makes the function async
508+
return val
509+
}
510+
511+
// This function calls an async function, making it async too.
512+
func caller(ch chan int) int {
513+
// We expect this call to be awaited in TypeScript
514+
result := receiveFromChan(ch)
515+
return result + 1
516+
}
517+
518+
func main() {
519+
myChan := make(chan int, 1)
520+
myChan <- 10
521+
finalResult := caller(myChan)
522+
println(finalResult) // Expected output: 11
523+
close(myChan)
524+
}
525+
526+
```
527+
528+
This translates to the following TypeScript:
529+
530+
```typescript
531+
import * as goscript from "@go/builtin";
532+
533+
// Marked async because it contains 'await ch.receive()'
534+
async function receiveFromChan(ch: goscript.Channel<number>): Promise<number> {
535+
let val = await ch.receive()
536+
return val
537+
}
538+
539+
// Marked async because it calls the async 'receiveFromChan'
540+
async function caller(ch: goscript.Channel<number>): Promise<number> {
541+
let result = await receiveFromChan(ch) // Call is awaited
542+
return result + 1
543+
}
544+
545+
// Marked async because it calls the async 'caller' and uses 'await myChan.send()'
546+
export async function main(): Promise<void> {
547+
let myChan = goscript.makeChannel<number>(1)
548+
await myChan.send(10) // Send is awaited
549+
let finalResult = await caller(myChan) // Call is awaited
550+
console.log(finalResult)
551+
myChan.close()
552+
}
553+
```
554+
555+
*Note on Microtasks:* While Go's concurrency model involves goroutines and a scheduler, the TypeScript translation primarily uses `async`/`await` and Promises for channel operations. Starting a new Goroutine with the `go` keyword is translated to a call to `queueMicrotask` with the target function, effectively scheduling it to run asynchronously similar to how Promises resolve.
556+
496557
## Constants
497558
498559
Go `const` declarations are translated into TypeScript `let` declarations at the module scope.

0 commit comments

Comments
 (0)