DocsGetting started
Setup and commands.
Check, run, format, and build a program; understand where Fango finds its library.
Once Fango is installed, two commands will cover most of your day: check while you edit, and run to execute the program. Compiler flags go before the source path, and anything after the path is passed to your program.
Check and run.
fango check hello.fango
fango run hello.fango
fango run program.fango -- first second
check parses and type-checks the program, and validates its lowered code, without generating any Go. It’s the fast way to find out whether something is wrong. run builds the program if needed and then runs it. Inside a program, Process.args() returns the arguments you passed.
Both commands follow imports from the entry file. When everything is fine they stay quiet apart from your program’s own output, and when it isn’t they show diagnostics pointing at the source. Add -v if you’d like to see progress.
Build an executable.
fango build hello.fango
fango build -o greeting hello.fango
The first command creates an executable named hello; the second names it greeting. The result is self-contained, so it doesn’t need the Fango library next to it at runtime and you can copy it wherever you like.
--debug builds an executable for the native debugger instead. If you want the generated Go project instead of an executable, use --emit-go. Treat it as exported build output: when you want to change how the program behaves, change the Fango source.
Formatting.
fango fmt hello.fango
fango fmt -w hello.fango
fango fmt -l hello.fango
On its own, fmt prints the formatted source. -w writes it back to the file, and -l lists the files that need formatting. You can pass several files at once. The formatter only needs the syntax to parse, so it works on programs that don’t type-check yet, and it keeps your comments. Let it decide the layout rather than tuning it around inferred types.
Entry points.
main is a function that takes Unit. It returns Unit when the program has nothing more to say:
main : () ->{Console} ()
main() = print "hello"
run never prints what main returns, so output has to be explicit. A value such as main = 42 is rejected, as is a main with real parameters; read arguments with Process.args() instead.
main’s row lists the services the program uses, such as Console, File.FileSystem, Net.Network, Process.Environment, Random, or Time.Clock.Clock. Each of them has a default handler, and the compiler wraps main in the defaults for whatever its row contains, so the console writes to the terminal and the clock reads the system time. Any other effect still needs a handler inside main. For instance, wrap a computation that can fail in Fail.attempt and decide how to report the result. If you leave main unannotated, its row is inferred and it gets the defaults of whatever it performs. An annotation is exact, so it also limits which services the program may reach.
Your own effects can declare a default the same way the library does, with an attribute that quotes the runner:
#[Runtime.Entry.DefaultHandler `runSystem`]
effect Environment
args : () -> List String
The runner has the shape (() ->{E, e} a) ->{R…, e} a, where the labels R… are only IO and effects that have defaults of their own. A default applies only around main, so a missing handler anywhere else is still a compile error.
To report failure to the shell, return a Process.Status instead of Unit:
import Process
main() =
print "checked"
Process.failure
This prints checked and exits with status 1. A returned status applies after main finishes normally, so every cleanup scope has released and every task has finished by then. Process.success is status 0, and Process.status n makes any other. Process.exit ends the process at once instead, skipping cleanup.
The library root.
The compiler needs a matching library root containing stdlib/, runtime/, and internal/. It looks in FANGO_ROOT first, then in the installed library locations relative to the executable, and finally in an enclosing Fango checkout. If you set FANGO_ROOT to something invalid, that’s an error rather than a silent fallback.
The easiest way to keep everything in step is make install in the language checkout, which installs the compiler and its support files together. Keep in mind that FANGO_ROOT only selects the library. It doesn’t change where your application’s source or build cache lives.
Build progress and statistics.
-v reports module checking, code emission, cache reuse, and linking. -vv adds finer detail about each stage and how long it took, which helps when you’re hunting for the slow part of a build.
Fango keeps reusable compilation and build artifacts in .fango/ next to the entry file, and it revalidates the current source graph before reusing any of them. -no-cache skips the checked artifacts for one run without throwing the cache away. FANGO_BUILD_DIR sends the generated build output somewhere else.
Clean cached output.
fango clean hello.fango
This removes the cache and build artifacts for the source file’s whole directory, including other entry programs that live there. It isn’t a way to clean just one executable.
Runtime failures.
When a compiled program panics, for example by dividing an integer by zero, it prints a Fango stack trace to standard error and exits with status 2. Each frame shows a function and the source line of the call, innermost first. If the panic happened in a spawned task, the trace also says where that task was spawned.
The REPL prints the same kind of trace for a runtime error and keeps your session going.
Frames follow what actually ran, not the source text. An inlined function may not get a frame of its own, and a function that tail-calls itself appears once, however many times it looped. If you need Go’s own goroutine dump to debug the runtime, set FANGO_TRACEBACK=go.
Programs can read the current stack with Trace.capture and turn those frames into text with Trace.render. For a typed application failure, use diagnostic failure reporting to keep the stack from its original abort site.
Language server and editor support.
The VS Code extension in the language repository’s editors/vscode/ runs fango lsp, giving you highlighting, formatting, diagnostics, hover information, definitions, and references. The installation guide shows how to enable it.
The language server shares its checking and module resolution with the command-line tools, so what your editor reports matches what fango check says. Save complete programs in source files, and reach for the REPL when you just want to try something small.
