Skip to content

Latest commit

Β 

History

History
878 lines (762 loc) Β· 54.3 KB

File metadata and controls

878 lines (762 loc) Β· 54.3 KB

GoScript: A Comprehensive Architecture Explainer

GoScript is an experimental Go-to-TypeScript transpiler that converts Go source code into maintainable, idiomatic TypeScript while preserving Go's semantics. This document provides a deep dive into how GoScript works.

Table of Contents

  1. Overview
  2. High-Level Architecture
  3. Compilation Pipeline
  4. Compiler Components
  5. Analysis Phase
  6. Code Generation Phase
  7. Type System Translation
  8. Runtime System
  9. Concurrency Model
  10. Value Semantics

Overview

GoScript translates Go code at the AST (Abstract Syntax Tree) level, producing readable TypeScript that preserves Go's type safety and semantics. The primary use case is sharing business logic between Go backends and TypeScript frontends.

Design Philosophy

  1. AST Mapping: Close mapping between Go AST and TypeScript output
  2. Type Preservation: Maintain Go's static typing in TypeScript
  3. Value Semantics: Emulate Go's value copying behavior for structs
  4. Idiomatic Output: Generate TypeScript that feels natural to TS developers
  5. Readability: Prioritize clear, understandable generated code

High-Level Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       GoScript Compile Service                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚  β”‚ Public       │───▢│ Compile      │───▢│ Package      β”‚             β”‚
β”‚  β”‚ Adapters     β”‚    β”‚ Request      β”‚    β”‚ Graph        β”‚             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚                                                  β”‚                    β”‚
β”‚                                                  β–Ό                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚  β”‚ TypeScript   │◀───│ TypeScript   │◀───│ Lowered      β”‚             β”‚
β”‚  β”‚ Output       β”‚    β”‚ Emitter      β”‚    β”‚ Program      β”‚             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚         β–²                 β–²                    β–²                      β”‚
β”‚         β”‚                 β”‚                    β”‚                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚  β”‚ Override     β”‚    β”‚ Runtime      β”‚    β”‚ Semantic     β”‚             β”‚
β”‚  β”‚ Registry     β”‚    β”‚ Contract     β”‚    β”‚ Model        β”‚             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚                                                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                  β”‚
                                  β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        @goscript/builtin Runtime                      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  varRef.ts β”‚ slice.ts β”‚ channel.ts β”‚ map.ts β”‚ type.ts β”‚ defer.ts      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The public CLI uses github.com/aperturerobotics/cli and constructs compiler.Config from command-local flag state. The public Go API is compiler.Compiler, which forwards package patterns into CompileService. The WASM/browser adapter parses and type-checks import-free single-file source strings, builds the same semantic model used by package compilation, and then reuses the v2 lowering and TypeScript emitter. Browser source imports still return a structured diagnostic; use the package workflow for imported code.


Compilation Pipeline

State Machine: Overall Compilation Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   COMPILATION STATE MACHINE                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  START  β”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ VALIDATE REQUEST  β”‚
β”‚                   β”‚
β”‚ - package patternsβ”‚
β”‚ - output path     β”‚
β”‚ - module root     β”‚
β”‚ - build flags     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LOAD PACKAGE GRAPHβ”‚ Uses golang.org/x/tools/go/packages
β”‚                   β”‚ Env: GOOS=js, GOARCH=wasm
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SEMANTIC MODEL    β”‚
β”‚                   β”‚
β”‚ - package facts   β”‚
β”‚ - addressability  β”‚
β”‚ - methods/types   β”‚
β”‚ - async facts     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ OVERRIDE COPY PLANβ”‚ Discover handwritten gs/ packages
β”‚                   β”‚ and validate dependencies before output
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LOWER PROGRAM     β”‚ Convert Go AST + semantic facts into
β”‚                   β”‚ compiler-owned IR
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ EMIT TYPESCRIPT   β”‚ Render only from lowered IR
β”‚                   β”‚ and generate indexes
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ COPY OVERRIDES    β”‚ Copy @goscript/builtin and required
β”‚                   β”‚ handwritten packages
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚   END   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Compiler Components

