Compile-time code, 1 of 4
Consts and compile-time evaluation
Have the compiler work out values before the program runs, with Consts, Const Functions, and
What you’ll build
A program whose numbers are worked out by the compiler: the seconds in a day and a week, a
Fibonacci number from a Const Function, and the size of a fixed array. You’ll see which values
the compiler computes, what happens when one of them overflows, and how #If picks code for a
debug or a release build.
Values the compiler works out
Const declares a value that can’t change. An expression made only of literals, Consts,
operators, and casts is computed by the compiler, so the program holds the result and does no
arithmetic for it when it runs.
Import std.core
Const SECONDS_PER_DAY = 24 * 60 * 60
Const SECONDS_PER_WEEK = SECONDS_PER_DAY * 7
Print(SECONDS_PER_DAY, SECONDS_PER_WEEK)86400 604800
Assigning to a Const is an error: 'SECONDS_PER_DAY' is a Const and can't be changed. A Const
whose value needs the program to run, like one that calls an ordinary function, is still a Const,
but it’s worked out once, as the program starts, in order with the Globals. A top-level Const the
compiler works out can be used anywhere in its file, even above its own line.
Const Functions
A Const Function runs in the compiler whenever every argument it’s given is known at compile
time. It takes and gives numbers, Bools, Strings, Chars, and Enums, can’t throw, and calls only
other Const Functions, Assert, Panic, and the New a Struct gets. It uses no Globals, and
makes no objects or arrays, though its Locals can be Structs, tuples, and fixed arrays.
Import std.core
Const Function Fib(n: Int): Int
Return n < 2 ? n : Fib(n - 1) + Fib(n - 2)
End Function
Const Function IsPrime(n: Int): Bool
If n < 2 Then Return False
Local d = 2
While d * d <= n
If n % d == 0 Then Return False
d += 1
End While
Return True
End Function
Const FIB_20 = Fib(20)
Print(FIB_20)
Print(IsPrime(97), IsPrime(91))
Local n = 30
Print(Fib(n))6765 True False 832040
Fib(20) and both calls of IsPrime are worked out as the program is built. Fib(n) takes a
Local, which isn’t known until the program runs, so it’s an ordinary call, made when the program
runs.
Sizes known at compile time
A fixed array’s size, like the 5 in Int[5], has to be known at compile time. A Const, or a
Const Function’s result, can give it.
Import std.core
Const Function Fib(n: Int): Int
Return n < 2 ? n : Fib(n - 1) + Fib(n - 2)
End Function
Const SLOTS = Fib(10)
Struct Board
Field Cells: Int[SLOTS]
End Struct
Local board = Board()
board.Cells[0] = 7
Print(board.Cells.Count, board.Cells[0])55 7
A Const whose value is only known when the program runs, like one that calls an ordinary function, can’t be a size:
Import std.core
Function Levels(): Int => 3
Const LEVELS = Levels()
Struct Board
Field Cells: Int[LEVELS]
End Struct
Print(Board().Cells.Count)Compiling main.fb main.fb:8:22: error: a fixed array's size must be an integer known at compile time, like 64 or 8 * 8 | 8 | Field Cells: Int[LEVELS] | ^^^^^^ error: couldn't build main.fb because of 1 error
Mistakes found at compile time
What would panic when the program runs is an error when the compiler runs it: an overflow, a
division by zero, an index out of range, or a failed Assert. The error points at the call and,
in a note, at the line in the Const Function where it went wrong.
Import std.core
Const Function Fact(n: Int): Int
Return n <= 1 ? 1 : n * Fact(n - 1)
End Function
Const BIG = Fact(25)
Print(BIG)Compiling main.fb main.fb:7:13: error: 'Fact' can't run at compile time: the result of '*' overflows Int32 | 7 | Const BIG = Fact(25) | ^^^^^^^^ main.fb:4:25: note: here | 4 | Return n <= 1 ? 1 : n * Fact(n - 1) | --------------- error: couldn't build main.fb because of 1 error
Code for one build
#If lines pick which code is compiled at all. DEBUG is defined in a debug build, RELEASE in
one made with fb build --release, and PLATFORM_WINDOWS, PLATFORM_LINUX, or PLATFORM_MACOS
by the platform it’s built on. The branches that aren’t picked are skipped, and don’t even need
to parse.
Import std.core
#If DEBUG
Print("a debug build")
#Else
Print("a release build")
#End Ifa debug build
The platform symbols work the same way. Built on Windows, this program prints its first line, and built on macOS or Linux, its second:
Import std.core
#If PLATFORM_WINDOWS
Print("built on Windows")
#ElseIf PLATFORM_MACOS || PLATFORM_LINUX
Print("built on macOS or Linux")
#End IfWhat you learned
- A Const made of literals, Consts, and operators is computed by the compiler.
- A
Const Functionruns in the compiler when all its arguments are known, and as an ordinary call otherwise. - Fixed array sizes need values known at compile time, which Consts and Const Functions give.
- A Const Function’s overflow or failed Assert at compile time is a compile error.
#Ifcompiles code only for the builds and platforms it names.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.