Chapters
Catena language basics
Catena is the little language you use to write sequences inside Castiel — short, readable recipes that a calculator carries out step by step. A sequence might work out a VAT-inclusive total, convert a run of measurements, or ask you for a figure and act on it. This chapter covers the groundwork: how a sequence is laid out line by line, how forgiving Catena is about the small stuff, how you name things, the three kinds of note you can attach to a line, the simplest values you can write down, and how you store a result in a variable.
If you have never written a sequence before, read this chapter top to bottom — every idea here is used in every sequence you will ever write. If you are already comfortable and just want the assignment forms, jump to Variables and assignment. For the wider tour of what sequences are and where you author them, see Getting started.
One instruction per line
A sequence is a list of lines, and the rule is as plain as it sounds: one line is one instruction. Lines do not end with a semicolon, a colon, or any other terminator — the line break itself ends the instruction. When you press Enter, the current instruction is finished and the next one begins.
price * 1.23 -> total
DISPLAY totalThat is two instructions: work out price × 1.23 and store it, then show the result. Nothing marks the end of a line except the end of the line.
Blank lines and indentation. Empty lines are ignored, so you can use them to space a long sequence into readable groups. Indentation is for your eyes only — unlike some languages, spacing a line further to the right never changes what it means. The editor will indent nested blocks for you to make structure visible, but a stray space can never break a sequence or alter a result. Where Catena has blocks (conditions, loops), they are closed by an explicit END rather than by how far a line is indented, so there is no invisible-whitespace trap to fall into.
Forgiving input
Catena is deliberately lenient about the small mechanical details that trip people up, on one firm condition: it is only forgiving where your intent is unmistakable. It will never quietly guess in a way that could change your answer. Within that limit, several things you might fuss over simply do not matter.
Spaces. Any run of spaces or tabs counts as a single separator. These three lines are identical:
a+b
a + b
a + bWrite whichever is easiest to read; the result is the same.
Commas. In a list of arguments, the space after a comma is optional, and a stray trailing comma is ignored. sin(a),cos(a) and sin(a), cos(a), are read the same way.
Brackets around argument lists. For commands, the parentheses around the arguments are optional. These two lines mean exactly the same thing:
PRINT("Total is", total)
PRINT "Total is", totalA missing closing mark at the end of a line. If you reach the end of a line having opened a bracket or a quote but not closed it, Catena closes it for you and shows a small hint rather than stopping with an error. Type PRINT("Total and press Enter, and the closing " and ) are supplied for you.
Where forgiveness stops. Catena is not lenient about grouping parentheses inside an expression, because those genuinely change the meaning. (a + b) / c and a + b / c are different calculations, so Catena will never add, move, or infer a grouping bracket on your behalf — you write the grouping you mean. That distinction (grouping is exact; almost everything else is forgiving) is the whole philosophy in one line. Grouping is covered in Expressions and operators.
Naming things
Whenever you store a value or write a sequence, you give it a name (an identifier). Names in Catena follow a few gentle rules:
- A name is made of letters, digits, and the underscore
_, and it must not start with a digit.total,net_price, andrate2are fine;2rateis not. - Letters may be any letters, not just the English alphabet — a name in your own language is accepted and stored exactly as you typed it.
- Names match without regard to case, but are shown exactly as you wrote them.
Total,total, andTOTALall refer to the same variable, so you cannot accidentally split one value across three near-identical names by mistyping the capitalisation. At the same time, Catena preserves the spelling you chose and displays it back to you, so a name you wrote asNetPricekeeps its capitals on screen. - Multi-word names are written with underscores —
total_cost. If you type a name as a phrase, the editor binds it into a single name for you and stores it with underscores, sototal costbecomestotal_cost.
A short, descriptive name pays for itself: vat, sale_price, and months_left tell a later reader (often you) what each value is, at a glance.
Three kinds of note
Catena lets you attach explanatory text to a line, and it distinguishes three different kinds because they have different audiences and different lifetimes. Keeping them separate means a note meant for you while editing never leaks into the calculation your reader sees.
1. Source comments — notes to whoever edits the sequence. A source comment starts with #. Everything after the # on that line is a comment, ignored when the sequence runs. It may sit at the end of a line or fill a whole line of its own:
sum_items * 0.05 -> vat # 5% VAT on the running total
# the next block asks the user for a discountUse these exactly as you would jot a note in the margin — to remind yourself why a line does what it does. They stay in the source and are never shown to someone merely reading the calculation.
2. Intent comments — a stated purpose. An intent comment records what a line or block is meant to accomplish ("this computes the VAT-inclusive total"), separately from the code that does it. It carries a note of where it came from — whether you wrote it or the authoring assistant suggested it — and it exists so intent and implementation can be checked against each other. Like a source comment, it stays in the source and is not printed when the sequence runs.
3. Tape annotations — messages to the person reading the results. A tape annotation is different in kind from the other two: it is output. When the line runs, the annotation is printed onto the shared paper tape alongside the result, for the end user reading the calculation to see. A line that prints "Sum is over $5000, so VAT is increased by 5%" is producing a tape annotation — a caption on the result, not a note on the code. You create these with the printing commands (PRINT, OUT), covered under commands.
The distinction to hold on to: the first two kinds live only in the source and speak to whoever edits the sequence; the third is emitted to the tape when the sequence runs and speaks to whoever reads the answer.
Simple values you can write down
The plain values you type directly into a sequence are called literals. This section covers the everyday ones — numbers, text, and true/false. Catena also has literals for money, quantities with units, and dates and times; those carry extra rules of their own and are covered in Types and formatting.
Numbers. Write a number the natural way: 42, 3.14, -5. Two conveniences are worth knowing:
- Digit grouping. You may place underscores between digits to make a large number readable:
1_000_000is one million. The underscores are purely cosmetic — they group the digits for your eye and have no effect on the value. - Exponent form. For very large or very small numbers you can use
enotation:2.5e3means2.5 × 10³, that is,2500. The digits before theeare the number and the digits after are the power of ten.
Everyday numbers in Catena are exact — the calculator does not lose the last penny of 0.10 + 0.20 the way ordinary calculators can. The reasoning behind that, and when a result switches to an approximate form, are explained in Types and formatting.
Text. A piece of text is written inside double quotes: "Net price?", "USD". Text is used for labels, prompts, and short codes. Catena is a calculator, not a word processor: there is no built-in way to split, search, or reshape text, because you never do arithmetic on it.
True and false. A yes/no value is written TRUE or FALSE. Because "yes" and "no" read more naturally in some sequences, Catena accepts YES for TRUE and NO for FALSE — they mean exactly the same thing. These values are what conditions test when a sequence decides between two courses of action.
399 # a number
"Net price?" # text
YES # the same value as TRUE
1_000_000 # one million, grouped for readability
2.5e3 # 2500 in exponent formVariables and assignment
A variable is a named box that holds a value. You put a value into a variable by assignment, and Catena's assignment reads left to right, in the order the calculator actually does the work: compute the value first, then store it.
The canonical form: the arrow ->. The standard way to assign is the left-to-right arrow. You write the calculation, then ->, then the name it should be stored under:
price * 1.23 -> totalRead that as "work out price × 1.23, and put the result in total." The direction matches how you think about it — do the sum, then keep the answer — and it matches the compute-then-store habit of a calculator's memory keys. Throughout Castiel the arrow is the form shown by default and the form saved in the file, so a sequence always travels in this canonical shape.
Notice that assignment uses ->, never =. This is deliberate and it removes a classic source of confusion: in Catena the equals sign = is left to mean genuine mathematical equality, exactly as it does in school, so it is free for use in comparisons and never doubles as "store this."
Friendly alternatives. Some people think of storing a value in other equally natural ways, so Catena accepts several spellings of the same assignment. You may type whichever reads best to you; Catena understands them all and stores the one canonical form. Taking "add one to a counter" as the example, every line below is the same instruction:
count + 1 -> count # canonical: arrow, calculation first
count <- count + 1 # right-to-left arrow
set count = count + 1 # algebra style, with the keyword 'set'
ADD 1 TO count # plain-language action
INCREASE count BY 1 # plain-language action
count++ # terse shorthand, add oneA few things to note about these alternatives:
- The right-to-left
<-and theset name = ...form are simply the arrow written the other way round, or in algebra style. Both are accepted on input. ADD ... TO ...andINCREASE ... BY ...are plain-language actions for the common case of changing a value in place — adding to it, or increasing it by an amount.count++is a terse shorthand for "add one." It is accepted when you type it, but it is not the form the app teaches or shows by default — it is normalised to the canonical arrow form like every other alternative.
Because all of these mean the same thing and are stored the same way, you can adopt whichever style suits you without worrying that you have written something subtly different.
Assign before you use. A variable comes into being the moment you first assign to it — there is no separate step to declare one. The one firm rule is that you must assign a value to a variable before you read it. Reading a name that was never assigned is reported as an error, and this is a feature, not a nuisance: it catches the commonest slip of all, a mistyped name.
price * 1.23 -> total
DISPLAY totl # error: 'totl' was never assigned. Did you mean 'total'?Here totl is a typo for total. Rather than quietly treating totl as a brand-new, empty variable and showing a wrong or blank result, Catena stops and points at the likely fix. The rule turns a silent wrong answer into an obvious, correctable mistake.
You can also state what type a variable should hold as you assign it — prompt_value -> age AS Int, for instance, to insist a value is a whole number. Types, and this AS form, are the subject of Types and formatting.
Putting it together
A short sequence drawing the pieces of this chapter into one place:
# work out a VAT-inclusive total from a net price
399 -> net_price # a plain number, stored
net_price * 0.20 -> vat # 20% VAT on the net price
net_price + vat -> gross # the total
PRINT "Total including VAT:", gross # a tape annotation for the readerEvery line is one instruction. Names are lower-case and descriptive. The # notes are for whoever edits the sequence; the PRINT line is the message that reaches the reader of the results. Each value is computed first and stored with the arrow. That is the whole shape of a Catena sequence — everything beyond this chapter builds on exactly this frame.
See also
- Getting started — what sequences are and where you write them.
- Types and formatting — money, quantities, dates, exact-versus-approximate numbers, and the
ASoperator. - Expressions and operators — arithmetic, comparison, grouping parentheses, and how calculations are built.