This page covers what Refingere source looks like: how a file is laid out, how lines and indentation work, and how names, literals and operators are written. The Syntax reference has the exact grammar of every construct, and Tokens the exact rules for each piece of text.
A program is a folder of .rfn files. A file holds definitions - functions, structs, enums, unions, interfaces, constants, types - and implement blocks, each optionally preceded by attributes such as @test. There are no statements at the top level: code runs from a function marked @main.
There are no imports either. Every file in a folder sees every other file's definitions, in any order, and the builtin types are always visible. A definition prefixed with local is visible only in its own file, and one prefixed with global can also be reached from other folders by its path. See File and Define.
Each statement starts on a line of its own - there are no semicolons to end one. Inside a { } block, every statement is indented by exactly two spaces more than the line that opened the block, and the closing } lines up with that line again. A statement can continue on the next lines if they're indented at least two spaces past its start, as the inline if above does.
That makes indentation part of the grammar, not just style: a line indented by the wrong amount is an error, and a line that isn't indented far enough to continue the statement above starts a new one. Only spaces count - a tab anywhere in the source is an error.
Between brackets the rules relax. A list can be laid out any way until its closing ], and a call's arguments continue on lines indented at least two past the statement.
/// starts a comment that runs to the end of the line, and /* ... */ one that runs up to the first */, across lines if needed. Line comments take three slashes because // is already an operator - floor division - so a habitual // changes what the line computes rather than being ignored. A comment can go anywhere a space can. See Comment.
A name starts with a letter or _ and continues with letters, digits and _ - letters from any script, not only ASCII. A lone _ is the pattern that matches anything and binds nothing, in match cases and destructuring.
A name in backticks can contain spaces and symbols, which is how tests get readable names. Any name can be one - a function's, a type's, a const's, a let's, a parameter's, a field's, an enum case's - and it's read back in backticks too: let `one sale` := `coffee sale`{`price each` := 2.5}, then `one sale`.`price each`. When it starts with /, ./ or ../ it's a path instead, reaching a global definition in another folder. See Word Reference and Path Reference.
Keywords are lowercase, and every definition and statement starts with one: function, struct, let, set, if, for, match, return, and so on. A line's first word says what kind of line it is. Some words - then, else, in, with, while - only mean something at one spot inside a construct. The Keyword Index lists them all.
Numbers are written in decimal, or with a 0x, 0o, 0b or 0d prefix for another base, with underscores anywhere among the digits. A fractional part is written in the same base as the rest. A decimal number can end in an exponent - 6.02e23, 1e-9 - which makes it a float even without a fractional part. A minus sign isn't part of the number: -1 is the prefix operator - applied to 1.
Strings use single or double quotes, which mean the same thing - pick whichever the text doesn't contain. Tripled quotes let a string span several lines. A backslash escapes the next character in every form. true, false and undefined are written as plain words. See Number Literal and String Literal.
Square brackets make a list, and parentheses a tuple - a fixed-size group whose elements can have different types. A struct is built by writing its name directly against braces. See List Literal, Tuple Literal and Brace Call.
Operators work mostly as in other languages, with a few additions: comparisons chain, ++ concatenates, and the logical and some other operators are words. Wrapping an operator in parentheses turns it into a value that can be passed to a function. The Operators reference lists every one with its precedence. The set is fixed - your own types get them by implementing an interface.
Spaces matter in two places. Symbol characters written together form one operator, so +- is a single name, not two operators - put a space between operators. And a call, an index or a struct's braces go directly against what they apply to, with no space in between.
A subscript after a value indexes it and a superscript raises it to a power, each either a number or a single letter standing for a name. √ takes a square root, or a root of another degree with a subscript right after it. It's the same code as the spelled-out version - only easier to compare with the formula it came from. See Index Access, Binary Operation and Root.
Three characters written directly against a name give it a different meaning. & reads a context value, @ names an attribute, and # uses a macro. A macro can take a string written directly after it, or a body between {{{ and }}} - text in another language, which the macro reads instead of the Refingere parser.