Skip to content

Commit

Permalink
Tweak stdlib semantics to remove past tense verbs
Browse files Browse the repository at this point in the history
Favor creating copies.
Favor popping the pre-existing scale.

ref #256
  • Loading branch information
frostburn committed Jun 2, 2024
1 parent 94878d1 commit 47b4ee8
Show file tree
Hide file tree
Showing 10 changed files with 336 additions and 595 deletions.
218 changes: 70 additions & 148 deletions documentation/BUILTIN.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/parser/__tests__/expression.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ describe('SonicWeave expression evaluator', () => {
});

it('has array comprehensions', () => {
const pyth12 = evaluate('map(str, sorted([3^i rdc 2 for i of [-4..7]]))');
const pyth12 = evaluate('map(str, sort([3^i rdc 2 for i of [-4..7]]))');
expect(pyth12).toEqual([
'2187/2048',
'9/8',
Expand Down Expand Up @@ -1742,7 +1742,7 @@ describe('SonicWeave expression evaluator', () => {
});

it('can sort an array of strings', () => {
const swac = evaluate('sorted([..."SonicWeave"])') as string[];
const swac = evaluate('sort([..."SonicWeave"])') as string[];
expect(swac.join('')).toBe('SWaceeinov');
});

Expand Down
30 changes: 26 additions & 4 deletions src/parser/__tests__/source.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ describe('SonicWeave parser', () => {
const scale = parseSource(`
const segment = [1..5];
segment;
reverse(segment);
reverseInPlace(segment);
map(i => i + 10, segment);
`);
expect(scale).toHaveLength(10);
Expand Down Expand Up @@ -1313,9 +1313,9 @@ describe('SonicWeave parser', () => {
const scale = expand(`{
riff popSort(i) {
if (isArray(i)) {
return sorted(popAll(i));
return sort(popAll(i));
}
return sorted(popAll($$));
return sort(popAll($$));
}
5:8:7:9:6:10;
Expand Down Expand Up @@ -1850,7 +1850,7 @@ describe('SonicWeave parser', () => {
5/4
3/2
2/1
sorted(%£ rdc pop$[-1])
sort(%£ rdc pop$[-1])
`);
expect(scale).toEqual(['4/3', '8/5', '2']);
});
Expand Down Expand Up @@ -1881,4 +1881,26 @@ describe('SonicWeave parser', () => {
'12\\12',
]);
});

it('can label intervals after generating', () => {
const scale = parseSource(`
4/3
3/2
2
£ ["fourth", "fifth", "octave"]
`);
expect(scale).toHaveLength(3);
expect(scale[0].label).toBe('fourth');
expect(scale[1].label).toBe('fifth');
expect(scale[2].label).toBe('octave');
});

it('can paint the whole scale', () => {
const scale = expand('3::6;white;£ "bob"');
expect(scale).toEqual([
'4/3 "bob" white',
'5/3 "bob" white',
'6/3 "bob" white',
]);
});
});
46 changes: 12 additions & 34 deletions src/parser/__tests__/stdlib.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,19 +400,19 @@ describe('SonicWeave standard library', () => {
});

it('can spell the just major chord sub-overtonally', () => {
const subOvertone = parseSource('revposed(6:5:4)');
const subOvertone = parseSource('revpose(6:5:4)');
expect(subOvertone[0].totalCents()).toBeCloseTo(386.313714); // major third
expect(subOvertone[1].totalCents()).toBeCloseTo(701.955001); // perfect fifth
});

it('can spell the just major chord retroverted', () => {
const retroversion = parseSource('retroverted(10:12:15)');
const retroversion = parseSource('retrovert(10:12:15)');
expect(retroversion[0].totalCents()).toBeCloseTo(386.313714); // major third
expect(retroversion[1].totalCents()).toBeCloseTo(701.955001); // perfect fifth
});

it('can spell the just major chord reflected', () => {
const reflection = parseSource('reflected(15:12:10)');
const reflection = parseSource('reflect(15:12:10)');
expect(reflection[0].totalCents()).toBeCloseTo(386.313714); // major third
expect(reflection[1].totalCents()).toBeCloseTo(701.955001); // perfect fifth
});
Expand All @@ -438,13 +438,13 @@ describe('SonicWeave standard library', () => {
});

it('can spell the just minor chord in first inversion with root on 1/1', () => {
const firstInversion = parseSource('reflected(3:5:4)');
const firstInversion = parseSource('reflect(3:5:4)');
expect(firstInversion[0].totalCents()).toBeCloseTo(-884.358713); // major sixth
expect(firstInversion[1].totalCents()).toBeCloseTo(-498.044999); // perfect fourth
});

it('can spell the just minor chord in second inversion with root on 1/1', () => {
const secondInversion = parseSource('reflected(6:5:8)');
const secondInversion = parseSource('reflect(6:5:8)');
expect(secondInversion[0].totalCents()).toBeCloseTo(315.641287); // major sixth
expect(secondInversion[1].totalCents()).toBeCloseTo(-498.044999); // perfect fourth
});
Expand Down Expand Up @@ -498,25 +498,12 @@ describe('SonicWeave standard library', () => {
});

it('has a copying repeater', () => {
const bigScale = expand('repeated(2, 3::6)');
const bigScale = expand('repeat(2, 3::6)');
// XXX: Would be cool if that last 4/1 was 12/3, but can't come up
// with formatting rules that wouldn't mess up everything else.
expect(bigScale).toEqual(['4/3', '5/3', '6/3', '8/3', '10/3', '4/1']);
});

it('can label intervals after generating', () => {
const scale = parseSource(`
4/3
3/2
2
label(["fourth", "fifth", "octave"])
`);
expect(scale).toHaveLength(3);
expect(scale[0].label).toBe('fourth');
expect(scale[1].label).toBe('fifth');
expect(scale[2].label).toBe('octave');
});

it('preserves color upon reflection', () => {
const scale = parseSource('4/3 green;3/2;2/1 red;reflect()');
expect(scale).toHaveLength(3);
Expand Down Expand Up @@ -757,8 +744,8 @@ describe('SonicWeave standard library', () => {
const ls = labelsOf()
clear()
3::6
label(cs)
label(ls)
£ cs
£ ls
}`);
expect(scale).toEqual(['4/3 "one" red', '5/3 "two"', '6/3']);
});
Expand Down Expand Up @@ -808,8 +795,8 @@ describe('SonicWeave standard library', () => {

it('has inline labeling', () => {
const pythagoras = expand(`
labeled(['F', 'C', 'G', 'D', 'A', 'E', 'B'], [3^i rdc 2 white for i of [-2..4]])
labeled(['Gb', 'Db', 'Ab', 'Eb', 'Bb'], [3^i rdc 2 black for i of [-7..-3]])
['F', 'C', 'G', 'D', 'A', 'E', 'B'] [3^i rdc 2 white for i of [-2..4]]
['Gb', 'Db', 'Ab', 'Eb', 'Bb'] [3^i rdc 2 black for i of [-7..-3]]
sort()
`);
expect(pythagoras).toEqual([
Expand Down Expand Up @@ -920,15 +907,6 @@ describe('SonicWeave standard library', () => {
]);
});

it('can paint the whole scale', () => {
const scale = expand('3::6;white;label("bob")');
expect(scale).toEqual([
'4/3 "bob" white',
'5/3 "bob" white',
'6/3 "bob" white',
]);
});

it('can detect domains (linear)', () => {
const scale = expand(
'10/8;12/10;7/6;stack();i => simplify(i) if isLinear(i) else i'
Expand Down Expand Up @@ -1008,12 +986,12 @@ describe('SonicWeave standard library', () => {
});

it('is stacked', () => {
const scale = expand('stacked([5/4, 6/5])');
const scale = expand('stack([5/4, 6/5])');
expect(scale).toEqual(['5/4', '3/2']);
});

it("isn't that stacked actually", () => {
const scale = expand('unstacked([5/4, 3/2])');
const scale = expand('unstack([5/4, 3/2])');
expect(scale).toEqual(['5/4', '6/5']);
});

Expand Down
9 changes: 9 additions & 0 deletions src/parser/expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,15 @@ export class ExpressionVisitor {
return empty;
}

if (
node.start === null &&
node.second === null &&
node.penultimate === false &&
node.end === null
) {
return typeof object === 'string' ? object : ([...object] as Interval[]);
}

let start = 0;
let step = 1;
const pu = node.penultimate;
Expand Down
4 changes: 2 additions & 2 deletions src/parser/statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
repr,
upcastBool,
SonicWeavePrimitive,
sort,
sortInPlace,
temper,
absolute,
} from '../stdlib';
Expand Down Expand Up @@ -866,7 +866,7 @@ export class StatementVisitor {
}
const tail = scale.slice(-entries.length);
scale.length = scale.length - tail.length;
sort.bind(subVisitor)(tail);
sortInPlace.bind(subVisitor)(tail);
scale.push(...tail);
} else {
this.spendGas(scale.length);
Expand Down
Loading

0 comments on commit 47b4ee8

Please sign in to comment.