@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
package/docs/ROADMAP.md CHANGED
@@ -6,7 +6,11 @@
6
6
 
7
7
  Devalang is a work in progress. Here’s what we’re planning next:
8
8
 
9
+ ## Completed
10
+
11
+ - ✅ **Audio engine**: Integrate the audio engine for sound playback.
9
12
  - ✅ **Basic syntax**: Implement the core syntax for Devalang, including data types and basic statements.
13
+ - ✅ **Watch mode**: Add a watch mode to automatically rebuild on file changes.
10
14
  - ✅ **Module system**: Add support for importing and exporting variables between files using `@import` and `@export`.
11
15
  - ✅ **AST generation**: Implement the Abstract Syntax Tree (AST) generation for debugging and future compilation.
12
16
  - ✅ **Basic data types**: Support strings, numbers, booleans, maps, and arrays.
@@ -16,12 +20,11 @@ Devalang is a work in progress. Here’s what we’re planning next:
16
20
  - ✅ **Instruction calls**: Add support for instruction calls with parameters (e.g. `.kick auto {reverb:10, decay:20}`).
17
21
  - ✅ **Let assignments**: Implement `let` assignments for storing reusable values.
18
22
  - ✅ **Sample loading**: Add `@load` assignment to load samples (.mp3, .wav) for use as values.
23
+ - ✅ **WASM support**: Compile Devalang to WebAssembly for use in web applications and other environments.
24
+ - ✅ **VSCode extension**: Create a VSCode extension for syntax highlighting and code completion.
25
+
26
+ ## Upcoming
19
27
 
20
- - ⏳ **VSCode extension**: Create a VSCode extension for syntax highlighting and code completion.
21
- - ⏳ **WASM support**: Compile Devalang to WebAssembly for use in web applications.
22
- - ⏳ **Other statements**: Implement `if`, `else`, and other control structures.
23
- - ⏳ **Pattern and group statements**: Add support for `@pattern` and `@group` to organize code.
24
- - ⏳ **Watch mode**: Add a watch mode to automatically rebuild on file changes.
25
- - ⏳ **Functions**: Add support for defining and calling functions.
26
- - ⏳ **Audio engine**: Integrate the audio engine for sound playback.
28
+ - ⏳ **Smart modules**: Let Devalang detect and use groups, samples, and variables without needing to import them manually.
29
+ - ⏳ **Other statements**: Implement `pattern`, `function`, and other control structures.
27
30
  - ⏳ **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
- ### Built-in triggers
107
-
108
- Usage : `.<trigger-name> <duration> <effects-map>`
122
+ ### Loading Samples
109
123
 
110
- Other triggers will be added in future releases (e.g. `.snare`, `.hihat`, `.tom`, `.clap`, `.crash`, `.ride`, `.synth`, `.bass`, `.pad`).
111
- You can also create custom triggers using the `@load` directive.
124
+ You can load your own samples and use them in your music.
112
125
 
113
- ```deva
114
- .kick
115
- .kick 1/4
116
- .kick auto {reverb: 50, decay: 30}
117
- ```
126
+ Load usage : `@load <path> as <name>`
118
127
 
