19 Commits

Author SHA1 Message Date
6f9a630a7a ANother update 2026-01-28 20:18:45 +11:00
4984c0cb71 fix install shell 2026-01-28 20:15:56 +11:00
9a4c0216d9 stuff 2026-01-28 18:38:33 +11:00
5bcaeb00a8 stuff 2026-01-28 18:34:18 +11:00
7710b8923a Update stuff 2026-01-28 18:31:10 +11:00
45489caa1d Changes 2026-01-27 14:32:05 +11:00
9648744e17 Update docs for structs and objects 2026-01-27 14:27:09 +11:00
f2a1b5a3ac update 2026-01-21 16:29:33 +11:00
ea11f5962e Update docs 2026-01-21 16:26:54 +11:00
6de79e5fa8 Update links 2026-01-20 12:15:50 +11:00
f492e3be22 upadte again 2026-01-19 20:04:36 +11:00
682ac98d67 Add highlighter 2026-01-18 14:48:31 +11:00
ca4c03367e update sidebar 2026-01-18 14:31:53 +11:00
eb48507091 Update docs 2026-01-18 14:28:21 +11:00
1410b025c5 Update script 2026-01-18 14:19:43 +11:00
5383e3fdf4 Update playground AGAIN (maybe I should test more) 2026-01-13 20:50:28 +11:00
2f91528f25 Update playground again 2026-01-13 20:47:45 +11:00
f50b365a5a update playground 2026-01-13 20:42:53 +11:00
b1bf2e9688 Merge pull request 'Update docs/index.html' (#2) from DiamondNether90/sols.dev:master into master
Reviewed-on: max/sols.dev#2
2026-01-13 20:36:59 +11:00
11 changed files with 636 additions and 197 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "pkgs"]
path = pkgs
url = https://chookspace.com/solstice/pkgs

118
docs/highlight.js Normal file
View File

@@ -0,0 +1,118 @@
// Solstice Syntax Highlighter
// Add this script to your HTML file before the closing </body> tag
document.addEventListener('DOMContentLoaded', function() {
highlightAllCode();
});
function highlightAllCode() {
const codeElements = document.querySelectorAll('pre.code code');
codeElements.forEach(element => {
// Get the text content (this automatically decodes HTML entities)
const code = element.textContent;
element.innerHTML = highlightSolstice(code);
});
}
function highlightSolstice(code) {
let result = '';
let i = 0;
// Tokenize the code
while (i < code.length) {
let matched = false;
// Check for comments
if (code.substr(i, 2) === '//') {
let end = code.indexOf('\n', i);
if (end === -1) end = code.length;
result += `<span class="comment">${escapeHtml(code.substring(i, end))}</span>`;
i = end;
matched = true;
}
// Check for strings
else if (code[i] === '"') {
let end = i + 1;
while (end < code.length && code[end] !== '"') {
if (code[end] === '\\') end++; // Skip escaped characters
end++;
}
end++; // Include closing quote
result += `<span class="string">${escapeHtml(code.substring(i, end))}</span>`;
i = end;
matched = true;
}
// Check for numbers
else if (/\d/.test(code[i])) {
let end = i;
while (end < code.length && /[\d.]/.test(code[end])) {
end++;
}
result += `<span class="number">${code.substring(i, end)}</span>`;
i = end;
matched = true;
}
// Check for keywords, types, built-ins, and identifiers
else if (/[a-zA-Z_]/.test(code[i])) {
let end = i;
while (end < code.length && /[a-zA-Z0-9_]/.test(code[end])) {
end++;
}
const word = code.substring(i, end);
// Check what type of word it is
if (['def', 'if', 'while', 'return', 'ground', 'puts', 'def', 'struct', 'new', 'use'].includes(word)) {
result += `<span class="keyword">${word}</span>`;
} else if (['input', 'print', 'println'].includes(word)) {
result += `<span class="builtin">${word}</span>`;
} else if (['int', 'double', 'string', 'char', 'bool'].includes(word)) {
result += `<span class="type">${word}</span>`;
} else if (['true', 'false'].includes(word)) {
result += `<span class="boolean">${word}</span>`;
} else {
// Check if it's a function call (followed by '(')
let j = end;
while (j < code.length && /\s/.test(code[j])) j++;
if (code[j] === '(') {
result += `<span class="function">${word}</span>`;
} else {
result += word;
}
}
i = end;
matched = true;
}
// Check for operators
else if ('+-*/=!<>:'.includes(code[i])) {
let op = code[i];
if (i + 1 < code.length && '='.includes(code[i + 1])) {
op += code[i + 1];
i++;
}
result += `<span class="operator">${escapeHtml(op)}</span>`;
i++;
matched = true;
}
// Everything else (whitespace, braces, etc.)
if (!matched) {
result += escapeHtml(code[i]);
i++;
}
}
return result;
}
function escapeHtml(text) {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}

View File

