2026-05-09 21:09:15 +10:00
<!DOCTYPE HTML>
< html lang = "en" class = "light sidebar-visible" dir = "ltr" >
< head >
<!-- Book generated using mdBook -->
< meta charset = "UTF-8" >
< title > Solstice Docs< / title >
< meta name = "robots" content = "noindex" >
<!-- Custom HTML head -->
< meta name = "description" content = "" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta name = "theme-color" content = "#ffffff" >
< link rel = "icon" href = "favicon-97ae436f.svg" >
< link rel = "shortcut icon" href = "favicon-9392e324.png" >
< link rel = "stylesheet" href = "css/variables-16ac1224.css" >
< link rel = "stylesheet" href = "css/general-e4fbb323.css" >
< link rel = "stylesheet" href = "css/chrome-ae938929.css" >
< link rel = "stylesheet" href = "css/print-9e4910d8.css" media = "print" >
<!-- Fonts -->
< link rel = "stylesheet" href = "fonts/fonts-6d524047.css" >
<!-- Highlight.js Stylesheets -->
< link rel = "stylesheet" id = "mdbook-highlight-css" href = "highlight-493f70e1.css" >
< link rel = "stylesheet" id = "mdbook-tomorrow-night-css" href = "tomorrow-night-4c0ae647.css" >
< link rel = "stylesheet" id = "mdbook-ayu-highlight-css" href = "ayu-highlight-3fdfc3ac.css" >
<!-- Custom theme stylesheets -->
<!-- Provide site root and default themes to javascript -->
< script >
const path_to_root = "";
const default_light_theme = "light";
const default_dark_theme = "navy";
2026-05-10 16:35:17 +10:00
window.path_to_searchindex_js = "searchindex-c4fb8585.js";
2026-05-09 21:09:15 +10:00
< / script >
<!-- Start loading toc.js asap -->
2026-05-10 16:35:17 +10:00
< script src = "toc-1ef53d19.js" > < / script >
2026-05-09 21:09:15 +10:00
< / head >
< body >
< div id = "mdbook-help-container" >
< div id = "mdbook-help-popup" >
< h2 class = "mdbook-help-title" > Keyboard shortcuts< / h2 >
< div >
< p > Press < kbd > ←< / kbd > or < kbd > →< / kbd > to navigate between chapters< / p >
< p > Press < kbd > S< / kbd > or < kbd > /< / kbd > to search in the book< / p >
< p > Press < kbd > ?< / kbd > to show this help< / p >
< p > Press < kbd > Esc< / kbd > to hide this help< / p >
< / div >
< / div >
< / div >
< div id = "mdbook-body-container" >
<!-- Work around some values being stored in localStorage wrapped in quotes -->
< script >
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') & & theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') & & sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
< / script >
<!-- Set the theme before any content is loaded, prevents flash -->
< script >
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
< / script >
< input type = "checkbox" id = "mdbook-sidebar-toggle-anchor" class = "hidden" >
<!-- Hide / unhide sidebar before it is displayed -->
< script >
let sidebar = null;
const sidebar_toggle = document.getElementById("mdbook-sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
sidebar_toggle.checked = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
< / script >
< nav id = "mdbook-sidebar" class = "sidebar" aria-label = "Table of contents" >
<!-- populated by js -->
< mdbook-sidebar-scrollbox class = "sidebar-scrollbox" > < / mdbook-sidebar-scrollbox >
< noscript >
< iframe class = "sidebar-iframe-outer" src = "toc.html" > < / iframe >
< / noscript >
< div id = "mdbook-sidebar-resize-handle" class = "sidebar-resize-handle" >
< div class = "sidebar-resize-indicator" > < / div >
< / div >
< / nav >
< div id = "mdbook-page-wrapper" class = "page-wrapper" >
< div class = "page" >
< div id = "mdbook-menu-bar-hover-placeholder" > < / div >
< div id = "mdbook-menu-bar" class = "menu-bar sticky" >
< div class = "left-buttons" >
< label id = "mdbook-sidebar-toggle" class = "icon-button" for = "mdbook-sidebar-toggle-anchor" title = "Toggle Table of Contents" aria-label = "Toggle Table of Contents" aria-controls = "mdbook-sidebar" >
< span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 448 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z" / > < / svg > < / span >
< / label >
< button id = "mdbook-theme-toggle" class = "icon-button" type = "button" title = "Change theme" aria-label = "Change theme" aria-haspopup = "true" aria-expanded = "false" aria-controls = "mdbook-theme-list" >
< span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 576 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z" / > < / svg > < / span >
< / button >
< ul id = "mdbook-theme-list" class = "theme-popup" aria-label = "Themes" role = "menu" >
< li role = "none" > < button role = "menuitem" class = "theme" id = "mdbook-theme-default_theme" > Auto< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "mdbook-theme-light" > Light< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "mdbook-theme-rust" > Rust< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "mdbook-theme-coal" > Coal< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "mdbook-theme-navy" > Navy< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "mdbook-theme-ayu" > Ayu< / button > < / li >
< / ul >
< button id = "mdbook-search-toggle" class = "icon-button" type = "button" title = "Search (`/`)" aria-label = "Toggle Searchbar" aria-expanded = "false" aria-keyshortcuts = "/ s" aria-controls = "mdbook-searchbar" >
< span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 512 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z" / > < / svg > < / span >
< / button >
< / div >
< h1 class = "menu-title" > Solstice Docs< / h1 >
< div class = "right-buttons" >
< a href = "print.html" title = "Print this book" aria-label = "Print this book" >
< span class = fa-svg id = "print-button" > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 512 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zm-16-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z" / > < / svg > < / span >
< / a >
< / div >
< / div >
< div id = "mdbook-search-wrapper" class = "hidden" >
< form id = "mdbook-searchbar-outer" class = "searchbar-outer" >
< div class = "search-wrapper" >
< input type = "search" id = "mdbook-searchbar" name = "searchbar" placeholder = "Search this book ..." aria-controls = "mdbook-searchresults-outer" aria-describedby = "searchresults-header" >
< div class = "spinner-wrapper" >
< span class = fa-svg id = "fa-spin" > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 512 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z" / > < / svg > < / span >
< / div >
< / div >
< / form >
< div id = "mdbook-searchresults-outer" class = "searchresults-outer hidden" >
< div id = "mdbook-searchresults-header" class = "searchresults-header" > < / div >
< ul id = "mdbook-searchresults" >
< / ul >
< / div >
< / div >
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
< script >
document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
< / script >
< div id = "mdbook-content" class = "content" >
< main >
< h1 id = "introduction" > < a class = "header" href = "#introduction" > Introduction< / a > < / h1 >
2026-05-10 16:35:17 +10:00
< p > Welcome to the Solstice documentation! Here we have a tutorial (starting < a href = "#installation" > here< / a > ) and a specification for the Solstice programming language.< / p >
< p > If you’ re new to Solstice, I’ d recommend starting the tutorial, at the < a href = "#installation" > installation< / a > page. If you’ ve already installed Solstice, start at the < a href = "#basics" > Basics< / a > page.< / p >
2026-05-09 21:09:15 +10:00
< p > Docs generated by mdBook.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
2026-05-10 16:35:17 +10:00
< h1 id = "installation" > < a class = "header" href = "#installation" > Installation< / a > < / h1 >
< p > Solstice is fully supported and tested on Linux, however should work on most UNIX-like environments. Windows support is theoretically possible, however not all features are avaliable, so use WSL, MSys, or Cygwin instead.< / p >
< h2 id = "which-method-is-for-you" > < a class = "header" href = "#which-method-is-for-you" > Which method is for you?< / a > < / h2 >
< p > Use a < a href = "#prebuilt-binaries" > prebuilt binary< / a > if you’ re in a rush, or you can’ t get a compiler on your system.< / p >
< p > Use the < a href = "#automated-build-script" > automated build script< / a > for a full install of Solstice and Ground, with maximum flexibility.< / p >
< p > Do a < a href = "#building-manually" > manual build< / a > if you intend to contribute to the Solstice source code.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "prebuilt-binaries" > < a class = "header" href = "#prebuilt-binaries" > Prebuilt Binaries< / a > < / h1 >
< p > Solstice binaries statically linked with Ground are avaliable from the < a href = "https://chookspace.com/solstice/solstice/releases" > Solstice releases page< / a > . For now, these are only for Linux x86_64, but more options may be avaliable in future.< / p >
< p > Download the latest release, copy it into a folder in your path (such as < code > /usr/local/bin< / code > ) and enjoy!< / p >
< h2 id = "producing-release-binaries" > < a class = "header" href = "#producing-release-binaries" > Producing release binaries< / a > < / h2 >
< p > There is a script < a href = "https://chookspace.com/solstice/builder" > on Chookspace< / a > which builds Solstice and Ground in a container. Use this script for building production releases, and determining whether bugs are setup-specific or affect all people.< / p >
< p > Use this script to produce prebuilt binaries for the releases page.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "build-dependencies" > < a class = "header" href = "#build-dependencies" > Build dependencies< / a > < / h1 >
< h2 id = "macos" > < a class = "header" href = "#macos" > macOS< / a > < / h2 >
< pre > < code class = "language-sh" > xcode-select --install
< / code > < / pre >
< p > Then, download UTHash < a href = "https://github.com/troydhanson/uthash/archive/master.zip" > here< / a > , and copy the contents of the < code > include< / code > folder to < code > /usr/local/include< / code > :< / p >
< pre > < code class = "language-sh" > sudo cp (/path/to/uthash-master)/include/* /usr/local/include
< / code > < / pre >
< h2 id = "ubuntudebian" > < a class = "header" href = "#ubuntudebian" > Ubuntu/Debian< / a > < / h2 >
< pre > < code class = "language-sh" > sudo apt install gcc git make uthash-dev
< / code > < / pre >
< h2 id = "arch-linux" > < a class = "header" href = "#arch-linux" > Arch Linux< / a > < / h2 >
< pre > < code class = "language-sh" > sudo pacman -S --needed gcc git make uthash
< / code > < / pre >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "automated-build-script" > < a class = "header" href = "#automated-build-script" > Automated Build Script< / a > < / h1 >
< p > This method requires the following installed:< / p >
< ul >
< li > uthash (in < code > /usr/include< / code > or similar)< / li >
< li > A gcc-compatible C compiler linked to < code > cc< / code >
< ul >
< li > GCC and Clang are both tested and will yield similar results.< / li >
< / ul >
< / li >
< li > Git (to get source code)< / li >
< li > Make (to organise building the code)< / li >
< / ul >
< p > Refer to < a href = "#build-dependencies" > Build Dependencies< / a > for instructions on how to install dependencies.< / p >
< h2 id = "running-the-installer" > < a class = "header" href = "#running-the-installer" > Running the installer< / a > < / h2 >
< p > Run this command in your terminal:< / p >
< pre > < code class = "language-sh" > bash -c "$(curl -fsSL https://sols.dev/install.sh)"
< / code > < / pre >
< p > This will:< / p >
< ul >
< li > Download a shell script from < code > https://sols.dev/install.sh< / code > < / li >
< li > Run the contents of the shell script in the < code > bash< / code > command interpreter< / li >
< / ul >
< p > The script does the following:< / p >
< ul >
< li > Checks if Ground and Solstice are installed on your system.< / li >
< li > If either Ground or Solstice aren’ t avaliable, it will download, build, and install the source code.< / li >
< li > If Ground or Solstice are installed, it will update them to the latest version.< / li >
< / ul >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "building-manually" > < a class = "header" href = "#building-manually" > Building Manually< / a > < / h1 >
< p > Refer to < a href = "#build-dependencies" > Build Dependencies< / a > for instructions on how to install dependencies.< / p >
< p > Build and install Ground:< / p >
< pre > < code class = "language-sh" > git clone https://chookspace.com/ground/ground
cd ground
make
sudo make install
cd ..
< / code > < / pre >
< p > After this, build and install Solstice:< / p >
< pre > < code class = "language-sh" > git clone https://chookspace.com/solstice/solstice
cd solstice
make
sudo make install
cd ..
< / code > < / pre >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "command-usage" > < a class = "header" href = "#command-usage" > Command Usage< / a > < / h1 >
< pre > < code > Solstice programming language
Usage: solstice < file> [-h] [--help] [-p] [--print] [-b < file> ] [--bytecode < file> ] [-c < file> ] [--compile < file> ]
Args:
< file> : Solstice source file
-h or --help: Prints this help message and exits
-p or --print: Prints textual version of Ground bytecode to console
-b < file> or --bytecode < file> : Generates Ground bytecode (.grbc) and saves it to the provided filename
-c < file> or --compile < file> : Compiles Ground to Linux x86_64 assembly, outputs a binary to the provided filename (experimental)
If no extra arguments are provided, the generated Ground bytecode will be executed.
< / code > < / pre >
< h2 id = "arguments" > < a class = "header" href = "#arguments" > Arguments:< / a > < / h2 >
< h3 id = "file" > < a class = "header" href = "#file" > < code > < file> < / code > < / a > < / h3 >
< p > The Solstice source file to run.< / p >
< p > There should never be more than one file, as Solstice allows files to import each other, rather than compiling multiple files into one manually.< / p >
< h3 id = "-h-or---help" > < a class = "header" href = "#-h-or---help" > < code > -h< / code > or < code > --help< / code > < / a > < / h3 >
< p > Shows the help message above.< / p >
< h3 id = "-p-or---print" > < a class = "header" href = "#-p-or---print" > < code > -p< / code > or < code > --print< / code > < / a > < / h3 >
< p > Prints the textual version of the generated Ground bytecode to the console.< / p >
< p > This is useful for debugging the compiler, and ensuring the correct output is produced for the GroundVM.< / p >
< h3 id = "-b-file-or---bytecode-file" > < a class = "header" href = "#-b-file-or---bytecode-file" > < code > -b < file> < / code > or < code > --bytecode < file> < / code > < / a > < / h3 >
< p > Outputs Ground bytecode (in < code > grbc< / code > format) and saves it in the file < code > < file> < / code > .< / p >
< p > Ground bytecode is useful for distributing software in a format where the target machine does not need Solstice installed, only the Ground VM.< / p >
< p > Run the compiled bytecode with:< / p >
< pre > < code class = "language-sh" > ground -b < file>
< / code > < / pre >
< h3 id = "-c-file-or---compile-file" > < a class = "header" href = "#-c-file-or---compile-file" > < code > -c < file> < / code > or < code > --compile < file> < / code > < / a > < / h3 >
< p > Compiles the Ground bytecode to assembly using the < a href = "https://chookspace.com/tram/tram" > Tram< / a > backend, outputting a binary named < code > < file> < / code > .< / p >
< p > Requires Ground to be built with Tram support, and Tram to be installed on your system.< / p >
< p > This backend is experimental and does not support all features.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "basics" > < a class = "header" href = "#basics" > Basics< / a > < / h1 >
< p > This part of the tutorial shows you the basics of using Solstice. Click next to see the “Hello, World!” program!< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "hello-world" > < a class = "header" href = "#hello-world" > Hello, World!< / a > < / h1 >
< p > Create a new file on your computer (preferably in a new folder) named < code > main.sols< / code > . In the file, write the following:< / p >
< pre > < code class = "language-solstice" > puts "Hello, World!"
< / code > < / pre >
< p > Save the file, then run in your terminal:< / p >
< pre > < code class = "language-sh" > solstice main.sols
< / code > < / pre >
< p > Solstice will run the file for you, which should print < code > Hello, World!< / code > to the console.< / p >
< p > Here’ s what it does:< / p >
< ul >
< li > < code > puts< / code > : Stands for “put something”. It’ s Solstice’ s built in “please print out this thing’ s current state” operator.< / li >
< li > < code > "Hello, World!"< / code > : A string. A string is a collection of characters. In Solstice, you denote a string by surrounding your text with double quotes (< code > "< / code > ).< / li >
< / ul >
< p > Next up: using variables!< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "variables" > < a class = "header" href = "#variables" > Variables< / a > < / h1 >
< h2 id = "creating-variables" > < a class = "header" href = "#creating-variables" > Creating Variables< / a > < / h2 >
< p > In Solstice, you can initialize a variable using the syntax:< / p >
< pre > < code class = "language-solstice" > name = value
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > name< / code > is the name of your variable. You can use all letters in variable names, as well as underscores and numbers.
< ul >
< li > The standard way to name your variables in Solstice is with < code > camelCase< / code > .< / li >
< / ul >
< / li >
< li > < code > value< / code > is some sort of value. This value can be:
< ul >
< li > an integer (number with no decimal place)< / li >
< li > a double (number with a decimal place)< / li >
< li > a string (collection of characters, as seen before)< / li >
< li > a character (a single letter)< / li >
< li > a boolean (either < code > true< / code > or < code > false< / code > )< / li >
< / ul >
< / li >
< / ul >
< p > We’ ll look at types of values in the next part.< / p >
< h2 id = "recalling-variables" > < a class = "header" href = "#recalling-variables" > Recalling Variables< / a > < / h2 >
< p > Recall a variable’ s content by using it’ s name:< / p >
< pre > < code class = "language-solstice" > puts name
< / code > < / pre >
< p > where < code > name< / code > is the name of your variable.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "comments" > < a class = "header" href = "#comments" > Comments< / a > < / h1 >
< p > In Solstice, there are 3 ways to do comments:< / p >
< h2 id = "-single-line-comment" > < a class = "header" href = "#-single-line-comment" > < code > //< / code > (Single-Line Comment)< / a > < / h2 >
< p > Writing < code > //< / code > tells Solstice to ignore the rest of the line.< / p >
< p > Some examples:< / p >
< pre > < code class = "language-solstice" > puts 2 + 2 // should be 4
// This variable holds the status code from checkStatus()
statusCode = checkStatus("file.txt")
< / code > < / pre >
< p > This comment should be used when writing your code’ s logic in Solstice.< / p >
< h2 id = "--multiline-comment" > < a class = "header" href = "#--multiline-comment" > < code > /* */< / code > (Multiline Comment)< / a > < / h2 >
< p > Any text in between < code > /*< / code > and < code > */< / code > will be ignored. These comments should be used to document functions and structs (we’ ll get to those later.)< / p >
< p > Example:< / p >
< pre > < code class = "language-solstice" > /*
Adds two numbers together.
*/
def add(int a, int b) int {
return a + b
}
< / code > < / pre >
< h2 id = "-shebang-comment" > < a class = "header" href = "#-shebang-comment" > < code > #< / code > (Shebang Comment)< / a > < / h2 >
< p > Use this comment only for using Solstice as a script interpreter in a shebang. Effectively the same as < code > //< / code > , but we recommend using < code > //< / code > over < code > #< / code > .< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "values-and-types" > < a class = "header" href = "#values-and-types" > Values and Types< / a > < / h1 >
< p > In Solstice, everything is a value, and every value has a type. Values can be moved around and passed to different functions, however to pass them around their type must be confirmed.< / p >
< h2 id = "int" > < a class = "header" href = "#int" > < code > int< / code > < / a > < / h2 >
< p > An < code > int< / code > is a signed (meaning either positive or negative) 8-byte integer (meaning no decimal place).< / p >
< p > Using this size, Solstice can accurately process numbers between < code > -9,223,372,036,854,775,807< / code > and < code > 9,223,372,036,854,775,807< / code > .< / p >
< p > Integers are represented as a collection of digits not seperated by anything, such as:< / p >
< pre > < code class = "language-solstice" > 123
7483
423843269
< / code > < / pre >
< h2 id = "double" > < a class = "header" href = "#double" > < code > double< / code > < / a > < / h2 >
< p > A < code > double< / code > is a signed 8-byte floating-point (meaning with a decimal place) number.< / p >
< p > Using this size, Solstice can accurately process numbers between 15 and 17 digits long.< / p >
< p > Doubles are represented as a collection of digits, with a dot (< code > .< / code > ) seperating the ones and tenths positions, such as:< / p >
< pre > < code class = "language-solstice" > 3.14
432.543
5907432.432
< / code > < / pre >
< h2 id = "string" > < a class = "header" href = "#string" > < code > string< / code > < / a > < / h2 >
< p > A < code > string< / code > is a collection of characters which end with a null byte (handled by Solstice).< / p >
< p > Solstice can accurately process strings of any size, provided your computer has enough memory.< / p >
< p > Strings are represented as a collection of characters surrounded by double quotes (< code > ""< / code > ), such as:< / p >
< pre > < code class = "language-solstice" > "Hello, World!"
"Solstice is cool"
"Rust kinda mid"
< / code > < / pre >
< h2 id = "char" > < a class = "header" href = "#char" > < code > char< / code > < / a > < / h2 >
< p > A < code > char< / code > is a signed 1-byte integer, represented as an ASCII character, however can also be used to represent a single byte in a stream.< / p >
< p > Solstice can accurately process any ASCII character.< / p >
< p > Characters are represented as a single character surrounded by single quotes (< code > ''< / code > ), such as:< / p >
< pre > < code class = "language-solstice" > 'a'
'b'
'c'
< / code > < / pre >
< h2 id = "bool" > < a class = "header" href = "#bool" > < code > bool< / code > < / a > < / h2 >
< p > A < code > bool< / code > is a variable which can either be < code > true< / code > or < code > false< / code > .< / p >
< pre > < code class = "language-solstice" > true
false
< / code > < / pre >
< h2 id = "other-types" > < a class = "header" href = "#other-types" > Other Types< / a > < / h2 >
< p > Solstice has three other types: < code > fun< / code > , < code > template< / code > , and < code > object< / code > , but we’ ll cover these in the < a href = "#functions" > Functions< / a > and < a href = "#structures" > Structures< / a > pages.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "functions" > < a class = "header" href = "#functions" > Functions< / a > < / h1 >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "structures" > < a class = "header" href = "#structures" > Structures< / a > < / h1 >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "naming-conventions" > < a class = "header" href = "#naming-conventions" > Naming Conventions< / a > < / h1 >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "comment-conventions" > < a class = "header" href = "#comment-conventions" > Comment Conventions< / a > < / h1 >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "code-layout" > < a class = "header" href = "#code-layout" > Code Layout< / a > < / h1 >
< div style = "break-before: page; page-break-before: always;" > < / div >
2026-05-09 21:09:15 +10:00
< h1 id = "reserved-words" > < a class = "header" href = "#reserved-words" > Reserved Words< / a > < / h1 >
< p > This is a list of all reserved words in Solstice, seperated by new lines. These words may not be used as identifiers.< / p >
< p > After < code > //< / code > , notes may be provided which detail exceptions to the reserved word, however, the word should still be treated as reserved regardless.< / p >
< pre > < code class = "language-solstice" > puts
if
while
def
lambda
return
use
struct
enum
constructor
destructor
duplicator
private
protected
ground // Only when targeting GroundVM
new
as
sizeof
pragma
< / code > < / pre >
< div style = "break-before: page; page-break-before: always;" > < / div >
2026-05-10 16:35:17 +10:00
< h1 id = "comments-1" > < a class = "header" href = "#comments-1" > Comments< / a > < / h1 >
2026-05-09 21:09:15 +10:00
< p > Comments in Solstice can be done in 3 ways:< / p >
2026-05-10 16:35:17 +10:00
< h2 id = "-single-line-comment-1" > < a class = "header" href = "#-single-line-comment-1" > < code > //< / code > (Single-Line Comment)< / a > < / h2 >
2026-05-09 21:09:15 +10:00
< p > Use < code > //< / code > to tell Solstice to ignore text until the end of the line.< / p >
< p > This kind of comment should be used inside code to explain how parts of code work.< / p >
2026-05-10 16:35:17 +10:00
< h2 id = "--multiline-comment-1" > < a class = "header" href = "#--multiline-comment-1" > < code > /* */< / code > (Multiline Comment)< / a > < / h2 >
2026-05-09 21:09:15 +10:00
< p > Use < code > /*< / code > and < code > */< / code > to tell Solstice to ignore text in between the two markers.< / p >
< p > This kind of comment should be used for explainations of how functions and structs work, placed above the definition.< / p >
2026-05-10 16:35:17 +10:00
< h2 id = "-shebang-comment-1" > < a class = "header" href = "#-shebang-comment-1" > < code > #< / code > (Shebang Comment)< / a > < / h2 >
2026-05-09 21:09:15 +10:00
< p > Use < code > #< / code > to tell Solstice to ignore text until the end of the line.< / p >
< p > This kind of comment should be used in a shebang (writing < code > #!/usr/bin/env solstice< / code > at the top of your entry point source file), not in the middle.< / p >
< h2 id = "example" > < a class = "header" href = "#example" > Example< / a > < / h2 >
< pre > < code class = "language-solstice" > #!/usr/bin/env solstice
/*
This function does something.
Input:
funnyNumber: A funny number
Returns: Another funny number
*/
def doSomething(int funnyNumber) int {
// Tell the user the number is funny
puts "The number" funnyNumber "is very funny"
// Now give them another funny number
return 532
}
< / code > < / pre >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "expressions" > < a class = "header" href = "#expressions" > Expressions< / a > < / h1 >
< p > An expression in Solstice is a combination of operators and values (whether literal or stored in a variable).;< / p >
< h2 id = "expression-types" > < a class = "header" href = "#expression-types" > Expression Types< / a > < / h2 >
< p > “Precedence” is a number which dictates the order of execution. The higher the precedence, the sooner an expression will be evaluated.< / p >
< h3 id = "binary-mathematical" > < a class = "header" href = "#binary-mathematical" > Binary Mathematical< / a > < / h3 >
< ul >
< li > < code > +< / code > : Adds two numbers on either side, or concatenates two strings
< ul >
< li > Accepts:
< ul >
< li > Two integers either side< / li >
< li > Two doubles either side< / li >
< li > Two strings either side< / li >
< li > An integer and a double on either side (order not significant)< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The sum of both values as an integer if both values are integers< / li >
< li > The sum of both values as a double if one value is a double and the other is an int, or both values are doubles< / li >
< li > The concatenated string when both values are strings< / li >
< / ul >
< / li >
< li > Precedence: 5< / li >
< / ul >
< / li >
< li > < code > -< / code > : Subtracts two numbers on either side
< ul >
< li > Accepts:
< ul >
< li > Two integers either side< / li >
< li > Two doubles either side< / li >
< li > An integer and a double on either side (order not significant)< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The difference of both values as an integer if both values are integers< / li >
< li > The difference of both values as a double if one value is a double and the other is an int, or both values are doubles< / li >
< / ul >
< / li >
< li > Precedence: 5< / li >
< / ul >
< / li >
< li > < code > *< / code > : Multiplies two numbers on either side
< ul >
< li > Accepts:
< ul >
< li > Two integers either side< / li >
< li > Two doubles either side< / li >
< li > An integer and a double on either side (order not significant)< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The product of both values as an integer if both values are integers< / li >
< li > The product of both values as a double if one value is a double and the other is an int, or both values are doubles< / li >
< / ul >
< / li >
< li > Precedence: 6< / li >
< / ul >
< / li >
< li > < code > /< / code > : Divides two numbers on either side
< ul >
< li > Accepts:
< ul >
< li > Two integers either side
< ul >
< li > Two doubles either side
< ul >
< li > An integer and a double on either side (order not significant)< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The quotient of both values as an integer if both values are integers< / li >
< li > The quotient of both values as a double if one value is a double and the other is an int, or both values are doubles< / li >
< / ul >
< / li >
< li > Precedence: 6< / li >
< / ul >
< / li >
< / ul >
< h3 id = "binary-comparative" > < a class = "header" href = "#binary-comparative" > Binary Comparative< / a > < / h3 >
< ul >
< li > < code > ==< / code > : Checks two values to determine if they are equal
< ul >
< li > Accepts:
< ul >
< li > Any two values either side which are of the same type< / li >
< li > An integer and a double on either side (order not significant)< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > < code > true< / code > if both provided values are exactly the same. < / li >
< li > < code > false< / code > otherwise.< / li >
< / ul >
< / li >
< li > Precedence: 2< / li >
< / ul >
< / li >
< li > < code > !=< / code > : Checks two values to determine if they are not equal
< ul >
< li > Accepts:
< ul >
< li > Any two values either side which are of the same type< / li >
< li > An integer and a double on either side (order not significant)< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > < code > true< / code > if both provided values are not exactly the same. < / li >
< li > < code > false< / code > otherwise.< / li >
< / ul >
< / li >
< li > Precedence: 2< / li >
< / ul >
< / li >
< li > < code > > < / code > : Checks two numbers to determine which is greater
< ul >
< li > Accepts:
< ul >
< li > Any two numbers (int or double) either side< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > < code > true< / code > if the number provided on the left is greater than the number provided on the right.< / li >
< li > < code > false< / code > otherwise.< / li >
< / ul >
< / li >
< li > Precedence: 2< / li >
< / ul >
< / li >
< li > < code > < < / code > : Checks two numbers to determine which is lesser
< ul >
< li > Accepts:
< ul >
< li > Any two numbers (int or double) either side< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > < code > true< / code > if the number provided on the left is lesser than the number provided on the right.< / li >
< li > < code > false< / code > otherwise.< / li >
< / ul >
< / li >
< li > Precedence: 2< / li >
< / ul >
< / li >
< li > < code > > =< / code > : Checks two numbers to determine which is greater, or whether both are equal
< ul >
< li > Accepts:
< ul >
< li > Any two numbers (int or double) either side< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > < code > true< / code > if the number provided on the left is greater than the number provided on the right, or if both numbers are equal.< / li >
< li > < code > false< / code > otherwise.< / li >
< / ul >
< / li >
< li > Precedence: 2< / li >
< / ul >
< / li >
< li > < code > < =< / code > : Checks two numbers to determine which is lesser, or whether both are equal
< ul >
< li > Accepts:
< ul >
< li > Any two numbers (int or double) either side< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > < code > true< / code > if the number provided on the left is lesser than the number provided on the right, or if both numbers are equal.< / li >
< li > < code > false< / code > otherwise.< / li >
< / ul >
< / li >
< li > Precedence: 2< / li >
< / ul >
< / li >
< / ul >
< h3 id = "binary-misc" > < a class = "header" href = "#binary-misc" > Binary Misc< / a > < / h3 >
< ul >
< li > < code > as< / code > : Converts between types.
< ul >
< li > Accepts:
< ul >
< li > Any object on the left, and a type which has an applicable conversion defined by the object on the right< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The object turned into the type on the right, in the way defined by the as-method< / li >
< / ul >
< / li >
< / ul >
< / li >
< li > < code > .< / code > : Accesses object fields
< ul >
< li > Accepts:
< ul >
< li > An object on the left, and an identifier on the right which corresponds to a field or method in the object< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The object field or method the identifier corresponds to< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< h3 id = "brackets" > < a class = "header" href = "#brackets" > Brackets< / a > < / h3 >
< ul >
< li > < code > (...)< / code > : Evaluates an expression inside the brackets before outside expressions.
< ul >
< li > Accepts:
< ul >
< li > Any expression inside the brackets (in place of < code > ...< / code > )< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The result of the expression in the brackets< / li >
< / ul >
< / li >
< li > Precedence: 7< / li >
< / ul >
< / li >
< / ul >
< h3 id = "function-call" > < a class = "header" href = "#function-call" > Function Call< / a > < / h3 >
< ul >
< li > < code > (...)< / code > : Calls the specified function.
< ul >
< li > Accepts:
< ul >
< li > An identifier for the function before the brackets, then comma-seperated expressions corresponding to the function type signature (see < a href = "#fun" > Types -> Combined Types -> fun< / a > ) inside the brackets (in place of < code > ...< / code > )< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The function’ s return type as specified by the function type signature (see < a href = "#fun" > Types -> Combined Types -> fun< / a > )< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< h3 id = "unary-misc" > < a class = "header" href = "#unary-misc" > Unary Misc< / a > < / h3 >
< ul >
< li > < code > new< / code > : Creates a new object from a template.
< ul >
< li > Accepts:
< ul >
< li > A template after the < code > new< / code > keyword.< / li >
< li > A core type identifier< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > An object based on the provided template, if provided with a template.< / li >
< li > The empty version of the core type, if provided with a core type, which is:
< ul >
< li > < code > int< / code > : < code > 0< / code > < / li >
< li > < code > double< / code > : < code > 0.0< / code > < / li >
< li > < code > string< / code > : < code > ""< / code > < / li >
< li > < code > char< / code > : < code > '\0'< / code > < / li >
< li > < code > bool< / code > : < code > false< / code > < / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< / li >
< li > < code > sizeof< / code > : Gets the size of something.
< ul >
< li > Accepts:
< ul >
< li > A string< / li >
< li > An object with an < code > int size< / code > field< / li >
< / ul >
< / li >
< li > Returns:
< ul >
< li > The string length if provided a string< / li >
< li > The < code > int size< / code > field of the object if provided an object< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "types" > < a class = "header" href = "#types" > Types< / a > < / h1 >
< p > Solstice is statically typed, meaning all values must have a known type before any code can be executed.< / p >
< h2 id = "core-types" > < a class = "header" href = "#core-types" > Core Types< / a > < / h2 >
< p > These core types are automatically avaliable in Solstice. The words to identify them are reserved and cannot be reassigned.< / p >
2026-05-10 16:35:17 +10:00
< h3 id = "int-1" > < a class = "header" href = "#int-1" > < code > int< / code > < / a > < / h3 >
2026-05-09 21:09:15 +10:00
< p > 8-byte signed integer, equivalent to C < code > int64_t< / code > or Ground < code > -int< / code > .< / p >
< p > Examples: < code > 32< / code > , < code > 121< / code > , < code > -5< / code > < / p >
2026-05-10 16:35:17 +10:00
< h3 id = "double-1" > < a class = "header" href = "#double-1" > < code > double< / code > < / a > < / h3 >
2026-05-09 21:09:15 +10:00
< p > 8-byte double prescision floating point number, equivalent to C < code > double< / code > or Ground < code > -double< / code > .< / p >
< p > Examples: < code > 3.14< / code > , < code > -2.7< / code > < / p >
2026-05-10 16:35:17 +10:00
< h3 id = "string-1" > < a class = "header" href = "#string-1" > < code > string< / code > < / a > < / h3 >
2026-05-09 21:09:15 +10:00
< p > C-style null-terminated array of characters. Equivalent to C < code > char*< / code > or Ground < code > -string< / code > .< / p >
2026-05-10 16:35:17 +10:00
< h3 id = "char-1" > < a class = "header" href = "#char-1" > < code > char< / code > < / a > < / h3 >
2026-05-09 21:09:15 +10:00
< p > 1-byte signed integer, usually used to store a character, however can also be used to store bytes. Equivalent to C < code > char< / code > or Ground < code > -char< / code > .< / p >
2026-05-10 16:35:17 +10:00
< h3 id = "bool-1" > < a class = "header" href = "#bool-1" > < code > bool< / code > < / a > < / h3 >
2026-05-09 21:09:15 +10:00
< p > 1-byte unsigned integer, either 1 or 0. Represented by the reserved words < code > true< / code > and < code > false< / code > . Equivalent to C < code > char< / code > (no stdbool.h) or < code > bool< / code > (with stdbool.h) or Ground < code > -bool< / code > .< / p >
< h2 id = "combined-types" > < a class = "header" href = "#combined-types" > Combined Types< / a > < / h2 >
< p > These types utilise core types to create new combinations. They take type arguments.< / p >
< h3 id = "fun" > < a class = "header" href = "#fun" > < code > fun< / code > < / a > < / h3 >
< p > Represents a function. Equivalent to Ground < code > -function< / code > , or a C function pointer.< / p >
< p > < strong > Syntax< / strong > :< / p >
< pre > < code class = "language-solstice" > fun(...) type
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > type< / code > is a type identifier, which will be the return type< / li >
< li > < code > ...< / code > is multiple type identifiers, seperated by commas, which are the argument types< / li >
< / ul >
< p > < strong > Example< / strong > :< / p >
< pre > < code class = "language-solstice" > fun(int, string) bool
< / code > < / pre >
< p > This represents a function which takes an < code > int< / code > and < code > string< / code > as arguments, and returns a < code > bool< / code > .< / p >
< h3 id = "template" > < a class = "header" href = "#template" > < code > template< / code > < / a > < / h3 >
< p > Represents an uninitialized object. Equivalent to Ground < code > -struct< / code > .< / p >
< p > < strong > Syntax< / strong > :< / p >
< pre > < code class = "language-solstice" > template(...)
< / code > < / pre >
< p > where < code > ...< / code > is multiple pairs of:< / p >
< ul >
< li > a type identifier for the field, and< / li >
< li > an identifier (representing the field name)< / li >
< / ul >
< p > seperated by commas.< / p >
< p > < strong > Example< / strong > :< / p >
< pre > < code class = "language-solstice" > template(int x, string y)
< / code > < / pre >
< p > This represents a template which, when initialized, has fields x (with integer) and y (with string).< / p >
< h3 id = "object" > < a class = "header" href = "#object" > < code > object< / code > < / a > < / h3 >
< p > Represents an initialized object.< / p >
< p > < strong > Syntax< / strong > :< / p >
< pre > < code class = "language-solstice" > object(...)
< / code > < / pre >
< p > where < code > ...< / code > is multiple pairs of:< / p >
< ul >
< li > a type identifier for the field, and< / li >
< li > an identifier (representing the field name)< / li >
< / ul >
< p > seperated by commas.< / p >
< p > < strong > Example< / strong > :< / p >
< pre > < code class = "language-solstice" > object(int x, string y)
< / code > < / pre >
< p > This represents a object which has fields x (with integer) and y (with string).< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
2026-05-10 16:35:17 +10:00
< h1 id = "variables-1" > < a class = "header" href = "#variables-1" > Variables< / a > < / h1 >
2026-05-09 21:09:15 +10:00
< p > Variables are defined and modified with the syntax:< / p >
< pre > < code class = "language-solstice" > name = value
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > name< / code > is an identifier, and< / li >
< li > < code > value< / code > is a literal, expression, or identifier previously assigned to a variable.< / li >
< / ul >
< p > All variables must have a known type and value at definition time. When updating a variable, the type may not change.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "scoping-and-lifetimes" > < a class = "header" href = "#scoping-and-lifetimes" > Scoping and Lifetimes< / a > < / h1 >
< h2 id = "subscoping" > < a class = "header" href = "#subscoping" > Subscoping< / a > < / h2 >
< p > A “subscope” is a scope contained inside a function, created inside curly braces (< code > {}< / code > ).< / p >
< p > Subscopes can view and modify variables avaliable in their parent scope.< / p >
< p > Subscopes may also create their own variables, however these will be destroyed when the subscope ends.< / p >
< h2 id = "function-scoping" > < a class = "header" href = "#function-scoping" > Function Scoping< / a > < / h2 >
< p > A function scope is a scope created inside a function.< / p >
< p > Function scopes are created from a function’ s attached closure, which is a snapshot of all variables at the time of function definition.< / p >
< p > The function’ s attached closure cannot be modified.< / p >
< p > Function scopes also contain all arguments provided to a function.< / p >
< p > When the function finishes running (with a < code > return< / code > ), all variables are destroyed.< / p >
< h2 id = "destructors" > < a class = "header" href = "#destructors" > Destructors< / a > < / h2 >
< p > Objects (see < a href = "#struct-definition" > here< / a > ) can contain a destructor which specifies custom behaviour for destroying itself. This is useful for:< / p >
< ul >
< li > Freeing heap-allocated memory< / li >
< li > Closing a connection< / li >
< li > Closing a file< / li >
< / ul >
< p > The destructor will always be in the field < code > destructor< / code > with type signature < code > fun() int< / code > . It should be automatically called when the variable goes out of scope.< / p >
< h2 id = "duplicators" > < a class = "header" href = "#duplicators" > Duplicators< / a > < / h2 >
< p > Objects (see < a href = "#struct-definition" > here< / a > ) can contain a duplicator which specifies custom behaviour for copying itself. This is useful for:< / p >
< ul >
< li > Duplicating heap-allocated memory< / li >
< / ul >
< p > The duplicator will always be in the field < code > duplicator< / code > with type signature < code > fun((self) old) (self)< / code > . It should be automatically called when the variable is:< / p >
< ul >
< li > Copied into a new variable< / li >
< li > Put inside a closure< / li >
< li > Passed to a function< / li >
< / ul >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "operators" > < a class = "header" href = "#operators" > Operators< / a > < / h1 >
< p > Operators are bits of code intended to control how the program runs.< / p >
< h2 id = "puts" > < a class = "header" href = "#puts" > < code > puts< / code > < / a > < / h2 >
< p > Stands for “put something”. Prints debug info to the console, followed by a new line.< / p >
< h3 id = "formatting" > < a class = "header" href = "#formatting" > Formatting< / a > < / h3 >
< ul >
< li >
< p > int: The literal number, as formatted by C < code > printf("%" PRId64)< / code > .< / p >
< / li >
< li >
< p > double: The literal number, as formatted by C < code > printf("%f")< / code > .< / p >
< / li >
< li >
< p > string: All characters in the string, as formatted by C < code > printf("%s")< / code > .< / p >
< / li >
< li >
< p > char: The ASCII character corresponding to the number held, as formatted by C < code > printf("%c")< / code > .< / p >
< / li >
< li >
< p > bool: If < code > true< / code > or < code > 1< / code > , print < code > true< / code > . Otherwise, print < code > false< / code > .< / p >
< / li >
< li >
< p > fun: Print < code > < function> < / code > .< / p >
< / li >
< li >
< p > template: Print < code > < struct fields: { ... }> < / code > , where:< / p >
< ul >
< li > < code > ...< / code > is a comma-seperated sequence of < code > key: value< / code > , where:
< ul >
< li > < code > key< / code > is the identifier of the field.< / li >
< li > < code > value< / code > is the properly formatted value in the field.< / li >
< / ul >
< / li >
< / ul >
< / li >
< li >
< p > object: Print < code > < object fields: { ... }> < / code > , where:< / p >
< ul >
< li > < code > ...< / code > is a comma-seperated sequence of < code > key: value< / code > , where:
< ul >
< li > < code > key< / code > is the identifier of the field.< / li >
< li > < code > value< / code > is the properly formatted value in the field.< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< h2 id = "if" > < a class = "header" href = "#if" > < code > if< / code > < / a > < / h2 >
< p > Runs a block of code only if the provided condition is true.< / p >
< p > Syntax:< / p >
< pre > < code class = "language-solstice" > if condition {
...
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > condition< / code > is an expression which evaluates to a boolean.
< ul >
< li > If this expression evaluates to < code > true< / code > , the code block will be run.< / li >
< li > Brackets surrounding the condition are optional.< / li >
< / ul >
< / li >
< li > < code > ...< / code > is the code to run if the condition is true.< / li >
< / ul >
< p > Example:< / p >
< pre > < code class = "language-solstice" > if 2 + 2 == 4 {
puts "phew!"
}
< / code > < / pre >
< h2 id = "while" > < a class = "header" href = "#while" > < code > while< / code > < / a > < / h2 >
< p > Runs a block of code until the provided condition is false.< / p >
< p > Syntax:< / p >
< pre > < code class = "language-solstice" > while condition {
...
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > condition< / code > is an expression which evaluates to a boolean.
< ul >
< li > If this expression evaluates to < code > false< / code > , the code block will not be run anymore.< / li >
< li > Brackets surrounding the condition are optional.< / li >
< / ul >
< / li >
< li > < code > ...< / code > is the code to run while the condition is true.< / li >
< / ul >
< p > Example:< / p >
< pre > < code class = "language-solstice" > while true {
puts "To infinity and beyond!"
}
< / code > < / pre >
< h2 id = "return" > < a class = "header" href = "#return" > < code > return< / code > < / a > < / h2 >
< p > Returns a value from a function.< / p >
< p > Syntax:< / p >
< pre > < code class = "language-solstice" > return value
< / code > < / pre >
< p > where < code > value< / code > is a value with the same type as the function’ s return type.< / p >
< h2 id = "ground" > < a class = "header" href = "#ground" > < code > ground< / code > < / a > < / h2 >
< p > < strong > Inline Ground is potentially dangerous. Only use if you know what you’ re doing!< / strong > < / p >
< p > Inserts inline Ground code into the generated program.< / p >
< p > Syntax:< / p >
< pre > < code class = "language-solstice" > ground {
...
}
< / code > < / pre >
< p > where < code > ...< / code > is the Ground code to insert.< / p >
< p > See < a href = "https://chookspace.com/ground/ground" > here< / a > for details about Ground.< / p >
< p > Note: < strong > Solstice cannot keep track of state inside < code > ground< / code > blocks!< / strong > Ground will allow you to do things without the overhead of the Solstice type checker.< / p >
< p > To extract a value from a Ground block, do something like this:< / p >
< pre > < code class = "language-solstice" > x = 0
ground {
set & x 10
}
puts x
< / code > < / pre >
< p > so the type checker can know what < code > x< / code > is.< / p >
2026-05-10 16:35:17 +10:00
< h2 id = "use" > < a class = "header" href = "#use" > < code > use< / code > < / a > < / h2 >
< p > The < code > use< / code > operator lets you import code from libraries, either from in the local folder or installed in the < code > $SOLSTICE_LIBS< / code > directory, which defaults to < code > /usr/lib/solstice< / code > .< / p >
< p > When using < code > use< / code > , Solstice will insert the selected file’ s contents at that position.< / p >
< h3 id = "local-use" > < a class = "header" href = "#local-use" > Local < code > use< / code > < / a > < / h3 >
< p > Supply a string after < code > use< / code > which is the path to the file to import, without the < code > .sols< / code > extension.< / p >
< pre > < code class = "language-solstice" > use "parser/Node"
use "parser/parser"
< / code > < / pre >
< h3 id = "global-use" > < a class = "header" href = "#global-use" > Global < code > use< / code > < / a > < / h3 >
< p > Supply an identifier after < code > use< / code > which is the name of the library to import, without the < code > .sols< / code > extension.< / p >
< pre > < code class = "language-solstice" > use io
< / code > < / pre >
2026-05-09 21:09:15 +10:00
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "function-definition" > < a class = "header" href = "#function-definition" > Function Definition< / a > < / h1 >
< h2 id = "named-functions" > < a class = "header" href = "#named-functions" > Named Functions< / a > < / h2 >
< p > Define a named function with the following syntax:< / p >
< pre > < code class = "language-solstice" > def functionName(args) type {
...
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > functionName< / code > is the name of the function.
< ul >
< li > If < code > functionName< / code > is already defined as a function or other value, it will only be overwritten if the type does not change.< / li >
< / ul >
< / li >
< li > < code > args< / code > is multiple comma-seperated pairs of:
< ul >
< li > a type identifier for the parameter, and< / li >
< li > an identifier (representing the parameter name)< / li >
< / ul >
< / li >
< li > < code > type< / code > is the type of value which the function will return< / li >
< li > < code > ...< / code > is the code inside the function (the function body).
< ul >
< li > The function body will have access to previously set variables through a closure. The closure is a copy of all variables in their current state at function definition time.< / li >
< li > The function body will also have access to the parameters defined in < code > args< / code > .< / li >
< / ul >
< / li >
< / ul >
< p > Example:< / p >
< pre > < code class = "language-solstice" > def add(int a, int b) int {
return a + b
}
< / code > < / pre >
< h2 id = "anonymouslambda-functions" > < a class = "header" href = "#anonymouslambda-functions" > Anonymous/Lambda functions< / a > < / h2 >
< p > Define a lambda function with the following syntax:< / p >
< pre > < code class = "language-solstice" > lambda(args) type {
...
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > args< / code > is multiple comma-seperated pairs of:
< ul >
< li > a type identifier for the parameter, and< / li >
< li > an identifier (representing the parameter name)< / li >
< / ul >
< / li >
< li > < code > type< / code > is the type of value which the function will return< / li >
< li > < code > ...< / code > is the code inside the function (the function body).
< ul >
< li > The function body will have access to previously set variables through a closure. The closure is a copy of all variables in their current state at function definition time.< / li >
< li > The function body will also have access to the parameters defined in < code > args< / code > .< / li >
< / ul >
< / li >
< / ul >
< p > Example:< / p >
< pre > < code class = "language-solstice" > add = lambda(int a, int b) int {
return a + b
}
< / code > < / pre >
< p > Lambda functions are most useful when passed as arguments to other functions.< / p >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "struct-definition" > < a class = "header" href = "#struct-definition" > Struct Definition< / a > < / h1 >
< p > Define a struct with the < code > struct< / code > keyword.< / p >
< p > Syntax:< / p >
< pre > < code class = "language-solstice" > struct StructName {
...
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > StructName< / code > is the name of your struct< / li >
< li > < code > ...< / code > is the body of your struct< / li >
< / ul >
< h2 id = "struct-body" > < a class = "header" href = "#struct-body" > Struct Body< / a > < / h2 >
< p > Inside the struct body, you can:< / p >
< ul >
< li > Define fields< / li >
< li > Define methods< / li >
< li > Define special methods (< code > constructor< / code > , < code > destructor< / code > , < code > duplicator< / code > , < code > as< / code > )< / li >
< / ul >
< h2 id = "defining-fields" > < a class = "header" href = "#defining-fields" > Defining fields< / a > < / h2 >
< p > A field in a struct is defined in the same way as a variable.< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
x = 5
}
< / code > < / pre >
< p > This creates a field named < code > x< / code > with a default value of < code > 5< / code > .< / p >
< h2 id = "defining-methods" > < a class = "header" href = "#defining-methods" > Defining methods< / a > < / h2 >
< p > A method in a struct is defined in the same way as a named function.< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
def myMethod() int {
return 0
}
}
< / code > < / pre >
< p > Methods have access to the struct’ s members through the < code > self< / code > object, which is implicitly passed.< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
x = 10
def myMethod() int {
return self.x * 2
}
}
< / code > < / pre >
< h2 id = "private-and-protected-fields" > < a class = "header" href = "#private-and-protected-fields" > Private and protected fields< / a > < / h2 >
< p > A private field is a field which only methods inside the object can read and write.< / p >
< p > A protected field is a field which only methods inside the object can write to, however anywhere else in the program the field can be read.< / p >
< p > All other fields are public, meaning anywhere in the program can read or write these fields.< / p >
< p > Methods and special methods are by default protected, however can be made private.< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
private x = 10
protected y = "Hi"
private doSomething() int {
return 14
}
}
< / code > < / pre >
< h2 id = "defining-special-methods" > < a class = "header" href = "#defining-special-methods" > Defining special methods< / a > < / h2 >
< p > In Solstice, objects have some special methods which provide ease of use while handling these objects.< / p >
< h3 id = "constructor" > < a class = "header" href = "#constructor" > Constructor< / a > < / h3 >
< p > A constructor is used to initialize an object with user-provided fields.< / p >
< p > Define a constructor like this:< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
constructor(args) {
...
}
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > args< / code > is multiple comma-seperated pairs of:
< ul >
< li > a type identifier for the parameter, and< / li >
< li > an identifier (representing the parameter name)< / li >
< / ul >
< / li >
< li > < code > ...< / code > is the constructor body
< ul >
< li > The constructor body has access to the < code > self< / code > object, which is how it can modify the newly created object.< / li >
< li > The < code > self< / code > object is automatically returned at the end of the constructor, however can be returned manually if required.< / li >
< / ul >
< / li >
< / ul >
< p > Use a constructor like this:< / p >
< pre > < code class = "language-solstice" > MyStruct(args)
< / code > < / pre >
< p > where:< / p >
< ul >
< li > args is many comma-seperated expressions corresponding to the signature of the defined constructor< / li >
< / ul >
< h3 id = "destructor" > < a class = "header" href = "#destructor" > Destructor< / a > < / h3 >
< p > A destructor is used to destroy an object once it goes out of scope.< / p >
< p > Define a destructor like this:< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
destructor {
...
}
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > ...< / code > is the destructor body
< ul >
< li > The destructor body has access to the < code > self< / code > object, which is how it can access and modify the object which is being destroyed.< / li >
< li > There is no need to return a value from the destructor.< / li >
< / ul >
< / li >
< / ul >
< p > Note how the destructor does not take any arguments.< / p >
< h3 id = "duplicator" > < a class = "header" href = "#duplicator" > Duplicator< / a > < / h3 >
< p > A duplicator is used to copy an object when it is assigned to a new name, or passed to a function.< / p >
< p > Define a duplicator like this:< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
duplicator {
...
}
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > ...< / code > is the duplicator body
< ul >
< li > The destructor body has access to the < code > self< / code > and < code > old< / code > objects.
< ul >
< li > The < code > self< / code > object is the new duplication and will be automatically returned< / li >
< li > The < code > old< / code > object is the old object and will not be copied out< / li >
< / ul >
< / li >
< / ul >
< / li >
< / ul >
< p > Note how the duplicator does not take any arguments.< / p >
< h3 id = "as-methods" > < a class = "header" href = "#as-methods" > As methods< / a > < / h3 >
< p > As methods allow easy conversion between different types.< / p >
< p > Define an as method like this:< / p >
< pre > < code class = "language-solstice" > struct MyStruct {
as type {
...
}
}
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > type< / code > is the type which the object will be converted to< / li >
< li > < code > ...< / code > is the as method body
< ul >
< li > The < code > self< / code > object is avaliable inside the as method< / li >
< li > You will need to initialize and return a new value with the specified type< / li >
< / ul >
< / li >
< / ul >
< p > Use an as method like this:< / p >
< pre > < code class = "language-solstice" > myobj as type
< / code > < / pre >
< p > where:< / p >
< ul >
< li > < code > myobj< / code > is an object with an as method which provides a conversion to < code > type< / code > < / li >
< li > < code > type< / code > is the target type< / li >
< / ul >
2026-05-10 16:35:17 +10:00
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "vela-0xx" > < a class = "header" href = "#vela-0xx" > “Vela” 0.x.x< / a > < / h1 >
< p > Vela is the codename for the 0.x.x releases of Solstice. It is named after the < a href = "https://en.wikipedia.org/wiki/Vela_(constellation)" > Vela constellation< / a > .< / p >
< h2 id = "changes" > < a class = "header" href = "#changes" > Changes< / a > < / h2 >
< p > Vela is the prerelease version of Solstice, and is the phase where core compiler features are added. Here are some features added in Vela to the compiler:< / p >
< ul >
< li > < code > puts< / code > < / li >
< li > Variables< / li >
< li > Values< / li >
< li > Static type system< / li >
< li > < code > if< / code > , < code > while< / code > control flow< / li >
< li > Functions
< ul >
< li > Lambda/Anonymous Functions< / li >
< li > Named Functions< / li >
< li > Closures attached to functions< / li >
< / ul >
< / li >
< li > Structs
< ul >
< li > Fields< / li >
< li > Methods< / li >
< li > < code > private< / code > and < code > protected< / code > < / li >
< li > < code > as< / code > -methods< / li >
< li > Constructors, destructors, duplicators< / li >
< / ul >
< / li >
< li > Generics (in progress)< / li >
< li > < code > pragma< / code > directives (in progress)< / li >
< li > Libraries with < code > use< / code > < / li >
< / ul >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "vela-010" > < a class = "header" href = "#vela-010" > “Vela” 0.1.0< / a > < / h1 >
< p > This is the very first release of Solstice! Not much to see here.< / p >
< p > This release contains:< / p >
< ul >
< li > < code > puts< / code > < / li >
< li > Variables< / li >
< li > Values< / li >
< li > Static type system< / li >
< li > < code > if< / code > , < code > while< / code > control flow< / li >
< li > Functions
< ul >
< li > Lambda/Anonymous Functions< / li >
< li > Named Functions< / li >
< li > Closures attached to functions< / li >
< / ul >
< / li >
< li > Structs
< ul >
< li > Fields< / li >
< li > Methods< / li >
< li > < code > private< / code > and < code > protected< / code > < / li >
< li > < code > as< / code > -methods< / li >
< li > Constructors, destructors, duplicators< / li >
< / ul >
< / li >
< li > Generics (partially, there are many bugs)< / li >
< li > < code > pragma< / code > directives in the parser< / li >
< li > Libraries with < code > use< / code > < / li >
< / ul >
< div style = "break-before: page; page-break-before: always;" > < / div >
< h1 id = "fornax-1xx" > < a class = "header" href = "#fornax-1xx" > “Fornax” 1.x.x< / a > < / h1 >
< p > Fornax will be the codename for the 1.x.x releases of Solstice. It is named after the < a href = "https://en.wikipedia.org/wiki/Fornax" > Fornax constellation< / a > .< / p >
< h2 id = "release-target" > < a class = "header" href = "#release-target" > Release Target< / a > < / h2 >
< p > Fornax will release when:< / p >
< ul >
< li > The compiler core is stable enough to host moderately sized projects< / li >
< li > The standard library is capable enough for many programming projects< / li >
< / ul >
< p > Fornax is not currently released.< / p >
2026-05-09 21:09:15 +10:00
< / main >
< nav class = "nav-wrapper" aria-label = "Page navigation" >
<!-- Mobile navigation buttons -->
< div style = "clear: both" > < / div >
< / nav >
< / div >
< / div >
< nav class = "nav-wide-wrapper" aria-label = "Page navigation" >
< / nav >
< / div >
< template id = fa-eye > < span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 576 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z" / > < / svg > < / span > < / template >
< template id = fa-eye-slash > < span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 640 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z" / > < / svg > < / span > < / template >
< template id = fa-copy > < span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 512 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z" / > < / svg > < / span > < / template >
< template id = fa-play > < span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 384 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z" / > < / svg > < / span > < / template >
< template id = fa-clock-rotate-left > < span class = fa-svg > < svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 512 512" > <!-- ! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --> < path d = "M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z" / > < / svg > < / span > < / template >
2026-05-10 16:35:17 +10:00
<!-- Livereload script (if served using the cli tool) -->
< script >
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
< / script >
2026-05-09 21:09:15 +10:00
< script >
window.playground_copyable = true;
< / script >
< script src = "elasticlunr-ef4e11c1.min.js" > < / script >
< script src = "mark-09e88c2c.min.js" > < / script >
< script src = "searcher-c2a407aa.js" > < / script >
< script src = "clipboard-1626706a.min.js" > < / script >
< script src = "highlight-d9401a48.js" > < / script >
< script src = "book-a0b12cfe.js" > < / script >
<!-- Custom JS scripts -->
< script >
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
< / script >
< / div >
< / body >
< / html >