@devaloop/devalang 0.0.1-alpha.1 → 0.0.1-alpha.10

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 (155) hide show
  1. package/.devalang +4 -0
  2. package/Cargo.toml +49 -45
  3. package/README.md +127 -46
  4. package/docs/CHANGELOG.md +172 -0
  5. package/docs/COMMANDS.md +60 -6
  6. package/docs/CONFIG.md +30 -0
  7. package/docs/ROADMAP.md +10 -7
  8. package/docs/SYNTAX.md +100 -18
  9. package/docs/TODO.md +31 -28
  10. package/examples/condition.deva +20 -0
  11. package/examples/group.deva +12 -0
  12. package/examples/index.deva +13 -4
  13. package/examples/loop.deva +16 -0
  14. package/examples/samples/hat-808.wav +0 -0
  15. package/examples/synth.deva +14 -0
  16. package/examples/variables.deva +9 -0
  17. package/out-tsc/bin/devalang.exe +0 -0
  18. package/out-tsc/scripts/version/fetch.js +1 -5
  19. package/package.json +5 -4
  20. package/project-version.json +3 -3
  21. package/rust/cli/build.rs +114 -28
  22. package/rust/cli/check.rs +96 -103
  23. package/rust/cli/init.rs +79 -0
  24. package/rust/cli/mod.rs +203 -1
  25. package/rust/cli/play.rs +193 -0
  26. package/rust/cli/template.rs +57 -0
  27. package/rust/config/loader.rs +13 -0
  28. package/rust/config/mod.rs +16 -0
  29. package/rust/core/audio/engine.rs +214 -0
  30. package/rust/core/audio/evaluator.rs +31 -0
  31. package/rust/core/audio/interpreter/arrow_call.rs +129 -0
  32. package/rust/core/audio/interpreter/call.rs +70 -0
  33. package/rust/core/audio/interpreter/condition.rs +69 -0
  34. package/rust/core/audio/interpreter/driver.rs +236 -0
  35. package/rust/core/audio/interpreter/let_.rs +19 -0
  36. package/rust/core/audio/interpreter/load.rs +18 -0
  37. package/rust/core/audio/interpreter/loop_.rs +67 -0
  38. package/rust/core/audio/interpreter/mod.rs +12 -0
  39. package/rust/core/audio/interpreter/sleep.rs +36 -0
  40. package/rust/core/audio/interpreter/spawn.rs +84 -0
  41. package/rust/core/audio/interpreter/tempo.rs +16 -0
  42. package/rust/core/audio/interpreter/trigger.rs +69 -0
  43. package/rust/core/audio/loader/mod.rs +1 -0
  44. package/rust/core/audio/loader/trigger.rs +52 -0
  45. package/rust/core/audio/mod.rs +6 -0
  46. package/rust/core/audio/player.rs +54 -0
  47. package/rust/core/audio/renderer.rs +54 -0
  48. package/rust/core/builder/mod.rs +70 -27
  49. package/rust/core/debugger/lexer.rs +27 -0
  50. package/rust/core/debugger/mod.rs +13 -49
  51. package/rust/core/debugger/preprocessor.rs +27 -0
  52. package/rust/core/debugger/store.rs +25 -0
  53. package/rust/core/error/mod.rs +60 -0
  54. package/rust/core/lexer/handler/arrow.rs +31 -0
  55. package/rust/core/lexer/handler/at.rs +21 -0
  56. package/rust/core/lexer/handler/brace.rs +41 -0
  57. package/rust/core/lexer/handler/colon.rs +21 -0
  58. package/rust/core/lexer/handler/comment.rs +30 -0
  59. package/rust/core/lexer/handler/dot.rs +21 -0
  60. package/rust/core/lexer/handler/driver.rs +230 -0
  61. package/rust/core/lexer/handler/identifier.rs +41 -0
  62. package/rust/core/lexer/handler/indent.rs +52 -0
  63. package/rust/core/lexer/handler/mod.rs +14 -0
  64. package/rust/core/lexer/handler/newline.rs +23 -0
  65. package/rust/core/lexer/handler/number.rs +31 -0
  66. package/rust/core/lexer/handler/operator.rs +44 -0
  67. package/rust/core/lexer/handler/string.rs +63 -0
  68. package/rust/core/lexer/mod.rs +37 -319
  69. package/rust/core/lexer/token.rs +86 -0
  70. package/rust/core/mod.rs +6 -2
  71. package/rust/core/parser/driver.rs +331 -0
  72. package/rust/core/parser/handler/arrow_call.rs +126 -0
  73. package/rust/core/parser/handler/at.rs +162 -0
  74. package/rust/core/parser/handler/bank.rs +41 -0
  75. package/rust/core/parser/handler/condition.rs +74 -0
  76. package/rust/core/parser/handler/dot.rs +112 -0
  77. package/rust/core/parser/handler/identifier/call.rs +41 -0
  78. package/rust/core/parser/handler/identifier/group.rs +75 -0
  79. package/rust/core/parser/handler/identifier/let_.rs +133 -0
  80. package/rust/core/parser/handler/identifier/mod.rs +51 -0
  81. package/rust/core/parser/handler/identifier/sleep.rs +33 -0
  82. package/rust/core/parser/handler/identifier/spawn.rs +41 -0
  83. package/rust/core/parser/handler/identifier/synth.rs +65 -0
  84. package/rust/core/parser/handler/loop_.rs +72 -0
  85. package/rust/core/parser/handler/mod.rs +8 -0
  86. package/rust/core/parser/handler/tempo.rs +47 -0
  87. package/rust/core/parser/mod.rs +3 -200
  88. package/rust/core/parser/statement.rs +96 -0
  89. package/rust/core/preprocessor/loader.rs +229 -0
  90. package/rust/core/preprocessor/mod.rs +2 -24
  91. package/rust/core/preprocessor/module.rs +42 -56
  92. package/rust/core/preprocessor/processor.rs +76 -0
  93. package/rust/core/preprocessor/resolver/bank.rs +41 -51
  94. package/rust/core/preprocessor/resolver/call.rs +123 -0
  95. package/rust/core/preprocessor/resolver/condition.rs +92 -0
  96. package/rust/core/preprocessor/resolver/driver.rs +227 -0
  97. package/rust/core/preprocessor/resolver/group.rs +61 -0
  98. package/rust/core/preprocessor/resolver/let_.rs +31 -0
  99. package/rust/core/preprocessor/resolver/loop_.rs +76 -67
  100. package/rust/core/preprocessor/resolver/mod.rs +12 -111
  101. package/rust/core/preprocessor/resolver/spawn.rs +58 -0
  102. package/rust/core/preprocessor/resolver/synth.rs +50 -0
  103. package/rust/core/preprocessor/resolver/tempo.rs +40 -61
  104. package/rust/core/preprocessor/resolver/trigger.rs +90 -154
  105. package/rust/core/preprocessor/resolver/value.rs +78 -0
  106. package/rust/core/shared/duration.rs +8 -0
  107. package/rust/core/shared/mod.rs +2 -0
  108. package/rust/core/shared/value.rs +28 -0
  109. package/rust/core/store/export.rs +28 -0
  110. package/rust/core/store/global.rs +39 -0
  111. package/rust/core/store/import.rs +28 -0
  112. package/rust/core/store/mod.rs +4 -0
  113. package/rust/core/store/variable.rs +28 -0
  114. package/rust/core/utils/mod.rs +2 -0
  115. package/rust/core/utils/path.rs +31 -0
  116. package/rust/core/utils/validation.rs +37 -0
  117. package/rust/lib.rs +161 -1
  118. package/rust/main.rs +46 -30
  119. package/rust/utils/file.rs +35 -0
  120. package/rust/utils/logger.rs +108 -34
  121. package/rust/utils/mod.rs +3 -2
  122. package/rust/utils/{loader.rs → spinner.rs} +2 -0
  123. package/rust/utils/watcher.rs +33 -0
  124. package/templates/minimal/.devalang +5 -0
  125. package/templates/minimal/README.md +202 -0
  126. package/templates/minimal/src/index.deva +2 -0
  127. package/templates/welcome/.devalang +5 -0
  128. package/templates/welcome/README.md +202 -0
  129. package/templates/welcome/samples/kick-808.wav +0 -0
  130. package/templates/welcome/src/index.deva +13 -0
  131. package/templates/welcome/src/variables.deva +5 -0
  132. package/typescript/scripts/version/fetch.ts +1 -6
  133. package/examples/exported.deva +0 -7
  134. package/rust/audio/mod.rs +0 -1
  135. package/rust/cli/new.rs +0 -1
  136. package/rust/core/parser/at.rs +0 -142
  137. package/rust/core/parser/bank.rs +0 -42
  138. package/rust/core/parser/dot.rs +0 -107
  139. package/rust/core/parser/identifer.rs +0 -91
  140. package/rust/core/parser/loop_.rs +0 -62
  141. package/rust/core/parser/tempo.rs +0 -42
  142. package/rust/core/parser/variable.rs +0 -129
  143. package/rust/core/preprocessor/dependencies.rs +0 -54
  144. package/rust/core/preprocessor/resolver/at.rs +0 -24
  145. package/rust/core/types/cli.rs +0 -160
  146. package/rust/core/types/mod.rs +0 -7
  147. package/rust/core/types/module.rs +0 -41
  148. package/rust/core/types/parser.rs +0 -73
  149. package/rust/core/types/statement.rs +0 -105
  150. package/rust/core/types/store.rs +0 -116
  151. package/rust/core/types/token.rs +0 -83
  152. package/rust/core/types/variable.rs +0 -32
  153. package/rust/runner/executer.rs +0 -44
  154. package/rust/runner/mod.rs +0 -1
  155. package/rust/utils/path.rs +0 -46
