Goiaba
An experimental Go parser and WebAssembly compiler written in Rust. Goiaba translates Go source code into WebAssembly bytecode, enabling Go programs to run in web browsers and other WebAssembly environments.
Features
Parse Go source code into an Abstract Syntax Tree (AST)
Compile Go functions to WebAssembly modules
Support for fundamental Go language features (functions, control flow, arithmetic)
Export Go functions for use in JavaScript/WebAssembly environments
Export Go functions for use in Rust through C ABI
Export Go functions for use in Zig through C ABI
Command-line interface for compilation
Programmatic API for integration into Rust projects
Installation
As a CLI Tool
cargo install goiaba
As a Library
Add to your Cargo.toml :
[ dependencies ] goiaba = " * "
Usage
Command Line Interface
Basic compilation:
goiaba main.go -o main.wasm
Compile with verbose output:
goiaba input.go --output output.wasm --verbose
Generate a complete web project with HTML and JavaScript:
goiaba main.go -w ./web-project
Advanced usage with multiple options:
goiaba calculator.go -o calc.wasm -w ./demo --verbose
Library Usage
Basic Compilation
use goiaba :: wasm :: compiler :: compile_str ; fn main ( ) { let go_source = r#" package main //export add func add(x int, y int) int { return x + y } "# ; let wasm_bytes = compile_str ( go_source ) . expect ( "Failed to compile Go to WASM" ) ; // Write to file or use with a WASM runtime std :: fs :: write ( "output.wasm" , wasm_bytes ) . expect ( "Failed to write WASM file" ) ; }
Executing Compiled WASM
use goiaba :: wasm :: compiler :: compile_str ; use wasmtime :: { Engine , Instance , Module , Store } ; fn main ( ) { let go_source = r#" package main //export add func add(x int, y int) int { return x + y } "# ; let wasm_bytes = compile_str ( go_source ) . expect ( "Failed to compile Go to WASM" ) ; // Create a WASM runtime let engine = Engine :: default ( ) ; let module = Module :: from_binary ( & engine , & wasm_bytes ) . expect ( "Failed to load WASM module" ) ; let mut store = Store :: new ( & engine , ( ) ) ; // Instantiate the module let instance = Instance :: new ( & mut store , & module , & [ ] ) . expect ( "Failed to instantiate module" ) ; // Get the exported function let add_func = instance . get_typed_func :: < ( i32 , i32 ) , i32 > ( & mut store , "add" ) . expect ( "Failed to get 'add' function" ) ; // Call the function let result = add_func . call ( & mut store , ( 5 , 3 ) ) . expect ( "Failed to call 'add' function" ) ; assert_eq ! ( result , 8 ) ; }
Parsing Go Source Code
use goiaba :: parser :: parse_str ; fn main ( ) { let source = r#" package main func fibonacci(n int) int { if n <= 1 { return n } return fibonacci(n-1) + fibonacci(n-2) } "# ; match parse_str ( source ) { Ok ( ( objects , file ) ) => { println ! ( "Successfully parsed Go source code" ) ; // Access AST nodes through objects and file } Err ( err ) => { eprintln ! ( "Parse error: {}" , err ) ; } } }
Supported Features
Currently Supported
Function definitions with parameters and return types
Integer arithmetic operations (+, -, *, /, %)
Comparison operations (<, >, <=, >=, ==, !=)
Bitwise operations (&, |, ^, <<, >>)
Logical operations (&&, ||, !)
Variable declarations and assignments
If-else statements and nested conditionals
For loops with initialization, condition, and post statements
Recursive function calls
Function calls with multiple arguments
Increment and decrement operators (++, --)
Unary operators (-, !)
Struct types with field access and assignment
Composite literals for struct initialization
Planned Features
Arrays and slices
String literals and operations
Switch statements
Pointer operations
Methods on types
Interfaces
Multiple return values
Defer statements
Panic and recover
Goroutines and channels
Package imports
Standard library support
Export Directive
To make Go functions callable from WebAssembly, use the //export directive:
//export function_name func function_name ( param1 int , param2 int ) int { return param1 + param2 }
The exported name will be used in the WebAssembly module exports.
Development Status
Completed Features
Go source code parsing to Abstract Syntax Tree (AST)
Go source code parsing to Abstract Syntax Tree (AST) Translation of Go constructs to WebAssembly representations
Translation of Go constructs to WebAssembly representations WebAssembly bytecode generation
WebAssembly bytecode generation Function definitions with parameter and return types
Function definitions with parameter and return types Variable declarations and assignments
Variable declarations and assignments Control flow statements (if/else, for loops)
Control flow statements (if/else, for loops) Exportable WASM functions
Exportable WASM functions Arithmetic operations (+, -, *, /, %)
Arithmetic operations (+, -, *, /, %) Comparison operations (<, >, <=, >=, ==, !=)
Comparison operations (<, >, <=, >=, ==, !=) Bitwise operations (&, |, ^, <<, >>)
Bitwise operations (&, |, ^, <<, >>) Logical operations (&&, ||, !)
Logical operations (&&, ||, !) Increment/decrement operators (++, --)
Increment/decrement operators (++, --) Recursive function calls
Recursive function calls Struct types with field access and assignment
Struct types with field access and assignment Command-line interface
Command-line interface Unary operators (negation, logical NOT)
Unary operators (negation, logical NOT) Arrays and slices
Arrays and slices String literals and operations
String literals and operations Switch statements
In Development
Pointer dereferencing and operations
Pointer dereferencing and operations Methods on types
Methods on types Interfaces
Interfaces Multiple return values
Multiple return values Defer statements
Defer statements Panic and recover
Panic and recover Package imports
Package imports Standard library functions
Standard library functions Floating-point operations
Floating-point operations Memory management optimizations
Future Plans
Goroutines and channels
Goroutines and channels Complete standard library support
Complete standard library support Source maps for debugging
Source maps for debugging Optimization passes for generated WASM
Optimization passes for generated WASM JavaScript bindings generation (wasm-bindgen)
JavaScript bindings generation (wasm-bindgen) Rust code generation
Rust code generation Zig code generation
Zig code generation LLVM-IR target compilation
Architecture
Goiaba consists of several key components:
Parser: Lexical analysis and syntax parsing of Go source code AST: Internal representation of Go program structure Translator: Conversion from Go AST to WebAssembly IR Compiler: Generation of WebAssembly bytecode CLI: Command-line interface for user interaction
Performance Considerations
The generated WebAssembly code prioritizes correctness over optimization. Future versions will include:
Dead code elimination
Constant folding
Register allocation improvements
Memory access optimization
Function inlining for small functions
Contributing
Contributions are welcome. Please ensure all tests pass before submitting pull requests:
cargo test cargo clippy cargo fmt
Testing
Run the test suite:
make test
Limitations
Current limitations of the compiler, yet to be added:
No garbage collection (manual memory management)
Limited standard library support
No concurrency primitives (goroutines, channels)
Single file compilation only
No optimizer passes
License
BSD-3-Clause
Copyright (c) 2024 Raphael Amorim
Acknowledgments
This project builds upon concepts from the Go language specification and WebAssembly standards. Parser implementation is adapted from the Goscript project.