119
- ### Custom triggers
120
-
121
- Same usage as built-in triggers, but with custom audio files or effects.
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
- ### Let variables
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
- ### Basic loops
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,78 @@ 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
+ ```
211
+
212
+ ### Synthesizers
213
+
214
+ Synthesizers are defined using the `synth` keyword, followed by the synthesizer type. You can create a synthesizer instance and use it to play notes.
215
+
216
+ ```deva
217
+ let mySynth = synth sine
218
+
219
+ mySynth -> note(C4, { duration: 400 })
220
+ mySynth -> note(G4, { duration: 400 })
221
+ mySynth -> note(E4, { duration: 600 })
222
+ mySynth -> note(A4, { duration: 400 })
223
+ mySynth -> note(F4, { duration: 800 })
224
+ mySynth -> note(D4, { duration: 400 })
225
+ mySynth -> note(B3, { duration: 600 })
226
+
227
+ # You can use call or spawn to execute the synthesizer actions in sequence or parallel.
228
+
229
+ call mySynth
230
+ ```
package/docs/TODO.md CHANGED
@@ -8,26 +8,29 @@ This is a list of tasks and features to be implemented in Devalang. Note that th
8
8
 
9
9
  ## Commands
10
10
 
11
- - [ ] New project
12
- - [ ] Template
13
- - [ ] Implement template list
14
- - [ ] Implement template info
11
+ - [x] Init project
12
+ - [x] Implement init command
13
+ - [x] Implement template selector
14
+ - [ ] Implement project name validation
15
+ - [x] Template
16
+ - [x] Implement template list
17
+ - [x] Implement template info
15
18
  - [x] Checking
16
- - [ ] Implement watch mode
19
+ - [x] Implement watch mode
17
20
  - [ ] Implement debug mode
18
21
  - [ ] Implement compilation mode
19
22
  - [x] Building
20
- - [ ] Implement watch mode
23
+ - [x] Implement watch mode
21
24
  - [ ] Implement debug mode
22
25
  - [ ] Implement compilation mode
23
26
  - [ ] Implement compression mode
24
- - [ ] Play
25
- - [ ] Implement Audio Engine
26
- - [ ] Implement loop mode
27
+ - [x] Play
28
+ - [x] Implement Audio Engine
29
+ - [x] Implement loop mode
27
30
 
28
31
  ## Core components
29
32
 
30
- - [ ] Audio Engine
33
+ - [x] Audio Engine
31
34
  - [x] Lexer
32
35
  - [x] Parser
33
36
  - [x] Preprocessor
@@ -36,31 +39,31 @@ This is a list of tasks and features to be implemented in Devalang. Note that th
36
39
 
37
40
  ## Syntax elements
38
41
 
39
- - [ ] #
42
+ - [x] #
40
43
  - [x] @import
41
44
  - [x] @export
42
- - [ ] @group
43
- - [ ] @pattern
44
- - [ ] @function
45
45
  - [x] @load
46
46
  - [ ] @include
47
+ - [ ] function
48
+ - [ ] pattern
49
+ - [x] group
50
+ - [x] call
51
+ - [x] spawn
52
+ - [x] sleep
47
53
  - [x] bpm
48
54
  - [x] bank
49
55
  - [x] loop
50
56
  - [x] let
51
- - [ ] if
52
- - [ ] else
53
- - [ ] else if
57
+ - [x] if
58
+ - [x] else
59
+ - [x] else if
54
60
 
55
- ## Built-in triggers
61
+ ## Triggers
56
62
 
57
- - [x] .kick
58
- - [ ] .snare
59
- - [ ] .hihat
60
- - [ ] .tom
61
- - [ ] .clap
62
- - [ ] .crash
63
- - [ ] .ride
64
- - [ ] .synth
65
- - [ ] .bass
66
- - [ ] .pad
63
+ - [x] Built-in triggers
64
+ - [x] Custom triggers
65
+
66
+ ## Other TODOs
67
+
68
+ - [ ] Comment all core components
69
+ - [ ] Add unit tests for all core components
@@ -0,0 +1,20 @@
1
+ # This file demonstrates the use of conditional blocks in Devalang.
2
+
3
+ @import { duration, default_bank, params, loopCount, tempo } from "./variables.deva"
4
+ @import { myGroup } from "./group.deva"
5
+
6
+ @load "./samples/kick-808.wav" as kickCustom
7
+ @load "./samples/hat-808.wav" as hatCustom
8
+
9
+ group conditionBlock:
10
+ if tempo > 120:
11
+ # Will be executed if the condition is true
12
+ .kickCustom auto
13
+ else if tempo > 155:
14
+ # Will be executed if the condition is false
15
+ .hatCustom auto
16
+ else:
17
+ .kickCustom auto
18
+ .hatCustom auto
19
+
20
+ @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 "./variables.deva"
4
+
5
+ @load "./samples/kick-808.wav" as kickCustom
6
+ @load "./samples/hat-808.wav" as hatCustom
7
+
8
+ group myGroup:
9
+ .kickCustom duration params
10
+ .hatCustom duration params
11
+
12
+ @export { myGroup }
@@ -1,9 +1,18 @@
1
- @import { duration, default_bank, params, loopCount, tempo } from "./examples/exported.deva"
2
- @load "./examples/samples/kick-808.wav" as sample
1
+ # This file demonstrates the use of main features in Devalang.
2
+
3
+ @import { duration, default_bank, params, loopCount, tempo } from "./variables.deva"
4
+ @import { myLead } from "./synth.deva"
5
+ @import { myLoop } from "./loop.deva"
6
+
7
+ @load "./samples/kick-808.wav" as kickCustom
8
+ @load "./samples/hat-808.wav" as hatCustom
3
9
 
4
10
  bpm tempo
5
11
 
6
12
  bank default_bank
7
13
 
8
- loop loopCount:
9
- .sample duration params
14
+ group myTrack:
15
+ spawn myLoop
16
+ spawn myLead
17
+
18
+ call myTrack
@@ -0,0 +1,16 @@
1
+ # This file demonstrates the use of a loop in Devalang.
2
+
3
+ @import { duration, default_bank, params, loopCount, tempo } from "./variables.deva"
4
+
5
+ @load "./samples/kick-808.wav" as kickCustom
6
+ @load "./samples/hat-808.wav" as hatCustom
7
+
8
+ group myLoop:
9
+ loop loopCount:
10
+ .kickCustom duration params
11
+
12
+ # Uncomment the next line (.hatCustom) while executing "play" command
13
+ # with `--repeat` option to see magic happen !
14
+ # .hatCustom duration params
15
+
16
+ @export { myLoop }
Binary file
@@ -0,0 +1,14 @@
1
+ # This file defines a simple synth lead using Devalang's syntax.
2
+
3
+ group myLead:
4
+ let mySynth = synth sine
5
+
6
+ mySynth -> note(C4, { duration: 400 })
7
+ mySynth -> note(G4, { duration: 400 })
8
+ mySynth -> note(E4, { duration: 600 })
9
+ mySynth -> note(A4, { duration: 400 })
10
+ mySynth -> note(F4, { duration: 800 })
11
+ mySynth -> note(D4, { duration: 400 })
12
+ mySynth -> note(B3, { duration: 600 })
13
+
14
+ @export { myLead }
@@ -0,0 +1,9 @@
1
+ # This file only exports variables for use in other files.
2
+
3
+ let duration = auto
4
+ let default_bank = 808
5
+ let params = { decay: 10, delay: 30 }
6
+ let loopCount = 5
7
+ let tempo = 115
8
+
9
+ @export { duration, default_bank, params, loopCount, tempo }
Binary file
@@ -16,19 +16,15 @@ exports.fetchVersion = void 0;
16
16
  const fs_1 = __importDefault(require("fs"));
17
17
  const child_process_1 = require("child_process");
18
18
  const fetchVersion = (projectVersionPath) => __awaiter(void 0, void 0, void 0, function* () {
19
- // Lire le fichier
20
19
  const data = JSON.parse(fs_1.default.readFileSync(projectVersionPath, "utf-8"));
21
- // Incrémenter le numéro de build
22
20
  data.build = (data.build || 0) + 1;
23
- // Récupérer le dernier hash git
24
21
  try {
25
22
  const commit = (0, child_process_1.execSync)("git rev-parse HEAD").toString().trim();
26
23
  data.lastCommit = commit;
27
24
  }
28
25
  catch (err) {
29
- console.warn("⚠️ Impossible de récupérer le hash git.");
26
+ console.warn("⚠️ Unable to fetch git commit hash. Ensure you are in a git repository.");
30
27
  }
31
- // Écrire la mise à jour
32
28
  fs_1.default.writeFileSync(projectVersionPath, JSON.stringify(data, null, 2));
33
29
  });
34
30
  exports.fetchVersion = fetchVersion;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devaloop/devalang",
3
3
  "private": false,
4
- "version": "0.0.1-alpha.1",
4
+ "version": "0.0.1-alpha.10",
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
  "main": "out-tsc/index.js",
7
7
  "bin": {
@@ -9,13 +9,14 @@
9
9
  },
10
10
  "scripts": {
11
11
  "prepublish": "cargo build --release && npm run script:postbuild",
12
- "rust:dev": "cargo run",
13
12
  "rust:dev:build": "cargo run build --entry examples --output output",
14
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",
15
16
  "script:postbuild": "tsc && node out-tsc/scripts/postbuild.js",
16
17
  "script:version:bump": "tsc && node out-tsc/scripts/version/index.js"
17
18
  },
18
- "homepage": "https://devaloop.com",
19
+ "homepage": "https://devalang.com",
19
20
  "keywords": [
20
21
  "devalang",
21
22
  "music",
@@ -40,4 +41,4 @@
40
41
  "dependencies": {
41
42
  "@types/node": "^24.0.3"
42
43
  }
43
- }
44
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "0.0.1-alpha.1",
2
+ "version": "0.0.1-alpha.10",
3
3
  "channel": "alpha",
4
- "lastCommit": "",
5
- "build": 1
4
+ "lastCommit": "a3649180a74374e193198131f4192a15f67009a5",
5
+ "build": 9
6
6
  }
package/rust/cli/build.rs CHANGED
@@ -1,51 +1,137 @@
1
- use std::{ thread, time::Duration };
2
-
3
1
  use crate::{
2
+ config::Config,
4
3
  core::{
5
- builder::{ build_ast, write_ast_to_file },
6
- debugger::Debugger,
7
- preprocessor::module::load_all_modules,
4
+ builder::Builder,
5
+ debugger::{
6
+ lexer::write_lexer_log_file,
7
+ preprocessor::write_preprocessor_log_file,
8
+ store::write_store_log_file,
9
+ },
10
+ preprocessor::loader::ModuleLoader,
11
+ store::global::GlobalStore,
12
+ utils::path::{ find_entry_file, normalize_path },
8
13
  },
9
- runner::executer::execute_statements,
10
- utils::{ loader::with_spinner, logger::log_message, path::{ find_entry_file, normalize_path } },
14
+ utils::{ logger::{ LogLevel, Logger }, spinner::with_spinner, watcher::watch_directory },
11
15
  };
16
+ use std::{ thread, time::Duration };
17
+
18
+ #[cfg(feature = "cli")]
19
+ pub fn handle_build_command(
20
+ config: Option<Config>,
21
+ entry: Option<String>,
22
+ output: Option<String>,
23
+ watch: bool
24
+ ) {
25
+ let fetched_entry = if entry.is_none() {
26
+ config
27
+ .as_ref()
28
+ .and_then(|c| c.defaults.entry.clone())
29
+ .unwrap_or_else(|| "".to_string())
30
+ } else {
31
+ entry.clone().unwrap_or_else(|| "".to_string())
32
+ };
33
+
34
+ let fetched_output = if output.is_none() {
35
+ config
36
+ .as_ref()
37
+ .and_then(|c| c.defaults.output.clone())
38
+ .unwrap_or_else(|| "".to_string())
39
+ } else {
40
+ output.clone().unwrap_or_else(|| "".to_string())
41
+ };
42
+
43
+ let fetched_watch = if watch {
44
+ watch
45
+ } else {
46
+ config
47
+ .as_ref()
48
+ .and_then(|c| c.defaults.watch)
49
+ .unwrap_or(false)
50
+ };
51
+
52
+ let logger = Logger::new();
53
+
54
+ if fetched_entry.is_empty() {
55
+ logger.log_message(
56
+ LogLevel::Error,
57
+ "Entry path is not specified. Please provide a valid entry path."
58
+ );
59
+ std::process::exit(1);
60
+ }
61
+ if fetched_output.is_empty() {
62
+ logger.log_message(
63
+ LogLevel::Error,
64
+ "Output directory is not specified. Please provide a valid output directory."
65
+ );
66
+ std::process::exit(1);
67
+ }
12
68
 
13
- pub fn handle_build_command(entry: String, output: String) {
14
- let entry_file = find_entry_file(&entry).unwrap_or_else(|| {
15
- eprintln!("❌ index.deva not found in directory: {}", entry);
69
+ let entry_file = find_entry_file(&fetched_entry).unwrap_or_else(|| {
70
+ logger.log_message(
71
+ LogLevel::Error,
72
+ &format!("❌ index.deva not found in directory: {}", fetched_entry)
73
+ );
16
74
  std::process::exit(1);
17
75
  });
18
76
 
77
+ // SECTION Begin build
78
+ if fetched_watch {
79
+ begin_build(entry_file.clone(), fetched_output.clone());
80
+
81
+ logger.log_message(
82
+ LogLevel::Watcher,
83
+ &format!("Watching for changes in '{}'...", fetched_entry)
84
+ );
85
+
86
+ watch_directory(entry_file.clone(), move || {
87
+ logger.log_message(LogLevel::Watcher, "Detected changes, re-building...");
88
+
89
+ begin_build(entry_file.clone(), fetched_output.clone());
90
+ }).unwrap();
91
+ } else {
92
+ begin_build(entry_file.clone(), fetched_output.clone());
93
+ }
94
+ }
95
+
96
+ fn begin_build(entry: String, output: String) {
19
97
  let spinner = with_spinner("Building...", || {
20
98
  thread::sleep(Duration::from_millis(800));
21
99
  });
22
100
 
23
101
  let duration = std::time::Instant::now();
24
102
 
25
- let normalized_entry_file = normalize_path(&entry_file);
103
+ let normalized_entry_file = normalize_path(&entry);
26
104
  let normalized_output_dir = normalize_path(&output);
27
105
 
28
- let global_store = load_all_modules(&normalized_entry_file);
106
+ let mut global_store = GlobalStore::new();
107
+ let module_loader = ModuleLoader::new(&normalized_entry_file, &normalized_output_dir);
29
108
 
30
- if let Some(module) = global_store.modules.get(&normalized_entry_file) {
31
- let mut module_clone = module.clone();
109
+ // SECTION Load
110
+ // NOTE: We use modules in the build command, so we need to load them
111
+ let (modules_tokens, modules_statements) = module_loader.load_all_modules(&mut global_store);
32
112
 
33
- let resolved_statements = execute_statements(&mut module_clone);
113
+ // SECTION Write logs
114
+ write_lexer_log_file(&normalized_output_dir, "lexer_tokens.log", modules_tokens.clone());
115
+ write_preprocessor_log_file(
116
+ &normalized_output_dir,
117
+ "resolved_statements.log",
118
+ modules_statements.clone()
119
+ );
120
+ write_store_log_file(&normalized_output_dir, "global_store.log", global_store.modules.clone());
34
121
 
35
- let ast = build_ast(&resolved_statements);
122
+ // SECTION Building AST and Audio
123
+ let builder = Builder::new();
124
+ builder.build_ast(&modules_statements, &normalized_output_dir);
125
+ builder.build_audio(&modules_statements, &normalized_output_dir, &mut global_store);
36
126
 
37
- let ast_dir = format!("{}/json", normalized_output_dir.clone());
38
- write_ast_to_file(&ast, &ast_dir);
127
+ // SECTION Logging
128
+ let logger = Logger::new();
39
129
 
40
- let debugger = Debugger::new(&module_clone);
41
- let debug_dir = format!("{}/debug/", normalized_output_dir.clone());
42
- debugger.write_files(debug_dir.as_str(), resolved_statements);
130
+ let success_message = format!(
131
+ "Build completed successfully in {:.2?}. Output files written to: '{}'",
132
+ duration.elapsed(),
133
+ normalized_output_dir
134
+ );
43
135
 
44
- let success_message = format!(
45
- "Build completed successfully in {:.2?}. Output files written to: '{}'",
46
- duration.elapsed(),
47
- normalized_output_dir
48
- );
49
- log_message(&success_message, "SUCCESS");
50
- }
136
+ logger.log_message(LogLevel::Success, &success_message);
51
137
  }