@devaloop/devalang 0.0.1-alpha.5 → 0.0.1-alpha.8
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/Cargo.toml +1 -1
- package/README.md +45 -14
- package/docs/CHANGELOG.md +39 -0
- package/docs/ROADMAP.md +2 -2
- package/docs/SYNTAX.md +80 -18
- package/docs/TODO.md +12 -11
- package/examples/condition.deva +24 -0
- package/examples/group.deva +12 -0
- package/examples/index.deva +8 -9
- package/examples/loop.deva +15 -0
- package/examples/variables.deva +9 -0
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +44 -44
- package/project-version.json +5 -5
- package/rust/cli/build.rs +6 -2
- package/rust/cli/play.rs +2 -1
- package/rust/core/audio/evaluator.rs +31 -0
- package/rust/core/audio/interpreter/call.rs +42 -0
- package/rust/core/audio/interpreter/condition.rs +65 -0
- package/rust/core/audio/interpreter/driver.rs +204 -0
- package/rust/core/audio/interpreter/let_.rs +19 -0
- package/rust/core/audio/interpreter/load.rs +18 -0
- package/rust/core/audio/interpreter/loop_.rs +59 -0
- package/rust/core/audio/interpreter/mod.rs +11 -0
- package/rust/core/audio/interpreter/sleep.rs +36 -0
- package/rust/core/audio/interpreter/spawn.rs +65 -0
- package/rust/core/audio/interpreter/tempo.rs +16 -0
- package/rust/core/audio/interpreter/trigger.rs +69 -0
- package/rust/core/audio/loader/mod.rs +1 -0
- package/rust/{audio/loader.rs → core/audio/loader/trigger.rs} +6 -0
- package/rust/{audio → core/audio}/mod.rs +2 -1
- package/rust/{audio/render.rs → core/audio/renderer.rs} +2 -2
- package/rust/core/builder/mod.rs +2 -1
- package/rust/core/debugger/lexer.rs +1 -1
- package/rust/core/debugger/mod.rs +1 -0
- package/rust/core/debugger/store.rs +25 -0
- package/rust/core/error/mod.rs +1 -1
- package/rust/core/lexer/handler/driver.rs +215 -0
- package/rust/core/lexer/handler/identifier.rs +2 -0
- package/rust/core/lexer/handler/indent.rs +1 -1
- package/rust/core/lexer/handler/mod.rs +3 -228
- package/rust/core/lexer/handler/operator.rs +44 -0
- package/rust/core/lexer/handler/string.rs +3 -6
- package/rust/core/lexer/mod.rs +1 -1
- package/rust/core/lexer/token.rs +36 -9
- package/rust/core/mod.rs +2 -1
- package/rust/core/parser/driver.rs +312 -0
- package/rust/core/parser/handler/at.rs +3 -7
- package/rust/core/parser/handler/bank.rs +5 -2
- package/rust/core/parser/handler/condition.rs +74 -0
- package/rust/core/parser/handler/dot.rs +1 -1
- package/rust/core/parser/handler/identifier.rs +130 -2
- package/rust/core/parser/handler/loop_.rs +1 -1
- package/rust/core/parser/handler/mod.rs +2 -1
- package/rust/core/parser/handler/tempo.rs +1 -1
- package/rust/core/parser/mod.rs +3 -237
- package/rust/core/parser/statement.rs +30 -33
- package/rust/core/preprocessor/loader.rs +7 -6
- package/rust/core/preprocessor/processor.rs +29 -3
- package/rust/core/preprocessor/resolver/bank.rs +10 -9
- package/rust/core/preprocessor/resolver/call.rs +53 -0
- package/rust/core/preprocessor/resolver/condition.rs +66 -0
- package/rust/core/preprocessor/resolver/driver.rs +182 -0
- package/rust/core/preprocessor/resolver/group.rs +118 -0
- package/rust/core/preprocessor/resolver/loop_.rs +3 -6
- package/rust/core/preprocessor/resolver/mod.rs +6 -147
- package/rust/core/preprocessor/resolver/spawn.rs +53 -0
- package/rust/core/preprocessor/resolver/trigger.rs +0 -3
- package/rust/lib.rs +0 -1
- package/rust/main.rs +0 -1
- package/examples/exported.deva +0 -7
- package/rust/audio/interpreter.rs +0 -143
- package/rust/core/lexer/handler/equal.rs +0 -32
- /package/rust/{audio → core/audio}/engine.rs +0 -0
- /package/rust/{audio → core/audio}/player.rs +0 -0
package/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "devalang"
|
|
3
|
-
version = "0.0.1-alpha.
|
|
3
|
+
version = "0.0.1-alpha.8"
|
|
4
4
|
authors = ["Devaloop <contact@devaloop.com>"]
|
|
5
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
6
|
license = "MIT"
|
package/README.md
CHANGED
|
@@ -16,10 +16,9 @@
|
|
|
16
16
|
|
|
17
17
|
[](https://marketplace.visualstudio.com/items?itemName=devaloop.devalang-vscode)
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
## 🎼 Devalang, by **Devaloop Labs**
|
|
21
20
|
|
|
22
|
-
🎶 Compose music with code —
|
|
21
|
+
🎶 Compose music with code — structured, expressive, and fast.
|
|
23
22
|
|
|
24
23
|
Devalang is a tiny domain-specific language (DSL) for music makers, sound designers, and audio hackers.
|
|
25
24
|
Compose loops, control samples, render and play audio — all in clean, readable text.
|
|
@@ -28,11 +27,13 @@ Compose loops, control samples, render and play audio — all in clean, readable
|
|
|
28
27
|
|
|
29
28
|
From studio sketches to live sets, Devalang gives you rhythmic control — with the elegance of code.
|
|
30
29
|
|
|
31
|
-
> 🚧 **v0.0.1-alpha.
|
|
30
|
+
> 🚧 **v0.0.1-alpha.8 Notice** 🚧
|
|
32
31
|
>
|
|
33
32
|
> NEW: Devalang VSCode extension is now available !
|
|
34
33
|
> [Get it here](https://marketplace.visualstudio.com/items?itemName=devaloop.devalang-vscode).
|
|
35
34
|
>
|
|
35
|
+
> NEW: Devalang supports conditional statements (`if`, `else`, `else if`) for more dynamic compositions !
|
|
36
|
+
>
|
|
36
37
|
> Currently, Devalang CLI is only available for **Windows**.
|
|
37
38
|
> Linux and macOS binaries will be added in future releases via cross-platform builds.
|
|
38
39
|
|
|
@@ -46,6 +47,15 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
46
47
|
- [🎨 Prettier Plugin](https://www.npmjs.com/package/@devaloop/prettier-plugin-devalang)
|
|
47
48
|
- [🌐 Project Website](https://devalang.com)
|
|
48
49
|
|
|
50
|
+
## ❓ Why Devalang?
|
|
51
|
+
|
|
52
|
+
- 🎹 Prototype audio ideas without opening a DAW
|
|
53
|
+
- 💻 Integrate sound into code-based workflows
|
|
54
|
+
- 🎛️ Control audio parameters through readable syntax
|
|
55
|
+
- 🧪 Build musical logic with variables and conditions
|
|
56
|
+
|
|
57
|
+
> Producer, coder, or both — Devalang gives you musical structure, instantly.
|
|
58
|
+
|
|
49
59
|
## 🚀 Features
|
|
50
60
|
|
|
51
61
|
- 🎵 **Audio Engine**: Integrated audio playback and rendering
|
|
@@ -54,6 +64,8 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
54
64
|
- 🔢 **Basic data types**: strings, numbers, booleans, maps, arrays
|
|
55
65
|
- 👁️ **Watch mode** for `build`, `check` and `play` commands
|
|
56
66
|
- 📂 **Project templates** for quick setup
|
|
67
|
+
- 🎛️ **Custom samples**: easily load and trigger your own audio files
|
|
68
|
+
- 🔄 **Looping and grouping**: create complex patterns with ease
|
|
57
69
|
|
|
58
70
|
## 📆 Installation
|
|
59
71
|
|
|
@@ -64,13 +76,13 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
64
76
|
Install the package globally (NPM)
|
|
65
77
|
|
|
66
78
|
```bash
|
|
67
|
-
npm install -g @devaloop/devalang
|
|
79
|
+
npm install -g @devaloop/devalang@latest
|
|
68
80
|
```
|
|
69
81
|
|
|
70
82
|
Usage without install (NPX)
|
|
71
83
|
|
|
72
84
|
```bash
|
|
73
|
-
npx @devaloop/devalang
|
|
85
|
+
npx @devaloop/devalang@latest
|
|
74
86
|
```
|
|
75
87
|
|
|
76
88
|
### For contributors
|
|
@@ -79,10 +91,11 @@ npx @devaloop/devalang <command>
|
|
|
79
91
|
> - ⚠️ Requires [Rust 1.70+](https://www.rust-lang.org/learn/get-started#installing-rust)
|
|
80
92
|
|
|
81
93
|
```bash
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
git clone https://github.com/devaloop-labs/devalang.git
|
|
95
|
+
|
|
96
|
+
cd devalang
|
|
97
|
+
|
|
98
|
+
npm install
|
|
86
99
|
```
|
|
87
100
|
|
|
88
101
|
Development usage (you can customize arguments in package.json)
|
|
@@ -90,6 +103,7 @@ Development usage (you can customize arguments in package.json)
|
|
|
90
103
|
```bash
|
|
91
104
|
# For syntax checking test
|
|
92
105
|
npm run rust:dev:check
|
|
106
|
+
|
|
93
107
|
# For building test
|
|
94
108
|
npm run rust:dev:build
|
|
95
109
|
```
|
|
@@ -167,13 +181,30 @@ bpm globalBpm
|
|
|
167
181
|
bank globalBank
|
|
168
182
|
# Will declare a custom instrument bank using the globalBank variable
|
|
169
183
|
|
|
184
|
+
# Loops
|
|
185
|
+
|
|
170
186
|
loop 5:
|
|
171
187
|
.customKick kickDuration {reverb=50, drive=25}
|
|
172
|
-
# Will play 5 times a
|
|
188
|
+
# Will play 5 times a custom sample for 500ms with reverb and overdrive effects
|
|
189
|
+
|
|
190
|
+
# Groups
|
|
191
|
+
|
|
192
|
+
group myGroup:
|
|
193
|
+
.customKick kickDuration {reverb=50, drive=25}
|
|
194
|
+
# Will play the same sample in a group, allowing for more complex patterns
|
|
195
|
+
|
|
196
|
+
# Will be executed line by line (sequentially)
|
|
197
|
+
call myGroup
|
|
198
|
+
|
|
199
|
+
# Will be executed in parallel (concurrently)
|
|
200
|
+
# ⚠️ Note: `spawn` runs the entire group in parallel, but the group’s internal logic remains sequential unless it uses `spawn` internally.
|
|
201
|
+
# spawn myGroup
|
|
173
202
|
```
|
|
174
203
|
|
|
204
|
+
> 🧠 Note: `call` and `spawn` only work with `group` blocks. They do not apply to individual samples or other statements.
|
|
205
|
+
|
|
175
206
|
```deva
|
|
176
|
-
#
|
|
207
|
+
# variables.deva
|
|
177
208
|
|
|
178
209
|
let globalBpm = 120
|
|
179
210
|
let globalBank = 808
|
|
@@ -184,15 +215,15 @@ let kickDuration = 500
|
|
|
184
215
|
|
|
185
216
|
## 🧯 Known issues
|
|
186
217
|
|
|
187
|
-
- No
|
|
188
|
-
- No support yet for
|
|
218
|
+
- No smart modules yet, all groups, variables, and samples must be explicitly imported where used
|
|
219
|
+
- No support yet for `pattern`, `function`, ... statements
|
|
189
220
|
- No support yet for cross-platform builds (Linux, macOS)
|
|
190
221
|
|
|
191
222
|
## 🧪 Roadmap Highlights
|
|
192
223
|
|
|
193
224
|
For more info, see [docs/ROADMAP.md](./docs/ROADMAP.md)
|
|
194
225
|
|
|
195
|
-
- ⏳ Other statements (e.g `
|
|
226
|
+
- ⏳ Other statements (e.g `function`, `pattern`, ...)
|
|
196
227
|
- ⏳ Cross-platform support (Linux, macOS)
|
|
197
228
|
- ⏳ More built-in instruments (e.g. snare, hi-hat, etc.)
|
|
198
229
|
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,45 @@
|
|
|
4
4
|
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
+
## Version 0.0.1-alpha.8 (2025-07-12)
|
|
8
|
+
|
|
9
|
+
### Syntax
|
|
10
|
+
|
|
11
|
+
- Implemented `if` directive to conditionally execute blocks of code.
|
|
12
|
+
- Implemented `else` directive to provide an alternative block of code when the `if` condition is not met.
|
|
13
|
+
- Implemented `else if` directive to provide additional conditions for the `if` directive.
|
|
14
|
+
|
|
15
|
+
### Core Components
|
|
16
|
+
|
|
17
|
+
- Implemented evaluator for audio statements, to execute conditional statements.
|
|
18
|
+
- Fixed `group` resolution and export issues.
|
|
19
|
+
- Implemented `Global Store` debugger to inspect variables by module for build command.
|
|
20
|
+
- Organized `TokenKind` and `StatementKind` enums for better clarity and maintainability.
|
|
21
|
+
- Refactored audio interpreter to handle the new syntax and directives.
|
|
22
|
+
- Refactored lexer to handle new directives and improve tokenization.
|
|
23
|
+
- Refactored parser to handle new directives and improve parsing logic.
|
|
24
|
+
- Added support for `call` and `spawn` execution of imported groups.
|
|
25
|
+
- Enforced scoped resolution of groups in `spawn` and `call` (must be imported in current module).
|
|
26
|
+
|
|
27
|
+
## Version 0.0.1-alpha.7 (2025-07-11)
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
- Added examples in `examples` folder (group, loop, variables, index).
|
|
32
|
+
|
|
33
|
+
## Structure
|
|
34
|
+
|
|
35
|
+
- Moved `rust/audio` folder to `rust/core/audio` to better organize the project structure.
|
|
36
|
+
|
|
37
|
+
### Core Components
|
|
38
|
+
|
|
39
|
+
- Implemented `group` directive to define groups of sounds.
|
|
40
|
+
- Implemented `call` directive to call a group of sounds.
|
|
41
|
+
- Implemented `spawn` directive to spawn a group of sounds in parallel.
|
|
42
|
+
- Implemented `sleep` directive to pause execution for a specified duration.
|
|
43
|
+
- Patched line and column tracking in the lexer to ensure correct indentation handling.
|
|
44
|
+
- Patched string lexing advancing to handle first character correctly.
|
|
45
|
+
|
|
7
46
|
## Version 0.0.1-alpha.5 (2025-07-05)
|
|
8
47
|
|
|
9
48
|
### Syntax
|
package/docs/ROADMAP.md
CHANGED
|
@@ -24,8 +24,8 @@ Devalang is a work in progress. Here’s what we’re planning next:
|
|
|
24
24
|
|
|
25
25
|
## Upcoming
|
|
26
26
|
|
|
27
|
+
- ⏳ **Smart modules**: Let Devalang detect and use groups, samples, and variables without needing to import them manually.
|
|
27
28
|
- ⏳ **VSCode extension**: Create a VSCode extension for syntax highlighting and code completion.
|
|
28
|
-
- ⏳ **Other statements**: Implement `
|
|
29
|
-
- ⏳ **Pattern and group statements**: Add support for `@pattern` and `@group` to organize code.
|
|
29
|
+
- ⏳ **Other statements**: Implement `pattern`, `function`, and other control structures.
|
|
30
30
|
- ⏳ **Functions**: Add support for defining and calling functions.
|
|
31
31
|
- ⏳ **Testing**: Expand test coverage for all features.
|
package/docs/SYNTAX.md
CHANGED
|
@@ -17,6 +17,18 @@ The engine uses indentation to define blocks, similar to Python. Each block must
|
|
|
17
17
|
<details>
|
|
18
18
|
<summary>Show available types</summary>
|
|
19
19
|
|
|
20
|
+
### Duration
|
|
21
|
+
|
|
22
|
+
Duration is defined using a number. It represents the length of a sound in milliseconds.
|
|
23
|
+
|
|
24
|
+
```deva
|
|
25
|
+
let duration = 1000
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Will play a sound for 1000 milliseconds (1 second).
|
|
29
|
+
|
|
30
|
+
NOTE: Other time units like seconds or beats are not supported yet, but will be in the future.
|
|
31
|
+
|
|
20
32
|
### String
|
|
21
33
|
|
|
22
34
|
Strings are defined using double quotes.
|
|
@@ -46,7 +58,7 @@ let boolean = false
|
|
|
46
58
|
Maps are key-value pairs defined using curly braces. Keys are strings, and values can be of any type (string, number, boolean, map, or array).
|
|
47
59
|
|
|
48
60
|
```deva
|
|
49
|
-
let map = {myKey: 99}
|
|
61
|
+
let map = { myKey: 99 }
|
|
50
62
|
```
|
|
51
63
|
|
|
52
64
|
### Array
|
|
@@ -81,13 +93,17 @@ bank 808
|
|
|
81
93
|
|
|
82
94
|
Modules can be imported and exported to share variables between different files.
|
|
83
95
|
|
|
96
|
+
> ⚠️ The import/export system is still experimental and may change in the future.
|
|
97
|
+
>
|
|
98
|
+
> You must explicitly declare imports and exports in each file — Devalang does not automatically detect or resolve them.
|
|
99
|
+
|
|
84
100
|
Exporting variables from a module :
|
|
85
101
|
|
|
86
102
|
```deva
|
|
87
103
|
# exported.deva
|
|
88
104
|
|
|
89
105
|
let exportedIterator = 10
|
|
90
|
-
let exportedParams = {drive: 50, decay: 30}
|
|
106
|
+
let exportedParams = { drive: 50, decay: 30 }
|
|
91
107
|
|
|
92
108
|
@export { exportedIterator, exportedParams }
|
|
93
109
|
```
|
|
@@ -103,22 +119,13 @@ loop exportedIterator:
|
|
|
103
119
|
.kick auto exportedParams
|
|
104
120
|
```
|
|
105
121
|
|
|
106
|
-
###
|
|
107
|
-
|
|
108
|
-
Usage : `.<trigger-name> <duration> <effects-map>`
|
|
122
|
+
### Loading Samples
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
You can also create custom triggers using the `@load` directive.
|
|
112
|
-
|
|
113
|
-
```deva
|
|
114
|
-
.kick
|
|
115
|
-
.kick 1/4
|
|
116
|
-
.kick auto {reverb: 50, decay: 30}
|
|
117
|
-
```
|
|
124
|
+
You can load your own samples and use them in your music.
|
|
118
125
|
|
|
119
|
-
|
|
126
|
+
Load usage : `@load <path> as <name>`
|
|
120
127
|
|
|
121
|
-
|
|
128
|
+
Trigger usage : `.<name> <duration> <params>`
|
|
122
129
|
|
|
123
130
|
```deva
|
|
124
131
|
@load "./path/to/instrument.mp3" as mySample
|
|
@@ -126,7 +133,7 @@ Same usage as built-in triggers, but with custom audio files or effects.
|
|
|
126
133
|
.mySample auto {reverb: 50, drive: 25}
|
|
127
134
|
```
|
|
128
135
|
|
|
129
|
-
###
|
|
136
|
+
### Variables
|
|
130
137
|
|
|
131
138
|
Variables are defined using the `let` keyword, followed by the variable name and its value. The value can be of any type (string, number, boolean, map, or array).
|
|
132
139
|
|
|
@@ -134,11 +141,11 @@ Variables are defined using the `let` keyword, followed by the variable name and
|
|
|
134
141
|
let number = 0
|
|
135
142
|
let boolean = true
|
|
136
143
|
let string = "string"
|
|
137
|
-
let map = {myKey: 200}
|
|
144
|
+
let map = { myKey: 200 }
|
|
138
145
|
let array = [0, 1, 2]
|
|
139
146
|
```
|
|
140
147
|
|
|
141
|
-
###
|
|
148
|
+
### Loops
|
|
142
149
|
|
|
143
150
|
Loops are defined using the `loop` keyword, followed by the number of iterations. The body of the loop is indented.
|
|
144
151
|
|
|
@@ -146,3 +153,58 @@ Loops are defined using the `loop` keyword, followed by the number of iterations
|
|
|
146
153
|
loop 10:
|
|
147
154
|
# ...
|
|
148
155
|
```
|
|
156
|
+
|
|
157
|
+
### Groups
|
|
158
|
+
|
|
159
|
+
Groups are defined using the `group` keyword, followed by the group name. The body of the group is indented.
|
|
160
|
+
|
|
161
|
+
Groups allow you to organize your code into reusable blocks. They can be called or spawned later in the code.
|
|
162
|
+
|
|
163
|
+
```deva
|
|
164
|
+
group myGroup:
|
|
165
|
+
# ...
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Conditions
|
|
169
|
+
|
|
170
|
+
Conditions are defined using the `if` keyword, followed by a condition. The body of the condition is indented.
|
|
171
|
+
|
|
172
|
+
```deva
|
|
173
|
+
if myCondition:
|
|
174
|
+
# ...
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
You can also use `else` and `else if` for alternative branches:
|
|
178
|
+
|
|
179
|
+
```deva
|
|
180
|
+
if myCondition:
|
|
181
|
+
# ...
|
|
182
|
+
else if anotherCondition:
|
|
183
|
+
# ...
|
|
184
|
+
else:
|
|
185
|
+
# ...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Calling Groups (Sequential Execution)
|
|
189
|
+
|
|
190
|
+
Groups can be called using the `call` keyword, which executes only the group in sequence.
|
|
191
|
+
|
|
192
|
+
> ⚠️ `call` only works on `group` declarations. It does not apply to other statements.
|
|
193
|
+
|
|
194
|
+
This executes the entire group in the current execution thread, following a sequential order.
|
|
195
|
+
|
|
196
|
+
```deva
|
|
197
|
+
call myGroup
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Spawning Groups (Parallel Execution)
|
|
201
|
+
|
|
202
|
+
Groups can be spawned using the `spawn` keyword, which executes only the group in parallel.
|
|
203
|
+
|
|
204
|
+
> ⚠️ spawn also only works on group declarations. It does not make the group’s content parallel unless it explicitly uses spawn inside.
|
|
205
|
+
|
|
206
|
+
This runs the entire group in a separate execution thread, allowing it to play alongside other actions.
|
|
207
|
+
|
|
208
|
+
```deva
|
|
209
|
+
spawn myGroup
|
|
210
|
+
```
|
package/docs/TODO.md
CHANGED
|
@@ -42,18 +42,21 @@ This is a list of tasks and features to be implemented in Devalang. Note that th
|
|
|
42
42
|
- [x] #
|
|
43
43
|
- [x] @import
|
|
44
44
|
- [x] @export
|
|
45
|
-
- [ ] @group
|
|
46
|
-
- [ ] @pattern
|
|
47
|
-
- [ ] @function
|
|
48
45
|
- [x] @load
|
|
49
46
|
- [ ] @include
|
|
47
|
+
- [ ] function
|
|
48
|
+
- [ ] pattern
|
|
49
|
+
- [x] group
|
|
50
|
+
- [x] call
|
|
51
|
+
- [x] spawn
|
|
52
|
+
- [x] sleep
|
|
50
53
|
- [x] bpm
|
|
51
54
|
- [x] bank
|
|
52
55
|
- [x] loop
|
|
53
56
|
- [x] let
|
|
54
|
-
- [
|
|
55
|
-
- [
|
|
56
|
-
- [
|
|
57
|
+
- [x] if
|
|
58
|
+
- [x] else
|
|
59
|
+
- [x] else if
|
|
57
60
|
|
|
58
61
|
## Triggers
|
|
59
62
|
|
|
@@ -62,8 +65,6 @@ This is a list of tasks and features to be implemented in Devalang. Note that th
|
|
|
62
65
|
|
|
63
66
|
## Other TODOs
|
|
64
67
|
|
|
65
|
-
- [
|
|
66
|
-
- [
|
|
67
|
-
- [
|
|
68
|
-
- [ ] Add unit tests for all core components
|
|
69
|
-
- [ ] Comment all core components
|
|
68
|
+
- [ ] Patch path handling to support relative paths
|
|
69
|
+
- [ ] Comment all core components
|
|
70
|
+
- [ ] Add unit tests for all core components
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# This file demonstrates the use of conditional blocks in Devalang.
|
|
2
|
+
|
|
3
|
+
@import { myGroup } from "./examples/group.deva"
|
|
4
|
+
|
|
5
|
+
@load "./examples/samples/kick-808.wav" as kickCustom
|
|
6
|
+
@load "./examples/samples/hat-808.wav" as hatCustom
|
|
7
|
+
|
|
8
|
+
group conditionBlock:
|
|
9
|
+
if tempo > 120:
|
|
10
|
+
# Will be executed if the condition is true
|
|
11
|
+
.kickCustom
|
|
12
|
+
else if tempo > 155:
|
|
13
|
+
# Will be executed if the condition is false
|
|
14
|
+
.hatCustom
|
|
15
|
+
else:
|
|
16
|
+
# Following lines will be executed if the condition is neither true or false
|
|
17
|
+
|
|
18
|
+
# This will call myGroup sequentially (in the main thread)
|
|
19
|
+
call myGroup
|
|
20
|
+
|
|
21
|
+
# This will spawn a group in parallel to the main thread (kick + hat simultaneously)
|
|
22
|
+
# spawn myGroup
|
|
23
|
+
|
|
24
|
+
@export { conditionBlock }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# This file demonstrates the use of grouping in Devalang.
|
|
2
|
+
|
|
3
|
+
@import { duration, default_bank, params, loopCount, tempo } from "./examples/variables.deva"
|
|
4
|
+
|
|
5
|
+
@load "./examples/samples/kick-808.wav" as kickCustom
|
|
6
|
+
@load "./examples/samples/hat-808.wav" as hatCustom
|
|
7
|
+
|
|
8
|
+
group myGroup:
|
|
9
|
+
.kickCustom duration params
|
|
10
|
+
.hatCustom duration params
|
|
11
|
+
|
|
12
|
+
@export { myGroup }
|
package/examples/index.deva
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
# This file demonstrates the use of main features in Devalang.
|
|
2
|
+
|
|
3
|
+
@import { duration, default_bank, params, loopCount, tempo } from "./examples/variables.deva"
|
|
4
|
+
@import { conditionBlock } from "./examples/condition.deva"
|
|
5
|
+
@import { myGroup } from "./examples/group.deva"
|
|
6
|
+
|
|
2
7
|
|
|
3
8
|
@load "./examples/samples/kick-808.wav" as kickCustom
|
|
4
9
|
@load "./examples/samples/hat-808.wav" as hatCustom
|
|
@@ -7,11 +12,5 @@ bpm tempo
|
|
|
7
12
|
|
|
8
13
|
bank default_bank
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# Uncomment the next line (.hat) while executing "play" command
|
|
14
|
-
# with `--repeat` option to see magic happen !
|
|
15
|
-
|
|
16
|
-
# .hatCustom duration params
|
|
17
|
-
|
|
15
|
+
# This will call the group sequentially (line by line)
|
|
16
|
+
call conditionBlock
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# This file demonstrates the use of a loop in Devalang.
|
|
2
|
+
|
|
3
|
+
@import { duration, default_bank, params, loopCount, tempo } from "./examples/variables.deva"
|
|
4
|
+
|
|
5
|
+
@load "./examples/samples/kick-808.wav" as kickCustom
|
|
6
|
+
@load "./examples/samples/hat-808.wav" as hatCustom
|
|
7
|
+
|
|
8
|
+
loop loopCount:
|
|
9
|
+
.kickCustom duration params
|
|
10
|
+
|
|
11
|
+
# Uncomment the next line (.hat) while executing "play" command
|
|
12
|
+
# with `--repeat` option to see magic happen !
|
|
13
|
+
|
|
14
|
+
.hatCustom duration params
|
|
15
|
+
|
package/out-tsc/bin/devalang.exe
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@devaloop/devalang",
|
|
3
|
-
"private": false,
|
|
4
|
-
"version": "0.0.1-alpha.
|
|
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
|
-
"main": "out-tsc/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"devalang": "./out-tsc/bin/index.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"prepublish": "cargo build --release && npm run script:postbuild",
|
|
12
|
-
"rust:dev:build": "cargo run build --entry examples --output output",
|
|
13
|
-
"rust:dev:check": "cargo run check --entry examples --output output",
|
|
14
|
-
"rust:wasm:web": "wasm-pack build --target=web --no-default-features",
|
|
15
|
-
"rust:wasm:node": "wasm-pack build --target=nodejs --no-default-features",
|
|
16
|
-
"script:postbuild": "tsc && node out-tsc/scripts/postbuild.js",
|
|
17
|
-
"script:version:bump": "tsc && node out-tsc/scripts/version/index.js"
|
|
18
|
-
},
|
|
19
|
-
"homepage": "https://devalang.com",
|
|
20
|
-
"keywords": [
|
|
21
|
-
"devalang",
|
|
22
|
-
"music",
|
|
23
|
-
"sound",
|
|
24
|
-
"domain-specific language",
|
|
25
|
-
"dsl",
|
|
26
|
-
"programming language",
|
|
27
|
-
"sound design",
|
|
28
|
-
"music hacking",
|
|
29
|
-
"audio",
|
|
30
|
-
"synthesis",
|
|
31
|
-
"scripting",
|
|
32
|
-
"sound synthesis",
|
|
33
|
-
"music programming"
|
|
34
|
-
],
|
|
35
|
-
"author": "Devaloop",
|
|
36
|
-
"license": "MIT",
|
|
37
|
-
"repository": {
|
|
38
|
-
"type": "git",
|
|
39
|
-
"url": "https://github.com/devaloop-labs/devalang.git"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@types/node": "^24.0.3"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@devaloop/devalang",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.0.1-alpha.8",
|
|
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
|
+
"main": "out-tsc/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"devalang": "./out-tsc/bin/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"prepublish": "cargo build --release && npm run script:postbuild",
|
|
12
|
+
"rust:dev:build": "cargo run build --entry examples --output output",
|
|
13
|
+
"rust:dev:check": "cargo run check --entry examples --output output",
|
|
14
|
+
"rust:wasm:web": "wasm-pack build --target=web --no-default-features",
|
|
15
|
+
"rust:wasm:node": "wasm-pack build --target=nodejs --no-default-features",
|
|
16
|
+
"script:postbuild": "tsc && node out-tsc/scripts/postbuild.js",
|
|
17
|
+
"script:version:bump": "tsc && node out-tsc/scripts/version/index.js"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://devalang.com",
|
|
20
|
+
"keywords": [
|
|
21
|
+
"devalang",
|
|
22
|
+
"music",
|
|
23
|
+
"sound",
|
|
24
|
+
"domain-specific language",
|
|
25
|
+
"dsl",
|
|
26
|
+
"programming language",
|
|
27
|
+
"sound design",
|
|
28
|
+
"music hacking",
|
|
29
|
+
"audio",
|
|
30
|
+
"synthesis",
|
|
31
|
+
"scripting",
|
|
32
|
+
"sound synthesis",
|
|
33
|
+
"music programming"
|
|
34
|
+
],
|
|
35
|
+
"author": "Devaloop",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/devaloop-labs/devalang.git"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@types/node": "^24.0.3"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/project-version.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "0.0.1-alpha.
|
|
3
|
-
"channel": "alpha",
|
|
4
|
-
"lastCommit": "
|
|
5
|
-
"build":
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1-alpha.8",
|
|
3
|
+
"channel": "alpha",
|
|
4
|
+
"lastCommit": "fdb440173acc82227067864903aabc83e1d1570c",
|
|
5
|
+
"build": 7
|
|
6
6
|
}
|
package/rust/cli/build.rs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
use crate::{
|
|
2
|
-
audio::render::render_audio_with_modules,
|
|
3
2
|
config::Config,
|
|
4
3
|
core::{
|
|
5
4
|
builder::Builder,
|
|
6
|
-
debugger::{
|
|
5
|
+
debugger::{
|
|
6
|
+
lexer::write_lexer_log_file,
|
|
7
|
+
preprocessor::write_preprocessor_log_file,
|
|
8
|
+
store::write_store_log_file,
|
|
9
|
+
},
|
|
7
10
|
preprocessor::loader::ModuleLoader,
|
|
8
11
|
store::global::GlobalStore,
|
|
9
12
|
utils::path::{ find_entry_file, normalize_path },
|
|
@@ -114,6 +117,7 @@ fn begin_build(entry: String, output: String) {
|
|
|
114
117
|
"resolved_statements.log",
|
|
115
118
|
modules_statements.clone()
|
|
116
119
|
);
|
|
120
|
+
write_store_log_file(&normalized_output_dir, "global_store.log", global_store.modules.clone());
|
|
117
121
|
|
|
118
122
|
// SECTION Building AST and Audio
|
|
119
123
|
let builder = Builder::new();
|
package/rust/cli/play.rs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
use crate::{
|
|
2
|
-
audio::player::AudioPlayer,
|
|
3
2
|
config::Config,
|
|
4
3
|
core::{
|
|
5
4
|
builder::Builder,
|
|
@@ -23,6 +22,8 @@ pub fn handle_play_command(
|
|
|
23
22
|
watch: bool,
|
|
24
23
|
repeat: bool
|
|
25
24
|
) {
|
|
25
|
+
use crate::core::audio::player::AudioPlayer;
|
|
26
|
+
|
|
26
27
|
let logger = Logger::new();
|
|
27
28
|
|
|
28
29
|
let entry_path = entry
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
use crate::core::{ shared::value::Value, store::variable::VariableTable };
|
|
2
|
+
|
|
3
|
+
pub fn evaluate_condition_string(expr: &str, vars: &VariableTable) -> bool {
|
|
4
|
+
let tokens: Vec<&str> = expr.split_whitespace().collect();
|
|
5
|
+
if tokens.len() != 3 {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let left = tokens[0];
|
|
10
|
+
let op = tokens[1];
|
|
11
|
+
let right = tokens[2];
|
|
12
|
+
|
|
13
|
+
let left_val = match vars.get(left) {
|
|
14
|
+
Some(Value::Number(n)) => *n,
|
|
15
|
+
_ => {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
let right_val: f32 = right.parse().unwrap_or(0.0);
|
|
21
|
+
|
|
22
|
+
match op {
|
|
23
|
+
">" => left_val > right_val,
|
|
24
|
+
"<" => left_val < right_val,
|
|
25
|
+
">=" => left_val >= right_val,
|
|
26
|
+
"<=" => left_val <= right_val,
|
|
27
|
+
"==" => (left_val - right_val).abs() < f32::EPSILON,
|
|
28
|
+
"!=" => (left_val - right_val).abs() > f32::EPSILON,
|
|
29
|
+
_ => false,
|
|
30
|
+
}
|
|
31
|
+
}
|