mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-13 14:26:58 -04:00
mondo: flip pipe order: now pining to the end of the function...
This commit is contained in:
+20
-47
@@ -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);
|
||||
|
||||
@@ -80,15 +80,15 @@ describe('mondo sugar', () => {
|
||||
it('should desugar mixed [] <>', () => expect(desguar('[a <b c>]')).toEqual('(square a (angle b c))'));
|
||||
it('should desugar mixed <> []', () => expect(desguar('<a [b c]>')).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('<bd cp, hh oh>')).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) <mt ht lt>] . 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))))',
|
||||
));
|
||||
});
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user