@graffiticode/basis 1.5.16 → 1.5.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1 -0
- package/package.json +4 -2
- package/spec/spec.html +528 -0
- package/spec/spec.md +332 -0
- package/src/compiler.js +45 -1
- package/src/lexicon.js +191 -0
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graffiticode/basis",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.18",
|
|
5
5
|
"description": "The basis library for creating Graffiticode languages",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "jest"
|
|
8
|
+
"test": "jest",
|
|
9
|
+
"build-spec": "npx spec-md ./spec/spec.md > ./spec/spec.html",
|
|
10
|
+
"watch-spec": "npx nodemon --exec 'npx spec-md > ./spec/spec.html' ./spec/spec.md"
|
|
9
11
|
},
|
|
10
12
|
"engines": {
|
|
11
13
|
"node": "22.x"
|
package/spec/spec.html
ADDED
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<!-- Built with spec-md https://spec-md.com -->
|
|
3
|
+
<html>
|
|
4
|
+
<head><meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"><title>Graffiticode Core Language Specification</title>
|
|
6
|
+
<style>@media (prefers-color-scheme: light){:root{--color-foreground: #333333;--color-background: #ffffff;--color-light-grey: #ccc;--color-grey: #666666;--color-white: #fff;--color-link: #3b5998;--color-subsection-link: var(--color-foreground);--color-toc-link: var(--color-foreground);--color-toc-id: var(--color-link);--color-toggle-border: #bbc;--color-sidebar-background: #f0f0f0;--color-sidebar-viewing-link: #8b9;--color-sidebar-toggle-button: rgba(0, 0, 0, .7);--color-sidebar-shadow-inset: rgba(0, 0, 0, .05);--color-sidebar-shadow: rgba(0, 0, 0, .04);--color-sidebar-large-shadow: rgba(0, 0, 0, .08);--color-pre-background: #fafafa;--color-pre-border: #e9e9e9;--color-code-background: rgba(0, 0, 0, .03);--color-spec-todo: var(--color-grey);--color-spec-example: #fafaff;--color-spec-example-border: #bbbbff;--color-spec-counter-example: #fffafa;--color-spec-counter-border: #ffbbbb;--color-spec-counter-example-link: #98593b;--color-spec-added-border: #396;--color-spec-removed-border: #933;--color-spec-prose: var(--color-grey);--color-spec-quantifier-list: var(--color-link);--color-spec-quantifier-optional: #83238e;--color-spec-condition: #1c7758;--color-spec-param: var(--color-grey);--color-spec-rx: var(--color-foreground);--color-spec-note-border: #f4e925;--color-spec-note-background: #fefef3;--color-spec-note-first-link: #6c6613;--color-source-link: var(--color-light-grey);--color-table-header: #f9f9f9;--color-table-header-border: #d0d0d0;--color-token-inserted: hsla(241, 71%, 34%, .69);--color-token-deleted: hsla(324, 92%, 33%, .74);--color-inserts-background: rgba(0, 200, 30, .08);--color-deletions-background: rgba(200, 0, 0, .08);--selection-background-color: #cacee0;--selection-background-color-link: #f0babe}.selection-link:hover{--selection-background-color: #3b5998}}@media (prefers-color-scheme: dark){:root{--color-foreground: #b6b6b6;--color-background: #262626;--color-light-grey: #373737;--color-grey: #828282;--color-white: rgb(29, 29, 29);--color-link: #89b7da;--color-subsection-link: var(--color-foreground);--color-toc-link: var(--color-foreground);--color-toc-id: var(--color-link);--color-toggle-border: #bbc;--color-sidebar-background: #323232;--color-sidebar-viewing-link: #8b9;--color-sidebar-toggle-button: rgba(220, 220, 220, .7);--color-sidebar-shadow-inset: rgba(0, 0, 0, .05);--color-sidebar-shadow: rgba(0, 0, 0, .04);--color-sidebar-large-shadow: rgba(0, 0, 0, .08);--color-pre-background: #2e2e2e;--color-pre-border: #3a3a3a;--color-code-background: rgba(41, 41, 41, .03);--color-spec-todo: var(--color-grey);--color-spec-example: #2b2b35;--color-spec-example-border: #4d4d6d;--color-spec-counter-example: #322828;--color-spec-counter-border: #664040;--color-spec-counter-example-link: #ff702d;--color-spec-added-border: #396;--color-spec-removed-border: #933;--color-spec-prose: var(--color-grey);--color-spec-quantifier-list: var(--color-link);--color-spec-quantifier-optional: #c689ce;--color-spec-condition: #6fa889;--color-spec-param: var(--color-grey);--color-spec-rx: var(--color-foreground);--color-spec-note-border: #605e39;--color-spec-note-background: #303028;--color-spec-note-first-link: #f0e330;--color-source-link: var(--color-grey);--color-table-header: #373737;--color-table-header-border: #525252;--color-token-inserted: hsla(241, 63%, 70%, .69);--color-token-deleted: hsla(325, 64%, 67%, .74);--color-inserts-background: rgba(0, 200, 30, .08);--color-deletions-background: rgba(200, 0, 0, .08);--selection-background-color: #656565;--selection-background-color-link: #f0babe}.selection-link:hover{--selection-background-color: #829edb}}:root{color:var(--color-foreground);background-color:var(--color-background);font-family:var(--font-family);font-size:15px;line-height:1.5;--mono-font-size: 13px;--indent: 1rem;--list-indent: 1.5rem;--dfn-indent: 0rem;--font-family: Cambria, "Palatino Linotype", Palatino, "Liberation Serif", serif;--font-family-monospace: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace}@media (min-width: 720px){:root{font-size:17px;--mono-font-size: 15px;--indent: 2rem;--list-indent: 2rem;--dfn-indent: 2rem}}body{margin:3rem 0 3rem}article{margin:0 1rem}@media (min-width: 720px){body{margin:6rem auto 3rem;max-width:800px;padding-left:75px;padding-right:clamp(0px,calc((100vw - 800px) * .25),75px)}}.source-link{display:none}@media screen and (min-width: 720px){.source-link{display:block;position:absolute;width:18px;fill:var(--color-source-link);opacity:.3}.source-link:hover{opacity:1}}.outdated-selection-link,.selection-link{position:absolute;display:block;color:var(--color-white);background:var(--selection-background-color);border-radius:4px;font-size:36px;height:23px;line-height:48px;text-align:center;text-decoration:none;width:25px;user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.outdated-selection-link:hover,.selection-link:hover{text-decoration:none}.outdated-selection-link:before,.selection-link:before{border:5px solid transparent;content:"";height:0;margin-top:-5px;margin-right:-5px;position:absolute;right:1px;top:50%;width:0}@media (max-width: 719px){.outdated-selection-link:before,.selection-link:before{border-bottom-color:var(--selection-background-color);border-top:0;right:50%;top:1px}}@media (min-width: 720px){.outdated-selection-link:before,.selection-link:before{border-left-color:var(--selection-background-color);border-right:0;right:1px;top:50%}}.outdated-selection-link{background:var(--selection-background-color-link);font-size:21px;font-weight:800;line-height:27px}.outdated-selection-link:hover:after{content:"This selection content has changed since this link was created.";font:9pt/11pt var(--font-family);position:absolute;display:block;white-space:nowrap;padding:2px 5px 1px;top:-20px;background:black;color:var(--color-white)}a{color:var(--color-link);text-decoration:none}a:hover{text-decoration:underline}img{max-width:100%}dl{margin:1rem 0 1rem var(--dfn-indent)}dd{margin:.25em 0 .5em var(--indent)}dd+dd{margin-top:1rem}dfn,.spec-ref{font-style:italic}dfn>a,.spec-ref>a{color:inherit}h1,h2,h3,h4,h5,h6{font-weight:bold;margin:3em 0 1em;position:relative}@media (min-width: 720px){header>h1{margin:6em 0 3em}}h1{font-size:1.5em;margin-top:5em}h2,h3{font-size:1.25em}h4,h5,h6{font-size:1em}section{padding-top:1rem;margin-top:-1rem}section.subsec>h6{margin-top:2em}section.subsec>h6>a{color:var(--color-subsection-link)}section .spec-secid{margin-right:1ex}@media (min-width: 720px){section .spec-secid{position:absolute;right:100%;text-align:right;white-space:nowrap}}footer{font-size:75%;opacity:.5;text-align:center;margin-top:12rem}.spec-toc{margin:1rem 0 3rem}.spec-toc .title{content:"Contents";display:block;font-weight:bold;margin:5em 0 1em}.spec-toc .spec-secid{margin-right:1ex}.spec-toc ol{list-style:none;padding-left:0;margin-top:0;margin-bottom:0}.spec-toc ol ol{list-style:none;padding-left:2ex;margin-bottom:.25em}.spec-toc li{position:relative;padding:5px 0 0 30px;margin:-5px 0 0 -30px}.spec-toc a{color:var(--color-toc-link)}.spec-toc a:hover{text-decoration:none}.spec-toc a .spec-secid{color:var(--color-toc-id)}.spec-toc a:hover .spec-secid{text-decoration:underline}.spec-toc .toggle{display:none}.spec-toc .toggle+label{cursor:pointer;left:6px;opacity:1;padding:5px 6px 5px 7px;position:absolute;top:6px;transform:rotate(0deg);transition:all .18s ease-in-out}.spec-toc .toggle+label:after{border-color:transparent transparent transparent var(--color-toggle-border);border-style:solid;border-width:6px 0 6px 7px;content:" ";display:block;height:0;width:0}@media (pointer: fine){.spec-toc .toggle+label{left:10px;padding:3px 5px 3px 6px;top:8px}}.spec-toc .toggle:checked+label{transform:rotate(90deg)}@media (hover: hover){.spec-toc li:not(:hover)>.toggle:checked+label{opacity:0}}.spec-toc .toggle:not(:checked)~ol{max-height:0;overflow:hidden;margin:0}.spec-sidebar-toggle{display:none}.spec-sidebar-toggle+label>.spec-sidebar-button{position:fixed;right:0;top:0;padding:10px 15px;font-size:30px;color:var(--color-sidebar-toggle-button);z-index:2;cursor:pointer;user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.spec-sidebar-toggle:checked+label:after{content:"";position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:0}.spec-sidebar{display:none;position:fixed;right:0;top:0;width:min(320px,calc(100vw - 48px));font-size:14px;line-height:1.75;overflow-y:scroll;height:100%;padding:0 0 5rem 30px;box-sizing:border-box;background:var(--color-sidebar-background);box-shadow:inset 1px 0 var(--color-sidebar-shadow-inset),-4px 0 8px -2px var(--color-sidebar-shadow);overscroll-behavior:contain}.spec-sidebar{user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.spec-sidebar-toggle:checked~.spec-sidebar{display:block}.spec-sidebar .viewing>a:after{color:var(--color-sidebar-viewing-link);content:"\2022";margin-left:1ex}@media (min-width: 1220px){.spec-sidebar-toggle+label{display:none}.spec-sidebar{display:block;box-shadow:inset 1px 0 var(--color-sidebar-shadow-inset),inset 4px 0 8px -2px var(--color-sidebar-large-shadow)!important}body{padding-right:345px}}.spec-note{background:var(--color-spec-note-background);border-left:solid 4px var(--color-spec-note-border);margin:1rem -1rem;min-width:70vw;padding:8px 1rem 12px calc(1rem - 4px);width:-moz-fit-content;width:-webkit-fit-content;width:fit-content}@media (min-width: 720px){.spec-note{min-width:416px}}.spec-note>a:first-child{color:var(--color-spec-note-first-link);display:block;font:italic 11pt/18pt var(--font-family);opacity:.6;user-select:none}.spec-todo{color:var(--color-spec-todo);margin:1em 0 1em 5em;min-height:1em}.spec-todo::before{content:"todo";display:block;float:left;margin-left:-5em;text-transform:uppercase}.spec-index ol{list-style-type:none;margin:0 0 0 var(--indent);padding:0;column-width:210px;column-gap:var(--indent)}.spec-index ol li{width:min-content;white-space:nowrap}pre,code{font-family:var(--font-family-monospace);font-size:var(--mono-font-size);font-weight:inherit}code{background:var(--color-code-background);margin:-2px -1px;padding:3px 3px;white-space:pre-wrap}pre>code{background:none;font-weight:inherit;margin:0;padding:0;white-space:pre}pre{background:var(--color-pre-background);border-left:solid 4px var(--color-pre-border);margin:1rem -1rem;min-width:70vw;padding:12px 1rem 12px calc(1rem - 4px);width:-moz-fit-content;width:-webkit-fit-content;width:fit-content;max-width:calc(100vw - 2rem);overflow-y:auto}@media (min-width: 720px){pre{min-width:40ch}}.spec-example{background:var(--color-spec-example);border-left:solid 4px var(--color-spec-example-border);padding-top:8px}.spec-counter-example{background:var(--color-spec-counter-example);border-left:solid 4px var(--color-spec-counter-border);padding-top:8px}.spec-example>a,.spec-counter-example>a{display:block;font:italic 11pt/18pt var(--font-family);opacity:.6;user-select:none}.spec-counter-example>a{color:var(--color-spec-counter-example-link)}table{border-collapse:collapse}th{background-color:var(--color-table-header)}td,th{border:1px solid var(--color-table-header-border);padding:.4em;vertical-align:baseline}ol,ul{padding-left:var(--list-indent)}li>ol,li>ul{margin-top:.25em;margin-bottom:.5em}li+li{margin-top:.25em}li.task{list-style-type:none;position:relative}li.task>input:first-child{margin-left:0;position:absolute;transform:translateX(calc(-100% - 1ch))}ins{background-color:var(--color-inserts-background);text-decoration:none}del{background-color:var(--color-deletions-background)}.spec-added,.spec-removed{border-left:4px solid;margin-left:-18px;padding-left:14px}.spec-added{border-color:var(--color-spec-added-border)}.spec-removed{border-color:var(--color-spec-removed-border);text-decoration:line-through}.spec-keyword{font-weight:bold}.spec-string{font-family:var(--font-family-monospace);font-size:85%;white-space:pre}var{font-style:italic}*[data-name]{transition:.15s background ease-out;border-radius:2px;padding:0 3px;margin:0 -3px}.spec-semantic,.spec-algo{margin:1rem 0 1rem var(--dfn-indent)}.spec-semantic>.spec-nt::after,.spec-algo>.spec-call:first-child::after{content:":";font-style:normal;font-weight:bold;margin-left:1ex}.spec-semantic ol,.spec-semantic ol ol ol ol,.spec-algo ol,.spec-algo ol ol ol ol{list-style-type:decimal}.spec-semantic ol ol,.spec-semantic ol ol ol ol ol,.spec-algo ol ol,.spec-algo ol ol ol ol ol{list-style-type:lower-alpha}.spec-semantic ol ol ol,.spec-semantic ol ol ol ol ol ol,.spec-algo ol ol ol,.spec-algo ol ol ol ol ol ol{list-style-type:lower-roman}.spec-call>a{color:inherit}.spec-production{margin:1rem 0 1rem var(--dfn-indent)}.spec-production>.spec-nt::after{content:":";font-style:normal;font-weight:bold;margin:0 1ex}.spec-semantic.d2>.spec-nt::after,.spec-production.d2>.spec-nt::after{content:"::"}.spec-semantic.d3>.spec-nt::after,.spec-production.d3>.spec-nt::after{content:":::"}.spec-production>.spec-rhs{line-height:1.1;margin:.25em 0 .5em calc(2 * var(--indent));text-indent:calc(-1 * var(--indent))}.spec-semantic>.spec-rhs{display:inline-block;text-indent:calc(-1 * var(--indent));margin-left:calc(1ex + var(--indent))}.spec-rhs>*{text-indent:0}.spec-oneof{display:inline}.spec-oneof::before{content:"one of";font-style:normal;font-weight:bold}.spec-oneof-grid{max-width:calc(100vw - 2rem);overflow:auto;margin:-1ex -1rem;padding:1ex 1rem}.spec-oneof-grid>table{margin-left:var(--indent)}.spec-oneof .spec-rhs{border:none;margin:0;padding:0 0 0 1rem;vertical-align:baseline;white-space:pre}.spec-oneof .spec-rhs:first-child{padding:0}.spec-rhs .spec-constrained:not(:first-child),.spec-rhs .spec-quantified:not(:first-child),.spec-rhs .spec-nt:not(:first-child),.spec-rhs .spec-t:not(:first-child),.spec-rhs .spec-rx:not(:first-child),.spec-rhs .spec-prose:not(:first-child),.spec-rhs .spec-empty:not(:first-child),.spec-rhs .spec-lookahead:not(:first-child){margin-left:1ex;display:inline-block}.spec-condition{font-size:85%}.spec-condition::before{content:"[if "}.spec-condition.not::before{content:"[if not "}.spec-condition::after{content:"]"}.spec-empty,.spec-prose{color:var(--color-spec-prose)}.spec-nt{font-style:italic}.spec-nt>a{color:inherit}.spec-quantifiers,.spec-params{font-size:65%;font-style:normal;vertical-align:sub}.spec-quantifier.list{color:var(--color-spec-quantifier-list)}.spec-quantifier.optional{color:var(--color-spec-quantifier-optional)}.spec-params,.spec-condition{color:var(--color-spec-condition)}.spec-params::before{content:"["}.spec-params::after{content:"]"}.spec-quantifier:not(:last-child)::after,.spec-param:not(:last-child)::after{color:var(--color-spec-param);content:", "}.spec-param.conditional::before{content:"?"}.spec-param.negated::before{content:"!"}.spec-t,.spec-rx{color:var(--color-spec-rx);font-family:var(--font-family-monospace);font-weight:bold}.spec-butnot::before{color:var(--color-grey);content:"but not";font-family:var(--font-family);font-weight:normal;margin-right:1ex}.spec-butnot>*:not(:first-child)::before{color:var(--color-grey);content:"or";font-family:var(--font-family);font-weight:normal;margin-right:1ex}.spec-rhs .spec-oneof::before,.spec-rhs .spec-butnot::before{margin-left:1ex}.spec-lookahead>*{margin:0!important}.spec-lookahead>*:not(:first-child)::before{color:var(--color-grey);content:", ";font-family:var(--font-family);font-style:normal;font-weight:normal}.spec-lookahead::before{color:var(--color-grey);content:"[lookahead = ";font-family:var(--font-family);font-style:normal;font-weight:normal}.spec-lookahead.not::before{content:"[lookahead \2260 "}.spec-lookahead.set::before{content:"[lookahead \2208 {";margin-right:0}.spec-lookahead.set.not::before{content:"[lookahead \2209 {"}.spec-lookahead.ntset::before{content:"[lookahead \2208 ";margin-right:0}.spec-lookahead.ntset.not::before{content:"[lookahead \2209 "}.spec-lookahead::after{color:var(--color-grey);content:"]"}.spec-lookahead.set::after{content:"}]"}code[class*=language-],pre[class*=language-]{color:var(--color-prism-foreground);background:none;text-shadow:0 1px var(--color-prism-text-shadow);font-family:var(--font-family-monospace);font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection{text-shadow:none;background:var(--color-prism-background)}pre[class*=language-]::selection,pre[class*=language-] ::selection,code[class*=language-]::selection,code[class*=language-] ::selection{text-shadow:none;background:var(--color-prism-background)}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:var(--color-prism-block-background)}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.atrule,.token.attr-value,.token.keyword,.token.property,.token.selector,.token.attr-name,.token.builtin,.token.entity,.token.url,.token.inserted{color:var(--color-token-inserted);background:none}.token.tag,.token.boolean,.token.number,.token.string,.token.char,.token.constant,.token.symbol,.token.regex,.token.important,.token.variable,.token.function,.token.class-name,.token.deleted{color:var(--color-token-deleted)}.token.comment,.token.prolog,.token.doctype,.token.cdata,.token.description{color:inherit;opacity:.3}.token.punctuation{color:inherit;opacity:.5}.token.operator,.token.namespace{color:inherit;opacity:.7}</style>
|
|
7
|
+
<script>(function(){var r,a=[];document.addEventListener("readystatechange",function(){document.readyState==="interactive"&&u()});function u(){var n=document.querySelector('label[for="spec-sidebar-toggle"]');n.addEventListener("scroll",o),n.addEventListener("touchmove",o);function o(d){d.preventDefault()}for(var t=document.getElementsByTagName("section"),e=0;e<t.length;e++)t[e].getAttribute("secid")&&a.push(t[e]);var i=window.scrollY,c=!1;window.addEventListener("scroll",function(d){i=window.scrollY,c||(c=!0,window.requestAnimationFrame(function(){s(i),c=!1}))})}function s(n){for(var o=n+document.documentElement.clientHeight/4,t,e=a.length-1;e>=0;e--)if(a[e].offsetTop<o){t=a[e];break}var i=t&&t.getAttribute("secid");i!==r&&(r&&l(r,!1),i&&l(i,!0),r=i)}function l(n,o){document.getElementById("_sidebar_"+n).className=o?"viewing":"";for(var t=n.split(".");t.length;){var e=document.getElementById("_toggle_"+t.join("."));e&&(e.checked=o),t.pop()}}s(window.scrollY);})();</script>
|
|
8
|
+
<script>(function(){var n=document.getElementsByTagName("style")[0].sheet,e;function u(){e&&(n.deleteRule(e),e=void 0)}function d(t){u(),e=n.insertRule('*[data-name="'+t+'"] { background: rgba(230,215,0,0.12); }',n.cssRules.length)}document.documentElement.addEventListener("mouseover",function(t){var a=t.target.attributes["data-name"];a&&d(a.value)});document.documentElement.addEventListener("mouseout",u);})();</script>
|
|
9
|
+
<script>(function(){var R="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",o,p,r,g;document.addEventListener("selectionchange",E);window.addEventListener("resize",C);window.addEventListener("hashchange",x);window.addEventListener("load",x);function S(n){y(new URL(n.target.href))}function x(){y(window.location)}function y(n){var e=n.hash.match(/^#sel-([A-Za-z0-9-_]+)$/);if(!!e){g=e[1],r=k(g);var t=r.getBoundingClientRect(),d=Math.max(20,Math.floor((window.innerHeight-t.height)*.4));window.scrollTo(0,window.scrollY+t.y-d);var c=document.getSelection();c.empty(),c.addRange(r),C()}}function E(n){var e=document.getSelection();if(e.isCollapsed)o&&(o.parentNode.removeChild(o),o=null);else{var t=e.getRangeAt(0);(!r||t.compareBoundaryPoints(Range.START_TO_START,r)!==0||t.compareBoundaryPoints(Range.END_TO_END,r)!==0)&&(r=t,g=B(r),C())}}function C(){if(!!r){p||(p=document.getElementsByTagName("article")[0]),o||(o=document.createElement("a"),document.body.appendChild(o)),o.href="#sel-"+g,o.onclick=S,o.className=r.isOutdated?"outdated-selection-link":"selection-link",o.innerText=r.isOutdated?"!":"\u201F";var n=window.innerWidth<720,e=r.getBoundingClientRect();if(n)o.style.left=Math.floor(e.x+e.width/2+window.scrollX-13)+"px",o.style.top=Math.floor(e.bottom+window.scrollY+10)+"px";else{var t=p.getBoundingClientRect().x;o.style.left=Math.floor(t+window.scrollX-37)+"px",o.style.top=Math.floor(e.y+window.scrollY-3)+"px"}}}function B(n){var e="",t=N(n.startContainer),d=N(n.endContainer),c=M(t,d);return l(c),l(t.slice(c.length).concat(n.startOffset)),l(d.slice(c.length).concat(n.endOffset)),i(L(n.toString())),e;function i(a){do e+=R[a&31|(a>31?32:0)],a>>=5;while(a>0)}function l(a){i(a.length);for(var h=0;h<a.length;h++)i(a[h])}}function k(n){for(var e=new Array(64),t=0;t<64;t++)e[R.charCodeAt(t)]=t;var d=0,c=m(),i=m(),l=m(),a=w(),h=i.pop(),P=O(c.concat(i)),T=l.pop(),A=O(c.concat(l)),u=document.createRange();return u.setStart(P,h),u.setEnd(A,T),u.isOutdated=a!==void 0&&a!==L(u.toString()),u;function w(){for(var s=0,v=0;d<n.length;){var f=e[n.charCodeAt(d++)];if(s|=(f&31)<<v,v+=5,f<32)return s}}function m(){var s=w();if(s!=null){for(var v=new Array(s),f=0;f<s;f++)v[f]=w();return v}}}function N(n){for(var e=[];n!=document.body;){var t=n.parentNode;e.push(Array.prototype.indexOf.call(t.childNodes,n)),n=t}return e.reverse()}function O(n){for(var e=document.body,t=0;t<n.length&&e;t++)e=e.childNodes[n[t]];return e}function M(n,e){for(var t=0;t<n.length&&t<e.length&&n[t]===e[t];)t++;return n.slice(0,t)}function L(n){for(var e=2166136261,t=0;t<n.length;++t)e^=n.charCodeAt(t),e+=(e<<1)+(e<<4)+(e<<7)+(e<<8)+(e<<24);return(e>>15^e)&32767}})();</script>
|
|
10
|
+
</head>
|
|
11
|
+
<body><article>
|
|
12
|
+
<header>
|
|
13
|
+
<h1>Graffiticode Core Language Specification</h1>
|
|
14
|
+
<nav class="spec-toc">
|
|
15
|
+
<div class="title">Contents</div>
|
|
16
|
+
<ol>
|
|
17
|
+
<li><a href="#sec-Introduction"><span class="spec-secid">1</span>Introduction</a></li>
|
|
18
|
+
<li><a href="#sec-Lexical-Structure"><span class="spec-secid">2</span>Lexical Structure</a><ol>
|
|
19
|
+
<li><a href="#sec-Tokens"><span class="spec-secid">2.1</span>Tokens</a></li>
|
|
20
|
+
<li><a href="#sec-Comments"><span class="spec-secid">2.2</span>Comments</a></li>
|
|
21
|
+
</ol>
|
|
22
|
+
</li>
|
|
23
|
+
<li><a href="#sec-Syntax"><span class="spec-secid">3</span>Syntax</a><ol>
|
|
24
|
+
<li><a href="#sec-Programs"><span class="spec-secid">3.1</span>Programs</a></li>
|
|
25
|
+
<li><a href="#sec-Expressions"><span class="spec-secid">3.2</span>Expressions</a><ol>
|
|
26
|
+
<li><a href="#sec-Function-Application"><span class="spec-secid">3.2.1</span>Function Application</a></li>
|
|
27
|
+
<li><a href="#sec-Lists"><span class="spec-secid">3.2.2</span>Lists</a></li>
|
|
28
|
+
<li><a href="#sec-Records"><span class="spec-secid">3.2.3</span>Records</a></li>
|
|
29
|
+
<li><a href="#sec-Lambdas"><span class="spec-secid">3.2.4</span>Lambdas</a></li>
|
|
30
|
+
<li><a href="#sec-Let-Bindings"><span class="spec-secid">3.2.5</span>Let Bindings</a></li>
|
|
31
|
+
</ol>
|
|
32
|
+
</li>
|
|
33
|
+
<li><a href="#sec-Pattern-Matching"><span class="spec-secid">3.3</span>Pattern Matching</a><ol>
|
|
34
|
+
<li><a href="#sec-Tag-Values"><span class="spec-secid">3.3.1</span>Tag Values</a></li>
|
|
35
|
+
</ol>
|
|
36
|
+
</li>
|
|
37
|
+
</ol>
|
|
38
|
+
</li>
|
|
39
|
+
<li><a href="#sec-Semantics"><span class="spec-secid">4</span>Semantics</a><ol>
|
|
40
|
+
<li><a href="#sec-Evaluation-Model"><span class="spec-secid">4.1</span>Evaluation Model</a></li>
|
|
41
|
+
<li><a href="#sec-Functions"><span class="spec-secid">4.2</span>Functions</a></li>
|
|
42
|
+
<li><a href="#sec-Scoping"><span class="spec-secid">4.3</span>Scoping</a></li>
|
|
43
|
+
<li><a href="#sec-Errors"><span class="spec-secid">4.4</span>Errors</a></li>
|
|
44
|
+
</ol>
|
|
45
|
+
</li>
|
|
46
|
+
<li><a href="#sec-Base-Library"><span class="spec-secid">5</span>Base Library</a><ol>
|
|
47
|
+
<li><a href="#sec-Types"><span class="spec-secid">5.1</span>Types</a></li>
|
|
48
|
+
<li><a href="#sec-Built-in-Functions"><span class="spec-secid">5.2</span>Built-in Functions</a><ol>
|
|
49
|
+
<li><a href="#sec-add"><span class="spec-secid">5.2.1</span>add</a></li>
|
|
50
|
+
<li><a href="#sec-sub"><span class="spec-secid">5.2.2</span>sub</a></li>
|
|
51
|
+
<li><a href="#sec-mul"><span class="spec-secid">5.2.3</span>mul</a></li>
|
|
52
|
+
<li><a href="#sec-div"><span class="spec-secid">5.2.4</span>div</a></li>
|
|
53
|
+
<li><a href="#sec-mod"><span class="spec-secid">5.2.5</span>mod</a></li>
|
|
54
|
+
<li><a href="#sec-min"><span class="spec-secid">5.2.6</span>min</a></li>
|
|
55
|
+
<li><a href="#sec-max"><span class="spec-secid">5.2.7</span>max</a></li>
|
|
56
|
+
<li><a href="#sec-range"><span class="spec-secid">5.2.8</span>range</a></li>
|
|
57
|
+
<li><a href="#sec-map"><span class="spec-secid">5.2.9</span>map</a></li>
|
|
58
|
+
<li><a href="#sec-filter"><span class="spec-secid">5.2.10</span>filter</a></li>
|
|
59
|
+
<li><a href="#sec-reduce"><span class="spec-secid">5.2.11</span>reduce</a></li>
|
|
60
|
+
<li><a href="#sec-hd"><span class="spec-secid">5.2.12</span>hd</a></li>
|
|
61
|
+
<li><a href="#sec-tl"><span class="spec-secid">5.2.13</span>tl</a></li>
|
|
62
|
+
<li><a href="#sec-nth"><span class="spec-secid">5.2.14</span>nth</a></li>
|
|
63
|
+
<li><a href="#sec-apply"><span class="spec-secid">5.2.15</span>apply</a></li>
|
|
64
|
+
<li><a href="#sec-isEmpty"><span class="spec-secid">5.2.16</span>isEmpty</a></li>
|
|
65
|
+
<li><a href="#sec-get"><span class="spec-secid">5.2.17</span>get</a></li>
|
|
66
|
+
<li><a href="#sec-set"><span class="spec-secid">5.2.18</span>set</a></li>
|
|
67
|
+
</ol>
|
|
68
|
+
</li>
|
|
69
|
+
</ol>
|
|
70
|
+
</li>
|
|
71
|
+
<li><a href="#sec-Program-Examples"><span class="spec-secid">6</span>Program Examples</a></li>
|
|
72
|
+
<li><a href="#index"><span class="spec-secid">§</span>Index</a></li>
|
|
73
|
+
</ol>
|
|
74
|
+
</nav>
|
|
75
|
+
</header>
|
|
76
|
+
<section id="sec-Introduction" secid="1">
|
|
77
|
+
<h1><span class="spec-secid" title="link to this section"><a href="#sec-Introduction">1</a></span>Introduction</h1>
|
|
78
|
+
<p>This document defines the <strong>Graffiticode Core Language Specification</strong>, covering syntax, semantics, and the base library. It excludes dialect-specific constructs, runtime behavior, and extended libraries.</p>
|
|
79
|
+
</section>
|
|
80
|
+
<section id="sec-Lexical-Structure" secid="2">
|
|
81
|
+
<h1><span class="spec-secid" title="link to this section"><a href="#sec-Lexical-Structure">2</a></span>Lexical Structure</h1>
|
|
82
|
+
<section id="sec-Tokens" secid="2.1">
|
|
83
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Tokens">2.1</a></span>Tokens</h2>
|
|
84
|
+
<ul>
|
|
85
|
+
<li><strong>Identifiers</strong>: Alphanumeric symbols beginning with a letter.</li>
|
|
86
|
+
<li><strong>Numbers</strong>: Integers and floats. Negative numbers start with <code>-</code>.</li>
|
|
87
|
+
<li><strong>Strings</strong>: Double-quoted UTF-8 strings.</li>
|
|
88
|
+
<li><strong>Symbols</strong>: <code>(</code>, <code>)</code>, <code>[</code>, <code>]</code>, <code>{</code>, <code>}</code>, <code>:</code>, <code>..</code>, <code><</code>, <code>></code>, <code>,</code></li>
|
|
89
|
+
</ul>
|
|
90
|
+
</section>
|
|
91
|
+
<section id="sec-Comments" secid="2.2">
|
|
92
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Comments">2.2</a></span>Comments</h2>
|
|
93
|
+
<ul>
|
|
94
|
+
<li><strong>Line Comments</strong>: Begin with <code>|</code> and continue to end of line.</li>
|
|
95
|
+
</ul>
|
|
96
|
+
</section>
|
|
97
|
+
</section>
|
|
98
|
+
<section id="sec-Syntax" secid="3">
|
|
99
|
+
<h1><span class="spec-secid" title="link to this section"><a href="#sec-Syntax">3</a></span>Syntax</h1>
|
|
100
|
+
<section id="sec-Programs" secid="3.1">
|
|
101
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Programs">3.1</a></span>Programs</h2>
|
|
102
|
+
<p>A <strong>Graffiticode program</strong> is a sequence of one or more <code>let</code> declarations, followed by a single top-level expression, and terminated with <code>..</code>.</p>
|
|
103
|
+
<pre><code>let double = <x: mul 2 x>..
|
|
104
|
+
map (double) [1 2 3]..
|
|
105
|
+
</code></pre>
|
|
106
|
+
<p>The top-level expression must always be followed by <code>..</code>.</p>
|
|
107
|
+
</section>
|
|
108
|
+
<section id="sec-Expressions" secid="3.2">
|
|
109
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Expressions">3.2</a></span>Expressions</h2>
|
|
110
|
+
<section id="sec-Function-Application" secid="3.2.1">
|
|
111
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-Function-Application">3.2.1</a></span>Function Application</h3>
|
|
112
|
+
<p>Function application is written in prefix style: <code>add 1 2</code></p>
|
|
113
|
+
<p>Parentheses are used to defer application: <code>map (double) [1 2 3]</code></p>
|
|
114
|
+
</section>
|
|
115
|
+
<section id="sec-Lists" secid="3.2.2">
|
|
116
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-Lists">3.2.2</a></span>Lists</h3>
|
|
117
|
+
<pre><code>[1 2 3]
|
|
118
|
+
</code></pre>
|
|
119
|
+
</section>
|
|
120
|
+
<section id="sec-Records" secid="3.2.3">
|
|
121
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-Records">3.2.3</a></span>Records</h3>
|
|
122
|
+
<pre><code>{ name: "Alice", age: 30 }
|
|
123
|
+
</code></pre>
|
|
124
|
+
</section>
|
|
125
|
+
<section id="sec-Lambdas" secid="3.2.4">
|
|
126
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-Lambdas">3.2.4</a></span>Lambdas</h3>
|
|
127
|
+
<pre><code><x: add x 1>
|
|
128
|
+
</code></pre>
|
|
129
|
+
<p>Multiple parameters: <code><x y: add x y></code></p>
|
|
130
|
+
</section>
|
|
131
|
+
<section id="sec-Let-Bindings" secid="3.2.5">
|
|
132
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-Let-Bindings">3.2.5</a></span>Let Bindings</h3>
|
|
133
|
+
<pre><code>let double = <x: mul 2 x>..
|
|
134
|
+
</code></pre>
|
|
135
|
+
</section>
|
|
136
|
+
</section>
|
|
137
|
+
<section id="sec-Pattern-Matching" secid="3.3">
|
|
138
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Pattern-Matching">3.3</a></span>Pattern Matching</h2>
|
|
139
|
+
<p>Pattern matching is done using <code>case</code>: <code>case x of 0: "zero" 1: "one" _: "other" end</code></p>
|
|
140
|
+
<div class="spec-production" id="Supports">
|
|
141
|
+
<span class="spec-nt"><a href="#Supports" data-name="Supports">Supports</a></span><div class="spec-rhs"><span class="spec-nt"><span data-name="Literal">Literal</span></span><span class="spec-t">values</span></div>
|
|
142
|
+
<div class="spec-rhs"><span class="spec-nt"><span data-name="Tuple">Tuple</span></span><span class="spec-t">destructuring:</span><span class="spec-t">(a, b)</span></div>
|
|
143
|
+
<div class="spec-rhs"><span class="spec-nt"><span data-name="Record">Record</span></span><span class="spec-t">destructuring:</span><span class="spec-t">{ name, age }</span></div>
|
|
144
|
+
<div class="spec-rhs"><span class="spec-nt"><span data-name="Wildcard">Wildcard</span></span><span class="spec-t">_</span></div>
|
|
145
|
+
</div>
|
|
146
|
+
<p>Pattern matching on function arguments is disallowed.</p>
|
|
147
|
+
<section id="sec-Tag-Values" secid="3.3.1">
|
|
148
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-Tag-Values">3.3.1</a></span>Tag Values</h3>
|
|
149
|
+
<p>A <strong>tag value</strong> is an arity-0 symbolic value that can be used in pattern matching or to encode variant types.</p>
|
|
150
|
+
<pre><code>red
|
|
151
|
+
</code></pre>
|
|
152
|
+
<p>Tag values:</p>
|
|
153
|
+
<ul>
|
|
154
|
+
<li>Are unbound identifiers that appear in expression position.</li>
|
|
155
|
+
<li>May optionally be introduced via implicit enum definitions.</li>
|
|
156
|
+
<li>Match directly in <code>case</code> expressions:</li>
|
|
157
|
+
</ul>
|
|
158
|
+
<pre><code>case color of
|
|
159
|
+
red: "warm"
|
|
160
|
+
blue: "cool"
|
|
161
|
+
_: "other"
|
|
162
|
+
end
|
|
163
|
+
</code></pre>
|
|
164
|
+
<p>Tags are resolved as special constants with symbolic identity. They are case-sensitive and may be compared for equality using regular pattern match semantics.</p>
|
|
165
|
+
</section>
|
|
166
|
+
</section>
|
|
167
|
+
</section>
|
|
168
|
+
<section id="sec-Semantics" secid="4">
|
|
169
|
+
<h1><span class="spec-secid" title="link to this section"><a href="#sec-Semantics">4</a></span>Semantics</h1>
|
|
170
|
+
<section id="sec-Evaluation-Model" secid="4.1">
|
|
171
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Evaluation-Model">4.1</a></span>Evaluation Model</h2>
|
|
172
|
+
<ul>
|
|
173
|
+
<li><strong>Purely functional</strong>: no side effects</li>
|
|
174
|
+
<li><strong>Strict evaluation</strong>: arguments evaluated before function application</li>
|
|
175
|
+
<li><strong>Immutable data</strong>: all values are immutable</li>
|
|
176
|
+
</ul>
|
|
177
|
+
</section>
|
|
178
|
+
<section id="sec-Functions" secid="4.2">
|
|
179
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Functions">4.2</a></span>Functions</h2>
|
|
180
|
+
<ul>
|
|
181
|
+
<li><strong>Fixed arity</strong>: every function has a known number of parameters</li>
|
|
182
|
+
<li><strong>Curried by default</strong>: partial application supported</li>
|
|
183
|
+
</ul>
|
|
184
|
+
</section>
|
|
185
|
+
<section id="sec-Scoping" secid="4.3">
|
|
186
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Scoping">4.3</a></span>Scoping</h2>
|
|
187
|
+
<ul>
|
|
188
|
+
<li><strong>Lexical scoping</strong></li>
|
|
189
|
+
<li><strong>Shadowing</strong> allowed within nested scopes</li>
|
|
190
|
+
</ul>
|
|
191
|
+
</section>
|
|
192
|
+
<section id="sec-Errors" secid="4.4">
|
|
193
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Errors">4.4</a></span>Errors</h2>
|
|
194
|
+
<ul>
|
|
195
|
+
<li><strong>Syntax errors</strong>: raised during parsing</li>
|
|
196
|
+
<li><strong>Type errors</strong>: raised during compilation</li>
|
|
197
|
+
<li><strong>Runtime errors</strong>: e.g., out-of-bounds access</li>
|
|
198
|
+
</ul>
|
|
199
|
+
</section>
|
|
200
|
+
</section>
|
|
201
|
+
<section id="sec-Base-Library" secid="5">
|
|
202
|
+
<h1><span class="spec-secid" title="link to this section"><a href="#sec-Base-Library">5</a></span>Base Library</h1>
|
|
203
|
+
<section id="sec-Types" secid="5.1">
|
|
204
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Types">5.1</a></span>Types</h2>
|
|
205
|
+
<ul>
|
|
206
|
+
<li><code>number</code></li>
|
|
207
|
+
<li><code>string</code></li>
|
|
208
|
+
<li><code>bool</code></li>
|
|
209
|
+
<li><code>list</code></li>
|
|
210
|
+
<li><code>record</code></li>
|
|
211
|
+
<li><code>tuple</code></li>
|
|
212
|
+
<li><code>json</code></li>
|
|
213
|
+
</ul>
|
|
214
|
+
</section>
|
|
215
|
+
<section id="sec-Built-in-Functions" secid="5.2">
|
|
216
|
+
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Built-in-Functions">5.2</a></span>Built-in Functions</h2>
|
|
217
|
+
<table>
|
|
218
|
+
<thead>
|
|
219
|
+
<tr>
|
|
220
|
+
<th align="left">Function</th>
|
|
221
|
+
<th align="left">Signature</th>
|
|
222
|
+
<th align="left">Description</th>
|
|
223
|
+
</tr>
|
|
224
|
+
</thead>
|
|
225
|
+
<tbody>
|
|
226
|
+
<tr>
|
|
227
|
+
<td align="left"><code>add</code></td>
|
|
228
|
+
<td align="left"><code><number number: number></code></td>
|
|
229
|
+
<td align="left">Adds two numbers</td>
|
|
230
|
+
</tr>
|
|
231
|
+
<tr>
|
|
232
|
+
<td align="left"><code>sub</code></td>
|
|
233
|
+
<td align="left"><code><number number: number></code></td>
|
|
234
|
+
<td align="left">Subtracts numbers</td>
|
|
235
|
+
</tr>
|
|
236
|
+
<tr>
|
|
237
|
+
<td align="left"><code>mul</code></td>
|
|
238
|
+
<td align="left"><code><number number: number></code></td>
|
|
239
|
+
<td align="left">Multiplies numbers</td>
|
|
240
|
+
</tr>
|
|
241
|
+
<tr>
|
|
242
|
+
<td align="left"><code>div</code></td>
|
|
243
|
+
<td align="left"><code><number number: number></code></td>
|
|
244
|
+
<td align="left">Divides numbers</td>
|
|
245
|
+
</tr>
|
|
246
|
+
<tr>
|
|
247
|
+
<td align="left"><code>mod</code></td>
|
|
248
|
+
<td align="left"><code><number number: number></code></td>
|
|
249
|
+
<td align="left">Remainder of division</td>
|
|
250
|
+
</tr>
|
|
251
|
+
<tr>
|
|
252
|
+
<td align="left"><code>min</code></td>
|
|
253
|
+
<td align="left"><code><number number: number></code></td>
|
|
254
|
+
<td align="left">Returns the smaller of two numbers</td>
|
|
255
|
+
</tr>
|
|
256
|
+
<tr>
|
|
257
|
+
<td align="left"><code>max</code></td>
|
|
258
|
+
<td align="left"><code><number number: number></code></td>
|
|
259
|
+
<td align="left">Returns the larger of two numbers</td>
|
|
260
|
+
</tr>
|
|
261
|
+
<tr>
|
|
262
|
+
<td align="left"><code>range</code></td>
|
|
263
|
+
<td align="left"><code><number number number: list></code></td>
|
|
264
|
+
<td align="left">Generates a range list</td>
|
|
265
|
+
</tr>
|
|
266
|
+
<tr>
|
|
267
|
+
<td align="left"><code>map</code></td>
|
|
268
|
+
<td align="left"><code><function list: list></code></td>
|
|
269
|
+
<td align="left">Applies function to each item</td>
|
|
270
|
+
</tr>
|
|
271
|
+
<tr>
|
|
272
|
+
<td align="left"><code>filter</code></td>
|
|
273
|
+
<td align="left"><code><function list: list></code></td>
|
|
274
|
+
<td align="left">Keeps items matching predicate</td>
|
|
275
|
+
</tr>
|
|
276
|
+
<tr>
|
|
277
|
+
<td align="left"><code>reduce</code></td>
|
|
278
|
+
<td align="left"><code><function list: any></code></td>
|
|
279
|
+
<td align="left">Combines list using a reducer</td>
|
|
280
|
+
</tr>
|
|
281
|
+
<tr>
|
|
282
|
+
<td align="left"><code>hd</code></td>
|
|
283
|
+
<td align="left"><code><list: any></code></td>
|
|
284
|
+
<td align="left">First item of list</td>
|
|
285
|
+
</tr>
|
|
286
|
+
<tr>
|
|
287
|
+
<td align="left"><code>tl</code></td>
|
|
288
|
+
<td align="left"><code><list: list></code></td>
|
|
289
|
+
<td align="left">All items except first</td>
|
|
290
|
+
</tr>
|
|
291
|
+
<tr>
|
|
292
|
+
<td align="left"><code>nth</code></td>
|
|
293
|
+
<td align="left"><code><number list: any></code></td>
|
|
294
|
+
<td align="left">Nth element of list</td>
|
|
295
|
+
</tr>
|
|
296
|
+
<tr>
|
|
297
|
+
<td align="left"><code>apply</code></td>
|
|
298
|
+
<td align="left"><code><function list: any></code></td>
|
|
299
|
+
<td align="left">Applies a function to a list of arguments</td>
|
|
300
|
+
</tr>
|
|
301
|
+
<tr>
|
|
302
|
+
<td align="left"><code>isEmpty</code></td>
|
|
303
|
+
<td align="left"><code><list: bool></code></td>
|
|
304
|
+
<td align="left">Returns true if the list is empty</td>
|
|
305
|
+
</tr>
|
|
306
|
+
<tr>
|
|
307
|
+
<td align="left"><code>get</code></td>
|
|
308
|
+
<td align="left"><code><record string: any></code></td>
|
|
309
|
+
<td align="left">Retrieves a value from a record by key</td>
|
|
310
|
+
</tr>
|
|
311
|
+
<tr>
|
|
312
|
+
<td align="left"><code>set</code></td>
|
|
313
|
+
<td align="left"><code><record string any: record></code></td>
|
|
314
|
+
<td align="left">Returns a new record with a key set to a value</td>
|
|
315
|
+
</tr>
|
|
316
|
+
</tbody>
|
|
317
|
+
</table>
|
|
318
|
+
<section id="sec-add" secid="5.2.1">
|
|
319
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-add">5.2.1</a></span>add</h3>
|
|
320
|
+
<p>Add two numbers.</p>
|
|
321
|
+
<pre><code>add 2 3 | returns 5
|
|
322
|
+
</code></pre>
|
|
323
|
+
</section>
|
|
324
|
+
<section id="sec-sub" secid="5.2.2">
|
|
325
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-sub">5.2.2</a></span>sub</h3>
|
|
326
|
+
<p>Subtract the second number from the first</p>
|
|
327
|
+
<pre><code>sub 5 2 | returns 3
|
|
328
|
+
</code></pre>
|
|
329
|
+
</section>
|
|
330
|
+
<section id="sec-mul" secid="5.2.3">
|
|
331
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-mul">5.2.3</a></span>mul</h3>
|
|
332
|
+
<p>Multiply two numbers</p>
|
|
333
|
+
<pre><code>mul 4 3 | returns 12
|
|
334
|
+
</code></pre>
|
|
335
|
+
</section>
|
|
336
|
+
<section id="sec-div" secid="5.2.4">
|
|
337
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-div">5.2.4</a></span>div</h3>
|
|
338
|
+
<p>Divide the first number by the second</p>
|
|
339
|
+
<pre><code>div 10 2 | returns 5
|
|
340
|
+
</code></pre>
|
|
341
|
+
</section>
|
|
342
|
+
<section id="sec-mod" secid="5.2.5">
|
|
343
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-mod">5.2.5</a></span>mod</h3>
|
|
344
|
+
<p>Compute the remainder</p>
|
|
345
|
+
<pre><code>mod 10 3 | returns 1
|
|
346
|
+
</code></pre>
|
|
347
|
+
</section>
|
|
348
|
+
<section id="sec-min" secid="5.2.6">
|
|
349
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-min">5.2.6</a></span>min</h3>
|
|
350
|
+
<p>Return the smaller of two numbers</p>
|
|
351
|
+
<pre><code>min 5 10 | returns 5
|
|
352
|
+
</code></pre>
|
|
353
|
+
</section>
|
|
354
|
+
<section id="sec-max" secid="5.2.7">
|
|
355
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-max">5.2.7</a></span>max</h3>
|
|
356
|
+
<p>Return the larger of two numbers</p>
|
|
357
|
+
<pre><code>max 5 10 | returns 10
|
|
358
|
+
</code></pre>
|
|
359
|
+
</section>
|
|
360
|
+
<section id="sec-range" secid="5.2.8">
|
|
361
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-range">5.2.8</a></span>range</h3>
|
|
362
|
+
<p>Produce a range list from start to end (exclusive) with step</p>
|
|
363
|
+
<pre><code>range 1 10 2 | returns [1 3 5 7 9]
|
|
364
|
+
</code></pre>
|
|
365
|
+
</section>
|
|
366
|
+
<section id="sec-map" secid="5.2.9">
|
|
367
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-map">5.2.9</a></span>map</h3>
|
|
368
|
+
<p>Apply a function to each element</p>
|
|
369
|
+
<pre><code>map (<x: add x 1>) [1 2 3] | returns [2 3 4]
|
|
370
|
+
</code></pre>
|
|
371
|
+
</section>
|
|
372
|
+
<section id="sec-filter" secid="5.2.10">
|
|
373
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-filter">5.2.10</a></span>filter</h3>
|
|
374
|
+
<p>Filter elements matching predicate</p>
|
|
375
|
+
<pre><code>filter (<x: mod x 2>) [1 2 3 4] | returns [1 3]
|
|
376
|
+
</code></pre>
|
|
377
|
+
</section>
|
|
378
|
+
<section id="sec-reduce" secid="5.2.11">
|
|
379
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-reduce">5.2.11</a></span>reduce</h3>
|
|
380
|
+
<p>Reduce a list to a single value, starting with an initial value</p>
|
|
381
|
+
<pre><code>reduce (<a b: add a b>) 0 [1 2 3 4] | returns 10
|
|
382
|
+
</code></pre>
|
|
383
|
+
</section>
|
|
384
|
+
<section id="sec-hd" secid="5.2.12">
|
|
385
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-hd">5.2.12</a></span>hd</h3>
|
|
386
|
+
<p>Return the first item</p>
|
|
387
|
+
<pre><code>hd [10 20 30] | returns 10
|
|
388
|
+
</code></pre>
|
|
389
|
+
</section>
|
|
390
|
+
<section id="sec-tl" secid="5.2.13">
|
|
391
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-tl">5.2.13</a></span>tl</h3>
|
|
392
|
+
<p>Return all but the first item</p>
|
|
393
|
+
<pre><code>tl [10 20 30] | returns [20 30]
|
|
394
|
+
</code></pre>
|
|
395
|
+
</section>
|
|
396
|
+
<section id="sec-nth" secid="5.2.14">
|
|
397
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-nth">5.2.14</a></span>nth</h3>
|
|
398
|
+
<p>Get the nth item (0-based)</p>
|
|
399
|
+
<pre><code>nth 1 [10 20 30] | returns 20
|
|
400
|
+
</code></pre>
|
|
401
|
+
</section>
|
|
402
|
+
<section id="sec-apply" secid="5.2.15">
|
|
403
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-apply">5.2.15</a></span>apply</h3>
|
|
404
|
+
<p>Apply a function to an argument list</p>
|
|
405
|
+
<pre><code>apply add [1 2] | returns 3
|
|
406
|
+
</code></pre>
|
|
407
|
+
</section>
|
|
408
|
+
<section id="sec-isEmpty" secid="5.2.16">
|
|
409
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-isEmpty">5.2.16</a></span>isEmpty</h3>
|
|
410
|
+
<p>Return true if list is empty, otherwise return false</p>
|
|
411
|
+
<pre><code>isEmpty [] | returns true
|
|
412
|
+
</code></pre>
|
|
413
|
+
</section>
|
|
414
|
+
<section id="sec-get" secid="5.2.17">
|
|
415
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-get">5.2.17</a></span>get</h3>
|
|
416
|
+
<p>Retrieve a record field</p>
|
|
417
|
+
<pre><code>get {a: 1, b: 2} "b" | returns 2
|
|
418
|
+
</code></pre>
|
|
419
|
+
</section>
|
|
420
|
+
<section id="sec-set" secid="5.2.18">
|
|
421
|
+
<h3><span class="spec-secid" title="link to this section"><a href="#sec-set">5.2.18</a></span>set</h3>
|
|
422
|
+
<p>Return a new record with an updated field</p>
|
|
423
|
+
<pre><code>set {a: 1} "a" 2 | returns {a: 2}
|
|
424
|
+
</code></pre>
|
|
425
|
+
</section>
|
|
426
|
+
</section>
|
|
427
|
+
</section>
|
|
428
|
+
<section id="sec-Program-Examples" secid="6">
|
|
429
|
+
<h1><span class="spec-secid" title="link to this section"><a href="#sec-Program-Examples">6</a></span>Program Examples</h1>
|
|
430
|
+
<pre><code>let double = <x: mul 2 x>..
|
|
431
|
+
map (double) [1 2 3]..
|
|
432
|
+
</code></pre>
|
|
433
|
+
<pre><code>case age of
|
|
434
|
+
18: "adult"
|
|
435
|
+
_: "other"
|
|
436
|
+
end..
|
|
437
|
+
</code></pre>
|
|
438
|
+
<p>---</p>
|
|
439
|
+
</section>
|
|
440
|
+
<section id="index" secid="index" class="spec-index">
|
|
441
|
+
<h1>
|
|
442
|
+
<span class="spec-secid" title="link to the index"><a href="#index">§</a></span>Index</h1>
|
|
443
|
+
<ol>
|
|
444
|
+
<li><a href="#Supports">Supports</a></li>
|
|
445
|
+
</ol>
|
|
446
|
+
</section>
|
|
447
|
+
</article>
|
|
448
|
+
<footer>
|
|
449
|
+
Written in <a href="https://spec-md.com" target="_blank">Spec Markdown</a>.</footer>
|
|
450
|
+
<input hidden class="spec-sidebar-toggle" type="checkbox" id="spec-sidebar-toggle" aria-hidden /><label for="spec-sidebar-toggle" aria-hidden><div class="spec-sidebar-button">☰</div></label>
|
|
451
|
+
<div class="spec-sidebar" aria-hidden>
|
|
452
|
+
<div class="spec-toc">
|
|
453
|
+
<div class="title"><a href="#">Graffiticode Core Language Specification</a></div>
|
|
454
|
+
<ol><li id="_sidebar_1"><a href="#sec-Introduction"><span class="spec-secid">1</span>Introduction</a></li>
|
|
455
|
+
<li id="_sidebar_2"><a href="#sec-Lexical-Structure"><span class="spec-secid">2</span>Lexical Structure</a>
|
|
456
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_2" /><label for="_toggle_2"></label>
|
|
457
|
+
<ol>
|
|
458
|
+
<li id="_sidebar_2.1"><a href="#sec-Tokens"><span class="spec-secid">2.1</span>Tokens</a></li>
|
|
459
|
+
<li id="_sidebar_2.2"><a href="#sec-Comments"><span class="spec-secid">2.2</span>Comments</a></li>
|
|
460
|
+
</ol>
|
|
461
|
+
</li>
|
|
462
|
+
<li id="_sidebar_3"><a href="#sec-Syntax"><span class="spec-secid">3</span>Syntax</a>
|
|
463
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_3" /><label for="_toggle_3"></label>
|
|
464
|
+
<ol>
|
|
465
|
+
<li id="_sidebar_3.1"><a href="#sec-Programs"><span class="spec-secid">3.1</span>Programs</a></li>
|
|
466
|
+
<li id="_sidebar_3.2"><a href="#sec-Expressions"><span class="spec-secid">3.2</span>Expressions</a>
|
|
467
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_3.2" /><label for="_toggle_3.2"></label>
|
|
468
|
+
<ol>
|
|
469
|
+
<li id="_sidebar_3.2.1"><a href="#sec-Function-Application"><span class="spec-secid">3.2.1</span>Function Application</a></li>
|
|
470
|
+
<li id="_sidebar_3.2.2"><a href="#sec-Lists"><span class="spec-secid">3.2.2</span>Lists</a></li>
|
|
471
|
+
<li id="_sidebar_3.2.3"><a href="#sec-Records"><span class="spec-secid">3.2.3</span>Records</a></li>
|
|
472
|
+
<li id="_sidebar_3.2.4"><a href="#sec-Lambdas"><span class="spec-secid">3.2.4</span>Lambdas</a></li>
|
|
473
|
+
<li id="_sidebar_3.2.5"><a href="#sec-Let-Bindings"><span class="spec-secid">3.2.5</span>Let Bindings</a></li>
|
|
474
|
+
</ol>
|
|
475
|
+
</li>
|
|
476
|
+
<li id="_sidebar_3.3"><a href="#sec-Pattern-Matching"><span class="spec-secid">3.3</span>Pattern Matching</a>
|
|
477
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_3.3" /><label for="_toggle_3.3"></label>
|
|
478
|
+
<ol>
|
|
479
|
+
<li id="_sidebar_3.3.1"><a href="#sec-Tag-Values"><span class="spec-secid">3.3.1</span>Tag Values</a></li>
|
|
480
|
+
</ol>
|
|
481
|
+
</li>
|
|
482
|
+
</ol>
|
|
483
|
+
</li>
|
|
484
|
+
<li id="_sidebar_4"><a href="#sec-Semantics"><span class="spec-secid">4</span>Semantics</a>
|
|
485
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_4" /><label for="_toggle_4"></label>
|
|
486
|
+
<ol>
|
|
487
|
+
<li id="_sidebar_4.1"><a href="#sec-Evaluation-Model"><span class="spec-secid">4.1</span>Evaluation Model</a></li>
|
|
488
|
+
<li id="_sidebar_4.2"><a href="#sec-Functions"><span class="spec-secid">4.2</span>Functions</a></li>
|
|
489
|
+
<li id="_sidebar_4.3"><a href="#sec-Scoping"><span class="spec-secid">4.3</span>Scoping</a></li>
|
|
490
|
+
<li id="_sidebar_4.4"><a href="#sec-Errors"><span class="spec-secid">4.4</span>Errors</a></li>
|
|
491
|
+
</ol>
|
|
492
|
+
</li>
|
|
493
|
+
<li id="_sidebar_5"><a href="#sec-Base-Library"><span class="spec-secid">5</span>Base Library</a>
|
|
494
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_5" /><label for="_toggle_5"></label>
|
|
495
|
+
<ol>
|
|
496
|
+
<li id="_sidebar_5.1"><a href="#sec-Types"><span class="spec-secid">5.1</span>Types</a></li>
|
|
497
|
+
<li id="_sidebar_5.2"><a href="#sec-Built-in-Functions"><span class="spec-secid">5.2</span>Built-in Functions</a>
|
|
498
|
+
<input hidden class="toggle" type="checkbox" id="_toggle_5.2" /><label for="_toggle_5.2"></label>
|
|
499
|
+
<ol>
|
|
500
|
+
<li id="_sidebar_5.2.1"><a href="#sec-add"><span class="spec-secid">5.2.1</span>add</a></li>
|
|
501
|
+
<li id="_sidebar_5.2.2"><a href="#sec-sub"><span class="spec-secid">5.2.2</span>sub</a></li>
|
|
502
|
+
<li id="_sidebar_5.2.3"><a href="#sec-mul"><span class="spec-secid">5.2.3</span>mul</a></li>
|
|
503
|
+
<li id="_sidebar_5.2.4"><a href="#sec-div"><span class="spec-secid">5.2.4</span>div</a></li>
|
|
504
|
+
<li id="_sidebar_5.2.5"><a href="#sec-mod"><span class="spec-secid">5.2.5</span>mod</a></li>
|
|
505
|
+
<li id="_sidebar_5.2.6"><a href="#sec-min"><span class="spec-secid">5.2.6</span>min</a></li>
|
|
506
|
+
<li id="_sidebar_5.2.7"><a href="#sec-max"><span class="spec-secid">5.2.7</span>max</a></li>
|
|
507
|
+
<li id="_sidebar_5.2.8"><a href="#sec-range"><span class="spec-secid">5.2.8</span>range</a></li>
|
|
508
|
+
<li id="_sidebar_5.2.9"><a href="#sec-map"><span class="spec-secid">5.2.9</span>map</a></li>
|
|
509
|
+
<li id="_sidebar_5.2.10"><a href="#sec-filter"><span class="spec-secid">5.2.10</span>filter</a></li>
|
|
510
|
+
<li id="_sidebar_5.2.11"><a href="#sec-reduce"><span class="spec-secid">5.2.11</span>reduce</a></li>
|
|
511
|
+
<li id="_sidebar_5.2.12"><a href="#sec-hd"><span class="spec-secid">5.2.12</span>hd</a></li>
|
|
512
|
+
<li id="_sidebar_5.2.13"><a href="#sec-tl"><span class="spec-secid">5.2.13</span>tl</a></li>
|
|
513
|
+
<li id="_sidebar_5.2.14"><a href="#sec-nth"><span class="spec-secid">5.2.14</span>nth</a></li>
|
|
514
|
+
<li id="_sidebar_5.2.15"><a href="#sec-apply"><span class="spec-secid">5.2.15</span>apply</a></li>
|
|
515
|
+
<li id="_sidebar_5.2.16"><a href="#sec-isEmpty"><span class="spec-secid">5.2.16</span>isEmpty</a></li>
|
|
516
|
+
<li id="_sidebar_5.2.17"><a href="#sec-get"><span class="spec-secid">5.2.17</span>get</a></li>
|
|
517
|
+
<li id="_sidebar_5.2.18"><a href="#sec-set"><span class="spec-secid">5.2.18</span>set</a></li>
|
|
518
|
+
</ol>
|
|
519
|
+
</li>
|
|
520
|
+
</ol>
|
|
521
|
+
</li>
|
|
522
|
+
<li id="_sidebar_6"><a href="#sec-Program-Examples"><span class="spec-secid">6</span>Program Examples</a></li>
|
|
523
|
+
<li id="_sidebar_index"><a href="#index"><span class="spec-secid">§</span>Index</a></li>
|
|
524
|
+
</ol>
|
|
525
|
+
</div>
|
|
526
|
+
</div>
|
|
527
|
+
</body>
|
|
528
|
+
</html>
|
package/spec/spec.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# Graffiticode Core Language Specification
|
|
2
|
+
|
|
3
|
+
# Introduction
|
|
4
|
+
|
|
5
|
+
This document defines the **Graffiticode Core Language Specification**, covering syntax, semantics, and the base library. It excludes dialect-specific constructs, runtime behavior, and extended libraries.
|
|
6
|
+
|
|
7
|
+
# Lexical Structure
|
|
8
|
+
|
|
9
|
+
## Tokens
|
|
10
|
+
|
|
11
|
+
- **Identifiers**: Alphanumeric symbols beginning with a letter.
|
|
12
|
+
- **Numbers**: Integers and floats. Negative numbers start with `-`.
|
|
13
|
+
- **Strings**: Double-quoted UTF-8 strings.
|
|
14
|
+
- **Symbols**: `(`, `)`, `[`, `]`, `{`, `}`, `:`, `..`, `<`, `>`, `,`
|
|
15
|
+
|
|
16
|
+
## Comments
|
|
17
|
+
|
|
18
|
+
- **Line Comments**: Begin with `|` and continue to end of line.
|
|
19
|
+
|
|
20
|
+
# Syntax
|
|
21
|
+
|
|
22
|
+
## Programs
|
|
23
|
+
|
|
24
|
+
A **Graffiticode program** is a sequence of one or more `let` declarations, followed by a single top-level expression, and terminated with `..`.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
let double = <x: mul 2 x>..
|
|
28
|
+
map (double) [1 2 3]..
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The top-level expression must always be followed by `..`.
|
|
32
|
+
|
|
33
|
+
## Expressions
|
|
34
|
+
|
|
35
|
+
### Function Application
|
|
36
|
+
|
|
37
|
+
Function application is written in prefix style:
|
|
38
|
+
```
|
|
39
|
+
add 1 2
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Parentheses are used to defer application:
|
|
43
|
+
```
|
|
44
|
+
map (double) [1 2 3]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Lists
|
|
48
|
+
```
|
|
49
|
+
[1 2 3]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Records
|
|
53
|
+
```
|
|
54
|
+
{ name: "Alice", age: 30 }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Lambdas
|
|
58
|
+
```
|
|
59
|
+
<x: add x 1>
|
|
60
|
+
```
|
|
61
|
+
Multiple parameters:
|
|
62
|
+
```
|
|
63
|
+
<x y: add x y>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Let Bindings
|
|
67
|
+
```
|
|
68
|
+
let double = <x: mul 2 x>..
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Pattern Matching
|
|
72
|
+
|
|
73
|
+
Pattern matching is done using `case`:
|
|
74
|
+
```
|
|
75
|
+
case x of
|
|
76
|
+
0: "zero"
|
|
77
|
+
1: "one"
|
|
78
|
+
_: "other"
|
|
79
|
+
end
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Supports:
|
|
83
|
+
- Literal values
|
|
84
|
+
- Tuple destructuring: `(a, b)`
|
|
85
|
+
- Record destructuring: `{ name, age }`
|
|
86
|
+
- Wildcard `_`
|
|
87
|
+
|
|
88
|
+
Pattern matching on function arguments is disallowed.
|
|
89
|
+
|
|
90
|
+
### Tag Values
|
|
91
|
+
|
|
92
|
+
A **tag value** is an arity-0 symbolic value that can be used in pattern matching or to encode variant types.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
red
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Tag values:
|
|
99
|
+
|
|
100
|
+
- Are unbound identifiers that appear in expression position.
|
|
101
|
+
- May optionally be introduced via implicit enum definitions.
|
|
102
|
+
- Match directly in `case` expressions:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
case color of
|
|
106
|
+
red: "warm"
|
|
107
|
+
blue: "cool"
|
|
108
|
+
_: "other"
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Tags are resolved as special constants with symbolic identity. They are case-sensitive and may be compared for equality using regular pattern match semantics.
|
|
113
|
+
|
|
114
|
+
# Semantics
|
|
115
|
+
|
|
116
|
+
## Evaluation Model
|
|
117
|
+
|
|
118
|
+
- **Purely functional**: no side effects
|
|
119
|
+
- **Strict evaluation**: arguments evaluated before function application
|
|
120
|
+
- **Immutable data**: all values are immutable
|
|
121
|
+
|
|
122
|
+
## Functions
|
|
123
|
+
|
|
124
|
+
- **Fixed arity**: every function has a known number of parameters
|
|
125
|
+
- **Curried by default**: partial application supported
|
|
126
|
+
|
|
127
|
+
## Scoping
|
|
128
|
+
|
|
129
|
+
- **Lexical scoping**
|
|
130
|
+
- **Shadowing** allowed within nested scopes
|
|
131
|
+
|
|
132
|
+
## Errors
|
|
133
|
+
|
|
134
|
+
- **Syntax errors**: raised during parsing
|
|
135
|
+
- **Type errors**: raised during compilation
|
|
136
|
+
- **Runtime errors**: e.g., out-of-bounds access
|
|
137
|
+
|
|
138
|
+
# Base Library
|
|
139
|
+
|
|
140
|
+
## Types
|
|
141
|
+
|
|
142
|
+
- `number`
|
|
143
|
+
- `string`
|
|
144
|
+
- `bool`
|
|
145
|
+
- `list`
|
|
146
|
+
- `record`
|
|
147
|
+
- `tuple`
|
|
148
|
+
- `json`
|
|
149
|
+
|
|
150
|
+
## Built-in Functions
|
|
151
|
+
|
|
152
|
+
| Function | Signature | Description |
|
|
153
|
+
| :------- | :-------- | :---------- |
|
|
154
|
+
| `add` | `<number number: number>` | Adds two numbers |
|
|
155
|
+
| `sub` | `<number number: number>` | Subtracts numbers |
|
|
156
|
+
| `mul` | `<number number: number>` | Multiplies numbers |
|
|
157
|
+
| `div` | `<number number: number>` | Divides numbers |
|
|
158
|
+
| `mod` | `<number number: number>` | Remainder of division |
|
|
159
|
+
| `min` | `<number number: number>` | Returns the smaller of two numbers |
|
|
160
|
+
| `max` | `<number number: number>` | Returns the larger of two numbers |
|
|
161
|
+
| `range` | `<number number number: list>` | Generates a range list |
|
|
162
|
+
| `map` | `<function list: list>` | Applies function to each item |
|
|
163
|
+
| `filter` | `<function list: list>` | Keeps items matching predicate |
|
|
164
|
+
| `reduce` | `<function list: any>` | Combines list using a reducer |
|
|
165
|
+
| `hd` | `<list: any>` | First item of list |
|
|
166
|
+
| `tl` | `<list: list>` | All items except first |
|
|
167
|
+
| `nth` | `<number list: any>` | Nth element of list |
|
|
168
|
+
| `apply` | `<function list: any>` | Applies a function to a list of arguments |
|
|
169
|
+
| `isEmpty` | `<list: bool>` | Returns true if the list is empty |
|
|
170
|
+
| `get` | `<record string: any>` | Retrieves a value from a record by key |
|
|
171
|
+
| `set` | `<record string any: record>` | Returns a new record with a key set to a value |
|
|
172
|
+
|
|
173
|
+
### add
|
|
174
|
+
|
|
175
|
+
Add two numbers.
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
add 2 3 | returns 5
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### sub
|
|
182
|
+
|
|
183
|
+
Subtract the second number from the first
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
sub 5 2 | returns 3
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### mul
|
|
190
|
+
|
|
191
|
+
Multiply two numbers
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
mul 4 3 | returns 12
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### div
|
|
198
|
+
|
|
199
|
+
Divide the first number by the second
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
div 10 2 | returns 5
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### mod
|
|
206
|
+
|
|
207
|
+
Compute the remainder
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
mod 10 3 | returns 1
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### min
|
|
214
|
+
|
|
215
|
+
Return the smaller of two numbers
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
min 5 10 | returns 5
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### max
|
|
222
|
+
|
|
223
|
+
Return the larger of two numbers
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
max 5 10 | returns 10
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### range
|
|
230
|
+
|
|
231
|
+
Produce a range list from start to end (exclusive) with step
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
range 1 10 2 | returns [1 3 5 7 9]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### map
|
|
238
|
+
|
|
239
|
+
Apply a function to each element
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
map (<x: add x 1>) [1 2 3] | returns [2 3 4]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### filter
|
|
246
|
+
|
|
247
|
+
Filter elements matching predicate
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
filter (<x: mod x 2>) [1 2 3 4] | returns [1 3]
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### reduce
|
|
254
|
+
|
|
255
|
+
Reduce a list to a single value, starting with an initial value
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
reduce (<a b: add a b>) 0 [1 2 3 4] | returns 10
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### hd
|
|
262
|
+
|
|
263
|
+
Return the first item
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
hd [10 20 30] | returns 10
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### tl
|
|
270
|
+
|
|
271
|
+
Return all but the first item
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
tl [10 20 30] | returns [20 30]
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### nth
|
|
278
|
+
|
|
279
|
+
Get the nth item (0-based)
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
nth 1 [10 20 30] | returns 20
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### apply
|
|
286
|
+
|
|
287
|
+
Apply a function to an argument list
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
apply add [1 2] | returns 3
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### isEmpty
|
|
294
|
+
|
|
295
|
+
Return true if list is empty, otherwise return false
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
isEmpty [] | returns true
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### get
|
|
302
|
+
|
|
303
|
+
Retrieve a record field
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
get {a: 1, b: 2} "b" | returns 2
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### set
|
|
310
|
+
|
|
311
|
+
Return a new record with an updated field
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
set {a: 1} "a" 2 | returns {a: 2}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
# Program Examples
|
|
318
|
+
|
|
319
|
+
```
|
|
320
|
+
let double = <x: mul 2 x>..
|
|
321
|
+
map (double) [1 2 3]..
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
case age of
|
|
326
|
+
18: "adult"
|
|
327
|
+
_: "other"
|
|
328
|
+
end..
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
package/src/compiler.js
CHANGED
|
@@ -407,6 +407,24 @@ export class Checker extends Visitor {
|
|
|
407
407
|
});
|
|
408
408
|
});
|
|
409
409
|
}
|
|
410
|
+
MIN(node, options, resume) {
|
|
411
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
412
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
413
|
+
const err = [].concat(err1).concat(err2);
|
|
414
|
+
const val = node;
|
|
415
|
+
resume(err, val);
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
MAX(node, options, resume) {
|
|
420
|
+
this.visit(node.elts[0], options, (err1, val1) => {
|
|
421
|
+
this.visit(node.elts[1], options, (err2, val2) => {
|
|
422
|
+
const err = [].concat(err1).concat(err2);
|
|
423
|
+
const val = node;
|
|
424
|
+
resume(err, val);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
}
|
|
410
428
|
}
|
|
411
429
|
|
|
412
430
|
function enterEnv(ctx, name, paramc) {
|
|
@@ -503,7 +521,7 @@ export class Transformer extends Visitor {
|
|
|
503
521
|
}
|
|
504
522
|
const patternNid = this.internPattern(pattern);
|
|
505
523
|
if (patternNid === this.internPattern(node) ||
|
|
506
|
-
patternNid === this.internPattern(newNode('
|
|
524
|
+
patternNid === this.internPattern(newNode('_', []))) {
|
|
507
525
|
return true;
|
|
508
526
|
}
|
|
509
527
|
if (pattern.tag === node.tag) {
|
|
@@ -1097,6 +1115,32 @@ export class Transformer extends Visitor {
|
|
|
1097
1115
|
});
|
|
1098
1116
|
});
|
|
1099
1117
|
}
|
|
1118
|
+
MIN(node, options, resume) {
|
|
1119
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1120
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1121
|
+
const err = [].concat(e0).concat(e1);
|
|
1122
|
+
try {
|
|
1123
|
+
const val = Decimal.min(new Decimal(v0), new Decimal(v1)).toNumber();
|
|
1124
|
+
resume(err, val);
|
|
1125
|
+
} catch (e) {
|
|
1126
|
+
resume([...err, `Error in MIN operation: ${e.message}`], NaN);
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
MAX(node, options, resume) {
|
|
1132
|
+
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1133
|
+
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1134
|
+
const err = [].concat(e0).concat(e1);
|
|
1135
|
+
try {
|
|
1136
|
+
const val = Decimal.max(new Decimal(v0), new Decimal(v1)).toNumber();
|
|
1137
|
+
resume(err, val);
|
|
1138
|
+
} catch (e) {
|
|
1139
|
+
resume([...err, `Error in MAX operation: ${e.message}`], NaN);
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1100
1144
|
RANGE(node, options, resume) {
|
|
1101
1145
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1102
1146
|
this.visit(node.elts[1], options, (e1, v1) => {
|
package/src/lexicon.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
export const lexicon = {
|
|
2
|
+
"print" : {
|
|
3
|
+
"tk": 1,
|
|
4
|
+
"name": "PRINT",
|
|
5
|
+
"cls": "function",
|
|
6
|
+
"length": 1,
|
|
7
|
+
"arity": 1
|
|
8
|
+
},
|
|
9
|
+
"get" : {
|
|
10
|
+
"tk": 1,
|
|
11
|
+
"name": "GET",
|
|
12
|
+
"cls": "function",
|
|
13
|
+
"length": 2,
|
|
14
|
+
"arity": 2
|
|
15
|
+
},
|
|
16
|
+
"set" : {
|
|
17
|
+
"tk": 1,
|
|
18
|
+
"name": "SET",
|
|
19
|
+
"cls": "function",
|
|
20
|
+
"length": 3,
|
|
21
|
+
"arity": 3
|
|
22
|
+
},
|
|
23
|
+
"nth" : {
|
|
24
|
+
"tk": 1,
|
|
25
|
+
"name": "NTH",
|
|
26
|
+
"cls": "function",
|
|
27
|
+
"length": 2,
|
|
28
|
+
"arity": 2
|
|
29
|
+
},
|
|
30
|
+
"sub" : {
|
|
31
|
+
"tk": 1,
|
|
32
|
+
"name": "SUB",
|
|
33
|
+
"cls": "function",
|
|
34
|
+
"length": 2,
|
|
35
|
+
"arity": 2
|
|
36
|
+
},
|
|
37
|
+
"filter" : {
|
|
38
|
+
"tk": 1,
|
|
39
|
+
"name": "FILTER",
|
|
40
|
+
"cls": "function",
|
|
41
|
+
"length": 2,
|
|
42
|
+
"arity": 2
|
|
43
|
+
},
|
|
44
|
+
"reduce" : {
|
|
45
|
+
"tk": 1,
|
|
46
|
+
"name": "REDUCE",
|
|
47
|
+
"cls": "function",
|
|
48
|
+
"length": 3,
|
|
49
|
+
"arity": 3
|
|
50
|
+
},
|
|
51
|
+
"map" : {
|
|
52
|
+
"tk": 1,
|
|
53
|
+
"name": "MAP",
|
|
54
|
+
"cls": "function",
|
|
55
|
+
"length": 2,
|
|
56
|
+
"arity": 2
|
|
57
|
+
},
|
|
58
|
+
"lt" : {
|
|
59
|
+
"tk": 1,
|
|
60
|
+
"name": "LT",
|
|
61
|
+
"cls": "function",
|
|
62
|
+
"length": 2,
|
|
63
|
+
"arity": 2
|
|
64
|
+
},
|
|
65
|
+
"le" : {
|
|
66
|
+
"tk": 1,
|
|
67
|
+
"name": "LE",
|
|
68
|
+
"cls": "function",
|
|
69
|
+
"length": 2,
|
|
70
|
+
"arity": 2
|
|
71
|
+
},
|
|
72
|
+
"gt" : {
|
|
73
|
+
"tk": 1,
|
|
74
|
+
"name": "GT",
|
|
75
|
+
"cls": "function",
|
|
76
|
+
"length": 2,
|
|
77
|
+
"arity": 2
|
|
78
|
+
},
|
|
79
|
+
"ge" : {
|
|
80
|
+
"tk": 1,
|
|
81
|
+
"name": "GE",
|
|
82
|
+
"cls": "function",
|
|
83
|
+
"length": 2,
|
|
84
|
+
"arity": 2
|
|
85
|
+
},
|
|
86
|
+
"ne" : {
|
|
87
|
+
"tk": 1,
|
|
88
|
+
"name": "NE",
|
|
89
|
+
"cls": "function",
|
|
90
|
+
"length": 2,
|
|
91
|
+
"arity": 2
|
|
92
|
+
},
|
|
93
|
+
"len" : {
|
|
94
|
+
"tk": 1,
|
|
95
|
+
"name": "LEN",
|
|
96
|
+
"cls": "function",
|
|
97
|
+
"length": 1,
|
|
98
|
+
"arity": 1
|
|
99
|
+
},
|
|
100
|
+
"concat" : {
|
|
101
|
+
"tk": 1,
|
|
102
|
+
"name": "CONCAT",
|
|
103
|
+
"cls": "function",
|
|
104
|
+
"length": 1,
|
|
105
|
+
"arity": 1
|
|
106
|
+
},
|
|
107
|
+
"add" : {
|
|
108
|
+
"tk": 1,
|
|
109
|
+
"name": "ADD",
|
|
110
|
+
"cls": "function",
|
|
111
|
+
"length": 2,
|
|
112
|
+
"arity": 2
|
|
113
|
+
},
|
|
114
|
+
"mul" : {
|
|
115
|
+
"tk": 1,
|
|
116
|
+
"name": "MUL",
|
|
117
|
+
"cls": "function",
|
|
118
|
+
"length": 2,
|
|
119
|
+
"arity": 2
|
|
120
|
+
},
|
|
121
|
+
"pow" : {
|
|
122
|
+
"tk": 1,
|
|
123
|
+
"name": "POW",
|
|
124
|
+
"cls": "function",
|
|
125
|
+
"length": 2,
|
|
126
|
+
"arity": 2
|
|
127
|
+
},
|
|
128
|
+
"map" : {
|
|
129
|
+
"tk": 1,
|
|
130
|
+
"name": "MAP",
|
|
131
|
+
"cls": "function",
|
|
132
|
+
"length": 2,
|
|
133
|
+
"arity": 2
|
|
134
|
+
},
|
|
135
|
+
"apply" : {
|
|
136
|
+
"tk": 1,
|
|
137
|
+
"name": "APPLY",
|
|
138
|
+
"cls": "function",
|
|
139
|
+
"length": 2,
|
|
140
|
+
"arity": 2
|
|
141
|
+
},
|
|
142
|
+
"data" : {
|
|
143
|
+
"tk": 1,
|
|
144
|
+
"name": "DATA",
|
|
145
|
+
"cls": "function",
|
|
146
|
+
"length": 1,
|
|
147
|
+
"arity": 1
|
|
148
|
+
},
|
|
149
|
+
"json" : {
|
|
150
|
+
"tk": 1,
|
|
151
|
+
"name": "JSON",
|
|
152
|
+
"cls": "function",
|
|
153
|
+
"length": 1,
|
|
154
|
+
"arity": 1
|
|
155
|
+
},
|
|
156
|
+
"eq" : {
|
|
157
|
+
"tk": 1,
|
|
158
|
+
"name": "EQ",
|
|
159
|
+
"cls": "function",
|
|
160
|
+
"length": 2,
|
|
161
|
+
"arity": 2
|
|
162
|
+
},
|
|
163
|
+
"mod" : {
|
|
164
|
+
"tk": 1,
|
|
165
|
+
"name": "MOD",
|
|
166
|
+
"cls": "function",
|
|
167
|
+
"length": 2,
|
|
168
|
+
"arity": 2
|
|
169
|
+
},
|
|
170
|
+
"min" : {
|
|
171
|
+
"tk": 1,
|
|
172
|
+
"name": "MIN",
|
|
173
|
+
"cls": "function",
|
|
174
|
+
"length": 2,
|
|
175
|
+
"arity": 2
|
|
176
|
+
},
|
|
177
|
+
"max" : {
|
|
178
|
+
"tk": 1,
|
|
179
|
+
"name": "MAX",
|
|
180
|
+
"cls": "function",
|
|
181
|
+
"length": 2,
|
|
182
|
+
"arity": 2
|
|
183
|
+
},
|
|
184
|
+
"range" : {
|
|
185
|
+
"tk": 1,
|
|
186
|
+
"name": "RANGE",
|
|
187
|
+
"cls": "function",
|
|
188
|
+
"length": 3,
|
|
189
|
+
"arity": 3
|
|
190
|
+
}
|
|
191
|
+
}
|