@devaloop/devalang 0.0.1-alpha.14 → 0.0.1-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devalang +10 -8
- package/.github/workflows/ci.yml +92 -0
- package/Cargo.toml +60 -58
- package/README.md +32 -15
- package/docs/CHANGELOG.md +93 -1
- package/docs/CONTRIBUTING.md +101 -1
- package/docs/ROADMAP.md +2 -2
- package/docs/TODO.md +1 -1
- package/examples/automation.deva +42 -0
- package/examples/bank.deva +4 -4
- package/examples/events.deva +12 -0
- package/examples/function.deva +4 -4
- package/examples/index.deva +39 -25
- package/examples/loop.deva +5 -11
- package/examples/pattern.deva +8 -0
- package/examples/plugin.deva +16 -0
- package/examples/variables.deva +1 -1
- package/out-tsc/bin/index.js +51 -7
- package/out-tsc/index.js +3 -1
- package/out-tsc/scripts/postbuild.js +9 -10
- package/out-tsc/scripts/postinstall.js +49 -0
- package/package.json +12 -4
- package/project-version.json +3 -3
- package/rust/cli/bank.rs +462 -456
- package/rust/cli/build.rs +252 -199
- package/rust/cli/check.rs +221 -180
- package/rust/cli/driver.rs +297 -292
- package/rust/cli/generator.rs +1 -0
- package/rust/cli/init.rs +87 -79
- package/rust/cli/install.rs +35 -32
- package/rust/cli/login.rs +127 -134
- package/rust/cli/mod.rs +13 -11
- package/rust/cli/play.rs +1123 -218
- package/rust/cli/telemetry.rs +19 -0
- package/rust/cli/template.rs +69 -57
- package/rust/cli/update.rs +6 -4
- package/rust/common/api.rs +5 -8
- package/rust/common/cdn.rs +3 -6
- package/rust/common/mod.rs +3 -3
- package/rust/common/sso.rs +3 -6
- package/rust/config/driver.rs +118 -94
- package/rust/config/loader.rs +165 -156
- package/rust/config/mod.rs +4 -2
- package/rust/config/settings.rs +91 -0
- package/rust/config/stats.rs +257 -0
- package/rust/core/audio/engine.rs +696 -518
- package/rust/core/audio/evaluator.rs +263 -31
- package/rust/core/audio/interpreter/arrow_call.rs +198 -161
- package/rust/core/audio/interpreter/automate.rs +18 -0
- package/rust/core/audio/interpreter/call.rs +98 -95
- package/rust/core/audio/interpreter/condition.rs +70 -71
- package/rust/core/audio/interpreter/driver.rs +487 -198
- package/rust/core/audio/interpreter/function.rs +26 -21
- package/rust/core/audio/interpreter/let_.rs +38 -19
- package/rust/core/audio/interpreter/load.rs +18 -18
- package/rust/core/audio/interpreter/loop_.rs +113 -73
- package/rust/core/audio/interpreter/mod.rs +14 -13
- package/rust/core/audio/interpreter/sleep.rs +27 -30
- package/rust/core/audio/interpreter/spawn.rs +105 -102
- package/rust/core/audio/interpreter/tempo.rs +19 -16
- package/rust/core/audio/interpreter/trigger.rs +239 -210
- package/rust/core/audio/loader/mod.rs +1 -1
- package/rust/core/audio/loader/trigger.rs +100 -97
- package/rust/core/audio/mod.rs +7 -6
- package/rust/core/audio/player.rs +64 -64
- package/rust/core/audio/renderer.rs +56 -53
- package/rust/core/audio/special/easing.rs +189 -0
- package/rust/core/audio/special/env.rs +43 -0
- package/rust/core/audio/special/math.rs +102 -0
- package/rust/core/audio/special/mod.rs +9 -0
- package/rust/core/audio/special/modulator.rs +143 -0
- package/rust/core/builder/mod.rs +80 -85
- package/rust/core/debugger/lexer.rs +27 -27
- package/rust/core/debugger/mod.rs +24 -23
- package/rust/core/debugger/module.rs +55 -47
- package/rust/core/debugger/preprocessor.rs +27 -27
- package/rust/core/debugger/store.rs +40 -39
- package/rust/core/error/mod.rs +80 -66
- package/rust/core/lexer/handler/arrow.rs +82 -31
- package/rust/core/lexer/handler/at.rs +21 -21
- package/rust/core/lexer/handler/brace.rs +41 -41
- package/rust/core/lexer/handler/colon.rs +21 -21
- package/rust/core/lexer/handler/comment.rs +30 -30
- package/rust/core/lexer/handler/dot.rs +21 -21
- package/rust/core/lexer/handler/driver.rs +337 -263
- package/rust/core/lexer/handler/identifier.rs +46 -42
- package/rust/core/lexer/handler/indent.rs +66 -66
- package/rust/core/lexer/handler/mod.rs +16 -16
- package/rust/core/lexer/handler/newline.rs +23 -23
- package/rust/core/lexer/handler/number.rs +31 -31
- package/rust/core/lexer/handler/operator.rs +46 -44
- package/rust/core/lexer/handler/parenthesis.rs +41 -41
- package/rust/core/lexer/handler/slash.rs +21 -21
- package/rust/core/lexer/handler/string.rs +63 -63
- package/rust/core/lexer/mod.rs +54 -51
- package/rust/core/lexer/token.rs +97 -91
- package/rust/core/mod.rs +11 -11
- package/rust/core/parser/driver.rs +513 -408
- package/rust/core/parser/handler/arrow_call.rs +233 -211
- package/rust/core/parser/handler/at.rs +245 -162
- package/rust/core/parser/handler/bank.rs +94 -69
- package/rust/core/parser/handler/condition.rs +80 -74
- package/rust/core/parser/handler/dot.rs +143 -135
- package/rust/core/parser/handler/identifier/automate.rs +257 -0
- package/rust/core/parser/handler/identifier/call.rs +91 -88
- package/rust/core/parser/handler/identifier/emit.rs +66 -0
- package/rust/core/parser/handler/identifier/function.rs +100 -92
- package/rust/core/parser/handler/identifier/group.rs +85 -75
- package/rust/core/parser/handler/identifier/let_.rs +158 -127
- package/rust/core/parser/handler/identifier/mod.rs +54 -52
- package/rust/core/parser/handler/identifier/on.rs +98 -0
- package/rust/core/parser/handler/identifier/print.rs +52 -0
- package/rust/core/parser/handler/identifier/sleep.rs +36 -33
- package/rust/core/parser/handler/identifier/spawn.rs +91 -88
- package/rust/core/parser/handler/identifier/synth.rs +65 -65
- package/rust/core/parser/handler/loop_.rs +170 -72
- package/rust/core/parser/handler/mod.rs +8 -8
- package/rust/core/parser/handler/tempo.rs +53 -47
- package/rust/core/parser/mod.rs +4 -4
- package/rust/core/parser/statement.rs +142 -108
- package/rust/core/plugin/loader.rs +123 -48
- package/rust/core/plugin/mod.rs +2 -1
- package/rust/core/plugin/runner.rs +296 -0
- package/rust/core/preprocessor/loader.rs +515 -326
- package/rust/core/preprocessor/mod.rs +4 -4
- package/rust/core/preprocessor/module.rs +60 -58
- package/rust/core/preprocessor/processor.rs +99 -101
- package/rust/core/preprocessor/resolver/bank.rs +51 -49
- package/rust/core/preprocessor/resolver/call.rs +100 -100
- package/rust/core/preprocessor/resolver/condition.rs +97 -97
- package/rust/core/preprocessor/resolver/driver.rs +310 -278
- package/rust/core/preprocessor/resolver/function.rs +69 -78
- package/rust/core/preprocessor/resolver/group.rs +96 -91
- package/rust/core/preprocessor/resolver/let_.rs +32 -28
- package/rust/core/preprocessor/resolver/loop_.rs +320 -91
- package/rust/core/preprocessor/resolver/mod.rs +15 -15
- package/rust/core/preprocessor/resolver/spawn.rs +76 -92
- package/rust/core/preprocessor/resolver/synth.rs +56 -50
- package/rust/core/preprocessor/resolver/tempo.rs +50 -49
- package/rust/core/preprocessor/resolver/trigger.rs +113 -116
- package/rust/core/preprocessor/resolver/value.rs +81 -87
- package/rust/core/shared/bank.rs +1 -1
- package/rust/core/shared/duration.rs +9 -9
- package/rust/core/shared/mod.rs +3 -3
- package/rust/core/shared/value.rs +35 -32
- package/rust/core/store/function.rs +34 -34
- package/rust/core/store/global.rs +55 -38
- package/rust/core/store/mod.rs +5 -5
- package/rust/core/store/variable.rs +37 -34
- package/rust/core/utils/mod.rs +2 -2
- package/rust/core/utils/path.rs +37 -31
- package/rust/core/utils/validation.rs +35 -37
- package/rust/installer/addon.rs +84 -80
- package/rust/installer/bank.rs +62 -65
- package/rust/installer/mod.rs +5 -5
- package/rust/installer/plugin.rs +54 -55
- package/rust/installer/utils.rs +56 -56
- package/rust/lib.rs +156 -164
- package/rust/main.rs +250 -145
- package/rust/utils/error.rs +200 -0
- package/rust/utils/file.rs +38 -35
- package/rust/utils/first_usage.rs +76 -0
- package/rust/utils/logger.rs +195 -139
- package/rust/utils/mod.rs +9 -50
- package/rust/utils/signature.rs +19 -17
- package/rust/utils/spinner.rs +22 -19
- package/rust/utils/telemetry.rs +292 -0
- package/rust/utils/watcher.rs +34 -33
- package/templates/minimal/README.md +97 -121
- package/templates/welcome/README.md +97 -121
- package/typescript/bin/index.ts +19 -5
- package/typescript/index.ts +3 -1
- package/typescript/scripts/postbuild.ts +10 -6
- package/typescript/scripts/postinstall.ts +56 -0
- package/typescript/scripts/version/bump.ts +0 -1
- package/typescript/scripts/version/index.ts +0 -1
- package/out-tsc/bin/devalang.exe +0 -0
package/.devalang
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
[defaults]
|
|
2
|
-
entry = "./examples"
|
|
3
|
-
output = "./output"
|
|
4
|
-
watch = false
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
[defaults]
|
|
2
|
+
entry = "./examples"
|
|
3
|
+
output = "./output"
|
|
4
|
+
watch = false
|
|
5
|
+
debug = true
|
|
6
|
+
compress = true
|
|
7
|
+
|
|
8
|
+
[[banks]]
|
|
9
|
+
path = "devalang://bank/devaloop.808"
|
|
10
|
+
version = "0.0.2"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
name: CI & Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
tags:
|
|
8
|
+
- "v*"
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build binaries
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
include:
|
|
18
|
+
- os: ubuntu-latest
|
|
19
|
+
target: x86_64-unknown-linux-gnu
|
|
20
|
+
bin_ext: ""
|
|
21
|
+
- os: macos-latest
|
|
22
|
+
target: x86_64-apple-darwin
|
|
23
|
+
bin_ext: ""
|
|
24
|
+
- os: windows-latest
|
|
25
|
+
target: x86_64-pc-windows-msvc
|
|
26
|
+
bin_ext: ".exe"
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout sources
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
|
|
32
|
+
- name: Install ALSA (Linux)
|
|
33
|
+
if: matrix.os == 'ubuntu-latest'
|
|
34
|
+
run: |
|
|
35
|
+
sudo apt-get update
|
|
36
|
+
sudo apt-get install -y libasound2-dev pkg-config
|
|
37
|
+
|
|
38
|
+
- name: Install Node.js
|
|
39
|
+
uses: actions/setup-node@v4
|
|
40
|
+
with:
|
|
41
|
+
node-version: 20
|
|
42
|
+
|
|
43
|
+
- name: Install Rust
|
|
44
|
+
uses: actions-rs/toolchain@v1
|
|
45
|
+
with:
|
|
46
|
+
toolchain: stable
|
|
47
|
+
override: true
|
|
48
|
+
target: ${{ matrix.target }}
|
|
49
|
+
|
|
50
|
+
- name: NPM Install
|
|
51
|
+
run: npm install
|
|
52
|
+
|
|
53
|
+
- name: Build TS
|
|
54
|
+
run: npx tsc
|
|
55
|
+
|
|
56
|
+
- name: Build release
|
|
57
|
+
run: cargo build --release --target ${{ matrix.target }}
|
|
58
|
+
|
|
59
|
+
- name: Ensure out-tsc/bin exists (Unix)
|
|
60
|
+
if: runner.os != 'Windows'
|
|
61
|
+
run: mkdir -p out-tsc/bin
|
|
62
|
+
|
|
63
|
+
- name: Ensure out-tsc/bin exists (Windows)
|
|
64
|
+
if: runner.os == 'Windows'
|
|
65
|
+
shell: pwsh
|
|
66
|
+
run: |
|
|
67
|
+
New-Item -ItemType Directory -Force out-tsc/bin | Out-Null
|
|
68
|
+
|
|
69
|
+
- name: Copy binary (Unix)
|
|
70
|
+
if: runner.os != 'Windows'
|
|
71
|
+
run: cp target/${{ matrix.target }}/release/devalang${{ matrix.bin_ext }} out-tsc/bin/devalang-${{ matrix.target }}${{ matrix.bin_ext }}
|
|
72
|
+
|
|
73
|
+
- name: Copy binary (Windows)
|
|
74
|
+
if: runner.os == 'Windows'
|
|
75
|
+
shell: pwsh
|
|
76
|
+
run: |
|
|
77
|
+
Copy-Item "target\${{ matrix.target }}\release\devalang${{ matrix.bin_ext }}" "out-tsc\bin\devalang-${{ matrix.target }}${{ matrix.bin_ext }}" -Force
|
|
78
|
+
|
|
79
|
+
- name: Upload artifact (CI)
|
|
80
|
+
if: startsWith(github.ref, 'refs/heads/')
|
|
81
|
+
uses: actions/upload-artifact@v4
|
|
82
|
+
with:
|
|
83
|
+
name: devalang-${{ matrix.target }}
|
|
84
|
+
path: out-tsc/bin/*
|
|
85
|
+
|
|
86
|
+
- name: Upload to GitHub Release
|
|
87
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
88
|
+
uses: softprops/action-gh-release@v2
|
|
89
|
+
with:
|
|
90
|
+
files: out-tsc/bin/*
|
|
91
|
+
env:
|
|
92
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/Cargo.toml
CHANGED
|
@@ -1,58 +1,60 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "devalang"
|
|
3
|
-
version = "0.0.1-alpha.
|
|
4
|
-
authors = ["Devaloop <contact@devaloop.com>"]
|
|
5
|
-
description = "Write music like code. Devalang is a domain-specific language (DSL) for sound designers and music hackers. Compose, automate, and control sound — in plain text."
|
|
6
|
-
license = "MIT"
|
|
7
|
-
repository = "https://github.com/devaloop-labs/devalang"
|
|
8
|
-
keywords = ["music", "dsl", "audio", "cli"]
|
|
9
|
-
categories = ["command-line-utilities", "development-tools", "parser-implementations"]
|
|
10
|
-
readme = "README.md"
|
|
11
|
-
homepage = "https://devalang.com"
|
|
12
|
-
documentation = "https://docs.devalang.com/"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
path = "rust/lib.rs"
|
|
23
|
-
crate-type = ["cdylib", "rlib"]
|
|
24
|
-
|
|
25
|
-
[profile.release]
|
|
26
|
-
opt-level = "s"
|
|
27
|
-
|
|
28
|
-
[features]
|
|
29
|
-
default = ["cli"]
|
|
30
|
-
cli = ["crossterm", "indicatif", "inquire", "zip", "reqwest", "flate2", "tokio"]
|
|
31
|
-
|
|
32
|
-
[dependencies]
|
|
33
|
-
clap = { version = "4.5", features = ["derive"] }
|
|
34
|
-
serde = { version = "1.0", features = ["derive"] }
|
|
35
|
-
serde_json = "1.0"
|
|
36
|
-
rodio = "0.17"
|
|
37
|
-
hound = "3.4.0"
|
|
38
|
-
toml = "0.8"
|
|
39
|
-
notify = "6.1"
|
|
40
|
-
fs_extra = "1.3"
|
|
41
|
-
include_dir = "0.7"
|
|
42
|
-
wasm-bindgen = "0.2"
|
|
43
|
-
serde-wasm-bindgen = "0.4"
|
|
44
|
-
nom_locate = "4.0.0"
|
|
45
|
-
chrono = "0.4"
|
|
46
|
-
crossterm = { version = "0.27", optional = true }
|
|
47
|
-
indicatif = { version = "0.17", optional = true }
|
|
48
|
-
inquire = { version = "0.7.5", optional = true }
|
|
49
|
-
js-sys = "0.3"
|
|
50
|
-
reqwest = { version = "0.12.22", optional = true, features = ["json"] }
|
|
51
|
-
flate2 = { version = "1.0", optional = true }
|
|
52
|
-
tokio = { version = "1", features = ["full"], optional = true }
|
|
53
|
-
zip = { version = "4.3.0", optional = true }
|
|
54
|
-
rayon = "1.10.0"
|
|
55
|
-
webbrowser = "0.8"
|
|
56
|
-
tiny_http = "0.9.0"
|
|
57
|
-
dirs = "5"
|
|
58
|
-
urlencoding = "2.1"
|
|
1
|
+
[package]
|
|
2
|
+
name = "devalang"
|
|
3
|
+
version = "0.0.1-alpha.16"
|
|
4
|
+
authors = ["Devaloop <contact@devaloop.com>"]
|
|
5
|
+
description = "Write music like code. Devalang is a domain-specific language (DSL) for sound designers and music hackers. Compose, automate, and control sound — in plain text."
|
|
6
|
+
license = "MIT"
|
|
7
|
+
repository = "https://github.com/devaloop-labs/devalang"
|
|
8
|
+
keywords = ["music", "dsl", "audio", "cli"]
|
|
9
|
+
categories = ["command-line-utilities", "development-tools", "parser-implementations"]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
homepage = "https://devalang.com"
|
|
12
|
+
documentation = "https://docs.devalang.com/"
|
|
13
|
+
edition = "2024"
|
|
14
|
+
|
|
15
|
+
[[bin]]
|
|
16
|
+
name = "devalang"
|
|
17
|
+
path = "rust/main.rs"
|
|
18
|
+
required-features = ["cli"]
|
|
19
|
+
|
|
20
|
+
[lib]
|
|
21
|
+
name = "devalang_core"
|
|
22
|
+
path = "rust/lib.rs"
|
|
23
|
+
crate-type = ["cdylib", "rlib"]
|
|
24
|
+
|
|
25
|
+
[profile.release]
|
|
26
|
+
opt-level = "s"
|
|
27
|
+
|
|
28
|
+
[features]
|
|
29
|
+
default = ["cli"]
|
|
30
|
+
cli = ["crossterm", "indicatif", "inquire", "zip", "reqwest", "flate2", "tokio"]
|
|
31
|
+
|
|
32
|
+
[dependencies]
|
|
33
|
+
clap = { version = "4.5", features = ["derive"] }
|
|
34
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
35
|
+
serde_json = "1.0"
|
|
36
|
+
rodio = "0.17"
|
|
37
|
+
hound = "3.4.0"
|
|
38
|
+
toml = "0.8"
|
|
39
|
+
notify = "6.1"
|
|
40
|
+
fs_extra = "1.3"
|
|
41
|
+
include_dir = "0.7"
|
|
42
|
+
wasm-bindgen = "0.2"
|
|
43
|
+
serde-wasm-bindgen = "0.4"
|
|
44
|
+
nom_locate = "4.0.0"
|
|
45
|
+
chrono = "0.4"
|
|
46
|
+
crossterm = { version = "0.27", optional = true }
|
|
47
|
+
indicatif = { version = "0.17", optional = true }
|
|
48
|
+
inquire = { version = "0.7.5", optional = true }
|
|
49
|
+
js-sys = "0.3"
|
|
50
|
+
reqwest = { version = "0.12.22", optional = true, features = ["json"] }
|
|
51
|
+
flate2 = { version = "1.0", optional = true }
|
|
52
|
+
tokio = { version = "1", features = ["full"], optional = true }
|
|
53
|
+
zip = { version = "4.3.0", optional = true }
|
|
54
|
+
rayon = "1.10.0"
|
|
55
|
+
webbrowser = "0.8"
|
|
56
|
+
tiny_http = "0.9.0"
|
|
57
|
+
dirs = "5"
|
|
58
|
+
urlencoding = "2.1"
|
|
59
|
+
uuid = { version = "1.18.0", features = ["v4"] }
|
|
60
|
+
wasmtime = "19"
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://devalang.com/images/devalang-logo.
|
|
2
|
+
<img src="https://devalang.com/images/devalang-logo-min.png" alt="Devalang Logo" width="100" />
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|

|
|
@@ -65,31 +65,48 @@ Create a new Devalang file `src/index.deva` in the project directory:
|
|
|
65
65
|
```deva
|
|
66
66
|
# src/index.deva
|
|
67
67
|
|
|
68
|
-
group
|
|
69
|
-
let
|
|
68
|
+
group main:
|
|
69
|
+
let lead = synth sine {
|
|
70
70
|
attack: 0,
|
|
71
71
|
decay: 100,
|
|
72
72
|
sustain: 100,
|
|
73
73
|
release: 100
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
# Global automation for this synth (applies to subsequent notes)
|
|
77
|
+
automate lead:
|
|
78
|
+
param volume {
|
|
79
|
+
0% = 0.0
|
|
80
|
+
100% = 1.0
|
|
81
|
+
}
|
|
82
|
+
param pan {
|
|
83
|
+
0% = -1.0
|
|
84
|
+
100% = 1.0
|
|
85
|
+
}
|
|
86
|
+
param pitch {
|
|
87
|
+
0% = -12.0
|
|
88
|
+
100% = 12.0
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
lead -> note(C4, {
|
|
77
92
|
duration: 400,
|
|
78
|
-
velocity: 0.
|
|
79
|
-
|
|
93
|
+
velocity: 0.8,
|
|
94
|
+
automate: { pan: { 0%: -1.0, 100%: 0.0 } }
|
|
80
95
|
})
|
|
81
96
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
lead -> note(E4, { duration: 400 })
|
|
98
|
+
lead -> note(G4, { duration: 600, glide: true, target_freq: 659.25 })
|
|
99
|
+
lead -> note(B3, { duration: 400, slide: true, target_amp: 0.3 })
|
|
100
|
+
|
|
101
|
+
for i in [1, 2, 3]:
|
|
102
|
+
lead -> note(C5, { duration: 200 })
|
|
86
103
|
|
|
87
104
|
# Play the lead
|
|
88
105
|
|
|
89
|
-
call
|
|
106
|
+
call main
|
|
90
107
|
```
|
|
91
108
|
|
|
92
|
-
And the best part ? You can play it directly from the command line:
|
|
109
|
+
### And the best part ? You can play it directly from the command line:
|
|
93
110
|
|
|
94
111
|
```bash
|
|
95
112
|
# Play the Devalang file
|
|
@@ -102,9 +119,9 @@ devalang play --watch
|
|
|
102
119
|
devalang play --repeat
|
|
103
120
|
```
|
|
104
121
|
|
|
105
|
-
### 🎉 You can now hear your Devalang code in action
|
|
122
|
+
### 🎉 You can now hear your Devalang code in action
|
|
106
123
|
|
|
107
|
-
> For more examples, check out the [examples directory](./examples/)
|
|
124
|
+
> For more examples, check out the [examples directory](./examples/)
|
|
108
125
|
|
|
109
126
|
## ❓ Why Devalang ?
|
|
110
127
|
|
|
@@ -128,7 +145,7 @@ devalang play --repeat
|
|
|
128
145
|
|
|
129
146
|
## 📄 Documentation
|
|
130
147
|
|
|
131
|
-
### Please refer to the [online documentation](https://docs.devalang.com) for detailed information on syntax, features, and usage examples
|
|
148
|
+
### Please refer to the [online documentation](https://docs.devalang.com) for detailed information on syntax, features, and usage examples
|
|
132
149
|
|
|
133
150
|
## 🧯 Known issues
|
|
134
151
|
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,101 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://devalang.com/images/devalang-logo.
|
|
2
|
+
<img src="https://devalang.com/images/devalang-logo-min.png" alt="Devalang Logo" width="100" />
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
+
## Version 0.0.1-alpha.16 (2025-08-28)
|
|
8
|
+
|
|
9
|
+
### 🌎 Ecosystem
|
|
10
|
+
|
|
11
|
+
- Added Github Actions to build and release binaries for multiple platforms.
|
|
12
|
+
|
|
13
|
+
### 🧩 Language Features
|
|
14
|
+
|
|
15
|
+
- `bank` handler: add `as <alias>` support and robust parsing of `author.name` and string names.
|
|
16
|
+
- Example: `bank user.808 as my808`, `bank user.myBank as myBank`
|
|
17
|
+
- `plugin` handler: initial implementation with basic support for loading and resolving plugins.
|
|
18
|
+
- Example: `@use user.myPlugin`, `@use user.myPlugin as myAlias`
|
|
19
|
+
- `on` event handler: implemented event trigger resolution and context management.
|
|
20
|
+
- Example: `on beat: ...`, `on bar: ...`, `on custom: ...`
|
|
21
|
+
- `emit` event handler: initial implementation for emitting events.
|
|
22
|
+
- Example: `emit beat`, `emit custom { value: 42 }`
|
|
23
|
+
- `print`: add JS-like string concatenation with `+` between strings, variables, numbers, and `$env`/`$math` expressions.
|
|
24
|
+
- Examples: `print "looping " + i`, `print "bpm=" + $env.bpm`, `print "sin=" + $math.sin(0.5)`
|
|
25
|
+
|
|
26
|
+
### 🧠 Core Engine
|
|
27
|
+
|
|
28
|
+
- Cleanest error handling for unknown triggers (module:line:column), no implicit file search.
|
|
29
|
+
- Real-time runner (play): loops are paced at 1 iteration per beat on the same thread.
|
|
30
|
+
- Periodic events (`on beat`, `on $beat`, `on bar`, `on $bar`) are suspended while a loop is running to avoid interleaving.
|
|
31
|
+
- Loops stop strictly at the end of their block (dedent / end-of-line).
|
|
32
|
+
- Duration estimation improved by accounting for loop iteration counts to keep the runner alive as needed.
|
|
33
|
+
|
|
34
|
+
### 🔎 Telemetry (stats)
|
|
35
|
+
|
|
36
|
+
- Added basic telemetry support for tracking module loading and resolution times.
|
|
37
|
+
- To enable telemetry, execute `devalang telemetry enable`
|
|
38
|
+
- To disable telemetry, execute `devalang telemetry disable`
|
|
39
|
+
|
|
40
|
+
## Version 0.0.1-alpha.15 (2025-08-27)
|
|
41
|
+
|
|
42
|
+
### ✨ Language Features
|
|
43
|
+
|
|
44
|
+
- Added `automate` statement to schedule parameter automation (e.g. volume, pan, pitch) over time
|
|
45
|
+
- Supports per-note automation via a `automate` map on note calls (e.g. `note(C4, { automate: { volume: { 0%: 0.0, 100%: 1.0 } } })`)
|
|
46
|
+
- Added `print` statement to ease debugging at runtime
|
|
47
|
+
- Added special variables and functions usable in expressions:
|
|
48
|
+
- `$env.bpm`, `$env.beat`
|
|
49
|
+
- `$math.sin(expr)`, `$math.cos(expr)`
|
|
50
|
+
- `$env.position` (alias of beat), `$env.seed` (global session seed for deterministic randomness)
|
|
51
|
+
- `$math.random(seed?)`, `$math.lerp(a, b, t)`
|
|
52
|
+
- `$easing.*` functions for shaping values in [0,1]:
|
|
53
|
+
- `linear`, `easeIn/Out/InOutQuad`, `easeIn/Out/InOutCubic`, `easeIn/Out/InOutQuart`,
|
|
54
|
+
`easeIn/Out/InOutExpo`, `easeIn/Out/InOutBack`, `easeIn/Out/InOutElastic`, `easeIn/Out/InOutBounce`
|
|
55
|
+
- `$mod.*` modulators for time-based control:
|
|
56
|
+
- `lfo.sine(ratePerBeat)`, `lfo.tri(ratePerBeat)`, `envelope(attack, decay, sustain, release, t)`
|
|
57
|
+
- Added basic `for` loops and array literals
|
|
58
|
+
- Example: `for i in [1, 2, 3]: print i`
|
|
59
|
+
|
|
60
|
+
### 🧠 Core Engine
|
|
61
|
+
|
|
62
|
+
- Implemented runtime automation in the audio renderer with linear envelope interpolation
|
|
63
|
+
- Per-note automation supported (volume, pan, pitch) and evaluated during rendering
|
|
64
|
+
- Fixed evaluator recursion guard and improved `$math.*` expression handling (prevents stack overflows)
|
|
65
|
+
- Minor ADSR defaults polish: ensure `sustain` defaults to `1.0`
|
|
66
|
+
- Evaluator now supports `$mod.*` and `$easing.*` calls (evaluated before `$math.*`) for richer automation
|
|
67
|
+
- Modularized `AudioEngine::insert_note` into small helpers (oscillator, ADSR computation, pan gains, envelope evaluation, stereo mix)
|
|
68
|
+
- Reused helpers in `pad_samples` to reduce duplication
|
|
69
|
+
- Moved special variables/functions to a dedicated module: `core::audio::special`, and refactored the evaluator to use it
|
|
70
|
+
- Continued borrow-friendly refactors to avoid unnecessary clones and improve readability
|
|
71
|
+
|
|
72
|
+
### 🧩 Parser / Preprocessor
|
|
73
|
+
|
|
74
|
+
- Parser upgrades for operators `+ - * /`, parentheses and brackets
|
|
75
|
+
- Improved arrow-call parsing and map handling for multi-line values
|
|
76
|
+
- Resolvers: refined `call`/`spawn` resolution (better error messages with stack traces)
|
|
77
|
+
|
|
78
|
+
### 🧱 Architecture / Refactor
|
|
79
|
+
|
|
80
|
+
- Modularized audio interpreter (split by statement type); clearer responsibilities
|
|
81
|
+
- Reduced allocations by passing slices/borrows instead of cloning large structures
|
|
82
|
+
- Removed dead code and unused params across resolvers, handlers, and interpreter modules
|
|
83
|
+
|
|
84
|
+
### 🧰 Tooling / Build
|
|
85
|
+
|
|
86
|
+
- Resolved binary/lib artifact collision by renaming the internal library crate to `devalang_core`
|
|
87
|
+
- Warning sweep: build now compiles cleanly without Rust warnings (and fewer Clippy lints)
|
|
88
|
+
- Moved error collection helpers into a dedicated `utils::error` module
|
|
89
|
+
|
|
90
|
+
### 🐛 Fixes & Stability
|
|
91
|
+
|
|
92
|
+
- Prevent infinite recursion during numeric expression evaluation
|
|
93
|
+
- Stabilized renderer and interpreter timing when combining `loop`, `call`, and `spawn`
|
|
94
|
+
|
|
95
|
+
### ⚠️ Breaking changes
|
|
96
|
+
|
|
97
|
+
- Internal crate rename to `devalang_core` (no change to the CLI or WASM package names)
|
|
98
|
+
|
|
7
99
|
## Version 0.0.1-alpha.14 (2025-08-24)
|
|
8
100
|
|
|
9
101
|
### 🌎 Ecosystem
|
package/docs/CONTRIBUTING.md
CHANGED
|
@@ -1 +1,101 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://devalang.com/images/devalang-logo-min.png" alt="Devalang Logo" width="100" />
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
# Contributing to Devalang
|
|
6
|
+
|
|
7
|
+
Thanks for considering a contribution! This document explains how to set up your environment, build the project, and submit changes.
|
|
8
|
+
|
|
9
|
+
## Code of Conduct
|
|
10
|
+
|
|
11
|
+
By participating, you agree to follow our community standards: be respectful, constructive, and empathetic. If something goes wrong, please open an issue.
|
|
12
|
+
|
|
13
|
+
## Project structure
|
|
14
|
+
|
|
15
|
+
- `rust/`: Rust CLI, core engine, parser, preprocessor, audio runtime
|
|
16
|
+
- `typescript/`: TypeScript utilities and scripts
|
|
17
|
+
- `pkg/`: WASM package output (generated by wasm-pack)
|
|
18
|
+
- `examples/`: Devalang examples
|
|
19
|
+
- `docs/`: Documentation
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
- Rust (stable, edition 2024)
|
|
24
|
+
- Node.js 18+
|
|
25
|
+
- wasm-pack (if you work on the WASM package)
|
|
26
|
+
|
|
27
|
+
## Setup
|
|
28
|
+
|
|
29
|
+
1. Install dependencies
|
|
30
|
+
|
|
31
|
+
- Rust toolchain (<https://rustup.rs>)
|
|
32
|
+
- Node.js (<https://nodejs.org>)
|
|
33
|
+
|
|
34
|
+
1. Clone and install
|
|
35
|
+
|
|
36
|
+
- Clone this repository
|
|
37
|
+
- Run `npm install`
|
|
38
|
+
|
|
39
|
+
## Build and run
|
|
40
|
+
|
|
41
|
+
- Build (debug): `cargo build`
|
|
42
|
+
- Build (release): `cargo build --release`
|
|
43
|
+
- TypeScript compile: `npm run script:build`
|
|
44
|
+
- Development helpers:
|
|
45
|
+
- `npm run rust:dev:build` — build AST/audio once
|
|
46
|
+
- `npm run rust:dev:check` — syntax checks with debug logs
|
|
47
|
+
- `npm run rust:dev:play` — play audio in a loop (repeat) with debug
|
|
48
|
+
- WASM builds:
|
|
49
|
+
- Web: `npm run rust:wasm:web`
|
|
50
|
+
- Node: `npm run rust:wasm:node`
|
|
51
|
+
|
|
52
|
+
## Tests and sanity checks
|
|
53
|
+
|
|
54
|
+
- Build and quick smoke test on examples:
|
|
55
|
+
- `cargo build`
|
|
56
|
+
- `npm run rust:dev:play`
|
|
57
|
+
- Prepublish (used by CI/release): `npm run prepublish`
|
|
58
|
+
|
|
59
|
+
## Versioning and releases
|
|
60
|
+
|
|
61
|
+
- Project version lives in multiple places:
|
|
62
|
+
- `Cargo.toml`
|
|
63
|
+
- `package.json`
|
|
64
|
+
- `project-version.json` (includes build counter and last commit)
|
|
65
|
+
- `pkg/package.json` (WASM package)
|
|
66
|
+
- Bump versions to the next pre-release (e.g. 0.0.1-alpha.16), then tag the repository:
|
|
67
|
+
- Bump version: `npm run script:version:bump pre`
|
|
68
|
+
- Commit bump: `git commit -am "chore: bump version to 0.0.1-alpha.X"`
|
|
69
|
+
- Create tag: `git tag v0.0.1-alpha.X`
|
|
70
|
+
- Push: `git push && git push origin v0.0.1-alpha.X`
|
|
71
|
+
- CI publishes release artifacts on tags matching `v*`.
|
|
72
|
+
|
|
73
|
+
## Pull requests
|
|
74
|
+
|
|
75
|
+
- Keep PRs small and focused
|
|
76
|
+
- Describe the motivation and the approach
|
|
77
|
+
- Link related issues
|
|
78
|
+
- Add/update tests (when relevant)
|
|
79
|
+
- Keep the existing style; avoid mass reformatting
|
|
80
|
+
|
|
81
|
+
## Coding guidelines
|
|
82
|
+
|
|
83
|
+
- Rust: follow Clippy suggestions where practical; prefer small, focused modules
|
|
84
|
+
- Keep public APIs stable; document breaking changes in the changelog
|
|
85
|
+
- Add comments where behavior is non-obvious (parser and interpreter paths)
|
|
86
|
+
|
|
87
|
+
## Reporting issues
|
|
88
|
+
|
|
89
|
+
Please include:
|
|
90
|
+
|
|
91
|
+
- Version (`devalang --version`), OS, and repro steps
|
|
92
|
+
- Minimal code sample (`.deva`) if possible
|
|
93
|
+
- Expected vs. actual behavior
|
|
94
|
+
|
|
95
|
+
## Security
|
|
96
|
+
|
|
97
|
+
If you discover a vulnerability, please report it privately (<contact@devaloop.com>). Do not open a public issue until coordinated disclosure.
|
|
98
|
+
|
|
99
|
+
## Thanks
|
|
100
|
+
|
|
101
|
+
We appreciate your time and contributions — whether it’s code, docs, or feedback.
|
package/docs/ROADMAP.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://devalang.com/images/devalang-logo.
|
|
2
|
+
<img src="https://devalang.com/images/devalang-logo-min.png" alt="Devalang Logo" width="100" />
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
# Roadmap
|
|
@@ -27,4 +27,4 @@ Devalang is a work in progress. Here’s what we’re planning next:
|
|
|
27
27
|
|
|
28
28
|
- ⏳ **Smart modules**: Let Devalang detect and use groups, samples, and variables without needing to import them manually.
|
|
29
29
|
- ⏳ **Other statements**: Implement `pattern`, `function`, and other control structures.
|
|
30
|
-
- ⏳ **Testing**: Expand test coverage for all features.
|
|
30
|
+
- ⏳ **Testing**: Expand test coverage for all features.
|
package/docs/TODO.md
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
bpm 120
|
|
2
|
+
|
|
3
|
+
group myLead:
|
|
4
|
+
let mySynth = synth sine
|
|
5
|
+
|
|
6
|
+
# This will automate all notes inside mySynth
|
|
7
|
+
# automate mySynth:
|
|
8
|
+
# param volume {
|
|
9
|
+
# 0% = 0.0
|
|
10
|
+
# 100% = 1.0
|
|
11
|
+
# }
|
|
12
|
+
# param pan {
|
|
13
|
+
# 0% = -1.0
|
|
14
|
+
# 100% = 1.0
|
|
15
|
+
# }
|
|
16
|
+
# param pitch {
|
|
17
|
+
# 0% = -12.0
|
|
18
|
+
# 100% = 12.0
|
|
19
|
+
# }
|
|
20
|
+
|
|
21
|
+
# This will automate only one note
|
|
22
|
+
mySynth -> note(C4, {
|
|
23
|
+
duration: 400,
|
|
24
|
+
automate: {
|
|
25
|
+
pitch: {
|
|
26
|
+
0%: -12.0
|
|
27
|
+
100%: 12.0
|
|
28
|
+
},
|
|
29
|
+
pan: {
|
|
30
|
+
0%: -1.0,
|
|
31
|
+
100%: 1.0
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
mySynth -> note(G4, { duration: 400 })
|
|
36
|
+
mySynth -> note(E4, { duration: 600 })
|
|
37
|
+
mySynth -> note(A4, { duration: 400 })
|
|
38
|
+
mySynth -> note(F4, { duration: 800 })
|
|
39
|
+
mySynth -> note(D4, { duration: 400 })
|
|
40
|
+
mySynth -> note(B3, { duration: 600 })
|
|
41
|
+
|
|
42
|
+
call myLead
|
package/examples/bank.deva
CHANGED
package/examples/function.deva
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# This file demonstrates the use of main features in Devalang.
|
|
2
2
|
bpm 135
|
|
3
3
|
|
|
4
|
-
bank 808
|
|
4
|
+
bank devaloop.808 as myBank
|
|
5
5
|
|
|
6
|
-
let entityTest1 = .
|
|
7
|
-
let entityTest2 = .
|
|
8
|
-
let entityTest3 = .
|
|
6
|
+
let entityTest1 = .myBank.kick auto
|
|
7
|
+
let entityTest2 = .myBank.clap auto
|
|
8
|
+
let entityTest3 = .myBank.snare auto
|
|
9
9
|
|
|
10
10
|
fn myFirstGroup(entity1, entity2, entity3):
|
|
11
11
|
.entity1
|