Files
sols.dev/docs/print.html

1029 lines
47 KiB
HTML
Raw Normal View History

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";
window.path_to_searchindex_js = "searchindex-c698e2a6.js";
</script>
<!-- Start loading toc.js asap -->
<script src="toc-cb4e10de.js"></script>
</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>
<p>Welcome to the Solstice docs! For now, the documentation is in the format of a specification, which instructs you on how Solstice should behave. In future, a tutorial (similar to the Rust book) will be written which shows you each part of the language, instead of declaring it like the spec.</p>
<p>Docs generated by mdBook.</p>
<div style="break-before: page; page-break-before: always;"></div>
<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>
<h1 id="comments"><a class="header" href="#comments">Comments</a></h1>
<p>Comments in Solstice can be done in 3 ways:</p>
<h2 id="-single-line-comment"><a class="header" href="#-single-line-comment"><code>//</code> (Single-Line Comment)</a></h2>
<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>
<h2 id="--multiline-comment"><a class="header" href="#--multiline-comment"><code>/* */</code> (Multiline Comment)</a></h2>
<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>
<h2 id="-shebang-comment"><a class="header" href="#-shebang-comment"><code>#</code> (Shebang Comment)</a></h2>
<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>&gt;</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>&lt;</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>&gt;=</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>&lt;=</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 -&gt; Combined Types -&gt; fun</a>) inside the brackets (in place of <code>...</code>)</li>
</ul>
</li>
<li>Returns:
<ul>
<li>The functions return type as specified by the function type signature (see <a href="#fun">Types -&gt; Combined Types -&gt; 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>
<h3 id="int"><a class="header" href="#int"><code>int</code></a></h3>
<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>
<h3 id="double"><a class="header" href="#double"><code>double</code></a></h3>
<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>
<h3 id="string"><a class="header" href="#string"><code>string</code></a></h3>
<p>C-style null-terminated array of characters. Equivalent to C <code>char*</code> or Ground <code>-string</code>.</p>
<h3 id="char"><a class="header" href="#char"><code>char</code></a></h3>
<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>
<h3 id="bool"><a class="header" href="#bool"><code>bool</code></a></h3>
<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>
<h1 id="variables"><a class="header" href="#variables">Variables</a></h1>
<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 functions attached closure, which is a snapshot of all variables at the time of function definition.</p>
<p>The functions 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>&lt;function&gt;</code>.</p>
</li>
<li>
<p>template: Print <code>&lt;struct fields: { ... }&gt;</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>&lt;object fields: { ... }&gt;</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 functions 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 youre 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 &amp;x 10
}
puts x
</code></pre>
<p>so the type checker can know what <code>x</code> is.</p>
<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 structs 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>
</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>
<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>