GoScript v2 uses owner-level components instead of a package/file compiler hierarchy. Each owner hides one durable rule boundary:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         PUBLIC ADAPTERS                           β”‚
β”‚  cmd/goscript: github.com/aperturerobotics/cli flag surface       β”‚
β”‚  compiler.Compiler: Go API adapter over CompileService            β”‚
β”‚  compiler/wasm: browser diagnostic adapter                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                                    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         CompileService                            β”‚
β”‚  - Coordinates request, graph, semantic, lowering, emit, copy      β”‚
β”‚  - Accumulates structured diagnostics                             β”‚
β”‚  - Stops before writing output when owner diagnostics are errors   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β–Ό                     β–Ό                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CompileRequestOwner  β”‚ β”‚ PackageGraphOwner    β”‚ β”‚ SemanticModelOwner   β”‚
β”‚ Normalizes adapters  β”‚ β”‚ Loads packages       β”‚ β”‚ Computes package,    β”‚
β”‚ and validates module β”‚ β”‚ with go/packages     β”‚ β”‚ type, method, async, β”‚
β”‚ package requests     β”‚ β”‚ and build flags      β”‚ β”‚ and address facts    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β–Ό                     β–Ό                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ OverrideRegistryOwnerβ”‚ β”‚ LoweringOwner        β”‚ β”‚ TypeScriptEmitOwner  β”‚
β”‚ Discovers/copies gs/ β”‚ β”‚ Converts semantic    β”‚ β”‚ Renders deterministicβ”‚
β”‚ packages and async   β”‚ β”‚ model + AST to IR    β”‚ β”‚ TypeScript from IR   β”‚
β”‚ override metadata    β”‚ β”‚                      β”‚ β”‚ only                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                                    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       RuntimeContractOwner                        β”‚
β”‚  Owns generated helper names and @goscript/builtin import policy  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The main design constraint is that text emission is the last step. Earlier owners decide package identity, imports, async coloring, pointer/value shape, interface descriptors, generic dictionaries, override dependencies, and runtime helper names before TypeScriptEmitOwner writes files.


Analysis Phase

The analysis phase pre-computes all information needed for code generation. This happens before any TypeScript is written.

Analysis State Machine

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    ANALYSIS STATE MACHINE                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  START  β”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PROCESS IMPORTS     β”‚
β”‚                     β”‚
β”‚ Collect import      β”‚
β”‚ statements and      β”‚
β”‚ their usage         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ANALYZE FUNCTIONS   β”‚
β”‚                     β”‚
β”‚ For each function:  β”‚
β”‚ β€’ Track receivers   β”‚
β”‚ β€’ Named returns     β”‚
β”‚ β€’ Closure captures  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ VARIABLE USAGE      β”‚     β”‚ Rules for NeedsVarRef:              β”‚
β”‚ ANALYSIS            │────▢│ β€’ Address taken (&var)              β”‚
β”‚                     β”‚     β”‚ β€’ Assigned to pointer               β”‚
β”‚ Determine which     β”‚     β”‚ β€’ Passed to function taking pointer β”‚
β”‚ vars need VarRef    β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ASYNC ANALYSIS      β”‚     β”‚ Async Roots (Inherently Async):     β”‚
β”‚ (Function Coloring) │────▢│ β€’ Channel receive: <-ch             β”‚
β”‚                     β”‚     β”‚ β€’ Channel send: ch <- val           β”‚
β”‚ Propagate async     β”‚     β”‚ β€’ select statements                 β”‚
β”‚ status through      β”‚     β”‚ β€’ go statements (goroutines)        β”‚
β”‚ call graph          β”‚     β”‚                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚ Propagation:                        β”‚
          β”‚                 β”‚ β€’ Calls async func β†’ becomes async  β”‚
          β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ DEFER ANALYSIS      β”‚
β”‚                     β”‚
β”‚ Mark blocks with    β”‚
β”‚ defer statements    β”‚
β”‚ (sync vs async)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ INTERFACE IMPL      β”‚
β”‚ TRACKING            β”‚
β”‚                     β”‚
β”‚ Map structs to      β”‚
β”‚ interfaces they     β”‚
β”‚ implement           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ BUILD ANALYSIS      β”‚
β”‚ RESULT              β”‚
β”‚                     β”‚
β”‚ Package into        β”‚
β”‚ read-only struct    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚  END   β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Analysis Data Structure