@@ -0,0 +1,202 @@
1
+ <div align="center">
2
+ <img src="https://firebasestorage.googleapis.com/v0/b/devaloop-labs.firebasestorage.app/o/devalang-teal-logo.svg?alt=media&token=d2a5705a-1eba-4b49-88e6-895a761fb7f7" alt="Devalang Logo">
3
+ </div>
4
+
5
+ ![Rust](https://img.shields.io/badge/Made%20with-Rust-orange?logo=rust)
6
+ ![TypeScript](https://img.shields.io/badge/Built%20with-TypeScript-blue?logo=typescript)
7
+ ![Node.js](https://img.shields.io/badge/Node.js-18%2B-brightgreen?logo=node.js)
8
+
9
+ ![Project Status](https://img.shields.io/badge/status-alpha-red)
10
+ ![Version](https://img.shields.io/badge/version-0.0.1-blue)
11
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
12
+ ![Platform](https://img.shields.io/badge/platform-Windows-blue)
13
+
14
+ ![npm](https://img.shields.io/npm/dt/@devaloop/devalang)
15
+ ![crates](https://img.shields.io/crates/d/devalang)
16
+
17
+ ## 🎼 Devalang, by **Devaloop Labs**
18
+
19
+ 🎶 Compose music with code — simple, structured, sonic.
20
+
21
+ Devalang is a tiny domain-specific language (DSL) for music makers, sound designers, and audio hackers.
22
+ Compose loops, control samples, render and play audio — all in clean, readable text.
23
+
24
+ 🦊 Whether you're building a track, shaping textures, or performing live, Devalang helps you think in rhythms. It’s designed to be simple, expressive, and fast — because your ideas shouldn’t wait.
25
+
26
+ From studio sketches to live sets, Devalang gives you rhythmic control — with the elegance of code.
27
+
28
+ > 🚧 **v0.0.1-alpha.5 Notice** 🚧
29
+ >
30
+ > Currently, Devalang CLI is only available for **Windows**.
31
+ > Linux and macOS binaries will be added in future releases via cross-platform builds.
32
+
33
+ ---
34
+
35
+ ## 📚 Quick Access
36
+
37
+ - [📖 Documentation](./docs/)
38
+ - [💡 Examples](./examples/)
39
+ - [🌐 Project Website](https://devalang.com)
40
+
41
+ ## 🚀 Features
42
+
43
+ - 🎵 **Audio Engine**: Integrated audio playback and rendering
44
+ - 🧩 **Module system** for importing and exporting variables between files
45
+ - 📜 **Structured AST** generation for debugging and future compilation
46
+ - 🔢 **Basic data types**: strings, numbers, booleans, maps, arrays
47
+ - 👁️ **Watch mode** for `build`, `check` and `play` commands
48
+ - 📂 **Project templates** for quick setup
49
+
50
+ ## 📆 Installation
51
+
52
+ ### For users
53
+
54
+ > - ⚠️ Requires [Node.js 18+](https://nodejs.org/en/download)
55
+
56
+ Install the package globally (NPM)
57
+
58
+ ```bash
59
+ npm install -g @devaloop/devalang
60
+ ```
61
+
62
+ Usage without install (NPX)
63
+
64
+ ```bash
65
+ npx @devaloop/devalang <command>
66
+ ```
67
+
68
+ ### For contributors
69
+
70
+ > - ⚠️ Requires [Node.js 18+](https://nodejs.org/en/download)
71
+ > - ⚠️ Requires [Rust 1.70+](https://www.rust-lang.org/learn/get-started#installing-rust)
72
+
73
+ ```bash
74
+ > git clone https://github.com/devaloop-labs/devalang.git
75
+ > cd devalang
76
+ > npm install
77
+ > cargo install --path .
78
+ ```
79
+
80
+ Development usage (you can customize arguments in package.json)
81
+
82
+ ```bash
83
+ # For syntax checking test
84
+ npm run rust:dev:check
85
+ # For building test
86
+ npm run rust:dev:build
87
+ ```
88
+
89
+ ## ❔ Usage
90
+
91
+ NOTE: Commands are available via `devalang` or `npx @devaloop/devalang`.
92
+
93
+ NOTE: Arguments can be passed to commands using `--<argument>` syntax. You can also use a configuration file to set default values for various settings, making it easier to manage your Devalang project.
94
+
95
+ NOTE: Some commands require a mandatory `--entry` argument to specify the input folder, and a `--output` argument to specify the output folder. If not specified, they default to `./src` and `./output` respectively.
96
+
97
+ For more examples, see [docs/COMMANDS.md](./docs/COMMANDS.md)
98
+
99
+ ### Initialize a new project
100
+
101
+ In the current directory
102
+
103
+ ```bash
104
+ devalang init
105
+ ```
106
+
107
+ Or use optional arguments to specify a directory name and a template
108
+
109
+ ```bash
110
+ devalang init --name <project-name> --template <template-name>
111
+ ```
112
+
113
+ ### Checking syntax only
114
+
115
+ ```bash
116
+ devalang check --watch
117
+ ```
118
+
119
+ ### Building output files
120
+
121
+ ```bash
122
+ devalang build --watch
123
+ ```
124
+
125
+ ### Playing audio files (once by file change)
126
+
127
+ ```bash
128
+ devalang play --watch
129
+ ```
130
+
131
+ ### Playing audio files (continuous playback, even without file changes)
132
+
133
+ ```bash
134
+ devalang play --repeat
135
+ ```
136
+
137
+ ## ⚙️ Configuration
138
+
139
+ You can use a configuration file to set default values for various settings, making it easier to manage your Devalang project.
140
+
141
+ To do this, create a `.devalang` file in the root of your project directory.
142
+
143
+ See [docs/CONFIG.md](./docs/CONFIG.md) for more information.
144
+
145
+ ## 📄 Syntax example
146
+
147
+ For more examples, see [docs/SYNTAX.md](./docs/SYNTAX.md)
148
+
149
+ ```deva
150
+ # index.deva
151
+
152
+ @import { globalBpm, globalBank, kickDuration } from "global.deva"
153
+
154
+ @load "./examples/samples/kick-808.wav" as customKick
155
+
156
+ bpm globalBpm
157
+ # Will declare the tempo at the globalBpm variable beats per minute
158
+
159
+ bank globalBank
160
+ # Will declare a custom instrument bank using the globalBank variable
161
+
162
+ loop 5:
163
+ .customKick kickDuration {reverb=50, drive=25}
164
+ # Will play 5 times a kick for the duration of the kickDuration variable with reverb and drive effects
165
+ ```
166
+
167
+ ```deva
168
+ # global.deva
169
+
170
+ let globalBpm = 120
171
+ let globalBank = 808
172
+ let kickDuration = 500
173
+
174
+ @export { globalBpm, globalBank, kickDuration }
175
+ ```
176
+
177
+ ## 🧯 Known issues
178
+
179
+ - No support yet for `if`, `else`, `else if` statements
180
+ - No support yet for `@group`, `@pattern`, `@function` statements
181
+ - No support yet for cross-platform builds (Linux, macOS)
182
+
183
+ ## 🧪 Roadmap Highlights
184
+
185
+ For more info, see [docs/ROADMAP.md](./docs/ROADMAP.md)
186
+
187
+ - ⏳ Other statements (e.g `if`, `@group`, ...)
188
+ - ⏳ Cross-platform support (Linux, macOS)
189
+ - ⏳ More built-in instruments (e.g. snare, hi-hat, etc.)
190
+
191
+ ## 🛡️ License
192
+
193
+ MIT — see [LICENSE](./LICENSE)
194
+
195
+ ## 🤝 Contributing
196
+
197
+ Contributions, bug reports and suggestions are welcome !
198
+ Feel free to open an issue or submit a pull request.
199
+
200
+ ## 📢 Contact
201
+
202
+ 📧 [contact@devaloop.com](mailto:contact@devaloop.com)
@@ -0,0 +1,2 @@
1
+ # Write your Devalang code here
2
+ # ...
@@ -0,0 +1,5 @@
1
+ [defaults]
2
+ entry = "./src"
3
+ output = "./output"
4
+ watch = false
5
+ repeat = false
@@ -0,0 +1,202 @@
1
+ <div align="center">
2
+ <img src="https://firebasestorage.googleapis.com/v0/b/devaloop-labs.firebasestorage.app/o/devalang-teal-logo.svg?alt=media&token=d2a5705a-1eba-4b49-88e6-895a761fb7f7" alt="Devalang Logo">
3
+ </div>
4
+
5
+ ![Rust](https://img.shields.io/badge/Made%20with-Rust-orange?logo=rust)
6
+ ![TypeScript](https://img.shields.io/badge/Built%20with-TypeScript-blue?logo=typescript)
7
+ ![Node.js](https://img.shields.io/badge/Node.js-18%2B-brightgreen?logo=node.js)
8
+
9
+ ![Project Status](https://img.shields.io/badge/status-alpha-red)
10
+ ![Version](https://img.shields.io/badge/version-0.0.1-blue)
11
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
12
+ ![Platform](https://img.shields.io/badge/platform-Windows-blue)
13
+
14
+ ![npm](https://img.shields.io/npm/dt/@devaloop/devalang)
15
+ ![crates](https://img.shields.io/crates/d/devalang)
16
+
17
+ ## 🎼 Devalang, by **Devaloop Labs**
18
+
19
+ 🎶 Compose music with code — simple, structured, sonic.
20
+
21
+ Devalang is a tiny domain-specific language (DSL) for music makers, sound designers, and audio hackers.
22
+ Compose loops, control samples, render and play audio — all in clean, readable text.
23
+
24
+ 🦊 Whether you're building a track, shaping textures, or performing live, Devalang helps you think in rhythms. It’s designed to be simple, expressive, and fast — because your ideas shouldn’t wait.
25
+
26
+ From studio sketches to live sets, Devalang gives you rhythmic control — with the elegance of code.
27
+
28
+ > 🚧 **v0.0.1-alpha.5 Notice** 🚧
29
+ >
30
+ > Currently, Devalang CLI is only available for **Windows**.
31
+ > Linux and macOS binaries will be added in future releases via cross-platform builds.
32
+
33
+ ---
34
+
35
+ ## 📚 Quick Access
36
+
37
+ - [📖 Documentation](./docs/)
38
+ - [💡 Examples](./examples/)
39
+ - [🌐 Project Website](https://devalang.com)
40
+
41
+ ## 🚀 Features
42
+
43
+ - 🎵 **Audio Engine**: Integrated audio playback and rendering
44
+ - 🧩 **Module system** for importing and exporting variables between files
45
+ - 📜 **Structured AST** generation for debugging and future compilation
46
+ - 🔢 **Basic data types**: strings, numbers, booleans, maps, arrays
47
+ - 👁️ **Watch mode** for `build`, `check` and `play` commands
48
+ - 📂 **Project templates** for quick setup
49
+
50
+ ## 📆 Installation
51
+
52
+ ### For users
53
+
54
+ > - ⚠️ Requires [Node.js 18+](https://nodejs.org/en/download)
55
+
56
+ Install the package globally (NPM)
57
+
58
+ ```bash
59
+ npm install -g @devaloop/devalang
60
+ ```
61
+
62
+ Usage without install (NPX)
63
+
64
+ ```bash
65
+ npx @devaloop/devalang <command>
66
+ ```
67
+
68
+ ### For contributors
69
+
70
+ > - ⚠️ Requires [Node.js 18+](https://nodejs.org/en/download)
71
+ > - ⚠️ Requires [Rust 1.70+](https://www.rust-lang.org/learn/get-started#installing-rust)
72
+
73
+ ```bash
74
+ > git clone https://github.com/devaloop-labs/devalang.git
75
+ > cd devalang
76
+ > npm install
77
+ > cargo install --path .
78
+ ```
79
+
80
+ Development usage (you can customize arguments in package.json)
81
+
82
+ ```bash
83
+ # For syntax checking test
84
+ npm run rust:dev:check
85
+ # For building test
86
+ npm run rust:dev:build
87
+ ```
88
+
89
+ ## ❔ Usage
90
+
91
+ NOTE: Commands are available via `devalang` or `npx @devaloop/devalang`.
92
+
93
+ NOTE: Arguments can be passed to commands using `--<argument>` syntax. You can also use a configuration file to set default values for various settings, making it easier to manage your Devalang project.
94
+
95
+ NOTE: Some commands require a mandatory `--entry` argument to specify the input folder, and a `--output` argument to specify the output folder. If not specified, they default to `./src` and `./output` respectively.
96
+
97
+ For more examples, see [docs/COMMANDS.md](./docs/COMMANDS.md)
98
+
99
+ ### Initialize a new project
100
+
101
+ In the current directory
102
+
103
+ ```bash
104
+ devalang init
105
+ ```
106
+
107
+ Or use optional arguments to specify a directory name and a template
108
+
109
+ ```bash
110
+ devalang init --name <project-name> --template <template-name>
111
+ ```
112
+
113
+ ### Checking syntax only
114
+
115
+ ```bash
116
+ devalang check --watch
117
+ ```
118
+
119
+ ### Building output files
120
+
121
+ ```bash
122
+ devalang build --watch
123
+ ```
124
+
125
+ ### Playing audio files (once by file change)
126
+
127
+ ```bash
128
+ devalang play --watch
129
+ ```
130
+
131
+ ### Playing audio files (continuous playback, even without file changes)
132
+
133
+ ```bash
134
+ devalang play --repeat
135
+ ```
136
+
137
+ ## ⚙️ Configuration
138
+
139
+ You can use a configuration file to set default values for various settings, making it easier to manage your Devalang project.
140
+
141
+ To do this, create a `.devalang` file in the root of your project directory.
142
+
143
+ See [docs/CONFIG.md](./docs/CONFIG.md) for more information.
144
+
145
+ ## 📄 Syntax example
146
+
147
+ For more examples, see [docs/SYNTAX.md](./docs/SYNTAX.md)
148
+
149
+ ```deva
150
+ # index.deva
151
+
152
+ @import { globalBpm, globalBank, kickDuration } from "global.deva"
153
+
154
+ @load "./examples/samples/kick-808.wav" as customKick
155
+
156
+ bpm globalBpm
157
+ # Will declare the tempo at the globalBpm variable beats per minute
158
+
159
+ bank globalBank
160
+ # Will declare a custom instrument bank using the globalBank variable
161
+
162
+ loop 5:
163
+ .customKick kickDuration {reverb=50, drive=25}
164
+ # Will play 5 times a kick for the duration of the kickDuration variable with reverb and drive effects
165
+ ```
166
+
167
+ ```deva
168
+ # global.deva
169
+
170
+ let globalBpm = 120
171
+ let globalBank = 808
172
+ let kickDuration = 500
173
+
174
+ @export { globalBpm, globalBank, kickDuration }
175
+ ```
176
+
177
+ ## 🧯 Known issues
178
+
179
+ - No support yet for `if`, `else`, `else if` statements
180
+ - No support yet for `@group`, `@pattern`, `@function` statements
181
+ - No support yet for cross-platform builds (Linux, macOS)
182
+
183
+ ## 🧪 Roadmap Highlights
184
+
185
+ For more info, see [docs/ROADMAP.md](./docs/ROADMAP.md)
186
+
187
+ - ⏳ Other statements (e.g `if`, `@group`, ...)
188
+ - ⏳ Cross-platform support (Linux, macOS)
189
+ - ⏳ More built-in instruments (e.g. snare, hi-hat, etc.)
190
+
191
+ ## 🛡️ License
192
+
193
+ MIT — see [LICENSE](./LICENSE)
194
+
195
+ ## 🤝 Contributing
196
+
197
+ Contributions, bug reports and suggestions are welcome !
198
+ Feel free to open an issue or submit a pull request.
199
+
200
+ ## 📢 Contact
201
+
202
+ 📧 [contact@devaloop.com](mailto:contact@devaloop.com)
@@ -0,0 +1,13 @@
1
+ # 🦊 Welcome to Devalang !
2
+ # This is your first Devalang program ?
3
+ # Let's start with a simple example that plays a sample in a loop.
4
+
5
+ @import { bpmVar, bankVar, loopVar } from './variables.deva'
6
+ @load "../samples/kick-808.wav" as sample
7
+
8
+ bpm bpmVar
9
+
10
+ bank bankVar
11
+
12
+ loop loopVar:
13
+ .sample auto
@@ -0,0 +1,5 @@
1
+ let bpmVar = 120
2
+ let bankVar = 808
3
+ let loopVar = 10
4
+
5
+ @export { bpmVar, bankVar, loopVar }
@@ -1,23 +1,18 @@
1
1
  import fs from "fs";
2
- import path from "path";
3
2
  import { execSync } from "child_process";
4
3
 
5
4
  export const fetchVersion = async (projectVersionPath: string) => {
6
- // Lire le fichier
7
5
  const data = JSON.parse(fs.readFileSync(projectVersionPath, "utf-8"));
8
6
 
9
- // Incrémenter le numéro de build
10
7
  data.build = (data.build || 0) + 1;
11
8
 
12
- // Récupérer le dernier hash git
13
9
  try {
14
10
  const commit = execSync("git rev-parse HEAD").toString().trim();
15
11
  data.lastCommit = commit;
16
12
  } catch (err) {
17
- console.warn("⚠️ Impossible de récupérer le hash git.");
13
+ console.warn("⚠️ Unable to fetch git commit hash. Ensure you are in a git repository.");
18
14
  }
19
15
 
20
- // Écrire la mise à jour
21
16
  fs.writeFileSync(projectVersionPath, JSON.stringify(data, null, 2));
22
17
  }
23
18
 
@@ -1,7 +0,0 @@
1
- let duration = auto
2
- let default_bank = 808
3
- let params = {decay:10, delay:30}
4
- let loopCount = 15
5
- let tempo = 155
6
-
7
- @export { duration, default_bank, params, loopCount, tempo }
package/rust/audio/mod.rs DELETED
@@ -1 +0,0 @@
1
- // TODO Audio engine
package/rust/cli/new.rs DELETED
@@ -1 +0,0 @@
1
- // TODO Implement the new command to create a new project with a template
@@ -1,142 +0,0 @@
1
- use crate::core::types::{
2
- parser::Parser,
3
- statement::{ Statement, StatementKind },
4
- token::TokenKind,
5
- variable::VariableValue,
6
- };
7
-
8
- pub fn parse_at(parser: &mut Parser) -> Result<Statement, String> {
9
- let token = parser.peek().ok_or("Unexpected EOF")?.clone();
10
-
11
- if token.kind != TokenKind::At {
12
- return Err(format!("Expected '@', found {:?}", token.kind));
13
- }
14
-
15
- parser.next();
16
-
17
- let identifier_token = parser.peek().ok_or("Expected identifier after '@'")?.clone();
18
- if identifier_token.kind != TokenKind::Identifier {
19
- return Err(format!("Expected Identifier, found {:?}", identifier_token.kind));
20
- }
21
-
22
- match identifier_token.lexeme.as_str() {
23
- "export" => {
24
- parser.next();
25
-
26
- if let Some(next_token) = parser.peek() {
27
- if next_token.kind == TokenKind::LBrace {
28
- parser.next(); // Consomme le LBrace
29
- }
30
- }
31
-
32
- let exportable_tokens = parser.collect_until(|t| { t.kind == TokenKind::RBrace });
33
-
34
- exportable_tokens.iter().for_each(|t| {
35
- let variable_value = parser.variable_table
36
- .get(&t.lexeme)
37
- .cloned()
38
- .unwrap_or_else(|| VariableValue::Text(t.lexeme.clone()));
39
-
40
- parser.export_table.exports.insert(t.lexeme.clone(), variable_value);
41
- });
42
-
43
- return Ok(Statement {
44
- kind: StatementKind::Export,
45
- value: VariableValue::Array(exportable_tokens),
46
- indent: token.indent,
47
- line: token.line,
48
- column: token.column,
49
- });
50
- }
51
- "import" => {
52
- parser.next();
53
-
54
- if let Some(next_token) = parser.peek() {
55
- if next_token.kind == TokenKind::LBrace {
56
- parser.next();
57
- }
58
- }
59
-
60
- let importable_tokens = parser.collect_until(|t| { t.kind == TokenKind::RBrace });
61
-
62
- parser.next();
63
-
64
- if let Some(from_token) = parser.peek() {
65
- if from_token.kind == TokenKind::Identifier && from_token.lexeme == "from" {
66
- parser.next();
67
- } else {
68
- return Err(format!("Expected 'from', found {:?}", from_token.kind));
69
- }
70
- } else {
71
- return Err("Expected 'from' after import declaration".into());
72
- }
73
-
74
- let source_token = parser.peek().ok_or("Expected source after 'from'")?.clone();
75
- if source_token.kind != TokenKind::String {
76
- return Err(format!("Expected String, found {:?}", source_token.kind));
77
- }
78
-
79
- let statement = Statement {
80
- kind: StatementKind::Import {
81
- names: importable_tokens
82
- .iter()
83
- .map(|t| t.lexeme.clone())
84
- .collect(),
85
- source: source_token.lexeme.clone(),
86
- },
87
- value: VariableValue::Array(importable_tokens),
88
- indent: token.indent,
89
- line: token.line,
90
- column: token.column,
91
- };
92
-
93
- return Ok(statement);
94
- }
95
- "load" => {
96
- parser.next();
97
-
98
- let source_token = parser.peek().ok_or("Expected source after load")?.clone();
99
- if source_token.kind != TokenKind::String {
100
- return Err(format!("Expected String, found {:?}", source_token.kind));
101
- }
102
-
103
- parser.next();
104
-
105
- let as_token = parser.peek().ok_or("Expected 'as' after load")?.clone();
106
- if as_token.kind != TokenKind::Identifier || as_token.lexeme != "as" {
107
- return Err(format!("Expected 'as', found {:?}", as_token.kind));
108
- }
109
-
110
- parser.next();
111
-
112
- let alias_token = parser.peek().ok_or("Expected alias after load")?.clone();
113
- if alias_token.kind != TokenKind::Identifier {
114
- return Err(format!("Expected Identifier, found {:?}", alias_token.kind));
115
- }
116
-
117
- parser.next();
118
-
119
- let statement = Statement {
120
- kind: StatementKind::Load {
121
- source: source_token.lexeme.clone(),
122
- alias: alias_token.lexeme.clone(),
123
- },
124
- value: VariableValue::Text(alias_token.lexeme.clone()),
125
- indent: token.indent,
126
- line: token.line,
127
- column: token.column,
128
- };
129
-
130
- return Ok(statement);
131
- }
132
-
133
- _ => {
134
- return Err(
135
- format!(
136
- "Expected 'export', 'import' or 'load', found '{}'",
137
- identifier_token.lexeme
138
- )
139
- );
140
- }
141
- }
142
- }
@@ -1,42 +0,0 @@
1
- use crate::core::types::{
2
- parser::Parser,
3
- statement::{ Statement, StatementKind },
4
- store::GlobalStore,
5
- token::TokenKind,
6
- variable::VariableValue,
7
- };
8
-
9
- pub fn parse_bank(
10
- parser: &mut Parser,
11
- global_store: &mut GlobalStore
12
- ) -> Result<Statement, String> {
13
- let token = parser.peek().ok_or("Unexpected EOF")?.clone();
14
-
15
- let mut bank_name = String::new();
16
-
17
- if parser.next().map(|t| t.kind.clone()) != Some(TokenKind::Bank) {
18
- return Err("Expected 'bank' keyword".to_string());
19
- }
20
-
21
- if let Some(token) = parser.next() {
22
- if token.kind == TokenKind::Identifier {
23
- bank_name = token.lexeme.clone();
24
- } else if token.kind == TokenKind::String {
25
- bank_name = token.lexeme.trim_matches('"').to_string();
26
- } else if token.kind == TokenKind::Number {
27
- bank_name = token.lexeme.clone();
28
- } else {
29
- return Err(format!("Expected bank name, found {:?}", token.kind));
30
- }
31
- } else {
32
- return Err("Expected bank name after 'bank' keyword".to_string());
33
- }
34
-
35
- Ok(Statement {
36
- kind: StatementKind::Bank,
37
- value: VariableValue::Text(bank_name.clone()),
38
- indent: token.indent,
39
- line: token.line,
40
- column: token.column,
41
- })
42
- }