@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.
Files changed (177) hide show
  1. package/.devalang +10 -8
  2. package/.github/workflows/ci.yml +92 -0
  3. package/Cargo.toml +60 -58
  4. package/README.md +32 -15
  5. package/docs/CHANGELOG.md +93 -1
  6. package/docs/CONTRIBUTING.md +101 -1
  7. package/docs/ROADMAP.md +2 -2
  8. package/docs/TODO.md +1 -1
  9. package/examples/automation.deva +42 -0
  10. package/examples/bank.deva +4 -4
  11. package/examples/events.deva +12 -0
  12. package/examples/function.deva +4 -4
  13. package/examples/index.deva +39 -25
  14. package/examples/loop.deva +5 -11
  15. package/examples/pattern.deva +8 -0
  16. package/examples/plugin.deva +16 -0
  17. package/examples/variables.deva +1 -1
  18. package/out-tsc/bin/index.js +51 -7
  19. package/out-tsc/index.js +3 -1
  20. package/out-tsc/scripts/postbuild.js +9 -10
  21. package/out-tsc/scripts/postinstall.js +49 -0
  22. package/package.json +12 -4
  23. package/project-version.json +3 -3
  24. package/rust/cli/bank.rs +462 -456
  25. package/rust/cli/build.rs +252 -199
  26. package/rust/cli/check.rs +221 -180
  27. package/rust/cli/driver.rs +297 -292
  28. package/rust/cli/generator.rs +1 -0
  29. package/rust/cli/init.rs +87 -79
  30. package/rust/cli/install.rs +35 -32
  31. package/rust/cli/login.rs +127 -134
  32. package/rust/cli/mod.rs +13 -11
  33. package/rust/cli/play.rs +1123 -218
  34. package/rust/cli/telemetry.rs +19 -0
  35. package/rust/cli/template.rs +69 -57
  36. package/rust/cli/update.rs +6 -4
  37. package/rust/common/api.rs +5 -8
  38. package/rust/common/cdn.rs +3 -6
  39. package/rust/common/mod.rs +3 -3
  40. package/rust/common/sso.rs +3 -6
  41. package/rust/config/driver.rs +118 -94
  42. package/rust/config/loader.rs +165 -156
  43. package/rust/config/mod.rs +4 -2
  44. package/rust/config/settings.rs +91 -0
  45. package/rust/config/stats.rs +257 -0
  46. package/rust/core/audio/engine.rs +696 -518
  47. package/rust/core/audio/evaluator.rs +263 -31
  48. package/rust/core/audio/interpreter/arrow_call.rs +198 -161
  49. package/rust/core/audio/interpreter/automate.rs +18 -0
  50. package/rust/core/audio/interpreter/call.rs +98 -95
  51. package/rust/core/audio/interpreter/condition.rs +70 -71
  52. package/rust/core/audio/interpreter/driver.rs +487 -198
  53. package/rust/core/audio/interpreter/function.rs +26 -21
  54. package/rust/core/audio/interpreter/let_.rs +38 -19
  55. package/rust/core/audio/interpreter/load.rs +18 -18
  56. package/rust/core/audio/interpreter/loop_.rs +113 -73
  57. package/rust/core/audio/interpreter/mod.rs +14 -13
  58. package/rust/core/audio/interpreter/sleep.rs +27 -30
  59. package/rust/core/audio/interpreter/spawn.rs +105 -102
  60. package/rust/core/audio/interpreter/tempo.rs +19 -16
  61. package/rust/core/audio/interpreter/trigger.rs +239 -210
  62. package/rust/core/audio/loader/mod.rs +1 -1
  63. package/rust/core/audio/loader/trigger.rs +100 -97
  64. package/rust/core/audio/mod.rs +7 -6
  65. package/rust/core/audio/player.rs +64 -64
  66. package/rust/core/audio/renderer.rs +56 -53
  67. package/rust/core/audio/special/easing.rs +189 -0
  68. package/rust/core/audio/special/env.rs +43 -0
  69. package/rust/core/audio/special/math.rs +102 -0
  70. package/rust/core/audio/special/mod.rs +9 -0
  71. package/rust/core/audio/special/modulator.rs +143 -0
  72. package/rust/core/builder/mod.rs +80 -85
  73. package/rust/core/debugger/lexer.rs +27 -27
  74. package/rust/core/debugger/mod.rs +24 -23
  75. package/rust/core/debugger/module.rs +55 -47
  76. package/rust/core/debugger/preprocessor.rs +27 -27
  77. package/rust/core/debugger/store.rs +40 -39
  78. package/rust/core/error/mod.rs +80 -66
  79. package/rust/core/lexer/handler/arrow.rs +82 -31
  80. package/rust/core/lexer/handler/at.rs +21 -21
  81. package/rust/core/lexer/handler/brace.rs +41 -41
  82. package/rust/core/lexer/handler/colon.rs +21 -21
  83. package/rust/core/lexer/handler/comment.rs +30 -30
  84. package/rust/core/lexer/handler/dot.rs +21 -21
  85. package/rust/core/lexer/handler/driver.rs +337 -263
  86. package/rust/core/lexer/handler/identifier.rs +46 -42
  87. package/rust/core/lexer/handler/indent.rs +66 -66
  88. package/rust/core/lexer/handler/mod.rs +16 -16
  89. package/rust/core/lexer/handler/newline.rs +23 -23
  90. package/rust/core/lexer/handler/number.rs +31 -31
  91. package/rust/core/lexer/handler/operator.rs +46 -44
  92. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  93. package/rust/core/lexer/handler/slash.rs +21 -21
  94. package/rust/core/lexer/handler/string.rs +63 -63
  95. package/rust/core/lexer/mod.rs +54 -51
  96. package/rust/core/lexer/token.rs +97 -91
  97. package/rust/core/mod.rs +11 -11
  98. package/rust/core/parser/driver.rs +513 -408
  99. package/rust/core/parser/handler/arrow_call.rs +233 -211
  100. package/rust/core/parser/handler/at.rs +245 -162
  101. package/rust/core/parser/handler/bank.rs +94 -69
  102. package/rust/core/parser/handler/condition.rs +80 -74
  103. package/rust/core/parser/handler/dot.rs +143 -135
  104. package/rust/core/parser/handler/identifier/automate.rs +257 -0
  105. package/rust/core/parser/handler/identifier/call.rs +91 -88
  106. package/rust/core/parser/handler/identifier/emit.rs +66 -0
  107. package/rust/core/parser/handler/identifier/function.rs +100 -92
  108. package/rust/core/parser/handler/identifier/group.rs +85 -75
  109. package/rust/core/parser/handler/identifier/let_.rs +158 -127
  110. package/rust/core/parser/handler/identifier/mod.rs +54 -52
  111. package/rust/core/parser/handler/identifier/on.rs +98 -0
  112. package/rust/core/parser/handler/identifier/print.rs +52 -0
  113. package/rust/core/parser/handler/identifier/sleep.rs +36 -33
  114. package/rust/core/parser/handler/identifier/spawn.rs +91 -88
  115. package/rust/core/parser/handler/identifier/synth.rs +65 -65
  116. package/rust/core/parser/handler/loop_.rs +170 -72
  117. package/rust/core/parser/handler/mod.rs +8 -8
  118. package/rust/core/parser/handler/tempo.rs +53 -47
  119. package/rust/core/parser/mod.rs +4 -4
  120. package/rust/core/parser/statement.rs +142 -108
  121. package/rust/core/plugin/loader.rs +123 -48
  122. package/rust/core/plugin/mod.rs +2 -1
  123. package/rust/core/plugin/runner.rs +296 -0
  124. package/rust/core/preprocessor/loader.rs +515 -326
  125. package/rust/core/preprocessor/mod.rs +4 -4
  126. package/rust/core/preprocessor/module.rs +60 -58
  127. package/rust/core/preprocessor/processor.rs +99 -101
  128. package/rust/core/preprocessor/resolver/bank.rs +51 -49
  129. package/rust/core/preprocessor/resolver/call.rs +100 -100
  130. package/rust/core/preprocessor/resolver/condition.rs +97 -97
  131. package/rust/core/preprocessor/resolver/driver.rs +310 -278
  132. package/rust/core/preprocessor/resolver/function.rs +69 -78
  133. package/rust/core/preprocessor/resolver/group.rs +96 -91
  134. package/rust/core/preprocessor/resolver/let_.rs +32 -28
  135. package/rust/core/preprocessor/resolver/loop_.rs +320 -91
  136. package/rust/core/preprocessor/resolver/mod.rs +15 -15
  137. package/rust/core/preprocessor/resolver/spawn.rs +76 -92
  138. package/rust/core/preprocessor/resolver/synth.rs +56 -50
  139. package/rust/core/preprocessor/resolver/tempo.rs +50 -49
  140. package/rust/core/preprocessor/resolver/trigger.rs +113 -116
  141. package/rust/core/preprocessor/resolver/value.rs +81 -87
  142. package/rust/core/shared/bank.rs +1 -1
  143. package/rust/core/shared/duration.rs +9 -9
  144. package/rust/core/shared/mod.rs +3 -3
  145. package/rust/core/shared/value.rs +35 -32
  146. package/rust/core/store/function.rs +34 -34
  147. package/rust/core/store/global.rs +55 -38
  148. package/rust/core/store/mod.rs +5 -5
  149. package/rust/core/store/variable.rs +37 -34
  150. package/rust/core/utils/mod.rs +2 -2
  151. package/rust/core/utils/path.rs +37 -31
  152. package/rust/core/utils/validation.rs +35 -37
  153. package/rust/installer/addon.rs +84 -80
  154. package/rust/installer/bank.rs +62 -65
  155. package/rust/installer/mod.rs +5 -5
  156. package/rust/installer/plugin.rs +54 -55
  157. package/rust/installer/utils.rs +56 -56
  158. package/rust/lib.rs +156 -164
  159. package/rust/main.rs +250 -145
  160. package/rust/utils/error.rs +200 -0
  161. package/rust/utils/file.rs +38 -35
  162. package/rust/utils/first_usage.rs +76 -0
  163. package/rust/utils/logger.rs +195 -139
  164. package/rust/utils/mod.rs +9 -50
  165. package/rust/utils/signature.rs +19 -17
  166. package/rust/utils/spinner.rs +22 -19
  167. package/rust/utils/telemetry.rs +292 -0
  168. package/rust/utils/watcher.rs +34 -33
  169. package/templates/minimal/README.md +97 -121
  170. package/templates/welcome/README.md +97 -121
  171. package/typescript/bin/index.ts +19 -5
  172. package/typescript/index.ts +3 -1
  173. package/typescript/scripts/postbuild.ts +10 -6
  174. package/typescript/scripts/postinstall.ts +56 -0
  175. package/typescript/scripts/version/bump.ts +0 -1
  176. package/typescript/scripts/version/index.ts +0 -1
  177. 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