type Analysis struct {
    // Variable reference tracking
    VariableUsage           map[types.Object]*VariableUsage

    // Function metadata
    FunctionData            map[types.Object]*FunctionInfo
    MethodAsyncStatus       map[string]bool

    // Per-node metadata
    NodeData                map[ast.Node]*NodeInfo

    // Interface implementations
    InterfaceImplementations map[InterfaceMethodKey][]ImplementationInfo

    // Import management
    SyntheticImportsPerFile map[string]map[string]*ImportInfo
    ReferencedTypesPerFile  map[string]map[types.Type]bool

    // Comment preservation
    Cmap                    ast.CommentMap
}

Code Generation Phase

After analysis, the compiler traverses the AST and generates TypeScript.

Code Generation State Machine

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 CODE GENERATION STATE MACHINE                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  START  β”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ WRITE IMPORTS       β”‚
β”‚                     β”‚
β”‚ import * as $ from  β”‚
β”‚ "@goscript/builtin" β”‚
β”‚                     β”‚
β”‚ Auto-imports from   β”‚
β”‚ same package        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ FOR EACH DECL       │◀──────────────────────────────────┐
β”‚                     β”‚                                   β”‚
β”‚ β€’ GenDecl (type,    β”‚                                   β”‚
β”‚   const, var)       β”‚                                   β”‚
β”‚ β€’ FuncDecl          β”‚                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                   β”‚
          β”‚                                               β”‚
          β”œβ”€β”€β”€β”€β”€β–Ά TYPE SPEC ──────▢ WriteTypeSpec         β”‚
          β”‚       (struct, interface, alias)              β”‚
          β”‚                                               β”‚
          β”œβ”€β”€β”€β”€β”€β–Ά VALUE SPEC ─────▢ WriteValueSpec        β”‚
          β”‚       (const, var)                            β”‚
          β”‚                                               β”‚
          β”œβ”€β”€β”€β”€β”€β–Ά FUNC DECL ──────▢ WriteFuncDecl         β”‚
          β”‚       (function, method)                      β”‚
          β”‚                                               β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚
                      β”‚ more decls?
                      β”‚
                      β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚  END   β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Expression Translation Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  EXPRESSION TRANSLATION FLOW                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                    WriteValueExpr(expr)
                           β”‚
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚               β”‚               β”‚
           β–Ό               β–Ό               β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ BasicLit   β”‚  β”‚ Ident      β”‚  β”‚ CallExpr   β”‚
    β”‚            β”‚  β”‚            β”‚  β”‚            β”‚
    β”‚ "hello"    β”‚  β”‚ varName    β”‚  β”‚ func()     β”‚
    β”‚ 42         β”‚  β”‚            β”‚  β”‚            β”‚
    β”‚ true       β”‚  β”‚ Check if   β”‚  β”‚ Check if   β”‚
    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β”‚ needs      β”‚  β”‚ async,     β”‚
          β”‚         β”‚ .value     β”‚  β”‚ builtin,   β”‚
          β”‚         β”‚ access     β”‚  β”‚ type conv  β”‚
          β–Ό         β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚               β”‚
    β”‚ Write      β”‚        β–Ό               β–Ό
    β”‚ literal    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ WriteIdent β”‚  β”‚ WriteCall  β”‚
                    β”‚            β”‚  β”‚ Expr       β”‚
                    β”‚ Add .value β”‚  β”‚            β”‚
                    β”‚ if VarRef  β”‚  β”‚ Add await  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ if async   β”‚
                                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

           β”‚               β”‚               β”‚
           β–Ό               β–Ό               β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ BinaryExpr β”‚  β”‚ UnaryExpr  β”‚  β”‚ IndexExpr  β”‚
    β”‚            β”‚  β”‚            β”‚  β”‚            β”‚
    β”‚ a + b      β”‚  β”‚ &x, *p     β”‚  β”‚ arr[i]     β”‚
    β”‚ x == y     β”‚  β”‚ -n, !b     β”‚  β”‚ map[key]   β”‚
    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
          β”‚               β”‚               β”‚
          β–Ό               β–Ό               β–Ό
    Write left    Handle addr/  Write collection
    op right      deref with    with index
                  VarRef logic

Type System Translation

Type Mapping Table

Go Type TypeScript Type Notes
int, int32, int64 number JavaScript number
float64, float32 number IEEE 754 64-bit
string string Direct mapping
bool boolean Direct mapping
rune number Unicode code point
byte number Byte value
error $.error | null Runtime interface
[]T T[] | null With __capacity
map[K]V Map<K, V> | null Standard Map
chan T $.Channel<T> Runtime class
*T T | null or $.VarRef<T> | null Depends on addressability
interface{} any Or specific interface

