From f36ff0f9bfba3c752f0e35124e517ffe6ccecfbb Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Sat, 9 May 2026 21:09:15 +1000 Subject: [PATCH] New docs built by mdbook --- docs/.nojekyll | 1 + docs/404.html | 225 +++ docs/ayu-highlight-3fdfc3ac.css | 77 + docs/book-a0b12cfe.js | 843 ++++++++++ docs/clipboard-1626706a.min.js | 7 + docs/comments.html | 262 +++ docs/css/chrome-ae938929.css | 756 +++++++++ docs/css/general-e4fbb323.css | 408 +++++ docs/css/print-9e4910d8.css | 50 + docs/css/variables-16ac1224.css | 445 +++++ docs/elasticlunr-ef4e11c1.min.js | 10 + docs/expressions.html | 531 ++++++ docs/favicon-9392e324.png | Bin 0 -> 10902 bytes docs/favicon-97ae436f.svg | 52 + docs/favicon.ico | Bin 180052 -> 0 bytes docs/fonts/fonts-6d524047.css | 1 + docs/function_definition.html | 295 ++++ docs/highlight-493f70e1.css | 83 + docs/highlight-d9401a48.js | 2630 ++++++++++++++++++++++++++++++ docs/highlight.js | 118 -- docs/index.css | 119 -- docs/index.html | 440 ++--- docs/introduction.html | 231 +++ docs/mark-09e88c2c.min.js | 7 + docs/node_modules/.mf/cf.json | 1 - docs/operators.html | 351 ++++ docs/print.html | 1028 ++++++++++++ docs/reserved_words.html | 257 +++ docs/scoping.html | 264 +++ docs/searcher-c2a407aa.js | 555 +++++++ docs/searchindex-c698e2a6.js | 1 + docs/struct_definition.html | 388 +++++ docs/toc-cb4e10de.js | 454 ++++++ docs/toc.html | 31 + docs/tomorrow-night-4c0ae647.css | 104 ++ docs/types.html | 296 ++++ docs/variables.html | 244 +++ 37 files changed, 11110 insertions(+), 455 deletions(-) create mode 100644 docs/.nojekyll create mode 100644 docs/404.html create mode 100644 docs/ayu-highlight-3fdfc3ac.css create mode 100644 docs/book-a0b12cfe.js create mode 100644 docs/clipboard-1626706a.min.js create mode 100644 docs/comments.html create mode 100644 docs/css/chrome-ae938929.css create mode 100644 docs/css/general-e4fbb323.css create mode 100644 docs/css/print-9e4910d8.css create mode 100644 docs/css/variables-16ac1224.css create mode 100644 docs/elasticlunr-ef4e11c1.min.js create mode 100644 docs/expressions.html create mode 100644 docs/favicon-9392e324.png create mode 100644 docs/favicon-97ae436f.svg delete mode 100644 docs/favicon.ico create mode 100644 docs/fonts/fonts-6d524047.css create mode 100644 docs/function_definition.html create mode 100644 docs/highlight-493f70e1.css create mode 100644 docs/highlight-d9401a48.js delete mode 100644 docs/highlight.js delete mode 100644 docs/index.css create mode 100644 docs/introduction.html create mode 100644 docs/mark-09e88c2c.min.js delete mode 100644 docs/node_modules/.mf/cf.json create mode 100644 docs/operators.html create mode 100644 docs/print.html create mode 100644 docs/reserved_words.html create mode 100644 docs/scoping.html create mode 100644 docs/searcher-c2a407aa.js create mode 100644 docs/searchindex-c698e2a6.js create mode 100644 docs/struct_definition.html create mode 100644 docs/toc-cb4e10de.js create mode 100644 docs/toc.html create mode 100644 docs/tomorrow-night-4c0ae647.css create mode 100644 docs/types.html create mode 100644 docs/variables.html diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..f173110 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ +This file makes sure that Github Pages doesn't process mdBook's output. diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..ae7b099 --- /dev/null +++ b/docs/404.html @@ -0,0 +1,225 @@ + + + + + + Page not found - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Document not found (404)

+

