Fable: F# to JavaScript Compiler
repository·main·Indexed 25 days ago
https://github.com/fable-compiler/fableFable is an F# to JavaScript compiler powered by FSharp Compiler Services (FCS) that allows F# developers to target the JavaScript ecosystem. It includes support for various targets including JavaScript, Python (beta), PHP (experimental), and Rust. The project provides tools such as fable-compiler-js for Node.js environments, fable-standalone for JS-only environments, and the Fable.Core library for core utilities.
What's inside Fable
- Fable is an F# to JavaScript compiler powered by FSharp Compiler Services (FCS). It is designed to enable F# to function as a first-class citizen within the JavaScript ecosystem. For detailed documentation and setup guides, visit fable.io.
Overview of Fable.Cli
mainFable.Cli contains the source files used when Fable is compiled as a command-line interface (CLI) tool. It is currently distributed embedded within the
fable-compilernpm package.Important Compatibility Note: This component assumes a
netcoreapptarget and utilizes APIs that are not compatible with Fable itself.Overview of Fable Python support
mainFable Python provides beta support for transforming F# code into Python. The compiler transforms the F# AST into a Python AST and then generates typed Python source code.
Key design mappings include:
- F# List: Translated to
List.fs(immutable). - F# ResizeArray: Translated to Python
list. - F# Record: Translated to
dataclasses.dataclassdecorated types intypes.py. - F# Option:
Noneis translated to PythonNone;Someis erased. - F# Arrays: Various numeric arrays (e.g.,
int[],float[]) are implemented asFSharpArrayusing a custompyo3wrapper.FSharpArraystores elements unboxed and returns them in their Python representation (e.g.,int[]yields plainints).
- F# List: Translated to
Overview of Fable.Transforms
mainFable.Transforms contains the logic used by Fable to transform the F# Abstract Syntax Tree (AST) into a Babel AST. This transformation layer is a core part of the Fable compilation pipeline, enabling F# code to be converted into JavaScript via Babel.Overview of fable-library
mainThefable-libraryis the core library used by F# projects that have been compiled with Fable. It provides the essential runtime support and standard library functions required for F# code to execute correctly in a JavaScript/TypeScript environment.Understand the purpose of fable-metadata
mainThefable-metadatapackage provides the essential assemblies required for the Fable compiler to process F# projects. It includes the necessary metadata for the .NET Base Class Library (BCL),FSharp.Core, andFable.Core.Architecture of Fable.Beam
mainFable.Beam follows the standard Fable compilation pipeline, transforming F# source into Erlang source files (
.erl) via the following stages:- F# Source
- FSharp2Fable: Converts F# to Fable AST
- FableTransforms: Optimizes the Fable AST
- Fable2Beam: Converts optimized Fable AST to Erlang AST
- ErlangPrinter: Generates
.erlsource files
Fable.Beam Target Overview
mainFable.Beam allows compiling F# to the BEAM (Erlang VM). It targets Erlang source code and follows several design principles to ensure idiomatic BEAM performance while maintaining F# semantics:
- Target Language: Erlang source.
- Minimum OTP Version: 25.
- Module Naming: Uses
snake_casederived from the filename (e.g.,MyModule.fsbecomesmy_module.erl). - String Representation: Uses modern Erlang binaries (
<<"hello">>) for efficiency. - Equality: Uses Erlang's exact equality (
=:=,/=:=) to match F#'s value equality semantics. - Records: Compiled to Erlang maps (
#{}) withsnake_caseatom field names. - Library Layout: Fable library files are placed in
fable_modules/fable-library-beam/within the output directory. Erlang resolves these via the code path (-pa).
Understand Fable.Core API implementation
mainNote thatFable.Coredoes not include raw source files. Instead, all APIs are compiled by Fable using theFable.Transforms.Replacementsmodule or via specific attributes such asEmitorEraseto define their behavior.Fable.Beam Language Feature Support
mainFable.Beam maps core F# features to Erlang primitives. Key mappings include:
- Records & DUs: Records map to Erlang maps (
#{field => value}). Discriminated Unions (DUs) map to tagged tuples (e.g.,{atom_tag, Field1, ...}). - Collections:
list<T>maps to Erlang lists.Map<K,V>maps to Erlang maps.Set<T>maps to Erlangordsets(sorted lists).array<T>maps to Erlang lists wrapped in dict refs (byte arrays useatomics).
- Async & Task: Implemented via Continuation-Passing Style (CPS).
Async<T>is a functionfun(Ctx) -> ok end.Taskis an alias forAsync. - Error Handling:
try/withmaps totry/catchusingerlang:error. Custom exceptions are represented as maps with anexn_typetag. - MailboxProcessor: Implemented as an in-process CPS model using the process dict for state management.
- Records & DUs: Records map to Erlang maps (
Understand the Fable Library for Python architecture
mainThe Fable Python target is designed to provide F# type support (such as
uint8) and high performance in Python. It uses a two-tier architecture:- Python components: The core Fable library functionality written in Python.
- Rust extensions: Native code used for performance and to support types not natively available in Python (e.g., unsigned integers).
When using libraries compiled with Fable, this architecture ensures cross-platform compatibility and proper type fidelity.
Use fable-standalone for JS-only environments
mainUse
fable-standaloneto bootstrap Fable in environments that only support JavaScript, such as the browser or Node.js.Important Note: This package does not output JavaScript code directly. Instead, it outputs a JSON AST (Abstract Syntax Tree) which must then be transformed into JavaScript using Babel.