Struct Translation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          STRUCT TRANSLATION                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Go Source:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ type Person struct {                β”‚
β”‚     Name string                     β”‚
β”‚     Age  int                        β”‚
β”‚     addr *Address                   β”‚
β”‚ }                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                    β”‚
                    β”‚  Translation
                    β–Ό

TypeScript Output:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ export class Person {                                                 β”‚
β”‚     // Getters/setters for clean API                                  β”‚
β”‚     public get Name(): string {                                       β”‚
β”‚         return this._fields.Name.value                                β”‚
β”‚     }                                                                 β”‚
β”‚     public set Name(value: string) {                                  β”‚
β”‚         this._fields.Name.value = value                               β”‚
β”‚     }                                                                 β”‚
β”‚     public get Age(): number {                                        β”‚
β”‚         return this._fields.Age.value                                 β”‚
β”‚     }                                                                 β”‚
β”‚     public set Age(value: number) {                                   β”‚
β”‚         this._fields.Age.value = value                                β”‚
β”‚     }                                                                 β”‚
β”‚     public get addr(): Address | null {                               β”‚
β”‚         return this._fields.addr.value                                β”‚
β”‚     }                                                                 β”‚
β”‚     public set addr(value: Address | null) {                          β”‚
β”‚         this._fields.addr.value = value                               β”‚
β”‚     }                                                                 β”‚
β”‚                                                                       β”‚
β”‚     // Internal storage with VarRefs for addressability               β”‚
β”‚     public _fields: {                                                 β”‚
β”‚         Name: $.VarRef<string>                                        β”‚
β”‚         Age: $.VarRef<number>                                         β”‚
β”‚         addr: $.VarRef<Address | null>                                β”‚
β”‚     }                                                                 β”‚
β”‚                                                                       β”‚
β”‚     constructor(init?: Partial<{Name?: string, Age?: number, ...}>) { β”‚
β”‚         this._fields = {                                              β”‚
β”‚             Name: $.varRef(init?.Name ?? ""),                         β”‚
β”‚             Age: $.varRef(init?.Age ?? 0),                            β”‚
β”‚             addr: $.varRef(init?.addr ?? null)                        β”‚
β”‚         }                                                             β”‚
β”‚     }                                                                 β”‚
β”‚                                                                       β”‚
β”‚     // Clone for value semantics                                      β”‚
β”‚     public clone(): Person {                                          β”‚
β”‚         const cloned = new Person()                                   β”‚
β”‚         cloned._fields = {                                            β”‚
β”‚             Name: $.varRef(this._fields.Name.value),                  β”‚
β”‚             Age: $.varRef(this._fields.Age.value),                    β”‚
β”‚             addr: $.varRef(this._fields.addr.value)                   β”‚
β”‚         }                                                             β”‚
β”‚         return cloned                                                 β”‚
β”‚     }                                                                 β”‚
β”‚ }                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Runtime System

The @goscript/builtin runtime provides essential helpers:

Runtime Components

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           @goscript/builtin                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ varRef.ts   β”‚  β”‚ slice.ts    β”‚  β”‚ channel.ts  β”‚  β”‚ map.ts      β”‚  β”‚
β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚  β”‚
β”‚  β”‚ VarRef<T>   β”‚  β”‚ makeSlice   β”‚  β”‚ Channel<T>  β”‚  β”‚ makeMap     β”‚  β”‚
β”‚  β”‚ varRef()    β”‚  β”‚ slice()     β”‚  β”‚ makeChannel β”‚  β”‚ mapSet      β”‚  β”‚
β”‚  β”‚ unref()     β”‚  β”‚ append()    β”‚  β”‚ selectStmt  β”‚  β”‚ mapGet      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ copy()      β”‚  β”‚ chanSend    β”‚  β”‚ deleteMap   β”‚  β”‚
β”‚                   β”‚ len()       β”‚  β”‚ chanRecv    β”‚  β”‚ Entry       β”‚  β”‚
β”‚                   β”‚ cap()       β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                    β”‚
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ type.ts     β”‚  β”‚ defer.ts    β”‚  β”‚ errors.ts   β”‚  β”‚ builtin.ts  β”‚  β”‚
β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚  β”‚
β”‚  β”‚ registerTypeβ”‚  β”‚ Disposable  β”‚  β”‚ error type  β”‚  β”‚ println     β”‚  β”‚
β”‚  β”‚ typeAssert  β”‚  β”‚ Stack       β”‚  β”‚ panic       β”‚  β”‚ print       β”‚  β”‚
β”‚  β”‚ TypeInfo    β”‚  β”‚ AsyncDisp.  β”‚  β”‚ recover     β”‚  β”‚ bitwise ops β”‚  β”‚
β”‚  β”‚ TypeKind    β”‚  β”‚ Stack       β”‚  β”‚             β”‚  β”‚ int(), byte β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