@@ -78,3 +78,42 @@ h2 {
h3 {
font-size: 25px;
}
/* Syntax highlighting styles for Solstice */
.comment {
color: #6c757d;
font-style: italic;
}
.string {
color: #98c379;
}
.number {
color: #d19a66;
}
.keyword {
color: #c678dd;
font-weight: bold;
}
.builtin {
color: #61afef;
}
.type {
color: #e5c07b;
}
.boolean {
color: #d19a66;
}
.operator {
color: #56b6c2;
}
.function {
color: #61afef;
}

View File

@@ -6,6 +6,7 @@
<title>Solstice Docs</title>
<link rel="stylesheet" href="https://sols.dev/index.css">
<link rel="stylesheet" href="index.css">
<script src="highlight.js"></script>
</head>
<body>
<div class="box">
@@ -17,14 +18,20 @@
<li><strong><a href="#type_system">Type System</a></strong></li>
<li><a href="#value_types">Value Types</a></li>
<li><a href="#type_checker">Type Checker</a></li>
<li><a href="#object_types">Types of Functions, Templates, and Objects</a></li>
<li><strong><a href="#structs">Structs, Templates and Objects</a></strong></li>
<li><strong><a href="#inline_ground">Inline Ground</a></strong></li>
<li><strong><a href="#builtins">Built In Functions</a></strong></li>
<li><a href="#input_string_msg__string">input(string msg) string</a></li>
<li><a href="#print_string_msg__string">print(string msg) string</a></li>
<li><a href="#println_string_msg__string">println(string msg) string</a></li>
<li><strong><a href="#nativecompiler">Native Compiler</a></strong></li>
</ul>
</div>
<div class="content">
<h1>Solstice Docs</h1>
<p>Welcome to the Solstice docs! Feel free to read in whichever order you like, or come back when you feel like it. You can read these head to tail if you want to understand the whole of the language as well.</p>
<p>See a mistake? Report it at <a href="https://chsp.au/max/sols.dev">this site's repository</a>.
<p>See a mistake? Report it at <a href="https://chookspace.com/max/sols.dev">this site's repository</a>.
<p>Happy coding!</p>
<div id="core_concepts">
<h2>Core Concepts</h2>
@@ -33,7 +40,8 @@
<p>Solstice's compiler is invoked via the <code>solstice</code> command. It provides some options:</p>
<ul>
<li><code>-o</code> or <code>--output</code>: Tells Solstice where to output a compiled file.</li>
<li><code>-t</code> or <code>--type</code>: Tells Solstice the type of file to output.<br>At present, Solstice only supports Ground source files as an output type, but more types may be added in future.</li>
<li><code>-t</code> or <code>--type</code>: Tells Solstice the type of file to output.
This can either be "ground" or "program". "ground" outputs a .grnd program, and "program" outputs a compiled native executable. See <a href="#nativecompiler">here</a> for details.</li>
</ul>
<p>Example usage:</p>
<pre class="code"><code>solstice fib.sols -o fib.grnd</code></pre>
@@ -57,16 +65,20 @@ puts true
puts "You can print out anything with puts!"</code></pre>
<h3>Variables</h3>
<p>Solstice variables are quite simple. Assign values with <code>=</code>, and read them with the variable name.</p>
<pre class="code"><code>x = 5<br>puts x</code></pre>
<pre class="code"><code>x = 5
puts x</code></pre>
<p>Types are automatically inferred by Solstice.</p>
<h3>Maths</h3>
<p>You can use <code>+</code> (add), <code>-</code> (subtract), <code>*</code> (multiply), and <code>/</code> (divide) to do math.</p>
<p>Math operations take two values on either side, and perform the operation. Order of operations is supported.</p>
<pre class="code"><code>x = 5 + 3<br>y = 10<br>puts x + y</code></pre>
<pre class="code"><code>x = 5 + 3
y = 10
puts x + y</code></pre>
<h3>Control Flow and Equalities</h3>
<p>Solstice supports <code>if</code> and <code>while</code> statements, as well as the <code>==</code>, <code>!=</code>, <code>></code>, <code>>=</code>, <code><</code>, and <code><=</code> operations.</p>
<p>Conditionals work just like maths: two values on either side, check whether the condition is correct or not based on those values, and output a boolean.</p>
<pre class="code"><code>puts 5 == 5<br>puts 5 != 5</code></pre>
<pre class="code"><code>puts 5 == 5
puts 5 != 5</code></pre>
<p><code>if</code> and <code>while</code> statements take a conditional, and then a code block afterwards. See these examples:</p>
<pre class="code"><code>x = 5
if x &gt; 10 {
@@ -88,7 +100,9 @@ while number &lt; 10 {
</code>
<h3>Functions</h3>
<p><strong>Note:</strong> Functions in Solstice are currently in beta. Type checking for functions is currently experimental, and arguments may not work as intended. Be warned!</p>
<p>In Solstice, function definitions have a syntax like this: <pre class="code"><code>def functionName(type arg1, type arg2, type arg3) returnType {<br> // code goes here<br>}</code></pre></p>
<p>In Solstice, function definitions have a syntax like this: <pre class="code"><code>def functionName(type arg1, type arg2, type arg3) returnType {
// code goes here
}</code></pre></p>
<p>Your types can be <code>int</code>, <code>double</code>, <code>string</code>, <code>bool</code>, or <code>char</code> (see the "Type System" section for more details)</p>
<p>Return a value (which must be the same type as your <code>returnType</code>) with <code>return value</code>.</p>
<p>Here's an example function:</p>
@@ -97,6 +111,11 @@ while number &lt; 10 {
}</code></pre>
<h3>Calling Functions</h3>
<p>Function calling is done like in most other programming languages, with the syntax <code>function(arg1, arg2, arg3)</code>.</p>
<h3>Importing Other Code</h3>
<p>Solstice allows you to write libraries in Solstice, or write wrappers for Ground libraries. Use the <code>use</code> keyword, followed by an identifier to import the library.</p>
<pre class="code"><code>use io
println("Hello!")</code></pre>
<h3>That's it!</h3>
<p>You now know everything you need to know about Solstice to start programming! You can continue reading for more information.</p>
</div>
@@ -113,6 +132,15 @@ while number &lt; 10 {
<li><code>bool</code>: Either true or false</li>
</ul>
</div>
<div id="object_types">
<h3>Types of Functions, Templates, and Objects</h3>
<p>The type signature of a function looks like this:</p>
<pre class="code"><code>fun(argType, argType, argType) returnType</code></pre>
<p>The type signature of a template looks like this:</p>
<pre class="code"><code>template(fieldType fieldName, fieldType fieldName, fieldType fieldName)</code></pre>
<p>The type signature of an object looks like this:</p>
<pre class="code"><code>object(fieldType fieldName, fieldType fieldName, fieldType fieldName)</code></pre>
</div>
<div id="type_checker">
<h3>Type Checker</h3>
<p>Solstice statically checks types at compile time to ensure your data is used as intended. These are the details of the type checker.</p>
@@ -125,13 +153,69 @@ while number &lt; 10 {
</ul>
</div>
</div>
<div id="structs">
<h2>Structs, templates and objects</h2>
<p><strong>Note:</strong> Structs, templates, and objects in Solstice are currently in beta. A lot of work in the type checker has been done, but accessing fields is still an issue.</p>
<p>In Solstice, you can create a struct to group various bits of data together. You can specify default values for each field with <code>:</code> or <code>=</code>.</p>
<pre class="code"><code>struct Person {
name: "John"
age: 32
}</code></pre>
<p>This struct generates a template named "Person" which can be used later to generate new objects.</p>
<p>You can use the <code>new</code> operator to create new instances of templates.</p>
<pre class="code"><code>max = new Person</code></pre>
</div>
<div id="inline_ground">
<h2>Inline Ground</h2>
<p>Since Solstice is built atop Ground, you can write Ground code inside Solstice code, usually to wrap a Ground function for the Solstice standard library.</p>
<p>Inline Ground is not vetted by the type checker. <strong>Be careful when modifying existing variables with inline ground!</strong> The type checker is not aware of any values created inside inline Ground.</p>
<p>If you would like the Solstice type checker to be aware of values created by Ground, initialise a variable with a blank of whatever type is made by Ground.</p>
<p>Variable names are the same inside inline Ground as they are in Solstice. Read Ground's syntax guide for an understanding on how it should work <a href="https://chookspace.com/ground/cground/src/branch/master/docs/syntax.md">here</a>.</p>
<pre class="code"><code>ground {
set &x 5
println $x
}</code></pre>
</div>
<div id="builtins">
<h2>Built In Functions</h2>
<h3><code>io</code> library</h3>
<div id="input_string_msg__string">
<h3>input(string msg) string</h3>
<h4>input(string msg) string</h4>
<p>Gets user input from the console until the next line. The msg is used as a prompt for the user. Returns inputted characters from the console.</p>
<pre class="code"><code>guess = input("What is the password? ")<br>if guess == "password123" {<br> puts "Good job!"<br>}</code></pre>
<pre class="code"><code>use io
guess = input("What is the password? ")
if guess == "password123" {
puts "Good job!"
}</code></pre>
</div>
<div id="print_string_msg__string">
<h4>print(string msg) string</h4>
<p>Prints a string to the console.</p>
<pre class="code"><code>use io
print("Hello, World!")</code></pre>
</div>
<div id="println_string_msg__string">
<h4>println(string msg) string</h4>
<p>Prints a string to the console. Appends a new line afterwards.</p>
<pre class="code"><code>use io
println("Hello, World!")</code></pre>
</div>
</div>
<div id="nativecompiler">
<h2>Native Compiler</h2>
<p>Ground has recently added a Ground->Native compiler which allows much faster execution of Ground programs.</p>
<p>However, this is quite early in development, and only supports some features:</p>
<ul>
<li>int data type - No other data type is currently supported.</li>
<li>No functions at present</li>
</ul>
<p>To try the native compiler, use this command:</p>
<pre class="code"><code>solstice program.sols --output program --type native</code></pre>
<h3>Debugging</h3>
<p>Solstice will create a temporary folder in your current directory which you can remove called ".(outputname)_solsbuild". In this folder is the assembly and object file generated by the compiler. If you think that there's a bug with Ground or Solstice, you can use these to find the issue.</p>
</div>
</div>
</div>

View File

@@ -14,7 +14,7 @@
<img src="https://sols.dev/solstice.svg" width="200" height="200" alt="Solstice logo"></img>
<h1>Solstice</h1>
<p class="big">A programming language focused on ease of use.</p>
<button onclick="window.location.href = 'https://chsp.au/max/solstice'">View Code</button>
<button onclick="window.location.href = 'https://chookspace.com/max/solstice'">View Code</button>
<button onclick="window.location.href = '#installing'">Install</button>
<button onclick="window.location.href = '/playground'">Try Online</button>
<button onclick="window.location.href = '/docs'">View Docs</button>
@@ -29,7 +29,7 @@
</div>
<div class="feature">
<h3>Built on Ground</h3>
<p>Solstice compiles for the Ground VM, a speedy, light platform.</p>
<p>Solstice compiles for the Ground VM, a speedy, light platform. It can even compile to a native executable.</p>
</div>
<div class="feature">
<h3>Simple syntax</h3>
@@ -90,12 +90,12 @@ while number < 100000 {
</div>
<div class="box" id="installing">
<h2>Getting Solstice</h2>
<p>Solstice is an in-development language, and you can find the latest code on the <a href="https://chsp.au/max/solstice">Git repository</a>. At present, the stability of Solstice is questionable, so don't trust it to handle your nuclear codes or anything like that yet.</p>
<p>Solstice is an in-development language, and you can find the latest code on the <a href="https://chookspace.com/max/solstice">Git repository</a>. At present, the stability of Solstice is questionable, so don't trust it to handle your nuclear codes or anything like that yet.</p>
<p>This script will automatically build and install Solstice and Ground from source for you, or update them if they are already installed.</p>
<pre class="code" style="overflow-y: auto">
<code>bash -c "$(curl -fsSL https://sols.dev/install.sh)"</code></pre>
<p>If you find any issues while trying Solstice, please report them <a href="https://chsp.au/max/solstice/issues">here</a>! Solstice needs all the help it can get.</p>
<p>Stable-ish builds are avaliable in <a href="https://chsp.au/max/solstice/releases">the releases tab</a> of the Git repository. These builds are likely to be more stable, but don't treat them as a stable branch yet.</p>
<p>If you find any issues while trying Solstice, please report them <a href="https://chookspace.com/max/solstice/issues">here</a>! Solstice needs all the help it can get.</p>
<p>Stable-ish builds are avaliable in <a href="https://chookspace.com/max/solstice/releases">the releases tab</a> of the Git repository. These builds are likely to be more stable, but don't treat them as a stable branch yet.</p>
<p>Once you've installed, <a href="/docs">read the docs</a> to get started.</p>
</div>
</div>

View File

@@ -18,9 +18,9 @@ then
exit 0;
fi
if ! command -v gmake 2>&1 >/dev/null
if ! command -v make 2>&1 >/dev/null
then
echo "gmake is not installed on your system. Install it with your package manager (or on macOS use xcode-select)"
echo "make is not installed on your system. Install it with your package manager (or on macOS use xcode-select)"
exit 0;
fi
@@ -60,8 +60,7 @@ then
git clone https://chookspace.com/max/solstice
cd solstice
make
sudo mkdir -p /usr/local/bin
sudo cp solstice /usr/local/bin/solstice
sudo make install
echo "Success!"
exit 0
fi
@@ -80,11 +79,13 @@ then
fi
echo "Updating Ground..."
git pull
make
make clean
make both
sudo make install
cd ..
echo "Updating Solstice..."
cd solstice
git pull
make clean
make
sudo cp solstice /usr/local/bin/solstice
sudo make install

2
node_modules/.mf/cf.json generated vendored
View File

@@ -1 +1 @@
{"httpProtocol":"HTTP/1.1","clientAcceptEncoding":"gzip, deflate, br","requestPriority":"","edgeRequestKeepAliveStatus":1,"requestHeaderNames":{},"clientTcpRtt":15,"colo":"SYD","asn":1221,"asOrganization":"Telstra Limited","country":"AU","isEUCountry":false,"city":"Sydney","continent":"OC","region":"New South Wales","regionCode":"NSW","timezone":"Australia/Sydney","longitude":"151.20732","latitude":"-33.86785","postalCode":"1001","tlsVersion":"TLSv1.3","tlsCipher":"AEAD-AES256-GCM-SHA384","tlsClientRandom":"VnosRll56NurYMmPAR45l8rG4I2Nklvmcb+fGaOXVTI=","tlsClientCiphersSha1":"kXrN3VEKDdzz2cPKTQaKzpxVTxQ=","tlsClientExtensionsSha1":"1eY97BUYYO8vDaTfHQywB1pcNdM=","tlsClientExtensionsSha1Le":"u4wtEMFQBY18l3BzHAvORm+KGRw=","tlsExportedAuthenticator":{"clientHandshake":"1dfbe7451ef201532a216471f87886dfd3d290b649ac6787f187e7a296c886e53a496bd6b59c693b87f2d5b78c90e5b4","serverHandshake":"f7b332d2f13f55a5ccd91cff8554173516c5141b77e217c37b7a2b1ee552da7c6a7abbb66b27c722d1adbfd96266d778","clientFinished":"01042563ecd01453b385f6679691fe23b1ba391e1d3faa8accca1c80dad3e39e69f8ceb924a9640b7b527f1c2dbddab9","serverFinished":"38937607097ad8fc3847b2cf632b60444be3233468e24bceaaf05ea263c7ea5bb3e8c62fedc65ad96ce62ffd3db9937e"},"tlsClientHelloLength":"1603","tlsClientAuth":{"certPresented":"0","certVerified":"NONE","certRevoked":"0","certIssuerDN":"","certSubjectDN":"","certIssuerDNRFC2253":"","certSubjectDNRFC2253":"","certIssuerDNLegacy":"","certSubjectDNLegacy":"","certSerial":"","certIssuerSerial":"","certSKI":"","certIssuerSKI":"","certFingerprintSHA1":"","certFingerprintSHA256":"","certNotBefore":"","certNotAfter":""},"verifiedBotCategory":"","botManagement":{"corporateProxy":false,"verifiedBot":false,"jsDetection":{"passed":false},"staticResource":false,"detectionIds":{},"score":99}}
{"httpProtocol":"HTTP/1.1","clientAcceptEncoding":"gzip, deflate, br","requestPriority":"","edgeRequestKeepAliveStatus":1,"requestHeaderNames":{},"clientTcpRtt":12,"colo":"SYD","asn":9443,"asOrganization":"Vocus","country":"AU","isEUCountry":false,"city":"Sydney","continent":"OC","region":"New South Wales","regionCode":"NSW","timezone":"Australia/Sydney","longitude":"151.20732","latitude":"-33.86785","postalCode":"1001","tlsVersion":"TLSv1.3","tlsCipher":"AEAD-AES256-GCM-SHA384","tlsClientRandom":"ZCFOIxx+dLjJKWNa9xLCxaSIHvshEBi9p5Ma3GkbD6Y=","tlsClientCiphersSha1":"kXrN3VEKDdzz2cPKTQaKzpxVTxQ=","tlsClientExtensionsSha1":"1eY97BUYYO8vDaTfHQywB1pcNdM=","tlsClientExtensionsSha1Le":"u4wtEMFQBY18l3BzHAvORm+KGRw=","tlsExportedAuthenticator":{"clientHandshake":"60c7a93668cf712955e55da8d87ad7d798dd50f3bd0f41cf6b50bd536330370c8d70f3c724a783da997a7ce56eb10942","serverHandshake":"a1387243818dc978c8e6191d9435d288d47c82a4c87c3727ee318328e68412165a11e528abea944087ca1463ad1dfeb5","clientFinished":"3187fbfafb25128e53194b2cc610611991652337efdaf72c36409d98dfd12ca3a8a01c6a4b3bec6b601abdd178673f94","serverFinished":"f55737956343d6a2de3e75a6297677de63f979c2a570fc887651fd9b0fa24a9671b4545cdec6cfab6ecd70e39f6b1aea"},"tlsClientHelloLength":"1603","tlsClientAuth":{"certPresented":"0","certVerified":"NONE","certRevoked":"0","certIssuerDN":"","certSubjectDN":"","certIssuerDNRFC2253":"","certSubjectDNRFC2253":"","certIssuerDNLegacy":"","certSubjectDNLegacy":"","certSerial":"","certIssuerSerial":"","certSKI":"","certIssuerSKI":"","certFingerprintSHA1":"","certFingerprintSHA256":"","certNotBefore":"","certNotAfter":""},"verifiedBotCategory":"","botManagement":{"corporateProxy":false,"verifiedBot":false,"jsDetection":{"passed":false},"staticResource":false,"detectionIds":{},"score":99}}

1
pkgs Submodule

Submodule pkgs added at 8e3f0bbc52

View File

@@ -16,6 +16,7 @@
<body>
<div class="box">
<h1>Solstice Playground</h1>
<h2>Broken right now. Sorry!</h2>
<textarea class="code" id="editor" spellcheck="false" placeholder="Enter Solstice code here..." rows="20">
puts "Hello from Solstice via WebAssembly!"

View File

@@ -1167,183 +1167,6 @@ function dbg(...args) {
assert(false, 'Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.');
};
var _abort = () => {
abort('native code called abort()');
};
var _emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
var getHeapMax = () =>
// Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
// for any code that deals with heap sizes, which would require special
// casing all heap size related code to treat 0 specially.
2147483648;
var growMemory = (size) => {
var b = wasmMemory.buffer;
var pages = (size - b.byteLength + 65535) / 65536;
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size
updateMemoryViews();
return 1 /*success*/;
} catch(e) {
err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`);
}
// implicit 0 return to save code size (caller will cast "undefined" into 0
// anyhow)
};
var _emscripten_resize_heap = (requestedSize) => {
var oldSize = HEAPU8.length;
// With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
requestedSize >>>= 0;
// With multithreaded builds, races can happen (another thread might increase the size
// in between), so return a failure, and let the caller retry.
assert(requestedSize > oldSize);
// Memory resize rules:
// 1. Always increase heap size to at least the requested size, rounded up
// to next page multiple.
// 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
// geometrically: increase the heap size according to
// MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
// overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
// 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
// linearly: increase the heap size by at least
// MEMORY_GROWTH_LINEAR_STEP bytes.
// 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
// MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
// 4. If we were unable to allocate as much memory, it may be due to
// over-eager decision to excessively reserve due to (3) above.
// Hence if an allocation fails, cut down on the amount of excess
// growth, in an attempt to succeed to perform a smaller allocation.
// A limit is set for how much we can grow. We should not exceed that
// (the wasm binary specifies it, so if we tried, we'd fail anyhow).
var maxHeapSize = getHeapMax();
if (requestedSize > maxHeapSize) {
err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
return false;
}
var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
// Loop through potential heap size increases. If we attempt a too eager
// reservation that fails, cut down on the attempted size and reserve a
// smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
// but limit overreserving (default to capping at +96MB overgrowth at most)
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
var replacement = growMemory(newSize);
if (replacement) {
return true;
}
}
err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);
return false;
};
var ENV = {
};
var getExecutableName = () => {
return thisProgram || './this.program';
};
var getEnvStrings = () => {
if (!getEnvStrings.strings) {
// Default values.
// Browser language detection #8751
var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8';
var env = {
'USER': 'web_user',
'LOGNAME': 'web_user',
'PATH': '/',
'PWD': '/',
'HOME': '/home/web_user',
'LANG': lang,
'_': getExecutableName()
};
// Apply the user-provided values, if any.
for (var x in ENV) {
// x is a key in ENV; if ENV[x] is undefined, that means it was
// explicitly set to be so. We allow user code to do that to
// force variables with default values to remain unset.
if (ENV[x] === undefined) delete env[x];
else env[x] = ENV[x];
}
var strings = [];
for (var x in env) {
strings.push(`${x}=${env[x]}`);
}
getEnvStrings.strings = strings;
}
return getEnvStrings.strings;
};
var stringToAscii = (str, buffer) => {
for (var i = 0; i < str.length; ++i) {
assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff));
HEAP8[buffer++] = str.charCodeAt(i);
}
// Null-terminate the string
HEAP8[buffer] = 0;
};
var _environ_get = (__environ, environ_buf) => {
var bufSize = 0;
getEnvStrings().forEach((string, i) => {
var ptr = environ_buf + bufSize;
HEAPU32[(((__environ)+(i*4))>>2)] = ptr;
stringToAscii(string, ptr);
bufSize += string.length + 1;
});
return 0;
};
var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
var strings = getEnvStrings();
HEAPU32[((penviron_count)>>2)] = strings.length;
var bufSize = 0;
strings.forEach((string) => bufSize += string.length + 1);
HEAPU32[((penviron_buf_size)>>2)] = bufSize;
return 0;
};
var runtimeKeepaliveCounter = 0;
var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
var _proc_exit = (code) => {
EXITSTATUS = code;
if (!keepRuntimeAlive()) {
Module['onExit']?.(code);
ABORT = true;
}
quit_(code, new ExitStatus(code));
};
/** @suppress {duplicate } */
/** @param {boolean|number=} implicit */
var exitJS = (status, implicit) => {
EXITSTATUS = status;
checkUnflushedContent();
// if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
if (keepRuntimeAlive() && !implicit) {
var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
readyPromiseReject(msg);
err(msg);
}
_proc_exit(status);
};
var _exit = exitJS;
var PATH = {
isAbs:(path) => path.charAt(0) === '/',
splitPath:(filename) => {
@@ -4208,6 +4031,367 @@ function dbg(...args) {
return stream;
},
};
function ___syscall_faccessat(dirfd, path, amode, flags) {
try {
path = SYSCALLS.getStr(path);
assert(flags === 0);
path = SYSCALLS.calculateAt(dirfd, path);
if (amode & ~7) {
// need a valid mode
return -28;
}
var lookup = FS.lookupPath(path, { follow: true });
var node = lookup.node;
if (!node) {
return -44;
}
var perms = '';
if (amode & 4) perms += 'r';
if (amode & 2) perms += 'w';
if (amode & 1) perms += 'x';
if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) {
return -2;
}
return 0;
} catch (e) {
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
return -e.errno;
}
}
function ___syscall_fcntl64(fd, cmd, varargs) {
SYSCALLS.varargs = varargs;
try {
var stream = SYSCALLS.getStreamFromFD(fd);
switch (cmd) {
case 0: {
var arg = SYSCALLS.get();
if (arg < 0) {
return -28;
}
while (FS.streams[arg]) {
arg++;
}
var newStream;
newStream = FS.dupStream(stream, arg);
return newStream.fd;
}
case 1:
case 2:
return 0; // FD_CLOEXEC makes no sense for a single process.
case 3:
return stream.flags;
case 4: {
var arg = SYSCALLS.get();
stream.flags |= arg;
return 0;
}
case 12: {
var arg = SYSCALLS.getp();
var offset = 0;
// We're always unlocked.
HEAP16[(((arg)+(offset))>>1)] = 2;
return 0;
}
case 13:
case 14:
return 0; // Pretend that the locking is successful.
}
return -28;
} catch (e) {
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
return -e.errno;
}
}
function ___syscall_ioctl(fd, op, varargs) {
SYSCALLS.varargs = varargs;
try {
var stream = SYSCALLS.getStreamFromFD(fd);
switch (op) {
case 21509: {
if (!stream.tty) return -59;
return 0;
}
case 21505: {
if (!stream.tty) return -59;
if (stream.tty.ops.ioctl_tcgets) {
var termios = stream.tty.ops.ioctl_tcgets(stream);
var argp = SYSCALLS.getp();
HEAP32[((argp)>>2)] = termios.c_iflag || 0;
HEAP32[(((argp)+(4))>>2)] = termios.c_oflag || 0;
HEAP32[(((argp)+(8))>>2)] = termios.c_cflag || 0;
HEAP32[(((argp)+(12))>>2)] = termios.c_lflag || 0;
for (var i = 0; i < 32; i++) {
HEAP8[(argp + i)+(17)] = termios.c_cc[i] || 0;
}
return 0;
}
return 0;
}
case 21510:
case 21511:
case 21512: {
if (!stream.tty) return -59;
return 0; // no-op, not actually adjusting terminal settings
}
case 21506:
case 21507:
case 21508: {
if (!stream.tty) return -59;
if (stream.tty.ops.ioctl_tcsets) {
var argp = SYSCALLS.getp();
var c_iflag = HEAP32[((argp)>>2)];
var c_oflag = HEAP32[(((argp)+(4))>>2)];
var c_cflag = HEAP32[(((argp)+(8))>>2)];
var c_lflag = HEAP32[(((argp)+(12))>>2)];
var c_cc = []
for (var i = 0; i < 32; i++) {
c_cc.push(HEAP8[(argp + i)+(17)]);
}
return stream.tty.ops.ioctl_tcsets(stream.tty, op, { c_iflag, c_oflag, c_cflag, c_lflag, c_cc });
}
return 0; // no-op, not actually adjusting terminal settings
}
case 21519: {
if (!stream.tty) return -59;
var argp = SYSCALLS.getp();
HEAP32[((argp)>>2)] = 0;
return 0;
}
case 21520: {
if (!stream.tty) return -59;
return -28; // not supported
}
case 21531: {
var argp = SYSCALLS.getp();
return FS.ioctl(stream, op, argp);
}
case 21523: {
// TODO: in theory we should write to the winsize struct that gets
// passed in, but for now musl doesn't read anything on it
if (!stream.tty) return -59;
if (stream.tty.ops.ioctl_tiocgwinsz) {
var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
var argp = SYSCALLS.getp();
HEAP16[((argp)>>1)] = winsize[0];
HEAP16[(((argp)+(2))>>1)] = winsize[1];
}
return 0;
}
case 21524: {
// TODO: technically, this ioctl call should change the window size.
// but, since emscripten doesn't have any concept of a terminal window
// yet, we'll just silently throw it away as we do TIOCGWINSZ
if (!stream.tty) return -59;
return 0;
}
case 21515: {
if (!stream.tty) return -59;
return 0;
}
default: return -28; // not supported
}
} catch (e) {
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
return -e.errno;
}
}
function ___syscall_openat(dirfd, path, flags, varargs) {
SYSCALLS.varargs = varargs;
try {
path = SYSCALLS.getStr(path);
path = SYSCALLS.calculateAt(dirfd, path);
var mode = varargs ? SYSCALLS.get() : 0;
return FS.open(path, flags, mode).fd;
} catch (e) {
if (typeof FS == 'undefined' || !(e.name === 'ErrnoError')) throw e;
return -e.errno;
}
}
var _abort = () => {
abort('native code called abort()');
};
var _emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num);
var getHeapMax = () =>
// Stay one Wasm page short of 4GB: while e.g. Chrome is able to allocate
// full 4GB Wasm memories, the size will wrap back to 0 bytes in Wasm side
// for any code that deals with heap sizes, which would require special
// casing all heap size related code to treat 0 specially.
2147483648;
var growMemory = (size) => {
var b = wasmMemory.buffer;
var pages = (size - b.byteLength + 65535) / 65536;
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
wasmMemory.grow(pages); // .grow() takes a delta compared to the previous size
updateMemoryViews();
return 1 /*success*/;
} catch(e) {
err(`growMemory: Attempted to grow heap from ${b.byteLength} bytes to ${size} bytes, but got error: ${e}`);
}
// implicit 0 return to save code size (caller will cast "undefined" into 0
// anyhow)
};
var _emscripten_resize_heap = (requestedSize) => {
var oldSize = HEAPU8.length;
// With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned.
requestedSize >>>= 0;
// With multithreaded builds, races can happen (another thread might increase the size
// in between), so return a failure, and let the caller retry.
assert(requestedSize > oldSize);
// Memory resize rules:
// 1. Always increase heap size to at least the requested size, rounded up
// to next page multiple.
// 2a. If MEMORY_GROWTH_LINEAR_STEP == -1, excessively resize the heap
// geometrically: increase the heap size according to
// MEMORY_GROWTH_GEOMETRIC_STEP factor (default +20%), At most
// overreserve by MEMORY_GROWTH_GEOMETRIC_CAP bytes (default 96MB).
// 2b. If MEMORY_GROWTH_LINEAR_STEP != -1, excessively resize the heap
// linearly: increase the heap size by at least
// MEMORY_GROWTH_LINEAR_STEP bytes.
// 3. Max size for the heap is capped at 2048MB-WASM_PAGE_SIZE, or by
// MAXIMUM_MEMORY, or by ASAN limit, depending on which is smallest
// 4. If we were unable to allocate as much memory, it may be due to
// over-eager decision to excessively reserve due to (3) above.
// Hence if an allocation fails, cut down on the amount of excess
// growth, in an attempt to succeed to perform a smaller allocation.
// A limit is set for how much we can grow. We should not exceed that
// (the wasm binary specifies it, so if we tried, we'd fail anyhow).
var maxHeapSize = getHeapMax();
if (requestedSize > maxHeapSize) {
err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
return false;
}
var alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
// Loop through potential heap size increases. If we attempt a too eager
// reservation that fails, cut down on the attempted size and reserve a
// smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
// but limit overreserving (default to capping at +96MB overgrowth at most)
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
var replacement = growMemory(newSize);
if (replacement) {
return true;
}
}
err(`Failed to grow the heap from ${oldSize} bytes to ${newSize} bytes, not enough memory!`);
return false;
};
var ENV = {
};
var getExecutableName = () => {
return thisProgram || './this.program';
};
var getEnvStrings = () => {
if (!getEnvStrings.strings) {
// Default values.
// Browser language detection #8751
var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8';
var env = {
'USER': 'web_user',
'LOGNAME': 'web_user',
'PATH': '/',
'PWD': '/',
'HOME': '/home/web_user',
'LANG': lang,
'_': getExecutableName()
};
// Apply the user-provided values, if any.
for (var x in ENV) {
// x is a key in ENV; if ENV[x] is undefined, that means it was
// explicitly set to be so. We allow user code to do that to
// force variables with default values to remain unset.
if (ENV[x] === undefined) delete env[x];
else env[x] = ENV[x];
}
var strings = [];
for (var x in env) {
strings.push(`${x}=${env[x]}`);
}
getEnvStrings.strings = strings;
}
return getEnvStrings.strings;
};
var stringToAscii = (str, buffer) => {
for (var i = 0; i < str.length; ++i) {
assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff));
HEAP8[buffer++] = str.charCodeAt(i);
}
// Null-terminate the string
HEAP8[buffer] = 0;
};
var _environ_get = (__environ, environ_buf) => {
var bufSize = 0;
getEnvStrings().forEach((string, i) => {
var ptr = environ_buf + bufSize;
HEAPU32[(((__environ)+(i*4))>>2)] = ptr;
stringToAscii(string, ptr);
bufSize += string.length + 1;
});
return 0;
};
var _environ_sizes_get = (penviron_count, penviron_buf_size) => {
var strings = getEnvStrings();
HEAPU32[((penviron_count)>>2)] = strings.length;
var bufSize = 0;
strings.forEach((string) => bufSize += string.length + 1);
HEAPU32[((penviron_buf_size)>>2)] = bufSize;
return 0;
};
var runtimeKeepaliveCounter = 0;
var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0;
var _proc_exit = (code) => {
EXITSTATUS = code;
if (!keepRuntimeAlive()) {
Module['onExit']?.(code);
ABORT = true;
}
quit_(code, new ExitStatus(code));
};
/** @suppress {duplicate } */
/** @param {boolean|number=} implicit */
var exitJS = (status, implicit) => {
EXITSTATUS = status;
checkUnflushedContent();
// if exit() was called explicitly, warn the user if the runtime isn't actually being shut down
if (keepRuntimeAlive() && !implicit) {
var msg = `program exited (with status: ${status}), but keepRuntimeAlive() is set (counter=${runtimeKeepaliveCounter}) due to an async operation, so halting execution but not exiting the runtime or preventing further async execution (you can use emscripten_force_exit, if you want to force a true shutdown)`;
readyPromiseReject(msg);
err(msg);
}
_proc_exit(status);
};
var _exit = exitJS;
function _fd_close(fd) {
try {
@@ -4715,6 +4899,14 @@ var wasmImports = {
/** @export */
__cxa_throw: ___cxa_throw,
/** @export */
__syscall_faccessat: ___syscall_faccessat,
/** @export */
__syscall_fcntl64: ___syscall_fcntl64,
/** @export */
__syscall_ioctl: ___syscall_ioctl,
/** @export */
__syscall_openat: ___syscall_openat,
/** @export */
abort: _abort,
/** @export */
emscripten_memcpy_js: _emscripten_memcpy_js,

Binary file not shown.