Skip to content

Commit

Permalink
Fix rest assignment
Browse files Browse the repository at this point in the history
Document variables and cross-domain multiplication.
  • Loading branch information
frostburn committed Apr 25, 2024
1 parent 8b12cc0 commit 833827b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 2 deletions.
101 changes: 101 additions & 0 deletions documentation/intermediate-dsl.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,104 @@ Upon encountering a *val* like `12@` the current scale is converted with no effe
Results in `$ = [5\12, 7\12, 15/8, 2/1]`, so only the first two intervals were converted to 12-tone equal temperament.

To learn more see [tempering.md](https://github.com/xenharmonic-devs/sonic-weave/blob/main/documentation/tempering.md) for details.

### Record unrolling
When a record is encountered its values are sorted by size and the keys are used for labels.

```c
4/3
{
fif: 3/2,
octave: 2,
"my third": 5/4,
}
```
Results in `$ = [4/3, 5/4 "my third", 3/2 "fif", 2 "octave"]`. Notice how 4/3 was left untouched even though 5/4 is smaller in size.

### Boolean conversion
`true` is converted to `1` and `false` to `0` before pushing them onto the current scale.

## Variables
Variables in SonicWeave can hold any type of value. They must be declared before use. Variables declared `const` cannot be re-assigned while `let` variables may change what value they refer to.

```c
const myComma = 81/80
myComma = 250/243 // WRONG! Throws an error.
```

```c
let myComma = 81/80
myComma = 250/243 // Valid: myComma now has the value 250/243
```

Constancy is skin-deep. The elements of a `const` array may be re-assigned at will.

```c
const myCommas = [81/80, 128/125];
myCommas[1] = 250/243 // Valid: myCommas now contains [81/80, 250/243]
```

Un-initialized `let` variables default to `niente`.

### Destructuring
Variables may be declared from an array.

```c
const [x, y] = [1, 2]
y
x
```
Results in `$ = [2, 1]`.

Variables may be re-assigned from an array.
```c
let x, y
[x, y] = [1, 2]
y
x
```
Results in `$ = [2, 1]`.

### Rest parameter

Rest declaration:
```c
const [x, ...r] = [1, 2, 3, 4]
// x has value 1
// r has value [2, 3, 4]
```

Rest assignment:
```c
let x, r
[x, ...r] = [1, 2, 3, 4]
// x has value 1
// r has value [2, 3, 4]
```

## Type system
Values in SonicWeave fall into these categories

| Type | Example | Notes |
| -------- | ------------------------ | -------------------------------------------------------------------- |
| None | `niente` | _Niente_ is used in music notation and means _nothing_ in Italian. |
| String | `'hello'` | Both single and double quoted strings are supported. Used for note labels. |
| Color | `#ff00ff` | CSS colors, short hexadecimal, and long hexadecimal colors supported. Used for note colors. |
| Boolean | `true` or `false` | Converted to `1` or `0` inside scales. |
| Interval | `7/5` | There are many kinds of intervals with their own operator semantics. |
| Val | `12@` | Used to convert scales in just intonation to equal temperaments. |
| Array | `[5/4, P5, 9\9]` | Musical scales are represented using arrays of intervals. |
| Record | `{fif: 3/2, "p/e": 2}` | Associative data indexed by strings. |
| Function | `riff plusOne(x) {x+1}` | _Riff_ is a music term for a short repeated phrase. |

## Interval domains

As explained in [basic DSL](https://github.com/xenharmonic-devs/sonic-weave/blob/main/documentation/dsl.md#domains) documentation. We need two distinct domains if we wish to capture the informal notion where `1 + 1/8` is `9/8` but also where `500. + 500.` is `1000.`.

Especially scalar multiplication and division can be hard to wrap your head around. An expression like `3 * x` is always equal to `x + x + x` no matter the domain of `x`. Similarly `const y = x / 3` results in an `y` such that `y + y + y` is equal to `x`.

This means that multiplication between linear and logarithmic quantities is the same as raising the underlying value of the logarithmic quantity to the underlying value of the linear quantity. Under the hood `P4 * 3` is actually doing `FJS( (4/3) ^ 3 )`.

Similarly a logarithmic quantity divided by a linear quantity is equivalent to taking an nth root. `P5 / 2` is doing `FJS( (3/2) ^ (1/2) )` or taking advantage of the exotic *recipropower* operator and operator precedence of fractions in SonicWeave `FJS( 3/2 /^ 2)`

Division of logarithmic quantities is a true mind-bender: `m7` is `2 * P4` so correspondingly `m7 / P4` evaluates to `2`, a linear scalar!
2 changes: 1 addition & 1 deletion documentation/technical.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Array and record types are recursive i.e. arrays may contain other arrays or rec

SonicWeave does not have classes and there's no `value.property` syntax.

The language is weakly typed. Logdivision is particularly leaky: `16 /_ 8` is rational `4/3` but `16 /_ 3` evaluates to a real (floating point) number. However most expressions that can be expressed as a radical (nth root) are exact.
The language is weakly typed and weakly valued. Logdivision is particularly leaky: `16 /_ 8` is rational `4/3` but `16 /_ 3` evaluates to a real (floating point) number. However most expressions that can be expressed as a radical (nth root) are exact.

## Operator precedence

Expand Down
10 changes: 10 additions & 0 deletions src/parser/__tests__/source.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1278,4 +1278,14 @@ describe('SonicWeave parser', () => {
'16/5',
]);
});

it('has rest assignment', () => {
const scale = parseSource(`
let x, r
[x, ...r] = [1, 2, 3, 4]
r
str;
`);
expect(scale).toEqual(['2', '3', '4']);
});
});
2 changes: 1 addition & 1 deletion src/parser/statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ export class StatementVisitor {
this.assign(name.identifiers[i], value[i]);
}
if (name.rest) {
this.assign(name, value.slice(name.identifiers.length));
this.assign(name.rest, value.slice(name.identifiers.length));
}
} else {
const id = name.id;
Expand Down

0 comments on commit 833827b

Please sign in to comment.