diff --git a/packages/mondo/mondo.mjs b/packages/mondo/mondo.mjs index cb088fa9f..68ce390d4 100644 --- a/packages/mondo/mondo.mjs +++ b/packages/mondo/mondo.mjs @@ -8,7 +8,8 @@ This program is free software: you can redistribute it and/or modify it under th export class MondoParser { // these are the tokens we expect token_types = { - string: /^"(.*?)"/, + quotes_double: /^"(.*?)"/, + quotes_single: /^'(.*?)'/, open_list: /^\(/, close_list: /^\)/, open_cat: /^ 1 || expressions[0].type !== 'list') { return { type: 'list', - children: this.desugar_children(expressions), + children: this.desugar(expressions), }; } // we have a single list @@ -110,7 +111,7 @@ export class MondoParser { let commaIndex = children.findIndex((child) => child.type === split_type); if (commaIndex === -1) break; const chunk = children.slice(0, commaIndex); - chunks.push(chunk); + chunk.length && chunks.push(chunk); children = children.slice(commaIndex + 1); } if (!chunks.length) { @@ -227,24 +228,26 @@ export class MondoParser { this.consume(close_type); return children; } + desugar(children, type) { + // not really needed but more readable and might be extended in the future + children = this.desugar_stack(children, type); + return children; + } parse_list() { let children = this.parse_pair('open_list', 'close_list'); - children = this.desugar_stack(children); - children = this.desugar_children(children); + children = this.desugar(children); return { type: 'list', children }; } parse_cat() { let children = this.parse_pair('open_cat', 'close_cat'); children = [{ type: 'plain', value: 'cat' }, ...children]; - children = this.desugar_stack(children, 'cat'); - children = this.desugar_children(children); + children = this.desugar(children, 'cat'); return { type: 'list', children }; } parse_seq() { let children = this.parse_pair('open_seq', 'close_seq'); children = [{ type: 'plain', value: 'seq' }, ...children]; - children = this.desugar_stack(children, 'seq'); - children = this.desugar_children(children); + children = this.desugar(children, 'seq'); return { type: 'list', children }; } consume(type) { @@ -322,16 +325,19 @@ export class MondoRunner { // process args const args = ast.children.slice(1).map((arg) => { - if (arg.type === 'string') { - return this.lib.string(arg.value.slice(1, -1), arg); + if (arg.type === 'list') { + return this.call(arg); } - if (arg.type === 'plain') { - return this.lib.plain(arg.value, arg); + if (!this.lib.leaf) { + throw new Error(`no handler for leaft nodes! add leaf to your lib`); } + if (arg.type === 'number') { - return this.lib.number(Number(arg.value), arg); + arg.value = Number(arg.value); + } else if (['quotes_double', 'quotes_single'].includes(arg.type)) { + arg.value = arg.value.slice(1, -1); } - return this.call(arg); + return this.lib.leaf(arg); }); if (name === '.') { diff --git a/packages/mondo/test/mondo.test.mjs b/packages/mondo/test/mondo.test.mjs index 40595004d..a88041821 100644 --- a/packages/mondo/test/mondo.test.mjs +++ b/packages/mondo/test/mondo.test.mjs @@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under th */ import { describe, expect, it } from 'vitest'; -import { MondoParser, MondoRunner, printAst } from '../mondo.mjs'; +import { MondoParser, printAst } from '../mondo.mjs'; const parser = new MondoParser(); const p = (code) => parser.parse(code, -1); diff --git a/packages/mondough/mondough.mjs b/packages/mondough/mondough.mjs index 21250ad20..52b169cae 100644 --- a/packages/mondough/mondough.mjs +++ b/packages/mondough/mondough.mjs @@ -1,21 +1,20 @@ -import { strudelScope, reify, fast, slow, isPattern } from '@strudel/core'; +import { strudelScope, reify, fast, slow } from '@strudel/core'; import { registerLanguage } from '@strudel/transpiler'; import { MondoRunner } from '../mondo/mondo.mjs'; -let runner = new MondoRunner(strudelScope, { pipepost: true, loc: true }); +let runner = new MondoRunner(strudelScope); -let getLeaf = (value, token) => { +strudelScope.leaf = (token) => { + let { value } = token; const [from, to] = token.loc; - if (strudelScope[value]) { + if (token.type === 'plain' && strudelScope[value]) { + // what if we want a string that happens to also be a variable name? + // example: "s sine" -> sine is also a variable return reify(strudelScope[value]).withLoc(from, to); } return reify(value).withLoc(from, to); }; -strudelScope.plain = getLeaf; -strudelScope.number = getLeaf; -strudelScope.string = getLeaf; - strudelScope.call = (fn, args, name) => { const [pat, ...rest] = args; if (!['seq', 'cat', 'stack'].includes(name)) {