From f71db4aeed3907e3a4e611100ef746fcbf5cdcf3 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 21 Mar 2025 23:50:14 +0100 Subject: [PATCH] mondo: flip pipe order: now pining to the end of the function... --- packages/mondo/mondo.mjs | 67 +++++++++--------------------- packages/mondo/test/mondo.test.mjs | 28 ++++++------- packages/mondough/mondough.mjs | 5 --- 3 files changed, 34 insertions(+), 66 deletions(-) diff --git a/packages/mondo/mondo.mjs b/packages/mondo/mondo.mjs index da969c23..1a211e60 100644 --- a/packages/mondo/mondo.mjs +++ b/packages/mondo/mondo.mjs @@ -106,25 +106,22 @@ export class MondoParser { children = this.resolve_pipes(children); return children; } - // Token[] => Token[][] . returns empty list if type not found + // Token[] => Token[][], e.g. (x , y z) => [['x'],['y','z']] split_children(children, split_type) { const chunks = []; while (true) { - let commaIndex = children.findIndex((child) => child.type === split_type); - if (commaIndex === -1) break; - const chunk = children.slice(0, commaIndex); + let splitIndex = children.findIndex((child) => child.type === split_type); + if (splitIndex === -1) break; + const chunk = children.slice(0, splitIndex); chunk.length && chunks.push(chunk); - children = children.slice(commaIndex + 1); - } - if (!chunks.length) { - return []; + children = children.slice(splitIndex + 1); } chunks.push(children); return chunks; } desugar_split(children, split_type, next) { const chunks = this.split_children(children, split_type); - if (!chunks.length) { + if (chunks.length === 1) { return next(children); } // collect args of stack function @@ -168,7 +165,8 @@ export class MondoParser { children[opIndex] = op; continue; } - const call = { type: 'list', children: [op, left, right] }; + //const call = { type: 'list', children: [op, left, right] }; + const call = { type: 'list', children: [op, right, left] }; // insert call while keeping other siblings children = [...children.slice(0, opIndex - 1), call, ...children.slice(opIndex + 2)]; children = this.unwrap_children(children); @@ -176,46 +174,21 @@ export class MondoParser { return children; } resolve_pipes(children) { - while (true) { - let pipeIndex = children.findIndex((child) => child.type === 'pipe'); - // no pipe => we're done - if (pipeIndex === -1) break; - // pipe up front => lambda - if (pipeIndex === 0) { - // . as lambda: (.fast 2) = (lambda (_) (fast _ 2)) - const args = [{ type: 'plain', value: '_' }]; - const body = this.desugar([args[0], ...children]); - return [ - { type: 'plain', value: 'lambda' }, - { type: 'list', children: args }, - { type: 'list', children: body }, - ]; - } - const rightSide = children.slice(pipeIndex + 2); - const right = children[pipeIndex + 1]; - if (right.type === 'list') { - // apply function only to left sibling (high precedence) - // s jazz.(fast 2) => s (fast jazz 2) - const [callee, ...rest] = right.children; - const leftSide = children.slice(0, pipeIndex - 1); - const left = children[pipeIndex - 1]; - let args = [callee, left, ...rest]; - const call = { type: 'list', children: args }; - children = [...leftSide, call, ...rightSide]; + let chunks = this.split_children(children, 'pipe'); + while (chunks.length > 1) { + let [left, right, ...rest] = chunks; + if (right.length && right[0].type === 'list') { + // s jazz hh.(fast 2) => s jazz (fast 2 hh) + const target = left[left.length - 1]; // hh + const call = { type: 'list', children: [...right[0].children, target] }; + chunks = [[...left.slice(0, -1), call, ...right.slice(1)], ...rest]; // jazz (fast 2 hh) } else { - // apply function to all left siblings (low precedence) - // s jazz . fast 2 => fast (s jazz) 2 - let leftSide = children.slice(0, pipeIndex); - if (leftSide.length === 1) { - leftSide = leftSide[0]; - } else { - // wrap in (..) if multiple items on the left side - leftSide = { type: 'list', children: leftSide }; - } - children = [right, leftSide, ...rightSide]; + //s jazz hh.fast 2 => (fast 2 (s jazz hh)) + const call = left.length > 1 ? { type: 'list', children: left } : left[0]; + chunks = [[...right, call], ...rest]; } } - return children; + return chunks[0]; } parse_pair(open_type, close_type) { this.consume(open_type); diff --git a/packages/mondo/test/mondo.test.mjs b/packages/mondo/test/mondo.test.mjs index c51844be..342a3f9f 100644 --- a/packages/mondo/test/mondo.test.mjs +++ b/packages/mondo/test/mondo.test.mjs @@ -80,15 +80,15 @@ describe('mondo sugar', () => { it('should desugar mixed [] <>', () => expect(desguar('[a ]')).toEqual('(square a (angle b c))')); it('should desugar mixed <> []', () => expect(desguar('')).toEqual('(angle a (square b c))')); - it('should desugar .', () => expect(desguar('s jazz . fast 2')).toEqual('(fast (s jazz) 2)')); - it('should desugar . square', () => expect(desguar('[bd cp . fast 2]')).toEqual('(fast (square bd cp) 2)')); - it('should desugar . twice', () => expect(desguar('s jazz . fast 2 . slow 2')).toEqual('(slow (fast (s jazz) 2) 2)')); - it('should desugar . nested', () => expect(desguar('(s cp . fast 2)')).toEqual('(fast (s cp) 2)')); - it('should desugar . within []', () => expect(desguar('[bd cp . fast 2]')).toEqual('(fast (square bd cp) 2)')); + it('should desugar .', () => expect(desguar('s jazz . fast 2')).toEqual('(fast 2 (s jazz))')); + it('should desugar . square', () => expect(desguar('[bd cp . fast 2]')).toEqual('(fast 2 (square bd cp))')); + it('should desugar . twice', () => expect(desguar('s jazz . fast 2 . slow 2')).toEqual('(slow 2 (fast 2 (s jazz)))')); + it('should desugar . nested', () => expect(desguar('(s cp . fast 2)')).toEqual('(fast 2 (s cp))')); + it('should desugar . within []', () => expect(desguar('[bd cp . fast 2]')).toEqual('(fast 2 (square bd cp))')); it('should desugar . within , within []', () => - expect(desguar('[bd cp . fast 2, x]')).toEqual('(stack (fast (square bd cp) 2) x)')); + expect(desguar('[bd cp . fast 2, x]')).toEqual('(stack (fast 2 (square bd cp)) x)')); - it('should desugar . ()', () => expect(desguar('[jazz hh.(fast 2)]')).toEqual('(square jazz (fast hh 2))')); + it('should desugar . ()', () => expect(desguar('[jazz hh.(fast 2)]')).toEqual('(square jazz (fast 2 hh))')); it('should desugar , |', () => expect(desguar('[bd, hh | oh]')).toEqual('(stack bd (or hh oh))')); it('should desugar , | of []', () => @@ -102,15 +102,15 @@ describe('mondo sugar', () => { it('should desugar , angle 3', () => expect(desguar('')).toEqual('(stack (angle bd cp) (angle hh oh))')); it('should desugar , ()', () => expect(desguar('(s bd, s cp)')).toEqual('(stack (s bd) (s cp))')); - it('should desugar * /', () => expect(desguar('[a b*2 c d/3 e]')).toEqual('(square a (* b 2) c (/ d 3) e)')); - it('should desugar []*x', () => expect(desguar('[a [b c]*3]')).toEqual('(square a (* (square b c) 3))')); - it('should desugar x:y', () => expect(desguar('x:y')).toEqual('(: x y)')); - it('should desugar x:y:z', () => expect(desguar('x:y:z')).toEqual('(: (: x y) z)')); - it('should desugar x:y*x', () => expect(desguar('bd:0*2')).toEqual('(* (: bd 0) 2)')); - it('should desugar a..b', () => expect(desguar('0..2')).toEqual('(.. 0 2)')); + it('should desugar * /', () => expect(desguar('[a b*2 c d/3 e]')).toEqual('(square a (* 2 b) c (/ 3 d) e)')); + it('should desugar []*x', () => expect(desguar('[a [b c]*3]')).toEqual('(square a (* 3 (square b c)))')); + it('should desugar x:y', () => expect(desguar('x:y')).toEqual('(: y x)')); + it('should desugar x:y:z', () => expect(desguar('x:y:z')).toEqual('(: z (: y x))')); + it('should desugar x:y*x', () => expect(desguar('bd:0*2')).toEqual('(* 2 (: 0 bd))')); + it('should desugar a..b', () => expect(desguar('0..2')).toEqual('(.. 2 0)')); it('should desugar README example', () => expect(desguar('s [bd hh*2 cp.(crush 4) ] . speed .8')).toEqual( - '(speed (s (square bd (* hh 2) (crush cp 4) (angle mt ht lt))) .8)', + '(speed .8 (s (square bd (* 2 hh) (crush 4 cp) (angle mt ht lt))))', )); }); diff --git a/packages/mondough/mondough.mjs b/packages/mondough/mondough.mjs index dcfb1c3c..0db3667c 100644 --- a/packages/mondough/mondough.mjs +++ b/packages/mondough/mondough.mjs @@ -43,11 +43,6 @@ let runner = new MondoRunner({ if (!fn) { throw new Error(`[moundough]: unknown function "${name}"`); } - if (!['square', 'angle', 'stack', 'curly'].includes(name)) { - // flip args (pat to end) - const [pat, ...rest] = args; - args = [...rest, pat]; - } return fn(...args); }, leaf(token, scope) {