Files and Folders

A Refingere program is a folder of .rfn files, and the folders inside it. There's no import statement and no module declaration - what a file can see follows from where it is. This page covers how names are shared between files and folders, and what else a folder decides.

A project

The compiler is given a folder as root, and every .rfn file under it is part of one program - see Command Line. Subfolders group the code, and each can have its own injected values. Tests live in the same files as the code they test.

Files in a folder

Every file sees the definitions of every other file in the same folder by their bare names, in any order. Splitting a file in two, or moving a function to another file in the folder, changes nothing for the code that uses it. The builtin types and functions are always visible too. Two files in a folder can't both define the same name.

Local definitions

local in front of a definition makes it visible only in its own file. It's for helpers that are an implementation detail of one file, and it lets two files each have their own helper with the same name. A local definition can't be global. Definitions inside a function's body are narrower still, visible only in that block. See Define.

Global definitions

A bare name only ever reaches the definitions of its own folder. global in front of a definition is what lets other folders reach it too, by its path. The name itself still stays in its folder: findOrder alone means nothing outside storage/. Everything that isn't global is private to its folder, so a folder's global definitions are the whole of what it offers the rest of the project. The builtin types' own members are defined this way - see Implementations.

Paths

A path is written in backticks, and how it starts says where it's read from:

  • `/storage/findOrder` starts at the project's root, so it means the same definition in every file.
  • `./reports/monthly` starts at the folder of the file using it, and `../storage/findOrder` at the folder above that.
  • Anything else in backticks, like `adds two numbers`, isn't a path. It's a name, found the same way a bare one is. A / anywhere else in it is an error.

Only a reference is a path. A definition can be named in backticks too - function `adds two numbers`(), struct `Order line`, let `one sale`, field `price each` - but that's its name, not where it is, so it can't hold a /.

A path can be used anywhere a name can - in calls, types and implement blocks - and it only ever reaches a global definition, even one in the same folder. See Path Reference.

implement blocks don't have names, and apply everywhere: once a type implements an interface in any file, it does so in the whole project.

What a folder decides

one per folder, seen by every call in it

A few things are set per file, folder or project:

  • The entry point. At most one function per folder is marked @main, or @app for a browser app. A second one in the same folder is an error.
  • Injected values. @inject provides a context value to every call in its file, @injectLocally in its folder, and @injectGlobally in the project - see Context.
  • Routes. A function marked @serve answers requests with the routes in its folder and the folders inside it - see Servers and Browser Apps.