Running your program

The pages before this one show how to WRITE loft. This one shows how to RUN it. You need one command to start, and everything else is optional.

Run a file

Put your program in a file ending in .loft and pass it to loft:

  $ loft hello.loft
  hello, world!

That is the whole thing. There is no build step to run first and no project to set up. A single file is a complete program.

Give your program some arguments

Put them after the file name, and declare one vector<text> parameter on main to read them:

  fn main(args: vector<text>) {
    for who in args { println("hello, {who}!"); }
  }
  $ loft greet.loft Ada Grace
  hello, Ada!
  hello, Grace!

That one parameter is the only shape main accepts. Any other — a plain text, two of them — is refused, because nothing would fill it.

Try something without making a file

Type loft on its own and you get a prompt where you can type one line at a time and see the answer straight away:

  loft
  loft REPL — :help for commands, :quit to exit
  loft> 2 + 3
  5

This is called a REPL, which is short for "read, evaluate, print, loop". It is the quickest way to check what a function does or try an idea.

Started by hand like that, the REPL remembers your session: the values you bound and the functions and structs you defined come back next time, and it says so as it starts.

  loft
  loft REPL — :help for commands, :quit to exit
  restored 2 statement(s) from last session
  loft>

--fresh asks for a clean one instead, and :reset clears it mid-session.

You can also feed it from a pipe, which is handy in a script. That is a different mode: it never reads or writes the saved session, so it always starts empty. The banner and the loft> prompts go to standard error and the answers to standard output, so a script can read just the answers:

  $ printf '2 + 3\n' | loft repl --fresh 2>/dev/null
  5

Two ways to run, and why you usually ignore this

loft can run your program in two ways. It compiles your program to a fast program first when it can, and otherwise it reads and runs your program directly. The second way is called interpreting.

You do not have to choose. loft picks for you, and the ANSWER is the same either way — that is a rule the language holds itself to, not a hope. You can ask for one on purpose when you want to:

  $ loft --interpret hello.loft
  hello, world!

A downloaded loft always interprets. That is normal and not something to fix.

Stop a program that runs too long

A loop with a mistake in it can run forever. Give loft a time limit and it stops the program for you:

  $ loft --timeout 10 hello.loft
  hello, world!

This is worth using whenever you run something for the first time.

Check your work without running it

Sometimes you only want to know whether the program is correct so far:

  $ loft check hello.loft
  ok

This reports mistakes and runs nothing. It is fast, and it is a good habit while you are still writing. It leaves a .loft folder beside your file to remember what it already worked out, which is why the second run is quicker.

When loft tells you something is wrong

A message from loft names the file, the line, and what to do. Say unused.loft binds a name it never uses:

  $ loft --interpret unused.loft
  warning[never-read]: Variable unused is never read
  note: 1 diagnostic above suggests what to write instead — re-run with `--explain`
  hello, world!

Between those first two lines it also prints the file and line it means, the source line itself, and a caret under the exact spot.

That closing note means loft has a replacement in mind. Ask for it:

  $ loft --explain --interpret unused.loft
  fix  delete `unused`   needs: computing it has no effect you are relying on   [dead-code lint · @F100]

The fix line is the suggested replacement and needs is the condition under which it applies — loft cannot know whether you meant to keep the name, so it tells you what it is assuming. The bracket names the topic to read up on; the feature catalogue has a page per tag. --explain only SHOWS you the fix. It changes nothing, so it is always safe to run.

fn main() {

A program is just a file with a main function in it, like this one. Everything above is how you would run this file.

  greeting = "hello";
  who = "world";
  message = "{greeting}, {who}!";
  assert(message == "hello, world!", "string interpolation builds the message");
  println(message);
}