Standard library
The standard library is written in CShift itself (stdlib/*.cshift) and embedded in the compiler. Only what a program
actually uses gets compiled (generics are instantiated per type). Examples are in tests/cases/stdlib_*.cshift.
| Namespace | File | Contents |
|---|---|---|
| global | core.cshift |
IDisposable, IComparable<T>, IEquatable<T>, IHashable, sqrt |
System |
list.cshift, dictionary.cshift, hashset.cshift, stack.cshift, queue.cshift, stringbuilder.cshift, process.cshift, file.cshift, directory.cshift, encoding.cshift |
List<T>, Dictionary<K,V>, HashSet<T>, Stack<T>, Queue<T>, StringBuilder, Process, KeyValuePair<K,V>, File, Directory, Path, Encoding (using System;) |
Char |
char.cshift |
Char.IsDigit/IsLetter/IsLetterOrDigit/IsHexDigit/IsWhiteSpace/IsUpper/IsLower/ToUpper/ToLower/HexValue |
ConsoleInput |
console.cshift |
ReadLine, which the compiler calls for Console.ReadLine() |
System.Native |
args.cshift |
a helper function for Main(string[] args) |
Math |
math.cshift |
math functions and constants (without using: Math.Sqrt(2)) |
FastTrig |
fasttrig.cshift |
table-based trigonometry with integer angles and fixed point results (FastTrig.Sin(angle)) |
String |
string.cshift |
string helpers, visible as methods on string |
System.Native |
native.cshift |
C imports (fopen, sin, pthread_mutex/cond_*, …), also usable by your own programs (using System.Native;) |
System |
thread.cshift, mutex.cshift |
Thread/Thread<T>, SharedPtr<T>, Mutex<T> (using System;, see threading.md) |
System |
random.cshift |
Random: seeded pseudo-random numbers |
System |
datetime.cshift |
DateTime, TimeSpan, DayOfWeek, Stopwatch |
System |
stream.cshift |
FileStream, StreamReader, StreamWriter, SeekOrigin |
System |
json.cshift |
Json, JsonValue, JsonKind, JsonError |
System |
regex.cshift |
Regex, RegexMatch, RegexError |
System.Compression |
compression.cshift |
Deflate, Zlib, Gzip, Crc32, Adler32, CompressionError |
System.Image |
image.cshift, image_png.cshift, image_bmp.cshift, image_ppm.cshift |
Image, Color, ImageFormat, ImageError: PNG, BMP and PPM files |
System.Net |
net.cshift |
TcpListener, TcpConnection, NetError: TCP connections over IPv4 (using System.Net;) |
System.Ui |
ui.cshift, ui_draw.cshift, ui_window.cshift, ui_fonts.cshift |
Ui, Window, Theme, UiInput, Key, Canvas, Font, Rect, UiCommand, Clipboard, UiError: user interfaces in immediate mode, drawn by a software renderer or as drawing commands; windows on Windows (Win32), Linux (X11), in the browser (a canvas) and on AmigaOS (Intuition), see ui.md |
System |
os/…, amiga/os.cshift |
the operating system layer (_Os: clock, time zone, file times, seeking; _Net: sockets); the compiler adds the one of the target |
Amiga |
amiga/hardware.cshift |
Hardware: the Amiga’s custom chips (take over the machine, copper, vertical blank, chip memory); only for m68k-amigaos, see amiga.md |
Amiga |
amiga/graphics.cshift |
Screen, Bitmap, Sprite, CopperList, Blitter, SystemFont: graphics with the blitter, sprites and the copper; only for m68k-amigaos, see amiga.md |
List<T> — a growable array. Create it with List<int>.Create() or a collection expression (List<int> xs = [];).
Add, AddRange(T[]), Insert(i, v), RemoveAt(i), Remove(v), Clear(), Get(i) / list[i], Set(i, v) /
list[i] = v, Count(), Capacity(), IndexOf(v), Contains(v) (T: IEquatable<T>), Sort() (T:
IComparable<T>, stable), Reverse(), ToArray(); with functions: ForEach(action), Where(test) (a new list),
Select<U>(convert), Any(test), All(test), FindIndex(test) (list.Where(x => x > 0)), IsCreated().
foreach (var x in list) works. An invalid index ends the program with a panic.
Dictionary<TKey, TValue> — a hash table. Create(), Set(k, v) / dict[k] = v, Get(k) / dict[k] (panics
if the key is missing), Add(k, v) (Error<void>, fails on a duplicate key), TryGet(k) (Optional<TValue>), GetOrDefault(k, fallback), ContainsKey(k), Remove(k),
Clear(), Count(), Keys(), Values(), Entries() (KeyValuePair<K,V>[]). Keys must satisfy IEquatable and
IHashable: numbers, bool, char, enums and string do so out of the box; your own structs define
bool Equals(T other) and int GetHashCode().
Since there are no classes,
ListandDictionaryare small structs that point at shared storage: copies (assignment, arguments) see the same elements. The storage is made byCreate()(or[]). The zero value —new(),new List<T>(), a field that was not given a value — is an empty container without storage: it can be read (Count()is 0,foreachruns no turn), butAdd/Set/Append/Push/Enqueuepanic.IsCreated()tells which one it is. The same holds forHashSet,Stack,QueueandStringBuilder.
StringBuilder — builds text in a buffer (Append takes strings and string slices; text += ... on a local
variable is in place as well, see strings): var sb = StringBuilder.Create(); sb.Append("x"); sb.Append('c'); sb.AppendLine("…"); sb.Length(); sb.Get(i); sb.Clear(); string s = sb.ToString(); (a handle to shared storage, like List).
HashSet<T> — Create(), Add(v) (true if it was new), Contains(v), Remove(v), Count(), Clear(),
ToArray().
Stack<T> (last in, first out) — Create(), Create(capacity), Push(v), Pop(), Peek() (both panic when
empty), TryPop(), TryPeek() (Optional<T>), Count(), Get(i) (0 = top), Contains(v), Clear(), ToArray()
(top first). foreach goes from the top down.
Queue<T> (first in, first out, a ring buffer) — Create(), Create(capacity), Enqueue(v), Dequeue(),
Peek() (both panic when empty), TryDequeue(), TryPeek() (Optional<T>), Count(), Get(i) (0 = front),
Contains(v), Clear(), ToArray() (front first). foreach goes from the front to the back. Both are handles to
shared storage, like List.
Number formats (numberformat.cshift) — x.ToString("F2"), $"{x,8:F2}": D, X, B, F, N, E, P, G
with up to two digits, see number formats.
NumberFormat.Check(format, floatingPoint) tells why a format is not valid ("" if it is).
Process.Run("command") runs a command line through the shell and returns its exit code (what the program wrote
before is written out first, so the output of the command comes after it); RunCapture("command")
also captures what it wrote to stdout (Optional<string>); GetEnv("NAME") reads an environment variable
(Optional<string>); IsWindows() and IsMacOS() report the platform.
Directory — Exists(path), Create(path) (including parent directories), GetEntries(path) (names, sorted),
FindFiles(path, extension) (recursive, sorted), GetCurrentDirectory() (C library calls, no shell),
Delete(path [, recursive]) (an empty directory, or everything in it), Move(source, target) (IoError<void>).
Path — Combine, Normalize, GetDirectory, GetFileName, GetExtension, GetStem, ChangeExtension,
IsRooted, GetFullPath (absolute, without ./..), GetRelativePath(from, to).
Command line: int Main(string[] args) receives the arguments without the program name. Console.WriteError(Line)
writes to stderr, string.FromCStr(char*) copies a C string (unsafe) into a string. Console.ReadLine() reads a
line of the standard input (Optional<string> without the line break, null at its end; console.cshift): what was
written before is shown first, so Console.Write("Name: ") is a prompt.
Console.Write("Name: ");if (Console.ReadLine() is string name) Console.WriteLine("Hello, " + name);File (static, text is UTF-8 by default): ReadAllText(path [, encoding]), ReadAllBytes(path),
WriteAllText(path, text [, encoding]), WriteAllBytes(path, bytes), Exists(path), Delete(path),
Copy(source, target [, overwrite]), Move(source, target [, overwrite]), GetLastWriteTime(path) /
GetLastWriteTimeUtc(path) (IoError<DateTime>), SetLastWriteTime(path, time) / SetLastWriteTimeUtc(path, time)
(also for folders; on POSIX systems the time of the last access is set too). Reading returns
IoError<string> or IoError<uint8[]>, writing, copying and deleting return IoError<void> (see Error codes
below); a UTF-8 BOM is skipped when reading text. Paths go to the C library unchanged (so, on Windows, no non-ASCII characters in the path).
Paths, names and commands (File, Directory, Path, the streams, Process) are StringSlice parameters: a string,
or a part of one such as line.Trim(), is passed without .ToString(); a part that does not reach the end of its
string is copied for the C library, a whole string is not.
using System;
Error<string> Load(string path){ var text = try File.ReadAllText(path); try File.WriteAllText(path + ".bak", text); return text.Trim();}Error codes (error enums, stdlib/errors.cshift):
| Enum | Members | Returned by |
|---|---|---|
IoError |
CannotOpen (1), CannotWrite (2), CannotDelete (3), AlreadyExists (4), InvalidText (5), CannotCreate (6), CannotMove (7) |
File.*, Directory.Delete/Move, the streams |
ParseError |
Invalid (1), OutOfRange (2) |
ParseInt, ParseInt64, ParseDouble |
EncodingError |
OutOfBounds (1), NotAscii (2), InvalidUtf8 (3) |
Encoding.GetString |
NetError (System.Net) |
CannotResolve (1), CannotConnect (2), CannotListen (3), ConnectionLost (4), NotSupported (5) |
TcpListener, TcpConnection |
A caller can match a code (case IoError.CannotOpen:, if (r is IoError code)); a typed result converts to a
plain Error<T>, and try passes it on from a function returning Error<T> or the same typed result.
TcpListener, TcpConnection (System.Net) — TCP over IPv4 on Windows, Linux and macOS (WebAssembly and AmigaOS
report NetError.NotSupported). A server: TcpListener.Start("127.0.0.1", port) ("0.0.0.0" for every network;
port 0 takes a free one, Port() says which), Pending(milliseconds) (a client is waiting), Accept(), Stop(). A
client: TcpConnection.Connect(host, port) (a name or an address). A connection: Read(buffer, offset, count) (what
has arrived; 0 when the other side closed it), Write(bytes), WriteText(text), WaitForData(milliseconds),
Close(). Waiting with a time limit (-1: none) lets one thread serve several connections. Both are IDisposable
handles: copies share the socket. Errors are NetErrors; sending to a connection that the other side closed is an
error, not the end of the program.
using System;using System.Net;
using var listener = try TcpListener.Start("127.0.0.1", 8080);using var client = try listener.Accept();var request = new uint8[4096];int got = try client.Read(request, 0, request.Length);try client.WriteText("HTTP/1.1 200 OK\r\nContent-Length: 6\r\nConnection: close\r\n\r\nHello\n");Encoding — Encoding.UTF8() and Encoding.ASCII(): GetBytes(string), GetString(uint8[] [, start, count])
(EncodingError<string>: invalid UTF-8, or bytes above 127 for ASCII, are errors), GetByteCount, Name(). Strings are
always UTF-8 in memory; GetBytes with ASCII replaces other characters with ?. More encodings can be added as a
new EncodingKind.
Math — constants PI, E, Tau; Abs/Min/Max/Clamp (int, int64, float, double), Sign; Sqrt,
Cbrt, Pow, Exp, Log, Log2, Log10, Hypot; Sin, Cos, Tan, Asin, Acos, Atan, Atan2, Sinh,
Cosh, Tanh, DegreesToRadians, RadiansToDegrees; Floor, Ceiling, Truncate, Round (rounds half to even,
like in C#), Lerp, IsNaN, IsInfinity. Integer arguments are widened to double (Math.Sqrt(2)).
FastTrig — trigonometry from tables, without floating point: fast on CPUs without an FPU (the 68000), for
raycasters, rotations and demo effects. Angles are ints with 1024 steps per full circle (Quarter = 256 = 90°); any
value works, it is taken modulo 1024 with a mask. Sin/Cos return int16 in 1.14 fixed point (SinOne = 16384 =
1.0), so (r * FastTrig.Cos(a)) >> 14 scales a length. Tan, Cot, Sec (1/cos) and Csc (1/sin) return 16.16
fixed point (FixedOne = 65536), 2147483647 or -2147483647 at their poles; Sec/Csc are the step lengths of a
raycaster’s grid walk. Atan2(y, x) returns the angle of a vector (0..1023, within one step), FromDegrees /
ToDegrees convert (rounded). The tables (about 8 KB) are generated by stdlib/tools/fasttrig.py.
String helpers (s.Contains(x) ≙ String.Contains(s, x), static as string.Join(sep, parts)) work on
slices: they take StringSlice (a string converts for free), can
be called on a string or a slice, and the ones that return a part of the text return a view (nothing is copied):
Returns a view (StringSlice) |
Trim/TrimStart/TrimEnd (white space, or a given character), Substring on a slice, Split (StringSlice[], by character or string) |
|---|---|
| Queries | IsNullOrEmpty, Contains, IndexOf (also IndexOf(char, start)), LastIndexOf, StartsWith, EndsWith |
| New strings | PadLeft/PadRight, ToUpper/ToLower (ASCII only), Replace, Repeat, Join (of string[] or StringSlice[]) |
| Parsing | ParseInt/ParseInt64/ParseDouble (ParseError<…>) |
string entry = "name = Ann Lee";int eq = entry.IndexOf('=');StringSlice key = entry[..eq].Trim(); // "name", a view of 'entry'string value = entry[eq + 1..].Trim().ToString(); // keep a copy as a stringforeach (var part in "a, b, c".Split(',')) // StringSlice[]: no string per part Console.WriteLine(part.Trim());Equals, GetHashCode (FNV-1a) and CompareTo (byte-wise) exist for strings and for StringSlice (the same hash
for the same text): both can be keys of a Dictionary, elements of a HashSet or sorted in a List. + joins slices
like strings, and slice.CStr() (unsafe) passes one to C. Positions
are byte offsets; string.FromBytes(bytes [, start, count]) builds a string from bytes. New helpers are just written
as a function in namespace String (the first parameter is the StringSlice).
Thread/Thread<T> — the handle returned by starting a thread function (start Foo(args); calling one
directly, without start, is a compile-time error): Join(), Cancel(), CancelAndWait(), IsCompleted(),
IsCancelled(), and (Thread<T> only) the non-blocking t is T value pattern. Real OS threads (pthreads on
every supported platform), isolated from global state; parameters are values, strings and ReadOnlySlice<T> (copied for the thread) and
SharedPtr<T>/Mutex<T> of thread-safe values — see threading.md, including
Thread.Cancelled.
SharedPtr<T> — Create(value), Get(), Ptr() (unsafe), IsNull(): a box with an atomically
reference-counted handle, safe to share between threads (unlike strings/arrays/containers).
Mutex<T> — Create(value), Lock() (a MutexGuard<T> with Get()/Set(v), released by Dispose()/using),
Get(), Set(v), Update(change) (counter.Update(n => n + 1)): a value shared by threads under a lock; values go
in and out as copies (see threading.md).
DateTime — a date and time of day (0001-01-01 to 9999-12-31, ticks of 100 ns), local or UTC (IsUtc):
Now(), UtcNow(), Today(), Create(y, m, d [, h, min, s [, ms]]) (local), CreateUtc(...),
FromUnixSeconds/FromUnixMilliseconds and ToUnixSeconds/ToUnixMilliseconds; Year(), Month(), Day(), Hour(),
Minute(), Second(), Millisecond(), DayOfWeek(), DayOfYear(), Date(), TimeOfDay(); Add(TimeSpan),
AddDays/AddHours/AddMinutes/AddSeconds/AddMilliseconds(double), AddMonths/AddYears(int) (Jan 31 + 1 month =
Feb 28/29), Subtract(DateTime) (a TimeSpan) and Subtract(TimeSpan); ToLocalTime(), ToUniversalTime();
CompareTo, Equals (also for Sort() and Dictionary keys); IsLeapYear(year), DaysInMonth(year, month).
ToString() is 2026-10-01 14:05:09; ToString(format) knows yyyy yy MMMM MMM MM M dddd ddd dd d HH H hh h mm m ss s fff ff f tt (English names), 'text' and \x are copied; ToIsoString() gives ISO 8601 with the zone
(…Z or …+02:00). DateTime.Parse(text) (ParseError<DateTime>) reads yyyy-MM-dd[(T| )HH:mm[:ss[.f…]]][Z|±hh:mm].
On AmigaOS the clock has no time zone (UTC = local) and a resolution of 1/50 s.
TimeSpan — a signed duration in ticks: FromDays/FromHours/FromMinutes/FromSeconds/FromMilliseconds(double),
FromTicks, Create(h, m, s), Create(d, h, m, s [, ms]); the parts Days() … Milliseconds(), the totals
TotalDays() … TotalMilliseconds(); Add, Subtract, Negate, Duration (absolute), Multiply(factor);
ToString() is [-][d.]hh:mm:ss[.fffffff].
Stopwatch — elapsed time from the monotonic clock: StartNew(), Start(), Stop(), Reset(), Restart(),
IsRunning(), Elapsed() (TimeSpan), ElapsedMilliseconds(), ElapsedTicks(). Thread.Sleep(milliseconds)
pauses the calling thread.
FileStream — a file read or written piece by piece: OpenRead(path), OpenReadWrite(path), Create(path),
Append(path) (all IoError<FileStream>); Read(buffer, offset, count) (the number of bytes read, 0 at the end),
ReadByte() (-1 at the end), Write(bytes) (a ReadOnlySlice<uint8>: an array, a part of one, text.AsBytes()),
Write(array, offset, count), WriteByte(b), WriteText(slice) (UTF-8),
Position(), Seek(offset, SeekOrigin.Begin/Current/End), Length(), Flush(), Close() / Dispose().
StreamReader — Open(path), ReadLine() (Optional<string>, without \n or \r\n; null at the end),
ReadToEnd(), EndOfStream(); a UTF-8 BOM is skipped, invalid bytes become ?. StreamWriter — Create(path),
Append(path), Write(text), WriteLine([text]), Flush(). All three are IDisposable (using var r = try StreamReader.Open(path);); a stream is a value around the C library’s FILE, so keep one owner (copies share it).
using var reader = try StreamReader.Open("log.txt");while (reader.ReadLine() is string line){ if (line.StartsWith("ERROR")) Console.WriteLine(line);}Json, JsonValue — JSON text (RFC 8259): Json.Parse(text) (JsonError<JsonValue>; the message says the line
and column, JsonError.TooDeep above 512 nested arrays/objects); a JsonValue has a Kind (JsonKind.Null, Bool,
Number, String, Array, Object) and is made with JsonValue.Null(), Bool(b), Number(d), String(s),
NewArray(), NewObject(). Reading: IsNull() … IsObject(), AsBool(), AsNumber(), AsInt(), AsInt64(),
AsString() (a panic for another kind), Count(); arrays: v[i] / Get(i), Set(i, x), Add(x), Items();
objects: v["key"] / Get(key) (JSON null if missing, so doc["a"]["b"] needs no checks), Has(key), Set(key, x),
Remove(key), Keys() (in the order they were added). Writing: ToString() (compact), ToIndentedString([spaces]).
Numbers are doubles (written as integers when they are whole); copies of an array or object share its elements.
var doc = try Json.Parse(try File.ReadAllText("config.json"));int port = doc["server"]["port"].IsNumber() ? doc["server"]["port"].AsInt() : 8080;var o = JsonValue.NewObject();o.Set("port", JsonValue.Number(port));Console.WriteLine(o.ToIndentedString());Regex — regular expressions: Regex.Create(pattern) (RegexError<Regex>; the message says what is wrong and
where), IsMatch(text), Match(text [, start]) (Optional<RegexMatch>), Matches(text), Replace(text, replacement) ($0, $1…$9, ${n}, ${name}, $$), Split(text). A RegexMatch has Index, Length,
Value, Group(n) / Group(name) ("" if the group did not take part), GroupMatched(n), GroupIndex(n),
GroupCount(). Syntax: characters and escapes (\., \n, \xHH, \uHHHH), ., sets [a-z] [^...], \d \w \s
\D \W \S, ^ $ (lines with (?m)), \A \z, \b \B, groups (...), (?<name>...), (?:...), |, * + ? {n} {n,} {n,m} and their lazy forms (*?, …), (?i) (ASCII letters) at the start. No backreferences or lookaround.
UTF-8 aware (. and sets match a whole character; positions are bytes). A search takes at most (pattern size) x
(text length) steps: the matcher remembers the states it tried, so patterns like (a*)*b cannot take exponential time.
var date = try Regex.Create("(?<y>\\d{4})-(?<m>\\d{2})-(?<d>\\d{2})");Console.WriteLine(date.Replace("due 2026-10-01", "${d}.${m}.${y}")); // due 01.10.2026System.Compression — Deflate.Compress(data [, level]) (raw deflate, RFC 1951: the entries of zip files),
Zlib.Compress (RFC 1950: PNG) and Gzip.Compress (RFC 1952: .gz files) give uint8[]; levels 0 (stored) to 9
like zlib’s, 6 by default, each block written in the smallest of the stored, fixed and dynamic forms (the sizes are
within a few bytes of zlib’s). Decompress(data) of each gives CompressionError<uint8[]> (InvalidData,
Truncated, ChecksumMismatch; damaged data never ends the program). Crc32.Compute(data) /
Crc32.Update(crc, data) (start with 0) and Adler32.Compute / Update (start with 1) are the checksums.
using System.Compression;
var packed = Zlib.Compress(bytes, 9);var same = try Zlib.Decompress(packed);uint32 crc = Crc32.Compute(bytes);System.Image — an Image is Width x Height pixels in Pixels (uint32[], row by row from the top
left, 0xAARRGGBB, not premultiplied); copies share the pixels like a List, Clone() copies them.
Image.Create(w, h [, fill]) (transparent black without fill), Image.Load(path) / Image.Decode(bytes)
(ImageError<Image>: the format is found by the content), Save(path) (the format of the extension: .png, .bmp,
.ppm) / Save(path, format) / Encode(format), GetPixel(x, y) / SetPixel(x, y, color) (a Color),
GetArgb / SetArgb (uint32), Clear(color), Crop(x, y, w, h), Copy(source, x, y) and
Copy(source, sx, sy, w, h, x, y) (replaces the pixels, clipped, may overlap within one image),
Image.DetectFormat(bytes), Image.FormatOfPath(path). A Color has A, R, G, B;
Color.FromArgb(a, r, g, b), Color.FromRgb(r, g, b), Color.FromArgb(uint32), ToArgb(), Color.Black(),
White(), Transparent() (0x00FFFFFF, like .NET). The formats (ImageFormat):
- PNG — reads every color type and bit depth, interlaced or not, with transparency (
tRNS); ancillary chunks are skipped (no gamma correction). Writes a palette (1 to 8 bits per pixel) for up to 256 colors, else RGB or RGBA with 8 bits per channel and a filter chosen per row. - BMP — reads the OS/2 and Windows headers (12 to 124 bytes), 1/4/8/16/24/32 bits per pixel, top-down and
bottom-up, RLE4/RLE8 and bit fields (with alpha only from an alpha mask: plain 32-bit pixels are opaque). Writes 24
bits per pixel, or 32 with an alpha mask (
BITMAPV4HEADER) if a pixel is not opaque. - PPM — reads PBM, PGM and PPM (
P1toP6, text and binary, up to 16 bits per sample); writesP6without alpha.
Decoding gives the same pixels as System.Drawing (GDI+) of .NET, including its rounding: 5- and 6-bit channels
repeat their bits, 16-bit gray follows the steps of GDI+, a transparent gray (tRNS) is transparent black.
using System.Image;
var sprite = try Image.Load("sprite.png");for (var y = 0; y < sprite.Height; y += 1){ for (var x = 0; x < sprite.Width; x += 1) { var c = sprite.GetPixel(x, y); sprite.SetPixel(x, y, Color.FromArgb(c.A, 255 - c.R, 255 - c.G, 255 - c.B)); }}try sprite.Save("inverted.png");Random — Random.Create(seed) (the same sequence for the same seed, on every system) or Random.Create()
(seeded from the clock): Next(), Next(max), Next(min, max), NextDouble() ([0, 1)), NextBool(),
NextBits(). xorshift64*, not for cryptography. A Random is a value: keep it in a variable and call its methods
on that.
Built into the compiler (no library code): Console.Write/WriteLine/WriteError/WriteErrorLine,
Memory.Allocate/Free (unsafe), Memory.CopyForThread(v) (a copy that shares no reference count: strings get new
blocks), Environment.Exit/Panic, Array.Copy, string.FromBytes, string.FromCStr (unsafe), ToString(),
CompareTo(), Equals(), GetHashCode() on numbers, int.MaxValue/MinValue. Files are embedded
at compile time with the keywords embed/embed_filenames/embed_lines.
Writing library code: stdlib/ is compiled by the compiler of the same commit, so it may use every language
feature; only the compiler’s own sources are limited to the stage 0 release. See compiler.md.