Transpilation

The sub command transpiles a single .sb source file into idiomatic code in any of 13 target languages. All backends share one AST, so the output is consistent and verifiable.

The sub Command

$ sub program.sb <target>    # → program.<ext>

The target is a required positional argument. The output file is written to the same directory with the appropriate extension.

Available targets

TargetOutput extensionCI-verified
python.py✓
javascript.js✓
typescript.ts✓
c.c✓
cpp.cpp✓
rust.rs✓
go.go✓
java.java✓
kotlin.kt✓
swift.swift✓
ruby.rb✓
asm.sgenerated
css.cssgenerated

Shared AST

All backends — transpiler, interpreter, and native compiler — operate on the same abstract syntax tree. The pipeline is:

  1. Lexer — tokenize the .sb source into tokens
  2. Parser — build the AST from the token stream
  3. Backend — walk the AST and emit output in the target format

Because every backend sees the same tree, behavior is consistent. The CI suite runs each program through the interpreter and every transpiler backend, then diffs the output.

Type Inference

SUB has no type annotations. The codegen_infer.c module performs lightweight type inference by tracking the types of values as they flow through the program. This information is used by backends that need static types (Rust, Go, C, C++, TypeScript, Java, Kotlin, Swift) to emit correct declarations.

Note: Type inference is best-effort. For dynamic targets (Python, JavaScript, Ruby), types are erased and the runtime handles everything natively.

Type Mapping

Here is how SUB types map to each target language:

SUBPythonJavaScriptRustGoCJava
intintnumberi64int64long longlong
floatfloatnumberf64float64doubledouble
stringstrstringStringstringchar*String
boolboolbooleanboolboolintboolean
nullNonenullOptionnilNULLnull
arraylistArrayVec[]TarrayArrayList
objectdictObjectHashMapmapstructHashMap

Backend-Specific Notes

Python

Output is clean Python 3. Stdlib modules are translated to Python equivalents. Run with python3 program.py.

JavaScript

Outputs ES6+ JavaScript. Uses let/const, arrow functions where possible. Run with node program.js.

TypeScript

Full type annotations are inferred and emitted. Compile with tsc program.ts or run with ts-node program.ts.

C

Outputs a single .c file with a main() function. Compile with cc program.c -o program. The C backend includes a small runtime header for string and array operations.

C++

Uses std::string, std::vector, and std::cout. Compile with c++ program.cpp -o program -std=c++17.

Rust

Outputs idiomatic Rust with proper ownership. Types are fully inferred. Compile with rustc program.rs.

Limitation: The Rust backend does not yet handle all string mutation patterns. Some programs may need minor adjustments for borrow-checker compliance.

Go

Outputs a single .go file with a main package. Build with go build program.go.

Java

Outputs a single class with a main method. Compile with javac Program.java and run with java Program.

Kotlin

Outputs idiomatic Kotlin with a main function. Compile with kotlinc program.kt -include-runtime -d program.jar.

Swift

Outputs Swift 5+ code. Compile with swiftc program.swift.

Ruby

Outputs clean Ruby. Run with ruby program.rb.

x86-64 Assembly

Outputs NASM-syntax x86-64 assembly. This is a code-generation target — the assembly is not executed in CI.

CSS

The CSS backend is specialized for the UI DSL. It translates ui.* declarations into CSS rules. Not a general-purpose backend.

Running Transpiled Output

Each target produces a file you can run with the standard toolchain for that language:

# Transpile
$ sub hello.sb python      # → hello.py
$ sub hello.sb rust        # → hello.rs
$ sub hello.sb go          # → hello.go

# Run
$ python3 hello.py
$ rustc hello.rs && ./hello
$ go run hello.go

Tip: Use the interpreter as the reference. If a transpiled program produces different output than subi, that's a bug — please report it.

Next Steps