Skip to content

Type System

RuneLang uses type annotations on declarations with dynamic dispatch at runtime. Every variable must declare its type, and the runtime enforces type safety during execution.

RuneLang typeTraditional nameRust equivalentSizeExample
CountstoneIntegeri6464-bit signed42, -7, 0xFF
PotionFloatf6464-bit IEEE 7543.14, -0.5
RunestoneStringStringUTF-8, heap"hello"
FlagstoneBooleanbool1 bitTruth, Falsehood
ScrollArrayVec<Value>Dynamic[1, 2, 3]
TomeMap / DictVec<(K, V)>Ordered{"a": 1}
CofferByteu88-bit unsignedbyte values
HexHex dataraw hex
FamiliarObject / AnyReferenceGuild instances
VoidNone / null()ZeroVoid
42 // decimal
-7 // negative
0xFF // hexadecimal (255)
0b1010 // binary (10)
1_000_000 // underscore separators (1000000)
3.14
-0.001
100.0
"hello world"
"line one\nline two"
"tab\there"
"quote: \"hi\""
"backslash: \\"
"null byte: \0"
Truth
Falsehood
[] // empty
[1, 2, 3] // integers
["a", "b", "c"] // strings
[1, "mixed", Truth, 3.14] // mixed types
[[1, 2], [3, 4]] // nested
{} // empty
{"name": "Gandalf", "level": 20}
{1: "one", 2: "two"} // integer keys

Keys must be Countstone, Runestone, or Flagstone. Values can be any type.

Void

Values have truthiness when used in conditions:

TypeTruthyFalsy
FlagstoneTruthFalsehood
Countstoneany non-zero0
Potionany non-zero0.0
Runestoneany non-empty""
Scrollany non-empty[]
Voidalways falsy
Everything elsealways truthy

RuneLang has no implicit type coercion. This is a deliberate safety feature.

// JavaScript: "5" + 3 === "53" (string)
// JavaScript: "5" - 3 === 2 (number)
// RuneLang: "5" + 3 === "53" (string concatenation is explicit)
// RuneLang: "5" - 3 === ERROR (type error)

The only exception is string concatenation with +, which converts the right operand to a string when the left operand is a Runestone.

Use Transmute for explicit conversions:

Countstone n is Transmute("42", "Countstone"); // 42
Runestone s is Transmute(42, "Runestone"); // "42"
Countstone i is Transmute(3.99, "Countstone"); // 3 (truncates)
Potion f is Transmute(42, "Potion"); // 42.0

All variables are immutable by default:

Countstone x is 5;
x is written as 10; // ERROR: cannot reassign enchanted (immutable) rune

Use Mutable to opt in:

Mutable Countstone x is 5;
x is written as 10; // works

This applies to all types, including Scrolls and Tomes. However, note that collection contents can be modified through methods (.push(), etc.) even on immutable bindings — the immutability applies to the variable binding, not the collection’s internal data.