VarRef (Variable Reference) System

The VarRef system enables Go's pointer semantics in TypeScript:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              VARREF SYSTEM                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Go Code:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ var x int = 10           β”‚
β”‚ p := &x                  β”‚
β”‚ *p = 20                  β”‚
β”‚ println(x) // 20         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

         β”‚ Analysis determines x needs VarRef (address taken)
         β–Ό

TypeScript Output:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ let x: $.VarRef<number> = $.varRef(10)  // x is wrapped in VarRef    β”‚
β”‚ let p: $.VarRef<number> | null = x       // p points to same VarRef  β”‚
β”‚ p!.value = 20                            // modify through pointer   β”‚
β”‚ $.println(x.value)                       // access value: 20         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜


Memory Model Visualization:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                         β”‚
β”‚   x ─────────────────┐                                                  β”‚
β”‚                      β”‚                                                  β”‚
β”‚                      β–Ό                                                  β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                        β”‚
β”‚              β”‚   VarRef<number>β”‚                                        β”‚
β”‚              β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                                        β”‚
β”‚              β”‚   β”‚ value: 20 β”‚ β”‚                                        β”‚
β”‚              β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                                        β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                        β”‚
β”‚                      β–²                                                  β”‚
β”‚                      β”‚                                                  β”‚
β”‚   p β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                  β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Concurrency Model

GoScript translates Go's concurrency to TypeScript async/await:

Function Coloring Algorithm

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       FUNCTION COLORING ALGORITHM                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Phase 1: Identify Async Roots
─────────────────────────────
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Scan all funcs β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Contains any of these? ────▢ Mark as ASYNC                     β”‚
  β”‚                                                                β”‚
  β”‚   β€’ <-ch       (channel receive)                               β”‚
  β”‚   β€’ ch <- val  (channel send)                                  β”‚
  β”‚   β€’ select {}  (select statement)                              β”‚
  β”‚   β€’ go func()  (goroutine creation)                            β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜


Phase 2: Propagate Async Status
───────────────────────────────
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚                                                                β”‚
  β”‚   func A() {           func B() {         func C() {          β”‚
  β”‚     <-ch  ◀── ASYNC      A()  ◀── ASYNC     B()  ◀── ASYNC   β”‚
  β”‚   }                    }                   }                   β”‚
  β”‚                                                                β”‚
  β”‚   Async propagates through call graph                          β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜


Phase 3: Code Generation
────────────────────────
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚                                                                β”‚
  β”‚   // SYNC function                // ASYNC function            β”‚
  β”‚   function add(a, b) {            async function recv(ch) {   β”‚
  β”‚     return a + b                    return await ch.receive() β”‚
  β”‚   }                               }                            β”‚
  β”‚                                                                β”‚
  β”‚   // Call site                    // Call site                 β”‚
  β”‚   let sum = add(1, 2)             let val = await recv(ch)    β”‚
  β”‚                                                                β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Channel Operations

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           CHANNEL TRANSLATION                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Go Code:                              TypeScript Output:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ch := make(chan int, 1)    β”‚  ───▢ β”‚ let ch = $.makeChannel<number>(1, 0)β”‚
β”‚                            β”‚       β”‚                                     β”‚
β”‚ ch <- 42                   β”‚  ───▢ β”‚ await $.chanSend(ch, 42)            β”‚
β”‚                            β”‚       β”‚                                     β”‚
β”‚ val := <-ch                β”‚  ───▢ β”‚ let val = await $.chanRecv(ch)      β”‚
β”‚                            β”‚       β”‚                                     β”‚
β”‚ val, ok := <-ch            β”‚  ───▢ β”‚ let {value: val, ok} =              β”‚
β”‚                            β”‚       β”‚     await $.chanRecvWithOk(ch)      β”‚
β”‚                            β”‚       β”‚                                     β”‚
β”‚ close(ch)                  β”‚  ───▢ β”‚ ch.close()                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜


