@graffiticode/basis 1.5.17 → 1.5.19

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 CHANGED
@@ -3,3 +3,4 @@ export const Checker = basis.Checker;
3
3
  export const Transformer = basis.Transformer;
4
4
  export const Renderer = basis.Renderer;
5
5
  export const Compiler = basis.Compiler;
6
+ export { lexicon } from "./src/lexicon.js";
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@graffiticode/basis",
3
3
  "type": "module",
4
- "version": "1.5.17",
4
+ "version": "1.5.19",
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",
11
+ "publish-spec": "npm run build-spec && for dir in ../l0*/packages/api/public; do cp ./spec/spec.html \"$dir/graffiticode-language-spec.html\"; echo \"Copied to $dir/graffiticode-language-spec.html\"; done"
9
12
  },
10
13
  "engines": {
11
14
  "node": "22.x"
package/spec/spec.html ADDED
@@ -0,0 +1,531 @@
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>&lt;</code>, <code>&gt;</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 = &lt;x: mul 2 x&gt;..
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>&lt;x: add x 1&gt;
128
+ </code></pre>
129
+ <p>Multiple parameters: <code>&lt;x y: add x y&gt;</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 = &lt;x: mul 2 x&gt;..
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
+ <p>Many built-in functions in Graffiticode follow a model-threading pattern. In this pattern, functions are defined to take one or more arguments followed by a model, which represents the current state of the program or view. The function uses the earlier arguments to compute an update to the model and returns a new model as its result.</p>
178
+ <p>This style enables a declarative and order-independent composition of functions. Since each function call returns a new model, multiple calls can be reordered without changing the final result, provided the functional dependencies are preserved.</p>
179
+ <p>This approach draws inspiration from <strong>Model-View-Update</strong> (MVU) architectures, in which the model represents the application state and functions describe pure, deterministic transformations of that state.</p>
180
+ </section>
181
+ <section id="sec-Functions" secid="4.2">
182
+ <h2><span class="spec-secid" title="link to this section"><a href="#sec-Functions">4.2</a></span>Functions</h2>
183
+ <ul>
184
+ <li><strong>Fixed arity</strong>: every function has a known number of parameters</li>
185
+ <li><strong>Curried by default</strong>: partial application supported</li>
186
+ </ul>
187
+ </section>
188
+ <section id="sec-Scoping" secid="4.3">
189
+ <h2><span class="spec-secid" title="link to this section"><a href="#sec-Scoping">4.3</a></span>Scoping</h2>
190
+ <ul>
191
+ <li><strong>Lexical scoping</strong></li>
192
+ <li><strong>Shadowing</strong> allowed within nested scopes</li>
193
+ </ul>
194
+ </section>
195
+ <section id="sec-Errors" secid="4.4">
196
+ <h2><span class="spec-secid" title="link to this section"><a href="#sec-Errors">4.4</a></span>Errors</h2>
197
+ <ul>
198
+ <li><strong>Syntax errors</strong>: raised during parsing</li>
199
+ <li><strong>Type errors</strong>: raised during compilation</li>
200
+ <li><strong>Runtime errors</strong>: e.g., out-of-bounds access</li>
201
+ </ul>
202
+ </section>
203
+ </section>
204
+ <section id="sec-Base-Library" secid="5">
205
+ <h1><span class="spec-secid" title="link to this section"><a href="#sec-Base-Library">5</a></span>Base Library</h1>
206
+ <section id="sec-Types" secid="5.1">
207
+ <h2><span class="spec-secid" title="link to this section"><a href="#sec-Types">5.1</a></span>Types</h2>
208
+ <ul>
209
+ <li><code>number</code></li>
210
+ <li><code>string</code></li>
211
+ <li><code>bool</code></li>
212
+ <li><code>list</code></li>
213
+ <li><code>record</code></li>
214
+ <li><code>tuple</code></li>
215
+ <li><code>json</code></li>
216
+ </ul>
217
+ </section>
218
+ <section id="sec-Built-in-Functions" secid="5.2">
219
+ <h2><span class="spec-secid" title="link to this section"><a href="#sec-Built-in-Functions">5.2</a></span>Built-in Functions</h2>
220
+ <table>
221
+ <thead>
222
+ <tr>
223
+ <th align="left">Function</th>
224
+ <th align="left">Signature</th>
225
+ <th align="left">Description</th>
226
+ </tr>
227
+ </thead>
228
+ <tbody>
229
+ <tr>
230
+ <td align="left"><code>add</code></td>
231
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
232
+ <td align="left">Adds two numbers</td>
233
+ </tr>
234
+ <tr>
235
+ <td align="left"><code>sub</code></td>
236
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
237
+ <td align="left">Subtracts numbers</td>
238
+ </tr>
239
+ <tr>
240
+ <td align="left"><code>mul</code></td>
241
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
242
+ <td align="left">Multiplies numbers</td>
243
+ </tr>
244
+ <tr>
245
+ <td align="left"><code>div</code></td>
246
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
247
+ <td align="left">Divides numbers</td>
248
+ </tr>
249
+ <tr>
250
+ <td align="left"><code>mod</code></td>
251
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
252
+ <td align="left">Remainder of division</td>
253
+ </tr>
254
+ <tr>
255
+ <td align="left"><code>min</code></td>
256
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
257
+ <td align="left">Returns the smaller of two numbers</td>
258
+ </tr>
259
+ <tr>
260
+ <td align="left"><code>max</code></td>
261
+ <td align="left"><code>&lt;number number: number&gt;</code></td>
262
+ <td align="left">Returns the larger of two numbers</td>
263
+ </tr>
264
+ <tr>
265
+ <td align="left"><code>range</code></td>
266
+ <td align="left"><code>&lt;number number number: list&gt;</code></td>
267
+ <td align="left">Generates a range list</td>
268
+ </tr>
269
+ <tr>
270
+ <td align="left"><code>map</code></td>
271
+ <td align="left"><code>&lt;function list: list&gt;</code></td>
272
+ <td align="left">Applies function to each item</td>
273
+ </tr>
274
+ <tr>
275
+ <td align="left"><code>filter</code></td>
276
+ <td align="left"><code>&lt;function list: list&gt;</code></td>
277
+ <td align="left">Keeps items matching predicate</td>
278
+ </tr>
279
+ <tr>
280
+ <td align="left"><code>reduce</code></td>
281
+ <td align="left"><code>&lt;function list: any&gt;</code></td>
282
+ <td align="left">Combines list using a reducer</td>
283
+ </tr>
284
+ <tr>
285
+ <td align="left"><code>hd</code></td>
286
+ <td align="left"><code>&lt;list: any&gt;</code></td>
287
+ <td align="left">First item of list</td>
288
+ </tr>
289
+ <tr>
290
+ <td align="left"><code>tl</code></td>
291
+ <td align="left"><code>&lt;list: list&gt;</code></td>
292
+ <td align="left">All items except first</td>
293
+ </tr>
294
+ <tr>
295
+ <td align="left"><code>nth</code></td>
296
+ <td align="left"><code>&lt;number list: any&gt;</code></td>
297
+ <td align="left">Nth element of list</td>
298
+ </tr>
299
+ <tr>
300
+ <td align="left"><code>apply</code></td>
301
+ <td align="left"><code>&lt;function list: any&gt;</code></td>
302
+ <td align="left">Applies a function to a list of arguments</td>
303
+ </tr>
304
+ <tr>
305
+ <td align="left"><code>isEmpty</code></td>
306
+ <td align="left"><code>&lt;list: bool&gt;</code></td>
307
+ <td align="left">Returns true if the list is empty</td>
308
+ </tr>
309
+ <tr>
310
+ <td align="left"><code>get</code></td>
311
+ <td align="left"><code>&lt;string record: any&gt;</code></td>
312
+ <td align="left">Retrieves a value from a record by key</td>
313
+ </tr>
314
+ <tr>
315
+ <td align="left"><code>set</code></td>
316
+ <td align="left"><code>&lt;string any record: record&gt;</code></td>
317
+ <td align="left">Returns a new record with a key set to a value</td>
318
+ </tr>
319
+ </tbody>
320
+ </table>
321
+ <section id="sec-add" secid="5.2.1">
322
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-add">5.2.1</a></span>add</h3>
323
+ <p>Add two numbers.</p>
324
+ <pre><code>add 2 3 | returns 5
325
+ </code></pre>
326
+ </section>
327
+ <section id="sec-sub" secid="5.2.2">
328
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-sub">5.2.2</a></span>sub</h3>
329
+ <p>Subtract the second number from the first</p>
330
+ <pre><code>sub 5 2 | returns 3
331
+ </code></pre>
332
+ </section>
333
+ <section id="sec-mul" secid="5.2.3">
334
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-mul">5.2.3</a></span>mul</h3>
335
+ <p>Multiply two numbers</p>
336
+ <pre><code>mul 4 3 | returns 12
337
+ </code></pre>
338
+ </section>
339
+ <section id="sec-div" secid="5.2.4">
340
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-div">5.2.4</a></span>div</h3>
341
+ <p>Divide the first number by the second</p>
342
+ <pre><code>div 10 2 | returns 5
343
+ </code></pre>
344
+ </section>
345
+ <section id="sec-mod" secid="5.2.5">
346
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-mod">5.2.5</a></span>mod</h3>
347
+ <p>Compute the remainder</p>
348
+ <pre><code>mod 10 3 | returns 1
349
+ </code></pre>
350
+ </section>
351
+ <section id="sec-min" secid="5.2.6">
352
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-min">5.2.6</a></span>min</h3>
353
+ <p>Return the smaller of two numbers</p>
354
+ <pre><code>min 5 10 | returns 5
355
+ </code></pre>
356
+ </section>
357
+ <section id="sec-max" secid="5.2.7">
358
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-max">5.2.7</a></span>max</h3>
359
+ <p>Return the larger of two numbers</p>
360
+ <pre><code>max 5 10 | returns 10
361
+ </code></pre>
362
+ </section>
363
+ <section id="sec-range" secid="5.2.8">
364
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-range">5.2.8</a></span>range</h3>
365
+ <p>Produce a range list from start to end (exclusive) with step</p>
366
+ <pre><code>range 1 10 2 | returns [1 3 5 7 9]
367
+ </code></pre>
368
+ </section>
369
+ <section id="sec-map" secid="5.2.9">
370
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-map">5.2.9</a></span>map</h3>
371
+ <p>Apply a function to each element</p>
372
+ <pre><code>map (&lt;x: add x 1&gt;) [1 2 3] | returns [2 3 4]
373
+ </code></pre>
374
+ </section>
375
+ <section id="sec-filter" secid="5.2.10">
376
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-filter">5.2.10</a></span>filter</h3>
377
+ <p>Filter elements matching predicate</p>
378
+ <pre><code>filter (&lt;x: mod x 2&gt;) [1 2 3 4] | returns [1 3]
379
+ </code></pre>
380
+ </section>
381
+ <section id="sec-reduce" secid="5.2.11">
382
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-reduce">5.2.11</a></span>reduce</h3>
383
+ <p>Reduce a list to a single value, starting with an initial value</p>
384
+ <pre><code>reduce (&lt;a b: add a b&gt;) 0 [1 2 3 4] | returns 10
385
+ </code></pre>
386
+ </section>
387
+ <section id="sec-hd" secid="5.2.12">
388
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-hd">5.2.12</a></span>hd</h3>
389
+ <p>Return the first item</p>
390
+ <pre><code>hd [10 20 30] | returns 10
391
+ </code></pre>
392
+ </section>
393
+ <section id="sec-tl" secid="5.2.13">
394
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-tl">5.2.13</a></span>tl</h3>
395
+ <p>Return all but the first item</p>
396
+ <pre><code>tl [10 20 30] | returns [20 30]
397
+ </code></pre>
398
+ </section>
399
+ <section id="sec-nth" secid="5.2.14">
400
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-nth">5.2.14</a></span>nth</h3>
401
+ <p>Get the nth item (0-based)</p>
402
+ <pre><code>nth 1 [10 20 30] | returns 20
403
+ </code></pre>
404
+ </section>
405
+ <section id="sec-apply" secid="5.2.15">
406
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-apply">5.2.15</a></span>apply</h3>
407
+ <p>Apply a function to an argument list</p>
408
+ <pre><code>apply add [1 2] | returns 3
409
+ </code></pre>
410
+ </section>
411
+ <section id="sec-isEmpty" secid="5.2.16">
412
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-isEmpty">5.2.16</a></span>isEmpty</h3>
413
+ <p>Return true if list is empty, otherwise return false</p>
414
+ <pre><code>isEmpty [] | returns true
415
+ </code></pre>
416
+ </section>
417
+ <section id="sec-get" secid="5.2.17">
418
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-get">5.2.17</a></span>get</h3>
419
+ <p>Retrieve a record field</p>
420
+ <pre><code>get "b" {a: 1, b: 2} | returns 2
421
+ </code></pre>
422
+ </section>
423
+ <section id="sec-set" secid="5.2.18">
424
+ <h3><span class="spec-secid" title="link to this section"><a href="#sec-set">5.2.18</a></span>set</h3>
425
+ <p>Return a new record with an updated field</p>
426
+ <pre><code>set "a" 2 {a: 1} | returns {a: 2}
427
+ </code></pre>
428
+ </section>
429
+ </section>
430
+ </section>
431
+ <section id="sec-Program-Examples" secid="6">
432
+ <h1><span class="spec-secid" title="link to this section"><a href="#sec-Program-Examples">6</a></span>Program Examples</h1>
433
+ <pre><code>let double = &lt;x: mul 2 x&gt;..
434
+ map (double) [1 2 3]..
435
+ </code></pre>
436
+ <pre><code>case age of
437
+ 18: "adult"
438
+ _: "other"
439
+ end..
440
+ </code></pre>
441
+ <p>---</p>
442
+ </section>
443
+ <section id="index" secid="index" class="spec-index">
444
+ <h1>
445
+ <span class="spec-secid" title="link to the index"><a href="#index">§</a></span>Index</h1>
446
+ <ol>
447
+ <li><a href="#Supports">Supports</a></li>
448
+ </ol>
449
+ </section>
450
+ </article>
451
+ <footer>
452
+ Written in <a href="https://spec-md.com" target="_blank">Spec Markdown</a>.</footer>
453
+ <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">&#x2630;</div></label>
454
+ <div class="spec-sidebar" aria-hidden>
455
+ <div class="spec-toc">
456
+ <div class="title"><a href="#">Graffiticode Core Language Specification</a></div>
457
+ <ol><li id="_sidebar_1"><a href="#sec-Introduction"><span class="spec-secid">1</span>Introduction</a></li>
458
+ <li id="_sidebar_2"><a href="#sec-Lexical-Structure"><span class="spec-secid">2</span>Lexical Structure</a>
459
+ <input hidden class="toggle" type="checkbox" id="_toggle_2" /><label for="_toggle_2"></label>
460
+ <ol>
461
+ <li id="_sidebar_2.1"><a href="#sec-Tokens"><span class="spec-secid">2.1</span>Tokens</a></li>
462
+ <li id="_sidebar_2.2"><a href="#sec-Comments"><span class="spec-secid">2.2</span>Comments</a></li>
463
+ </ol>
464
+ </li>
465
+ <li id="_sidebar_3"><a href="#sec-Syntax"><span class="spec-secid">3</span>Syntax</a>
466
+ <input hidden class="toggle" type="checkbox" id="_toggle_3" /><label for="_toggle_3"></label>
467
+ <ol>
468
+ <li id="_sidebar_3.1"><a href="#sec-Programs"><span class="spec-secid">3.1</span>Programs</a></li>
469
+ <li id="_sidebar_3.2"><a href="#sec-Expressions"><span class="spec-secid">3.2</span>Expressions</a>
470
+ <input hidden class="toggle" type="checkbox" id="_toggle_3.2" /><label for="_toggle_3.2"></label>
471
+ <ol>
472
+ <li id="_sidebar_3.2.1"><a href="#sec-Function-Application"><span class="spec-secid">3.2.1</span>Function Application</a></li>
473
+ <li id="_sidebar_3.2.2"><a href="#sec-Lists"><span class="spec-secid">3.2.2</span>Lists</a></li>
474
+ <li id="_sidebar_3.2.3"><a href="#sec-Records"><span class="spec-secid">3.2.3</span>Records</a></li>
475
+ <li id="_sidebar_3.2.4"><a href="#sec-Lambdas"><span class="spec-secid">3.2.4</span>Lambdas</a></li>
476
+ <li id="_sidebar_3.2.5"><a href="#sec-Let-Bindings"><span class="spec-secid">3.2.5</span>Let Bindings</a></li>
477
+ </ol>
478
+ </li>
479
+ <li id="_sidebar_3.3"><a href="#sec-Pattern-Matching"><span class="spec-secid">3.3</span>Pattern Matching</a>
480
+ <input hidden class="toggle" type="checkbox" id="_toggle_3.3" /><label for="_toggle_3.3"></label>
481
+ <ol>
482
+ <li id="_sidebar_3.3.1"><a href="#sec-Tag-Values"><span class="spec-secid">3.3.1</span>Tag Values</a></li>
483
+ </ol>
484
+ </li>
485
+ </ol>
486
+ </li>
487
+ <li id="_sidebar_4"><a href="#sec-Semantics"><span class="spec-secid">4</span>Semantics</a>
488
+ <input hidden class="toggle" type="checkbox" id="_toggle_4" /><label for="_toggle_4"></label>
489
+ <ol>
490
+ <li id="_sidebar_4.1"><a href="#sec-Evaluation-Model"><span class="spec-secid">4.1</span>Evaluation Model</a></li>
491
+ <li id="_sidebar_4.2"><a href="#sec-Functions"><span class="spec-secid">4.2</span>Functions</a></li>
492
+ <li id="_sidebar_4.3"><a href="#sec-Scoping"><span class="spec-secid">4.3</span>Scoping</a></li>
493
+ <li id="_sidebar_4.4"><a href="#sec-Errors"><span class="spec-secid">4.4</span>Errors</a></li>
494
+ </ol>
495
+ </li>
496
+ <li id="_sidebar_5"><a href="#sec-Base-Library"><span class="spec-secid">5</span>Base Library</a>
497
+ <input hidden class="toggle" type="checkbox" id="_toggle_5" /><label for="_toggle_5"></label>
498
+ <ol>
499
+ <li id="_sidebar_5.1"><a href="#sec-Types"><span class="spec-secid">5.1</span>Types</a></li>
500
+ <li id="_sidebar_5.2"><a href="#sec-Built-in-Functions"><span class="spec-secid">5.2</span>Built-in Functions</a>
501
+ <input hidden class="toggle" type="checkbox" id="_toggle_5.2" /><label for="_toggle_5.2"></label>
502
+ <ol>
503
+ <li id="_sidebar_5.2.1"><a href="#sec-add"><span class="spec-secid">5.2.1</span>add</a></li>
504
+ <li id="_sidebar_5.2.2"><a href="#sec-sub"><span class="spec-secid">5.2.2</span>sub</a></li>
505
+ <li id="_sidebar_5.2.3"><a href="#sec-mul"><span class="spec-secid">5.2.3</span>mul</a></li>
506
+ <li id="_sidebar_5.2.4"><a href="#sec-div"><span class="spec-secid">5.2.4</span>div</a></li>
507
+ <li id="_sidebar_5.2.5"><a href="#sec-mod"><span class="spec-secid">5.2.5</span>mod</a></li>
508
+ <li id="_sidebar_5.2.6"><a href="#sec-min"><span class="spec-secid">5.2.6</span>min</a></li>
509
+ <li id="_sidebar_5.2.7"><a href="#sec-max"><span class="spec-secid">5.2.7</span>max</a></li>
510
+ <li id="_sidebar_5.2.8"><a href="#sec-range"><span class="spec-secid">5.2.8</span>range</a></li>
511
+ <li id="_sidebar_5.2.9"><a href="#sec-map"><span class="spec-secid">5.2.9</span>map</a></li>
512
+ <li id="_sidebar_5.2.10"><a href="#sec-filter"><span class="spec-secid">5.2.10</span>filter</a></li>
513
+ <li id="_sidebar_5.2.11"><a href="#sec-reduce"><span class="spec-secid">5.2.11</span>reduce</a></li>
514
+ <li id="_sidebar_5.2.12"><a href="#sec-hd"><span class="spec-secid">5.2.12</span>hd</a></li>
515
+ <li id="_sidebar_5.2.13"><a href="#sec-tl"><span class="spec-secid">5.2.13</span>tl</a></li>
516
+ <li id="_sidebar_5.2.14"><a href="#sec-nth"><span class="spec-secid">5.2.14</span>nth</a></li>
517
+ <li id="_sidebar_5.2.15"><a href="#sec-apply"><span class="spec-secid">5.2.15</span>apply</a></li>
518
+ <li id="_sidebar_5.2.16"><a href="#sec-isEmpty"><span class="spec-secid">5.2.16</span>isEmpty</a></li>
519
+ <li id="_sidebar_5.2.17"><a href="#sec-get"><span class="spec-secid">5.2.17</span>get</a></li>
520
+ <li id="_sidebar_5.2.18"><a href="#sec-set"><span class="spec-secid">5.2.18</span>set</a></li>
521
+ </ol>
522
+ </li>
523
+ </ol>
524
+ </li>
525
+ <li id="_sidebar_6"><a href="#sec-Program-Examples"><span class="spec-secid">6</span>Program Examples</a></li>
526
+ <li id="_sidebar_index"><a href="#index"><span class="spec-secid">§</span>Index</a></li>
527
+ </ol>
528
+ </div>
529
+ </div>
530
+ </body>
531
+ </html>
package/spec/spec.md ADDED
@@ -0,0 +1,340 @@
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
+ Many built-in functions in Graffiticode follow a model-threading pattern. In this pattern, functions are defined to take one or more arguments followed by a model, which represents the current state of the program or view. The function uses the earlier arguments to compute an update to the model and returns a new model as its result.
123
+
124
+ This style enables a declarative and order-independent composition of functions. Since each function call returns a new model, multiple calls can be reordered without changing the final result, provided the functional dependencies are preserved.
125
+
126
+ This approach draws inspiration from **Model-View-Update** (MVU) architectures, in which the model represents the application state and functions describe pure, deterministic transformations of that state.
127
+
128
+
129
+
130
+ ## Functions
131
+
132
+ - **Fixed arity**: every function has a known number of parameters
133
+ - **Curried by default**: partial application supported
134
+
135
+ ## Scoping
136
+
137
+ - **Lexical scoping**
138
+ - **Shadowing** allowed within nested scopes
139
+
140
+ ## Errors
141
+
142
+ - **Syntax errors**: raised during parsing
143
+ - **Type errors**: raised during compilation
144
+ - **Runtime errors**: e.g., out-of-bounds access
145
+
146
+ # Base Library
147
+
148
+ ## Types
149
+
150
+ - `number`
151
+ - `string`
152
+ - `bool`
153
+ - `list`
154
+ - `record`
155
+ - `tuple`
156
+ - `json`
157
+
158
+ ## Built-in Functions
159
+
160
+ | Function | Signature | Description |
161
+ | :------- | :-------- | :---------- |
162
+ | `add` | `<number number: number>` | Adds two numbers |
163
+ | `sub` | `<number number: number>` | Subtracts numbers |
164
+ | `mul` | `<number number: number>` | Multiplies numbers |
165
+ | `div` | `<number number: number>` | Divides numbers |
166
+ | `mod` | `<number number: number>` | Remainder of division |
167
+ | `min` | `<number number: number>` | Returns the smaller of two numbers |
168
+ | `max` | `<number number: number>` | Returns the larger of two numbers |
169
+ | `range` | `<number number number: list>` | Generates a range list |
170
+ | `map` | `<function list: list>` | Applies function to each item |
171
+ | `filter` | `<function list: list>` | Keeps items matching predicate |
172
+ | `reduce` | `<function list: any>` | Combines list using a reducer |
173
+ | `hd` | `<list: any>` | First item of list |
174
+ | `tl` | `<list: list>` | All items except first |
175
+ | `nth` | `<number list: any>` | Nth element of list |
176
+ | `apply` | `<function list: any>` | Applies a function to a list of arguments |
177
+ | `isEmpty` | `<list: bool>` | Returns true if the list is empty |
178
+ | `get` | `<string record: any>` | Retrieves a value from a record by key |
179
+ | `set` | `<string any record: record>` | Returns a new record with a key set to a value |
180
+
181
+ ### add
182
+
183
+ Add two numbers.
184
+
185
+ ```
186
+ add 2 3 | returns 5
187
+ ```
188
+
189
+ ### sub
190
+
191
+ Subtract the second number from the first
192
+
193
+ ```
194
+ sub 5 2 | returns 3
195
+ ```
196
+
197
+ ### mul
198
+
199
+ Multiply two numbers
200
+
201
+ ```
202
+ mul 4 3 | returns 12
203
+ ```
204
+
205
+ ### div
206
+
207
+ Divide the first number by the second
208
+
209
+ ```
210
+ div 10 2 | returns 5
211
+ ```
212
+
213
+ ### mod
214
+
215
+ Compute the remainder
216
+
217
+ ```
218
+ mod 10 3 | returns 1
219
+ ```
220
+
221
+ ### min
222
+
223
+ Return the smaller of two numbers
224
+
225
+ ```
226
+ min 5 10 | returns 5
227
+ ```
228
+
229
+ ### max
230
+
231
+ Return the larger of two numbers
232
+
233
+ ```
234
+ max 5 10 | returns 10
235
+ ```
236
+
237
+ ### range
238
+
239
+ Produce a range list from start to end (exclusive) with step
240
+
241
+ ```
242
+ range 1 10 2 | returns [1 3 5 7 9]
243
+ ```
244
+
245
+ ### map
246
+
247
+ Apply a function to each element
248
+
249
+ ```
250
+ map (<x: add x 1>) [1 2 3] | returns [2 3 4]
251
+ ```
252
+
253
+ ### filter
254
+
255
+ Filter elements matching predicate
256
+
257
+ ```
258
+ filter (<x: mod x 2>) [1 2 3 4] | returns [1 3]
259
+ ```
260
+
261
+ ### reduce
262
+
263
+ Reduce a list to a single value, starting with an initial value
264
+
265
+ ```
266
+ reduce (<a b: add a b>) 0 [1 2 3 4] | returns 10
267
+ ```
268
+
269
+ ### hd
270
+
271
+ Return the first item
272
+
273
+ ```
274
+ hd [10 20 30] | returns 10
275
+ ```
276
+
277
+ ### tl
278
+
279
+ Return all but the first item
280
+
281
+ ```
282
+ tl [10 20 30] | returns [20 30]
283
+ ```
284
+
285
+ ### nth
286
+
287
+ Get the nth item (0-based)
288
+
289
+ ```
290
+ nth 1 [10 20 30] | returns 20
291
+ ```
292
+
293
+ ### apply
294
+
295
+ Apply a function to an argument list
296
+
297
+ ```
298
+ apply add [1 2] | returns 3
299
+ ```
300
+
301
+ ### isEmpty
302
+
303
+ Return true if list is empty, otherwise return false
304
+
305
+ ```
306
+ isEmpty [] | returns true
307
+ ```
308
+
309
+ ### get
310
+
311
+ Retrieve a record field
312
+
313
+ ```
314
+ get "b" {a: 1, b: 2} | returns 2
315
+ ```
316
+
317
+ ### set
318
+
319
+ Return a new record with an updated field
320
+
321
+ ```
322
+ set "a" 2 {a: 1} | returns {a: 2}
323
+ ```
324
+
325
+ # Program Examples
326
+
327
+ ```
328
+ let double = <x: mul 2 x>..
329
+ map (double) [1 2 3]..
330
+ ```
331
+
332
+ ```
333
+ case age of
334
+ 18: "adult"
335
+ _: "other"
336
+ end..
337
+ ```
338
+
339
+ ---
340
+
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) {
@@ -989,9 +1007,9 @@ export class Transformer extends Visitor {
989
1007
  this.visit(node.elts[0], options, (e0, v0) => {
990
1008
  this.visit(node.elts[1], options, (e1, v1) => {
991
1009
  const err = [...e0, ...e1];
992
- assert(typeof v0 === "object", "Type Error: expected v0 to be an object. Got " + JSON.stringify(v0));
993
- assert(typeof v1 === "string", "Type Error: expected v1 to be a string.");
994
- const val = v0[v1];
1010
+ assert(typeof v0 === "string", "Type Error: expected v0 to be a string.");
1011
+ assert(typeof v1 === "object", "Type Error: expected v1 to be an object. Got " + JSON.stringify(v1));
1012
+ const val = v1[v0];
995
1013
  resume(err, val);
996
1014
  });
997
1015
  });
@@ -1000,12 +1018,12 @@ export class Transformer extends Visitor {
1000
1018
  this.visit(node.elts[0], options, (e0, v0) => {
1001
1019
  this.visit(node.elts[1], options, (e1, v1) => {
1002
1020
  this.visit(node.elts[2], options, (e2, v2) => {
1003
- const err = [...e0, ...e1];
1004
- assert(typeof v0 === "object", "Type Error: expected v0 to be an object.");
1005
- assert(typeof v1 === "string", "Type Error: expected v1 to be a string.");
1021
+ const err = [...e0, ...e1, ...e2];
1022
+ assert(typeof v0 === "string", "Type Error: expected v0 to be a string.");
1023
+ assert(typeof v2 === "object", "Type Error: expected v2 to be an object.");
1006
1024
  const val = {
1007
- ...v0,
1008
- [v1]: v2,
1025
+ ...v2,
1026
+ [v0]: v1,
1009
1027
  };
1010
1028
  resume(err, val);
1011
1029
  });
@@ -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,193 @@
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
+ "args": ["key", "record"]
16
+ },
17
+ "set" : {
18
+ "tk": 1,
19
+ "name": "SET",
20
+ "cls": "function",
21
+ "length": 3,
22
+ "arity": 3,
23
+ "args": ["key", "value", "record"]
24
+ },
25
+ "nth" : {
26
+ "tk": 1,
27
+ "name": "NTH",
28
+ "cls": "function",
29
+ "length": 2,
30
+ "arity": 2
31
+ },
32
+ "sub" : {
33
+ "tk": 1,
34
+ "name": "SUB",
35
+ "cls": "function",
36
+ "length": 2,
37
+ "arity": 2
38
+ },
39
+ "filter" : {
40
+ "tk": 1,
41
+ "name": "FILTER",
42
+ "cls": "function",
43
+ "length": 2,
44
+ "arity": 2
45
+ },
46
+ "reduce" : {
47
+ "tk": 1,
48
+ "name": "REDUCE",
49
+ "cls": "function",
50
+ "length": 3,
51
+ "arity": 3
52
+ },
53
+ "map" : {
54
+ "tk": 1,
55
+ "name": "MAP",
56
+ "cls": "function",
57
+ "length": 2,
58
+ "arity": 2
59
+ },
60
+ "lt" : {
61
+ "tk": 1,
62
+ "name": "LT",
63
+ "cls": "function",
64
+ "length": 2,
65
+ "arity": 2
66
+ },
67
+ "le" : {
68
+ "tk": 1,
69
+ "name": "LE",
70
+ "cls": "function",
71
+ "length": 2,
72
+ "arity": 2
73
+ },
74
+ "gt" : {
75
+ "tk": 1,
76
+ "name": "GT",
77
+ "cls": "function",
78
+ "length": 2,
79
+ "arity": 2
80
+ },
81
+ "ge" : {
82
+ "tk": 1,
83
+ "name": "GE",
84
+ "cls": "function",
85
+ "length": 2,
86
+ "arity": 2
87
+ },
88
+ "ne" : {
89
+ "tk": 1,
90
+ "name": "NE",
91
+ "cls": "function",
92
+ "length": 2,
93
+ "arity": 2
94
+ },
95
+ "len" : {
96
+ "tk": 1,
97
+ "name": "LEN",
98
+ "cls": "function",
99
+ "length": 1,
100
+ "arity": 1
101
+ },
102
+ "concat" : {
103
+ "tk": 1,
104
+ "name": "CONCAT",
105
+ "cls": "function",
106
+ "length": 1,
107
+ "arity": 1
108
+ },
109
+ "add" : {
110
+ "tk": 1,
111
+ "name": "ADD",
112
+ "cls": "function",
113
+ "length": 2,
114
+ "arity": 2
115
+ },
116
+ "mul" : {
117
+ "tk": 1,
118
+ "name": "MUL",
119
+ "cls": "function",
120
+ "length": 2,
121
+ "arity": 2
122
+ },
123
+ "pow" : {
124
+ "tk": 1,
125
+ "name": "POW",
126
+ "cls": "function",
127
+ "length": 2,
128
+ "arity": 2
129
+ },
130
+ "map" : {
131
+ "tk": 1,
132
+ "name": "MAP",
133
+ "cls": "function",
134
+ "length": 2,
135
+ "arity": 2
136
+ },
137
+ "apply" : {
138
+ "tk": 1,
139
+ "name": "APPLY",
140
+ "cls": "function",
141
+ "length": 2,
142
+ "arity": 2
143
+ },
144
+ "data" : {
145
+ "tk": 1,
146
+ "name": "DATA",
147
+ "cls": "function",
148
+ "length": 1,
149
+ "arity": 1
150
+ },
151
+ "json" : {
152
+ "tk": 1,
153
+ "name": "JSON",
154
+ "cls": "function",
155
+ "length": 1,
156
+ "arity": 1
157
+ },
158
+ "eq" : {
159
+ "tk": 1,
160
+ "name": "EQ",
161
+ "cls": "function",
162
+ "length": 2,
163
+ "arity": 2
164
+ },
165
+ "mod" : {
166
+ "tk": 1,
167
+ "name": "MOD",
168
+ "cls": "function",
169
+ "length": 2,
170
+ "arity": 2
171
+ },
172
+ "min" : {
173
+ "tk": 1,
174
+ "name": "MIN",
175
+ "cls": "function",
176
+ "length": 2,
177
+ "arity": 2
178
+ },
179
+ "max" : {
180
+ "tk": 1,
181
+ "name": "MAX",
182
+ "cls": "function",
183
+ "length": 2,
184
+ "arity": 2
185
+ },
186
+ "range" : {
187
+ "tk": 1,
188
+ "name": "RANGE",
189
+ "cls": "function",
190
+ "length": 3,
191
+ "arity": 3
192
+ }
193
+ }