Fun (FLS) for VS Code
June 10, 2026 · View on GitHub
Official VS Code support for the Fun language. This extension provides syntax highlighting and connects VS Code to the fls language server.
Features
- Syntax highlighting for
.fnfiles - Language Server support via
fls(hover, completion, diagnostics, go-to-definition, formatting, etc. as provided byfls) - ▶ Run and ⚙ Debug code lenses above every
fun main(for single-action run and debug workflows - Full debugger experience: breakpoints on
.fnfiles, call stack, variables panel with Fun type names - Output channel: Fun Language Server (useful for debugging startup issues)
- Bundled color theme: Fun Web (matches the reference website palette)
Requirements
You need the Fun tooling installed:
flslanguage serverfuncompiler (required for Run / Debug)
For the Debug feature you also need:
- A native debugger extension — CodeLLDB (recommended on macOS/Linux/Windows) or C/C++ (cpptools)
- A system C compiler:
cc/clang/gccon macOS/Linux,clang-clorcl.exeon Windows
By default the extension will try, in order:
- Workspace-local binaries:
zig-out/bin/fls(.exe)andzig-out/bin/fun(.exe) - Your system
PATH(e.g.fls,fun)
Getting Started
- Install the extension.
- Open a
.fnfile. - If the server doesn’t start, open View → Output and select Fun Language Server.
For local development builds, the extension prefers workspace binaries from zig-out/bin before falling back to executables on PATH.
Optional: set Preferences → Theme → Color Theme → Fun Web to use the same code palette as the website.
Settings
These settings live under Settings → Extensions → Fun:
fun.fls.path- Path to the
flsexecutable. - Default:
fls(falls back tozig-out/bin/flswhen available)
- Path to the
fun.fls.funPath- Optional path to the
funexecutable. - When set to a valid executable, it is passed to
flsvia theFLS_FUN_PATHenvironment variable.
- Optional path to the
fun.fls.stdlibDir- Optional stdlib root (folder containing
std/). - Passed to
flsviaFUN_STDLIB_DIRand takes precedence over derived paths.
- Optional stdlib root (folder containing
fun.debugger.type- Debugger to use for ⚙ Debug. One of
lldb(CodeLLDB) orcppdbg(cpptools). - Leave empty for auto-detection.
- Debugger to use for ⚙ Debug. One of
Notes:
- Settings support
${workspaceFolder}/${workspaceRoot}. - On Windows,
%VAR%environment variables inside paths are expanded (best-effort).
Run and Debug
Every .fn file that defines fun main( shows two buttons above it:
- ▶ Run — compiles and runs the file in an integrated terminal (equivalent to
fun -in file.fn). - ⚙ Debug — compiles with debug info, then launches the native debugger.
Debug experience
Breakpoints are set directly on .fn source lines. When a breakpoint is hit:
- Call stack shows Fun function names and
.fnfile/line numbers. - Variables panel shows variable names from your Fun code with Fun type names (
num,str,bin,dec,raw*, etc.) instead of C equivalents. - Watch and Debug Console expressions also display Fun types.
- Internal C boilerplate frames (e.g. async helpers) are marked as secondary and collapsed by default.
Debugging async functions
await expressions lower to a chain of C trampoline functions (__fun_async_call_, __fun_async_spawn_, __fun_async_entry_, then the real function body). The actual function call goes through pthread_create (or CreateThread on Windows) — which is opaque C runtime code the debugger cannot step through at the Fun source level.
This means step into on an await line will not automatically land inside the called async function. Instead the debugger follows the C runtime path:
await to_consumer.send_async(out); // step into → enters trampoline C code
The right way to debug async calls:
- Set a breakpoint inside the async function you want to inspect (e.g. a line inside
send_asyncinchannel.fn). The debugger will break there when the spawned thread executes it, and you can step normally from that point. - Alternatively, set a breakpoint on the line after the
awaitto resume once the call has returned.
Step-over (F10) on an await line works correctly — it blocks until the async call completes and advances to the next Fun source line.
How it works
- The compiler is invoked with
-gwhich embeds#line N "file.fn"directives in the generated C. These tell the C compiler to attribute all DWARF symbols to the original Fun source locations. - The C file is compiled with
-g(or/Zion Windows) to produce a native binary with full DWARF/CodeView debug info. - VS Code launches the native debugger (CodeLLDB or cpptools) against the binary. Because DWARF points to
.fnfiles, the debugger shows Fun source natively — no extra mapping layer. - A DAP message tracker intercepts variable type strings and remaps them from C types back to Fun types in real time.
- Temp files (
.cand compiled binary) are cleaned up automatically when the debug session ends.
Debugger auto-detection
The extension picks the debugger in this order:
fun.debugger.typesetting (if set explicitly)- CodeLLDB (
vadimcn.vscode-lldb) if installed - cpptools (
ms-vscode.cpptools) if installed - CodeLLDB on macOS/Linux, cpptools on Windows (best-effort fallback)
On Windows the extension tries clang-cl first (produces DWARF-compatible debug info for CodeLLDB), then cl.exe (MSVC, works with cpptools).
Commands
Open the Command Palette and run:
- Fun: Restart Language Server
- Fun: Show Language Server Output
- Fun: Run — run the current file
- Fun: Debug — debug the current file
Troubleshooting
No hover / completions / diagnostics
- Verify
flsis found:- Either ensure it’s on
PATH, or setfun.fls.pathto the full path.
- Either ensure it’s on
- If you’re building Fun from source, ensure
zig-out/binexists (or point settings at the built executables).
Standard library isn’t found
- The extension attempts to derive
FUN_STDLIB_DIRfrom the directory containingfls/fun. - Check the Fun Language Server output for the resolved paths.
Developing This Extension
From this folder (editors/vscode):
npm installnpm run compile- Press
F5in VS Code (Extension Development Host)
Packaging a .vsix:
npm install
npm run package
code --install-extension fun-language-*.vsix
See CONTRIBUTING.md for repo-wide contribution guidelines.