Guide
Values and Expressions

Values and Expressions

All runtime "values" in Terbium are represented as expressions. An expression is a syntactic construct, and it is a piece of code that can be evaluated to produce a value. For example, the expression 1 + 21 + 2 evaluates to the value 33.

There are many different kinds of expressions in Terbium, some including,

  • literals, such as 11 and "hello""hello". These are expressions that evaluate to themselves.
  • variables, such as xx and yy. These are expressions that evaluate to the value bound to the variable.
  • operators, such as 1 + 21 + 2 and -3-3. These are expressions that evaluate to the result of applying the operator to the operands.
  • groups, such as (1 + 2)(1 + 2) and -(3)-(3). These are expressions that evaluate to the value of the expression inside the group, and are used to control the order of evaluation.

We will take a closer look at each of these kinds of expressions.

Literals

A literal is an expression that evaluates to itself. For example, the expression 11 evaluates to the value 11, and the expression "hello""hello" evaluates to the value "hello""hello".

Literals take many forms:

  • integer literals, such as 11 and 22.
  • floating-point literals, such as 1.01.0 and 2.02.0.
  • character literals, such as c'a'c'a'.
  • string literals, such as "hello""hello" and "world""world".
  • boolean literals, such as truetrue and falsefalse.
  • void, the unit value, evaluating to voidvoid. This is the value of an expression that does not evaluate to anything.

Integer literals

An integer literal can be written as a sequence of digits, optionally suffixed with u to indicate that the integer is unsigned. We will see more about unsigned integers later.

Optionally, an integer literal can be prefixed with radix modifiers:

  • 0b or 0B for binary,
  • 0o or 0O for octal, and
  • 0x or 0X for hexadecimal.

For example, 0b1010b101 is the same as 55, and 0xff0xff is the same as 255255.

Additionally, underscores may be used to separate digits in an integer literal, for example, 1_000_0001_000_000 is the same as 10000001000000.

Floating-point literals

A floating-point literal evaluates to a floating-point number. A floating-point number is a number with a fractional part, such as 1.51.5 or 3.143.14.

A floating-point literal can have underscores to separate digits, for example, 1_000.000_0011_000.000_001 is the same as 1000.0000011000.000001.

You can also use e or E to indicate scientific notation, for example, 1e61e6 is the same as 10000001000000, and 1.5e-31.5e-3 is the same as 0.00150.0015.

Character literals

A character literal evaluates to a character. A character literal is written as a one-character string prefixed with c, for example c'A'c'A' or c'\n'c'\n'.

We will see more about characters later.

String literals

A string literal evaluates to a string. A string literal is written as a sequence of characters surrounded by single or double quotes, for example "hello""hello"

Strings can span multiple lines:

"this string
spans multiple lines"

Escape sequences

Strings can also contain escape sequences:

SequenceDescription
\nNewline
\rCarriage Return
\tTab
\bBackspace
\fForm Feed
\\Literal backslash
\'Literal '
\"Literal "
\0 [1]Null byte
\x12 [2]Character by hex codepoint (2 digits)
\u1234 [2]Character by hex codepoint (4 digits)
\U12345678 [2]Character by hex codepoint (8 digits)

[1] Because strings will always have an encoding, null-bytes can only be placed in byte-string literals.
[2] Numbers are a placeholder of a valid hex value of the specified length, e.g. \u200b

'Here\'s a contraction with apostrophes'
"This is a \"quote\" with quotation marks"
'This string has\nnewlines'
'An em dash: \u2014'

Raw strings

Strings can also be raw, which means that escape sequences are not interpreted. A raw string is written as a string prefixed with ~, for example ~"hello \n world"~"hello \n world" is the same as "hello \\n world""hello \\n world".

Quote-escaped strings