This URL is invalid, sorry. Please use the navigation bar or search to continue.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/ayu-highlight-3fdfc3ac.css b/docs/ayu-highlight-3fdfc3ac.css new file mode 100644 index 0000000..dba94b0 --- /dev/null +++ b/docs/ayu-highlight-3fdfc3ac.css @@ -0,0 +1,77 @@ +/* +Based off of the Ayu theme +Original by Dempfi (https://github.com/dempfi/ayu) +*/ + +.hljs { + display: block; + overflow-x: auto; + background: #191f26; + color: #e6e1cf; +} + +.hljs-comment, +.hljs-quote { + color: #5c6773; +} + +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr, +.hljs-regexp, +.hljs-link, +.hljs-selector-id, +.hljs-selector-class { + color: #ff7733; +} + +.hljs-number, +.hljs-meta, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #ffee99; +} + +.hljs-string, +.hljs-bullet { + color: #b8cc52; +} + +.hljs-title, +.hljs-built_in, +.hljs-section { + color: #ffb454; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-symbol { + color: #ff7733; +} + +.hljs-name { + color: #36a3d9; +} + +.hljs-tag { + color: #00568d; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-addition { + color: #91b362; +} + +.hljs-deletion { + color: #d96c75; +} diff --git a/docs/book-a0b12cfe.js b/docs/book-a0b12cfe.js new file mode 100644 index 0000000..62d7c4c --- /dev/null +++ b/docs/book-a0b12cfe.js @@ -0,0 +1,843 @@ +'use strict'; + +/* global default_theme, default_dark_theme, default_light_theme, hljs, ClipboardJS */ + +// Fix back button cache problem +window.onunload = function() { }; + +// Global variable, shared between modules +function playground_text(playground, hidden = true) { + const code_block = playground.querySelector('code'); + + if (window.ace && code_block.classList.contains('editable')) { + const editor = window.ace.edit(code_block); + return editor.getValue(); + } else if (hidden) { + return code_block.textContent; + } else { + return code_block.innerText; + } +} + +(function codeSnippets() { + function fetch_with_timeout(url, options, timeout = 6000) { + return Promise.race([ + fetch(url, options), + new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)), + ]); + } + + const playgrounds = Array.from(document.querySelectorAll('.playground')); + if (playgrounds.length > 0) { + fetch_with_timeout('https://play.rust-lang.org/meta/crates', { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + mode: 'cors', + }) + .then(response => response.json()) + .then(response => { + // get list of crates available in the rust playground + const playground_crates = response.crates.map(item => item['id']); + playgrounds.forEach(block => handle_crate_list_update(block, playground_crates)); + }); + } + + function handle_crate_list_update(playground_block, playground_crates) { + // update the play buttons after receiving the response + update_play_button(playground_block, playground_crates); + + // and install on change listener to dynamically update ACE editors + if (window.ace) { + const code_block = playground_block.querySelector('code'); + if (code_block.classList.contains('editable')) { + const editor = window.ace.edit(code_block); + editor.addEventListener('change', () => { + update_play_button(playground_block, playground_crates); + }); + // add Ctrl-Enter command to execute rust code + editor.commands.addCommand({ + name: 'run', + bindKey: { + win: 'Ctrl-Enter', + mac: 'Ctrl-Enter', + }, + exec: _editor => run_rust_code(playground_block), + }); + } + } + } + + // updates the visibility of play button based on `no_run` class and + // used crates vs ones available on https://play.rust-lang.org + function update_play_button(pre_block, playground_crates) { + const play_button = pre_block.querySelector('.play-button'); + + // skip if code is `no_run` + if (pre_block.querySelector('code').classList.contains('no_run')) { + play_button.classList.add('hidden'); + return; + } + + // get list of `extern crate`'s from snippet + const txt = playground_text(pre_block); + const re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g; + const snippet_crates = []; + let item; + while (item = re.exec(txt)) { + snippet_crates.push(item[1]); + } + + // check if all used crates are available on play.rust-lang.org + const all_available = snippet_crates.every(function(elem) { + return playground_crates.indexOf(elem) > -1; + }); + + if (all_available) { + play_button.classList.remove('hidden'); + play_button.hidden = false; + } else { + play_button.classList.add('hidden'); + } + } + + function run_rust_code(code_block) { + let result_block = code_block.querySelector('.result'); + if (!result_block) { + result_block = document.createElement('code'); + result_block.className = 'result hljs language-bash'; + + code_block.append(result_block); + } + + const text = playground_text(code_block); + const classes = code_block.querySelector('code').classList; + let edition = '2015'; + classes.forEach(className => { + if (className.startsWith('edition')) { + edition = className.slice(7); + } + }); + const params = { + version: 'stable', + optimize: '0', + code: text, + edition: edition, + }; + + if (text.indexOf('#![feature') !== -1) { + params.version = 'nightly'; + } + + result_block.innerText = 'Running...'; + + fetch_with_timeout('https://play.rust-lang.org/evaluate.json', { + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + mode: 'cors', + body: JSON.stringify(params), + }) + .then(response => response.json()) + .then(response => { + if (response.result.trim() === '') { + result_block.innerText = 'No output'; + result_block.classList.add('result-no-output'); + } else { + result_block.innerText = response.result; + result_block.classList.remove('result-no-output'); + } + }) + .catch(error => result_block.innerText = 'Playground Communication: ' + error.message); + } + + // Syntax highlighting Configuration + hljs.configure({ + tabReplace: ' ', // 4 spaces + languages: [], // Languages used for auto-detection + }); + + const code_nodes = Array + .from(document.querySelectorAll('code')) + // Don't highlight `inline code` blocks in headers. + .filter(function(node) { + return !node.parentElement.classList.contains('header'); + }); + + if (window.ace) { + // language-rust class needs to be removed for editable + // blocks or highlightjs will capture events + code_nodes + .filter(function(node) { + return node.classList.contains('editable'); + }) + .forEach(function(block) { + block.classList.remove('language-rust'); + }); + + code_nodes + .filter(function(node) { + return !node.classList.contains('editable'); + }) + .forEach(function(block) { + hljs.highlightBlock(block); + }); + } else { + code_nodes.forEach(function(block) { + hljs.highlightBlock(block); + }); + } + + // Adding the hljs class gives code blocks the color css + // even if highlighting doesn't apply + code_nodes.forEach(function(block) { + block.classList.add('hljs'); + }); + + Array.from(document.querySelectorAll('code.hljs')).forEach(function(block) { + + const lines = Array.from(block.querySelectorAll('.boring')); + // If no lines were hidden, return + if (!lines.length) { + return; + } + block.classList.add('hide-boring'); + + const buttons = document.createElement('div'); + buttons.className = 'buttons'; + buttons.innerHTML = ''; + buttons.firstChild.innerHTML = document.getElementById('fa-eye').innerHTML; + + // add expand button + const pre_block = block.parentNode; + pre_block.insertBefore(buttons, pre_block.firstChild); + + buttons.firstChild.addEventListener('click', function(e) { + if (this.title === 'Show hidden lines') { + this.innerHTML = document.getElementById('fa-eye-slash').innerHTML; + this.title = 'Hide lines'; + this.setAttribute('aria-label', e.target.title); + + block.classList.remove('hide-boring'); + } else if (this.title === 'Hide lines') { + this.innerHTML = document.getElementById('fa-eye').innerHTML; + this.title = 'Show hidden lines'; + this.setAttribute('aria-label', e.target.title); + + block.classList.add('hide-boring'); + } + }); + }); + + if (window.playground_copyable) { + Array.from(document.querySelectorAll('pre code')).forEach(function(block) { + const pre_block = block.parentNode; + if (!pre_block.classList.contains('playground')) { + let buttons = pre_block.querySelector('.buttons'); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + const clipButton = document.createElement('button'); + clipButton.className = 'clip-button'; + clipButton.title = 'Copy to clipboard'; + clipButton.setAttribute('aria-label', clipButton.title); + clipButton.innerHTML = ''; + + buttons.insertBefore(clipButton, buttons.firstChild); + } + }); + } + + // Process playground code blocks + Array.from(document.querySelectorAll('.playground')).forEach(function(pre_block) { + // Add play button + let buttons = pre_block.querySelector('.buttons'); + if (!buttons) { + buttons = document.createElement('div'); + buttons.className = 'buttons'; + pre_block.insertBefore(buttons, pre_block.firstChild); + } + + const runCodeButton = document.createElement('button'); + runCodeButton.className = 'play-button'; + runCodeButton.hidden = true; + runCodeButton.title = 'Run this code'; + runCodeButton.setAttribute('aria-label', runCodeButton.title); + runCodeButton.innerHTML = document.getElementById('fa-play').innerHTML; + + buttons.insertBefore(runCodeButton, buttons.firstChild); + runCodeButton.addEventListener('click', () => { + run_rust_code(pre_block); + }); + + if (window.playground_copyable) { + const copyCodeClipboardButton = document.createElement('button'); + copyCodeClipboardButton.className = 'clip-button'; + copyCodeClipboardButton.innerHTML = ''; + copyCodeClipboardButton.title = 'Copy to clipboard'; + copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title); + + buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild); + } + + const code_block = pre_block.querySelector('code'); + if (window.ace && code_block.classList.contains('editable')) { + const undoChangesButton = document.createElement('button'); + undoChangesButton.className = 'reset-button'; + undoChangesButton.title = 'Undo changes'; + undoChangesButton.setAttribute('aria-label', undoChangesButton.title); + undoChangesButton.innerHTML += + document.getElementById('fa-clock-rotate-left').innerHTML; + + buttons.insertBefore(undoChangesButton, buttons.firstChild); + + undoChangesButton.addEventListener('click', function() { + const editor = window.ace.edit(code_block); + editor.setValue(editor.originalCode); + editor.clearSelection(); + }); + } + }); +})(); + +(function themes() { + const html = document.querySelector('html'); + const themeToggleButton = document.getElementById('mdbook-theme-toggle'); + const themePopup = document.getElementById('mdbook-theme-list'); + const themeColorMetaTag = document.querySelector('meta[name="theme-color"]'); + const themeIds = []; + themePopup.querySelectorAll('button.theme').forEach(function(el) { + themeIds.push(el.id); + }); + const stylesheets = { + ayuHighlight: document.querySelector('#mdbook-ayu-highlight-css'), + tomorrowNight: document.querySelector('#mdbook-tomorrow-night-css'), + highlight: document.querySelector('#mdbook-highlight-css'), + }; + + function showThemes() { + themePopup.style.display = 'block'; + themeToggleButton.setAttribute('aria-expanded', true); + themePopup.querySelector('button#mdbook-theme-' + get_theme()).focus(); + } + + function updateThemeSelected() { + themePopup.querySelectorAll('.theme-selected').forEach(function(el) { + el.classList.remove('theme-selected'); + }); + const selected = get_saved_theme() ?? 'default_theme'; + let element = themePopup.querySelector('button#mdbook-theme-' + selected); + if (element === null) { + // Fall back in case there is no "Default" item. + element = themePopup.querySelector('button#mdbook-theme-' + get_theme()); + } + element.classList.add('theme-selected'); + } + + function hideThemes() { + themePopup.style.display = 'none'; + themeToggleButton.setAttribute('aria-expanded', false); + themeToggleButton.focus(); + } + + function get_saved_theme() { + let theme = null; + try { + theme = localStorage.getItem('mdbook-theme'); + } catch { + // ignore error. + } + return theme; + } + + function delete_saved_theme() { + localStorage.removeItem('mdbook-theme'); + } + + function get_theme() { + const theme = get_saved_theme(); + if (theme === null || theme === undefined || !themeIds.includes('mdbook-theme-' + theme)) { + if (typeof default_dark_theme === 'undefined') { + // A customized index.hbs might not define this, so fall back to + // old behavior of determining the default on page load. + return default_theme; + } + return window.matchMedia('(prefers-color-scheme: dark)').matches + ? default_dark_theme + : default_light_theme; + } else { + return theme; + } + } + + let previousTheme = default_theme; + function set_theme(theme, store = true) { + let ace_theme; + + if (theme === 'coal' || theme === 'navy') { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = false; + stylesheets.highlight.disabled = true; + + ace_theme = 'ace/theme/tomorrow_night'; + } else if (theme === 'ayu') { + stylesheets.ayuHighlight.disabled = false; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = true; + ace_theme = 'ace/theme/tomorrow_night'; + } else { + stylesheets.ayuHighlight.disabled = true; + stylesheets.tomorrowNight.disabled = true; + stylesheets.highlight.disabled = false; + ace_theme = 'ace/theme/dawn'; + } + + setTimeout(function() { + themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor; + }, 1); + + if (window.ace && window.editors) { + window.editors.forEach(function(editor) { + editor.setTheme(ace_theme); + }); + } + + if (store) { + try { + localStorage.setItem('mdbook-theme', theme); + } catch { + // ignore error. + } + } + + html.classList.remove(previousTheme); + html.classList.add(theme); + previousTheme = theme; + updateThemeSelected(); + } + + const query = window.matchMedia('(prefers-color-scheme: dark)'); + query.onchange = function() { + set_theme(get_theme(), false); + }; + + // Set theme. + set_theme(get_theme(), false); + + themeToggleButton.addEventListener('click', function() { + if (themePopup.style.display === 'block') { + hideThemes(); + } else { + showThemes(); + } + }); + + themePopup.addEventListener('click', function(e) { + let theme; + if (e.target.className === 'theme') { + theme = e.target.id; + } else if (e.target.parentElement.className === 'theme') { + theme = e.target.parentElement.id; + } else { + return; + } + theme = theme.replace(/^mdbook-theme-/, ''); + + if (theme === 'default_theme' || theme === null) { + delete_saved_theme(); + set_theme(get_theme(), false); + } else { + set_theme(theme); + } + }); + + themePopup.addEventListener('focusout', function(e) { + // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below) + if (!!e.relatedTarget && + !themeToggleButton.contains(e.relatedTarget) && + !themePopup.contains(e.relatedTarget) + ) { + hideThemes(); + } + }); + + // Should not be needed, but it works around an issue on macOS & iOS: + // https://github.com/rust-lang/mdBook/issues/628 + document.addEventListener('click', function(e) { + if (themePopup.style.display === 'block' && + !themeToggleButton.contains(e.target) && + !themePopup.contains(e.target) + ) { + hideThemes(); + } + }); + + document.addEventListener('keydown', function(e) { + if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { + return; + } + if (!themePopup.contains(e.target)) { + return; + } + + let li; + switch (e.key) { + case 'Escape': + e.preventDefault(); + hideThemes(); + break; + case 'ArrowUp': + e.preventDefault(); + li = document.activeElement.parentElement; + if (li && li.previousElementSibling) { + li.previousElementSibling.querySelector('button').focus(); + } + break; + case 'ArrowDown': + e.preventDefault(); + li = document.activeElement.parentElement; + if (li && li.nextElementSibling) { + li.nextElementSibling.querySelector('button').focus(); + } + break; + case 'Home': + e.preventDefault(); + themePopup.querySelector('li:first-child button').focus(); + break; + case 'End': + e.preventDefault(); + themePopup.querySelector('li:last-child button').focus(); + break; + } + }); +})(); + +(function sidebar() { + const sidebar = document.getElementById('mdbook-sidebar'); + const sidebarLinks = document.querySelectorAll('#mdbook-sidebar a'); + const sidebarToggleButton = document.getElementById('mdbook-sidebar-toggle'); + const sidebarResizeHandle = document.getElementById('mdbook-sidebar-resize-handle'); + const sidebarCheckbox = document.getElementById('mdbook-sidebar-toggle-anchor'); + let firstContact = null; + + + /* Because we cannot change the `display` using only CSS after/before the transition, we + need JS to do it. We change the display to prevent the browsers search to find text inside + the collapsed sidebar. */ + if (!document.documentElement.classList.contains('sidebar-visible')) { + sidebar.style.display = 'none'; + } + sidebar.addEventListener('transitionend', () => { + /* We only change the display to "none" if we're collapsing the sidebar. */ + if (!sidebarCheckbox.checked) { + sidebar.style.display = 'none'; + } + }); + sidebarToggleButton.addEventListener('click', () => { + /* To allow the sidebar expansion animation, we first need to put back the display. */ + if (!sidebarCheckbox.checked) { + sidebar.style.display = ''; + // Workaround for Safari skipping the animation when changing + // `display` and a transform in the same event loop. This forces a + // reflow after updating the display. + sidebar.offsetHeight; + } + }); + + function showSidebar() { + document.documentElement.classList.add('sidebar-visible'); + Array.from(sidebarLinks).forEach(function(link) { + link.setAttribute('tabIndex', 0); + }); + sidebarToggleButton.setAttribute('aria-expanded', true); + sidebar.setAttribute('aria-hidden', false); + try { + localStorage.setItem('mdbook-sidebar', 'visible'); + } catch { + // Ignore error. + } + } + + function hideSidebar() { + document.documentElement.classList.remove('sidebar-visible'); + Array.from(sidebarLinks).forEach(function(link) { + link.setAttribute('tabIndex', -1); + }); + sidebarToggleButton.setAttribute('aria-expanded', false); + sidebar.setAttribute('aria-hidden', true); + try { + localStorage.setItem('mdbook-sidebar', 'hidden'); + } catch { + // Ignore error. + } + } + + // Toggle sidebar + sidebarCheckbox.addEventListener('change', function sidebarToggle() { + if (sidebarCheckbox.checked) { + const current_width = parseInt( + document.documentElement.style.getPropertyValue('--sidebar-target-width'), 10); + if (current_width < 150) { + document.documentElement.style.setProperty('--sidebar-target-width', '150px'); + } + showSidebar(); + } else { + hideSidebar(); + } + }); + + sidebarResizeHandle.addEventListener('mousedown', initResize, false); + + function initResize() { + window.addEventListener('mousemove', resize, false); + window.addEventListener('mouseup', stopResize, false); + document.documentElement.classList.add('sidebar-resizing'); + } + function resize(e) { + let pos = e.clientX - sidebar.offsetLeft; + if (pos < 20) { + hideSidebar(); + } else { + if (!document.documentElement.classList.contains('sidebar-visible')) { + showSidebar(); + } + pos = Math.min(pos, window.innerWidth - 100); + document.documentElement.style.setProperty('--sidebar-target-width', pos + 'px'); + } + } + //on mouseup remove windows functions mousemove & mouseup + function stopResize() { + document.documentElement.classList.remove('sidebar-resizing'); + window.removeEventListener('mousemove', resize, false); + window.removeEventListener('mouseup', stopResize, false); + } + + document.addEventListener('touchstart', function(e) { + firstContact = { + x: e.touches[0].clientX, + time: Date.now(), + }; + }, { passive: true }); + + document.addEventListener('touchmove', function(e) { + if (!firstContact) { + return; + } + + const curX = e.touches[0].clientX; + const xDiff = curX - firstContact.x, + tDiff = Date.now() - firstContact.time; + + if (tDiff < 250 && Math.abs(xDiff) >= 150) { + if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300)) { + showSidebar(); + } else if (xDiff < 0 && curX < 300) { + hideSidebar(); + } + + firstContact = null; + } + }, { passive: true }); +})(); + +(function chapterNavigation() { + document.addEventListener('keydown', function(e) { + if (e.altKey || e.ctrlKey || e.metaKey) { + return; + } + if (window.search && window.search.hasFocus()) { + return; + } + const html = document.querySelector('html'); + + function next() { + const nextButton = document.querySelector('.nav-chapters.next'); + if (nextButton) { + window.location.href = nextButton.href; + } + } + function prev() { + const previousButton = document.querySelector('.nav-chapters.previous'); + if (previousButton) { + window.location.href = previousButton.href; + } + } + function showHelp() { + const container = document.getElementById('mdbook-help-container'); + const overlay = document.getElementById('mdbook-help-popup'); + container.style.display = 'flex'; + + // Clicking outside the popup will dismiss it. + const mouseHandler = event => { + if (overlay.contains(event.target)) { + return; + } + if (event.button !== 0) { + return; + } + event.preventDefault(); + event.stopPropagation(); + document.removeEventListener('mousedown', mouseHandler); + hideHelp(); + }; + + // Pressing esc will dismiss the popup. + const escapeKeyHandler = event => { + if (event.key === 'Escape') { + event.preventDefault(); + event.stopPropagation(); + document.removeEventListener('keydown', escapeKeyHandler, true); + hideHelp(); + } + }; + document.addEventListener('keydown', escapeKeyHandler, true); + document.getElementById('mdbook-help-container') + .addEventListener('mousedown', mouseHandler); + } + function hideHelp() { + document.getElementById('mdbook-help-container').style.display = 'none'; + } + + // Usually needs the Shift key to be pressed + switch (e.key) { + case '?': + e.preventDefault(); + showHelp(); + break; + } + + // Rest of the keys are only active when the Shift key is not pressed + if (e.shiftKey) { + return; + } + + switch (e.key) { + case 'ArrowRight': + e.preventDefault(); + if (html.dir === 'rtl') { + prev(); + } else { + next(); + } + break; + case 'ArrowLeft': + e.preventDefault(); + if (html.dir === 'rtl') { + next(); + } else { + prev(); + } + break; + } + }); +})(); + +(function clipboard() { + const clipButtons = document.querySelectorAll('.clip-button'); + + function hideTooltip(elem) { + elem.firstChild.innerText = ''; + elem.className = 'clip-button'; + } + + function showTooltip(elem, msg) { + elem.firstChild.innerText = msg; + elem.className = 'clip-button tooltipped'; + } + + const clipboardSnippets = new ClipboardJS('.clip-button', { + text: function(trigger) { + hideTooltip(trigger); + const playground = trigger.closest('pre'); + return playground_text(playground, false); + }, + }); + + Array.from(clipButtons).forEach(function(clipButton) { + clipButton.addEventListener('mouseout', function(e) { + hideTooltip(e.currentTarget); + }); + }); + + clipboardSnippets.on('success', function(e) { + e.clearSelection(); + showTooltip(e.trigger, 'Copied!'); + }); + + clipboardSnippets.on('error', function(e) { + showTooltip(e.trigger, 'Clipboard error!'); + }); +})(); + +(function scrollToTop() { + const menuTitle = document.querySelector('.menu-title'); + + menuTitle.addEventListener('click', function() { + document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' }); + }); +})(); + +(function controllMenu() { + const menu = document.getElementById('mdbook-menu-bar'); + + (function controllPosition() { + let scrollTop = document.scrollingElement.scrollTop; + let prevScrollTop = scrollTop; + const minMenuY = -menu.clientHeight - 50; + // When the script loads, the page can be at any scroll (e.g. if you refresh it). + menu.style.top = scrollTop + 'px'; + // Same as parseInt(menu.style.top.slice(0, -2), but faster + let topCache = menu.style.top.slice(0, -2); + menu.classList.remove('sticky'); + let stickyCache = false; // Same as menu.classList.contains('sticky'), but faster + document.addEventListener('scroll', function() { + scrollTop = Math.max(document.scrollingElement.scrollTop, 0); + // `null` means that it doesn't need to be updated + let nextSticky = null; + let nextTop = null; + const scrollDown = scrollTop > prevScrollTop; + const menuPosAbsoluteY = topCache - scrollTop; + if (scrollDown) { + nextSticky = false; + if (menuPosAbsoluteY > 0) { + nextTop = prevScrollTop; + } + } else { + if (menuPosAbsoluteY > 0) { + nextSticky = true; + } else if (menuPosAbsoluteY < minMenuY) { + nextTop = prevScrollTop + minMenuY; + } + } + if (nextSticky === true && stickyCache === false) { + menu.classList.add('sticky'); + stickyCache = true; + } else if (nextSticky === false && stickyCache === true) { + menu.classList.remove('sticky'); + stickyCache = false; + } + if (nextTop !== null) { + menu.style.top = nextTop + 'px'; + topCache = nextTop; + } + prevScrollTop = scrollTop; + }, { passive: true }); + })(); + (function controllBorder() { + function updateBorder() { + if (menu.offsetTop === 0) { + menu.classList.remove('bordered'); + } else { + menu.classList.add('bordered'); + } + } + updateBorder(); + document.addEventListener('scroll', updateBorder, { passive: true }); + })(); +})(); diff --git a/docs/clipboard-1626706a.min.js b/docs/clipboard-1626706a.min.js new file mode 100644 index 0000000..02c549e --- /dev/null +++ b/docs/clipboard-1626706a.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.4 + * https://zenorocha.github.io/clipboard.js + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return function(n){var o={};function r(t){if(o[t])return o[t].exports;var e=o[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,r),e.l=!0,e.exports}return r.m=n,r.c=o,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,n){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=function(){function o(t,e){for(var n=0;n + + + + + Comments - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Comments

+

Comments in Solstice can be done in 3 ways:

+

// (Single-Line Comment)

+

Use // to tell Solstice to ignore text until the end of the line.

+

This kind of comment should be used inside code to explain how parts of code work.

+

/* */ (Multiline Comment)

+

Use /* and */ to tell Solstice to ignore text in between the two markers.

+

This kind of comment should be used for explainations of how functions and structs work, placed above the definition.

+

# (Shebang Comment)

+

Use # to tell Solstice to ignore text until the end of the line.

+

This kind of comment should be used in a shebang (writing #!/usr/bin/env solstice at the top of your entry point source file), not in the middle.

+

Example

+
#!/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
+}
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/css/chrome-ae938929.css b/docs/css/chrome-ae938929.css new file mode 100644 index 0000000..bab3889 --- /dev/null +++ b/docs/css/chrome-ae938929.css @@ -0,0 +1,756 @@ +/* CSS for UI elements (a.k.a. chrome) */ + +html { + scrollbar-color: var(--scrollbar) transparent; +} +#mdbook-searchresults a, +.content a:link, +a:visited, +a > .hljs { + color: var(--links); +} + +/* + mdbook-body-container is necessary because mobile browsers don't seem to like + overflow-x on the body tag when there is a tag. +*/ +#mdbook-body-container { + /* + This is used when the sidebar pushes the body content off the side of + the screen on small screens. Without it, dragging on mobile Safari + will want to reposition the viewport in a weird way. + */ + overflow-x: clip; +} + +/* Menu Bar */ + +#mdbook-menu-bar, +#mdbook-menu-bar-hover-placeholder { + z-index: 101; + margin: auto calc(0px - var(--page-padding)); +} +#mdbook-menu-bar { + position: relative; + display: flex; + flex-wrap: wrap; + background-color: var(--bg); + border-block-end-color: var(--bg); + border-block-end-width: 1px; + border-block-end-style: solid; +} +#mdbook-menu-bar.sticky, +#mdbook-menu-bar-hover-placeholder:hover + #mdbook-menu-bar, +#mdbook-menu-bar:hover, +html.sidebar-visible #mdbook-menu-bar { + position: -webkit-sticky; + position: sticky; + top: 0 !important; +} +#mdbook-menu-bar-hover-placeholder { + position: sticky; + position: -webkit-sticky; + top: 0; + height: var(--menu-bar-height); +} +#mdbook-menu-bar.bordered { + border-block-end-color: var(--table-border-color); +} +#mdbook-menu-bar .fa-svg, #mdbook-menu-bar .icon-button { + position: relative; + padding: 0 8px; + z-index: 10; + line-height: var(--menu-bar-height); + cursor: pointer; + transition: color 0.5s; +} +@media only screen and (max-width: 420px) { + #mdbook-menu-bar .fa-svg, #mdbook-menu-bar .icon-button { + padding: 0 5px; + } +} + +.icon-button { + border: none; + background: none; + padding: 0; + color: inherit; +} +.icon-button .fa-svg { + margin: 0; +} + +.right-buttons { + margin: 0 15px; +} +.right-buttons a { + text-decoration: none; +} + +.left-buttons { + display: flex; + margin: 0 5px; +} +html:not(.js) .left-buttons button { + display: none; +} + +.menu-title { + display: inline-block; + font-weight: 200; + font-size: 2.4rem; + line-height: var(--menu-bar-height); + text-align: center; + margin: 0; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.menu-title { + cursor: pointer; +} + +.menu-bar, +.menu-bar:visited, +.nav-chapters, +.nav-chapters:visited, +.mobile-nav-chapters, +.mobile-nav-chapters:visited, +.menu-bar .icon-button, +.menu-bar a .fa-svg { + color: var(--icons); +} + +.menu-bar .fa-svg:hover, +.menu-bar .icon-button:hover, +.nav-chapters:hover, +.mobile-nav-chapters .fa-svg:hover { + color: var(--icons-hover); +} + +/* Nav Icons */ + +.nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + + position: fixed; + top: 0; + bottom: 0; + margin: 0; + max-width: 150px; + min-width: 90px; + + display: flex; + justify-content: center; + align-content: center; + flex-direction: column; + + transition: color 0.5s, background-color 0.5s; +} + +.nav-chapters:hover { + text-decoration: none; + background-color: var(--theme-hover); + transition: background-color 0.15s, color 0.15s; +} + +.nav-wrapper { + margin-block-start: 50px; + display: none; +} + +.mobile-nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + width: 90px; + border-radius: 5px; + background-color: var(--sidebar-bg); +} + +/* Only Firefox supports flow-relative values */ +.previous { float: left; } +[dir=rtl] .previous { float: right; } + +/* Only Firefox supports flow-relative values */ +.next { + float: right; + right: var(--page-padding); +} +[dir=rtl] .next { + float: left; + right: unset; + left: var(--page-padding); +} + +@media only screen and (max-width: 1080px) { + .nav-wide-wrapper { display: none; } + .nav-wrapper { display: block; } +} + +/* sidebar-visible */ +@media only screen and (max-width: 1380px) { + #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wide-wrapper { display: none; } + #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wrapper { display: block; } +} + +/* Inline code */ + +:not(pre) > .hljs { + display: inline; + padding: 0.1em 0.3em; + border-radius: 3px; +} + +:not(pre):not(a) > .hljs { + color: var(--inline-code-color); + overflow-x: initial; +} + +a:hover > .hljs { + text-decoration: underline; +} + +pre { + position: relative; +} +pre > .buttons { + position: absolute; + z-index: 100; + right: 0px; + top: 2px; + margin: 0px; + padding: 2px 0px; + + color: var(--sidebar-fg); + cursor: pointer; + visibility: hidden; + opacity: 0; + transition: visibility 0.1s linear, opacity 0.1s linear; +} +pre:hover > .buttons { + visibility: visible; + opacity: 1 +} +pre > .buttons :hover { + color: var(--sidebar-active); + border-color: var(--icons-hover); + background-color: var(--theme-hover); +} +pre > .buttons button { + cursor: inherit; + margin: 0px 5px; + padding: 2px 3px 0px 4px; + font-size: 23px; + + border-style: solid; + border-width: 1px; + border-radius: 4px; + border-color: var(--icons); + background-color: var(--theme-popup-bg); + transition: 100ms; + transition-property: color,border-color,background-color; + color: var(--icons); +} + +pre > .buttons button.clip-button { + padding: 2px 4px 0px 6px; +} +pre > .buttons button.clip-button::before { + /* clipboard image from octicons (https://github.com/primer/octicons/tree/v2.0.0) MIT license + */ + content: url('data:image/svg+xml,\ +\ +\ +'); + filter: var(--copy-button-filter); +} +pre > .buttons button.clip-button:hover::before { + filter: var(--copy-button-filter-hover); +} + +@media (pointer: coarse) { + pre > .buttons button { + /* On mobile, make it easier to tap buttons. */ + padding: 0.3rem 1rem; + } + + .sidebar-resize-indicator { + /* Hide resize indicator on devices with limited accuracy */ + display: none; + } +} +pre > code { + display: block; + padding: 1rem; +} + +/* FIXME: ACE editors overlap their buttons because ACE does absolute + positioning within the code block which breaks padding. The only solution I + can think of is to move the padding to the outer pre tag (or insert a div + wrapper), but that would require fixing a whole bunch of CSS rules. +*/ +.hljs.ace_editor { + padding: 0rem 0rem; +} + +pre > .result { + margin-block-start: 10px; +} + +/* Search */ + +#mdbook-searchresults a { + text-decoration: none; +} + +mark { + border-radius: 2px; + padding-block-start: 0; + padding-block-end: 1px; + padding-inline-start: 3px; + padding-inline-end: 3px; + margin-block-start: 0; + margin-block-end: -1px; + margin-inline-start: -3px; + margin-inline-end: -3px; + background-color: var(--search-mark-bg); + transition: background-color 300ms linear; + cursor: pointer; +} + +mark.fade-out { + background-color: rgba(0,0,0,0) !important; + cursor: auto; +} + +.searchbar-outer { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); +} + +#mdbook-searchbar-outer.searching #mdbook-searchbar { + padding-right: 30px; +} +#mdbook-searchbar-outer .spinner-wrapper { + display: none; +} +#mdbook-searchbar-outer.searching .spinner-wrapper { + display: block; +} + +.search-wrapper { + position: relative; +} + +.spinner-wrapper { + --spinner-margin: 2px; + position: absolute; + margin-block-start: calc(var(--searchbar-margin-block-start) + var(--spinner-margin)); + right: var(--spinner-margin); + top: 0; + bottom: var(--spinner-margin); + padding: 6px; + background-color: var(--bg); +} + +#fa-spin { + animation: rotating 2s linear infinite; + display: inline-block; +} + +@keyframes rotating { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +#mdbook-searchbar { + width: 100%; + margin-block-start: var(--searchbar-margin-block-start); + margin-block-end: 0; + margin-inline-start: auto; + margin-inline-end: auto; + padding: 10px 16px; + transition: box-shadow 300ms ease-in-out; + border: 1px solid var(--searchbar-border-color); + border-radius: 3px; + background-color: var(--searchbar-bg); + color: var(--searchbar-fg); +} +#mdbook-searchbar:focus, +#mdbook-searchbar.active { + box-shadow: 0 0 3px var(--searchbar-shadow-color); +} + +.searchresults-header { + font-weight: bold; + font-size: 1em; + padding-block-start: 18px; + padding-block-end: 0; + padding-inline-start: 5px; + padding-inline-end: 0; + color: var(--searchresults-header-fg); +} + +.searchresults-outer { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); + border-block-end: 1px dashed var(--searchresults-border-color); +} + +ul#mdbook-searchresults { + list-style: none; + padding-inline-start: 20px; +} +ul#mdbook-searchresults li { + margin: 10px 0px; + padding: 2px; + border-radius: 2px; +} +ul#mdbook-searchresults li.focus { + background-color: var(--searchresults-li-bg); +} +ul#mdbook-searchresults span.teaser { + display: block; + clear: both; + margin-block-start: 5px; + margin-block-end: 0; + margin-inline-start: 20px; + margin-inline-end: 0; + font-size: 0.8em; +} +ul#mdbook-searchresults span.teaser em { + font-weight: bold; + font-style: normal; +} + +/* Sidebar */ + +.sidebar { + position: fixed; + left: 0; + top: 0; + bottom: 0; + width: var(--sidebar-width); + font-size: 0.875em; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + overscroll-behavior-y: contain; + background-color: var(--sidebar-bg); + color: var(--sidebar-fg); +} +.sidebar-iframe-inner { + --padding: 10px; + + background-color: var(--sidebar-bg); + padding: var(--padding); + margin: 0; + font-size: 1.4rem; + color: var(--sidebar-fg); + min-height: calc(100vh - var(--padding) * 2); +} +.sidebar-iframe-outer { + border: none; + height: 100%; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} +[dir=rtl] .sidebar { left: unset; right: 0; } +.sidebar-resizing { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} +html:not(.sidebar-resizing) .sidebar { + transition: transform 0.3s; /* Animation: slide away */ +} +.sidebar code { + line-height: 2em; +} +.sidebar .sidebar-scrollbox { + overflow-y: auto; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: 10px 10px; +} +.sidebar .sidebar-resize-handle { + position: absolute; + cursor: col-resize; + width: 0; + right: calc(var(--sidebar-resize-indicator-width) * -1); + top: 0; + bottom: 0; + display: flex; + align-items: center; +} + +.sidebar-resize-handle .sidebar-resize-indicator { + width: 100%; + height: 16px; + color: var(--icons); + margin-inline-start: var(--sidebar-resize-indicator-space); + display: flex; + align-items: center; + justify-content: flex-start; +} +.sidebar-resize-handle .sidebar-resize-indicator::before { + content: ""; + width: 2px; + height: 12px; + border-left: dotted 2px currentColor; +} +.sidebar-resize-handle .sidebar-resize-indicator::after { + content: ""; + width: 2px; + height: 16px; + border-left: dotted 2px currentColor; +} + +[dir=rtl] .sidebar .sidebar-resize-handle { + left: calc(var(--sidebar-resize-indicator-width) * -1); + right: unset; +} +.js .sidebar .sidebar-resize-handle { + cursor: col-resize; + width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space)); +} + +html:not(.js) .sidebar-resize-handle { + display: none; +} + +/* sidebar-hidden */ +#mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar { + transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); +} +[dir=rtl] #mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar { + transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); +} +.sidebar::-webkit-scrollbar { + background: var(--sidebar-bg); +} +.sidebar::-webkit-scrollbar-thumb { + background: var(--scrollbar); +} + +/* sidebar-visible */ +#mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width))); +} +[dir=rtl] #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width))); +} +@media only screen and (min-width: 620px) { + #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: none; + margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)); + } + [dir=rtl] #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper { + transform: none; + } +} + +.chapter { + list-style: none outside none; + padding-inline-start: 0; + line-height: 2.2em; +} + +.chapter li { + color: var(--sidebar-non-existant); +} + +/* This is a span wrapping the chapter link and the fold chevron. */ +.chapter-link-wrapper { + /* Used to position the chevron to the right, allowing the text to wrap before it. */ + display: flex; +} + +.chapter li a { + /* Remove underlines. */ + text-decoration: none; + color: var(--sidebar-fg); +} + +.chapter li a:hover { + color: var(--sidebar-active); +} + +.chapter li a.active { + color: var(--sidebar-active); +} + +/* This is the toggle chevron. */ +.chapter-fold-toggle { + cursor: pointer; + /* Positions the chevron to the side. */ + margin-inline-start: auto; + padding: 0 10px; + user-select: none; + opacity: 0.68; +} + +.chapter-fold-toggle div { + transition: transform 0.5s; +} + +/* collapse the section */ +.chapter li:not(.expanded) > ol { + display: none; +} + +.chapter li.chapter-item { + line-height: 1.5em; + margin-block-start: 0.6em; +} + +/* When expanded, rotate the chevron to point down. */ +.chapter li.expanded > span > .chapter-fold-toggle div { + transform: rotate(90deg); +} + +.chapter a.current-header { + color: var(--sidebar-active); +} + +.on-this-page { + margin-left: 22px; + border-inline-start: 4px solid var(--sidebar-header-border-color); + padding-left: 8px; +} + +.on-this-page > ol { + padding-left: 0; +} + +/* Horizontal line in chapter list. */ +.spacer { + width: 100%; + height: 3px; + margin: 5px 0px; +} +.chapter .spacer { + background-color: var(--sidebar-spacer); +} + +/* On touch devices, add more vertical spacing to make it easier to tap links. */ +@media (-moz-touch-enabled: 1), (pointer: coarse) { + .chapter li a { padding: 5px 0; } + .spacer { margin: 10px 0; } +} + +.section { + list-style: none outside none; + padding-inline-start: 20px; + line-height: 1.9em; +} + +/* Theme Menu Popup */ + +.theme-popup { + position: absolute; + left: 10px; + top: var(--menu-bar-height); + z-index: 1000; + border-radius: 4px; + font-size: 0.7em; + color: var(--fg); + background: var(--theme-popup-bg); + border: 1px solid var(--theme-popup-border); + margin: 0; + padding: 0; + list-style: none; + display: none; + /* Don't let the children's background extend past the rounded corners. */ + overflow: hidden; +} +[dir=rtl] .theme-popup { left: unset; right: 10px; } +.theme-popup .default { + color: var(--icons); +} +.theme-popup .theme { + width: 100%; + border: 0; + margin: 0; + padding: 2px 20px; + line-height: 25px; + white-space: nowrap; + text-align: start; + cursor: pointer; + color: inherit; + background: inherit; + font-size: inherit; +} +.theme-popup .theme:hover { + background-color: var(--theme-hover); +} + +.theme-selected::before { + display: inline-block; + content: "✓"; + margin-inline-start: -14px; + width: 14px; +} + +/* The container for the help popup that covers the whole window. */ +#mdbook-help-container { + /* Position and size for the whole window. */ + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + /* This uses flex layout (which is set in book.js), and centers the popup + in the window.*/ + display: none; + align-items: center; + justify-content: center; + z-index: 1000; + /* Dim out the book while the popup is visible. */ + background: var(--overlay-bg); +} + +/* The popup help box. */ +#mdbook-help-popup { + box-shadow: 0 4px 24px rgba(0,0,0,0.15); + min-width: 300px; + max-width: 500px; + width: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + background-color: var(--bg); + color: var(--fg); + border-width: 1px; + border-color: var(--theme-popup-border); + border-style: solid; + border-radius: 8px; + padding: 10px; +} + +.mdbook-help-title { + text-align: center; + /* mdbook's margin for h2 is way too large. */ + margin: 10px; +} diff --git a/docs/css/general-e4fbb323.css b/docs/css/general-e4fbb323.css new file mode 100644 index 0000000..974a73e --- /dev/null +++ b/docs/css/general-e4fbb323.css @@ -0,0 +1,408 @@ +/* Base styles and content styles */ + +:root { + /* Browser default font-size is 16px, this way 1 rem = 10px */ + font-size: 62.5%; + color-scheme: var(--color-scheme); +} + +html { + font-family: "Inter", sans-serif; + color: var(--fg); + background-color: var(--bg); + text-size-adjust: none; + -webkit-text-size-adjust: none; +} + +body { + margin: 0; + font-size: 1.6rem; + overflow-x: hidden; +} + +code { + font-family: var(--mono-font) !important; + font-size: var(--code-font-size); + direction: ltr !important; +} + +/* make long words/inline code not x overflow */ +main { + overflow-wrap: break-word; +} + +/* make wide tables scroll if they overflow */ +.table-wrapper { + overflow-x: auto; +} + +/* Don't change font size in headers. */ +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + font-size: unset; +} + +.left { float: left; } +.right { float: right; } +.boring { opacity: 0.6; } +.hide-boring .boring { display: none; } +.hidden { display: none !important; } + +h2, h3 { margin-block-start: 2.5em; } +h4, h5 { margin-block-start: 2em; } + +.header + .header h3, +.header + .header h4, +.header + .header h5 { + margin-block-start: 1em; +} + +h1:target::before, +h2:target::before, +h3:target::before, +h4:target::before, +h5:target::before, +h6:target::before, +dt:target::before { + display: inline-block; + content: "»"; + margin-inline-start: -30px; + width: 30px; +} + +/* This is broken on Safari as of version 14, but is fixed + in Safari Technology Preview 117 which I think will be Safari 14.2. + https://bugs.webkit.org/show_bug.cgi?id=218076 +*/ +:target { + /* Safari does not support logical properties */ + scroll-margin-top: calc(var(--menu-bar-height) + 0.5em); +} + +.page { + outline: 0; + padding: 0 var(--page-padding); + margin-block-start: calc(0px - var(--menu-bar-height)); /* Compensate for the #mdbook-menu-bar-hover-placeholder */ +} +.page-wrapper { + box-sizing: border-box; + background-color: var(--bg); +} +html:not(.js) .page-wrapper, +.js:not(.sidebar-resizing) .page-wrapper { + transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ +} +[dir=rtl]:not(.js) .page-wrapper, +[dir=rtl].js:not(.sidebar-resizing) .page-wrapper { + transition: margin-right 0.3s ease, transform 0.3s ease; /* Animation: slide away */ +} + +.content { + overflow-y: auto; + padding: 0 5px 50px 5px; +} +.content main { + margin-inline-start: auto; + margin-inline-end: auto; + max-width: var(--content-max-width); +} +.content p { line-height: 1.45em; } +.content ol { line-height: 1.45em; } +.content ul { line-height: 1.45em; } +.content a { text-decoration: none; } +.content a:hover { text-decoration: underline; } +.content img, .content video { max-width: 100%; } +.content .header:link, +.content .header:visited { + color: var(--fg); +} +.content .header:link, +.content .header:visited:hover { + text-decoration: none; +} + +table { + margin: 0 auto; + border-collapse: collapse; +} +table td { + padding: 3px 20px; + border: 1px var(--table-border-color) solid; +} +table thead { + background: var(--table-header-bg); +} +table thead td { + font-weight: 700; + border: none; +} +table thead th { + padding: 3px 20px; +} +table thead tr { + border: 1px var(--table-header-bg) solid; +} +/* Alternate background colors for rows */ +table tbody tr:nth-child(2n) { + background: var(--table-alternate-bg); +} + + +blockquote { + margin: 20px 0; + padding: 0 20px; + color: var(--fg); + background-color: var(--quote-bg); + border-block-start: .1em solid var(--quote-border); + border-block-end: .1em solid var(--quote-border); +} + +/* TODO: Remove .warning in a future version of mdbook, it is replaced by +blockquote tags. */ +.warning { + margin: 20px; + padding: 0 20px; + border-inline-start: 2px solid var(--warning-border); +} + +.warning:before { + position: absolute; + width: 3rem; + height: 3rem; + margin-inline-start: calc(-1.5rem - 21px); + content: "ⓘ"; + text-align: center; + background-color: var(--bg); + color: var(--warning-border); + font-weight: bold; + font-size: 2rem; +} + +blockquote .warning:before { + background-color: var(--quote-bg); +} + +kbd { + background-color: var(--table-border-color); + border-radius: 4px; + border: solid 1px var(--theme-popup-border); + box-shadow: inset 0 -1px 0 var(--theme-hover); + display: inline-block; + font-size: var(--code-font-size); + font-family: var(--mono-font); + line-height: 10px; + padding: 4px 5px; + vertical-align: middle; +} + +sup { + /* Set the line-height for superscript and footnote references so that there + isn't an awkward space appearing above lines that contain the footnote. + + See https://github.com/rust-lang/mdBook/pull/2443#discussion_r1813773583 + for an explanation. + */ + line-height: 0; +} + +.footnote-definition { + font-size: 0.9em; +} +/* The default spacing for a list is a little too large. */ +.footnote-definition ul, +.footnote-definition ol { + padding-left: 20px; +} +.footnote-definition > li { + /* Required to position the ::before target */ + position: relative; +} +.footnote-definition > li:target { + scroll-margin-top: 50vh; +} +.footnote-reference:target { + scroll-margin-top: 50vh; +} +/* Draws a border around the footnote (including the marker) when it is selected. + TODO: If there are multiple linkbacks, highlight which one you just came + from so you know which one to click. +*/ +.footnote-definition > li:target::before { + border: 2px solid var(--footnote-highlight); + border-radius: 6px; + position: absolute; + top: -8px; + right: -8px; + bottom: -8px; + left: -32px; + pointer-events: none; + content: ""; +} +/* Pulses the footnote reference so you can quickly see where you left off reading. + This could use some improvement. +*/ +@media not (prefers-reduced-motion) { + .footnote-reference:target { + animation: fn-highlight 0.8s; + border-radius: 2px; + } + + @keyframes fn-highlight { + from { + background-color: var(--footnote-highlight); + } + } +} + +.tooltiptext { + position: absolute; + visibility: hidden; + color: #fff; + background-color: #333; + transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */ + left: -8px; /* Half of the width of the icon */ + top: -35px; + font-size: 0.8em; + text-align: center; + border-radius: 6px; + padding: 5px 8px; + margin: 5px; + z-index: 1000; +} +.tooltipped .tooltiptext { + visibility: visible; +} + +.chapter li.part-title { + color: var(--sidebar-fg); + margin: 5px 0px; + font-weight: bold; +} + +.result-no-output { + font-style: italic; +} + +.fa-svg svg { + width: 1em; + height: 1em; + fill: currentColor; + margin-bottom: -0.1em; +} + +dt { + font-weight: bold; + margin-top: 0.5em; + margin-bottom: 0.1em; +} + +/* This uses a CSS counter to add numbers to definitions, but only if there is + more than one definition. */ +dl, dt { + counter-reset: dd-counter; +} + +/* When there is more than one definition, increment the counter. The first +selector selects the first definition, and the second one selects definitions +2 and beyond.*/ +dd:has(+ dd), dd + dd { + counter-increment: dd-counter; + /* Use flex display to help with positioning the numbers when there is a p + tag inside the definition. */ + display: flex; + align-items: flex-start; +} + +/* Shows the counter for definitions. The first selector selects the first +definition, and the second one selections definitions 2 and beyond.*/ +dd:has(+ dd)::before, dd + dd::before { + content: counter(dd-counter) ". "; + font-weight: 600; + display: inline-block; + margin-right: 0.5em; +} + +dd > p { + /* For loose definitions that have a p tag inside, don't add a bunch of + space before the definition. */ + margin-top: 0; +} + +/* Remove some excess space from the bottom. */ +.blockquote-tag p:last-child { + margin-bottom: 2px; +} + +.blockquote-tag { + /* Add some padding to make the vertical bar a little taller than the text.*/ + padding: 2px 0px 2px 20px; + /* Add a solid color bar on the left side. */ + border-inline-start-style: solid; + border-inline-start-width: 4px; + /* Disable the background color from normal blockquotes . */ + background-color: inherit; + /* Disable border blocks from blockquotes. */ + border-block-start: none; + border-block-end: none; +} + +.blockquote-tag-title svg { + fill: currentColor; + /* Add space between the icon and the title. */ + margin-right: 8px; +} + +.blockquote-tag-note { + border-inline-start-color: var(--blockquote-note-color); +} + +.blockquote-tag-tip { + border-inline-start-color: var(--blockquote-tip-color); +} + +.blockquote-tag-important { + border-inline-start-color: var(--blockquote-important-color); +} + +.blockquote-tag-warning { + border-inline-start-color: var(--blockquote-warning-color); +} + +.blockquote-tag-caution { + border-inline-start-color: var(--blockquote-caution-color); +} + +.blockquote-tag-note .blockquote-tag-title { + color: var(--blockquote-note-color); +} + +.blockquote-tag-tip .blockquote-tag-title { + color: var(--blockquote-tip-color); +} + +.blockquote-tag-important .blockquote-tag-title { + color: var(--blockquote-important-color); +} + +.blockquote-tag-warning .blockquote-tag-title { + color: var(--blockquote-warning-color); +} + +.blockquote-tag-caution .blockquote-tag-title { + color: var(--blockquote-caution-color); +} + +.blockquote-tag-title { + /* Slightly increase the weight for more emphasis. */ + font-weight: 600; + /* Vertically center the icon with the text. */ + display: flex; + align-items: center; + /* Remove default large margins for a more compact display. */ + margin: 2px 0 8px 0; +} + +.blockquote-tag-title .fa-svg { + fill: currentColor; + /* Add some space between the icon and the text. */ + margin-right: 8px; +} diff --git a/docs/css/print-9e4910d8.css b/docs/css/print-9e4910d8.css new file mode 100644 index 0000000..2004384 --- /dev/null +++ b/docs/css/print-9e4910d8.css @@ -0,0 +1,50 @@ + +#mdbook-sidebar, +#mdbook-menu-bar, +.nav-chapters, +.mobile-nav-chapters { + display: none; +} + +#mdbook-page-wrapper.page-wrapper { + transform: none !important; + margin-inline-start: 0px; + overflow-y: initial; +} + +#mdbook-content { + max-width: none; + margin: 0; + padding: 0; +} + +.page { + overflow-y: initial; +} + +code { + direction: ltr !important; +} + +pre > .buttons { + z-index: 2; +} + +a, a:visited, a:active, a:hover { + color: #4183c4; + text-decoration: none; +} + +h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid; + page-break-after: avoid; +} + +pre, code { + page-break-inside: avoid; + white-space: pre-wrap; +} + +.fa { + display: none !important; +} diff --git a/docs/css/variables-16ac1224.css b/docs/css/variables-16ac1224.css new file mode 100644 index 0000000..1570bcb --- /dev/null +++ b/docs/css/variables-16ac1224.css @@ -0,0 +1,445 @@ + +/* Globals */ + +:root { + --sidebar-target-width: 300px; + --sidebar-width: min(var(--sidebar-target-width), 80vw); + --sidebar-resize-indicator-width: 8px; + --sidebar-resize-indicator-space: 2px; + --page-padding: 15px; + --content-max-width: 750px; + --menu-bar-height: 50px; + --mono-font: "JetBrains Mono", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace; + --code-font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */ + --searchbar-margin-block-start: 5px; +} + +/* Themes */ + +.ayu { + --bg: hsl(210, 25%, 8%); + --fg: #c5c5c5; + + --sidebar-bg: #14191f; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #5c6773; + --sidebar-active: #ffb454; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #0096cf; + + --inline-code-color: #ffb454; + + --theme-popup-bg: #14191f; + --theme-popup-border: #5c6773; + --theme-hover: #191f26; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(210, 25%, 13%); + --table-header-bg: hsl(210, 25%, 28%); + --table-alternate-bg: hsl(210, 25%, 11%); + + --searchbar-border-color: #848484; + --searchbar-bg: #424242; + --searchbar-fg: #fff; + --searchbar-shadow-color: #d4c89f; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #252932; + --search-mark-bg: #e3b171; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(45%) sepia(6%) saturate(621%) hue-rotate(198deg) brightness(99%) contrast(85%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%); + + --footnote-highlight: #2668a6; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #74b9ff; + --blockquote-tip-color: #09ca09; + --blockquote-important-color: #d3abff; + --blockquote-warning-color: #f0b72f; + --blockquote-caution-color: #f21424; + + --sidebar-header-border-color: #c18639; +} + +.coal { + --bg: hsl(200, 7%, 8%); + --fg: #98a3ad; + + --sidebar-bg: #292c2f; + --sidebar-fg: #a1adb8; + --sidebar-non-existant: #505254; + --sidebar-active: #3473ad; + --sidebar-spacer: #393939; + + --scrollbar: var(--sidebar-fg); + + --icons: #43484d; + --icons-hover: #b3c0cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #141617; + --theme-popup-border: #43484d; + --theme-hover: #1f2124; + + --quote-bg: hsl(234, 21%, 18%); + --quote-border: hsl(234, 21%, 23%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(200, 7%, 13%); + --table-header-bg: hsl(200, 7%, 28%); + --table-alternate-bg: hsl(200, 7%, 11%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #b7b7b7; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #98a3ad; + --searchresults-li-bg: #2b2b2f; + --search-mark-bg: #355c7d; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #08ae08; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #d91b29; + + --sidebar-header-border-color: #3473ad; +} + +.light, html:not(.js) { + --bg: hsl(0, 0%, 100%); + --fg: hsl(0, 0%, 0%); + + --sidebar-bg: #fafafa; + --sidebar-fg: hsl(0, 0%, 0%); + --sidebar-non-existant: #aaaaaa; + --sidebar-active: #1f1fff; + --sidebar-spacer: #f4f4f4; + + --scrollbar: #8F8F8F; + + --icons: #747474; + --icons-hover: #000000; + + --links: #20609f; + + --inline-code-color: #301900; + + --theme-popup-bg: #fafafa; + --theme-popup-border: #cccccc; + --theme-hover: #e6e6e6; + + --quote-bg: hsl(197, 37%, 96%); + --quote-border: hsl(197, 37%, 91%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(0, 0%, 95%); + --table-header-bg: hsl(0, 0%, 80%); + --table-alternate-bg: hsl(0, 0%, 97%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #fafafa; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #e4f2fe; + --search-mark-bg: #a2cff5; + + --color-scheme: light; + + /* Same as `--icons` */ + --copy-button-filter: invert(45.49%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%); + + --footnote-highlight: #7e7eff; + + --overlay-bg: rgba(200, 200, 205, 0.4); + + --blockquote-note-color: #0969da; + --blockquote-tip-color: #008000; + --blockquote-important-color: #8250df; + --blockquote-warning-color: #9a6700; + --blockquote-caution-color: #b52731; + + --sidebar-header-border-color: #6e6edb; +} + +.nnavy { + --bg: hsl(226, 23%, 11%); + --fg: #bcbdd0; + + --sidebar-bg: #282d3f; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #505274; + --sidebar-active: #2b79a2; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #161923; + --theme-popup-border: #737480; + --theme-hover: #282e40; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(226, 23%, 16%); + --table-header-bg: hsl(226, 23%, 31%); + --table-alternate-bg: hsl(226, 23%, 14%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #aeaec6; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #5f5f71; + --searchresults-border-color: #5c5c68; + --searchresults-li-bg: #242430; + --search-mark-bg: #a2cff5; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #09ca09; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #f21424; + + --sidebar-header-border-color: #2f6ab5; +} + +.rust { + --bg: hsl(60, 9%, 87%); + --fg: #262625; + + --sidebar-bg: #3b2e2a; + --sidebar-fg: #c8c9db; + --sidebar-non-existant: #505254; + --sidebar-active: #e69f67; + --sidebar-spacer: #45373a; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #262625; + + --links: #2b79a2; + + --inline-code-color: #6e6b5e; + + --theme-popup-bg: #e1e1db; + --theme-popup-border: #b38f6b; + --theme-hover: #99908a; + + --quote-bg: hsl(60, 5%, 75%); + --quote-border: hsl(60, 5%, 70%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(60, 9%, 82%); + --table-header-bg: #b3a497; + --table-alternate-bg: hsl(60, 9%, 84%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #fafafa; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #888; + --searchresults-li-bg: #dec2a2; + --search-mark-bg: #e69f67; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%); + + --footnote-highlight: #d3a17a; + + --overlay-bg: rgba(150, 150, 150, 0.25); + + --blockquote-note-color: #023b95; + --blockquote-tip-color: #007700; + --blockquote-important-color: #8250df; + --blockquote-warning-color: #603700; + --blockquote-caution-color: #aa1721; + + --sidebar-header-border-color: #8c391f; +} + +.navy { + --bg: #161031; + --fg: #ffffff; + + --sidebar-bg: #080511; + --sidebar-fg: #bebebf; + --sidebar-non-existant: #505274; + --sidebar-active: #a594f9; + --sidebar-spacer: #2d334f; + + --scrollbar: var(--sidebar-fg); + + --icons: #737480; + --icons-hover: #b7b9cc; + + --links: #a594f9; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #161923; + --theme-popup-border: #737480; + --theme-hover: #282e40; + + --quote-bg: hsl(226, 15%, 17%); + --quote-border: hsl(226, 15%, 22%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(226, 23%, 16%); + --table-header-bg: hsl(226, 23%, 31%); + --table-alternate-bg: hsl(226, 23%, 14%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #aeaec6; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #5f5f71; + --searchresults-border-color: #5c5c68; + --searchresults-li-bg: #242430; + --search-mark-bg: #a2cff5; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #09ca09; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #f21424; + + --sidebar-header-border-color: #000000; +} + + +@media (prefers-color-scheme: dark) { + html:not(.js) { + --bg: hsl(200, 7%, 8%); + --fg: #98a3ad; + + --sidebar-bg: #292c2f; + --sidebar-fg: #a1adb8; + --sidebar-non-existant: #505254; + --sidebar-active: #3473ad; + --sidebar-spacer: #393939; + + --scrollbar: var(--sidebar-fg); + + --icons: #43484d; + --icons-hover: #b3c0cc; + + --links: #2b79a2; + + --inline-code-color: #c5c8c6; + + --theme-popup-bg: #141617; + --theme-popup-border: #43484d; + --theme-hover: #1f2124; + + --quote-bg: hsl(234, 21%, 18%); + --quote-border: hsl(234, 21%, 23%); + + --warning-border: #ff8e00; + + --table-border-color: hsl(200, 7%, 13%); + --table-header-bg: hsl(200, 7%, 28%); + --table-alternate-bg: hsl(200, 7%, 11%); + + --searchbar-border-color: #aaa; + --searchbar-bg: #b7b7b7; + --searchbar-fg: #000; + --searchbar-shadow-color: #aaa; + --searchresults-header-fg: #666; + --searchresults-border-color: #98a3ad; + --searchresults-li-bg: #2b2b2f; + --search-mark-bg: #355c7d; + + --color-scheme: dark; + + /* Same as `--icons` */ + --copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%); + /* Same as `--sidebar-active` */ + --copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%); + + --footnote-highlight: #4079ae; + + --overlay-bg: rgba(33, 40, 48, 0.4); + + --blockquote-note-color: #4493f8; + --blockquote-tip-color: #08ae08; + --blockquote-important-color: #ab7df8; + --blockquote-warning-color: #d29922; + --blockquote-caution-color: #d91b29; + + --sidebar-header-border-color: #3473ad; + } +} diff --git a/docs/elasticlunr-ef4e11c1.min.js b/docs/elasticlunr-ef4e11c1.min.js new file mode 100644 index 0000000..94b20dd --- /dev/null +++ b/docs/elasticlunr-ef4e11c1.min.js @@ -0,0 +1,10 @@ +/** + * elasticlunr - http://weixsong.github.io + * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.5 + * + * Copyright (C) 2017 Oliver Nightingale + * Copyright (C) 2017 Wei Song + * MIT Licensed + * @license + */ +!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o + + + + + Expressions - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Expressions

+

An expression in Solstice is a combination of operators and values (whether literal or stored in a variable).;

+

Expression Types

+

“Precedence” is a number which dictates the order of execution. The higher the precedence, the sooner an expression will be evaluated.

+

Binary Mathematical

+
    +
  • +: Adds two numbers on either side, or concatenates two strings +
      +
    • Accepts: +
        +
      • Two integers either side
      • +
      • Two doubles either side
      • +
      • Two strings either side
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • The sum of both values as an integer if both values are integers
      • +
      • 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
      • +
      • The concatenated string when both values are strings
      • +
      +
    • +
    • Precedence: 5
    • +
    +
  • +
  • -: Subtracts two numbers on either side +
      +
    • Accepts: +
        +
      • Two integers either side
      • +
      • Two doubles either side
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • The difference of both values as an integer if both values are integers
      • +
      • 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
      • +
      +
    • +
    • Precedence: 5
    • +
    +
  • +
  • *: Multiplies two numbers on either side +
      +
    • Accepts: +
        +
      • Two integers either side
      • +
      • Two doubles either side
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • The product of both values as an integer if both values are integers
      • +
      • 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
      • +
      +
    • +
    • Precedence: 6
    • +
    +
  • +
  • /: Divides two numbers on either side +
      +
    • Accepts: +
        +
      • Two integers either side +
          +
        • Two doubles either side +
            +
          • An integer and a double on either side (order not significant)
          • +
          +
        • +
        +
      • +
      +
    • +
    • Returns: +
        +
      • The quotient of both values as an integer if both values are integers
      • +
      • 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
      • +
      +
    • +
    • Precedence: 6
    • +
    +
  • +
+

Binary Comparative

+
    +
  • ==: Checks two values to determine if they are equal +
      +
    • Accepts: +
        +
      • Any two values either side which are of the same type
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • true if both provided values are exactly the same.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • !=: Checks two values to determine if they are not equal +
      +
    • Accepts: +
        +
      • Any two values either side which are of the same type
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • true if both provided values are not exactly the same.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • >: Checks two numbers to determine which is greater +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is greater than the number provided on the right.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • <: Checks two numbers to determine which is lesser +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is lesser than the number provided on the right.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • >=: Checks two numbers to determine which is greater, or whether both are equal +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is greater than the number provided on the right, or if both numbers are equal.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • <=: Checks two numbers to determine which is lesser, or whether both are equal +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is lesser than the number provided on the right, or if both numbers are equal.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
+

Binary Misc

+
    +
  • as: Converts between types. +
      +
    • Accepts: +
        +
      • Any object on the left, and a type which has an applicable conversion defined by the object on the right
      • +
      +
    • +
    • Returns: +
        +
      • The object turned into the type on the right, in the way defined by the as-method
      • +
      +
    • +
    +
  • +
  • .: Accesses object fields +
      +
    • Accepts: +
        +
      • An object on the left, and an identifier on the right which corresponds to a field or method in the object
      • +
      +
    • +
    • Returns: +
        +
      • The object field or method the identifier corresponds to
      • +
      +
    • +
    +
  • +
+

Brackets

+
    +
  • (...): Evaluates an expression inside the brackets before outside expressions. +
      +
    • Accepts: +
        +
      • Any expression inside the brackets (in place of ...)
      • +
      +
    • +
    • Returns: +
        +
      • The result of the expression in the brackets
      • +
      +
    • +
    • Precedence: 7
    • +
    +
  • +
+

Function Call

+
    +
  • (...): Calls the specified function. +
      +
    • Accepts: +
        +
      • An identifier for the function before the brackets, then comma-seperated expressions corresponding to the function type signature (see Types -> Combined Types -> fun) inside the brackets (in place of ...)
      • +
      +
    • +
    • Returns: + +
    • +
    +
  • +
+

Unary Misc

+
    +
  • new: Creates a new object from a template. +
      +
    • Accepts: +
        +
      • A template after the new keyword.
      • +
      • A core type identifier
      • +
      +
    • +
    • Returns: +
        +
      • An object based on the provided template, if provided with a template.
      • +
      • The empty version of the core type, if provided with a core type, which is: +
          +
        • int: 0
        • +
        • double: 0.0
        • +
        • string: ""
        • +
        • char: '\0'
        • +
        • bool: false
        • +
        +
      • +
      +
    • +
    +
  • +
  • sizeof: Gets the size of something. +
      +
    • Accepts: +
        +
      • A string
      • +
      • An object with an int size field
      • +
      +
    • +
    • Returns: +
        +
      • The string length if provided a string
      • +
      • The int size field of the object if provided an object
      • +
      +
    • +
    +
  • +
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/favicon-9392e324.png b/docs/favicon-9392e324.png new file mode 100644 index 0000000000000000000000000000000000000000..73798d7dc1dfd3e22143f172940fb10e6540f007 GIT binary patch literal 10902 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⪼ZZmA^?stK0DO>*!2P7o=Qc(x6i!0VgitCZU3gV* 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 F{{grM%a8y7 literal 0 HcmV?d00001 diff --git a/docs/favicon-97ae436f.svg b/docs/favicon-97ae436f.svg new file mode 100644 index 0000000..d9bb21e --- /dev/null +++ b/docs/favicon-97ae436f.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + diff --git a/docs/favicon.ico b/docs/favicon.ico deleted file mode 100644 index 25578d681cbf64f0003bccb8485796b70ef5bbc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 180052 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 m + + + + + Function Definition - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + diff --git a/docs/highlight-493f70e1.css b/docs/highlight-493f70e1.css new file mode 100644 index 0000000..352c79b --- /dev/null +++ b/docs/highlight-493f70e1.css @@ -0,0 +1,83 @@ +/* + * An increased contrast highlighting scheme loosely based on the + * "Base16 Atelier Dune Light" theme by Bram de Haan + * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) + * Original Base16 color scheme by Chris Kempson + * (https://github.com/chriskempson/base16) + */ + +/* Comment */ +.hljs-comment, +.hljs-quote { + color: #575757; +} + +/* Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-attribute, +.hljs-attr, +.hljs-tag, +.hljs-name, +.hljs-regexp, +.hljs-link, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #d70025; +} + +/* Orange */ +.hljs-number, +.hljs-meta, +.hljs-built_in, +.hljs-builtin-name, +.hljs-literal, +.hljs-type, +.hljs-params { + color: #b21e00; +} + +/* Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet { + color: #008200; +} + +/* Blue */ +.hljs-title, +.hljs-section { + color: #0030f2; +} + +/* Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #9d00ec; +} + +.hljs { + display: block; + overflow-x: auto; + background: #f6f7f6; + color: #000; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-addition { + color: #22863a; + background-color: #f0fff4; +} + +.hljs-deletion { + color: #b31d28; + background-color: #ffeef0; +} diff --git a/docs/highlight-d9401a48.js b/docs/highlight-d9401a48.js new file mode 100644 index 0000000..e736ca7 --- /dev/null +++ b/docs/highlight-d9401a48.js @@ -0,0 +1,2630 @@ +/*! + Highlight.js v11.11.1 (git: 08cb242e7d) + (c) 2006-2025 Josh Goebel and other contributors + License: BSD-3-Clause + */ +var hljs = (function () { + 'use strict'; + + /* eslint-disable no-multi-assign */ + + function deepFreeze(obj) { + if (obj instanceof Map) { + obj.clear = + obj.delete = + obj.set = + function () { + throw new Error('map is read-only'); + }; + } else if (obj instanceof Set) { + obj.add = + obj.clear = + obj.delete = + function () { + throw new Error('set is read-only'); + }; + } + + // Freeze self + Object.freeze(obj); + + Object.getOwnPropertyNames(obj).forEach((name) => { + const prop = obj[name]; + const type = typeof prop; + + // Freeze prop if it is an object or function and also not already frozen + if ((type === 'object' || type === 'function') && !Object.isFrozen(prop)) { + deepFreeze(prop); + } + }); + + return obj; + } + + /** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */ + /** @typedef {import('highlight.js').CompiledMode} CompiledMode */ + /** @implements CallbackResponse */ + + class Response { + /** + * @param {CompiledMode} mode + */ + constructor(mode) { + // eslint-disable-next-line no-undefined + if (mode.data === undefined) mode.data = {}; + + this.data = mode.data; + this.isMatchIgnored = false; + } + + ignoreMatch() { + this.isMatchIgnored = true; + } + } + + /** + * @param {string} value + * @returns {string} + */ + function escapeHTML(value) { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + /** + * performs a shallow merge of multiple objects into one + * + * @template T + * @param {T} original + * @param {Record[]} objects + * @returns {T} a single new object + */ + function inherit$1(original, ...objects) { + /** @type Record */ + const result = Object.create(null); + + for (const key in original) { + result[key] = original[key]; + } + objects.forEach(function(obj) { + for (const key in obj) { + result[key] = obj[key]; + } + }); + return /** @type {T} */ (result); + } + + /** + * @typedef {object} Renderer + * @property {(text: string) => void} addText + * @property {(node: Node) => void} openNode + * @property {(node: Node) => void} closeNode + * @property {() => string} value + */ + + /** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */ + /** @typedef {{walk: (r: Renderer) => void}} Tree */ + /** */ + + const SPAN_CLOSE = ''; + + /** + * Determines if a node needs to be wrapped in + * + * @param {Node} node */ + const emitsWrappingTags = (node) => { + // rarely we can have a sublanguage where language is undefined + // TODO: track down why + return !!node.scope; + }; + + /** + * + * @param {string} name + * @param {{prefix:string}} options + */ + const scopeToCSSClass = (name, { prefix }) => { + // sub-language + if (name.startsWith("language:")) { + return name.replace("language:", "language-"); + } + // tiered scope: comment.line + if (name.includes(".")) { + const pieces = name.split("."); + return [ + `${prefix}${pieces.shift()}`, + ...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`)) + ].join(" "); + } + // simple scope + return `${prefix}${name}`; + }; + + /** @type {Renderer} */ + class HTMLRenderer { + /** + * Creates a new HTMLRenderer + * + * @param {Tree} parseTree - the parse tree (must support `walk` API) + * @param {{classPrefix: string}} options + */ + constructor(parseTree, options) { + this.buffer = ""; + this.classPrefix = options.classPrefix; + parseTree.walk(this); + } + + /** + * Adds texts to the output stream + * + * @param {string} text */ + addText(text) { + this.buffer += escapeHTML(text); + } + + /** + * Adds a node open to the output stream (if needed) + * + * @param {Node} node */ + openNode(node) { + if (!emitsWrappingTags(node)) return; + + const className = scopeToCSSClass(node.scope, + { prefix: this.classPrefix }); + this.span(className); + } + + /** + * Adds a node close to the output stream (if needed) + * + * @param {Node} node */ + closeNode(node) { + if (!emitsWrappingTags(node)) return; + + this.buffer += SPAN_CLOSE; + } + + /** + * returns the accumulated buffer + */ + value() { + return this.buffer; + } + + // helpers + + /** + * Builds a span element + * + * @param {string} className */ + span(className) { + this.buffer += ``; + } + } + + /** @typedef {{scope?: string, language?: string, children: Node[]} | string} Node */ + /** @typedef {{scope?: string, language?: string, children: Node[]} } DataNode */ + /** @typedef {import('highlight.js').Emitter} Emitter */ + /** */ + + /** @returns {DataNode} */ + const newNode = (opts = {}) => { + /** @type DataNode */ + const result = { children: [] }; + Object.assign(result, opts); + return result; + }; + + class TokenTree { + constructor() { + /** @type DataNode */ + this.rootNode = newNode(); + this.stack = [this.rootNode]; + } + + get top() { + return this.stack[this.stack.length - 1]; + } + + get root() { return this.rootNode; } + + /** @param {Node} node */ + add(node) { + this.top.children.push(node); + } + + /** @param {string} scope */ + openNode(scope) { + /** @type Node */ + const node = newNode({ scope }); + this.add(node); + this.stack.push(node); + } + + closeNode() { + if (this.stack.length > 1) { + return this.stack.pop(); + } + // eslint-disable-next-line no-undefined + return undefined; + } + + closeAllNodes() { + while (this.closeNode()); + } + + toJSON() { + return JSON.stringify(this.rootNode, null, 4); + } + + /** + * @typedef { import("./html_renderer").Renderer } Renderer + * @param {Renderer} builder + */ + walk(builder) { + // this does not + return this.constructor._walk(builder, this.rootNode); + // this works + // return TokenTree._walk(builder, this.rootNode); + } + + /** + * @param {Renderer} builder + * @param {Node} node + */ + static _walk(builder, node) { + if (typeof node === "string") { + builder.addText(node); + } else if (node.children) { + builder.openNode(node); + node.children.forEach((child) => this._walk(builder, child)); + builder.closeNode(node); + } + return builder; + } + + /** + * @param {Node} node + */ + static _collapse(node) { + if (typeof node === "string") return; + if (!node.children) return; + + if (node.children.every(el => typeof el === "string")) { + // node.text = node.children.join(""); + // delete node.children; + node.children = [node.children.join("")]; + } else { + node.children.forEach((child) => { + TokenTree._collapse(child); + }); + } + } + } + + /** + Currently this is all private API, but this is the minimal API necessary + that an Emitter must implement to fully support the parser. + + Minimal interface: + + - addText(text) + - __addSublanguage(emitter, subLanguageName) + - startScope(scope) + - endScope() + - finalize() + - toHTML() + + */ + + /** + * @implements {Emitter} + */ + class TokenTreeEmitter extends TokenTree { + /** + * @param {*} options + */ + constructor(options) { + super(); + this.options = options; + } + + /** + * @param {string} text + */ + addText(text) { + if (text === "") { return; } + + this.add(text); + } + + /** @param {string} scope */ + startScope(scope) { + this.openNode(scope); + } + + endScope() { + this.closeNode(); + } + + /** + * @param {Emitter & {root: DataNode}} emitter + * @param {string} name + */ + __addSublanguage(emitter, name) { + /** @type DataNode */ + const node = emitter.root; + if (name) node.scope = `language:${name}`; + + this.add(node); + } + + toHTML() { + const renderer = new HTMLRenderer(this, this.options); + return renderer.value(); + } + + finalize() { + this.closeAllNodes(); + return true; + } + } + + /** + * @param {string} value + * @returns {RegExp} + * */ + + /** + * @param {RegExp | string } re + * @returns {string} + */ + function source(re) { + if (!re) return null; + if (typeof re === "string") return re; + + return re.source; + } + + /** + * @param {RegExp | string } re + * @returns {string} + */ + function lookahead(re) { + return concat('(?=', re, ')'); + } + + /** + * @param {RegExp | string } re + * @returns {string} + */ + function anyNumberOfTimes(re) { + return concat('(?:', re, ')*'); + } + + /** + * @param {RegExp | string } re + * @returns {string} + */ + function optional(re) { + return concat('(?:', re, ')?'); + } + + /** + * @param {...(RegExp | string) } args + * @returns {string} + */ + function concat(...args) { + const joined = args.map((x) => source(x)).join(""); + return joined; + } + + /** + * @param { Array } args + * @returns {object} + */ + function stripOptionsFromArgs(args) { + const opts = args[args.length - 1]; + + if (typeof opts === 'object' && opts.constructor === Object) { + args.splice(args.length - 1, 1); + return opts; + } else { + return {}; + } + } + + /** @typedef { {capture?: boolean} } RegexEitherOptions */ + + /** + * Any of the passed expresssions may match + * + * Creates a huge this | this | that | that match + * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args + * @returns {string} + */ + function either(...args) { + /** @type { object & {capture?: boolean} } */ + const opts = stripOptionsFromArgs(args); + const joined = '(' + + (opts.capture ? "" : "?:") + + args.map((x) => source(x)).join("|") + ")"; + return joined; + } + + /** + * @param {RegExp | string} re + * @returns {number} + */ + function countMatchGroups(re) { + return (new RegExp(re.toString() + '|')).exec('').length - 1; + } + + /** + * Does lexeme start with a regular expression match at the beginning + * @param {RegExp} re + * @param {string} lexeme + */ + function startsWith(re, lexeme) { + const match = re && re.exec(lexeme); + return match && match.index === 0; + } + + // BACKREF_RE matches an open parenthesis or backreference. To avoid + // an incorrect parse, it additionally matches the following: + // - [...] elements, where the meaning of parentheses and escapes change + // - other escape sequences, so we do not misparse escape sequences as + // interesting elements + // - non-matching or lookahead parentheses, which do not capture. These + // follow the '(' with a '?'. + const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./; + + // **INTERNAL** Not intended for outside usage + // join logically computes regexps.join(separator), but fixes the + // backreferences so they continue to match. + // it also places each individual regular expression into it's own + // match group, keeping track of the sequencing of those match groups + // is currently an exercise for the caller. :-) + /** + * @param {(string | RegExp)[]} regexps + * @param {{joinWith: string}} opts + * @returns {string} + */ + function _rewriteBackreferences(regexps, { joinWith }) { + let numCaptures = 0; + + return regexps.map((regex) => { + numCaptures += 1; + const offset = numCaptures; + let re = source(regex); + let out = ''; + + while (re.length > 0) { + const match = BACKREF_RE.exec(re); + if (!match) { + out += re; + break; + } + out += re.substring(0, match.index); + re = re.substring(match.index + match[0].length); + if (match[0][0] === '\\' && match[1]) { + // Adjust the backreference. + out += '\\' + String(Number(match[1]) + offset); + } else { + out += match[0]; + if (match[0] === '(') { + numCaptures++; + } + } + } + return out; + }).map(re => `(${re})`).join(joinWith); + } + + /** @typedef {import('highlight.js').Mode} Mode */ + /** @typedef {import('highlight.js').ModeCallback} ModeCallback */ + + // Common regexps + const MATCH_NOTHING_RE = /\b\B/; + const IDENT_RE = '[a-zA-Z]\\w*'; + const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; + const NUMBER_RE = '\\b\\d+(\\.\\d+)?'; + const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float + const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b... + const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~'; + + /** + * @param { Partial & {binary?: string | RegExp} } opts + */ + const SHEBANG = (opts = {}) => { + const beginShebang = /^#![ ]*\//; + if (opts.binary) { + opts.begin = concat( + beginShebang, + /.*\b/, + opts.binary, + /\b.*/); + } + return inherit$1({ + scope: 'meta', + begin: beginShebang, + end: /$/, + relevance: 0, + /** @type {ModeCallback} */ + "on:begin": (m, resp) => { + if (m.index !== 0) resp.ignoreMatch(); + } + }, opts); + }; + + // Common modes + const BACKSLASH_ESCAPE = { + begin: '\\\\[\\s\\S]', relevance: 0 + }; + const APOS_STRING_MODE = { + scope: 'string', + begin: '\'', + end: '\'', + illegal: '\\n', + contains: [BACKSLASH_ESCAPE] + }; + const QUOTE_STRING_MODE = { + scope: 'string', + begin: '"', + end: '"', + illegal: '\\n', + contains: [BACKSLASH_ESCAPE] + }; + const PHRASAL_WORDS_MODE = { + begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ + }; + /** + * Creates a comment mode + * + * @param {string | RegExp} begin + * @param {string | RegExp} end + * @param {Mode | {}} [modeOptions] + * @returns {Partial} + */ + const COMMENT = function(begin, end, modeOptions = {}) { + const mode = inherit$1( + { + scope: 'comment', + begin, + end, + contains: [] + }, + modeOptions + ); + mode.contains.push({ + scope: 'doctag', + // hack to avoid the space from being included. the space is necessary to + // match here to prevent the plain text rule below from gobbling up doctags + begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)', + end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/, + excludeBegin: true, + relevance: 0 + }); + const ENGLISH_WORD = either( + // list of common 1 and 2 letter words in English + "I", + "a", + "is", + "so", + "us", + "to", + "at", + "if", + "in", + "it", + "on", + // note: this is not an exhaustive list of contractions, just popular ones + /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc + /[A-Za-z]+[-][a-z]+/, // `no-way`, etc. + /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences + ); + // looking like plain text, more likely to be a comment + mode.contains.push( + { + // TODO: how to include ", (, ) without breaking grammars that use these for + // comment delimiters? + // begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/ + // --- + + // this tries to find sequences of 3 english words in a row (without any + // "programming" type syntax) this gives us a strong signal that we've + // TRULY found a comment - vs perhaps scanning with the wrong language. + // It's possible to find something that LOOKS like the start of the + // comment - but then if there is no readable text - good chance it is a + // false match and not a comment. + // + // for a visual example please see: + // https://github.com/highlightjs/highlight.js/issues/2827 + + begin: concat( + /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */ + '(', + ENGLISH_WORD, + /[.]?[:]?([.][ ]|[ ])/, + '){3}') // look for 3 words in a row + } + ); + return mode; + }; + const C_LINE_COMMENT_MODE = COMMENT('//', '$'); + const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/'); + const HASH_COMMENT_MODE = COMMENT('#', '$'); + const NUMBER_MODE = { + scope: 'number', + begin: NUMBER_RE, + relevance: 0 + }; + const C_NUMBER_MODE = { + scope: 'number', + begin: C_NUMBER_RE, + relevance: 0 + }; + const BINARY_NUMBER_MODE = { + scope: 'number', + begin: BINARY_NUMBER_RE, + relevance: 0 + }; + const REGEXP_MODE = { + scope: "regexp", + begin: /\/(?=[^/\n]*\/)/, + end: /\/[gimuy]*/, + contains: [ + BACKSLASH_ESCAPE, + { + begin: /\[/, + end: /\]/, + relevance: 0, + contains: [BACKSLASH_ESCAPE] + } + ] + }; + const TITLE_MODE = { + scope: 'title', + begin: IDENT_RE, + relevance: 0 + }; + const UNDERSCORE_TITLE_MODE = { + scope: 'title', + begin: UNDERSCORE_IDENT_RE, + relevance: 0 + }; + const METHOD_GUARD = { + // excludes method names from keyword processing + begin: '\\.\\s*' + UNDERSCORE_IDENT_RE, + relevance: 0 + }; + + /** + * Adds end same as begin mechanics to a mode + * + * Your mode must include at least a single () match group as that first match + * group is what is used for comparison + * @param {Partial} mode + */ + const END_SAME_AS_BEGIN = function(mode) { + return Object.assign(mode, + { + /** @type {ModeCallback} */ + 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; }, + /** @type {ModeCallback} */ + 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); } + }); + }; + + var MODES = /*#__PURE__*/Object.freeze({ + __proto__: null, + APOS_STRING_MODE: APOS_STRING_MODE, + BACKSLASH_ESCAPE: BACKSLASH_ESCAPE, + BINARY_NUMBER_MODE: BINARY_NUMBER_MODE, + BINARY_NUMBER_RE: BINARY_NUMBER_RE, + COMMENT: COMMENT, + C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE, + C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE, + C_NUMBER_MODE: C_NUMBER_MODE, + C_NUMBER_RE: C_NUMBER_RE, + END_SAME_AS_BEGIN: END_SAME_AS_BEGIN, + HASH_COMMENT_MODE: HASH_COMMENT_MODE, + IDENT_RE: IDENT_RE, + MATCH_NOTHING_RE: MATCH_NOTHING_RE, + METHOD_GUARD: METHOD_GUARD, + NUMBER_MODE: NUMBER_MODE, + NUMBER_RE: NUMBER_RE, + PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE, + QUOTE_STRING_MODE: QUOTE_STRING_MODE, + REGEXP_MODE: REGEXP_MODE, + RE_STARTERS_RE: RE_STARTERS_RE, + SHEBANG: SHEBANG, + TITLE_MODE: TITLE_MODE, + UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE, + UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE + }); + + /** + @typedef {import('highlight.js').CallbackResponse} CallbackResponse + @typedef {import('highlight.js').CompilerExt} CompilerExt + */ + + // Grammar extensions / plugins + // See: https://github.com/highlightjs/highlight.js/issues/2833 + + // Grammar extensions allow "syntactic sugar" to be added to the grammar modes + // without requiring any underlying changes to the compiler internals. + + // `compileMatch` being the perfect small example of now allowing a grammar + // author to write `match` when they desire to match a single expression rather + // than being forced to use `begin`. The extension then just moves `match` into + // `begin` when it runs. Ie, no features have been added, but we've just made + // the experience of writing (and reading grammars) a little bit nicer. + + // ------ + + // TODO: We need negative look-behind support to do this properly + /** + * Skip a match if it has a preceding dot + * + * This is used for `beginKeywords` to prevent matching expressions such as + * `bob.keyword.do()`. The mode compiler automatically wires this up as a + * special _internal_ 'on:begin' callback for modes with `beginKeywords` + * @param {RegExpMatchArray} match + * @param {CallbackResponse} response + */ + function skipIfHasPrecedingDot(match, response) { + const before = match.input[match.index - 1]; + if (before === ".") { + response.ignoreMatch(); + } + } + + /** + * + * @type {CompilerExt} + */ + function scopeClassName(mode, _parent) { + // eslint-disable-next-line no-undefined + if (mode.className !== undefined) { + mode.scope = mode.className; + delete mode.className; + } + } + + /** + * `beginKeywords` syntactic sugar + * @type {CompilerExt} + */ + function beginKeywords(mode, parent) { + if (!parent) return; + if (!mode.beginKeywords) return; + + // for languages with keywords that include non-word characters checking for + // a word boundary is not sufficient, so instead we check for a word boundary + // or whitespace - this does no harm in any case since our keyword engine + // doesn't allow spaces in keywords anyways and we still check for the boundary + // first + mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)'; + mode.__beforeBegin = skipIfHasPrecedingDot; + mode.keywords = mode.keywords || mode.beginKeywords; + delete mode.beginKeywords; + + // prevents double relevance, the keywords themselves provide + // relevance, the mode doesn't need to double it + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 0; + } + + /** + * Allow `illegal` to contain an array of illegal values + * @type {CompilerExt} + */ + function compileIllegal(mode, _parent) { + if (!Array.isArray(mode.illegal)) return; + + mode.illegal = either(...mode.illegal); + } + + /** + * `match` to match a single expression for readability + * @type {CompilerExt} + */ + function compileMatch(mode, _parent) { + if (!mode.match) return; + if (mode.begin || mode.end) throw new Error("begin & end are not supported with match"); + + mode.begin = mode.match; + delete mode.match; + } + + /** + * provides the default 1 relevance to all modes + * @type {CompilerExt} + */ + function compileRelevance(mode, _parent) { + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 1; + } + + // allow beforeMatch to act as a "qualifier" for the match + // the full match begin must be [beforeMatch][begin] + const beforeMatchExt = (mode, parent) => { + if (!mode.beforeMatch) return; + // starts conflicts with endsParent which we need to make sure the child + // rule is not matched multiple times + if (mode.starts) throw new Error("beforeMatch cannot be used with starts"); + + const originalMode = Object.assign({}, mode); + Object.keys(mode).forEach((key) => { delete mode[key]; }); + + mode.keywords = originalMode.keywords; + mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin)); + mode.starts = { + relevance: 0, + contains: [ + Object.assign(originalMode, { endsParent: true }) + ] + }; + mode.relevance = 0; + + delete originalMode.beforeMatch; + }; + + // keywords that should have no default relevance value + const COMMON_KEYWORDS = [ + 'of', + 'and', + 'for', + 'in', + 'not', + 'or', + 'if', + 'then', + 'parent', // common variable name + 'list', // common variable name + 'value' // common variable name + ]; + + const DEFAULT_KEYWORD_SCOPE = "keyword"; + + /** + * Given raw keywords from a language definition, compile them. + * + * @param {string | Record | Array} rawKeywords + * @param {boolean} caseInsensitive + */ + function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) { + /** @type {import("highlight.js/private").KeywordDict} */ + const compiledKeywords = Object.create(null); + + // input can be a string of keywords, an array of keywords, or a object with + // named keys representing scopeName (which can then point to a string or array) + if (typeof rawKeywords === 'string') { + compileList(scopeName, rawKeywords.split(" ")); + } else if (Array.isArray(rawKeywords)) { + compileList(scopeName, rawKeywords); + } else { + Object.keys(rawKeywords).forEach(function(scopeName) { + // collapse all our objects back into the parent object + Object.assign( + compiledKeywords, + compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName) + ); + }); + } + return compiledKeywords; + + // --- + + /** + * Compiles an individual list of keywords + * + * Ex: "for if when while|5" + * + * @param {string} scopeName + * @param {Array} keywordList + */ + function compileList(scopeName, keywordList) { + if (caseInsensitive) { + keywordList = keywordList.map(x => x.toLowerCase()); + } + keywordList.forEach(function(keyword) { + const pair = keyword.split('|'); + compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])]; + }); + } + } + + /** + * Returns the proper score for a given keyword + * + * Also takes into account comment keywords, which will be scored 0 UNLESS + * another score has been manually assigned. + * @param {string} keyword + * @param {string} [providedScore] + */ + function scoreForKeyword(keyword, providedScore) { + // manual scores always win over common keywords + // so you can force a score of 1 if you really insist + if (providedScore) { + return Number(providedScore); + } + + return commonKeyword(keyword) ? 0 : 1; + } + + /** + * Determines if a given keyword is common or not + * + * @param {string} keyword */ + function commonKeyword(keyword) { + return COMMON_KEYWORDS.includes(keyword.toLowerCase()); + } + + /* + + For the reasoning behind this please see: + https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419 + + */ + + /** + * @type {Record} + */ + const seenDeprecations = {}; + + /** + * @param {string} message + */ + const error = (message) => { + console.error(message); + }; + + /** + * @param {string} message + * @param {any} args + */ + const warn = (message, ...args) => { + console.log(`WARN: ${message}`, ...args); + }; + + /** + * @param {string} version + * @param {string} message + */ + const deprecated = (version, message) => { + if (seenDeprecations[`${version}/${message}`]) return; + + console.log(`Deprecated as of ${version}. ${message}`); + seenDeprecations[`${version}/${message}`] = true; + }; + + /* eslint-disable no-throw-literal */ + + /** + @typedef {import('highlight.js').CompiledMode} CompiledMode + */ + + const MultiClassError = new Error(); + + /** + * Renumbers labeled scope names to account for additional inner match + * groups that otherwise would break everything. + * + * Lets say we 3 match scopes: + * + * { 1 => ..., 2 => ..., 3 => ... } + * + * So what we need is a clean match like this: + * + * (a)(b)(c) => [ "a", "b", "c" ] + * + * But this falls apart with inner match groups: + * + * (a)(((b)))(c) => ["a", "b", "b", "b", "c" ] + * + * Our scopes are now "out of alignment" and we're repeating `b` 3 times. + * What needs to happen is the numbers are remapped: + * + * { 1 => ..., 2 => ..., 5 => ... } + * + * We also need to know that the ONLY groups that should be output + * are 1, 2, and 5. This function handles this behavior. + * + * @param {CompiledMode} mode + * @param {Array} regexes + * @param {{key: "beginScope"|"endScope"}} opts + */ + function remapScopeNames(mode, regexes, { key }) { + let offset = 0; + const scopeNames = mode[key]; + /** @type Record */ + const emit = {}; + /** @type Record */ + const positions = {}; + + for (let i = 1; i <= regexes.length; i++) { + positions[i + offset] = scopeNames[i]; + emit[i + offset] = true; + offset += countMatchGroups(regexes[i - 1]); + } + // we use _emit to keep track of which match groups are "top-level" to avoid double + // output from inside match groups + mode[key] = positions; + mode[key]._emit = emit; + mode[key]._multi = true; + } + + /** + * @param {CompiledMode} mode + */ + function beginMultiClass(mode) { + if (!Array.isArray(mode.begin)) return; + + if (mode.skip || mode.excludeBegin || mode.returnBegin) { + error("skip, excludeBegin, returnBegin not compatible with beginScope: {}"); + throw MultiClassError; + } + + if (typeof mode.beginScope !== "object" || mode.beginScope === null) { + error("beginScope must be object"); + throw MultiClassError; + } + + remapScopeNames(mode, mode.begin, { key: "beginScope" }); + mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" }); + } + + /** + * @param {CompiledMode} mode + */ + function endMultiClass(mode) { + if (!Array.isArray(mode.end)) return; + + if (mode.skip || mode.excludeEnd || mode.returnEnd) { + error("skip, excludeEnd, returnEnd not compatible with endScope: {}"); + throw MultiClassError; + } + + if (typeof mode.endScope !== "object" || mode.endScope === null) { + error("endScope must be object"); + throw MultiClassError; + } + + remapScopeNames(mode, mode.end, { key: "endScope" }); + mode.end = _rewriteBackreferences(mode.end, { joinWith: "" }); + } + + /** + * this exists only to allow `scope: {}` to be used beside `match:` + * Otherwise `beginScope` would necessary and that would look weird + + { + match: [ /def/, /\w+/ ] + scope: { 1: "keyword" , 2: "title" } + } + + * @param {CompiledMode} mode + */ + function scopeSugar(mode) { + if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) { + mode.beginScope = mode.scope; + delete mode.scope; + } + } + + /** + * @param {CompiledMode} mode + */ + function MultiClass(mode) { + scopeSugar(mode); + + if (typeof mode.beginScope === "string") { + mode.beginScope = { _wrap: mode.beginScope }; + } + if (typeof mode.endScope === "string") { + mode.endScope = { _wrap: mode.endScope }; + } + + beginMultiClass(mode); + endMultiClass(mode); + } + + /** + @typedef {import('highlight.js').Mode} Mode + @typedef {import('highlight.js').CompiledMode} CompiledMode + @typedef {import('highlight.js').Language} Language + @typedef {import('highlight.js').HLJSPlugin} HLJSPlugin + @typedef {import('highlight.js').CompiledLanguage} CompiledLanguage + */ + + // compilation + + /** + * Compiles a language definition result + * + * Given the raw result of a language definition (Language), compiles this so + * that it is ready for highlighting code. + * @param {Language} language + * @returns {CompiledLanguage} + */ + function compileLanguage(language) { + /** + * Builds a regex with the case sensitivity of the current language + * + * @param {RegExp | string} value + * @param {boolean} [global] + */ + function langRe(value, global) { + return new RegExp( + source(value), + 'm' + + (language.case_insensitive ? 'i' : '') + + (language.unicodeRegex ? 'u' : '') + + (global ? 'g' : '') + ); + } + + /** + Stores multiple regular expressions and allows you to quickly search for + them all in a string simultaneously - returning the first match. It does + this by creating a huge (a|b|c) regex - each individual item wrapped with () + and joined by `|` - using match groups to track position. When a match is + found checking which position in the array has content allows us to figure + out which of the original regexes / match groups triggered the match. + + The match object itself (the result of `Regex.exec`) is returned but also + enhanced by merging in any meta-data that was registered with the regex. + This is how we keep track of which mode matched, and what type of rule + (`illegal`, `begin`, end, etc). + */ + class MultiRegex { + constructor() { + this.matchIndexes = {}; + // @ts-ignore + this.regexes = []; + this.matchAt = 1; + this.position = 0; + } + + // @ts-ignore + addRule(re, opts) { + opts.position = this.position++; + // @ts-ignore + this.matchIndexes[this.matchAt] = opts; + this.regexes.push([opts, re]); + this.matchAt += countMatchGroups(re) + 1; + } + + compile() { + if (this.regexes.length === 0) { + // avoids the need to check length every time exec is called + // @ts-ignore + this.exec = () => null; + } + const terminators = this.regexes.map(el => el[1]); + this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true); + this.lastIndex = 0; + } + + /** @param {string} s */ + exec(s) { + this.matcherRe.lastIndex = this.lastIndex; + const match = this.matcherRe.exec(s); + if (!match) { return null; } + + // eslint-disable-next-line no-undefined + const i = match.findIndex((el, i) => i > 0 && el !== undefined); + // @ts-ignore + const matchData = this.matchIndexes[i]; + // trim off any earlier non-relevant match groups (ie, the other regex + // match groups that make up the multi-matcher) + match.splice(0, i); + + return Object.assign(match, matchData); + } + } + + /* + Created to solve the key deficiently with MultiRegex - there is no way to + test for multiple matches at a single location. Why would we need to do + that? In the future a more dynamic engine will allow certain matches to be + ignored. An example: if we matched say the 3rd regex in a large group but + decided to ignore it - we'd need to started testing again at the 4th + regex... but MultiRegex itself gives us no real way to do that. + + So what this class creates MultiRegexs on the fly for whatever search + position they are needed. + + NOTE: These additional MultiRegex objects are created dynamically. For most + grammars most of the time we will never actually need anything more than the + first MultiRegex - so this shouldn't have too much overhead. + + Say this is our search group, and we match regex3, but wish to ignore it. + + regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0 + + What we need is a new MultiRegex that only includes the remaining + possibilities: + + regex4 | regex5 ' ie, startAt = 3 + + This class wraps all that complexity up in a simple API... `startAt` decides + where in the array of expressions to start doing the matching. It + auto-increments, so if a match is found at position 2, then startAt will be + set to 3. If the end is reached startAt will return to 0. + + MOST of the time the parser will be setting startAt manually to 0. + */ + class ResumableMultiRegex { + constructor() { + // @ts-ignore + this.rules = []; + // @ts-ignore + this.multiRegexes = []; + this.count = 0; + + this.lastIndex = 0; + this.regexIndex = 0; + } + + // @ts-ignore + getMatcher(index) { + if (this.multiRegexes[index]) return this.multiRegexes[index]; + + const matcher = new MultiRegex(); + this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts)); + matcher.compile(); + this.multiRegexes[index] = matcher; + return matcher; + } + + resumingScanAtSamePosition() { + return this.regexIndex !== 0; + } + + considerAll() { + this.regexIndex = 0; + } + + // @ts-ignore + addRule(re, opts) { + this.rules.push([re, opts]); + if (opts.type === "begin") this.count++; + } + + /** @param {string} s */ + exec(s) { + const m = this.getMatcher(this.regexIndex); + m.lastIndex = this.lastIndex; + let result = m.exec(s); + + // The following is because we have no easy way to say "resume scanning at the + // existing position but also skip the current rule ONLY". What happens is + // all prior rules are also skipped which can result in matching the wrong + // thing. Example of matching "booger": + + // our matcher is [string, "booger", number] + // + // ....booger.... + + // if "booger" is ignored then we'd really need a regex to scan from the + // SAME position for only: [string, number] but ignoring "booger" (if it + // was the first match), a simple resume would scan ahead who knows how + // far looking only for "number", ignoring potential string matches (or + // future "booger" matches that might be valid.) + + // So what we do: We execute two matchers, one resuming at the same + // position, but the second full matcher starting at the position after: + + // /--- resume first regex match here (for [number]) + // |/---- full match here for [string, "booger", number] + // vv + // ....booger.... + + // Which ever results in a match first is then used. So this 3-4 step + // process essentially allows us to say "match at this position, excluding + // a prior rule that was ignored". + // + // 1. Match "booger" first, ignore. Also proves that [string] does non match. + // 2. Resume matching for [number] + // 3. Match at index + 1 for [string, "booger", number] + // 4. If #2 and #3 result in matches, which came first? + if (this.resumingScanAtSamePosition()) { + if (result && result.index === this.lastIndex) ; else { // use the second matcher result + const m2 = this.getMatcher(0); + m2.lastIndex = this.lastIndex + 1; + result = m2.exec(s); + } + } + + if (result) { + this.regexIndex += result.position + 1; + if (this.regexIndex === this.count) { + // wrap-around to considering all matches again + this.considerAll(); + } + } + + return result; + } + } + + /** + * Given a mode, builds a huge ResumableMultiRegex that can be used to walk + * the content and find matches. + * + * @param {CompiledMode} mode + * @returns {ResumableMultiRegex} + */ + function buildModeRegex(mode) { + const mm = new ResumableMultiRegex(); + + mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: "begin" })); + + if (mode.terminatorEnd) { + mm.addRule(mode.terminatorEnd, { type: "end" }); + } + if (mode.illegal) { + mm.addRule(mode.illegal, { type: "illegal" }); + } + + return mm; + } + + /** skip vs abort vs ignore + * + * @skip - The mode is still entered and exited normally (and contains rules apply), + * but all content is held and added to the parent buffer rather than being + * output when the mode ends. Mostly used with `sublanguage` to build up + * a single large buffer than can be parsed by sublanguage. + * + * - The mode begin ands ends normally. + * - Content matched is added to the parent mode buffer. + * - The parser cursor is moved forward normally. + * + * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it + * never matched) but DOES NOT continue to match subsequent `contains` + * modes. Abort is bad/suboptimal because it can result in modes + * farther down not getting applied because an earlier rule eats the + * content but then aborts. + * + * - The mode does not begin. + * - Content matched by `begin` is added to the mode buffer. + * - The parser cursor is moved forward accordingly. + * + * @ignore - Ignores the mode (as if it never matched) and continues to match any + * subsequent `contains` modes. Ignore isn't technically possible with + * the current parser implementation. + * + * - The mode does not begin. + * - Content matched by `begin` is ignored. + * - The parser cursor is not moved forward. + */ + + /** + * Compiles an individual mode + * + * This can raise an error if the mode contains certain detectable known logic + * issues. + * @param {Mode} mode + * @param {CompiledMode | null} [parent] + * @returns {CompiledMode | never} + */ + function compileMode(mode, parent) { + const cmode = /** @type CompiledMode */ (mode); + if (mode.isCompiled) return cmode; + + [ + scopeClassName, + // do this early so compiler extensions generally don't have to worry about + // the distinction between match/begin + compileMatch, + MultiClass, + beforeMatchExt + ].forEach(ext => ext(mode, parent)); + + language.compilerExtensions.forEach(ext => ext(mode, parent)); + + // __beforeBegin is considered private API, internal use only + mode.__beforeBegin = null; + + [ + beginKeywords, + // do this later so compiler extensions that come earlier have access to the + // raw array if they wanted to perhaps manipulate it, etc. + compileIllegal, + // default to 1 relevance if not specified + compileRelevance + ].forEach(ext => ext(mode, parent)); + + mode.isCompiled = true; + + let keywordPattern = null; + if (typeof mode.keywords === "object" && mode.keywords.$pattern) { + // we need a copy because keywords might be compiled multiple times + // so we can't go deleting $pattern from the original on the first + // pass + mode.keywords = Object.assign({}, mode.keywords); + keywordPattern = mode.keywords.$pattern; + delete mode.keywords.$pattern; + } + keywordPattern = keywordPattern || /\w+/; + + if (mode.keywords) { + mode.keywords = compileKeywords(mode.keywords, language.case_insensitive); + } + + cmode.keywordPatternRe = langRe(keywordPattern, true); + + if (parent) { + if (!mode.begin) mode.begin = /\B|\b/; + cmode.beginRe = langRe(cmode.begin); + if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/; + if (mode.end) cmode.endRe = langRe(cmode.end); + cmode.terminatorEnd = source(cmode.end) || ''; + if (mode.endsWithParent && parent.terminatorEnd) { + cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd; + } + } + if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal)); + if (!mode.contains) mode.contains = []; + + mode.contains = [].concat(...mode.contains.map(function(c) { + return expandOrCloneMode(c === 'self' ? mode : c); + })); + mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); }); + + if (mode.starts) { + compileMode(mode.starts, parent); + } + + cmode.matcher = buildModeRegex(cmode); + return cmode; + } + + if (!language.compilerExtensions) language.compilerExtensions = []; + + // self is not valid at the top-level + if (language.contains && language.contains.includes('self')) { + throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation."); + } + + // we need a null object, which inherit will guarantee + language.classNameAliases = inherit$1(language.classNameAliases || {}); + + return compileMode(/** @type Mode */ (language)); + } + + /** + * Determines if a mode has a dependency on it's parent or not + * + * If a mode does have a parent dependency then often we need to clone it if + * it's used in multiple places so that each copy points to the correct parent, + * where-as modes without a parent can often safely be re-used at the bottom of + * a mode chain. + * + * @param {Mode | null} mode + * @returns {boolean} - is there a dependency on the parent? + * */ + function dependencyOnParent(mode) { + if (!mode) return false; + + return mode.endsWithParent || dependencyOnParent(mode.starts); + } + + /** + * Expands a mode or clones it if necessary + * + * This is necessary for modes with parental dependenceis (see notes on + * `dependencyOnParent`) and for nodes that have `variants` - which must then be + * exploded into their own individual modes at compile time. + * + * @param {Mode} mode + * @returns {Mode | Mode[]} + * */ + function expandOrCloneMode(mode) { + if (mode.variants && !mode.cachedVariants) { + mode.cachedVariants = mode.variants.map(function(variant) { + return inherit$1(mode, { variants: null }, variant); + }); + } + + // EXPAND + // if we have variants then essentially "replace" the mode with the variants + // this happens in compileMode, where this function is called from + if (mode.cachedVariants) { + return mode.cachedVariants; + } + + // CLONE + // if we have dependencies on parents then we need a unique + // instance of ourselves, so we can be reused with many + // different parents without issue + if (dependencyOnParent(mode)) { + return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null }); + } + + if (Object.isFrozen(mode)) { + return inherit$1(mode); + } + + // no special dependency issues, just return ourselves + return mode; + } + + var version = "11.11.1"; + + class HTMLInjectionError extends Error { + constructor(reason, html) { + super(reason); + this.name = "HTMLInjectionError"; + this.html = html; + } + } + + /* + Syntax highlighting with language autodetection. + https://highlightjs.org/ + */ + + + + /** + @typedef {import('highlight.js').Mode} Mode + @typedef {import('highlight.js').CompiledMode} CompiledMode + @typedef {import('highlight.js').CompiledScope} CompiledScope + @typedef {import('highlight.js').Language} Language + @typedef {import('highlight.js').HLJSApi} HLJSApi + @typedef {import('highlight.js').HLJSPlugin} HLJSPlugin + @typedef {import('highlight.js').PluginEvent} PluginEvent + @typedef {import('highlight.js').HLJSOptions} HLJSOptions + @typedef {import('highlight.js').LanguageFn} LanguageFn + @typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement + @typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext + @typedef {import('highlight.js/private').MatchType} MatchType + @typedef {import('highlight.js/private').KeywordData} KeywordData + @typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch + @typedef {import('highlight.js/private').AnnotatedError} AnnotatedError + @typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult + @typedef {import('highlight.js').HighlightOptions} HighlightOptions + @typedef {import('highlight.js').HighlightResult} HighlightResult + */ + + + const escape = escapeHTML; + const inherit = inherit$1; + const NO_MATCH = Symbol("nomatch"); + const MAX_KEYWORD_HITS = 7; + + /** + * @param {any} hljs - object that is extended (legacy) + * @returns {HLJSApi} + */ + const HLJS = function(hljs) { + // Global internal variables used within the highlight.js library. + /** @type {Record} */ + const languages = Object.create(null); + /** @type {Record} */ + const aliases = Object.create(null); + /** @type {HLJSPlugin[]} */ + const plugins = []; + + // safe/production mode - swallows more errors, tries to keep running + // even if a single syntax or parse hits a fatal error + let SAFE_MODE = true; + const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?"; + /** @type {Language} */ + const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] }; + + // Global options used when within external APIs. This is modified when + // calling the `hljs.configure` function. + /** @type HLJSOptions */ + let options = { + ignoreUnescapedHTML: false, + throwUnescapedHTML: false, + noHighlightRe: /^(no-?highlight)$/i, + languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i, + classPrefix: 'hljs-', + cssSelector: 'pre code', + languages: null, + // beta configuration options, subject to change, welcome to discuss + // https://github.com/highlightjs/highlight.js/issues/1086 + __emitter: TokenTreeEmitter + }; + + /* Utility functions */ + + /** + * Tests a language name to see if highlighting should be skipped + * @param {string} languageName + */ + function shouldNotHighlight(languageName) { + return options.noHighlightRe.test(languageName); + } + + /** + * @param {HighlightedHTMLElement} block - the HTML element to determine language for + */ + function blockLanguage(block) { + let classes = block.className + ' '; + + classes += block.parentNode ? block.parentNode.className : ''; + + // language-* takes precedence over non-prefixed class names. + const match = options.languageDetectRe.exec(classes); + if (match) { + const language = getLanguage(match[1]); + if (!language) { + warn(LANGUAGE_NOT_FOUND.replace("{}", match[1])); + warn("Falling back to no-highlight mode for this block.", block); + } + return language ? match[1] : 'no-highlight'; + } + + return classes + .split(/\s+/) + .find((_class) => shouldNotHighlight(_class) || getLanguage(_class)); + } + + /** + * Core highlighting function. + * + * OLD API + * highlight(lang, code, ignoreIllegals, continuation) + * + * NEW API + * highlight(code, {lang, ignoreIllegals}) + * + * @param {string} codeOrLanguageName - the language to use for highlighting + * @param {string | HighlightOptions} optionsOrCode - the code to highlight + * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail + * + * @returns {HighlightResult} Result - an object that represents the result + * @property {string} language - the language name + * @property {number} relevance - the relevance score + * @property {string} value - the highlighted HTML code + * @property {string} code - the original raw code + * @property {CompiledMode} top - top of the current mode stack + * @property {boolean} illegal - indicates whether any illegal matches were found + */ + function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) { + let code = ""; + let languageName = ""; + if (typeof optionsOrCode === "object") { + code = codeOrLanguageName; + ignoreIllegals = optionsOrCode.ignoreIllegals; + languageName = optionsOrCode.language; + } else { + // old API + deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated."); + deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"); + languageName = codeOrLanguageName; + code = optionsOrCode; + } + + // https://github.com/highlightjs/highlight.js/issues/3149 + // eslint-disable-next-line no-undefined + if (ignoreIllegals === undefined) { ignoreIllegals = true; } + + /** @type {BeforeHighlightContext} */ + const context = { + code, + language: languageName + }; + // the plugin can change the desired language or the code to be highlighted + // just be changing the object it was passed + fire("before:highlight", context); + + // a before plugin can usurp the result completely by providing it's own + // in which case we don't even need to call highlight + const result = context.result + ? context.result + : _highlight(context.language, context.code, ignoreIllegals); + + result.code = context.code; + // the plugin can change anything in result to suite it + fire("after:highlight", result); + + return result; + } + + /** + * private highlight that's used internally and does not fire callbacks + * + * @param {string} languageName - the language to use for highlighting + * @param {string} codeToHighlight - the code to highlight + * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail + * @param {CompiledMode?} [continuation] - current continuation mode, if any + * @returns {HighlightResult} - result of the highlight operation + */ + function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) { + const keywordHits = Object.create(null); + + /** + * Return keyword data if a match is a keyword + * @param {CompiledMode} mode - current mode + * @param {string} matchText - the textual match + * @returns {KeywordData | false} + */ + function keywordData(mode, matchText) { + return mode.keywords[matchText]; + } + + function processKeywords() { + if (!top.keywords) { + emitter.addText(modeBuffer); + return; + } + + let lastIndex = 0; + top.keywordPatternRe.lastIndex = 0; + let match = top.keywordPatternRe.exec(modeBuffer); + let buf = ""; + + while (match) { + buf += modeBuffer.substring(lastIndex, match.index); + const word = language.case_insensitive ? match[0].toLowerCase() : match[0]; + const data = keywordData(top, word); + if (data) { + const [kind, keywordRelevance] = data; + emitter.addText(buf); + buf = ""; + + keywordHits[word] = (keywordHits[word] || 0) + 1; + if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance; + if (kind.startsWith("_")) { + // _ implied for relevance only, do not highlight + // by applying a class name + buf += match[0]; + } else { + const cssClass = language.classNameAliases[kind] || kind; + emitKeyword(match[0], cssClass); + } + } else { + buf += match[0]; + } + lastIndex = top.keywordPatternRe.lastIndex; + match = top.keywordPatternRe.exec(modeBuffer); + } + buf += modeBuffer.substring(lastIndex); + emitter.addText(buf); + } + + function processSubLanguage() { + if (modeBuffer === "") return; + /** @type HighlightResult */ + let result = null; + + if (typeof top.subLanguage === 'string') { + if (!languages[top.subLanguage]) { + emitter.addText(modeBuffer); + return; + } + result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]); + continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top); + } else { + result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null); + } + + // Counting embedded language score towards the host language may be disabled + // with zeroing the containing mode relevance. Use case in point is Markdown that + // allows XML everywhere and makes every XML snippet to have a much larger Markdown + // score. + if (top.relevance > 0) { + relevance += result.relevance; + } + emitter.__addSublanguage(result._emitter, result.language); + } + + function processBuffer() { + if (top.subLanguage != null) { + processSubLanguage(); + } else { + processKeywords(); + } + modeBuffer = ''; + } + + /** + * @param {string} text + * @param {string} scope + */ + function emitKeyword(keyword, scope) { + if (keyword === "") return; + + emitter.startScope(scope); + emitter.addText(keyword); + emitter.endScope(); + } + + /** + * @param {CompiledScope} scope + * @param {RegExpMatchArray} match + */ + function emitMultiClass(scope, match) { + let i = 1; + const max = match.length - 1; + while (i <= max) { + if (!scope._emit[i]) { i++; continue; } + const klass = language.classNameAliases[scope[i]] || scope[i]; + const text = match[i]; + if (klass) { + emitKeyword(text, klass); + } else { + modeBuffer = text; + processKeywords(); + modeBuffer = ""; + } + i++; + } + } + + /** + * @param {CompiledMode} mode - new mode to start + * @param {RegExpMatchArray} match + */ + function startNewMode(mode, match) { + if (mode.scope && typeof mode.scope === "string") { + emitter.openNode(language.classNameAliases[mode.scope] || mode.scope); + } + if (mode.beginScope) { + // beginScope just wraps the begin match itself in a scope + if (mode.beginScope._wrap) { + emitKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap); + modeBuffer = ""; + } else if (mode.beginScope._multi) { + // at this point modeBuffer should just be the match + emitMultiClass(mode.beginScope, match); + modeBuffer = ""; + } + } + + top = Object.create(mode, { parent: { value: top } }); + return top; + } + + /** + * @param {CompiledMode } mode - the mode to potentially end + * @param {RegExpMatchArray} match - the latest match + * @param {string} matchPlusRemainder - match plus remainder of content + * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode + */ + function endOfMode(mode, match, matchPlusRemainder) { + let matched = startsWith(mode.endRe, matchPlusRemainder); + + if (matched) { + if (mode["on:end"]) { + const resp = new Response(mode); + mode["on:end"](match, resp); + if (resp.isMatchIgnored) matched = false; + } + + if (matched) { + while (mode.endsParent && mode.parent) { + mode = mode.parent; + } + return mode; + } + } + // even if on:end fires an `ignore` it's still possible + // that we might trigger the end node because of a parent mode + if (mode.endsWithParent) { + return endOfMode(mode.parent, match, matchPlusRemainder); + } + } + + /** + * Handle matching but then ignoring a sequence of text + * + * @param {string} lexeme - string containing full match text + */ + function doIgnore(lexeme) { + if (top.matcher.regexIndex === 0) { + // no more regexes to potentially match here, so we move the cursor forward one + // space + modeBuffer += lexeme[0]; + return 1; + } else { + // no need to move the cursor, we still have additional regexes to try and + // match at this very spot + resumeScanAtSamePosition = true; + return 0; + } + } + + /** + * Handle the start of a new potential mode match + * + * @param {EnhancedMatch} match - the current match + * @returns {number} how far to advance the parse cursor + */ + function doBeginMatch(match) { + const lexeme = match[0]; + const newMode = match.rule; + + const resp = new Response(newMode); + // first internal before callbacks, then the public ones + const beforeCallbacks = [newMode.__beforeBegin, newMode["on:begin"]]; + for (const cb of beforeCallbacks) { + if (!cb) continue; + cb(match, resp); + if (resp.isMatchIgnored) return doIgnore(lexeme); + } + + if (newMode.skip) { + modeBuffer += lexeme; + } else { + if (newMode.excludeBegin) { + modeBuffer += lexeme; + } + processBuffer(); + if (!newMode.returnBegin && !newMode.excludeBegin) { + modeBuffer = lexeme; + } + } + startNewMode(newMode, match); + return newMode.returnBegin ? 0 : lexeme.length; + } + + /** + * Handle the potential end of mode + * + * @param {RegExpMatchArray} match - the current match + */ + function doEndMatch(match) { + const lexeme = match[0]; + const matchPlusRemainder = codeToHighlight.substring(match.index); + + const endMode = endOfMode(top, match, matchPlusRemainder); + if (!endMode) { return NO_MATCH; } + + const origin = top; + if (top.endScope && top.endScope._wrap) { + processBuffer(); + emitKeyword(lexeme, top.endScope._wrap); + } else if (top.endScope && top.endScope._multi) { + processBuffer(); + emitMultiClass(top.endScope, match); + } else if (origin.skip) { + modeBuffer += lexeme; + } else { + if (!(origin.returnEnd || origin.excludeEnd)) { + modeBuffer += lexeme; + } + processBuffer(); + if (origin.excludeEnd) { + modeBuffer = lexeme; + } + } + do { + if (top.scope) { + emitter.closeNode(); + } + if (!top.skip && !top.subLanguage) { + relevance += top.relevance; + } + top = top.parent; + } while (top !== endMode.parent); + if (endMode.starts) { + startNewMode(endMode.starts, match); + } + return origin.returnEnd ? 0 : lexeme.length; + } + + function processContinuations() { + const list = []; + for (let current = top; current !== language; current = current.parent) { + if (current.scope) { + list.unshift(current.scope); + } + } + list.forEach(item => emitter.openNode(item)); + } + + /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */ + let lastMatch = {}; + + /** + * Process an individual match + * + * @param {string} textBeforeMatch - text preceding the match (since the last match) + * @param {EnhancedMatch} [match] - the match itself + */ + function processLexeme(textBeforeMatch, match) { + const lexeme = match && match[0]; + + // add non-matched text to the current mode buffer + modeBuffer += textBeforeMatch; + + if (lexeme == null) { + processBuffer(); + return 0; + } + + // we've found a 0 width match and we're stuck, so we need to advance + // this happens when we have badly behaved rules that have optional matchers to the degree that + // sometimes they can end up matching nothing at all + // Ref: https://github.com/highlightjs/highlight.js/issues/2140 + if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") { + // spit the "skipped" character that our regex choked on back into the output sequence + modeBuffer += codeToHighlight.slice(match.index, match.index + 1); + if (!SAFE_MODE) { + /** @type {AnnotatedError} */ + const err = new Error(`0 width match regex (${languageName})`); + err.languageName = languageName; + err.badRule = lastMatch.rule; + throw err; + } + return 1; + } + lastMatch = match; + + if (match.type === "begin") { + return doBeginMatch(match); + } else if (match.type === "illegal" && !ignoreIllegals) { + // illegal match, we do not continue processing + /** @type {AnnotatedError} */ + const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '') + '"'); + err.mode = top; + throw err; + } else if (match.type === "end") { + const processed = doEndMatch(match); + if (processed !== NO_MATCH) { + return processed; + } + } + + // edge case for when illegal matches $ (end of line) which is technically + // a 0 width match but not a begin/end match so it's not caught by the + // first handler (when ignoreIllegals is true) + if (match.type === "illegal" && lexeme === "") { + // advance so we aren't stuck in an infinite loop + modeBuffer += "\n"; + return 1; + } + + // infinite loops are BAD, this is a last ditch catch all. if we have a + // decent number of iterations yet our index (cursor position in our + // parsing) still 3x behind our index then something is very wrong + // so we bail + if (iterations > 100000 && iterations > match.index * 3) { + const err = new Error('potential infinite loop, way more iterations than matches'); + throw err; + } + + /* + Why might be find ourselves here? An potential end match that was + triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH. + (this could be because a callback requests the match be ignored, etc) + + This causes no real harm other than stopping a few times too many. + */ + + modeBuffer += lexeme; + return lexeme.length; + } + + const language = getLanguage(languageName); + if (!language) { + error(LANGUAGE_NOT_FOUND.replace("{}", languageName)); + throw new Error('Unknown language: "' + languageName + '"'); + } + + const md = compileLanguage(language); + let result = ''; + /** @type {CompiledMode} */ + let top = continuation || md; + /** @type Record */ + const continuations = {}; // keep continuations for sub-languages + const emitter = new options.__emitter(options); + processContinuations(); + let modeBuffer = ''; + let relevance = 0; + let index = 0; + let iterations = 0; + let resumeScanAtSamePosition = false; + + try { + if (!language.__emitTokens) { + top.matcher.considerAll(); + + for (;;) { + iterations++; + if (resumeScanAtSamePosition) { + // only regexes not matched previously will now be + // considered for a potential match + resumeScanAtSamePosition = false; + } else { + top.matcher.considerAll(); + } + top.matcher.lastIndex = index; + + const match = top.matcher.exec(codeToHighlight); + // console.log("match", match[0], match.rule && match.rule.begin) + + if (!match) break; + + const beforeMatch = codeToHighlight.substring(index, match.index); + const processedCount = processLexeme(beforeMatch, match); + index = match.index + processedCount; + } + processLexeme(codeToHighlight.substring(index)); + } else { + language.__emitTokens(codeToHighlight, emitter); + } + + emitter.finalize(); + result = emitter.toHTML(); + + return { + language: languageName, + value: result, + relevance, + illegal: false, + _emitter: emitter, + _top: top + }; + } catch (err) { + if (err.message && err.message.includes('Illegal')) { + return { + language: languageName, + value: escape(codeToHighlight), + illegal: true, + relevance: 0, + _illegalBy: { + message: err.message, + index, + context: codeToHighlight.slice(index - 100, index + 100), + mode: err.mode, + resultSoFar: result + }, + _emitter: emitter + }; + } else if (SAFE_MODE) { + return { + language: languageName, + value: escape(codeToHighlight), + illegal: false, + relevance: 0, + errorRaised: err, + _emitter: emitter, + _top: top + }; + } else { + throw err; + } + } + } + + /** + * returns a valid highlight result, without actually doing any actual work, + * auto highlight starts with this and it's possible for small snippets that + * auto-detection may not find a better match + * @param {string} code + * @returns {HighlightResult} + */ + function justTextHighlightResult(code) { + const result = { + value: escape(code), + illegal: false, + relevance: 0, + _top: PLAINTEXT_LANGUAGE, + _emitter: new options.__emitter(options) + }; + result._emitter.addText(code); + return result; + } + + /** + Highlighting with language detection. Accepts a string with the code to + highlight. Returns an object with the following properties: + + - language (detected language) + - relevance (int) + - value (an HTML string with highlighting markup) + - secondBest (object with the same structure for second-best heuristically + detected language, may be absent) + + @param {string} code + @param {Array} [languageSubset] + @returns {AutoHighlightResult} + */ + function highlightAuto(code, languageSubset) { + languageSubset = languageSubset || options.languages || Object.keys(languages); + const plaintext = justTextHighlightResult(code); + + const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name => + _highlight(name, code, false) + ); + results.unshift(plaintext); // plaintext is always an option + + const sorted = results.sort((a, b) => { + // sort base on relevance + if (a.relevance !== b.relevance) return b.relevance - a.relevance; + + // always award the tie to the base language + // ie if C++ and Arduino are tied, it's more likely to be C++ + if (a.language && b.language) { + if (getLanguage(a.language).supersetOf === b.language) { + return 1; + } else if (getLanguage(b.language).supersetOf === a.language) { + return -1; + } + } + + // otherwise say they are equal, which has the effect of sorting on + // relevance while preserving the original ordering - which is how ties + // have historically been settled, ie the language that comes first always + // wins in the case of a tie + return 0; + }); + + const [best, secondBest] = sorted; + + /** @type {AutoHighlightResult} */ + const result = best; + result.secondBest = secondBest; + + return result; + } + + /** + * Builds new class name for block given the language name + * + * @param {HTMLElement} element + * @param {string} [currentLang] + * @param {string} [resultLang] + */ + function updateClassName(element, currentLang, resultLang) { + const language = (currentLang && aliases[currentLang]) || resultLang; + + element.classList.add("hljs"); + element.classList.add(`language-${language}`); + } + + /** + * Applies highlighting to a DOM node containing code. + * + * @param {HighlightedHTMLElement} element - the HTML element to highlight + */ + function highlightElement(element) { + /** @type HTMLElement */ + let node = null; + const language = blockLanguage(element); + + if (shouldNotHighlight(language)) return; + + fire("before:highlightElement", + { el: element, language }); + + if (element.dataset.highlighted) { + console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.", element); + return; + } + + // we should be all text, no child nodes (unescaped HTML) - this is possibly + // an HTML injection attack - it's likely too late if this is already in + // production (the code has likely already done its damage by the time + // we're seeing it)... but we yell loudly about this so that hopefully it's + // more likely to be caught in development before making it to production + if (element.children.length > 0) { + if (!options.ignoreUnescapedHTML) { + console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."); + console.warn("https://github.com/highlightjs/highlight.js/wiki/security"); + console.warn("The element with unescaped HTML:"); + console.warn(element); + } + if (options.throwUnescapedHTML) { + const err = new HTMLInjectionError( + "One of your code blocks includes unescaped HTML.", + element.innerHTML + ); + throw err; + } + } + + node = element; + const text = node.textContent; + const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text); + + element.innerHTML = result.value; + element.dataset.highlighted = "yes"; + updateClassName(element, language, result.language); + element.result = { + language: result.language, + // TODO: remove with version 11.0 + re: result.relevance, + relevance: result.relevance + }; + if (result.secondBest) { + element.secondBest = { + language: result.secondBest.language, + relevance: result.secondBest.relevance + }; + } + + fire("after:highlightElement", { el: element, result, text }); + } + + /** + * Updates highlight.js global options with the passed options + * + * @param {Partial} userOptions + */ + function configure(userOptions) { + options = inherit(options, userOptions); + } + + // TODO: remove v12, deprecated + const initHighlighting = () => { + highlightAll(); + deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now."); + }; + + // TODO: remove v12, deprecated + function initHighlightingOnLoad() { + highlightAll(); + deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now."); + } + + let wantsHighlight = false; + + /** + * auto-highlights all pre>code elements on the page + */ + function highlightAll() { + function boot() { + // if a highlight was requested before DOM was loaded, do now + highlightAll(); + } + + // if we are called too early in the loading process + if (document.readyState === "loading") { + // make sure the event listener is only added once + if (!wantsHighlight) { + window.addEventListener('DOMContentLoaded', boot, false); + } + wantsHighlight = true; + return; + } + + const blocks = document.querySelectorAll(options.cssSelector); + blocks.forEach(highlightElement); + } + + /** + * Register a language grammar module + * + * @param {string} languageName + * @param {LanguageFn} languageDefinition + */ + function registerLanguage(languageName, languageDefinition) { + let lang = null; + try { + lang = languageDefinition(hljs); + } catch (error$1) { + error("Language definition for '{}' could not be registered.".replace("{}", languageName)); + // hard or soft error + if (!SAFE_MODE) { throw error$1; } else { error(error$1); } + // languages that have serious errors are replaced with essentially a + // "plaintext" stand-in so that the code blocks will still get normal + // css classes applied to them - and one bad language won't break the + // entire highlighter + lang = PLAINTEXT_LANGUAGE; + } + // give it a temporary name if it doesn't have one in the meta-data + if (!lang.name) lang.name = languageName; + languages[languageName] = lang; + lang.rawDefinition = languageDefinition.bind(null, hljs); + + if (lang.aliases) { + registerAliases(lang.aliases, { languageName }); + } + } + + /** + * Remove a language grammar module + * + * @param {string} languageName + */ + function unregisterLanguage(languageName) { + delete languages[languageName]; + for (const alias of Object.keys(aliases)) { + if (aliases[alias] === languageName) { + delete aliases[alias]; + } + } + } + + /** + * @returns {string[]} List of language internal names + */ + function listLanguages() { + return Object.keys(languages); + } + + /** + * @param {string} name - name of the language to retrieve + * @returns {Language | undefined} + */ + function getLanguage(name) { + name = (name || '').toLowerCase(); + return languages[name] || languages[aliases[name]]; + } + + /** + * + * @param {string|string[]} aliasList - single alias or list of aliases + * @param {{languageName: string}} opts + */ + function registerAliases(aliasList, { languageName }) { + if (typeof aliasList === 'string') { + aliasList = [aliasList]; + } + aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; }); + } + + /** + * Determines if a given language has auto-detection enabled + * @param {string} name - name of the language + */ + function autoDetection(name) { + const lang = getLanguage(name); + return lang && !lang.disableAutodetect; + } + + /** + * Upgrades the old highlightBlock plugins to the new + * highlightElement API + * @param {HLJSPlugin} plugin + */ + function upgradePluginAPI(plugin) { + // TODO: remove with v12 + if (plugin["before:highlightBlock"] && !plugin["before:highlightElement"]) { + plugin["before:highlightElement"] = (data) => { + plugin["before:highlightBlock"]( + Object.assign({ block: data.el }, data) + ); + }; + } + if (plugin["after:highlightBlock"] && !plugin["after:highlightElement"]) { + plugin["after:highlightElement"] = (data) => { + plugin["after:highlightBlock"]( + Object.assign({ block: data.el }, data) + ); + }; + } + } + + /** + * @param {HLJSPlugin} plugin + */ + function addPlugin(plugin) { + upgradePluginAPI(plugin); + plugins.push(plugin); + } + + /** + * @param {HLJSPlugin} plugin + */ + function removePlugin(plugin) { + const index = plugins.indexOf(plugin); + if (index !== -1) { + plugins.splice(index, 1); + } + } + + /** + * + * @param {PluginEvent} event + * @param {any} args + */ + function fire(event, args) { + const cb = event; + plugins.forEach(function(plugin) { + if (plugin[cb]) { + plugin[cb](args); + } + }); + } + + /** + * DEPRECATED + * @param {HighlightedHTMLElement} el + */ + function deprecateHighlightBlock(el) { + deprecated("10.7.0", "highlightBlock will be removed entirely in v12.0"); + deprecated("10.7.0", "Please use highlightElement now."); + + return highlightElement(el); + } + + /* Interface definition */ + Object.assign(hljs, { + highlight, + highlightAuto, + highlightAll, + highlightElement, + // TODO: Remove with v12 API + highlightBlock: deprecateHighlightBlock, + configure, + initHighlighting, + initHighlightingOnLoad, + registerLanguage, + unregisterLanguage, + listLanguages, + getLanguage, + registerAliases, + autoDetection, + inherit, + addPlugin, + removePlugin + }); + + hljs.debugMode = function() { SAFE_MODE = false; }; + hljs.safeMode = function() { SAFE_MODE = true; }; + hljs.versionString = version; + + hljs.regex = { + concat: concat, + lookahead: lookahead, + either: either, + optional: optional, + anyNumberOfTimes: anyNumberOfTimes + }; + + for (const key in MODES) { + // @ts-ignore + if (typeof MODES[key] === "object") { + // @ts-ignore + deepFreeze(MODES[key]); + } + } + + // merge all the modes/regexes into our main object + Object.assign(hljs, MODES); + + return hljs; + }; + + // Other names for the variable may break build script + const highlight = HLJS({}); + + // returns a new instance of the highlighter to be used for extensions + // check https://github.com/wooorm/lowlight/issues/47 + highlight.newInstance = () => HLJS({}); + + return highlight; + +})(); +if (typeof exports === 'object' && typeof module !== 'undefined') { module.exports = hljs; } + +hljs.registerLanguage("solstice", function(hljs) { + return { + keywords: { + keyword: "puts if while def lambda return use struct enum constructor destructor duplicator private protected ground new as sizeof pragma int double string bool char fun template object", + literal: "true false" + }, + contains: [ + hljs.C_NUMBER_MODE, + hljs.QUOTE_STRING_MODE, + hljs.C_LINE_COMMENT_MODE, + hljs.C_BLOCK_COMMENT_MODE, + hljs.COMMENT( + '#', '\n', { + contains: [ + { + scope: 'doc', begin: '@\\w+' + } + ] + } + ) + ] + }; +}); diff --git a/docs/highlight.js b/docs/highlight.js deleted file mode 100644 index 057bd8d..0000000 --- a/docs/highlight.js +++ /dev/null @@ -1,118 +0,0 @@ -// Solstice Syntax Highlighter -// Add this script to your HTML file before the closing 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 += `${escapeHtml(code.substring(i, end))}`; - 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 += `${escapeHtml(code.substring(i, end))}`; - 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 += `${code.substring(i, end)}`; - 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 += `${word}`; - } else if (['input', 'print', 'println'].includes(word)) { - result += `${word}`; - } else if (['int', 'double', 'string', 'char', 'bool'].includes(word)) { - result += `${word}`; - } else if (['true', 'false'].includes(word)) { - result += `${word}`; - } 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 += `${word}`; - } 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 += `${escapeHtml(op)}`; - i++; - matched = true; - } - - // Everything else (whitespace, braces, etc.) - if (!matched) { - result += escapeHtml(code[i]); - i++; - } - } - - return result; -} - -function escapeHtml(text) { - return text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} diff --git a/docs/index.css b/docs/index.css deleted file mode 100644 index 04376c7..0000000 --- a/docs/index.css +++ /dev/null @@ -1,119 +0,0 @@ -.twopane { - margin: 0; - padding: 0; - box-sizing: border-box; - display: flex; - align-items: flex-start; - gap: 5%; -} - -.box { - position: relative; -} - -.sidebar { - position: sticky; - top: 40px; - width: 250px; - padding: 20px; - background: #080511; - border-radius: 8px; - border: 1px solid #26146b; - color: white; -} - -.sidebar h3 { - margin-top: 0; - margin-bottom: 1rem; - font-size: 1.2rem; - color: #a594f9; -} - -.sidebar ul { - list-style: none; - padding: 0; - margin: 0; -} - -.sidebar li { - margin-bottom: 0.5rem; -} - -.sidebar a { - text-decoration: none; - color: #ccc; - display: block; - padding: 8px 12px; - border-radius: 6px; - transition: background-color 0.2s, color 0.2s; -} - -.sidebar a:hover { - background-color: #26146b; - color: white; -} - -.content { - flex: 1; -} - -@media (max-width: 768px) { - .twopane { - flex-direction: column; - } - - .sidebar { - width: 100%; - position: relative; - top: 0; - margin-bottom: 20px; - box-sizing: border-box; - } -} - -h2 { - font-size: 35px; -} - -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; -} diff --git a/docs/index.html b/docs/index.html index f1b19ec..346512f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,225 +1,231 @@ - - + + + - - Solstice Docs - - - + Introduction - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
-
- -
-

Solstice Docs

-

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.

-

See a mistake? Report it at this site's repository. -

Happy coding!

-
-

Core Concepts

-

Solstice is a high level programming language. It compiles to Ground's bytecode.

-

The solstice command

-

Solstice's compiler is invoked via the solstice command. It provides some options:

-

Note: For now, as we transition to the C-based compiler, Solstice does not support extra flags, and can only run and print code (printing with the -p flag)

-
    -
  • -o or --output: Tells Solstice where to output a compiled file.
  • -
  • -t or --type: 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 here for details.
  • -
-

Example usage:

-
solstice fib.sols -o fib.grnd
-
solstice fib.sols
-

Writing Solstice code

-

Solstice code consists of four main things: values, identifiers, operators, and code blocks.

-
    -
  • Values: these are your literal values in your program, like "Hello!", 32, or true. More on values and the Solstice type system later.
  • -
  • Identifiers: these are names of variables. They normally hold something in them.
  • -
  • Operators: these make up the actual logic of your program. Operators are thing like +, =, or if. (if and while are operators in Solstice.)
  • -
  • Code blocks: this is the collection of values, identifiers, and operators, usually in between { and }.
  • -
-

Comments

-

You can type // to insert a comment into your program. The rest of your line will be commented out. -

puts

-

The puts command in Solstice is used to print out a value. It is not a function, but a built in operator, similar to + or =.

-

Use it like this:

-
puts "Hello, World!"
-puts 3.14
-puts true
-puts "You can print out anything with puts!"
-

Variables

-

Solstice variables are quite simple. Assign values with =, and read them with the variable name.

-
x = 5
-puts x
-

Types are automatically inferred by Solstice.

-

Maths

-

You can use + (add), - (subtract), * (multiply), and / (divide) to do math.

-

Math operations take two values on either side, and perform the operation. Order of operations is supported.

-
x = 5 + 3
-y = 10
-puts x + y
-

Control Flow and Equalities

-

Solstice supports if and while statements, as well as the ==, !=, >, >=, <, and <= operations.

-

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.

-
puts 5 == 5
-puts 5 != 5
-

if and while statements take a conditional, and then a code block afterwards. See these examples:

-
x = 5
-if x > 10 {
-    puts "x is bigger than 10"
-}
-if x < 10 {
-    puts "x is smaller than 10"
-}
-if x == 10 {
-    puts "x is 10"
-}
-
-number = 0
-
-while number < 10 {
-    number = number + 1 
-    puts number
-}
- -

Functions

-

Note: Functions in Solstice are currently in beta. Type checking for functions is currently experimental, and arguments may not work as intended. Be warned!

-

In Solstice, function definitions have a syntax like this:

def functionName(type arg1, type arg2, type arg3) returnType {
-    // code goes here
-}

-

Your types can be int, double, string, bool, or char (see the "Type System" section for more details)

-

Return a value (which must be the same type as your returnType) with return value.

-

Here's an example function:

-
def add(int a, int b) int {
-    return a + b
-}
-

Calling Functions

-

Function calling is done like in most other programming languages, with the syntax function(arg1, arg2, arg3).

-

Importing Other Code

-

Solstice allows you to write libraries in Solstice, or write wrappers for Ground libraries. Use the use keyword, followed by an identifier to import the library.

-
use io
-
-println("Hello!")
-

That's it!

-

You now know everything you need to know about Solstice to start programming! You can continue reading for more information.

-
-
-

Type System

-

Solstice's type system is currently a work in progress, but what is so far implemented will be detailed.

-
-

Value Types

-
    -
  • int: Signed 64 bit integer
  • -
  • double: Double prescision floating point number
  • -
  • string: Character array
  • -
  • char: A single character
  • -
  • bool: Either true or false
  • -
-
-
-

Types of Functions, Templates, and Objects

-

The type signature of a function looks like this:

-
fun(argType, argType, argType) returnType
-

The type signature of a template looks like this:

-
template(fieldType fieldName, fieldType fieldName, fieldType fieldName)
-

The type signature of an object looks like this:

-
object(fieldType fieldName, fieldType fieldName, fieldType fieldName)
-
-
-

Type Checker

-

Solstice statically checks types at compile time to ensure your data is used as intended. These are the details of the type checker.

-
    -
  • Types of variables when setting with = are autoinferred and cannot be provided by the user. All variables must have a value.
  • -
  • When setting a variable with =, it's type must not mutate in any way.
  • -
  • Functions must have types annotated. There is no "any" type.
  • -
  • When using operators, integers are able to promote to doubles where required. No other types can automatically convert.
  • -
  • All equality operators require the same type on both sides of the equality.
  • -
-
-
-
-

Structs, templates and objects

-

Note: 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.

-

In Solstice, you can create a struct to group various bits of data together. You can specify default values for each field with : or =.

-
struct Person {
-    name: "John"
-    age: 32
-}
-

This struct generates a template named "Person" which can be used later to generate new objects.

-

You can use the new operator to create new instances of templates.

-
max = new Person
-
-
-

Inline Ground

-

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.

-

Inline Ground is not vetted by the type checker. Be careful when modifying existing variables with inline ground! The type checker is not aware of any values created inside inline Ground.

-

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.

-

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 here.

-
ground {
-    set &x 5
-    println $x
-}
-
-
-

Built In Functions

-

io library

-
-

input(string msg) string

-

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.

-
use io
-
-guess = input("What is the password? ")
-if guess == "password123" {
-    puts "Good job!"
-}
-
- -
-

println(string msg) string

-

Prints a string to the console. Appends a new line afterwards.

-
use io
-
-println("Hello, World!")
-
-
-
-

Native Compiler

-

Ground has recently added a Ground->Native compiler which allows much faster execution of Ground programs.

-

However, this is quite early in development, and only supports some features:

-
    -
  • int data type - No other data type is currently supported.
  • -
  • No functions at present
  • -
-

To try the native compiler, use this command:

-
solstice program.sols --output program --type native
-

Debugging

-

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.

-
-
+
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Introduction

+

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.

+

Docs generated by mdBook.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/docs/introduction.html b/docs/introduction.html new file mode 100644 index 0000000..346512f --- /dev/null +++ b/docs/introduction.html @@ -0,0 +1,231 @@ + + + + + + Introduction - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Introduction

+

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.

+

Docs generated by mdBook.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/mark-09e88c2c.min.js b/docs/mark-09e88c2c.min.js new file mode 100644 index 0000000..1636231 --- /dev/null +++ b/docs/mark-09e88c2c.min.js @@ -0,0 +1,7 @@ +/*!*************************************************** +* mark.js v8.11.1 +* https://markjs.io/ +* Copyright (c) 2014–2018, Julian Kühnel +* Released under the MIT license https://git.io/vwTVl +*****************************************************/ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Mark=t()}(this,function(){"use strict";var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=i,this.iframesTimeout=o}return n(e,[{key:"getContexts",value:function(){var e=[];return(void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:[]).forEach(function(t){var n=e.filter(function(e){return e.contains(t)}).length>0;-1!==e.indexOf(t)||n||e.push(t)}),e}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var i=e.contentWindow;if(r=i.document,!i||!r)throw new Error("iframe inaccessible")}catch(e){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,i=!1,o=null,a=function a(){if(!i){i=!0,clearTimeout(o);try{r.isIframeBlank(e)||(e.removeEventListener("load",a),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener("load",a),o=setTimeout(a,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,function(){return!0},function(e){r++,n.waitForIframes(e.querySelector("html"),function(){--r||t()})},function(e){e||t()})}},{key:"forEachIframe",value:function(t,n,r){var i=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},a=t.querySelectorAll("iframe"),s=a.length,c=0;a=Array.prototype.slice.call(a);var u=function(){--s<=0&&o(c)};s||u(),a.forEach(function(t){e.matches(t,i.exclude)?u():i.onIframeReady(t,function(e){n(t)&&(c++,r(e)),u()},u)})}},{key:"createIterator",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){if(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_PRECEDING){if(null===t)return!0;if(t.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode();return{prevNode:t,node:null===t?e.nextNode():e.nextNode()&&e.nextNode()}}},{key:"checkIframeFilter",value:function(e,t,n,r){var i=!1,o=!1;return r.forEach(function(e,t){e.val===n&&(i=t,o=e.handled)}),this.compareNodeIframe(e,t,n)?(!1!==i||o?!1===i||o||(r[i].handled=!0):r.push({val:n,handled:!0}),!0):(!1===i&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var i=this;e.forEach(function(e){e.handled||i.getIframeContents(e.val,function(e){i.createInstanceOnIframe(e).forEachNode(t,n,r)})})}},{key:"iterateThroughNodes",value:function(e,t,n,r,i){for(var o,a=this,s=this.createIterator(t,e,r),c=[],u=[],l=void 0,h=void 0;void 0,o=a.getIteratorNode(s),h=o.prevNode,l=o.node;)this.iframes&&this.forEachIframe(t,function(e){return a.checkIframeFilter(l,h,e,c)},function(t){a.createInstanceOnIframe(t).forEachNode(e,function(e){return u.push(e)},r)}),u.push(l);u.forEach(function(e){n(e)}),this.iframes&&this.handleOpenIframes(c,e,n,r),i()}},{key:"forEachNode",value:function(e,t,n){var r=this,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},o=this.getContexts(),a=o.length;a||i(),o.forEach(function(o){var s=function(){r.iterateThroughNodes(e,o,t,n,function(){--a<=0&&i()})};r.iframes?r.waitForIframes(o,s):s()})}}],[{key:"matches",value:function(e,t){var n="string"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var i=!1;return n.every(function(t){return!r.call(e,t)||(i=!0,!1)}),i}return!1}}]),e}(),o=function(){function e(n){t(this,e),this.opt=r({},{diacritics:!0,synonyms:{},accuracy:"partially",caseSensitive:!1,ignoreJoiners:!1,ignorePunctuation:[],wildcards:"disabled"},n)}return n(e,[{key:"create",value:function(e){return"disabled"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),"disabled"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e),new RegExp(e,"gm"+(this.opt.caseSensitive?"":"i"))}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var i in t)if(t.hasOwnProperty(i)){var o=t[i],a="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(i):this.escapeStr(i),s="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o);""!==a&&""!==s&&(e=e.replace(new RegExp("("+this.escapeStr(a)+"|"+this.escapeStr(s)+")","gm"+n),r+"("+this.processSynonyms(a)+"|"+this.processSynonyms(s)+")"+r))}return e}},{key:"processSynonyms",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:"setupWildcardsRegExp",value:function(e){return(e=e.replace(/(?:\\)*\?/g,function(e){return"\\"===e.charAt(0)?"?":""})).replace(/(?:\\)*\*/g,function(e){return"\\"===e.charAt(0)?"*":""})}},{key:"createWildcardsRegExp",value:function(e){var t="withSpaces"===this.opt.wildcards;return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"})}},{key:"createJoinersRegExp",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join("["+t.join("")+"]*"):e}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["aàáảãạăằắẳẵặâầấẩẫậäåāą","AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćč","CÇĆČ","dđď","DĐĎ","eèéẻẽẹêềếểễệëěēę","EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïī","IÌÍỈĨỊÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøō","OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúủũụưừứửữựûüůū","UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿ","YÝỲỶỸỴŸ","zžżź","ZŽŻŹ"]:["aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ","cçćčCÇĆČ","dđďDĐĎ","eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ","iìíỉĩịîïīIÌÍỈĨỊÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ","yýỳỷỹỵÿYÝỲỶỸỴŸ","zžżźZŽŻŹ"],r=[];return e.split("").forEach(function(i){n.every(function(n){if(-1!==n.indexOf(i)){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0})}),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n=this.opt.accuracy,r="string"==typeof n?n:n.value,i="";switch(("string"==typeof n?[]:n.limiters).forEach(function(e){i+="|"+t.escapeStr(e)}),r){case"partially":default:return"()("+e+")";case"complementary":return"()([^"+(i="\\s"+(i||this.escapeStr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿")))+"]*"+e+"[^"+i+"]*)";case"exactly":return"(^|\\s"+i+")("+e+")(?=$|\\s"+i+")"}}}]),e}(),a=function(){function a(e){t(this,a),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf("MSIE")>-1||n.indexOf("Trident")>-1)&&(this.ie=!0)}return n(a,[{key:"log",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",r=this.opt.log;this.opt.debug&&"object"===(void 0===r?"undefined":e(r))&&"function"==typeof r[n]&&r[n]("mark.js: "+t)}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach(function(e){t.opt.separateWordSearch?e.split(" ").forEach(function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)}):e.trim()&&-1===n.indexOf(e)&&n.push(e)}),{keywords:n.sort(function(e,t){return t.length-e.length}),length:n.length}}},{key:"isNumeric",value:function(e){return Number(parseFloat(e))==e}},{key:"checkRanges",value:function(e){var t=this;if(!Array.isArray(e)||"[object Object]"!==Object.prototype.toString.call(e[0]))return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort(function(e,t){return e.start-t.start}).forEach(function(e){var i=t.callNoMatchOnInvalidRanges(e,r),o=i.start,a=i.end;i.valid&&(e.start=o,e.length=a-o,n.push(e),r=a)}),n}},{key:"callNoMatchOnInvalidRanges",value:function(e,t){var n=void 0,r=void 0,i=!1;return e&&void 0!==e.start?(r=(n=parseInt(e.start,10))+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?i=!0:(this.log("Ignoring invalid or overlapping range: "+JSON.stringify(e)),this.opt.noMatch(e))):(this.log("Ignoring invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:i}}},{key:"checkWhitespaceRanges",value:function(e,t,n){var r=void 0,i=!0,o=n.length,a=t-o,s=parseInt(e.start,10)-a;return(r=(s=s>o?o:s)+parseInt(e.length,10))>o&&(r=o,this.log("End range automatically set to the max value of "+o)),s<0||r-s<0||s>o||r>o?(i=!1,this.log("Invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)):""===n.substring(s,r).replace(/\s+/g,"")&&(i=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:s,end:r,valid:i}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})},function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){e({value:n,nodes:r})})}},{key:"matchesExclude",value:function(e){return i.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,t,n){var r=this.opt.element?this.opt.element:"mark",i=e.splitText(t),o=i.splitText(n-t),a=document.createElement(r);return a.setAttribute("data-markjs","true"),this.opt.className&&a.setAttribute("class",this.opt.className),a.textContent=i.textContent,i.parentNode.replaceChild(a,i),o}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,i){var o=this;e.nodes.every(function(a,s){var c=e.nodes[s+1];if(void 0===c||c.start>t){if(!r(a.node))return!1;var u=t-a.start,l=(n>a.end?a.end:n)-a.start,h=e.value.substr(0,a.start),f=e.value.substr(l+a.start);if(a.node=o.wrapRangeInTextNode(a.node,u,l),e.value=h+f,e.nodes.forEach(function(t,n){n>=s&&(e.nodes[n].start>0&&n!==s&&(e.nodes[n].start-=l),e.nodes[n].end-=l)}),n-=l,i(a.node.previousSibling,a.start),!(n>a.end))return!1;t=a.end}return!0})}},{key:"wrapGroups",value:function(e,t,n,r){return r((e=this.wrapRangeInTextNode(e,t,t+n)).previousSibling),e}},{key:"separateGroups",value:function(e,t,n,r,i){for(var o=t.length,a=1;a-1&&r(t[a],e)&&(e=this.wrapGroups(e,s,t[a].length,i))}return e}},{key:"wrapMatches",value:function(e,t,n,r,i){var o=this,a=0===t?0:t+1;this.getTextNodes(function(t){t.nodes.forEach(function(t){t=t.node;for(var i=void 0;null!==(i=e.exec(t.textContent))&&""!==i[a];){if(o.opt.separateGroups)t=o.separateGroups(t,i,a,n,r);else{if(!n(i[a],t))continue;var s=i.index;if(0!==a)for(var c=1;c + + + + + Operators - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Operators

+

Operators are bits of code intended to control how the program runs.

+

puts

+

Stands for “put something”. Prints debug info to the console, followed by a new line.

+

Formatting

+
    +
  • +

    int: The literal number, as formatted by C printf("%" PRId64).

    +
  • +
  • +

    double: The literal number, as formatted by C printf("%f").

    +
  • +
  • +

    string: All characters in the string, as formatted by C printf("%s").

    +
  • +
  • +

    char: The ASCII character corresponding to the number held, as formatted by C printf("%c").

    +
  • +
  • +

    bool: If true or 1, print true. Otherwise, print false.

    +
  • +
  • +

    fun: Print <function>.

    +
  • +
  • +

    template: Print <struct fields: { ... }>, where:

    +
      +
    • ... is a comma-seperated sequence of key: value, where: +
        +
      • key is the identifier of the field.
      • +
      • value is the properly formatted value in the field.
      • +
      +
    • +
    +
  • +
  • +

    object: Print <object fields: { ... }>, where:

    +
      +
    • ... is a comma-seperated sequence of key: value, where: +
        +
      • key is the identifier of the field.
      • +
      • value is the properly formatted value in the field.
      • +
      +
    • +
    +
  • +
+

if

+

Runs a block of code only if the provided condition is true.

+

Syntax:

+
if condition {
+    ...
+}
+
+

where:

+
    +
  • condition is an expression which evaluates to a boolean. +
      +
    • If this expression evaluates to true, the code block will be run.
    • +
    • Brackets surrounding the condition are optional.
    • +
    +
  • +
  • ... is the code to run if the condition is true.
  • +
+

Example:

+
if 2 + 2 == 4 {
+    puts "phew!"
+}
+
+

while

+

Runs a block of code until the provided condition is false.

+

Syntax:

+
while condition {
+    ...
+}
+
+

where:

+
    +
  • condition is an expression which evaluates to a boolean. +
      +
    • If this expression evaluates to false, the code block will not be run anymore.
    • +
    • Brackets surrounding the condition are optional.
    • +
    +
  • +
  • ... is the code to run while the condition is true.
  • +
+

Example:

+
while true {
+    puts "To infinity and beyond!"
+}
+
+

return

+

Returns a value from a function.

+

Syntax:

+
return value
+
+

where value is a value with the same type as the function’s return type.

+

ground

+

Inline Ground is potentially dangerous. Only use if you know what you’re doing!

+

Inserts inline Ground code into the generated program.

+

Syntax:

+
ground {
+    ...
+}
+
+

where ... is the Ground code to insert.

+

See here for details about Ground.

+

Note: Solstice cannot keep track of state inside ground blocks! Ground will allow you to do things without the overhead of the Solstice type checker.

+

To extract a value from a Ground block, do something like this:

+
x = 0
+ground {
+    set &x 10
+}
+
+puts x
+
+

so the type checker can know what x is.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/print.html b/docs/print.html new file mode 100644 index 0000000..0755633 --- /dev/null +++ b/docs/print.html @@ -0,0 +1,1028 @@ + + + + + + Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Introduction

+

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.

+

Docs generated by mdBook.

+
+

Reserved Words

+

This is a list of all reserved words in Solstice, seperated by new lines. These words may not be used as identifiers.

+

After //, notes may be provided which detail exceptions to the reserved word, however, the word should still be treated as reserved regardless.

+
puts
+if
+while
+def
+lambda
+return
+use
+struct
+enum
+constructor
+destructor
+duplicator
+private
+protected
+ground      // Only when targeting GroundVM
+new
+as
+sizeof
+pragma
+
+
+

Comments

+

Comments in Solstice can be done in 3 ways:

+

// (Single-Line Comment)

+

Use // to tell Solstice to ignore text until the end of the line.

+

This kind of comment should be used inside code to explain how parts of code work.

+

/* */ (Multiline Comment)

+

Use /* and */ to tell Solstice to ignore text in between the two markers.

+

This kind of comment should be used for explainations of how functions and structs work, placed above the definition.

+

# (Shebang Comment)

+

Use # to tell Solstice to ignore text until the end of the line.

+

This kind of comment should be used in a shebang (writing #!/usr/bin/env solstice at the top of your entry point source file), not in the middle.

+

Example

+
#!/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
+}
+
+
+

Expressions

+

An expression in Solstice is a combination of operators and values (whether literal or stored in a variable).;

+

Expression Types

+

“Precedence” is a number which dictates the order of execution. The higher the precedence, the sooner an expression will be evaluated.

+

Binary Mathematical

+
    +
  • +: Adds two numbers on either side, or concatenates two strings +
      +
    • Accepts: +
        +
      • Two integers either side
      • +
      • Two doubles either side
      • +
      • Two strings either side
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • The sum of both values as an integer if both values are integers
      • +
      • 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
      • +
      • The concatenated string when both values are strings
      • +
      +
    • +
    • Precedence: 5
    • +
    +
  • +
  • -: Subtracts two numbers on either side +
      +
    • Accepts: +
        +
      • Two integers either side
      • +
      • Two doubles either side
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • The difference of both values as an integer if both values are integers
      • +
      • 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
      • +
      +
    • +
    • Precedence: 5
    • +
    +
  • +
  • *: Multiplies two numbers on either side +
      +
    • Accepts: +
        +
      • Two integers either side
      • +
      • Two doubles either side
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • The product of both values as an integer if both values are integers
      • +
      • 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
      • +
      +
    • +
    • Precedence: 6
    • +
    +
  • +
  • /: Divides two numbers on either side +
      +
    • Accepts: +
        +
      • Two integers either side +
          +
        • Two doubles either side +
            +
          • An integer and a double on either side (order not significant)
          • +
          +
        • +
        +
      • +
      +
    • +
    • Returns: +
        +
      • The quotient of both values as an integer if both values are integers
      • +
      • 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
      • +
      +
    • +
    • Precedence: 6
    • +
    +
  • +
+

Binary Comparative

+
    +
  • ==: Checks two values to determine if they are equal +
      +
    • Accepts: +
        +
      • Any two values either side which are of the same type
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • true if both provided values are exactly the same.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • !=: Checks two values to determine if they are not equal +
      +
    • Accepts: +
        +
      • Any two values either side which are of the same type
      • +
      • An integer and a double on either side (order not significant)
      • +
      +
    • +
    • Returns: +
        +
      • true if both provided values are not exactly the same.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • >: Checks two numbers to determine which is greater +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is greater than the number provided on the right.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • <: Checks two numbers to determine which is lesser +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is lesser than the number provided on the right.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • >=: Checks two numbers to determine which is greater, or whether both are equal +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is greater than the number provided on the right, or if both numbers are equal.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
  • <=: Checks two numbers to determine which is lesser, or whether both are equal +
      +
    • Accepts: +
        +
      • Any two numbers (int or double) either side
      • +
      +
    • +
    • Returns: +
        +
      • true if the number provided on the left is lesser than the number provided on the right, or if both numbers are equal.
      • +
      • false otherwise.
      • +
      +
    • +
    • Precedence: 2
    • +
    +
  • +
+

Binary Misc

+
    +
  • as: Converts between types. +
      +
    • Accepts: +
        +
      • Any object on the left, and a type which has an applicable conversion defined by the object on the right
      • +
      +
    • +
    • Returns: +
        +
      • The object turned into the type on the right, in the way defined by the as-method
      • +
      +
    • +
    +
  • +
  • .: Accesses object fields +
      +
    • Accepts: +
        +
      • An object on the left, and an identifier on the right which corresponds to a field or method in the object
      • +
      +
    • +
    • Returns: +
        +
      • The object field or method the identifier corresponds to
      • +
      +
    • +
    +
  • +
+

Brackets

+
    +
  • (...): Evaluates an expression inside the brackets before outside expressions. +
      +
    • Accepts: +
        +
      • Any expression inside the brackets (in place of ...)
      • +
      +
    • +
    • Returns: +
        +
      • The result of the expression in the brackets
      • +
      +
    • +
    • Precedence: 7
    • +
    +
  • +
+

Function Call

+
    +
  • (...): Calls the specified function. +
      +
    • Accepts: +
        +
      • An identifier for the function before the brackets, then comma-seperated expressions corresponding to the function type signature (see Types -> Combined Types -> fun) inside the brackets (in place of ...)
      • +
      +
    • +
    • Returns: + +
    • +
    +
  • +
+

Unary Misc

+
    +
  • new: Creates a new object from a template. +
      +
    • Accepts: +
        +
      • A template after the new keyword.
      • +
      • A core type identifier
      • +
      +
    • +
    • Returns: +
        +
      • An object based on the provided template, if provided with a template.
      • +
      • The empty version of the core type, if provided with a core type, which is: +
          +
        • int: 0
        • +
        • double: 0.0
        • +
        • string: ""
        • +
        • char: '\0'
        • +
        • bool: false
        • +
        +
      • +
      +
    • +
    +
  • +
  • sizeof: Gets the size of something. +
      +
    • Accepts: +
        +
      • A string
      • +
      • An object with an int size field
      • +
      +
    • +
    • Returns: +
        +
      • The string length if provided a string
      • +
      • The int size field of the object if provided an object
      • +
      +
    • +
    +
  • +
+
+

Types

+

Solstice is statically typed, meaning all values must have a known type before any code can be executed.

+

Core Types

+

These core types are automatically avaliable in Solstice. The words to identify them are reserved and cannot be reassigned.

+

int

+

8-byte signed integer, equivalent to C int64_t or Ground -int.

+

Examples: 32, 121, -5

+

double

+

8-byte double prescision floating point number, equivalent to C double or Ground -double.

+

Examples: 3.14, -2.7

+

string

+

C-style null-terminated array of characters. Equivalent to C char* or Ground -string.

+

char

+

1-byte signed integer, usually used to store a character, however can also be used to store bytes. Equivalent to C char or Ground -char.

+

bool

+

1-byte unsigned integer, either 1 or 0. Represented by the reserved words true and false. Equivalent to C char (no stdbool.h) or bool (with stdbool.h) or Ground -bool.

+

Combined Types

+

These types utilise core types to create new combinations. They take type arguments.

+

fun

+

Represents a function. Equivalent to Ground -function, or a C function pointer.

+

Syntax:

+
fun(...) type
+
+

where:

+
    +
  • type is a type identifier, which will be the return type
  • +
  • ... is multiple type identifiers, seperated by commas, which are the argument types
  • +
+

Example:

+
fun(int, string) bool
+
+

This represents a function which takes an int and string as arguments, and returns a bool.

+

template

+

Represents an uninitialized object. Equivalent to Ground -struct.

+

Syntax:

+
template(...)
+
+

where ... is multiple pairs of:

+
    +
  • a type identifier for the field, and
  • +
  • an identifier (representing the field name)
  • +
+

seperated by commas.

+

Example:

+
template(int x, string y)
+
+

This represents a template which, when initialized, has fields x (with integer) and y (with string).

+

object

+

Represents an initialized object.

+

Syntax:

+
object(...)
+
+

where ... is multiple pairs of:

+
    +
  • a type identifier for the field, and
  • +
  • an identifier (representing the field name)
  • +
+

seperated by commas.

+

Example:

+
object(int x, string y)
+
+

This represents a object which has fields x (with integer) and y (with string).

+
+

Variables

+

Variables are defined and modified with the syntax:

+
name = value
+
+

where:

+
    +
  • name is an identifier, and
  • +
  • value is a literal, expression, or identifier previously assigned to a variable.
  • +
+

All variables must have a known type and value at definition time. When updating a variable, the type may not change.

+
+

Scoping and Lifetimes

+

Subscoping

+

A “subscope” is a scope contained inside a function, created inside curly braces ({}).

+

Subscopes can view and modify variables avaliable in their parent scope.

+

Subscopes may also create their own variables, however these will be destroyed when the subscope ends.

+

Function Scoping

+

A function scope is a scope created inside a function.

+

Function scopes are created from a function’s attached closure, which is a snapshot of all variables at the time of function definition.

+

The function’s attached closure cannot be modified.

+

Function scopes also contain all arguments provided to a function.

+

When the function finishes running (with a return), all variables are destroyed.

+

Destructors

+

Objects (see here) can contain a destructor which specifies custom behaviour for destroying itself. This is useful for:

+
    +
  • Freeing heap-allocated memory
  • +
  • Closing a connection
  • +
  • Closing a file
  • +
+

The destructor will always be in the field destructor with type signature fun() int. It should be automatically called when the variable goes out of scope.

+

Duplicators

+

Objects (see here) can contain a duplicator which specifies custom behaviour for copying itself. This is useful for:

+
    +
  • Duplicating heap-allocated memory
  • +
+

The duplicator will always be in the field duplicator with type signature fun((self) old) (self). It should be automatically called when the variable is:

+
    +
  • Copied into a new variable
  • +
  • Put inside a closure
  • +
  • Passed to a function
  • +
+
+

Operators

+

Operators are bits of code intended to control how the program runs.

+

puts

+

Stands for “put something”. Prints debug info to the console, followed by a new line.

+

Formatting

+
    +
  • +

    int: The literal number, as formatted by C printf("%" PRId64).

    +
  • +
  • +

    double: The literal number, as formatted by C printf("%f").

    +
  • +
  • +

    string: All characters in the string, as formatted by C printf("%s").

    +
  • +
  • +

    char: The ASCII character corresponding to the number held, as formatted by C printf("%c").

    +
  • +
  • +

    bool: If true or 1, print true. Otherwise, print false.

    +
  • +
  • +

    fun: Print <function>.

    +
  • +
  • +

    template: Print <struct fields: { ... }>, where:

    +
      +
    • ... is a comma-seperated sequence of key: value, where: +
        +
      • key is the identifier of the field.
      • +
      • value is the properly formatted value in the field.
      • +
      +
    • +
    +
  • +
  • +

    object: Print <object fields: { ... }>, where:

    +
      +
    • ... is a comma-seperated sequence of key: value, where: +
        +
      • key is the identifier of the field.
      • +
      • value is the properly formatted value in the field.
      • +
      +
    • +
    +
  • +
+

if

+

Runs a block of code only if the provided condition is true.

+

Syntax:

+
if condition {
+    ...
+}
+
+

where:

+
    +
  • condition is an expression which evaluates to a boolean. +
      +
    • If this expression evaluates to true, the code block will be run.
    • +
    • Brackets surrounding the condition are optional.
    • +
    +
  • +
  • ... is the code to run if the condition is true.
  • +
+

Example:

+
if 2 + 2 == 4 {
+    puts "phew!"
+}
+
+

while

+

Runs a block of code until the provided condition is false.

+

Syntax:

+
while condition {
+    ...
+}
+
+

where:

+
    +
  • condition is an expression which evaluates to a boolean. +
      +
    • If this expression evaluates to false, the code block will not be run anymore.
    • +
    • Brackets surrounding the condition are optional.
    • +
    +
  • +
  • ... is the code to run while the condition is true.
  • +
+

Example:

+
while true {
+    puts "To infinity and beyond!"
+}
+
+

return

+

Returns a value from a function.

+

Syntax:

+
return value
+
+

where value is a value with the same type as the function’s return type.

+

ground

+

Inline Ground is potentially dangerous. Only use if you know what you’re doing!

+

Inserts inline Ground code into the generated program.

+

Syntax:

+
ground {
+    ...
+}
+
+

where ... is the Ground code to insert.

+

See here for details about Ground.

+

Note: Solstice cannot keep track of state inside ground blocks! Ground will allow you to do things without the overhead of the Solstice type checker.

+

To extract a value from a Ground block, do something like this:

+
x = 0
+ground {
+    set &x 10
+}
+
+puts x
+
+

so the type checker can know what x is.

+
+

Function Definition

+

Named Functions

+

Define a named function with the following syntax:

+
def functionName(args) type {
+    ...
+}
+
+

where:

+
    +
  • functionName is the name of the function. +
      +
    • If functionName is already defined as a function or other value, it will only be overwritten if the type does not change.
    • +
    +
  • +
  • args is multiple comma-seperated pairs of: +
      +
    • a type identifier for the parameter, and
    • +
    • an identifier (representing the parameter name)
    • +
    +
  • +
  • type is the type of value which the function will return
  • +
  • ... is the code inside the function (the function body). +
      +
    • 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.
    • +
    • The function body will also have access to the parameters defined in args.
    • +
    +
  • +
+

Example:

+
def add(int a, int b) int {
+    return a + b
+}
+
+

Anonymous/Lambda functions

+

Define a lambda function with the following syntax:

+
lambda(args) type {
+    ...
+}
+
+

where:

+
    +
  • args is multiple comma-seperated pairs of: +
      +
    • a type identifier for the parameter, and
    • +
    • an identifier (representing the parameter name)
    • +
    +
  • +
  • type is the type of value which the function will return
  • +
  • ... is the code inside the function (the function body). +
      +
    • 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.
    • +
    • The function body will also have access to the parameters defined in args.
    • +
    +
  • +
+

Example:

+
add = lambda(int a, int b) int {
+    return a + b
+}
+
+

Lambda functions are most useful when passed as arguments to other functions.

+
+

Struct Definition

+

Define a struct with the struct keyword.

+

Syntax:

+
struct StructName {
+    ...
+}
+
+

where:

+
    +
  • StructName is the name of your struct
  • +
  • ... is the body of your struct
  • +
+

Struct Body

+

Inside the struct body, you can:

+
    +
  • Define fields
  • +
  • Define methods
  • +
  • Define special methods (constructor, destructor, duplicator, as)
  • +
+

Defining fields

+

A field in a struct is defined in the same way as a variable.

+
struct MyStruct {
+    x = 5
+}
+
+

This creates a field named x with a default value of 5.

+

Defining methods

+

A method in a struct is defined in the same way as a named function.

+
struct MyStruct {
+    def myMethod() int {
+        return 0
+    }
+}
+
+

Methods have access to the struct’s members through the self object, which is implicitly passed.

+
struct MyStruct {
+
+    x = 10
+
+    def myMethod() int {
+        return self.x * 2
+    }
+}
+
+

Private and protected fields

+

A private field is a field which only methods inside the object can read and write.

+

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.

+

All other fields are public, meaning anywhere in the program can read or write these fields.

+

Methods and special methods are by default protected, however can be made private.

+
struct MyStruct {
+    private x = 10
+    protected y = "Hi"
+
+    private doSomething() int {
+        return 14
+    }
+}
+
+

Defining special methods

+

In Solstice, objects have some special methods which provide ease of use while handling these objects.

+

Constructor

+

A constructor is used to initialize an object with user-provided fields.

+

Define a constructor like this:

+
struct MyStruct {
+    constructor(args) {
+        ...
+    }
+}
+
+

where:

+
    +
  • args is multiple comma-seperated pairs of: +
      +
    • a type identifier for the parameter, and
    • +
    • an identifier (representing the parameter name)
    • +
    +
  • +
  • ... is the constructor body +
      +
    • The constructor body has access to the self object, which is how it can modify the newly created object.
    • +
    • The self object is automatically returned at the end of the constructor, however can be returned manually if required.
    • +
    +
  • +
+

Use a constructor like this:

+
MyStruct(args)
+
+

where:

+
    +
  • args is many comma-seperated expressions corresponding to the signature of the defined constructor
  • +
+

Destructor

+

A destructor is used to destroy an object once it goes out of scope.

+

Define a destructor like this:

+
struct MyStruct {
+    destructor {
+        ...
+    }
+}
+
+

where:

+
    +
  • ... is the destructor body +
      +
    • The destructor body has access to the self object, which is how it can access and modify the object which is being destroyed.
    • +
    • There is no need to return a value from the destructor.
    • +
    +
  • +
+

Note how the destructor does not take any arguments.

+

Duplicator

+

A duplicator is used to copy an object when it is assigned to a new name, or passed to a function.

+

Define a duplicator like this:

+
struct MyStruct {
+    duplicator {
+        ...
+    }
+}
+
+

where:

+
    +
  • ... is the duplicator body +
      +
    • The destructor body has access to the self and old objects. +
        +
      • The self object is the new duplication and will be automatically returned
      • +
      • The old object is the old object and will not be copied out
      • +
      +
    • +
    +
  • +
+

Note how the duplicator does not take any arguments.

+

As methods

+

As methods allow easy conversion between different types.

+

Define an as method like this:

+
struct MyStruct {
+    as type {
+        ...
+    }
+}
+
+

where:

+
    +
  • type is the type which the object will be converted to
  • +
  • ... is the as method body +
      +
    • The self object is avaliable inside the as method
    • +
    • You will need to initialize and return a new value with the specified type
    • +
    +
  • +
+

Use an as method like this:

+
myobj as type
+
+

where:

+
    +
  • myobj is an object with an as method which provides a conversion to type
  • +
  • type is the target type
  • +
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/reserved_words.html b/docs/reserved_words.html new file mode 100644 index 0000000..d5bba6f --- /dev/null +++ b/docs/reserved_words.html @@ -0,0 +1,257 @@ + + + + + + Reserved Words - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Reserved Words

+

This is a list of all reserved words in Solstice, seperated by new lines. These words may not be used as identifiers.

+

After //, notes may be provided which detail exceptions to the reserved word, however, the word should still be treated as reserved regardless.

+
puts
+if
+while
+def
+lambda
+return
+use
+struct
+enum
+constructor
+destructor
+duplicator
+private
+protected
+ground      // Only when targeting GroundVM
+new
+as
+sizeof
+pragma
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/scoping.html b/docs/scoping.html new file mode 100644 index 0000000..348456c --- /dev/null +++ b/docs/scoping.html @@ -0,0 +1,264 @@ + + + + + + Scoping - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Scoping and Lifetimes

+

Subscoping

+

A “subscope” is a scope contained inside a function, created inside curly braces ({}).

+

Subscopes can view and modify variables avaliable in their parent scope.

+

Subscopes may also create their own variables, however these will be destroyed when the subscope ends.

+

Function Scoping

+

A function scope is a scope created inside a function.

+

Function scopes are created from a function’s attached closure, which is a snapshot of all variables at the time of function definition.

+

The function’s attached closure cannot be modified.

+

Function scopes also contain all arguments provided to a function.

+

When the function finishes running (with a return), all variables are destroyed.

+

Destructors

+

Objects (see here) can contain a destructor which specifies custom behaviour for destroying itself. This is useful for:

+
    +
  • Freeing heap-allocated memory
  • +
  • Closing a connection
  • +
  • Closing a file
  • +
+

The destructor will always be in the field destructor with type signature fun() int. It should be automatically called when the variable goes out of scope.

+

Duplicators

+

Objects (see here) can contain a duplicator which specifies custom behaviour for copying itself. This is useful for:

+
    +
  • Duplicating heap-allocated memory
  • +
+

The duplicator will always be in the field duplicator with type signature fun((self) old) (self). It should be automatically called when the variable is:

+
    +
  • Copied into a new variable
  • +
  • Put inside a closure
  • +
  • Passed to a function
  • +
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/searcher-c2a407aa.js b/docs/searcher-c2a407aa.js new file mode 100644 index 0000000..637959d --- /dev/null +++ b/docs/searcher-c2a407aa.js @@ -0,0 +1,555 @@ +'use strict'; + +/* global Mark, elasticlunr, path_to_root */ + +window.search = window.search || {}; +(function search() { + // Search functionality + // + // You can use !hasFocus() to prevent keyhandling in your key + // event handlers while the user is typing their search. + + if (!Mark || !elasticlunr) { + return; + } + + // eslint-disable-next-line max-len + // IE 11 Compatibility from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith + if (!String.prototype.startsWith) { + String.prototype.startsWith = function(search, pos) { + return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; + }; + } + + const search_wrap = document.getElementById('mdbook-search-wrapper'), + searchbar_outer = document.getElementById('mdbook-searchbar-outer'), + searchbar = document.getElementById('mdbook-searchbar'), + searchresults = document.getElementById('mdbook-searchresults'), + searchresults_outer = document.getElementById('mdbook-searchresults-outer'), + searchresults_header = document.getElementById('mdbook-searchresults-header'), + searchicon = document.getElementById('mdbook-search-toggle'), + content = document.getElementById('mdbook-content'), + + // SVG text elements don't render if inside a tag. + mark_exclude = ['text'], + marker = new Mark(content), + URL_SEARCH_PARAM = 'search', + URL_MARK_PARAM = 'highlight'; + + let current_searchterm = '', + doc_urls = [], + search_options = { + bool: 'AND', + expand: true, + fields: { + title: {boost: 1}, + body: {boost: 1}, + breadcrumbs: {boost: 0}, + }, + }, + searchindex = null, + results_options = { + teaser_word_count: 30, + limit_results: 30, + }, + teaser_count = 0; + + function hasFocus() { + return searchbar === document.activeElement; + } + + function removeChildren(elem) { + while (elem.firstChild) { + elem.removeChild(elem.firstChild); + } + } + + // Helper to parse a url into its building blocks. + function parseURL(url) { + const a = document.createElement('a'); + a.href = url; + return { + source: url, + protocol: a.protocol.replace(':', ''), + host: a.hostname, + port: a.port, + params: (function() { + const ret = {}; + const seg = a.search.replace(/^\?/, '').split('&'); + for (const part of seg) { + if (!part) { + continue; + } + const s = part.split('='); + ret[s[0]] = s[1]; + } + return ret; + })(), + file: (a.pathname.match(/\/([^/?#]+)$/i) || ['', ''])[1], + hash: a.hash.replace('#', ''), + path: a.pathname.replace(/^([^/])/, '/$1'), + }; + } + + // Helper to recreate a url string from its building blocks. + function renderURL(urlobject) { + let url = urlobject.protocol + '://' + urlobject.host; + if (urlobject.port !== '') { + url += ':' + urlobject.port; + } + url += urlobject.path; + let joiner = '?'; + for (const prop in urlobject.params) { + if (Object.prototype.hasOwnProperty.call(urlobject.params, prop)) { + url += joiner + prop + '=' + urlobject.params[prop]; + joiner = '&'; + } + } + if (urlobject.hash !== '') { + url += '#' + urlobject.hash; + } + return url; + } + + // Helper to escape html special chars for displaying the teasers + const escapeHTML = (function() { + const MAP = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + }; + const repl = function(c) { + return MAP[c]; + }; + return function(s) { + return s.replace(/[&<>'"]/g, repl); + }; + })(); + + function formatSearchMetric(count, searchterm) { + if (count === 1) { + return count + ' search result for \'' + searchterm + '\':'; + } else if (count === 0) { + return 'No search results for \'' + searchterm + '\'.'; + } else { + return count + ' search results for \'' + searchterm + '\':'; + } + } + + function formatSearchResult(result, searchterms) { + const teaser = makeTeaser(escapeHTML(result.doc.body), searchterms); + teaser_count++; + + // The ?URL_MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor + const url = doc_urls[result.ref].split('#'); + if (url.length === 1) { // no anchor found + url.push(''); + } + + // encodeURIComponent escapes all chars that could allow an XSS except + // for '. Due to that we also manually replace ' with its url-encoded + // representation (%27). + const encoded_search = encodeURIComponent(searchterms.join(' ')).replace(/'/g, '%27'); + + return '' + + result.doc.breadcrumbs + '' + + '' + teaser + ''; + } + + function makeTeaser(body, searchterms) { + // The strategy is as follows: + // First, assign a value to each word in the document: + // Words that correspond to search terms (stemmer aware): 40 + // Normal words: 2 + // First word in a sentence: 8 + // Then use a sliding window with a constant number of words and count the + // sum of the values of the words within the window. Then use the window that got the + // maximum sum. If there are multiple maximas, then get the last one. + // Enclose the terms in . + const stemmed_searchterms = searchterms.map(function(w) { + return elasticlunr.stemmer(w.toLowerCase()); + }); + const searchterm_weight = 40; + const weighted = []; // contains elements of ["word", weight, index_in_document] + // split in sentences, then words + const sentences = body.toLowerCase().split('. '); + let index = 0; + let value = 0; + let searchterm_found = false; + for (const sentenceindex in sentences) { + const words = sentences[sentenceindex].split(' '); + value = 8; + for (const wordindex in words) { + const word = words[wordindex]; + if (word.length > 0) { + for (const searchtermindex in stemmed_searchterms) { + if (elasticlunr.stemmer(word).startsWith( + stemmed_searchterms[searchtermindex]) + ) { + value = searchterm_weight; + searchterm_found = true; + } + } + weighted.push([word, value, index]); + value = 2; + } + index += word.length; + index += 1; // ' ' or '.' if last word in sentence + } + index += 1; // because we split at a two-char boundary '. ' + } + + if (weighted.length === 0) { + return body; + } + + const window_weight = []; + const window_size = Math.min(weighted.length, results_options.teaser_word_count); + + let cur_sum = 0; + for (let wordindex = 0; wordindex < window_size; wordindex++) { + cur_sum += weighted[wordindex][1]; + } + window_weight.push(cur_sum); + for (let wordindex = 0; wordindex < weighted.length - window_size; wordindex++) { + cur_sum -= weighted[wordindex][1]; + cur_sum += weighted[wordindex + window_size][1]; + window_weight.push(cur_sum); + } + + let max_sum_window_index = 0; + if (searchterm_found) { + let max_sum = 0; + // backwards + for (let i = window_weight.length - 1; i >= 0; i--) { + if (window_weight[i] > max_sum) { + max_sum = window_weight[i]; + max_sum_window_index = i; + } + } + } else { + max_sum_window_index = 0; + } + + // add around searchterms + const teaser_split = []; + index = weighted[max_sum_window_index][2]; + for (let i = max_sum_window_index; i < max_sum_window_index + window_size; i++) { + const word = weighted[i]; + if (index < word[2]) { + // missing text from index to start of `word` + teaser_split.push(body.substring(index, word[2])); + index = word[2]; + } + if (word[1] === searchterm_weight) { + teaser_split.push(''); + } + index = word[2] + word[0].length; + teaser_split.push(body.substring(word[2], index)); + if (word[1] === searchterm_weight) { + teaser_split.push(''); + } + } + + return teaser_split.join(''); + } + + function init(config) { + results_options = config.results_options; + search_options = config.search_options; + doc_urls = config.doc_urls; + searchindex = elasticlunr.Index.load(config.index); + + searchbar_outer.classList.remove('searching'); + + searchbar.focus(); + + const searchterm = searchbar.value.trim(); + if (searchterm !== '') { + searchbar.classList.add('active'); + doSearch(searchterm); + } + } + + function initSearchInteractions(config) { + // Set up events + searchicon.addEventListener('click', () => { + searchIconClickHandler(); + }, false); + searchbar.addEventListener('keyup', () => { + searchbarKeyUpHandler(); + }, false); + document.addEventListener('keydown', e => { + globalKeyHandler(e); + }, false); + // If the user uses the browser buttons, do the same as if a reload happened + window.onpopstate = () => { + doSearchOrMarkFromUrl(); + }; + // Suppress "submit" events so the page doesn't reload when the user presses Enter + document.addEventListener('submit', e => { + e.preventDefault(); + }, false); + + // If reloaded, do the search or mark again, depending on the current url parameters + doSearchOrMarkFromUrl(); + + // Exported functions + config.hasFocus = hasFocus; + } + + initSearchInteractions(window.search); + + function unfocusSearchbar() { + // hacky, but just focusing a div only works once + const tmp = document.createElement('input'); + tmp.setAttribute('style', 'position: absolute; opacity: 0;'); + searchicon.appendChild(tmp); + tmp.focus(); + tmp.remove(); + } + + // On reload or browser history backwards/forwards events, parse the url and do search or mark + function doSearchOrMarkFromUrl() { + // Check current URL for search request + const url = parseURL(window.location.href); + if (Object.prototype.hasOwnProperty.call(url.params, URL_SEARCH_PARAM) + && url.params[URL_SEARCH_PARAM] !== '') { + showSearch(true); + searchbar.value = decodeURIComponent( + (url.params[URL_SEARCH_PARAM] + '').replace(/\+/g, '%20')); + searchbarKeyUpHandler(); // -> doSearch() + } else { + showSearch(false); + } + + if (Object.prototype.hasOwnProperty.call(url.params, URL_MARK_PARAM)) { + const words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' '); + marker.mark(words, { + exclude: mark_exclude, + }); + + const markers = document.querySelectorAll('mark'); + const hide = () => { + for (let i = 0; i < markers.length; i++) { + markers[i].classList.add('fade-out'); + window.setTimeout(() => { + marker.unmark(); + }, 300); + } + }; + + for (let i = 0; i < markers.length; i++) { + markers[i].addEventListener('click', hide); + } + } + } + + // Eventhandler for keyevents on `document` + function globalKeyHandler(e) { + if (e.altKey || + e.ctrlKey || + e.metaKey || + e.shiftKey || + e.target.type === 'textarea' || + e.target.type === 'text' || + !hasFocus() && /^(?:input|select|textarea)$/i.test(e.target.nodeName) + ) { + return; + } + + if (e.key === 'Escape') { + e.preventDefault(); + searchbar.classList.remove('active'); + setSearchUrlParameters('', + searchbar.value.trim() !== '' ? 'push' : 'replace'); + if (hasFocus()) { + unfocusSearchbar(); + } + showSearch(false); + marker.unmark(); + } else if (!hasFocus() && (e.key === 's' || e.key === '/')) { + e.preventDefault(); + showSearch(true); + window.scrollTo(0, 0); + searchbar.select(); + } else if (hasFocus() && (e.key === 'ArrowDown' + || e.key === 'Enter')) { + e.preventDefault(); + const first = searchresults.firstElementChild; + if (first !== null) { + unfocusSearchbar(); + first.classList.add('focus'); + if (e.key === 'Enter') { + window.location.assign(first.querySelector('a')); + } + } + } else if (!hasFocus() && (e.key === 'ArrowDown' + || e.key === 'ArrowUp' + || e.key === 'Enter')) { + // not `:focus` because browser does annoying scrolling + const focused = searchresults.querySelector('li.focus'); + if (!focused) { + return; + } + e.preventDefault(); + if (e.key === 'ArrowDown') { + const next = focused.nextElementSibling; + if (next) { + focused.classList.remove('focus'); + next.classList.add('focus'); + } + } else if (e.key === 'ArrowUp') { + focused.classList.remove('focus'); + const prev = focused.previousElementSibling; + if (prev) { + prev.classList.add('focus'); + } else { + searchbar.select(); + } + } else { // Enter + window.location.assign(focused.querySelector('a')); + } + } + } + + function loadSearchScript(url, id) { + if (document.getElementById(id)) { + return; + } + searchbar_outer.classList.add('searching'); + + const script = document.createElement('script'); + script.src = url; + script.id = id; + script.onload = () => init(window.search); + script.onerror = error => { + console.error(`Failed to load \`${url}\`: ${error}`); + }; + document.head.append(script); + } + + function showSearch(yes) { + if (yes) { + loadSearchScript( + window.path_to_searchindex_js || + path_to_root + 'searchindex-c698e2a6.js', + 'mdbook-search-index'); + search_wrap.classList.remove('hidden'); + searchicon.setAttribute('aria-expanded', 'true'); + } else { + search_wrap.classList.add('hidden'); + searchicon.setAttribute('aria-expanded', 'false'); + const results = searchresults.children; + for (let i = 0; i < results.length; i++) { + results[i].classList.remove('focus'); + } + } + } + + function showResults(yes) { + if (yes) { + searchresults_outer.classList.remove('hidden'); + } else { + searchresults_outer.classList.add('hidden'); + } + } + + // Eventhandler for search icon + function searchIconClickHandler() { + if (search_wrap.classList.contains('hidden')) { + showSearch(true); + window.scrollTo(0, 0); + searchbar.select(); + } else { + showSearch(false); + } + } + + // Eventhandler for keyevents while the searchbar is focused + function searchbarKeyUpHandler() { + const searchterm = searchbar.value.trim(); + if (searchterm !== '') { + searchbar.classList.add('active'); + doSearch(searchterm); + } else { + searchbar.classList.remove('active'); + showResults(false); + removeChildren(searchresults); + } + + setSearchUrlParameters(searchterm, 'push_if_new_search_else_replace'); + + // Remove marks + marker.unmark(); + } + + // Update current url with ?URL_SEARCH_PARAM= parameter, remove ?URL_MARK_PARAM and + // `#heading-anchor`. `action` can be one of "push", "replace", + // "push_if_new_search_else_replace" and replaces or pushes a new browser history item. + // "push_if_new_search_else_replace" pushes if there is no `?URL_SEARCH_PARAM=abc` yet. + function setSearchUrlParameters(searchterm, action) { + const url = parseURL(window.location.href); + const first_search = !Object.prototype.hasOwnProperty.call(url.params, URL_SEARCH_PARAM); + + if (searchterm !== '' || action === 'push_if_new_search_else_replace') { + url.params[URL_SEARCH_PARAM] = searchterm; + delete url.params[URL_MARK_PARAM]; + url.hash = ''; + } else { + delete url.params[URL_MARK_PARAM]; + delete url.params[URL_SEARCH_PARAM]; + } + // A new search will also add a new history item, so the user can go back + // to the page prior to searching. A updated search term will only replace + // the url. + if (action === 'push' || action === 'push_if_new_search_else_replace' && first_search ) { + history.pushState({}, document.title, renderURL(url)); + } else if (action === 'replace' || + action === 'push_if_new_search_else_replace' && + !first_search + ) { + history.replaceState({}, document.title, renderURL(url)); + } + } + + function doSearch(searchterm) { + // Don't search the same twice + if (current_searchterm === searchterm) { + return; + } + searchbar_outer.classList.add('searching'); + if (searchindex === null) { + return; + } + + current_searchterm = searchterm; + + // Do the actual search + const results = searchindex.search(searchterm, search_options); + const resultcount = Math.min(results.length, results_options.limit_results); + + // Display search metrics + searchresults_header.innerText = formatSearchMetric(resultcount, searchterm); + + // Clear and insert results + const searchterms = searchterm.split(' '); + removeChildren(searchresults); + for (let i = 0; i < resultcount ; i++) { + const resultElem = document.createElement('li'); + resultElem.innerHTML = formatSearchResult(results[i], searchterms); + searchresults.appendChild(resultElem); + } + + // Display results + showResults(true); + searchbar_outer.classList.remove('searching'); + } + + // Exported functions + search.hasFocus = hasFocus; +})(window.search); diff --git a/docs/searchindex-c698e2a6.js b/docs/searchindex-c698e2a6.js new file mode 100644 index 0000000..bb76507 --- /dev/null +++ b/docs/searchindex-c698e2a6.js @@ -0,0 +1 @@ +window.search = Object.assign(window.search, JSON.parse('{"doc_urls":["introduction.html#introduction","reserved_words.html#reserved-words","comments.html#comments","comments.html#-single-line-comment","comments.html#--multiline-comment","comments.html#-shebang-comment","comments.html#example","expressions.html#expressions","expressions.html#expression-types","expressions.html#binary-mathematical","expressions.html#binary-comparative","expressions.html#binary-misc","expressions.html#brackets","expressions.html#function-call","expressions.html#unary-misc","types.html#types","types.html#core-types","types.html#int","types.html#double","types.html#string","types.html#char","types.html#bool","types.html#combined-types","types.html#fun","types.html#template","types.html#object","variables.html#variables","scoping.html#scoping-and-lifetimes","scoping.html#subscoping","scoping.html#function-scoping","scoping.html#destructors","scoping.html#duplicators","operators.html#operators","operators.html#puts","operators.html#formatting","operators.html#if","operators.html#while","operators.html#return","operators.html#ground","function_definition.html#function-definition","function_definition.html#named-functions","function_definition.html#anonymouslambda-functions","struct_definition.html#struct-definition","struct_definition.html#struct-body","struct_definition.html#defining-fields","struct_definition.html#defining-methods","struct_definition.html#private-and-protected-fields","struct_definition.html#defining-special-methods","struct_definition.html#constructor","struct_definition.html#destructor","struct_definition.html#duplicator","struct_definition.html#as-methods"],"index":{"documentStore":{"docInfo":{"0":{"body":26,"breadcrumbs":2,"title":1},"1":{"body":39,"breadcrumbs":4,"title":2},"10":{"body":162,"breadcrumbs":3,"title":2},"11":{"body":38,"breadcrumbs":3,"title":2},"12":{"body":18,"breadcrumbs":2,"title":1},"13":{"body":36,"breadcrumbs":3,"title":2},"14":{"body":56,"breadcrumbs":3,"title":2},"15":{"body":10,"breadcrumbs":2,"title":1},"16":{"body":9,"breadcrumbs":3,"title":2},"17":{"body":13,"breadcrumbs":2,"title":1},"18":{"body":15,"breadcrumbs":2,"title":1},"19":{"body":11,"breadcrumbs":2,"title":1},"2":{"body":5,"breadcrumbs":2,"title":1},"20":{"body":16,"breadcrumbs":2,"title":1},"21":{"body":19,"breadcrumbs":2,"title":1},"22":{"body":10,"breadcrumbs":3,"title":2},"23":{"body":35,"breadcrumbs":2,"title":1},"24":{"body":32,"breadcrumbs":2,"title":1},"25":{"body":28,"breadcrumbs":2,"title":1},"26":{"body":25,"breadcrumbs":2,"title":1},"27":{"body":0,"breadcrumbs":3,"title":2},"28":{"body":22,"breadcrumbs":2,"title":1},"29":{"body":33,"breadcrumbs":3,"title":2},"3":{"body":17,"breadcrumbs":4,"title":3},"30":{"body":33,"breadcrumbs":2,"title":1},"31":{"body":35,"breadcrumbs":2,"title":1},"32":{"body":7,"breadcrumbs":2,"title":1},"33":{"body":10,"breadcrumbs":2,"title":1},"34":{"body":73,"breadcrumbs":2,"title":1},"35":{"body":32,"breadcrumbs":1,"title":0},"36":{"body":33,"breadcrumbs":1,"title":0},"37":{"body":13,"breadcrumbs":2,"title":1},"38":{"body":56,"breadcrumbs":2,"title":1},"39":{"body":0,"breadcrumbs":4,"title":2},"4":{"body":18,"breadcrumbs":3,"title":2},"40":{"body":71,"breadcrumbs":4,"title":2},"41":{"body":65,"breadcrumbs":4,"title":2},"42":{"body":12,"breadcrumbs":4,"title":2},"43":{"body":13,"breadcrumbs":4,"title":2},"44":{"body":17,"breadcrumbs":4,"title":2},"45":{"body":33,"breadcrumbs":4,"title":2},"46":{"body":47,"breadcrumbs":5,"title":3},"47":{"body":9,"breadcrumbs":5,"title":3},"48":{"body":56,"breadcrumbs":3,"title":1},"49":{"body":33,"breadcrumbs":3,"title":1},"5":{"body":21,"breadcrumbs":3,"title":2},"50":{"body":38,"breadcrumbs":3,"title":1},"51":{"body":43,"breadcrumbs":3,"title":1},"6":{"body":32,"breadcrumbs":2,"title":1},"7":{"body":9,"breadcrumbs":2,"title":1},"8":{"body":10,"breadcrumbs":3,"title":2},"9":{"body":159,"breadcrumbs":3,"title":2}},"docs":{"0":{"body":"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. Docs generated by mdBook.","breadcrumbs":"Introduction » Introduction","id":"0","title":"Introduction"},"1":{"body":"This is a list of all reserved words in Solstice, seperated by new lines. These words may not be used as identifiers. After //, notes may be provided which detail exceptions to the reserved word, however, the word should still be treated as reserved regardless. puts\\nif\\nwhile\\ndef\\nlambda\\nreturn\\nuse\\nstruct\\nenum\\nconstructor\\ndestructor\\nduplicator\\nprivate\\nprotected\\nground // Only when targeting GroundVM\\nnew\\nas\\nsizeof\\npragma","breadcrumbs":"Reserved Words » Reserved Words","id":"1","title":"Reserved Words"},"10":{"body":"==: Checks two values to determine if they are equal Accepts: Any two values either side which are of the same type An integer and a double on either side (order not significant) Returns: true if both provided values are exactly the same. false otherwise. Precedence: 2 !=: Checks two values to determine if they are not equal Accepts: Any two values either side which are of the same type An integer and a double on either side (order not significant) Returns: true if both provided values are not exactly the same. false otherwise. Precedence: 2 >: Checks two numbers to determine which is greater Accepts: Any two numbers (int or double) either side Returns: true if the number provided on the left is greater than the number provided on the right. false otherwise. Precedence: 2 <: Checks two numbers to determine which is lesser Accepts: Any two numbers (int or double) either side Returns: true if the number provided on the left is lesser than the number provided on the right. false otherwise. Precedence: 2 >=: Checks two numbers to determine which is greater, or whether both are equal Accepts: Any two numbers (int or double) either side Returns: true if the number provided on the left is greater than the number provided on the right, or if both numbers are equal. false otherwise. Precedence: 2 <=: Checks two numbers to determine which is lesser, or whether both are equal Accepts: Any two numbers (int or double) either side Returns: true if the number provided on the left is lesser than the number provided on the right, or if both numbers are equal. false otherwise. Precedence: 2","breadcrumbs":"Expressions » Binary Comparative","id":"10","title":"Binary Comparative"},"11":{"body":"as: Converts between types. Accepts: Any object on the left, and a type which has an applicable conversion defined by the object on the right Returns: The object turned into the type on the right, in the way defined by the as-method .: Accesses object fields Accepts: An object on the left, and an identifier on the right which corresponds to a field or method in the object Returns: The object field or method the identifier corresponds to","breadcrumbs":"Expressions » Binary Misc","id":"11","title":"Binary Misc"},"12":{"body":"(...): Evaluates an expression inside the brackets before outside expressions. Accepts: Any expression inside the brackets (in place of ...) Returns: The result of the expression in the brackets Precedence: 7","breadcrumbs":"Expressions » Brackets","id":"12","title":"Brackets"},"13":{"body":"(...): Calls the specified function. Accepts: An identifier for the function before the brackets, then comma-seperated expressions corresponding to the function type signature (see Types -> Combined Types -> fun) inside the brackets (in place of ...) Returns: The function’s return type as specified by the function type signature (see Types -> Combined Types -> fun)","breadcrumbs":"Expressions » Function Call","id":"13","title":"Function Call"},"14":{"body":"new: Creates a new object from a template. Accepts: A template after the new keyword. A core type identifier Returns: An object based on the provided template, if provided with a template. The empty version of the core type, if provided with a core type, which is: int: 0 double: 0.0 string: \\"\\" char: \'\\\\0\' bool: false sizeof: Gets the size of something. Accepts: A string An object with an int size field Returns: The string length if provided a string The int size field of the object if provided an object","breadcrumbs":"Expressions » Unary Misc","id":"14","title":"Unary Misc"},"15":{"body":"Solstice is statically typed, meaning all values must have a known type before any code can be executed.","breadcrumbs":"Types » Types","id":"15","title":"Types"},"16":{"body":"These core types are automatically avaliable in Solstice. The words to identify them are reserved and cannot be reassigned.","breadcrumbs":"Types » Core Types","id":"16","title":"Core Types"},"17":{"body":"8-byte signed integer, equivalent to C int64_t or Ground -int. Examples: 32, 121, -5","breadcrumbs":"Types » int","id":"17","title":"int"},"18":{"body":"8-byte double prescision floating point number, equivalent to C double or Ground -double. Examples: 3.14, -2.7","breadcrumbs":"Types » double","id":"18","title":"double"},"19":{"body":"C-style null-terminated array of characters. Equivalent to C char* or Ground -string.","breadcrumbs":"Types » string","id":"19","title":"string"},"2":{"body":"Comments in Solstice can be done in 3 ways:","breadcrumbs":"Comments » Comments","id":"2","title":"Comments"},"20":{"body":"1-byte signed integer, usually used to store a character, however can also be used to store bytes. Equivalent to C char or Ground -char.","breadcrumbs":"Types » char","id":"20","title":"char"},"21":{"body":"1-byte unsigned integer, either 1 or 0. Represented by the reserved words true and false. Equivalent to C char (no stdbool.h) or bool (with stdbool.h) or Ground -bool.","breadcrumbs":"Types » bool","id":"21","title":"bool"},"22":{"body":"These types utilise core types to create new combinations. They take type arguments.","breadcrumbs":"Types » Combined Types","id":"22","title":"Combined Types"},"23":{"body":"Represents a function. Equivalent to Ground -function, or a C function pointer. Syntax: fun(...) type where: type is a type identifier, which will be the return type ... is multiple type identifiers, seperated by commas, which are the argument types Example: fun(int, string) bool This represents a function which takes an int and string as arguments, and returns a bool.","breadcrumbs":"Types » fun","id":"23","title":"fun"},"24":{"body":"Represents an uninitialized object. Equivalent to Ground -struct. Syntax: template(...) where ... is multiple pairs of: a type identifier for the field, and an identifier (representing the field name) seperated by commas. Example: template(int x, string y) This represents a template which, when initialized, has fields x (with integer) and y (with string).","breadcrumbs":"Types » template","id":"24","title":"template"},"25":{"body":"Represents an initialized object. Syntax: object(...) where ... is multiple pairs of: a type identifier for the field, and an identifier (representing the field name) seperated by commas. Example: object(int x, string y) This represents a object which has fields x (with integer) and y (with string).","breadcrumbs":"Types » object","id":"25","title":"object"},"26":{"body":"Variables are defined and modified with the syntax: name = value where: name is an identifier, and value is a literal, expression, or identifier previously assigned to a variable. All variables must have a known type and value at definition time. When updating a variable, the type may not change.","breadcrumbs":"Variables » Variables","id":"26","title":"Variables"},"27":{"body":"","breadcrumbs":"Scoping » Scoping and Lifetimes","id":"27","title":"Scoping and Lifetimes"},"28":{"body":"A “subscope” is a scope contained inside a function, created inside curly braces ( {}). Subscopes can view and modify variables avaliable in their parent scope. Subscopes may also create their own variables, however these will be destroyed when the subscope ends.","breadcrumbs":"Scoping » Subscoping","id":"28","title":"Subscoping"},"29":{"body":"A function scope is a scope created inside a function. Function scopes are created from a function’s attached closure, which is a snapshot of all variables at the time of function definition. The function’s attached closure cannot be modified. Function scopes also contain all arguments provided to a function. When the function finishes running (with a return), all variables are destroyed.","breadcrumbs":"Scoping » Function Scoping","id":"29","title":"Function Scoping"},"3":{"body":"Use // to tell Solstice to ignore text until the end of the line. This kind of comment should be used inside code to explain how parts of code work.","breadcrumbs":"Comments » // (Single-Line Comment)","id":"3","title":"// (Single-Line Comment)"},"30":{"body":"Objects (see here) can contain a destructor which specifies custom behaviour for destroying itself. This is useful for: Freeing heap-allocated memory Closing a connection Closing a file The destructor will always be in the field destructor with type signature fun() int. It should be automatically called when the variable goes out of scope.","breadcrumbs":"Scoping » Destructors","id":"30","title":"Destructors"},"31":{"body":"Objects (see here) can contain a duplicator which specifies custom behaviour for copying itself. This is useful for: Duplicating heap-allocated memory The duplicator will always be in the field duplicator with type signature fun((self) old) (self). It should be automatically called when the variable is: Copied into a new variable Put inside a closure Passed to a function","breadcrumbs":"Scoping » Duplicators","id":"31","title":"Duplicators"},"32":{"body":"Operators are bits of code intended to control how the program runs.","breadcrumbs":"Operators » Operators","id":"32","title":"Operators"},"33":{"body":"Stands for “put something”. Prints debug info to the console, followed by a new line.","breadcrumbs":"Operators » puts","id":"33","title":"puts"},"34":{"body":"int: The literal number, as formatted by C printf(\\"%\\" PRId64). double: The literal number, as formatted by C printf(\\"%f\\"). string: All characters in the string, as formatted by C printf(\\"%s\\"). char: The ASCII character corresponding to the number held, as formatted by C printf(\\"%c\\"). bool: If true or 1, print true. Otherwise, print false. fun: Print . template: Print , where: ... is a comma-seperated sequence of key: value, where: key is the identifier of the field. value is the properly formatted value in the field. object: Print , where: ... is a comma-seperated sequence of key: value, where: key is the identifier of the field. value is the properly formatted value in the field.","breadcrumbs":"Operators » Formatting","id":"34","title":"Formatting"},"35":{"body":"Runs a block of code only if the provided condition is true. Syntax: if condition { ...\\n} where: condition is an expression which evaluates to a boolean. If this expression evaluates to true, the code block will be run. Brackets surrounding the condition are optional. ... is the code to run if the condition is true. Example: if 2 + 2 == 4 { puts \\"phew!\\"\\n}","breadcrumbs":"Operators » if","id":"35","title":"if"},"36":{"body":"Runs a block of code until the provided condition is false. Syntax: while condition { ...\\n} where: condition is an expression which evaluates to a boolean. If this expression evaluates to false, the code block will not be run anymore. Brackets surrounding the condition are optional. ... is the code to run while the condition is true. Example: while true { puts \\"To infinity and beyond!\\"\\n}","breadcrumbs":"Operators » while","id":"36","title":"while"},"37":{"body":"Returns a value from a function. Syntax: return value where value is a value with the same type as the function’s return type.","breadcrumbs":"Operators » return","id":"37","title":"return"},"38":{"body":"Inline Ground is potentially dangerous. Only use if you know what you’re doing! Inserts inline Ground code into the generated program. Syntax: ground { ...\\n} where ... is the Ground code to insert. See here for details about Ground. Note: Solstice cannot keep track of state inside ground blocks! Ground will allow you to do things without the overhead of the Solstice type checker. To extract a value from a Ground block, do something like this: x = 0\\nground { set &x 10\\n} puts x so the type checker can know what x is.","breadcrumbs":"Operators » ground","id":"38","title":"ground"},"39":{"body":"","breadcrumbs":"Function Definition » Function Definition","id":"39","title":"Function Definition"},"4":{"body":"Use /* and */ to tell Solstice to ignore text in between the two markers. This kind of comment should be used for explainations of how functions and structs work, placed above the definition.","breadcrumbs":"Comments » /* */ (Multiline Comment)","id":"4","title":"/* */ (Multiline Comment)"},"40":{"body":"Define a named function with the following syntax: def functionName(args) type { ...\\n} where: functionName is the name of the function. If functionName is already defined as a function or other value, it will only be overwritten if the type does not change. args is multiple comma-seperated pairs of: a type identifier for the parameter, and an identifier (representing the parameter name) type is the type of value which the function will return ... is the code inside the function (the function body). 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. The function body will also have access to the parameters defined in args. Example: def add(int a, int b) int { return a + b\\n}","breadcrumbs":"Function Definition » Named Functions","id":"40","title":"Named Functions"},"41":{"body":"Define a lambda function with the following syntax: lambda(args) type { ...\\n} where: args is multiple comma-seperated pairs of: a type identifier for the parameter, and an identifier (representing the parameter name) type is the type of value which the function will return ... is the code inside the function (the function body). 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. The function body will also have access to the parameters defined in args. Example: add = lambda(int a, int b) int { return a + b\\n} Lambda functions are most useful when passed as arguments to other functions.","breadcrumbs":"Function Definition » Anonymous/Lambda functions","id":"41","title":"Anonymous/Lambda functions"},"42":{"body":"Define a struct with the struct keyword. Syntax: struct StructName { ...\\n} where: StructName is the name of your struct ... is the body of your struct","breadcrumbs":"Struct Definition » Struct Definition","id":"42","title":"Struct Definition"},"43":{"body":"Inside the struct body, you can: Define fields Define methods Define special methods ( constructor, destructor, duplicator, as)","breadcrumbs":"Struct Definition » Struct Body","id":"43","title":"Struct Body"},"44":{"body":"A field in a struct is defined in the same way as a variable. struct MyStruct { x = 5\\n} This creates a field named x with a default value of 5.","breadcrumbs":"Struct Definition » Defining fields","id":"44","title":"Defining fields"},"45":{"body":"A method in a struct is defined in the same way as a named function. struct MyStruct { def myMethod() int { return 0 }\\n} Methods have access to the struct’s members through the self object, which is implicitly passed. struct MyStruct { x = 10 def myMethod() int { return self.x * 2 }\\n}","breadcrumbs":"Struct Definition » Defining methods","id":"45","title":"Defining methods"},"46":{"body":"A private field is a field which only methods inside the object can read and write. 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. All other fields are public, meaning anywhere in the program can read or write these fields. Methods and special methods are by default protected, however can be made private. struct MyStruct { private x = 10 protected y = \\"Hi\\" private doSomething() int { return 14 }\\n}","breadcrumbs":"Struct Definition » Private and protected fields","id":"46","title":"Private and protected fields"},"47":{"body":"In Solstice, objects have some special methods which provide ease of use while handling these objects.","breadcrumbs":"Struct Definition » Defining special methods","id":"47","title":"Defining special methods"},"48":{"body":"A constructor is used to initialize an object with user-provided fields. Define a constructor like this: struct MyStruct { constructor(args) { ... }\\n} where: args is multiple comma-seperated pairs of: a type identifier for the parameter, and an identifier (representing the parameter name) ... is the constructor body The constructor body has access to the self object, which is how it can modify the newly created object. The self object is automatically returned at the end of the constructor, however can be returned manually if required. Use a constructor like this: MyStruct(args) where: args is many comma-seperated expressions corresponding to the signature of the defined constructor","breadcrumbs":"Struct Definition » Constructor","id":"48","title":"Constructor"},"49":{"body":"A destructor is used to destroy an object once it goes out of scope. Define a destructor like this: struct MyStruct { destructor { ... }\\n} where: ... is the destructor body The destructor body has access to the self object, which is how it can access and modify the object which is being destroyed. There is no need to return a value from the destructor. Note how the destructor does not take any arguments.","breadcrumbs":"Struct Definition » Destructor","id":"49","title":"Destructor"},"5":{"body":"Use # to tell Solstice to ignore text until the end of the line. This kind of comment should be used in a shebang (writing #!/usr/bin/env solstice at the top of your entry point source file), not in the middle.","breadcrumbs":"Comments » # (Shebang Comment)","id":"5","title":"# (Shebang Comment)"},"50":{"body":"A duplicator is used to copy an object when it is assigned to a new name, or passed to a function. Define a duplicator like this: struct MyStruct { duplicator { ... }\\n} where: ... is the duplicator body The destructor body has access to the self and old objects. The self object is the new duplication and will be automatically returned The old object is the old object and will not be copied out Note how the duplicator does not take any arguments.","breadcrumbs":"Struct Definition » Duplicator","id":"50","title":"Duplicator"},"51":{"body":"As methods allow easy conversion between different types. Define an as method like this: struct MyStruct { as type { ... }\\n} where: type is the type which the object will be converted to ... is the as method body The self object is avaliable inside the as method You will need to initialize and return a new value with the specified type Use an as method like this: myobj as type where: myobj is an object with an as method which provides a conversion to type type is the target type","breadcrumbs":"Struct Definition » As methods","id":"51","title":"As methods"},"6":{"body":"#!/usr/bin/env solstice /* This function does something. Input: funnyNumber: A funny number Returns: Another funny number\\n*/\\ndef 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\\n}","breadcrumbs":"Comments » Example","id":"6","title":"Example"},"7":{"body":"An expression in Solstice is a combination of operators and values (whether literal or stored in a variable).;","breadcrumbs":"Expressions » Expressions","id":"7","title":"Expressions"},"8":{"body":"“Precedence” is a number which dictates the order of execution. The higher the precedence, the sooner an expression will be evaluated.","breadcrumbs":"Expressions » Expression Types","id":"8","title":"Expression Types"},"9":{"body":"+: Adds two numbers on either side, or concatenates two strings Accepts: Two integers either side Two doubles either side Two strings either side An integer and a double on either side (order not significant) Returns: The sum of both values as an integer if both values are integers 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 The concatenated string when both values are strings Precedence: 5 -: Subtracts two numbers on either side Accepts: Two integers either side Two doubles either side An integer and a double on either side (order not significant) Returns: The difference of both values as an integer if both values are integers 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 Precedence: 5 *: Multiplies two numbers on either side Accepts: Two integers either side Two doubles either side An integer and a double on either side (order not significant) Returns: The product of both values as an integer if both values are integers 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 Precedence: 6 /: Divides two numbers on either side Accepts: Two integers either side Two doubles either side An integer and a double on either side (order not significant) Returns: The quotient of both values as an integer if both values are integers 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 Precedence: 6","breadcrumbs":"Expressions » Binary Mathematical","id":"9","title":"Binary Mathematical"}},"length":52,"save":true},"fields":["title","body","breadcrumbs"],"index":{"body":{"root":{"0":{".":{"0":{"df":1,"docs":{"14":{"tf":1.0}}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.4142135623730951},"21":{"tf":1.0},"38":{"tf":1.0},"45":{"tf":1.0}}},"1":{"0":{"df":3,"docs":{"38":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0}}},"2":{"1":{"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}},"4":{"df":1,"docs":{"46":{"tf":1.0}}},"df":3,"docs":{"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"34":{"tf":1.0}}},"2":{".":{"7":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"10":{"tf":2.449489742783178},"35":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"3":{".":{"1":{"4":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"df":1,"docs":{"17":{"tf":1.0}}},"df":1,"docs":{"2":{"tf":1.0}}},"4":{"df":1,"docs":{"35":{"tf":1.0}}},"5":{"3":{"2":{"df":1,"docs":{"6":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"17":{"tf":1.0},"44":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}},"6":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}},"7":{"df":1,"docs":{"12":{"tf":1.0}}},"8":{"df":2,"docs":{"17":{"tf":1.0},"18":{"tf":1.0}}},"a":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":1,"docs":{"4":{"tf":1.0}}}}},"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":6,"docs":{"10":{"tf":2.449489742783178},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.4142135623730951},"9":{"tf":2.0}}}},"s":{"df":0,"docs":{},"s":{"df":7,"docs":{"11":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"45":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.4142135623730951},"50":{"tf":1.0}}}}}},"df":0,"docs":{}},"d":{"d":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":2,"docs":{"41":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}},"df":0,"docs":{},"w":{"df":2,"docs":{"38":{"tf":1.0},"51":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"/":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"m":{"b":{"d":{"a":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"6":{"tf":1.4142135623730951}}}}},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"36":{"tf":1.0}}}}},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"46":{"tf":1.4142135623730951}}}}}}}},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"g":{"df":3,"docs":{"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"48":{"tf":1.4142135623730951}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":6,"docs":{"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"29":{"tf":1.0},"41":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}}}}}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"i":{"df":1,"docs":{"34":{"tf":1.0}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"26":{"tf":1.0},"50":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"29":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":5,"docs":{"16":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"48":{"tf":1.0},"50":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":3,"docs":{"16":{"tf":1.0},"28":{"tf":1.0},"51":{"tf":1.0}}}}},"df":0,"docs":{}}},"b":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"14":{"tf":1.0}}}}},"df":2,"docs":{"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951}},"e":{"df":1,"docs":{"49":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":3,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"15":{"tf":1.0}}}}},"h":{"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":3,"docs":{"11":{"tf":1.0},"4":{"tf":1.0},"51":{"tf":1.0}}}}}}},"y":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":3,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}},"t":{"df":1,"docs":{"32":{"tf":1.0}}}},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"38":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"i":{"df":8,"docs":{"40":{"tf":1.7320508075688772},"41":{"tf":1.7320508075688772},"42":{"tf":1.0},"43":{"tf":1.4142135623730951},"48":{"tf":1.4142135623730951},"49":{"tf":1.4142135623730951},"50":{"tf":1.4142135623730951},"51":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}},"l":{"df":4,"docs":{"14":{"tf":1.0},"21":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"34":{"tf":1.0}},"e":{"a":{"df":0,"docs":{},"n":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"10":{"tf":2.449489742783178},"9":{"tf":4.123105625617661}}}}},"r":{"a":{"c":{"df":0,"docs":{},"e":{"df":1,"docs":{"28":{"tf":1.0}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":4,"docs":{"12":{"tf":2.0},"13":{"tf":1.4142135623730951},"35":{"tf":1.0},"36":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":4,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0}}}}}},"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0}}}}},"df":7,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.0},"23":{"tf":1.0},"34":{"tf":2.0}},"h":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":2,"docs":{"26":{"tf":1.0},"40":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":3,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"34":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":5,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.7320508075688772},"21":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"10":{"tf":2.449489742783178}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"30":{"tf":1.4142135623730951}}},"u":{"df":0,"docs":{},"r":{"df":4,"docs":{"29":{"tf":1.4142135623730951},"31":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951}}}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":8,"docs":{"15":{"tf":1.0},"3":{"tf":1.4142135623730951},"32":{"tf":1.0},"35":{"tf":1.7320508075688772},"36":{"tf":1.7320508075688772},"38":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"22":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"a":{"df":8,"docs":{"13":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.4142135623730951}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"2":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"4":{"tf":1.4142135623730951},"5":{"tf":1.4142135623730951}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}},"n":{"c":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"35":{"tf":2.23606797749979},"36":{"tf":2.23606797749979}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"33":{"tf":1.0}}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"48":{"tf":1.0}}}}},"df":0,"docs":{}},"df":3,"docs":{"1":{"tf":1.0},"43":{"tf":1.0},"48":{"tf":2.8284271247461903}}}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":4,"docs":{"28":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"32":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":2,"docs":{"11":{"tf":1.0},"51":{"tf":1.4142135623730951}}},"t":{"df":2,"docs":{"11":{"tf":1.0},"51":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":4,"docs":{"31":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0},"50":{"tf":1.4142135623730951}}}},"r":{"df":0,"docs":{},"e":{"df":3,"docs":{"14":{"tf":1.7320508075688772},"16":{"tf":1.4142135623730951},"22":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":4,"docs":{"11":{"tf":1.4142135623730951},"13":{"tf":1.0},"34":{"tf":1.0},"48":{"tf":1.0}}},"df":0,"docs":{}}}}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":6,"docs":{"14":{"tf":1.0},"22":{"tf":1.0},"28":{"tf":1.4142135623730951},"29":{"tf":1.4142135623730951},"44":{"tf":1.0},"48":{"tf":1.0}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"28":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"40":{"tf":1.0},"41":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}}}},"d":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":1,"docs":{"33":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":2,"docs":{"44":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":4,"docs":{"1":{"tf":1.0},"40":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":13,"docs":{"11":{"tf":1.4142135623730951},"26":{"tf":1.0},"40":{"tf":1.7320508075688772},"41":{"tf":1.4142135623730951},"42":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"47":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":7,"docs":{"26":{"tf":1.0},"29":{"tf":1.0},"39":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"42":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"df":4,"docs":{"28":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"49":{"tf":1.4142135623730951}}}},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":5,"docs":{"1":{"tf":1.0},"30":{"tf":2.0},"43":{"tf":1.0},"49":{"tf":2.8284271247461903},"50":{"tf":1.0}}}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"1":{"tf":1.0},"38":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"10":{"tf":2.449489742783178}}}}}}}}},"i":{"c":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"8":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"51":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"c":{"df":1,"docs":{"0":{"tf":1.4142135623730951}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"df":1,"docs":{"38":{"tf":1.0}},"n":{"df":0,"docs":{},"e":{"df":1,"docs":{"2":{"tf":1.0}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"46":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":5,"docs":{"10":{"tf":2.449489742783178},"14":{"tf":1.0},"18":{"tf":2.0},"34":{"tf":1.0},"9":{"tf":4.47213595499958}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":4,"docs":{"1":{"tf":1.0},"31":{"tf":2.23606797749979},"43":{"tf":1.0},"50":{"tf":2.6457513110645907}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":1,"docs":{"47":{"tf":1.0}},"i":{"df":1,"docs":{"51":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}}}},"n":{"d":{"df":4,"docs":{"28":{"tf":1.0},"3":{"tf":1.0},"48":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"5":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":2.449489742783178}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"a":{"df":0,"docs":{},"l":{"df":7,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":4,"docs":{"12":{"tf":1.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"x":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":10,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"6":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":8,"docs":{"12":{"tf":2.0},"13":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"48":{"tf":1.0},"7":{"tf":1.4142135623730951},"8":{"tf":1.4142135623730951}}}}}}},"t":{"df":0,"docs":{},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"f":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"s":{"df":5,"docs":{"10":{"tf":2.449489742783178},"14":{"tf":1.0},"21":{"tf":1.0},"34":{"tf":1.0},"36":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"d":{"df":11,"docs":{"11":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"24":{"tf":1.7320508075688772},"25":{"tf":1.7320508075688772},"30":{"tf":1.0},"31":{"tf":1.0},"34":{"tf":2.449489742783178},"43":{"tf":1.0},"44":{"tf":1.7320508075688772},"46":{"tf":2.8284271247461903},"48":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"30":{"tf":1.0},"5":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"29":{"tf":1.0}}}}}}},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":3,"docs":{"33":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"34":{"tf":2.6457513110645907}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"30":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"(":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"31":{"tf":1.0}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":14,"docs":{"13":{"tf":2.23606797749979},"23":{"tf":2.0},"28":{"tf":1.0},"29":{"tf":2.8284271247461903},"31":{"tf":1.0},"34":{"tf":1.0},"37":{"tf":1.0},"39":{"tf":1.0},"4":{"tf":1.0},"40":{"tf":3.1622776601683795},"41":{"tf":3.1622776601683795},"45":{"tf":1.0},"50":{"tf":1.0},"6":{"tf":1.0}},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"e":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"’":{"df":3,"docs":{"13":{"tf":1.0},"29":{"tf":1.4142135623730951},"37":{"tf":1.0}}}}}}}},"df":4,"docs":{"13":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"30":{"tf":1.0},"34":{"tf":1.0}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"6":{"tf":2.23606797749979}}},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"b":{"df":1,"docs":{"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"0":{"tf":1.0},"38":{"tf":1.0}}}}},"t":{"df":1,"docs":{"14":{"tf":1.0}}}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"6":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"e":{"df":2,"docs":{"30":{"tf":1.0},"49":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":2.0}}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":9,"docs":{"1":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"38":{"tf":3.1622776601683795}},"v":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"l":{"df":1,"docs":{"47":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"p":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}},"df":0,"docs":{},"l":{"d":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":3,"docs":{"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}}}}},"i":{"df":1,"docs":{"46":{"tf":1.0}},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"8":{"tf":1.0}}}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":13,"docs":{"1":{"tf":1.0},"11":{"tf":1.4142135623730951},"13":{"tf":1.0},"14":{"tf":1.0},"16":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"48":{"tf":1.4142135623730951}}}}}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":3,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}}}}},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"36":{"tf":1.0}}}},"o":{"df":1,"docs":{"33":{"tf":1.0}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":4,"docs":{"24":{"tf":1.0},"25":{"tf":1.0},"48":{"tf":1.0},"51":{"tf":1.0}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"6":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}}}},"i":{"d":{"df":12,"docs":{"12":{"tf":1.4142135623730951},"13":{"tf":1.0},"28":{"tf":1.4142135623730951},"29":{"tf":1.0},"3":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.0},"46":{"tf":1.4142135623730951},"51":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"0":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"6":{"4":{"_":{"df":0,"docs":{},"t":{"df":1,"docs":{"17":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":12,"docs":{"10":{"tf":2.0},"14":{"tf":1.7320508075688772},"17":{"tf":1.4142135623730951},"23":{"tf":1.0},"30":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":2.0}},"e":{"df":0,"docs":{},"g":{"df":7,"docs":{"10":{"tf":1.4142135623730951},"17":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":4.0}}},"n":{"d":{"df":1,"docs":{"32":{"tf":1.0}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"t":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":1,"docs":{"38":{"tf":1.0}}}},"y":{"df":1,"docs":{"34":{"tf":2.0}},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"14":{"tf":1.0},"42":{"tf":1.0}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"n":{"d":{"df":3,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"38":{"tf":1.4142135623730951}},"n":{"df":2,"docs":{"15":{"tf":1.0},"26":{"tf":1.0}}}}}}},"l":{"a":{"df":0,"docs":{},"m":{"b":{"d":{"a":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"41":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"41":{"tf":1.0}}}}}},"df":2,"docs":{"1":{"tf":1.0},"41":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":2.0},"11":{"tf":1.4142135623730951}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"14":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":2.0}}}}}}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"27":{"tf":1.0}}}}}}},"n":{"df":0,"docs":{},"e":{"df":4,"docs":{"1":{"tf":1.0},"3":{"tf":1.4142135623730951},"33":{"tf":1.0},"5":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"26":{"tf":1.0},"34":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}}}},"m":{"a":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"46":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"48":{"tf":1.0}}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"48":{"tf":1.0}}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"d":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"n":{"df":2,"docs":{"15":{"tf":1.0},"46":{"tf":1.0}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"45":{"tf":1.0}}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"df":6,"docs":{"11":{"tf":1.7320508075688772},"43":{"tf":1.4142135623730951},"45":{"tf":1.7320508075688772},"46":{"tf":2.0},"47":{"tf":1.4142135623730951},"51":{"tf":2.6457513110645907}}},"df":0,"docs":{}}}}},"i":{"d":{"d":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"s":{"c":{"df":2,"docs":{"11":{"tf":1.0},"14":{"tf":1.0}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":5,"docs":{"26":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0}}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}}}}},"p":{"df":0,"docs":{},"l":{"df":6,"docs":{"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.0}},"i":{"df":1,"docs":{"9":{"tf":1.0}}}}}}}}},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"45":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"51":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"48":{"tf":1.0}}}}},"df":0,"docs":{}},"df":7,"docs":{"44":{"tf":1.0},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0}}}},"df":0,"docs":{}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":10,"docs":{"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.4142135623730951},"40":{"tf":2.0},"41":{"tf":1.0},"42":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"48":{"tf":1.0},"50":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"d":{"df":2,"docs":{"49":{"tf":1.0},"51":{"tf":1.0}}},"df":0,"docs":{}},"w":{"df":7,"docs":{"1":{"tf":1.4142135623730951},"14":{"tf":1.7320508075688772},"22":{"tf":1.0},"31":{"tf":1.0},"33":{"tf":1.0},"50":{"tf":1.4142135623730951},"51":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"48":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":4,"docs":{"1":{"tf":1.0},"38":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}}}},"w":{"df":2,"docs":{"0":{"tf":1.0},"6":{"tf":1.0}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":6,"docs":{"10":{"tf":4.242640687119285},"18":{"tf":1.0},"34":{"tf":1.7320508075688772},"6":{"tf":2.23606797749979},"8":{"tf":1.0},"9":{"tf":2.0}}}}},"df":0,"docs":{}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}}}},"df":14,"docs":{"11":{"tf":2.6457513110645907},"14":{"tf":2.23606797749979},"24":{"tf":1.0},"25":{"tf":2.0},"30":{"tf":1.0},"31":{"tf":1.0},"34":{"tf":1.4142135623730951},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"47":{"tf":1.4142135623730951},"48":{"tf":2.0},"49":{"tf":1.7320508075688772},"50":{"tf":2.23606797749979},"51":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"31":{"tf":1.0},"50":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"n":{"c":{"df":1,"docs":{"49":{"tf":1.0}}},"df":1,"docs":{"9":{"tf":2.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"32":{"tf":1.4142135623730951},"7":{"tf":1.0}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}}}}}},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"8":{"tf":1.0},"9":{"tf":2.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":2,"docs":{"10":{"tf":2.449489742783178},"34":{"tf":1.0}}}}}}}}},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"30":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}},"s":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}}}}}}},"p":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":5,"docs":{"24":{"tf":1.0},"25":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.0}}}},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":3,"docs":{"40":{"tf":1.7320508075688772},"41":{"tf":1.7320508075688772},"48":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"28":{"tf":1.0}}}}},"t":{"df":2,"docs":{"0":{"tf":1.0},"3":{"tf":1.0}}}},"s":{"df":0,"docs":{},"s":{"df":4,"docs":{"31":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0},"50":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"35":{"tf":1.0}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":3,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"5":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"r":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"m":{"a":{"df":1,"docs":{"1":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"e":{"d":{"df":4,"docs":{"10":{"tf":2.449489742783178},"12":{"tf":1.0},"8":{"tf":1.4142135623730951},"9":{"tf":2.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":3,"docs":{"26":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}}}}},"i":{"d":{"6":{"4":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"33":{"tf":1.0},"34":{"tf":2.23606797749979}},"f":{"(":{"\\"":{"%":{"c":{"df":1,"docs":{"34":{"tf":1.0}}},"df":1,"docs":{"34":{"tf":1.0}},"f":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"34":{"tf":1.0}}}}},"v":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.0},"46":{"tf":2.23606797749979}}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"32":{"tf":1.0},"38":{"tf":1.0},"46":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"34":{"tf":1.4142135623730951}}}}}}},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.0},"46":{"tf":2.0}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"d":{"df":9,"docs":{"1":{"tf":1.0},"10":{"tf":3.1622776601683795},"14":{"tf":2.23606797749979},"29":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"47":{"tf":1.0},"48":{"tf":1.0},"51":{"tf":1.0}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"46":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"t":{"df":7,"docs":{"1":{"tf":1.0},"31":{"tf":1.0},"33":{"tf":1.4142135623730951},"35":{"tf":1.0},"36":{"tf":1.0},"38":{"tf":1.0},"6":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"46":{"tf":1.7320508075688772}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"16":{"tf":1.0}}}}}}}},"df":0,"docs":{},"g":{"a":{"df":0,"docs":{},"r":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"1":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":7,"docs":{"21":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.7320508075688772},"25":{"tf":1.7320508075688772},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.0}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":1,"docs":{"48":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":3,"docs":{"1":{"tf":2.0},"16":{"tf":1.0},"21":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":19,"docs":{"1":{"tf":1.0},"10":{"tf":2.449489742783178},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"29":{"tf":1.0},"37":{"tf":2.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":2.0}}}}}}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":2.0},"11":{"tf":1.7320508075688772}}}}}},"u":{"df":0,"docs":{},"n":{"df":4,"docs":{"29":{"tf":1.0},"32":{"tf":1.0},"35":{"tf":1.7320508075688772},"36":{"tf":1.7320508075688772}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"s":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"10":{"tf":2.0},"37":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":5,"docs":{"27":{"tf":1.0},"28":{"tf":1.4142135623730951},"29":{"tf":2.23606797749979},"30":{"tf":1.0},"49":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}}},"l":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"x":{"df":1,"docs":{"45":{"tf":1.0}}}},"df":6,"docs":{"31":{"tf":1.0},"45":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.4142135623730951},"51":{"tf":1.0}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":9,"docs":{"1":{"tf":1.0},"13":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.4142135623730951}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"34":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}},"t":{"df":3,"docs":{"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}},"h":{"df":0,"docs":{},"e":{"b":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"5":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"0":{"tf":1.0}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":2,"docs":{"10":{"tf":2.8284271247461903},"9":{"tf":4.123105625617661}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"48":{"tf":1.0}}}}}},"df":2,"docs":{"17":{"tf":1.0},"20":{"tf":1.0}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"10":{"tf":1.4142135623730951},"9":{"tf":2.0}}},"df":0,"docs":{}}}}}},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"3":{"tf":1.0}}}}},"z":{"df":0,"docs":{},"e":{"df":1,"docs":{"14":{"tf":1.7320508075688772}},"o":{"df":0,"docs":{},"f":{"df":2,"docs":{"1":{"tf":1.0},"14":{"tf":1.0}}}}}}},"n":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"29":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":12,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"2":{"tf":1.0},"3":{"tf":1.0},"38":{"tf":1.4142135623730951},"4":{"tf":1.0},"47":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":4,"docs":{"14":{"tf":1.0},"33":{"tf":1.0},"38":{"tf":1.0},"6":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"8":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"0":{"tf":1.0}},"i":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"43":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.4142135623730951}}}},"df":0,"docs":{},"f":{"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"51":{"tf":1.0}}}}}},"df":0,"docs":{}}},"t":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"33":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"df":3,"docs":{"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}},"i":{"c":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}},"d":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{".":{"df":0,"docs":{},"h":{"df":1,"docs":{"21":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"1":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":7,"docs":{"14":{"tf":2.0},"19":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"9":{"tf":2.0}}}}},"u":{"c":{"df":0,"docs":{},"t":{"df":13,"docs":{"1":{"tf":1.0},"24":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0},"42":{"tf":2.449489742783178},"43":{"tf":1.4142135623730951},"44":{"tf":1.4142135623730951},"45":{"tf":1.7320508075688772},"46":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0}},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"42":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"’":{"df":1,"docs":{"45":{"tf":1.0}}}}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"u":{"b":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"28":{"tf":2.23606797749979}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"m":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"x":{"df":11,"docs":{"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"42":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":4,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.0},"51":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":4,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":2.0},"24":{"tf":1.7320508075688772},"34":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"24":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"x":{"df":0,"docs":{},"t":{"df":3,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"38":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":3,"docs":{"40":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"26":{"tf":1.0},"29":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"5":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"e":{"df":5,"docs":{"10":{"tf":2.449489742783178},"21":{"tf":1.0},"34":{"tf":1.4142135623730951},"35":{"tf":1.7320508075688772},"36":{"tf":1.4142135623730951}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"11":{"tf":1.0}}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"w":{"df":0,"docs":{},"o":{"df":3,"docs":{"10":{"tf":3.4641016151377544},"4":{"tf":1.0},"9":{"tf":3.7416573867739413}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":20,"docs":{"10":{"tf":1.4142135623730951},"11":{"tf":1.7320508075688772},"13":{"tf":2.6457513110645907},"14":{"tf":1.7320508075688772},"15":{"tf":1.7320508075688772},"16":{"tf":1.4142135623730951},"22":{"tf":2.0},"23":{"tf":2.449489742783178},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"37":{"tf":1.4142135623730951},"38":{"tf":1.4142135623730951},"40":{"tf":2.23606797749979},"41":{"tf":2.0},"48":{"tf":1.0},"51":{"tf":3.0},"8":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"24":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"21":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":3,"docs":{"3":{"tf":1.0},"36":{"tf":1.0},"5":{"tf":1.0}}}}}},"p":{"d":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"s":{"df":14,"docs":{"1":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.4142135623730951},"41":{"tf":1.0},"47":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"5":{"tf":1.4142135623730951},"50":{"tf":1.0},"51":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"48":{"tf":1.0},"6":{"tf":1.0}}}},"r":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"v":{"df":2,"docs":{"5":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":13,"docs":{"10":{"tf":2.449489742783178},"15":{"tf":1.0},"26":{"tf":1.7320508075688772},"34":{"tf":2.449489742783178},"37":{"tf":2.0},"38":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.0},"44":{"tf":1.0},"49":{"tf":1.0},"51":{"tf":1.0},"7":{"tf":1.0},"9":{"tf":4.58257569495584}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":9,"docs":{"26":{"tf":2.23606797749979},"28":{"tf":1.4142135623730951},"29":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"44":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"6":{"tf":1.0}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"14":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"28":{"tf":1.0}}}}}},"w":{"a":{"df":0,"docs":{},"y":{"df":4,"docs":{"11":{"tf":1.0},"2":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"0":{"tf":1.0}}}}},"df":0,"docs":{}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"10":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"r":{"d":{"df":3,"docs":{"1":{"tf":2.23606797749979},"16":{"tf":1.0},"21":{"tf":1.0}}},"df":0,"docs":{},"k":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"46":{"tf":1.7320508075688772},"5":{"tf":1.0}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}}},"x":{"df":6,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"38":{"tf":2.0},"44":{"tf":1.4142135623730951},"45":{"tf":1.0},"46":{"tf":1.0}}},"y":{"df":3,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"46":{"tf":1.0}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"’":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"breadcrumbs":{"root":{"0":{".":{"0":{"df":1,"docs":{"14":{"tf":1.0}}},"df":0,"docs":{}},"df":4,"docs":{"14":{"tf":1.4142135623730951},"21":{"tf":1.0},"38":{"tf":1.0},"45":{"tf":1.0}}},"1":{"0":{"df":3,"docs":{"38":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0}}},"2":{"1":{"df":1,"docs":{"17":{"tf":1.0}}},"df":0,"docs":{}},"4":{"df":1,"docs":{"46":{"tf":1.0}}},"df":3,"docs":{"20":{"tf":1.0},"21":{"tf":1.4142135623730951},"34":{"tf":1.0}}},"2":{".":{"7":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"10":{"tf":2.449489742783178},"35":{"tf":1.4142135623730951},"45":{"tf":1.0}}},"3":{".":{"1":{"4":{"df":1,"docs":{"18":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"2":{"df":1,"docs":{"17":{"tf":1.0}}},"df":1,"docs":{"2":{"tf":1.0}}},"4":{"df":1,"docs":{"35":{"tf":1.0}}},"5":{"3":{"2":{"df":1,"docs":{"6":{"tf":1.0}}},"df":0,"docs":{}},"df":3,"docs":{"17":{"tf":1.0},"44":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}},"6":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}},"7":{"df":1,"docs":{"12":{"tf":1.0}}},"8":{"df":2,"docs":{"17":{"tf":1.0},"18":{"tf":1.0}}},"a":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"v":{"df":1,"docs":{"4":{"tf":1.0}}}}},"c":{"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":6,"docs":{"10":{"tf":2.449489742783178},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.0},"14":{"tf":1.4142135623730951},"9":{"tf":2.0}}}},"s":{"df":0,"docs":{},"s":{"df":7,"docs":{"11":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"45":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.4142135623730951},"50":{"tf":1.0}}}}}},"df":0,"docs":{}},"d":{"d":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"40":{"tf":1.0}}}}}},"df":2,"docs":{"41":{"tf":1.0},"9":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"c":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}},"df":0,"docs":{},"w":{"df":2,"docs":{"38":{"tf":1.0},"51":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":0,"docs":{},"i":{"df":1,"docs":{"40":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"a":{"df":0,"docs":{},"y":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"/":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"m":{"b":{"d":{"a":{"df":1,"docs":{"41":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"6":{"tf":1.4142135623730951}}}}},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"36":{"tf":1.0}}}}},"w":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"46":{"tf":1.4142135623730951}}}}}}}},"p":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"11":{"tf":1.0}}},"df":0,"docs":{}}}}},"r":{"df":0,"docs":{},"g":{"df":3,"docs":{"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"48":{"tf":1.4142135623730951}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":6,"docs":{"22":{"tf":1.0},"23":{"tf":1.4142135623730951},"29":{"tf":1.0},"41":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}}}}}}}},"r":{"a":{"df":0,"docs":{},"y":{"df":1,"docs":{"19":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"i":{"df":1,"docs":{"34":{"tf":1.0}}}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":2,"docs":{"26":{"tf":1.0},"50":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"t":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"29":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":5,"docs":{"16":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0},"48":{"tf":1.0},"50":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":3,"docs":{"16":{"tf":1.0},"28":{"tf":1.0},"51":{"tf":1.0}}}}},"df":0,"docs":{}}},"b":{"a":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"14":{"tf":1.0}}}}},"df":2,"docs":{"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951}},"e":{"df":1,"docs":{"49":{"tf":1.0}},"f":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":3,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"15":{"tf":1.0}}}}},"h":{"a":{"df":0,"docs":{},"v":{"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"w":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":3,"docs":{"11":{"tf":1.0},"4":{"tf":1.0},"51":{"tf":1.0}}}}}}},"y":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"36":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"11":{"tf":1.4142135623730951},"9":{"tf":1.4142135623730951}}}}},"df":0,"docs":{}},"t":{"df":1,"docs":{"32":{"tf":1.0}}}},"l":{"df":0,"docs":{},"o":{"c":{"df":0,"docs":{},"k":{"df":3,"docs":{"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"38":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"i":{"df":8,"docs":{"40":{"tf":1.7320508075688772},"41":{"tf":1.7320508075688772},"42":{"tf":1.0},"43":{"tf":1.7320508075688772},"48":{"tf":1.4142135623730951},"49":{"tf":1.4142135623730951},"50":{"tf":1.4142135623730951},"51":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}},"l":{"df":4,"docs":{"14":{"tf":1.0},"21":{"tf":2.0},"23":{"tf":1.4142135623730951},"34":{"tf":1.0}},"e":{"a":{"df":0,"docs":{},"n":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}}},"df":0,"docs":{}}}},"t":{"df":0,"docs":{},"h":{"df":2,"docs":{"10":{"tf":2.449489742783178},"9":{"tf":4.123105625617661}}}}},"r":{"a":{"c":{"df":0,"docs":{},"e":{"df":1,"docs":{"28":{"tf":1.0}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":4,"docs":{"12":{"tf":2.23606797749979},"13":{"tf":1.4142135623730951},"35":{"tf":1.0},"36":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"y":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":4,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"20":{"tf":1.4142135623730951},"21":{"tf":1.0}}}}}},"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":3,"docs":{"13":{"tf":1.7320508075688772},"30":{"tf":1.0},"31":{"tf":1.0}}}}},"df":7,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.4142135623730951},"20":{"tf":1.0},"21":{"tf":1.0},"23":{"tf":1.0},"34":{"tf":2.0}},"h":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":2,"docs":{"26":{"tf":1.0},"40":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":3,"docs":{"19":{"tf":1.0},"20":{"tf":1.0},"34":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"df":5,"docs":{"14":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":2.0},"21":{"tf":1.0},"34":{"tf":1.0}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"10":{"tf":2.449489742783178}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":1,"docs":{"30":{"tf":1.4142135623730951}}},"u":{"df":0,"docs":{},"r":{"df":4,"docs":{"29":{"tf":1.4142135623730951},"31":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951}}}}}}},"o":{"d":{"df":0,"docs":{},"e":{"df":8,"docs":{"15":{"tf":1.0},"3":{"tf":1.4142135623730951},"32":{"tf":1.0},"35":{"tf":1.7320508075688772},"36":{"tf":1.7320508075688772},"38":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"13":{"tf":1.4142135623730951},"22":{"tf":1.7320508075688772},"7":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"a":{"df":8,"docs":{"13":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.4142135623730951}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":5,"docs":{"2":{"tf":2.0},"3":{"tf":2.0},"4":{"tf":2.0},"5":{"tf":2.0},"6":{"tf":1.0}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"n":{"c":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{}},"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"35":{"tf":2.23606797749979},"36":{"tf":2.23606797749979}}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"30":{"tf":1.0}}}},"df":0,"docs":{}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"33":{"tf":1.0}}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"48":{"tf":1.0}}}}},"df":0,"docs":{}},"df":3,"docs":{"1":{"tf":1.0},"43":{"tf":1.0},"48":{"tf":3.0}}}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":4,"docs":{"28":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"31":{"tf":1.0}}}}},"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"32":{"tf":1.0}}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"s":{"df":2,"docs":{"11":{"tf":1.0},"51":{"tf":1.4142135623730951}}},"t":{"df":2,"docs":{"11":{"tf":1.0},"51":{"tf":1.0}}}}}}},"p":{"df":0,"docs":{},"i":{"df":4,"docs":{"31":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0},"50":{"tf":1.4142135623730951}}}},"r":{"df":0,"docs":{},"e":{"df":3,"docs":{"14":{"tf":1.7320508075688772},"16":{"tf":1.7320508075688772},"22":{"tf":1.0}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"p":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"d":{"df":4,"docs":{"11":{"tf":1.4142135623730951},"13":{"tf":1.0},"34":{"tf":1.0},"48":{"tf":1.0}}},"df":0,"docs":{}}}}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":6,"docs":{"14":{"tf":1.0},"22":{"tf":1.0},"28":{"tf":1.4142135623730951},"29":{"tf":1.4142135623730951},"44":{"tf":1.0},"48":{"tf":1.0}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"28":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"40":{"tf":1.0},"41":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}}}},"d":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"b":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":1,"docs":{"33":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"a":{"df":0,"docs":{},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":2,"docs":{"44":{"tf":1.0},"46":{"tf":1.0}}}}}},"df":4,"docs":{"1":{"tf":1.0},"40":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"6":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":13,"docs":{"11":{"tf":1.4142135623730951},"26":{"tf":1.0},"40":{"tf":1.7320508075688772},"41":{"tf":1.4142135623730951},"42":{"tf":1.0},"43":{"tf":1.7320508075688772},"44":{"tf":1.7320508075688772},"45":{"tf":1.7320508075688772},"47":{"tf":1.4142135623730951},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":16,"docs":{"26":{"tf":1.0},"29":{"tf":1.0},"39":{"tf":1.7320508075688772},"4":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"42":{"tf":1.7320508075688772},"43":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"y":{"df":4,"docs":{"28":{"tf":1.0},"29":{"tf":1.0},"30":{"tf":1.0},"49":{"tf":1.4142135623730951}}}},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":5,"docs":{"1":{"tf":1.0},"30":{"tf":2.23606797749979},"43":{"tf":1.0},"49":{"tf":3.0},"50":{"tf":1.0}}}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":2,"docs":{"1":{"tf":1.0},"38":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"10":{"tf":2.449489742783178}}}}}}}}},"i":{"c":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"8":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"f":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"51":{"tf":1.0},"9":{"tf":1.4142135623730951}}}}}},"v":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"9":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"c":{"df":1,"docs":{"0":{"tf":1.4142135623730951}},"u":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}},"df":1,"docs":{"38":{"tf":1.0}},"n":{"df":0,"docs":{},"e":{"df":1,"docs":{"2":{"tf":1.0}}}},"s":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"46":{"tf":1.0}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":5,"docs":{"10":{"tf":2.449489742783178},"14":{"tf":1.0},"18":{"tf":2.23606797749979},"34":{"tf":1.0},"9":{"tf":4.47213595499958}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":4,"docs":{"1":{"tf":1.0},"31":{"tf":2.449489742783178},"43":{"tf":1.0},"50":{"tf":2.8284271247461903}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"a":{"c":{"df":0,"docs":{},"h":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{},"s":{"df":1,"docs":{"47":{"tf":1.0}},"i":{"df":1,"docs":{"51":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}}}},"n":{"d":{"df":4,"docs":{"28":{"tf":1.0},"3":{"tf":1.0},"48":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"5":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"10":{"tf":2.449489742783178}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"a":{"df":0,"docs":{},"l":{"df":7,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0}}}},"df":0,"docs":{}}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":4,"docs":{"12":{"tf":1.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"x":{"a":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"10":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":10,"docs":{"17":{"tf":1.0},"18":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"6":{"tf":1.4142135623730951}}}}}},"c":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":2,"docs":{"15":{"tf":1.0},"8":{"tf":1.0}}}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":12,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"12":{"tf":2.23606797749979},"13":{"tf":1.4142135623730951},"14":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.4142135623730951},"36":{"tf":1.4142135623730951},"48":{"tf":1.0},"7":{"tf":2.0},"8":{"tf":2.0},"9":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}}},"f":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"s":{"df":5,"docs":{"10":{"tf":2.449489742783178},"14":{"tf":1.0},"21":{"tf":1.0},"34":{"tf":1.0},"36":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"d":{"df":11,"docs":{"11":{"tf":1.7320508075688772},"14":{"tf":1.4142135623730951},"24":{"tf":1.7320508075688772},"25":{"tf":1.7320508075688772},"30":{"tf":1.0},"31":{"tf":1.0},"34":{"tf":2.449489742783178},"43":{"tf":1.0},"44":{"tf":2.0},"46":{"tf":3.0},"48":{"tf":1.0}}},"df":0,"docs":{}}},"l":{"df":0,"docs":{},"e":{"df":2,"docs":{"30":{"tf":1.0},"5":{"tf":1.0}}}},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":1,"docs":{"29":{"tf":1.0}}}}}}},"l":{"df":0,"docs":{},"o":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":3,"docs":{"33":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}}},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"0":{"tf":1.0},"34":{"tf":2.8284271247461903}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":1,"docs":{"30":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"n":{"(":{"(":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":1,"docs":{"31":{"tf":1.0}}}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"23":{"tf":1.0}}}}}},"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":14,"docs":{"13":{"tf":2.449489742783178},"23":{"tf":2.0},"28":{"tf":1.0},"29":{"tf":3.0},"31":{"tf":1.0},"34":{"tf":1.0},"37":{"tf":1.0},"39":{"tf":1.7320508075688772},"4":{"tf":1.0},"40":{"tf":3.4641016151377544},"41":{"tf":3.4641016151377544},"45":{"tf":1.0},"50":{"tf":1.0},"6":{"tf":1.0}},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"40":{"tf":1.4142135623730951}},"e":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"’":{"df":3,"docs":{"13":{"tf":1.0},"29":{"tf":1.4142135623730951},"37":{"tf":1.0}}}}}}}},"df":4,"docs":{"13":{"tf":1.4142135623730951},"23":{"tf":1.7320508075688772},"30":{"tf":1.0},"34":{"tf":1.0}},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"6":{"tf":2.23606797749979}}},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"u":{"df":0,"docs":{},"m":{"b":{"df":1,"docs":{"6":{"tf":1.7320508075688772}}},"df":0,"docs":{}}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"0":{"tf":1.0},"38":{"tf":1.0}}}}},"t":{"df":1,"docs":{"14":{"tf":1.0}}}},"i":{"df":0,"docs":{},"v":{"df":0,"docs":{},"e":{"df":1,"docs":{"6":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"e":{"df":2,"docs":{"30":{"tf":1.0},"49":{"tf":1.0}}}},"r":{"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":2.0}}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":9,"docs":{"1":{"tf":1.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"38":{"tf":3.3166247903554}},"v":{"df":0,"docs":{},"m":{"df":1,"docs":{"1":{"tf":1.0}}}}},"df":0,"docs":{}}}}}},"h":{"a":{"df":0,"docs":{},"n":{"d":{"df":0,"docs":{},"l":{"df":1,"docs":{"47":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"p":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}},"df":0,"docs":{},"l":{"d":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"e":{"df":3,"docs":{"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}}}}},"i":{"df":1,"docs":{"46":{"tf":1.0}},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"8":{"tf":1.0}}}}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":13,"docs":{"1":{"tf":1.0},"11":{"tf":1.4142135623730951},"13":{"tf":1.0},"14":{"tf":1.0},"16":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"48":{"tf":1.4142135623730951}}}}}}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":3,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}}}}},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"45":{"tf":1.0}}}}}}},"df":0,"docs":{}}}}},"n":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"36":{"tf":1.0}}}},"o":{"df":1,"docs":{"33":{"tf":1.0}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":4,"docs":{"24":{"tf":1.0},"25":{"tf":1.0},"48":{"tf":1.0},"51":{"tf":1.0}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}}}},"p":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"6":{"tf":1.0}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.4142135623730951}}}}},"i":{"d":{"df":12,"docs":{"12":{"tf":1.4142135623730951},"13":{"tf":1.0},"28":{"tf":1.4142135623730951},"29":{"tf":1.0},"3":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"43":{"tf":1.0},"46":{"tf":1.4142135623730951},"51":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"0":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"6":{"4":{"_":{"df":0,"docs":{},"t":{"df":1,"docs":{"17":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":12,"docs":{"10":{"tf":2.0},"14":{"tf":1.7320508075688772},"17":{"tf":1.7320508075688772},"23":{"tf":1.0},"30":{"tf":1.0},"34":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"6":{"tf":1.0},"9":{"tf":2.0}},"e":{"df":0,"docs":{},"g":{"df":7,"docs":{"10":{"tf":1.4142135623730951},"17":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"9":{"tf":4.0}}},"n":{"d":{"df":1,"docs":{"32":{"tf":1.0}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}},"t":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"f":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}}}},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":0,"docs":{},"p":{"df":1,"docs":{"38":{"tf":1.0}}}},"y":{"df":1,"docs":{"34":{"tf":2.0}},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":2,"docs":{"14":{"tf":1.0},"42":{"tf":1.0}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"n":{"d":{"df":3,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"38":{"tf":1.4142135623730951}},"n":{"df":2,"docs":{"15":{"tf":1.0},"26":{"tf":1.0}}}}}}},"l":{"a":{"df":0,"docs":{},"m":{"b":{"d":{"a":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"41":{"tf":1.0}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"41":{"tf":1.0}}}}}},"df":2,"docs":{"1":{"tf":1.0},"41":{"tf":1.4142135623730951}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"u":{"a":{"df":0,"docs":{},"g":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":2.0},"11":{"tf":1.4142135623730951}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":1,"docs":{"14":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":2.0}}}}}}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"27":{"tf":1.4142135623730951}}}}}}},"n":{"df":0,"docs":{},"e":{"df":4,"docs":{"1":{"tf":1.0},"3":{"tf":1.7320508075688772},"33":{"tf":1.0},"5":{"tf":1.0}}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"26":{"tf":1.0},"34":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}}}},"m":{"a":{"d":{"df":0,"docs":{},"e":{"df":1,"docs":{"46":{"tf":1.0}}}},"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":1,"docs":{"48":{"tf":1.0}}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"48":{"tf":1.0}}}},"df":0,"docs":{}}},"r":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"4":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}}},"d":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"k":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"n":{"df":2,"docs":{"15":{"tf":1.0},"46":{"tf":1.0}}}},"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"45":{"tf":1.0}}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":2,"docs":{"30":{"tf":1.0},"31":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"df":6,"docs":{"11":{"tf":1.7320508075688772},"43":{"tf":1.4142135623730951},"45":{"tf":2.0},"46":{"tf":2.0},"47":{"tf":1.7320508075688772},"51":{"tf":2.8284271247461903}}},"df":0,"docs":{}}}}},"i":{"d":{"d":{"df":0,"docs":{},"l":{"df":1,"docs":{"5":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"s":{"c":{"df":2,"docs":{"11":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":5,"docs":{"26":{"tf":1.0},"28":{"tf":1.0},"29":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0}}}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.4142135623730951}}}}},"p":{"df":0,"docs":{},"l":{"df":6,"docs":{"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.0}},"i":{"df":1,"docs":{"9":{"tf":1.0}}}}}}}}},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"df":1,"docs":{"45":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":1,"docs":{"51":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"(":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"g":{"df":1,"docs":{"48":{"tf":1.0}}}}},"df":0,"docs":{}},"df":7,"docs":{"44":{"tf":1.0},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"48":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0}}}},"df":0,"docs":{}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":10,"docs":{"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.4142135623730951},"40":{"tf":2.23606797749979},"41":{"tf":1.0},"42":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0},"48":{"tf":1.0},"50":{"tf":1.0}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"d":{"df":2,"docs":{"49":{"tf":1.0},"51":{"tf":1.0}}},"df":0,"docs":{}},"w":{"df":7,"docs":{"1":{"tf":1.4142135623730951},"14":{"tf":1.7320508075688772},"22":{"tf":1.0},"31":{"tf":1.0},"33":{"tf":1.0},"50":{"tf":1.4142135623730951},"51":{"tf":1.0}},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"48":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":4,"docs":{"1":{"tf":1.0},"38":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}}}},"w":{"df":2,"docs":{"0":{"tf":1.0},"6":{"tf":1.0}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"19":{"tf":1.0}}}},"m":{"b":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":6,"docs":{"10":{"tf":4.242640687119285},"18":{"tf":1.0},"34":{"tf":1.7320508075688772},"6":{"tf":2.23606797749979},"8":{"tf":1.0},"9":{"tf":2.0}}}}},"df":0,"docs":{}}}},"o":{"b":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}}}},"df":14,"docs":{"11":{"tf":2.6457513110645907},"14":{"tf":2.23606797749979},"24":{"tf":1.0},"25":{"tf":2.23606797749979},"30":{"tf":1.0},"31":{"tf":1.0},"34":{"tf":1.4142135623730951},"45":{"tf":1.0},"46":{"tf":1.4142135623730951},"47":{"tf":1.4142135623730951},"48":{"tf":2.0},"49":{"tf":1.7320508075688772},"50":{"tf":2.23606797749979},"51":{"tf":1.7320508075688772}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"31":{"tf":1.0},"50":{"tf":1.7320508075688772}}},"df":0,"docs":{}},"n":{"c":{"df":1,"docs":{"49":{"tf":1.0}}},"df":1,"docs":{"9":{"tf":2.0}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":8,"docs":{"32":{"tf":2.0},"33":{"tf":1.0},"34":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"7":{"tf":1.0}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}}}}}},"r":{"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":3,"docs":{"10":{"tf":1.4142135623730951},"8":{"tf":1.0},"9":{"tf":2.0}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"w":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":2,"docs":{"10":{"tf":2.449489742783178},"34":{"tf":1.0}}}}}}}}},"u":{"df":0,"docs":{},"t":{"df":3,"docs":{"30":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}},"s":{"df":0,"docs":{},"i":{"d":{"df":1,"docs":{"12":{"tf":1.0}}},"df":0,"docs":{}}}}},"v":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}}},"w":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"40":{"tf":1.0}}}}}}}}}}}}},"p":{"a":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":5,"docs":{"24":{"tf":1.0},"25":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.0}}}},"r":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":3,"docs":{"40":{"tf":1.7320508075688772},"41":{"tf":1.7320508075688772},"48":{"tf":1.4142135623730951}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"28":{"tf":1.0}}}}},"t":{"df":2,"docs":{"0":{"tf":1.0},"3":{"tf":1.0}}}},"s":{"df":0,"docs":{},"s":{"df":4,"docs":{"31":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0},"50":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"35":{"tf":1.0}}}}},"l":{"a":{"c":{"df":0,"docs":{},"e":{"df":3,"docs":{"12":{"tf":1.0},"13":{"tf":1.0},"4":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"18":{"tf":1.0},"5":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"23":{"tf":1.0}}}}}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"r":{"a":{"df":0,"docs":{},"g":{"df":0,"docs":{},"m":{"a":{"df":1,"docs":{"1":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"e":{"d":{"df":4,"docs":{"10":{"tf":2.449489742783178},"12":{"tf":1.0},"8":{"tf":1.4142135623730951},"9":{"tf":2.0}}},"df":0,"docs":{}}},"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"18":{"tf":1.0}}}}},"df":0,"docs":{}},"v":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"df":3,"docs":{"26":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}}}}},"i":{"d":{"6":{"4":{"df":1,"docs":{"34":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":2,"docs":{"33":{"tf":1.0},"34":{"tf":2.23606797749979}},"f":{"(":{"\\"":{"%":{"c":{"df":1,"docs":{"34":{"tf":1.0}}},"df":1,"docs":{"34":{"tf":1.0}},"f":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":1,"docs":{"34":{"tf":1.0}}}}},"v":{"a":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.0},"46":{"tf":2.449489742783178}}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"r":{"a":{"df":0,"docs":{},"m":{"df":3,"docs":{"32":{"tf":1.0},"38":{"tf":1.0},"46":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":1,"docs":{"34":{"tf":1.4142135623730951}}}}}}},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.0},"46":{"tf":2.23606797749979}}}},"df":0,"docs":{}}},"v":{"df":0,"docs":{},"i":{"d":{"df":9,"docs":{"1":{"tf":1.0},"10":{"tf":3.1622776601683795},"14":{"tf":2.23606797749979},"29":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"47":{"tf":1.0},"48":{"tf":1.0},"51":{"tf":1.0}}},"df":0,"docs":{}}}}},"u":{"b":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":1,"docs":{"46":{"tf":1.0}}},"df":0,"docs":{}}}},"df":0,"docs":{},"t":{"df":7,"docs":{"1":{"tf":1.0},"31":{"tf":1.0},"33":{"tf":1.7320508075688772},"35":{"tf":1.0},"36":{"tf":1.0},"38":{"tf":1.0},"6":{"tf":1.0}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}}}}}}}}},"r":{"df":0,"docs":{},"e":{"a":{"d":{"df":1,"docs":{"46":{"tf":1.7320508075688772}}},"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"16":{"tf":1.0}}}}}}}},"df":0,"docs":{},"g":{"a":{"df":0,"docs":{},"r":{"d":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":1,"docs":{"1":{"tf":1.0}}}}}}},"df":0,"docs":{}}},"df":0,"docs":{}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":7,"docs":{"21":{"tf":1.0},"23":{"tf":1.4142135623730951},"24":{"tf":1.7320508075688772},"25":{"tf":1.7320508075688772},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.0}}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"i":{"df":0,"docs":{},"r":{"df":1,"docs":{"48":{"tf":1.0}}}}}},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":3,"docs":{"1":{"tf":2.449489742783178},"16":{"tf":1.0},"21":{"tf":1.0}}}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":19,"docs":{"1":{"tf":1.0},"10":{"tf":2.449489742783178},"11":{"tf":1.4142135623730951},"12":{"tf":1.0},"13":{"tf":1.4142135623730951},"14":{"tf":1.4142135623730951},"23":{"tf":1.4142135623730951},"29":{"tf":1.0},"37":{"tf":2.23606797749979},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"45":{"tf":1.4142135623730951},"46":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.0},"51":{"tf":1.0},"6":{"tf":1.4142135623730951},"9":{"tf":2.0}}}}}}},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":0,"docs":{},"t":{"df":2,"docs":{"10":{"tf":2.0},"11":{"tf":1.7320508075688772}}}}}},"u":{"df":0,"docs":{},"n":{"df":4,"docs":{"29":{"tf":1.0},"32":{"tf":1.0},"35":{"tf":1.7320508075688772},"36":{"tf":1.7320508075688772}}},"s":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}}}},"s":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"10":{"tf":2.0},"37":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}}},"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":6,"docs":{"27":{"tf":1.7320508075688772},"28":{"tf":1.7320508075688772},"29":{"tf":2.6457513110645907},"30":{"tf":1.4142135623730951},"31":{"tf":1.0},"49":{"tf":1.0}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"e":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0}}},"l":{"df":0,"docs":{},"f":{".":{"df":0,"docs":{},"x":{"df":1,"docs":{"45":{"tf":1.0}}}},"df":6,"docs":{"31":{"tf":1.0},"45":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"50":{"tf":1.4142135623730951},"51":{"tf":1.0}}}},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":9,"docs":{"1":{"tf":1.0},"13":{"tf":1.0},"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"34":{"tf":1.4142135623730951},"40":{"tf":1.0},"41":{"tf":1.0},"48":{"tf":1.4142135623730951}}}}},"q":{"df":0,"docs":{},"u":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"c":{"df":1,"docs":{"34":{"tf":1.4142135623730951}}},"df":0,"docs":{}}}}},"t":{"df":3,"docs":{"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}},"h":{"df":0,"docs":{},"e":{"b":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"5":{"tf":1.7320508075688772}}}}},"df":0,"docs":{}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"w":{"df":1,"docs":{"0":{"tf":1.0}}}}},"i":{"d":{"df":0,"docs":{},"e":{"df":2,"docs":{"10":{"tf":2.8284271247461903},"9":{"tf":4.123105625617661}}}},"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"48":{"tf":1.0}}}}}},"df":2,"docs":{"17":{"tf":1.0},"20":{"tf":1.0}},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"10":{"tf":1.4142135623730951},"9":{"tf":2.0}}},"df":0,"docs":{}}}}}},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}}},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"3":{"tf":1.4142135623730951}}}}},"z":{"df":0,"docs":{},"e":{"df":1,"docs":{"14":{"tf":1.7320508075688772}},"o":{"df":0,"docs":{},"f":{"df":2,"docs":{"1":{"tf":1.0},"14":{"tf":1.0}}}}}}},"n":{"a":{"df":0,"docs":{},"p":{"df":0,"docs":{},"s":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"t":{"df":1,"docs":{"29":{"tf":1.0}}}}}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"l":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"c":{"df":12,"docs":{"0":{"tf":1.4142135623730951},"1":{"tf":1.0},"15":{"tf":1.0},"16":{"tf":1.0},"2":{"tf":1.0},"3":{"tf":1.0},"38":{"tf":1.4142135623730951},"4":{"tf":1.0},"47":{"tf":1.0},"5":{"tf":1.4142135623730951},"6":{"tf":1.0},"7":{"tf":1.0}}},"df":0,"docs":{}}}}},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":4,"docs":{"14":{"tf":1.0},"33":{"tf":1.0},"38":{"tf":1.0},"6":{"tf":1.0}}}}}},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"8":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"r":{"c":{"df":1,"docs":{"5":{"tf":1.0}}},"df":0,"docs":{}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":1,"docs":{"0":{"tf":1.0}},"i":{"a":{"df":0,"docs":{},"l":{"df":3,"docs":{"43":{"tf":1.0},"46":{"tf":1.0},"47":{"tf":1.7320508075688772}}}},"df":0,"docs":{},"f":{"df":1,"docs":{"0":{"tf":1.0}},"i":{"df":4,"docs":{"13":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"51":{"tf":1.0}}}}}},"df":0,"docs":{}}},"t":{"a":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"33":{"tf":1.0}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"e":{"df":3,"docs":{"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}},"i":{"c":{"df":1,"docs":{"15":{"tf":1.0}}},"df":0,"docs":{}}}},"d":{"b":{"df":0,"docs":{},"o":{"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{".":{"df":0,"docs":{},"h":{"df":1,"docs":{"21":{"tf":1.4142135623730951}}}},"df":0,"docs":{}}}}},"df":0,"docs":{}},"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"1":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":2,"docs":{"20":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":7,"docs":{"14":{"tf":2.0},"19":{"tf":1.7320508075688772},"23":{"tf":1.4142135623730951},"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"34":{"tf":1.4142135623730951},"9":{"tf":2.0}}}}},"u":{"c":{"df":0,"docs":{},"t":{"df":14,"docs":{"1":{"tf":1.0},"24":{"tf":1.0},"34":{"tf":1.0},"4":{"tf":1.0},"42":{"tf":2.8284271247461903},"43":{"tf":2.0},"44":{"tf":1.7320508075688772},"45":{"tf":2.0},"46":{"tf":1.4142135623730951},"47":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.4142135623730951},"50":{"tf":1.4142135623730951},"51":{"tf":1.4142135623730951}},"n":{"a":{"df":0,"docs":{},"m":{"df":1,"docs":{"42":{"tf":1.4142135623730951}}}},"df":0,"docs":{}},"’":{"df":1,"docs":{"45":{"tf":1.0}}}}},"df":0,"docs":{}}},"y":{"df":0,"docs":{},"l":{"df":0,"docs":{},"e":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"u":{"b":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"28":{"tf":2.449489742783178}}}}},"df":0,"docs":{}},"t":{"df":0,"docs":{},"r":{"a":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"m":{"df":1,"docs":{"9":{"tf":1.4142135623730951}}},"r":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":2,"docs":{"35":{"tf":1.0},"36":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"y":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"a":{"df":0,"docs":{},"x":{"df":11,"docs":{"23":{"tf":1.0},"24":{"tf":1.0},"25":{"tf":1.0},"26":{"tf":1.0},"35":{"tf":1.0},"36":{"tf":1.0},"37":{"tf":1.0},"38":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0},"42":{"tf":1.0}}}},"df":0,"docs":{}}}}},"t":{"a":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":4,"docs":{"22":{"tf":1.0},"23":{"tf":1.0},"49":{"tf":1.0},"50":{"tf":1.0}}}},"r":{"df":0,"docs":{},"g":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":2,"docs":{"1":{"tf":1.0},"51":{"tf":1.0}}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":4,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0},"6":{"tf":1.0}}}},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":3,"docs":{"14":{"tf":2.0},"24":{"tf":2.0},"34":{"tf":1.0}},"e":{"(":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"24":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}}}},"r":{"df":0,"docs":{},"m":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"19":{"tf":1.0}}}}}},"x":{"df":0,"docs":{},"t":{"df":3,"docs":{"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}}}},"h":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"38":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"g":{"df":0,"docs":{},"h":{"df":3,"docs":{"40":{"tf":1.0},"41":{"tf":1.0},"45":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":4,"docs":{"26":{"tf":1.0},"29":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"5":{"tf":1.0}}}},"r":{"a":{"c":{"df":0,"docs":{},"k":{"df":1,"docs":{"38":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{},"e":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"1":{"tf":1.0}}}},"df":0,"docs":{}},"u":{"df":0,"docs":{},"e":{"df":5,"docs":{"10":{"tf":2.449489742783178},"21":{"tf":1.0},"34":{"tf":1.4142135623730951},"35":{"tf":1.7320508075688772},"36":{"tf":1.4142135623730951}}}}},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"11":{"tf":1.0}}}},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"0":{"tf":1.0}}}}}}},"w":{"df":0,"docs":{},"o":{"df":3,"docs":{"10":{"tf":3.4641016151377544},"4":{"tf":1.0},"9":{"tf":3.7416573867739413}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":25,"docs":{"10":{"tf":1.4142135623730951},"11":{"tf":1.7320508075688772},"13":{"tf":2.6457513110645907},"14":{"tf":1.7320508075688772},"15":{"tf":2.23606797749979},"16":{"tf":2.0},"17":{"tf":1.0},"18":{"tf":1.0},"19":{"tf":1.0},"20":{"tf":1.0},"21":{"tf":1.0},"22":{"tf":2.449489742783178},"23":{"tf":2.6457513110645907},"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"26":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"37":{"tf":1.4142135623730951},"38":{"tf":1.4142135623730951},"40":{"tf":2.23606797749979},"41":{"tf":2.0},"48":{"tf":1.0},"51":{"tf":3.0},"8":{"tf":1.4142135623730951}}}}}},"u":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.4142135623730951}}}}},"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":1,"docs":{"24":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"g":{"df":0,"docs":{},"n":{"df":1,"docs":{"21":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":3,"docs":{"3":{"tf":1.0},"36":{"tf":1.0},"5":{"tf":1.0}}}}}},"p":{"d":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}},"s":{"df":14,"docs":{"1":{"tf":1.4142135623730951},"20":{"tf":1.4142135623730951},"3":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.0},"38":{"tf":1.0},"4":{"tf":1.4142135623730951},"41":{"tf":1.0},"47":{"tf":1.0},"48":{"tf":1.4142135623730951},"49":{"tf":1.0},"5":{"tf":1.4142135623730951},"50":{"tf":1.0},"51":{"tf":1.0}},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"48":{"tf":1.0},"6":{"tf":1.0}}}},"r":{"/":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"/":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"v":{"df":2,"docs":{"5":{"tf":1.0},"6":{"tf":1.0}}}}}},"df":0,"docs":{}}}},"df":0,"docs":{}},"df":0,"docs":{}},"u":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"s":{"df":1,"docs":{"22":{"tf":1.0}}}}}}}},"v":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"u":{"df":13,"docs":{"10":{"tf":2.449489742783178},"15":{"tf":1.0},"26":{"tf":1.7320508075688772},"34":{"tf":2.449489742783178},"37":{"tf":2.0},"38":{"tf":1.0},"40":{"tf":1.4142135623730951},"41":{"tf":1.0},"44":{"tf":1.0},"49":{"tf":1.0},"51":{"tf":1.0},"7":{"tf":1.0},"9":{"tf":4.58257569495584}}}},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":9,"docs":{"26":{"tf":2.6457513110645907},"28":{"tf":1.4142135623730951},"29":{"tf":1.4142135623730951},"30":{"tf":1.0},"31":{"tf":1.4142135623730951},"40":{"tf":1.4142135623730951},"41":{"tf":1.4142135623730951},"44":{"tf":1.0},"7":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"6":{"tf":1.0}}},"s":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":1,"docs":{"14":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"w":{"df":1,"docs":{"28":{"tf":1.0}}}}}},"w":{"a":{"df":0,"docs":{},"y":{"df":4,"docs":{"11":{"tf":1.0},"2":{"tf":1.0},"44":{"tf":1.0},"45":{"tf":1.0}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"m":{"df":1,"docs":{"0":{"tf":1.0}}}}},"df":0,"docs":{}}},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":2,"docs":{"10":{"tf":1.4142135623730951},"7":{"tf":1.0}}}}}}}},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}},"o":{"df":0,"docs":{},"r":{"d":{"df":3,"docs":{"1":{"tf":2.6457513110645907},"16":{"tf":1.0},"21":{"tf":1.0}}},"df":0,"docs":{},"k":{"df":2,"docs":{"3":{"tf":1.0},"4":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"df":2,"docs":{"46":{"tf":1.7320508075688772},"5":{"tf":1.0}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":1,"docs":{"0":{"tf":1.0}}}}}}}}},"x":{"df":6,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"38":{"tf":2.0},"44":{"tf":1.4142135623730951},"45":{"tf":1.0},"46":{"tf":1.0}}},"y":{"df":3,"docs":{"24":{"tf":1.4142135623730951},"25":{"tf":1.4142135623730951},"46":{"tf":1.0}},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"’":{"df":0,"docs":{},"r":{"df":1,"docs":{"38":{"tf":1.0}}}}}}}}},"title":{"root":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":0,"docs":{},"y":{"df":0,"docs":{},"m":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"s":{"/":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"m":{"b":{"d":{"a":{"df":1,"docs":{"41":{"tf":1.0}}},"df":0,"docs":{}},"df":0,"docs":{}},"df":0,"docs":{}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}}}}}},"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":3,"docs":{"10":{"tf":1.0},"11":{"tf":1.0},"9":{"tf":1.0}}}}},"df":0,"docs":{}}},"o":{"d":{"df":0,"docs":{},"i":{"df":1,"docs":{"43":{"tf":1.0}}}},"df":0,"docs":{},"o":{"df":0,"docs":{},"l":{"df":1,"docs":{"21":{"tf":1.0}}}}},"r":{"a":{"c":{"df":0,"docs":{},"k":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":1,"docs":{"12":{"tf":1.0}}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"c":{"a":{"df":0,"docs":{},"l":{"df":0,"docs":{},"l":{"df":1,"docs":{"13":{"tf":1.0}}}}},"df":0,"docs":{},"h":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"20":{"tf":1.0}}}},"df":0,"docs":{}},"o":{"df":0,"docs":{},"m":{"b":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"22":{"tf":1.0}}}}},"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":4,"docs":{"2":{"tf":1.0},"3":{"tf":1.0},"4":{"tf":1.0},"5":{"tf":1.0}}}}}},"p":{"a":{"df":0,"docs":{},"r":{"df":1,"docs":{"10":{"tf":1.0}}}},"df":0,"docs":{}}},"n":{"df":0,"docs":{},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":1,"docs":{"48":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"r":{"df":0,"docs":{},"e":{"df":1,"docs":{"16":{"tf":1.0}}}}}},"d":{"df":0,"docs":{},"e":{"df":0,"docs":{},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":3,"docs":{"44":{"tf":1.0},"45":{"tf":1.0},"47":{"tf":1.0}},"i":{"df":0,"docs":{},"t":{"df":2,"docs":{"39":{"tf":1.0},"42":{"tf":1.0}}}}}}},"s":{"df":0,"docs":{},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"df":2,"docs":{"30":{"tf":1.0},"49":{"tf":1.0}}}}}},"df":0,"docs":{}}}}}},"o":{"df":0,"docs":{},"u":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"18":{"tf":1.0}}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"c":{"df":2,"docs":{"31":{"tf":1.0},"50":{"tf":1.0}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"x":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"df":1,"docs":{"6":{"tf":1.0}}}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"s":{"df":2,"docs":{"7":{"tf":1.0},"8":{"tf":1.0}}}}}}}}},"f":{"df":0,"docs":{},"i":{"df":0,"docs":{},"e":{"df":0,"docs":{},"l":{"d":{"df":2,"docs":{"44":{"tf":1.0},"46":{"tf":1.0}}},"df":0,"docs":{}}}},"o":{"df":0,"docs":{},"r":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"34":{"tf":1.0}}}},"df":0,"docs":{}}}},"u":{"df":0,"docs":{},"n":{"c":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"o":{"df":0,"docs":{},"n":{"df":5,"docs":{"13":{"tf":1.0},"29":{"tf":1.0},"39":{"tf":1.0},"40":{"tf":1.0},"41":{"tf":1.0}}}}}}},"df":1,"docs":{"23":{"tf":1.0}}}}},"g":{"df":0,"docs":{},"r":{"df":0,"docs":{},"o":{"df":0,"docs":{},"u":{"df":0,"docs":{},"n":{"d":{"df":1,"docs":{"38":{"tf":1.0}}},"df":0,"docs":{}}}}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"t":{"df":1,"docs":{"17":{"tf":1.0}},"r":{"df":0,"docs":{},"o":{"d":{"df":0,"docs":{},"u":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"0":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}}}}},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"f":{"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"m":{"df":1,"docs":{"27":{"tf":1.0}}}}}}},"n":{"df":0,"docs":{},"e":{"df":1,"docs":{"3":{"tf":1.0}}}}}},"m":{"a":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"9":{"tf":1.0}}}},"df":0,"docs":{}}}}}},"df":0,"docs":{},"e":{"df":0,"docs":{},"t":{"df":0,"docs":{},"h":{"df":0,"docs":{},"o":{"d":{"df":3,"docs":{"45":{"tf":1.0},"47":{"tf":1.0},"51":{"tf":1.0}}},"df":0,"docs":{}}}}},"i":{"df":0,"docs":{},"s":{"c":{"df":2,"docs":{"11":{"tf":1.0},"14":{"tf":1.0}}},"df":0,"docs":{}}},"u":{"df":0,"docs":{},"l":{"df":0,"docs":{},"t":{"df":0,"docs":{},"i":{"df":0,"docs":{},"l":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":1,"docs":{"4":{"tf":1.0}}}}}}}}}},"n":{"a":{"df":0,"docs":{},"m":{"df":0,"docs":{},"e":{"df":1,"docs":{"40":{"tf":1.0}}}}},"df":0,"docs":{}},"o":{"b":{"df":0,"docs":{},"j":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"25":{"tf":1.0}}}},"df":0,"docs":{}}}},"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":1,"docs":{"32":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"v":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"46":{"tf":1.0}}}},"df":0,"docs":{}}},"o":{"df":0,"docs":{},"t":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"t":{"df":1,"docs":{"46":{"tf":1.0}}}},"df":0,"docs":{}}}}},"u":{"df":0,"docs":{},"t":{"df":1,"docs":{"33":{"tf":1.0}}}}},"r":{"df":0,"docs":{},"e":{"df":0,"docs":{},"s":{"df":0,"docs":{},"e":{"df":0,"docs":{},"r":{"df":0,"docs":{},"v":{"df":1,"docs":{"1":{"tf":1.0}}}}}},"t":{"df":0,"docs":{},"u":{"df":0,"docs":{},"r":{"df":0,"docs":{},"n":{"df":1,"docs":{"37":{"tf":1.0}}}}}}}},"s":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":2,"docs":{"27":{"tf":1.0},"29":{"tf":1.0}}}}}},"df":0,"docs":{},"h":{"df":0,"docs":{},"e":{"b":{"a":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"5":{"tf":1.0}}}}},"df":0,"docs":{}},"df":0,"docs":{}}},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":0,"docs":{},"l":{"df":1,"docs":{"3":{"tf":1.0}}}}}},"p":{"df":0,"docs":{},"e":{"c":{"df":0,"docs":{},"i":{"a":{"df":0,"docs":{},"l":{"df":1,"docs":{"47":{"tf":1.0}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":0,"docs":{},"n":{"df":0,"docs":{},"g":{"df":1,"docs":{"19":{"tf":1.0}}}}},"u":{"c":{"df":0,"docs":{},"t":{"df":2,"docs":{"42":{"tf":1.0},"43":{"tf":1.0}}}},"df":0,"docs":{}}}},"u":{"b":{"df":0,"docs":{},"s":{"c":{"df":0,"docs":{},"o":{"df":0,"docs":{},"p":{"df":1,"docs":{"28":{"tf":1.0}}}}},"df":0,"docs":{}}},"df":0,"docs":{}}},"t":{"df":0,"docs":{},"e":{"df":0,"docs":{},"m":{"df":0,"docs":{},"p":{"df":0,"docs":{},"l":{"a":{"df":0,"docs":{},"t":{"df":1,"docs":{"24":{"tf":1.0}}}},"df":0,"docs":{}}}}},"y":{"df":0,"docs":{},"p":{"df":0,"docs":{},"e":{"df":4,"docs":{"15":{"tf":1.0},"16":{"tf":1.0},"22":{"tf":1.0},"8":{"tf":1.0}}}}}},"u":{"df":0,"docs":{},"n":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"df":1,"docs":{"14":{"tf":1.0}}}}},"df":0,"docs":{}}},"v":{"a":{"df":0,"docs":{},"r":{"df":0,"docs":{},"i":{"a":{"b":{"df":0,"docs":{},"l":{"df":1,"docs":{"26":{"tf":1.0}}}},"df":0,"docs":{}},"df":0,"docs":{}}}},"df":0,"docs":{}},"w":{"df":0,"docs":{},"o":{"df":0,"docs":{},"r":{"d":{"df":1,"docs":{"1":{"tf":1.0}}},"df":0,"docs":{}}}}}}},"lang":"English","pipeline":["trimmer","stopWordFilter","stemmer"],"ref":"id","version":"0.9.5"},"results_options":{"limit_results":30,"teaser_word_count":30},"search_options":{"bool":"OR","expand":true,"fields":{"body":{"boost":1},"breadcrumbs":{"boost":1},"title":{"boost":2}}}}')); \ No newline at end of file diff --git a/docs/struct_definition.html b/docs/struct_definition.html new file mode 100644 index 0000000..23ce8c1 --- /dev/null +++ b/docs/struct_definition.html @@ -0,0 +1,388 @@ + + + + + + Struct Definition - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Struct Definition

+

Define a struct with the struct keyword.

+

Syntax:

+
struct StructName {
+    ...
+}
+
+

where:

+
    +
  • StructName is the name of your struct
  • +
  • ... is the body of your struct
  • +
+

Struct Body

+

Inside the struct body, you can:

+
    +
  • Define fields
  • +
  • Define methods
  • +
  • Define special methods (constructor, destructor, duplicator, as)
  • +
+

Defining fields

+

A field in a struct is defined in the same way as a variable.

+
struct MyStruct {
+    x = 5
+}
+
+

This creates a field named x with a default value of 5.

+

Defining methods

+

A method in a struct is defined in the same way as a named function.

+
struct MyStruct {
+    def myMethod() int {
+        return 0
+    }
+}
+
+

Methods have access to the struct’s members through the self object, which is implicitly passed.

+
struct MyStruct {
+
+    x = 10
+
+    def myMethod() int {
+        return self.x * 2
+    }
+}
+
+

Private and protected fields

+

A private field is a field which only methods inside the object can read and write.

+

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.

+

All other fields are public, meaning anywhere in the program can read or write these fields.

+

Methods and special methods are by default protected, however can be made private.

+
struct MyStruct {
+    private x = 10
+    protected y = "Hi"
+
+    private doSomething() int {
+        return 14
+    }
+}
+
+

Defining special methods

+

In Solstice, objects have some special methods which provide ease of use while handling these objects.

+

Constructor

+

A constructor is used to initialize an object with user-provided fields.

+

Define a constructor like this:

+
struct MyStruct {
+    constructor(args) {
+        ...
+    }
+}
+
+

where:

+
    +
  • args is multiple comma-seperated pairs of: +
      +
    • a type identifier for the parameter, and
    • +
    • an identifier (representing the parameter name)
    • +
    +
  • +
  • ... is the constructor body +
      +
    • The constructor body has access to the self object, which is how it can modify the newly created object.
    • +
    • The self object is automatically returned at the end of the constructor, however can be returned manually if required.
    • +
    +
  • +
+

Use a constructor like this:

+
MyStruct(args)
+
+

where:

+
    +
  • args is many comma-seperated expressions corresponding to the signature of the defined constructor
  • +
+

Destructor

+

A destructor is used to destroy an object once it goes out of scope.

+

Define a destructor like this:

+
struct MyStruct {
+    destructor {
+        ...
+    }
+}
+
+

where:

+
    +
  • ... is the destructor body +
      +
    • The destructor body has access to the self object, which is how it can access and modify the object which is being destroyed.
    • +
    • There is no need to return a value from the destructor.
    • +
    +
  • +
+

Note how the destructor does not take any arguments.

+

Duplicator

+

A duplicator is used to copy an object when it is assigned to a new name, or passed to a function.

+

Define a duplicator like this:

+
struct MyStruct {
+    duplicator {
+        ...
+    }
+}
+
+

where:

+
    +
  • ... is the duplicator body +
      +
    • The destructor body has access to the self and old objects. +
        +
      • The self object is the new duplication and will be automatically returned
      • +
      • The old object is the old object and will not be copied out
      • +
      +
    • +
    +
  • +
+

Note how the duplicator does not take any arguments.

+

As methods

+

As methods allow easy conversion between different types.

+

Define an as method like this:

+
struct MyStruct {
+    as type {
+        ...
+    }
+}
+
+

where:

+
    +
  • type is the type which the object will be converted to
  • +
  • ... is the as method body +
      +
    • The self object is avaliable inside the as method
    • +
    • You will need to initialize and return a new value with the specified type
    • +
    +
  • +
+

Use an as method like this:

+
myobj as type
+
+

where:

+
    +
  • myobj is an object with an as method which provides a conversion to type
  • +
  • type is the target type
  • +
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/toc-cb4e10de.js b/docs/toc-cb4e10de.js new file mode 100644 index 0000000..98fcdc3 --- /dev/null +++ b/docs/toc-cb4e10de.js @@ -0,0 +1,454 @@ +// Populate the sidebar +// +// This is a script, and not included directly in the page, to control the total size of the book. +// The TOC contains an entry for each page, so if each page includes a copy of the TOC, +// the total size of the page becomes O(n**2). +class MDBookSidebarScrollbox extends HTMLElement { + constructor() { + super(); + } + connectedCallback() { + this.innerHTML = '
  1. Introduction
  2. Specification
  3. Reserved Words
  4. Comments
  5. Expressions
  6. Types
  7. Variables
  8. Scoping
  9. Operators
  10. Function Definition
  11. Struct Definition
'; + // Set the current, active page, and reveal it if it's hidden + let current_page = document.location.href.toString().split('#')[0].split('?')[0]; + if (current_page.endsWith('/')) { + current_page += 'index.html'; + } + const links = Array.prototype.slice.call(this.querySelectorAll('a')); + const l = links.length; + for (let i = 0; i < l; ++i) { + const link = links[i]; + const href = link.getAttribute('href'); + if (href && !href.startsWith('#') && !/^(?:[a-z+]+:)?\/\//.test(href)) { + link.href = path_to_root + href; + } + // The 'index' page is supposed to alias the first chapter in the book. + if (link.href === current_page + || i === 0 + && path_to_root === '' + && current_page.endsWith('/index.html')) { + link.classList.add('active'); + let parent = link.parentElement; + while (parent) { + if (parent.tagName === 'LI' && parent.classList.contains('chapter-item')) { + parent.classList.add('expanded'); + } + parent = parent.parentElement; + } + } + } + // Track and set sidebar scroll position + this.addEventListener('click', e => { + if (e.target.tagName === 'A') { + const clientRect = e.target.getBoundingClientRect(); + const sidebarRect = this.getBoundingClientRect(); + sessionStorage.setItem('sidebar-scroll-offset', clientRect.top - sidebarRect.top); + } + }, { passive: true }); + const sidebarScrollOffset = sessionStorage.getItem('sidebar-scroll-offset'); + sessionStorage.removeItem('sidebar-scroll-offset'); + if (sidebarScrollOffset !== null) { + // preserve sidebar scroll position when navigating via links within sidebar + const activeSection = this.querySelector('.active'); + if (activeSection) { + const clientRect = activeSection.getBoundingClientRect(); + const sidebarRect = this.getBoundingClientRect(); + const currentOffset = clientRect.top - sidebarRect.top; + this.scrollTop += currentOffset - parseFloat(sidebarScrollOffset); + } + } else { + // scroll sidebar to current active section when navigating via + // 'next/previous chapter' buttons + const activeSection = document.querySelector('#mdbook-sidebar .active'); + if (activeSection) { + activeSection.scrollIntoView({ block: 'center' }); + } + } + // Toggle buttons + const sidebarAnchorToggles = document.querySelectorAll('.chapter-fold-toggle'); + function toggleSection(ev) { + ev.currentTarget.parentElement.parentElement.classList.toggle('expanded'); + } + Array.from(sidebarAnchorToggles).forEach(el => { + el.addEventListener('click', toggleSection); + }); + } +} +window.customElements.define('mdbook-sidebar-scrollbox', MDBookSidebarScrollbox); + + +// --------------------------------------------------------------------------- +// Support for dynamically adding headers to the sidebar. + +(function() { + // This is used to detect which direction the page has scrolled since the + // last scroll event. + let lastKnownScrollPosition = 0; + // This is the threshold in px from the top of the screen where it will + // consider a header the "current" header when scrolling down. + const defaultDownThreshold = 150; + // Same as defaultDownThreshold, except when scrolling up. + const defaultUpThreshold = 300; + // The threshold is a virtual horizontal line on the screen where it + // considers the "current" header to be above the line. The threshold is + // modified dynamically to handle headers that are near the bottom of the + // screen, and to slightly offset the behavior when scrolling up vs down. + let threshold = defaultDownThreshold; + // This is used to disable updates while scrolling. This is needed when + // clicking the header in the sidebar, which triggers a scroll event. It + // is somewhat finicky to detect when the scroll has finished, so this + // uses a relatively dumb system of disabling scroll updates for a short + // time after the click. + let disableScroll = false; + // Array of header elements on the page. + let headers; + // Array of li elements that are initially collapsed headers in the sidebar. + // I'm not sure why eslint seems to have a false positive here. + // eslint-disable-next-line prefer-const + let headerToggles = []; + // This is a debugging tool for the threshold which you can enable in the console. + let thresholdDebug = false; + + // Updates the threshold based on the scroll position. + function updateThreshold() { + const scrollTop = window.pageYOffset || document.documentElement.scrollTop; + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight; + + // The number of pixels below the viewport, at most documentHeight. + // This is used to push the threshold down to the bottom of the page + // as the user scrolls towards the bottom. + const pixelsBelow = Math.max(0, documentHeight - (scrollTop + windowHeight)); + // The number of pixels above the viewport, at least defaultDownThreshold. + // Similar to pixelsBelow, this is used to push the threshold back towards + // the top when reaching the top of the page. + const pixelsAbove = Math.max(0, defaultDownThreshold - scrollTop); + // How much the threshold should be offset once it gets close to the + // bottom of the page. + const bottomAdd = Math.max(0, windowHeight - pixelsBelow - defaultDownThreshold); + let adjustedBottomAdd = bottomAdd; + + // Adjusts bottomAdd for a small document. The calculation above + // assumes the document is at least twice the windowheight in size. If + // it is less than that, then bottomAdd needs to be shrunk + // proportional to the difference in size. + if (documentHeight < windowHeight * 2) { + const maxPixelsBelow = documentHeight - windowHeight; + const t = 1 - pixelsBelow / Math.max(1, maxPixelsBelow); + const clamp = Math.max(0, Math.min(1, t)); + adjustedBottomAdd *= clamp; + } + + let scrollingDown = true; + if (scrollTop < lastKnownScrollPosition) { + scrollingDown = false; + } + + if (scrollingDown) { + // When scrolling down, move the threshold up towards the default + // downwards threshold position. If near the bottom of the page, + // adjustedBottomAdd will offset the threshold towards the bottom + // of the page. + const amountScrolledDown = scrollTop - lastKnownScrollPosition; + const adjustedDefault = defaultDownThreshold + adjustedBottomAdd; + threshold = Math.max(adjustedDefault, threshold - amountScrolledDown); + } else { + // When scrolling up, move the threshold down towards the default + // upwards threshold position. If near the bottom of the page, + // quickly transition the threshold back up where it normally + // belongs. + const amountScrolledUp = lastKnownScrollPosition - scrollTop; + const adjustedDefault = defaultUpThreshold - pixelsAbove + + Math.max(0, adjustedBottomAdd - defaultDownThreshold); + threshold = Math.min(adjustedDefault, threshold + amountScrolledUp); + } + + if (documentHeight <= windowHeight) { + threshold = 0; + } + + if (thresholdDebug) { + const id = 'mdbook-threshold-debug-data'; + let data = document.getElementById(id); + if (data === null) { + data = document.createElement('div'); + data.id = id; + data.style.cssText = ` + position: fixed; + top: 50px; + right: 10px; + background-color: 0xeeeeee; + z-index: 9999; + pointer-events: none; + `; + document.body.appendChild(data); + } + data.innerHTML = ` + + + + + + + + + + +
documentHeight${documentHeight.toFixed(1)}
windowHeight${windowHeight.toFixed(1)}
scrollTop${scrollTop.toFixed(1)}
pixelsAbove${pixelsAbove.toFixed(1)}
pixelsBelow${pixelsBelow.toFixed(1)}
bottomAdd${bottomAdd.toFixed(1)}
adjustedBottomAdd${adjustedBottomAdd.toFixed(1)}
scrollingDown${scrollingDown}
threshold${threshold.toFixed(1)}
+ `; + drawDebugLine(); + } + + lastKnownScrollPosition = scrollTop; + } + + function drawDebugLine() { + if (!document.body) { + return; + } + const id = 'mdbook-threshold-debug-line'; + const existingLine = document.getElementById(id); + if (existingLine) { + existingLine.remove(); + } + const line = document.createElement('div'); + line.id = id; + line.style.cssText = ` + position: fixed; + top: ${threshold}px; + left: 0; + width: 100vw; + height: 2px; + background-color: red; + z-index: 9999; + pointer-events: none; + `; + document.body.appendChild(line); + } + + function mdbookEnableThresholdDebug() { + thresholdDebug = true; + updateThreshold(); + drawDebugLine(); + } + + window.mdbookEnableThresholdDebug = mdbookEnableThresholdDebug; + + // Updates which headers in the sidebar should be expanded. If the current + // header is inside a collapsed group, then it, and all its parents should + // be expanded. + function updateHeaderExpanded(currentA) { + // Add expanded to all header-item li ancestors. + let current = currentA.parentElement; + while (current) { + if (current.tagName === 'LI' && current.classList.contains('header-item')) { + current.classList.add('expanded'); + } + current = current.parentElement; + } + } + + // Updates which header is marked as the "current" header in the sidebar. + // This is done with a virtual Y threshold, where headers at or below + // that line will be considered the current one. + function updateCurrentHeader() { + if (!headers || !headers.length) { + return; + } + + // Reset the classes, which will be rebuilt below. + const els = document.getElementsByClassName('current-header'); + for (const el of els) { + el.classList.remove('current-header'); + } + for (const toggle of headerToggles) { + toggle.classList.remove('expanded'); + } + + // Find the last header that is above the threshold. + let lastHeader = null; + for (const header of headers) { + const rect = header.getBoundingClientRect(); + if (rect.top <= threshold) { + lastHeader = header; + } else { + break; + } + } + if (lastHeader === null) { + lastHeader = headers[0]; + const rect = lastHeader.getBoundingClientRect(); + const windowHeight = window.innerHeight; + if (rect.top >= windowHeight) { + return; + } + } + + // Get the anchor in the summary. + const href = '#' + lastHeader.id; + const a = [...document.querySelectorAll('.header-in-summary')] + .find(element => element.getAttribute('href') === href); + if (!a) { + return; + } + + a.classList.add('current-header'); + + updateHeaderExpanded(a); + } + + // Updates which header is "current" based on the threshold line. + function reloadCurrentHeader() { + if (disableScroll) { + return; + } + updateThreshold(); + updateCurrentHeader(); + } + + + // When clicking on a header in the sidebar, this adjusts the threshold so + // that it is located next to the header. This is so that header becomes + // "current". + function headerThresholdClick(event) { + // See disableScroll description why this is done. + disableScroll = true; + setTimeout(() => { + disableScroll = false; + }, 100); + // requestAnimationFrame is used to delay the update of the "current" + // header until after the scroll is done, and the header is in the new + // position. + requestAnimationFrame(() => { + requestAnimationFrame(() => { + // Closest is needed because if it has child elements like . + const a = event.target.closest('a'); + const href = a.getAttribute('href'); + const targetId = href.substring(1); + const targetElement = document.getElementById(targetId); + if (targetElement) { + threshold = targetElement.getBoundingClientRect().bottom; + updateCurrentHeader(); + } + }); + }); + } + + // Takes the nodes from the given head and copies them over to the + // destination, along with some filtering. + function filterHeader(source, dest) { + const clone = source.cloneNode(true); + clone.querySelectorAll('mark').forEach(mark => { + mark.replaceWith(...mark.childNodes); + }); + dest.append(...clone.childNodes); + } + + // Scans page for headers and adds them to the sidebar. + document.addEventListener('DOMContentLoaded', function() { + const activeSection = document.querySelector('#mdbook-sidebar .active'); + if (activeSection === null) { + return; + } + + const main = document.getElementsByTagName('main')[0]; + headers = Array.from(main.querySelectorAll('h2, h3, h4, h5, h6')) + .filter(h => h.id !== '' && h.children.length && h.children[0].tagName === 'A'); + + if (headers.length === 0) { + return; + } + + // Build a tree of headers in the sidebar. + + const stack = []; + + const firstLevel = parseInt(headers[0].tagName.charAt(1)); + for (let i = 1; i < firstLevel; i++) { + const ol = document.createElement('ol'); + ol.classList.add('section'); + if (stack.length > 0) { + stack[stack.length - 1].ol.appendChild(ol); + } + stack.push({level: i + 1, ol: ol}); + } + + // The level where it will start folding deeply nested headers. + const foldLevel = 3; + + for (let i = 0; i < headers.length; i++) { + const header = headers[i]; + const level = parseInt(header.tagName.charAt(1)); + + const currentLevel = stack[stack.length - 1].level; + if (level > currentLevel) { + // Begin nesting to this level. + for (let nextLevel = currentLevel + 1; nextLevel <= level; nextLevel++) { + const ol = document.createElement('ol'); + ol.classList.add('section'); + const last = stack[stack.length - 1]; + const lastChild = last.ol.lastChild; + // Handle the case where jumping more than one nesting + // level, which doesn't have a list item to place this new + // list inside of. + if (lastChild) { + lastChild.appendChild(ol); + } else { + last.ol.appendChild(ol); + } + stack.push({level: nextLevel, ol: ol}); + } + } else if (level < currentLevel) { + while (stack.length > 1 && stack[stack.length - 1].level > level) { + stack.pop(); + } + } + + const li = document.createElement('li'); + li.classList.add('header-item'); + li.classList.add('expanded'); + if (level < foldLevel) { + li.classList.add('expanded'); + } + const span = document.createElement('span'); + span.classList.add('chapter-link-wrapper'); + const a = document.createElement('a'); + span.appendChild(a); + a.href = '#' + header.id; + a.classList.add('header-in-summary'); + filterHeader(header.children[0], a); + a.addEventListener('click', headerThresholdClick); + const nextHeader = headers[i + 1]; + if (nextHeader !== undefined) { + const nextLevel = parseInt(nextHeader.tagName.charAt(1)); + if (nextLevel > level && level >= foldLevel) { + const toggle = document.createElement('a'); + toggle.classList.add('chapter-fold-toggle'); + toggle.classList.add('header-toggle'); + toggle.addEventListener('click', () => { + li.classList.toggle('expanded'); + }); + const toggleDiv = document.createElement('div'); + toggleDiv.textContent = '❱'; + toggle.appendChild(toggleDiv); + span.appendChild(toggle); + headerToggles.push(li); + } + } + li.appendChild(span); + + const currentParent = stack[stack.length - 1]; + currentParent.ol.appendChild(li); + } + + const onThisPage = document.createElement('div'); + onThisPage.classList.add('on-this-page'); + onThisPage.append(stack[0].ol); + const activeItemSpan = activeSection.parentElement; + activeItemSpan.after(onThisPage); + }); + + document.addEventListener('DOMContentLoaded', reloadCurrentHeader); + document.addEventListener('scroll', reloadCurrentHeader, { passive: true }); +})(); + diff --git a/docs/toc.html b/docs/toc.html new file mode 100644 index 0000000..4515923 --- /dev/null +++ b/docs/toc.html @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + +
  1. Introduction
  2. Specification
  3. Reserved Words
  4. Comments
  5. Expressions
  6. Types
  7. Variables
  8. Scoping
  9. Operators
  10. Function Definition
  11. Struct Definition
+ + diff --git a/docs/tomorrow-night-4c0ae647.css b/docs/tomorrow-night-4c0ae647.css new file mode 100644 index 0000000..11752b8 --- /dev/null +++ b/docs/tomorrow-night-4c0ae647.css @@ -0,0 +1,104 @@ +/* Tomorrow Night Theme */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* https://github.com/jmblog/color-themes-for-highlightjs */ + +/* Tomorrow Comment */ +.hljs-comment { + color: #969896; +} + +/* Tomorrow Red */ +.hljs-variable, +.hljs-attribute, +.hljs-attr, +.hljs-tag, +.hljs-regexp, +.ruby .hljs-constant, +.xml .hljs-tag .hljs-title, +.xml .hljs-pi, +.xml .hljs-doctype, +.html .hljs-doctype, +.css .hljs-id, +.css .hljs-class, +.css .hljs-pseudo { + color: #cc6666; +} + +/* Tomorrow Orange */ +.hljs-number, +.hljs-preprocessor, +.hljs-pragma, +.hljs-built_in, +.hljs-literal, +.hljs-params, +.hljs-constant { + color: #de935f; +} + +/* Tomorrow Yellow */ +.ruby .hljs-class .hljs-title, +.css .hljs-rule .hljs-attribute { + color: #f0c674; +} + +/* Tomorrow Green */ +.hljs-string, +.hljs-value, +.hljs-inheritance, +.hljs-header, +.hljs-name, +.ruby .hljs-symbol, +.xml .hljs-cdata { + color: #b5bd68; +} + +/* Tomorrow Aqua */ +.hljs-title, +.hljs-section, +.css .hljs-hexcolor { + color: #8abeb7; +} + +/* Tomorrow Blue */ +.hljs-function, +.python .hljs-decorator, +.python .hljs-title, +.ruby .hljs-function .hljs-title, +.ruby .hljs-title .hljs-keyword, +.perl .hljs-sub, +.javascript .hljs-title, +.coffeescript .hljs-title { + color: #81a2be; +} + +/* Tomorrow Purple */ +.hljs-keyword, +.javascript .hljs-function { + color: #b294bb; +} + +.hljs { + display: block; + overflow-x: auto; + background: #1d1f21; + color: #c5c8c6; +} + +.coffeescript .javascript, +.javascript .xml, +.tex .hljs-formula, +.xml .javascript, +.xml .vbscript, +.xml .css, +.xml .hljs-cdata { + opacity: 0.5; +} + +.hljs-addition { + color: #718c00; +} + +.hljs-deletion { + color: #c82829; +} diff --git a/docs/types.html b/docs/types.html new file mode 100644 index 0000000..12ca27f --- /dev/null +++ b/docs/types.html @@ -0,0 +1,296 @@ + + + + + + Types - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Types

+

Solstice is statically typed, meaning all values must have a known type before any code can be executed.

+

Core Types

+

These core types are automatically avaliable in Solstice. The words to identify them are reserved and cannot be reassigned.

+

int

+

8-byte signed integer, equivalent to C int64_t or Ground -int.

+

Examples: 32, 121, -5

+

double

+

8-byte double prescision floating point number, equivalent to C double or Ground -double.

+

Examples: 3.14, -2.7

+

string

+

C-style null-terminated array of characters. Equivalent to C char* or Ground -string.

+

char

+

1-byte signed integer, usually used to store a character, however can also be used to store bytes. Equivalent to C char or Ground -char.

+

bool

+

1-byte unsigned integer, either 1 or 0. Represented by the reserved words true and false. Equivalent to C char (no stdbool.h) or bool (with stdbool.h) or Ground -bool.

+

Combined Types

+

These types utilise core types to create new combinations. They take type arguments.

+

fun

+

Represents a function. Equivalent to Ground -function, or a C function pointer.

+

Syntax:

+
fun(...) type
+
+

where:

+
    +
  • type is a type identifier, which will be the return type
  • +
  • ... is multiple type identifiers, seperated by commas, which are the argument types
  • +
+

Example:

+
fun(int, string) bool
+
+

This represents a function which takes an int and string as arguments, and returns a bool.

+

template

+

Represents an uninitialized object. Equivalent to Ground -struct.

+

Syntax:

+
template(...)
+
+

where ... is multiple pairs of:

+
    +
  • a type identifier for the field, and
  • +
  • an identifier (representing the field name)
  • +
+

seperated by commas.

+

Example:

+
template(int x, string y)
+
+

This represents a template which, when initialized, has fields x (with integer) and y (with string).

+

object

+

Represents an initialized object.

+

Syntax:

+
object(...)
+
+

where ... is multiple pairs of:

+
    +
  • a type identifier for the field, and
  • +
  • an identifier (representing the field name)
  • +
+

seperated by commas.

+

Example:

+
object(int x, string y)
+
+

This represents a object which has fields x (with integer) and y (with string).

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/docs/variables.html b/docs/variables.html new file mode 100644 index 0000000..034cc57 --- /dev/null +++ b/docs/variables.html @@ -0,0 +1,244 @@ + + + + + + Variables - Solstice Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Keyboard shortcuts

+
+

Press or to navigate between chapters

+

Press S or / to search in the book

+

Press ? to show this help

+

Press Esc to hide this help

+
+
+
+
+ + + + + + + + + + + + + +
+ +
+
+ + + + + + + +
+
+

Variables

+

Variables are defined and modified with the syntax:

+
name = value
+
+

where:

+
    +
  • name is an identifier, and
  • +
  • value is a literal, expression, or identifier previously assigned to a variable.
  • +
+

All variables must have a known type and value at definition time. When updating a variable, the type may not change.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + +
+ +
+
+
+ + + + + + +
+
+

Function Definition

+

Named Functions

+

Define a named function with the following syntax:

+
def functionName(args) type {
+    ...
+}
+
+

where:

+
    +
  • functionName is the name of the function. +
      +
    • If functionName is already defined as a function or other value, it will only be overwritten if the type does not change.
    • +
    +
  • +
  • args is multiple comma-seperated pairs of: +
      +
    • a type identifier for the parameter, and
    • +
    • an identifier (representing the parameter name)
    • +
    +
  • +
  • type is the type of value which the function will return
  • +
  • ... is the code inside the function (the function body). +
      +
    • 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.
    • +
    • The function body will also have access to the parameters defined in args.
    • +
    +
  • +
+

Example:

+
def add(int a, int b) int {
+    return a + b
+}
+
+

Anonymous/Lambda functions

+

Define a lambda function with the following syntax:

+
lambda(args) type {
+    ...
+}
+
+

where:

+
    +
  • args is multiple comma-seperated pairs of: +
      +
    • a type identifier for the parameter, and
    • +
    • an identifier (representing the parameter name)
    • +
    +
  • +
  • type is the type of value which the function will return
  • +
  • ... is the code inside the function (the function body). +
      +
    • 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.
    • +
    • The function body will also have access to the parameters defined in args.
    • +
    +
  • +
+

Example:

+
add = lambda(int a, int b) int {
+    return a + b
+}
+
+

Lambda functions are most useful when passed as arguments to other functions.

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +