Skip to content

Commit

Permalink
Make topic a lowdash
Browse files Browse the repository at this point in the history
  • Loading branch information
dy committed Jun 24, 2024
1 parent 03db6bd commit f5b1653
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 46 deletions.
30 changes: 12 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ x[i] x[] \\ member access, length
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ variables
foo=1, bar=2.0; \\ declare vars
AbCF, $0, Δx, _; \\ names permit alnum, unicodes, _$
AbCF, $0, Δx, _; \\ names permit alnum, unicodes, _$#@
fooBar123 != FooBar123; \\ case-sensitive
default=1, eval=fn, else=0; \\ freedom of speech
true = 0b1, false = 0b0; \\ alias bools
Expand Down Expand Up @@ -104,12 +104,12 @@ i = 10.. |> ( \\ descend over range
i < 5 ? ^; \\ if item < 5 continue
i < 0 ? ^^; \\ if item < 0 break
); \\
x[..] |> f(%) |> g(%); \\ sequence of ops
x[..] |> % * 2 |> y[..]; \\ write to destination
x[..] |> f(_) |> g(_); \\ sequence of ops
x[..] |> _ * 2 |> y[..]; \\ write to destination
i = 0..w |> ( \\ nest iterations
j = 0..h |> f(i, j); \\ f(x,y)
); \\
(x,,y) = (a,b,c |> % * 2); \\ x = a * 2, y = c * 2;
(x,,y) = (a,b,c |> _ * 2); \\ x = a * 2, y = c * 2;
.. |> i < 10 ? i++ : ^; \\ while i < 10 i++
..(i < 10) / 0 |> i++; \\ alternative while
Expand Down Expand Up @@ -176,7 +176,7 @@ gain( \\ define a function with block, volume argume
volume ~ 0..100 \\ volume is limited to 0..100 range
) = (
block[..]
|> % * volume \\ multiply each sample by volume value
|> _ * volume \\ multiply each sample by volume value
|> block[..]
);
Expand Down Expand Up @@ -284,16 +284,14 @@ coin(freq=1675, jump=freq/2, delay=0.06, shape=0) = (
t = i / 1s;
\\ generate samples block, apply adsr/curve, write result to out
out[..] = (
i = out[..]
|> oscillator[shape](phase)
|> adsr(i, 0, 0, .06, .24)
|> curve(i, 1.82)
);
.. |> oscillator[shape](phase)
|> adsr(_, 0, 0, .06, .24)
|> curve(_, 1.82)
|> out[..];
i++;
phase += (freq + (t > delay && jump)) * 2pi / 1s;
).
)
```

</details>
Expand Down Expand Up @@ -451,13 +449,9 @@ const arrValues = new Float64Array(memory, arr.value, 3)

## Motivation

_Melo_ is personal take on what would well designed language look like.
It has narrow focus - audio processing & DSP, mainly to give advantage over JS / Web Audio in terms of performance & memory.

_Web Audio_ is unreliable - it has unpredictable pauses, glitches and so on, so <q>audio is better handled in WASM worklet</q> ([@stagas](https://github.com/stagas)). Besides, audio processing in general has no cross-platform solution, various environments deal with audio differently, some don't have audio processing at all. Good old audio code gets dated, in 20 years most of the soft is unable to run.
_Web Audio_ is unreliable - it has unpredictable pauses, glitches and so on, so <q>audio is better handled in WASM worklet</q> ([@stagas](https://github.com/stagas)). Besides, audio processing in general has no cross-platform solution, various environments deal with audio differently, some don't have audio processing at all.

So _melo_ attempts to fill that gap, trying to provide a standard layer.
WASM enables it for browsers, [audio/worklets](https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process), web-workers, nodejs, [embedded systems](https://github.com/bytecodealliance/wasm-micro-runtime) and any other envs. In the future it aims at GL and JS as compile targets.
_Melo_ attempts to fill that gap, providing a common layer for audio processing. It is personal attempt in language design - with foundation from C, JS, Python, Rust, Scala and bits of inspiration from indie langs. WASM enables it for browsers, [audio/worklets](https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process), web-workers, nodejs, [embedded systems](https://github.com/bytecodealliance/wasm-micro-runtime) and any other envs.

<!--
### Principles
Expand Down
38 changes: 21 additions & 17 deletions docs/r&d.md
Original file line number Diff line number Diff line change
Expand Up @@ -1105,7 +1105,7 @@
+ that solves problem of instancing
+ identified by callstack

## [ ] Stateful variable syntax → `*` seems to match "save value" pointers intuition
## [ ] Stateful vars syntax → `*` seems to match "save value" pointers intuition

* There's disagreement on `...` is best candidate for loading prev state. Let's consider alternatives.
1. `...x1,y1,x2,y2`
Expand Down Expand Up @@ -1298,7 +1298,7 @@
- requires strings to implement dynamic access `x['first']`
- some arrays have aliases, others don't: we're not going to make aliases dynamic

## [ ] If `a ? b`, elvis: `a ?: b`? -> why not?
## [x] If `a ? b`, elvis: `a ?: b`? -> why not?
+ organic extension of ternary `a ? b`, `a ?: b`.
- weirdly confusing, as if very important part is lost. Maybe just introduce elvis `a>b ? a=1``a<=b ?: a=1`
- it has no definite returning type. What's the result of `(a ? b)`?
Expand All @@ -1319,12 +1319,6 @@

! ALT: can be done via early return as `(a ? b.; )`

## [ ] mix, smoothstep operators: `~*` for mix

* `x -< a..b` defines clamping?
* `a..b -> x` looks like function, but is possible
* can be done via external lib

## [x] Loops: ~~`i <- 0..10 <| a + i`, `i <- list <| a`, `[x <- 1,2,3 <| x*2]`~~ ~~`0..10 | i -> a + i`~~ ~~`list |> # * 2;`~~