Select Statement:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ select {                   β”‚       β”‚ await $.selectStatement([           β”‚
β”‚ case val := <-ch1:         β”‚  ───▢ β”‚   {                                 β”‚
β”‚   process(val)             β”‚       β”‚     id: 0, isSend: false,           β”‚
β”‚ case ch2 <- data:          β”‚       β”‚     channel: ch1,                   β”‚
β”‚   sent()                   β”‚       β”‚     onSelected: async (r) => {      β”‚
β”‚ default:                   β”‚       β”‚       let val = r.value             β”‚
β”‚   nothing()                β”‚       β”‚       process(val)                  β”‚
β”‚ }                          β”‚       β”‚     }                               β”‚
β”‚                            β”‚       β”‚   },                                β”‚
β”‚                            β”‚       β”‚   {                                 β”‚
β”‚                            β”‚       β”‚     id: 1, isSend: true,            β”‚
β”‚                            β”‚       β”‚     channel: ch2, value: data,      β”‚
β”‚                            β”‚       β”‚     onSelected: async () => sent()  β”‚
β”‚                            β”‚       β”‚   }                                 β”‚
β”‚                            β”‚       β”‚ ], true)                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Goroutine Translation

Go Code:                              TypeScript Output:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ go func() {                β”‚       β”‚ queueMicrotask(async () => {        β”‚
β”‚   doWork()                 β”‚  ───▢ β”‚   {                                 β”‚
β”‚ }()                        β”‚       β”‚     doWork()                        β”‚
β”‚                            β”‚       β”‚   }                                 β”‚
β”‚                            β”‚       β”‚ })                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Value Semantics

GoScript preserves Go's value semantics for structs:

Clone on Assignment

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       VALUE SEMANTICS TRANSLATION                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Go Code:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ original := Point{X: 10, Y: 20}    β”‚
β”‚ copy := original                   β”‚  // Creates independent copy
β”‚ copy.X = 100                       β”‚
β”‚ println(original.X)                β”‚  // Still 10
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                    β”‚
                    β–Ό

TypeScript Output:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ let original = new Point({X: 10, Y: 20})                               β”‚
β”‚ let copy = original.clone()         // .clone() creates deep copy      β”‚
β”‚ copy.X = 100                                                           β”‚
β”‚ $.println(original.X)               // Still 10                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜


Clone Implementation:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ public clone(): Point {                                                β”‚
β”‚     const cloned = new Point()                                         β”‚
β”‚     cloned._fields = {                                                 β”‚
β”‚         X: $.varRef(this._fields.X.value),   // Copy value             β”‚
β”‚         Y: $.varRef(this._fields.Y.value)    // Copy value             β”‚
β”‚     }                                                                  β”‚
β”‚     return cloned                                                      β”‚
β”‚ }                                                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Control Flow Translation

For Loop Variants

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          FOR LOOP TRANSLATION                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Standard For:
  Go:    for i := 0; i < 10; i++ { }
  TS:    for (let i = 0; i < 10; i++) { }

While Loop:
  Go:    for condition { }
  TS:    while (condition) { }

Infinite Loop:
  Go:    for { }
  TS:    for (;;) { }

For-Range (Slice):
  Go:    for i, v := range slice { }
  TS:    for (const [i, v] of $.rangeSlice(slice)) { }
         // rangeSlice captures slice state before iteration

For-Range (Map):
  Go:    for k, v := range m { }
  TS:    for (const [k, v] of m.entries()) { }

For-Range (String):
  Go:    for i, r := range str { }
  TS:    for (const [i, r] of $.rangeString(str)) { }
         // Iterates over runes, not bytes

