Skip to content

Commit

Permalink
Expand technical docs
Browse files Browse the repository at this point in the history
  • Loading branch information
frostburn committed May 13, 2024
1 parent a4adaae commit 3f972af
Showing 1 changed file with 85 additions and 13 deletions.
98 changes: 85 additions & 13 deletions documentation/technical.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# SonicWeave - Technical overview
This documentation describes the SonicWeave DSL as it relates to other programming languages.

## Purpose
SonicWeave is designed for notating microtonal scales as an extension of Scala .scl syntax. Programming is secondary so you'll have to dodge around reserved patterns such as `C4` which look like identifiers but correspond to musical literals.

### Other pitfals
Fraction slash `/` binds stronger than exponentiation. Use `÷` or `%` if you need division that follows [PEMDAS](https://en.wikipedia.org/wiki/Order_of_operations).

The exponent is required in decimal literals. `1.23e0` instead of `1.23` which is instead interpreted a musical interval 1.23 cents wide.

The meaning of `*` changes depending on the operands. Use `~*` to mean musical stacking of relative intervals i.e. mathematic multiplication.

## Type system
Values in SonicWeave fall into these categories

Expand Down Expand Up @@ -35,7 +45,7 @@ All operations are left-associative except exponentiation, recipropower, and log
| `{x, key: value, "third key": value, ...}` | Record display |
| `x[index]`, `x[start..end]`, `x[s,next..end]` | Access, slice |
| `x(arguments...)` | Call |
| `interval color label` | Labeling |
| `interval color label` | Intrinsic call e.g. painting or labeling |
| `++x`, `--x`, `+x`, `^x`, `∧x`, `∨x`, `/x`, `\x` | Increment, decrement, no-op, up, down, lift, drop |
| `/` | Fraction |
| `^`, `^/`, `/^`, `/_` | Exponentiation, recipropower, logdivision* |
Expand All @@ -50,36 +60,98 @@ All operations are left-associative except exponentiation, recipropower, and log
| `not x`, `vnot x` | Boolean not, vector not |
| `and`, `vand` | Boolean and, vector and |
| `or`, `vor`, `al` | Boolean or, vector or, niente coalescing |
| `x if y else z` | Ternary conditional |
| `x if y else z`, `x where y else z` | Ternary conditional, vector ternary conditional |
| `lest` | Fallback[^1] |

Parenthesis, `^`, `×`, `÷`, `+`, `-` follow [PEMDAS](https://en.wikipedia.org/wiki/Order_of_operations). The fraction slash `/` represents vertically aligned fractions similar to `$\frac{3}{2}^\frac{1}{2}$` in LaTeX e.g. `3/2 ^ 1/2` evaluates to `sqrt(3 ÷ 2)`.

[^1]: `lest` is a fully associative operation, thus `a() lest b() lest c()` = `(a() lest b()) lest c()` = `a() lest (b() lest c())`. This means that one can always treat a sequence `a() lest b() lest ... lest c()` as if the evaluations occurred from left to right. Any possible parenthesis may be ignored in such a sequence.

## Control flow

### For..of
The contents of arrays and records can be iterated over using
```c
for (const element of container) {
/* body of the loop utilizing element */
}
```

### For..in
The indices of arrays or keys of records can be iterated over using
```c
for (const element in container) {
/* body of the loop utilizing element */
}
```

### While
The body of a while loop is executed until the condition becomes falsy.
```c
let i = 10;
while (--i)
i;
// Result is numbers from 9 to 1 pushed onto the implicit array $.
```

### Break, continue
Loops terminate on `break` and continue with the next iteration on `continue`.

### For/while...else
The `else` branch of a for or while loop is executed unless a `break` statement was encountered.

## Functions
Functions are constructed using either the `riff` keyword or the `fn` alias. The return value is indicated using the `return` keyword. If the end of the function body is encountered the return value is the array of intervals pushed onto the current scale i.e. `return $`.

## Exceptions
Exceptions (strings) are raised using `throw` and handled inside `try..catch` blocks or inline using `x() lest y()`.

## Conditional execution
Use chained `if..else`. There is no `elif`.

## Deferred execution
To defer execution to the end of the current block prefix the statement with `defer`. Multiple statements with `defer` inside a single block are executed in reverse order.

## Interval subtypes

TODO: List all interval subtypes
| Type | Examples | Domain | Echelon | Notes |
| ------------ | ----------------------- | ------------- | --------- | ----- |
| Integer | `2`, `5` | Linear | Relative | Same as `2/1` or `5/1`. |
| Decimal | `1.2e`, `14e-1` | Linear | Relative | Decimal commas (`1,2`) only work on isolated lines. |
| Fraction | `4/3`, `10/7` | Linear | Relative | The fraction slash binds stronger than exponentiation |
| N-of-EDO | `1\5`, `7\12` | Logarithmic | Relative | `n\m` means `n` steps of `m` equal divisions of the octave `2/1`. |
| N-of-EDJI | `9\13<3>`, `2\5<3/2>` | Logarithmic | Relative | `n\m<p/q>` means `n` steps of `m` equal divisions of the ratio `p/q`. |
| Step | `` | Logarithmic | Relative | Correspond to edo-steps when tempering is applied. |
| Cents | `701.955`, `100c` | Logarithmic | Relative | One centisemitone `1.0` is equal to `1\1200`. |
| Monzo | `[-4 4 -1>`, `[1,-1/2>` | Logarithmic | Relative | Also known as prime count vectors. Each component is an exponent of a prime number factor. |
| FJS | `P5`, `M3^5` | Logarithmic | Relative | [Functional Just System](https://en.xen.wiki/w/Functional_Just_System) |
| TAMNAMS | `P0ms`, `m4ms` | Logarithmic | Relative | Requires a `MOS` declaration. |
| Frequency | `440 Hz`, `2.2 kHz` | Linear | Absolute | Absolute frequency of oscillation. |
| Duration | `1 ms` | Linear | Absolute | Absolute period of oscillation. |
| Absolute FJS | `C4`, `Eb_5` | Logarithmic | Absolute* | Absolute version of [FJS](https://en.xen.wiki/w/Functional_Just_System). |
| Diamond-mos | `J&4`, `M@3` | Logarithmic | Absolute* | Absolute counterpart to TAMNAMS. Requires `MOS` declaration. |
| S-expression | `S8`, `S5..8` | Logarithmic | Relative | Additive spelling of [square superparticulars](https://en.xen.wiki/w/Square_superparticular). |
| Val | `<12, 19, 28]` | Cologarithmic | Relative | Used to temper scales. |
| Warts | `17c@`, `[email protected]/5` | Cologarithmic | Relative | [Shorthand](https://en.xen.wiki/w/Val#Shorthand_notation) for vals. |
| SOV | `17[^5]@` | Cologarithmic | Relative | [Shorthand](https://en.xen.wiki/w/Val#Sparse_Offset_Val_notationn) for vals. |
| Jorp | `` | Cologarithmic | Relative | `<1200]` |
| Pilcrowspoob | `` | Cologarithmic | Absolute | `withEquave(<1]@Hz, 1 Hz)` |

## Domains

TODO: List domains of literals and domains of operations
Linear domain values add as in mathematics. Logarithmic domain values add by multiplying the underlying values. Modulo (`mod`) can be implemented using repeated subtraction so it turns into repeated division in the logarithmic domain. This applies to most other operators that can be reduced to addition and negation.

The cologarithmic domain has the semantics of the co-domain of the logarithmic as a vector space where the exponents of prime numbers form the basis.

## Echelons

TODO: List echelons of literals and echelons of operations.
Anything that can be normalized to a frequency by inverting and negating its time exponent is in the absolute echelon the exponent of the Hertz unit works as a weighting factor in addition. Scalars with a zero time exponent are in the relative echelon with no hidden weights or projection.

## Ranges of values

TODO: Explain the limits of radical values and reals.

## Control flow

TODO: For and while loops

## TODO
The number of prime components is set by calling `numComponents(n)`. Any value with a lower nth prime limit will then support exact square roots and other radicals. The maximum exponent of a prime number is `9007199254740991` and the same `2^53 - 1` limit applies to the denominator of the exponent. The multiplicative higher prime residue has the same range but the `Number.MAX_SAFE_INTEGER` limit applies directly to the numerator and denominator of the residual and no square root of a higher prime is representable as a radical.

TODO: Other technical notes
Real values are double precision floating point numbers.

## Next steps

Expand Down

0 comments on commit 3f972af

Please sign in to comment.