- [[banks]]
7
- path = "devalang://bank/devaloop.808"
8
- version = "0.0.2"
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.14"
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
- license-file = "LICENSE"
14
- edition = "2024"
15
-
16
- [[bin]]
17
- name = "devalang"
18
- path = "rust/main.rs"
19
- required-features = ["cli"]
20
-
21
- [lib]
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.svg" alt="Devalang Logo" width="300" />
2
+ <img src="https://devalang.com/images/devalang-logo-min.png" alt="Devalang Logo" width="100" />
3
3
  </div>
4
4
 
5
5
  ![Rust](https://img.shields.io/badge/Made%20with-Rust-orange?logo=rust)
@@ -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 myLead:
69
- let mySynth = synth sine {
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
- mySynth -> note(C4, {
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.7,
79
- glide: true
93
+ velocity: 0.8,
94
+ automate: { pan: { 0%: -1.0, 100%: 0.0 } }
80
95
  })
81
96
 
82
- mySynth -> note(G4, {
83
- duration: 600,
84
- slide: true
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 myLead
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.svg" alt="Devalang Logo" width="300" />
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
@@ -1 +1,101 @@
1
- # This file is a placeholder
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.svg" alt="Devalang Logo" width="300" />
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
@@ -1,5 +1,5 @@
1
1
  <div align="center">
2
- <img src="https://devalang.com/images/devalang-logo.svg" alt="Devalang Logo" width="300" />
2
+ <img src="https://devalang.com/images/devalang-logo-min.png" alt="Devalang Logo" width="100" />
3
3
  </div>
4
4
 
5
5
  # TODOs list
@@ -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
@@ -1,7 +1,7 @@
1
1
  # This file demonstrates the use of banks in Devalang.
2
2
 
3
- bank devaloop.808
3
+ bank devaloop.808 as myBank
4
4
 
5
- .808.kick auto
6
- .808.snare auto
7
- .808.openhat auto
5
+ .myBank.kick auto
6
+ .myBank.snare auto
7
+ .myBank.openhat auto
@@ -0,0 +1,12 @@
1
+ bpm 120
2
+
3
+ on beat:
4
+ print "kick on each beat"
5
+
6
+ on bar:
7
+ print "bar!"
8
+
9
+ on custom(value):
10
+ print "custom event with value: " + value
11
+
12
+ emit custom(10)
@@ -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 = .808.kick auto
7
- let entityTest2 = .808.clap auto
8
- let entityTest3 = .808.snare auto
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