Defer Translation

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           DEFER TRANSLATION                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Sync Defer:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ func process() {           β”‚       β”‚ function process() {                β”‚
β”‚   f := open("file")        β”‚       β”‚   const $defer = new $.DisposableStack()
β”‚   defer f.Close()          β”‚  ───▢ β”‚   try {                             β”‚
β”‚   // work with f           β”‚       β”‚     let f = open("file")            β”‚
β”‚ }                          β”‚       β”‚     $defer.defer(() => f.Close())   β”‚
β”‚                            β”‚       β”‚     // work with f                  β”‚
β”‚                            β”‚       β”‚   } finally {                       β”‚
β”‚                            β”‚       β”‚     $defer.dispose()                β”‚
β”‚                            β”‚       β”‚   }                                 β”‚
β”‚                            β”‚       β”‚ }                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Async Defer:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ func process() {           β”‚       β”‚ async function process() {          β”‚
β”‚   ch := make(chan int)     β”‚       β”‚   await using $defer =              β”‚
β”‚   defer close(ch)          β”‚  ───▢ β”‚     new $.AsyncDisposableStack()    β”‚
β”‚   // use channel           β”‚       β”‚   let ch = $.makeChannel(...)       β”‚
β”‚ }                          β”‚       β”‚   $defer.defer(() => ch.close())    β”‚
β”‚                            β”‚       β”‚   // use channel                    β”‚
β”‚                            β”‚       β”‚ }                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

File Organization

goscript/
β”œβ”€β”€ cmd/goscript/          # CLI entry point
β”œβ”€β”€ compiler/              # Core v2 compiler owners
β”‚   β”œβ”€β”€ compiler.go        # Public Go adapter over CompileService
β”‚   β”œβ”€β”€ service.go         # Pipeline coordinator
β”‚   β”œβ”€β”€ compile-request.go # Adapter normalization and request validation
β”‚   β”œβ”€β”€ package-graph.go   # go/packages loading and package graph facts
β”‚   β”œβ”€β”€ semantic-model.go  # Semantic/package/type/method/async facts
β”‚   β”œβ”€β”€ lowering.go        # Go AST + semantic facts to compiler IR
β”‚   β”œβ”€β”€ lowered-model.go   # Lowered IR structs
β”‚   β”œβ”€β”€ typescript-emitter.go # Deterministic TypeScript rendering
β”‚   β”œβ”€β”€ runtime-contract.go   # Generated helper/import contract
β”‚   β”œβ”€β”€ override-registry.go  # Handwritten gs/ package metadata/copy plans
β”‚   └── wasm_api.go       # Browser source-compilation adapter
β”œβ”€β”€ gs/                    # Runtime & handwritten packages
β”‚   β”œβ”€β”€ builtin/           # @goscript/builtin runtime
β”‚   β”‚   β”œβ”€β”€ index.ts       # Main exports
β”‚   β”‚   β”œβ”€β”€ varRef.ts      # VarRef type
β”‚   β”‚   β”œβ”€β”€ slice.ts       # Slice helpers
β”‚   β”‚   β”œβ”€β”€ channel.ts     # Channel implementation
β”‚   β”‚   β”œβ”€β”€ map.ts         # Map helpers
β”‚   β”‚   β”œβ”€β”€ type.ts        # Runtime type info
β”‚   β”‚   β”œβ”€β”€ defer.ts       # Defer support
β”‚   β”‚   └── errors.ts      # Error handling
β”‚   └── [std packages]/    # Handwritten std library
β”œβ”€β”€ design/                # Design documentation
β”‚   β”œβ”€β”€ DESIGN.md          # Main design doc
β”‚   β”œβ”€β”€ ASYNC.md           # Async design
β”‚   β”œβ”€β”€ VAR_REFS.md        # VarRef design
β”‚   └── ...
β”œβ”€β”€ tests/                 # Compliance test suite
β”‚   └── tests/             # 260+ test cases
└── docs/
    └── explainer.md       # This file

Summary

GoScript achieves Go-to-TypeScript translation through:

  1. Owner-Separated Pipeline: Request, graph, semantic, lowering, runtime, override, and emit owners keep durable rules in one place
  2. VarRef System: Enables pointer semantics in TypeScript
  3. Function Coloring: Automatically determines async/sync boundaries
  4. Runtime Helpers: Provide Go-like semantics for slices, channels, maps
  5. Value Semantics: Clone methods preserve Go's copy behavior
  6. Structured Diagnostics: Unsupported requests or syntax fail before output is written
  7. Comprehensive Type Mapping: Go types become idiomatic TypeScript

The result is maintainable TypeScript that preserves Go's behavior while feeling natural to TypeScript developers.