A cleaner way to escape quotes is to use quote-escaped strings. A quote-escaped string is written by prefixing the string with any N number of pound symbols (#), and then suffixing the string with the same number of pound symbols.

For example, #"hello "world""##"hello "world""# is the same as "hello \"world\"""hello \"world\"", and ###"hello #"world"#"######"hello #"world"#"### is the same as "hello #\"world\"""hello #\"world\"".

Interpolated strings

Strings can also be interpolated, which means that expressions can be evaluated inside the string. An interpolated string is written as a string prefixed with $, any then any interpolated expressions are surrounded by { and }. Use {{ and }} to escape the braces.

For example, $"1 + 2 = {1 + 2}"$"1 + 2 = {1 + 2}" is the same as "1 + 2 = 3""1 + 2 = 3". The internals of string interpolation are explained later.

Boolean literals

A boolean literal evaluates to a boolean value. A boolean represents a truth value, and can be either truetrue or falsefalse.

Void

Void is the unit value, and is written as voidvoid. Void is the value of an expression that does not evaluate to anything, and it should not be commonly used.

Operators and Arithmetic

An operator is an expression that evaluates to the result of applying the operator to the operands. For example, 1 + 21 + 2 evaluates to 33, and -3-3 evaluates to -3-3.

Operators can be unary, binary, or ternary.

Unary operators

A unary operator is an operator that takes one operand. For example, -3-3 is a unary operator, because it takes one operand, 33.

There are two types of unary operators: prefix and postfix. A prefix unary operator is written before the operand, for example -3-3. A postfix unary operator is written after the operand. There are no postfix unary operators in Terbium.

The following are the unary operators in Terbium:

OperatorDescription
-Negation
!Logical not
~Bitwise not

Binary operators

A binary operator is an operator that takes two operands. For example, 1 + 21 + 2 is a binary operator, because it takes two operands, 11 and 22. All binary operators in Terbium are infix, which means that they are written between the operands.

The following are the binary operators in Terbium:

OperatorDescription
+Addition
-Subtraction
*Multiplication
/Division
%Modulo
**Exponentiation
&Bitwise and
|Bitwise or
^Bitwise xor
<<Bitwise left shift
>>Bitwise right shift
&&Logical and
||Logical or
==Equality
!=Inequality
<Less than
<=Less than or equal to
>Greater than
>=Greater than or equal to
..Range
..=Inclusive range

There are also keyword operators, which are operators that are written as keywords. The following are the keyword operators in Terbium:

OperatorDescription
isisType equality
ininContains
totoType-cast

Comparison operators

Comparison operators are a subset of binary operators that compare two values, always returning a boolean value (truetrue or falsefalse). They are ====, !=!=, <<, <=<=, >>, >=>=, isis and inin.

isis and inin have negated counterparts, !is!is and !in!in respectively. a !is ba !is b is the same as !(a is b)!(a is b) and a !in ba !in b is the same as !(a in b)!(a in b).

Comparison operators can be chained together to compare multiple values. For example, 1 < x != 101 < x != 10 is the same as writing 1 < x && x != 101 < x && x != 10.

Generally, if aa, bb, cc ... zz are expressions and op1, op2, op3 ... opN are comparison operators, then a op1 b op2 c op3 d ... opN za op1 b op2 c op3 d ... opN z is the same as writing a op1 b && b op2 c && c op3 d && ... && y opN za op1 b && b op2 c && c op3 d && ... && y opN z.

Ternary operators

A ternary operator is an operator that takes three operands. The ternary if or inline if operator is the only ternary operator in Terbium. It is written as if CONDITION then THEN_VALUE else ELSE_VALUEif CONDITION then THEN_VALUE else ELSE_VALUE.

For example, if 1 > 2 then "yes" else "no"if 1 > 2 then "yes" else "no" evaluates to "no""no". Ternary operators desugar to standard if-statements, which are explained in the Control Flow section.

Grouping (Parentheses)

Similar in mathematics, parentheses can be used to group expressions so that they are evaluated first. For example, (1 + 2) * 3(1 + 2) * 3 evaluates to 99.