* `for i in 0..10 (a,b,c)`, `for i in src a;`
Expand Down Expand Up @@ -1737,6 +1731,7 @@
* Such comments would make sense if: code was case-sensitive; it had standard allowed chars (no #@); code had if|else|while|for|return|in keywords.
- code is case-sensitive now
+ gives fresh feeling of old standard, since syntax is updated to be cool
+ and still it's like scala also

3. `\` or `\\`
+ mono lang reference
Expand Down Expand Up @@ -4132,31 +4127,34 @@
? ALT: `<( x>2?!; )>`
### [x] What's the best character for placeholder? -> within `_#$%^@&` `#` feels the best
### [ ] What's the best character for topic placeholder? -> within `_#$%^@&` ~~`#` feels the best~~ `_` means "insert here"
* `list |> #*2`, `list |> #>2?^^#:^#;`
+ `#` is almost perfect for topic/reference, associates with `#`th item
- pipe is not loop, it's "previous expressino output insert here"
- has more meaning as "number of" rather than i-th number
~+ current item number as well
+ has typographival meaning as placeholder, or "insertion field"
+ has typographical meaning as placeholder, or "insertion field"
- less of "insert here" more of template
- needs prohibiting variables starting from # though
- which is problematic for mono buffers `#tri = [..1s] <|= tri(# * 2)`
~+ no, doesn't need, why?
-~ interferes with `<math#a,b,c>`
~ these imports are unwieldy tbh, too much legacy mixup: JSX, C++, types, URLs.
+ no "select-all" problem as acute as with `_`
* `list |> &*2`, `list |> &>2?^^&:^&;`
* ~~`list |> &*2`, `list |> &>2?^^&:^&;`~~
+ & is almost-character, feels more like an id
- has weird connotation as binary
- makes `list |> ^^&&&` a valid construct, ugh
- there's too much meaning for `&` character as `&`, `&&` already
* `list |> @ * 2`, `list |> @>2?^^@:^@`
+ relatively safe
+ associates with id / character quite a bit
+ is not overused by other meanings, except for import
+ allows reserved name, no var name `#` shadowing
+ associates with id / character
+ not reserved by other meanings
-~ import
+ allows reserved name, no var name like `#` shadowing
+ `items |> filter(@)` looks softer than `items |> filter(#)`
~- unusual convention (no such precedence)
~- unusual convention (no such precedents)
- conflicts/associates with import (import can be `<>`, but still)
- makefile denotes `$@` as target file (exports?), and `$^` as current file
+ matches `au-` from language name, also looks like aura around a
Expand All @@ -4168,18 +4166,22 @@
* `list |> _ * 2`, `list |> _>2?^^_:^_`
+ less mystery than with `@`
+ more conventional (Elixir, Julia, Scala, Perl, PowerShell)
+ not an operator
+ literally means "insert here" like in written forms for fields
- not as distinguished from code, as `^@#&`
- select-all problem, esp. since default separator in vars is `_`, like `sin_w`
~ not necessary, since we are likely case-sensitive
- has tinge of "throwaway variable"
~+ we don't need throwaways, since we support skipped args `(,,)`
- has tinge of "private variable"
~ we don't have privates
+ literally means "placeholder", for "placeholder" variable
+ we don't have special designation for lowdash otherwise
* `list |> ^ * 2`
- conflicts with `^` for return `list |> ^>2?^^^:^^;`
+ compatible with js proposal; compatible with makefile;
* `list |> ~ * 2`
* `list |> () * 2`
* ~~`list |> ~ * 2`~~
* ~~`list |> () * 2`~~
* `list |> . * 2`
- conflicts with export
- field is taken by `..`, `.` as export, `x.2` as prop, `.2` as float
Expand Down Expand Up @@ -4646,6 +4648,7 @@
* `x ~/ a..b`
+ allows `x -/ a..b` for lerp
* `x ~< a..b`
* `x ~~/ a..b` for smoothstep
* `a..b -> x`
- looks like function
* can be done via external lib
Expand All @@ -4658,6 +4661,7 @@
* `x <= a..b`
- can be used to compare ranges
## [x] how do we represent infinity? -> `1/0`, `0/0`
* `oo`
Expand Down
4 changes: 2 additions & 2 deletions src/compile.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// compile source/ast to WAST
import { FLOAT, INT } from './const.js';
import parse, { TOPIC } from './parse.js';
import parse from './parse.js';
import stdlib from './stdlib.js';
import precompile from './precompile.js';
import { ids, stringify, err, u82s } from './util.js';
Expand Down Expand Up @@ -439,7 +439,7 @@ Object.assign(expr, {
depth++
// i = from; to; while (i < to) {% = i; ...; i++}
const [, min, max] = a
const cur = define(TOPIC, 'f64'),
const cur = define('_', 'f64'),
idx = define(`idx:${depth}`, 'f64'),
end = define(`end:${depth}`, 'f64'),
body = expr(b), type = body.type.join(' ')
Expand Down
5 changes: 0 additions & 5 deletions src/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ const PREC_SEMI = 1, // a; b;
PREC_CALL = 27, // a(b), a.b, a[b], a[]
PREC_TOKEN = 28 // [a,b] etc

export const TOPIC = '%'

// make id support #@
const isId = parse.id = char => id(char) || char === HASH

Expand Down Expand Up @@ -187,9 +185,6 @@ token('^', PREC_TOKEN, (a, b) => !a && (b = expr(PREC_RETURN), b ? ['^', b] : ['
token('^^', PREC_TOKEN, (a, b) => (!a && (b = expr(PREC_RETURN), b ? ['^^', b] : ['^^']))) // break: ../
token('^^^', PREC_TOKEN, (a, b) => !a && (b = expr(PREC_RETURN), b ? ['^^^', b] : ['^^^'])) // return: ../

// % - topic holder
token(TOPIC, PREC_TOKEN, (a) => !a && TOPIC)

// a.b
// NOTE: we don't parse expression to avoid 0..1 recognizing as 0[.1]
// NOTE: for now we disable prop access since we don't have aliases and just static index can be done via x[0]
Expand Down
8 changes: 4 additions & 4 deletions test/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ t.todo('compile: break/continue', t => {

t('compile: loops range global', t => {
let wat, mod
wat = compileMelo(`x=[1..3]; 0..2 |> x[%]=%+1; x`)
wat = compileMelo(`x=[1..3]; 0..2 |> x[_]=_+1; x`)
mod = compileWat(wat)
let { __memory: memory, x } = mod.instance.exports

Expand All @@ -651,7 +651,7 @@ t('compile: loops range global', t => {

t('compile: loops range local', t => {
let wat, mod
wat = compileMelo(`x=[1..3]; fill() = (0..x[] |> x[%]=%+1); fill, x`)
wat = compileMelo(`x=[1..3]; fill() = (0..x[] |> x[_]=_+1); fill, x`)
mod = compileWat(wat)
let { __memory: memory, x, fill } = mod.instance.exports

Expand All @@ -665,8 +665,8 @@ t('compile: loops range local', t => {

t('compile: loop range in range', t => {
let wat = compileMelo(`a=[..9], f(a,w,h)=(
0..w |> (x=%;
0..h |> (y=%;
0..w |> (x=_;
0..h |> (y=_;
a[y*w + x] = x+y*w
)
)
Expand Down

0 comments on commit f5b1653

Please sign in to comment.