Make a file
A Turf program lives in a plain text file whose name ends in .tr. That ending tells everyone, including the compiler, that the file holds Turf.
Make a folder for your code
Somewhere easy to find, such as your home folder. Call it
turf-practice.Make a new file in it called hello.tr
Use your text editor’s New File and Save As. Check the name ends in
.trand not.tr.txt: some editors add.txtwithout asking.Open a terminal in that folder
In the terminal,
cdmeans “change directory”, which means go into a folder. Typecd turf-practiceand press Enter.
mkdir turf-practicecd turf-practiceThe two commands above do steps 1 and 3 from the terminal: mkdir makes a folder, and cd goes into it.
Type the program
Type this into hello.tr, or copy it with the button, and save the file:
fn main(): int { printline("Hello, world!"); return 0;}Be careful to copy every symbol exactly: the brackets ( ), the curly braces { }, the quote marks " " and the semicolons ;. To a compiler, every one of them matters.
Run it
Back in the terminal, type:
turf run hello.trand you should see this:
$ turf run hello.tr Compiled to /tmp/turf-run-228119781/hello.o Successfully compiled to /tmp/turf-run-228119781/hello Hello, world!
You just wrote and ran a program!
The first two lines are turf telling you it compiled your program and where it put it. The last line is your program running: that’s your Hello, world!.
What each line means
Here is hello.tr again, taken apart one line at a time:
1fn main(): int {fnstarts a function: a named list of instructions. This one is calledmain, and that name is special:mainis where every Turf program starts. The empty()means it needs nothing to get going,: intsays it gives back a whole number when it finishes, and{opens its body.2 printline("Hello, world!");printlineprints some text, then moves to a new line. The text goes between double quotes. The;at the end finishes the instruction, like a full stop finishes a sentence.3 return 0;returnends the function and hands back a value. Formain, the number goes back to the computer, and0means “everything went well”.4}The closing
}ends the body ofmain. Every{needs a matching}.
Make it your own
Programs get interesting when you change them. Here’s hello.tr with a variable: a name that holds a value, so you can use it later. immut name = "Turf"; makes a variable called name that holds the text "Turf" (immut means it can’t be changed later; Language Basics explains). Then + joins pieces of text together:
fn main(): int { immut name = "Turf"; printline("Hello, " + name + "!"); return 0;}$ turf run hello.tr
Hello, Turf!
Each printline prints its own line, so several of them print several lines, top to bottom, in order:
fn main(): int { printline("Roses are red,"); printline("violets are blue,"); printline("this program runs,"); printline("and so can you."); return 0;}$ turf run lines.tr
Roses are red, violets are blue, this program runs, and so can you.
When things go wrong
Everybody makes mistakes when they program, including people who’ve done it for years. What matters is finding them quickly, and that’s where the compiler helps. Let’s make a mistake on purpose.
A misspelled name
This program spells name as nmae on line 3. To see what’s wrong without running anything, use turf check: it reads the program and reports every problem it finds.
fn main(): int { immut name = "Turf"; printline("Hello, " + nmae + "!"); return 0;}$ turf check oops.tr oops.tr (1 error) ── error at line 3, col 27 [E040 · undeclared variable] I can't find anything named 'nmae'. Hint: It may be from the current file: 'name' 3 │ printline("Hello, " + nmae + "!"); │ ^~~~ Here! Run `turf --explain E040` for more details.
That’s a lot of text, but every part has a job. From top to bottom:
Which file, and how many problems
oops.tr (1 error): the file and the number of errors in it.Where, and what kind
line 3, col 27is the spot: line 3, 27 characters along.E040is the error’s code, andundeclared variableis the kind of error.The message
What’s wrong, in plain words: there is nothing called
nmae.The hint
A suggestion for fixing it. Here the compiler noticed that
namelooks very similar, so you probably meant that.The picture
Your line of code, with
^~~~ Here!underlining the exact problem.Where to learn more
A command that explains this kind of error in detail.
Fix the spelling, run turf check oops.tr again, and it prints nothing at all. When turf check is silent, there are no errors.
Asking turf to explain
Every error code has a longer explanation, with examples. Ask for it with turf explain and the code:
$ turf explain E040 E040 ReferenceError (UNDECLARED_VARIABLE) I can't find anything with that name Turf looked everywhere it knows to look -- the current block, any block around it, the whole file -- and couldn't find anything called by that name. No variable, no struct, no enum, nothing. This is the most common error you'll hit while learning, and it's almost always one of two very fixable things. The first is a plain typo: mut count: int = 0; count = coutn + 1; // typo! should be "count" ...
A missing semicolon
Here’s another very common mistake: a ; left off the end of line 2.
fn main(): int { printline("Hello, world!") return 0;}$ turf check semi.tr semi.tr (1 error) ── error at line 3, col 5 [E102 · syntax error] Expected ';' after statement. 3 │ return 0; │ ^~~~~~ Here! Run `turf --explain E102` for more details.
Notice that the error points at line 3, not line 2. That’s because the compiler only knows the ; is missing when it reaches return and finds something it didn’t expect. When an error points at the start of a line, look at the end of the line before it too.
A program you can keep
turf run throws its program away when it’s done. To keep a program, so you can run it again any time without Turf, compile it with turf and a file name. -o hello names the program it makes:
$ turf hello.tr -o hello Compiled to hello.o Successfully compiled to hello $ ./hello Hello, world!
Now there’s a program called hello in your folder, and ./hello runs it. The ./ means “the one in this folder”. Along the way the compiler also made hello.o, a halfway step called an object file; you can ignore it.
Your first project
One file is fine for practice. Bigger programs are split over many files, and they have tests and settings. For that, Turf has projects. turf new makes one for you, ready to run:
$ turf new hello Created program package 'hello' in hello/ hello/turf.toml hello/src/main.tr hello/README.md hello/.vscode/extensions.json hello/.gitignore $ cd hello $ turf run Compiled to build/hello.o Successfully compiled to build/hello Hello, TurfLang! This is hello.
Inside a project you just type turf run, without a file name: turf knows where to start. Here’s what it made:
- turf.tomlthe manifest: the project’s name, version and settings
- src/your code lives here
- main.trwhere the program starts: what
turf runruns - README.mda short page about the project, with everyday commands
- .vscode/recommends the Turf extension to VS Code
- .gitignoretells git not to save the
build/folder - build/appears when you build: the finished program goes here
turf.toml is short. TOML is a simple format for settings: names on the left, values on the right.
[package]
name = "hello"
version = "0.1.0"
turf = "2.0"
[dependencies]
turf = "2.0" says this project needs Turf 2.0 or newer. [dependencies] is where other people’s code you use will be listed; it’s empty for now.
And this is src/main.tr:
// src/main.tr: this package's entry point. `turf run` builds and runs it.import io;fn main(): int { io::printline("Hello, TurfLang! This is hello."); return 0;}Two things are new here:
- The first line starts with
//, so it’s a comment: a note for people. The compiler skips everything from//to the end of the line. import io;brings in the standard library’siomodule, where printing lives, andio::printlinemeans “theprintlinefromio”. You didn’t need this inhello.trbecause the most common modules,ioamong them, are always available. Writingio::just makes it clear whereprintlinecomes from.
Build without running
turf build compiles the project without running it. The program is saved as build/hello:
$ turf build Compiled to build/hello.o Successfully compiled to build/hello
Your first test
A test is a small program that checks your code does what you expect. In a project, tests live in a folder called tests/. Make that folder, and put this in tests/basic.tr:
import test;fn main(): int { test::assert(1 + 1 == 2, "arithmetic still works"); return 0;}test::assert checks that something is true. Here it checks that 1 + 1 == 2; == means “is equal to”. If it weren’t true, the test would fail and print the message. Now run every test in the project:
$ turf test Running Turf Test Suites... [tests] basic.tr ... PASS === Test Summary === Total Tests: 1 Passed: 1 Failed: 0 All tests passed successfully!
Every file in tests/ runs as its own program, and a test passes when it finishes with 0.
A failing test looks like this. The details at the bottom name the file and the line (basic.tr:4), followed by your message:
$ turf test Running Turf Test Suites... [tests] basic.tr ... RUNTIME FAILED (Exit code 134) === Test Summary === Total Tests: 1 Passed: 0 Failed: 1 Failed Tests Details: --- tests/basic.tr (Runtime Error exit 134): basic.tr:4: arithmetic still works ---
What you learned
- A Turf program is a
.trfile, and it starts atfn main(). turf run file.trcompiles a program and runs it;turf file.tr -o namemakes a program you can keep.turf checkfinds mistakes, andturf explainexplains an error code.turf newmakes a project;turf run,turf buildandturf testwork inside it.
Next, you’ll learn the building blocks every program is made of: values, variables, maths, choices and loops.