@devaloop/devalang 0.0.1-alpha.2 → 0.0.1-alpha.3
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 +46 -46
- package/README.md +7 -6
- package/docs/CHANGELOG.md +11 -6
- package/docs/ROADMAP.md +5 -1
- package/docs/TODO.md +6 -31
- package/examples/exported.deva +1 -1
- package/examples/index.deva +1 -0
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +1 -2
- package/project-version.json +3 -3
- package/rust/cli/build.rs +57 -40
- package/rust/cli/check.rs +47 -111
- package/rust/cli/init.rs +1 -1
- package/rust/cli/mod.rs +174 -2
- package/rust/{utils/config.rs → config/loader.rs} +3 -2
- package/rust/{core/types/config.rs → config/mod.rs} +5 -5
- package/rust/core/builder/mod.rs +21 -27
- package/rust/core/debugger/lexer.rs +12 -0
- package/rust/core/debugger/mod.rs +12 -49
- package/rust/core/debugger/preprocessor.rs +23 -0
- package/rust/core/error/mod.rs +60 -0
- package/rust/core/lexer/{at.rs → handler/at.rs} +1 -1
- package/rust/core/lexer/{brace.rs → handler/brace.rs} +1 -1
- package/rust/core/lexer/{colon.rs → handler/colon.rs} +1 -1
- package/rust/core/lexer/{comment.rs → handler/comment.rs} +3 -3
- package/rust/core/lexer/{dot.rs → handler/dot.rs} +1 -1
- package/rust/core/lexer/{equal.rs → handler/equal.rs} +1 -1
- package/rust/core/lexer/{identifier.rs → handler/identifier.rs} +1 -1
- package/rust/core/lexer/{indent.rs → handler/indent.rs} +10 -5
- package/rust/core/lexer/handler/mod.rs +238 -0
- package/rust/core/lexer/{newline.rs → handler/newline.rs} +6 -10
- package/rust/core/lexer/{number.rs → handler/number.rs} +1 -1
- package/rust/core/lexer/handler/string.rs +66 -0
- package/rust/core/lexer/mod.rs +25 -14
- package/rust/core/lexer/token.rs +55 -0
- package/rust/core/mod.rs +5 -2
- package/rust/core/parser/handler/at.rs +166 -0
- package/rust/core/parser/handler/bank.rs +38 -0
- package/rust/core/parser/handler/dot.rs +112 -0
- package/rust/core/parser/handler/identifier.rs +134 -0
- package/rust/core/parser/handler/loop_.rs +55 -0
- package/rust/core/parser/handler/mod.rs +6 -0
- package/rust/core/parser/handler/tempo.rs +47 -0
- package/rust/core/parser/mod.rs +204 -166
- package/rust/core/parser/statement.rs +91 -0
- package/rust/core/preprocessor/loader.rs +105 -0
- package/rust/core/preprocessor/mod.rs +2 -24
- package/rust/core/preprocessor/module.rs +37 -56
- package/rust/core/preprocessor/processor.rs +41 -0
- package/rust/core/preprocessor/resolver.rs +372 -0
- package/rust/core/shared/duration.rs +8 -0
- package/rust/core/shared/mod.rs +2 -0
- package/rust/core/shared/value.rs +18 -0
- package/rust/core/store/export.rs +28 -0
- package/rust/core/store/global.rs +39 -0
- package/rust/core/store/import.rs +28 -0
- package/rust/core/store/mod.rs +4 -0
- package/rust/core/store/variable.rs +28 -0
- package/rust/core/utils/mod.rs +2 -0
- package/rust/core/utils/validation.rs +35 -0
- package/rust/lib.rs +0 -1
- package/rust/main.rs +17 -19
- package/rust/utils/logger.rs +69 -34
- package/rust/utils/mod.rs +3 -5
- package/templates/minimal/.devalang +1 -1
- package/templates/welcome/.devalang +1 -1
- package/rust/audio/mod.rs +0 -1
- package/rust/core/lexer/bracket.rs +0 -41
- package/rust/core/lexer/driver.rs +0 -286
- package/rust/core/lexer/quote.rs +0 -61
- package/rust/core/parser/at.rs +0 -142
- package/rust/core/parser/bank.rs +0 -42
- package/rust/core/parser/dot.rs +0 -137
- package/rust/core/parser/identifer.rs +0 -91
- package/rust/core/parser/loop_.rs +0 -62
- package/rust/core/parser/tempo.rs +0 -42
- package/rust/core/parser/variable.rs +0 -129
- package/rust/core/preprocessor/dependencies.rs +0 -54
- package/rust/core/preprocessor/resolver/at.rs +0 -24
- package/rust/core/preprocessor/resolver/bank.rs +0 -59
- package/rust/core/preprocessor/resolver/loop_.rs +0 -82
- package/rust/core/preprocessor/resolver/mod.rs +0 -113
- package/rust/core/preprocessor/resolver/tempo.rs +0 -70
- package/rust/core/preprocessor/resolver/trigger.rs +0 -176
- package/rust/core/types/cli.rs +0 -182
- package/rust/core/types/mod.rs +0 -8
- package/rust/core/types/module.rs +0 -41
- package/rust/core/types/parser.rs +0 -73
- package/rust/core/types/statement.rs +0 -105
- package/rust/core/types/store.rs +0 -116
- package/rust/core/types/token.rs +0 -83
- package/rust/core/types/variable.rs +0 -32
- package/rust/runner/executer.rs +0 -44
- package/rust/runner/mod.rs +0 -1
- /package/rust/{utils → core/utils}/path.rs +0 -0
- /package/rust/utils/{loader.rs → spinner.rs} +0 -0
package/Cargo.toml
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
[package]
|
|
2
|
-
name = "devalang"
|
|
3
|
-
version = "0.0.1-alpha.
|
|
4
|
-
authors = ["Devaloop <contact@devaloop.com>"]
|
|
5
|
-
description = "Write music like code. Devalang is a domain-specific language (DSL) for sound designers and music hackers. Compose, automate, and control sound — in plain text."
|
|
6
|
-
license = "MIT"
|
|
7
|
-
repository = "https://github.com/devaloop-labs/devalang"
|
|
8
|
-
keywords = ["music", "dsl", "audio", "cli"]
|
|
9
|
-
categories = ["command-line-utilities", "audio", "development-tools"]
|
|
10
|
-
readme = "README.md"
|
|
11
|
-
homepage = "https://devaloop.com"
|
|
12
|
-
documentation = "https://docs.rs/devalang"
|
|
13
|
-
edition = "2024"
|
|
14
|
-
|
|
15
|
-
[[bin]]
|
|
16
|
-
name = "devalang"
|
|
17
|
-
path = "rust/main.rs"
|
|
18
|
-
|
|
19
|
-
[lib]
|
|
20
|
-
path = "rust/lib.rs"
|
|
21
|
-
crate-type = ["cdylib"]
|
|
22
|
-
|
|
23
|
-
[profile.release]
|
|
24
|
-
opt-level = "s"
|
|
25
|
-
|
|
26
|
-
[features]
|
|
27
|
-
default = ["cli"]
|
|
28
|
-
cli = ["crossterm"]
|
|
29
|
-
|
|
30
|
-
[dependencies]
|
|
31
|
-
clap = { version = "4.5", features = ["derive"] }
|
|
32
|
-
serde = { version = "1.0", features = ["derive"] }
|
|
33
|
-
serde_json = "1.0"
|
|
34
|
-
rodio = "0.17"
|
|
35
|
-
hound = "3.4.0"
|
|
36
|
-
toml = "0.8"
|
|
37
|
-
notify = "6.1"
|
|
38
|
-
fs_extra = "1.3"
|
|
39
|
-
include_dir = "0.7"
|
|
40
|
-
wasm-bindgen = "0.2"
|
|
41
|
-
serde-wasm-bindgen = "0.4"
|
|
42
|
-
nom_locate = "4.0.0"
|
|
43
|
-
chrono = "0.4"
|
|
44
|
-
crossterm = { version = "0.27", optional = true }
|
|
45
|
-
indicatif = "0.17"
|
|
46
|
-
inquire = "0.7.5"
|
|
1
|
+
[package]
|
|
2
|
+
name = "devalang"
|
|
3
|
+
version = "0.0.1-alpha.3"
|
|
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", "audio", "development-tools"]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
homepage = "https://devaloop.com"
|
|
12
|
+
documentation = "https://docs.rs/devalang"
|
|
13
|
+
edition = "2024"
|
|
14
|
+
|
|
15
|
+
[[bin]]
|
|
16
|
+
name = "devalang"
|
|
17
|
+
path = "rust/main.rs"
|
|
18
|
+
|
|
19
|
+
[lib]
|
|
20
|
+
path = "rust/lib.rs"
|
|
21
|
+
crate-type = ["cdylib"]
|
|
22
|
+
|
|
23
|
+
[profile.release]
|
|
24
|
+
opt-level = "s"
|
|
25
|
+
|
|
26
|
+
[features]
|
|
27
|
+
default = ["cli"]
|
|
28
|
+
cli = ["crossterm"]
|
|
29
|
+
|
|
30
|
+
[dependencies]
|
|
31
|
+
clap = { version = "4.5", features = ["derive"] }
|
|
32
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
33
|
+
serde_json = "1.0"
|
|
34
|
+
rodio = "0.17"
|
|
35
|
+
hound = "3.4.0"
|
|
36
|
+
toml = "0.8"
|
|
37
|
+
notify = "6.1"
|
|
38
|
+
fs_extra = "1.3"
|
|
39
|
+
include_dir = "0.7"
|
|
40
|
+
wasm-bindgen = "0.2"
|
|
41
|
+
serde-wasm-bindgen = "0.4"
|
|
42
|
+
nom_locate = "4.0.0"
|
|
43
|
+
chrono = "0.4"
|
|
44
|
+
crossterm = { version = "0.27", optional = true }
|
|
45
|
+
indicatif = "0.17"
|
|
46
|
+
inquire = "0.7.5"
|
package/README.md
CHANGED
|
@@ -30,7 +30,6 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
30
30
|
>
|
|
31
31
|
> You can parse code, generate the AST, and validate syntax — all essential building blocks for the upcoming audio engine.
|
|
32
32
|
>
|
|
33
|
-
> Currently, only `.kick` is included as a built-in trigger.
|
|
34
33
|
> Custom instruments can be defined with `@load`, allowing any sound sample to be triggered with the same syntax.
|
|
35
34
|
>
|
|
36
35
|
> Currently, Devalang CLI is only available for **Windows**.
|
|
@@ -84,7 +83,9 @@ Usage for development (feel free to change arguments in package.json)
|
|
|
84
83
|
|
|
85
84
|
```bash
|
|
86
85
|
# For syntax checking test
|
|
87
|
-
npm run rust:dev
|
|
86
|
+
npm run rust:dev:check
|
|
87
|
+
# For building test
|
|
88
|
+
npm run rust:dev:build
|
|
88
89
|
```
|
|
89
90
|
|
|
90
91
|
## ❔ Usage
|
|
@@ -105,13 +106,13 @@ Or use optional arguments to specify a directory name and a template
|
|
|
105
106
|
devalang init --name <project-name> --template <template-name>
|
|
106
107
|
```
|
|
107
108
|
|
|
108
|
-
### Checking syntax only
|
|
109
|
+
### Checking syntax only
|
|
109
110
|
|
|
110
111
|
```bash
|
|
111
112
|
devalang check --entry <entry-directory> --output <output-directory> --watch
|
|
112
113
|
```
|
|
113
114
|
|
|
114
|
-
### Building output
|
|
115
|
+
### Building output files
|
|
115
116
|
|
|
116
117
|
```bash
|
|
117
118
|
devalang build --entry <entry-directory> --output <output-directory> --watch
|
|
@@ -160,13 +161,13 @@ let kickDuration = 500
|
|
|
160
161
|
- No support yet for Audio Engine
|
|
161
162
|
- No support yet for `if`, `else`, `else if` statements
|
|
162
163
|
- No support yet for `@group`, `@pattern`, `@function` statements
|
|
163
|
-
-
|
|
164
|
+
- No support yet for cross-platform builds (Linux, macOS)
|
|
164
165
|
|
|
165
166
|
## 🧪 Roadmap Highlights
|
|
166
167
|
|
|
167
168
|
For more info, see [docs/ROADMAP.md](./docs/ROADMAP.md)
|
|
168
169
|
|
|
169
|
-
- ⏳ Audio engine integration
|
|
170
|
+
- ⏳ Audio engine integration (priority for alpha.4)
|
|
170
171
|
- ⏳ Other statements (e.g `if`, `@group`, ...)
|
|
171
172
|
- ⏳ Cross-platform support (Linux, macOS)
|
|
172
173
|
- ⏳ More built-in instruments (e.g. snare, hi-hat, etc.)
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
-
## Version 0.0.1-alpha.
|
|
7
|
+
## Version 0.0.1-alpha.3 (2025-07-01)
|
|
8
|
+
|
|
9
|
+
- /!\ Major refactor of the project structure and module system /!\
|
|
10
|
+
- Refactored module system to support multiple modules and submodules.
|
|
11
|
+
- Patched all directives to be compatible with the new project structure.
|
|
12
|
+
- Prepared for the upcoming audio engine integration and sound rendering capabilities.
|
|
13
|
+
- Updated documentation to reflect the new project structure and features.
|
|
14
|
+
|
|
15
|
+
## Version 0.0.1-alpha.2 (2025-06-26)
|
|
8
16
|
|
|
9
17
|
### Commands
|
|
10
18
|
|
|
@@ -18,17 +26,14 @@
|
|
|
18
26
|
|
|
19
27
|
- Implemented Config manager to handle configuration files.
|
|
20
28
|
- Added support for `.devalang` configuration file as a TOML file.
|
|
21
|
-
- Added support for `--no-config` flag to disable configuration file usage.
|
|
22
29
|
- Implemented File System watcher to monitor file changes.
|
|
23
30
|
- Implemented Template manager to handle templates and their metadata.
|
|
24
|
-
- Refactored Lexer to support new syntax elements and directives.
|
|
25
31
|
|
|
26
32
|
### Syntax
|
|
27
33
|
|
|
28
|
-
- Added support for built-in triggers for `.snare`, `.hihat`, `.clap`, `.tom`, `.crash`, `.ride`.
|
|
29
|
-
- Added support for custom triggers with `@load` using the syntax `.trigger-name`.
|
|
34
|
+
- Added support for built-in triggers for `.snare`, `.hihat`, `.clap`, `.tom`, `.crash`, `.ride`, `.synth`, `.bass`, and `.pad`.
|
|
30
35
|
|
|
31
|
-
## Version 0.0.1-alpha.1 (
|
|
36
|
+
## Version 0.0.1-alpha.1 (2025-06-25)
|
|
32
37
|
|
|
33
38
|
### Syntax
|
|
34
39
|
|
package/docs/ROADMAP.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
Devalang is a work in progress. Here’s what we’re planning next:
|
|
8
8
|
|
|
9
|
+
### Stable
|
|
10
|
+
|
|
9
11
|
- ✅ **Basic syntax**: Implement the core syntax for Devalang, including data types and basic statements.
|
|
10
12
|
- ✅ **Watch mode**: Add a watch mode to automatically rebuild on file changes.
|
|
11
13
|
- ✅ **Module system**: Add support for importing and exporting variables between files using `@import` and `@export`.
|
|
@@ -18,10 +20,12 @@ Devalang is a work in progress. Here’s what we’re planning next:
|
|
|
18
20
|
- ✅ **Let assignments**: Implement `let` assignments for storing reusable values.
|
|
19
21
|
- ✅ **Sample loading**: Add `@load` assignment to load samples (.mp3, .wav) for use as values.
|
|
20
22
|
|
|
23
|
+
### Upcoming
|
|
24
|
+
|
|
25
|
+
- ⏳ **Audio engine**: Integrate the audio engine for sound playback.
|
|
21
26
|
- ⏳ **VSCode extension**: Create a VSCode extension for syntax highlighting and code completion.
|
|
22
27
|
- ⏳ **WASM support**: Compile Devalang to WebAssembly for use in web applications.
|
|
23
28
|
- ⏳ **Other statements**: Implement `if`, `else`, and other control structures.
|
|
24
29
|
- ⏳ **Pattern and group statements**: Add support for `@pattern` and `@group` to organize code.
|
|
25
30
|
- ⏳ **Functions**: Add support for defining and calling functions.
|
|
26
|
-
- ⏳ **Audio engine**: Integrate the audio engine for sound playback.
|
|
27
31
|
- ⏳ **Testing**: Expand test coverage for all features.
|
package/docs/TODO.md
CHANGED
|
@@ -31,7 +31,6 @@ This is a list of tasks and features to be implemented in Devalang. Note that th
|
|
|
31
31
|
## Core components
|
|
32
32
|
|
|
33
33
|
- [ ] Audio Engine
|
|
34
|
-
- [x] Configuration
|
|
35
34
|
- [x] Lexer
|
|
36
35
|
- [x] Parser
|
|
37
36
|
- [x] Preprocessor
|
|
@@ -58,37 +57,13 @@ This is a list of tasks and features to be implemented in Devalang. Note that th
|
|
|
58
57
|
|
|
59
58
|
## Triggers
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- [x] .kick
|
|
64
|
-
- [x] .snare
|
|
65
|
-
- [x] .hihat
|
|
66
|
-
- [x] .tom
|
|
67
|
-
- [x] .clap
|
|
68
|
-
- [x] .crash
|
|
69
|
-
- [x] .ride
|
|
70
|
-
|
|
71
|
-
### Instrument triggers
|
|
72
|
-
|
|
73
|
-
- [ ] .guitar
|
|
74
|
-
- [ ] .piano
|
|
75
|
-
- [ ] .flute
|
|
76
|
-
- [ ] .violin
|
|
77
|
-
|
|
78
|
-
### Synth & effects triggers
|
|
79
|
-
|
|
80
|
-
- [ ] .lead
|
|
81
|
-
- [ ] .bass
|
|
82
|
-
- [ ] .pad
|
|
83
|
-
- [ ] .arp
|
|
84
|
-
- [ ] .fx
|
|
85
|
-
- [ ] .vocal
|
|
60
|
+
- [x] Built-in triggers
|
|
61
|
+
- [x] Custom triggers
|
|
86
62
|
|
|
87
63
|
## Other TODOs
|
|
88
64
|
|
|
89
|
-
- [
|
|
90
|
-
- [
|
|
91
|
-
- [
|
|
92
|
-
- [ ] Implement a more comprehensive logging system
|
|
65
|
+
- [x] Implement a more robust error handling system
|
|
66
|
+
- [x] Replace eprintln & println with `log_message` function
|
|
67
|
+
- [x] Implement a more comprehensive logging system
|
|
93
68
|
- [ ] Add unit tests for all core components
|
|
94
|
-
- [ ] Comment all core components
|
|
69
|
+
- [ ] Comment all core components
|
package/examples/exported.deva
CHANGED
package/examples/index.deva
CHANGED
package/out-tsc/bin/devalang.exe
CHANGED
|
Binary file
|
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.
|
|
4
|
+
"version": "0.0.1-alpha.3",
|
|
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,7 +9,6 @@
|
|
|
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",
|
|
15
14
|
"script:postbuild": "tsc && node out-tsc/scripts/postbuild.js",
|
package/project-version.json
CHANGED
package/rust/cli/build.rs
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
use std::{ thread, time::Duration };
|
|
2
|
-
|
|
3
1
|
use crate::{
|
|
2
|
+
config::Config,
|
|
4
3
|
core::{
|
|
5
|
-
builder::
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
runner::executer::execute_statements,
|
|
11
|
-
utils::{
|
|
12
|
-
loader::with_spinner,
|
|
13
|
-
logger::log_message,
|
|
14
|
-
path::{ find_entry_file, normalize_path },
|
|
15
|
-
watcher::watch_directory,
|
|
4
|
+
builder::Builder,
|
|
5
|
+
preprocessor::loader::ModuleLoader,
|
|
6
|
+
store::global::GlobalStore,
|
|
7
|
+
utils::path::{ find_entry_file, normalize_path },
|
|
16
8
|
},
|
|
9
|
+
utils::{ logger::{ LogLevel, Logger }, spinner::with_spinner, watcher::watch_directory },
|
|
17
10
|
};
|
|
11
|
+
use std::{ thread, time::Duration };
|
|
18
12
|
|
|
19
13
|
pub fn handle_build_command(
|
|
20
|
-
config: Option<
|
|
14
|
+
config: Option<Config>,
|
|
21
15
|
entry: Option<String>,
|
|
22
16
|
output: Option<String>,
|
|
23
17
|
watch: bool
|
|
@@ -49,26 +43,51 @@ pub fn handle_build_command(
|
|
|
49
43
|
.unwrap_or(false)
|
|
50
44
|
};
|
|
51
45
|
|
|
46
|
+
let logger = Logger::new();
|
|
47
|
+
|
|
48
|
+
if fetched_entry.is_empty() {
|
|
49
|
+
logger.log_message(
|
|
50
|
+
LogLevel::Error,
|
|
51
|
+
"Entry path is not specified. Please provide a valid entry path."
|
|
52
|
+
);
|
|
53
|
+
std::process::exit(1);
|
|
54
|
+
}
|
|
55
|
+
if fetched_output.is_empty() {
|
|
56
|
+
logger.log_message(
|
|
57
|
+
LogLevel::Error,
|
|
58
|
+
"Output directory is not specified. Please provide a valid output directory."
|
|
59
|
+
);
|
|
60
|
+
std::process::exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
52
63
|
let entry_file = find_entry_file(&fetched_entry).unwrap_or_else(|| {
|
|
53
|
-
|
|
64
|
+
logger.log_message(
|
|
65
|
+
LogLevel::Error,
|
|
66
|
+
&format!("❌ index.deva not found in directory: {}", fetched_entry)
|
|
67
|
+
);
|
|
54
68
|
std::process::exit(1);
|
|
55
69
|
});
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
71
|
+
// SECTION Begin build
|
|
72
|
+
if fetched_watch {
|
|
73
|
+
begin_build(entry_file.clone(), fetched_output.clone());
|
|
59
74
|
|
|
60
|
-
|
|
75
|
+
logger.log_message(
|
|
76
|
+
LogLevel::Watcher,
|
|
77
|
+
&format!("Watching for changes in '{}'...", fetched_entry)
|
|
78
|
+
);
|
|
61
79
|
|
|
62
80
|
watch_directory(entry_file.clone(), move || {
|
|
63
|
-
log_message("
|
|
64
|
-
|
|
81
|
+
logger.log_message(LogLevel::Watcher, "Detected changes, re-building...");
|
|
82
|
+
|
|
83
|
+
begin_build(entry_file.clone(), fetched_output.clone());
|
|
65
84
|
}).unwrap();
|
|
66
85
|
} else {
|
|
67
|
-
begin_build(entry_file.clone(), fetched_output.clone()
|
|
86
|
+
begin_build(entry_file.clone(), fetched_output.clone());
|
|
68
87
|
}
|
|
69
88
|
}
|
|
70
89
|
|
|
71
|
-
fn begin_build(entry: String, output: String
|
|
90
|
+
fn begin_build(entry: String, output: String) {
|
|
72
91
|
let spinner = with_spinner("Building...", || {
|
|
73
92
|
thread::sleep(Duration::from_millis(800));
|
|
74
93
|
});
|
|
@@ -78,27 +97,25 @@ fn begin_build(entry: String, output: String, watch: bool) {
|
|
|
78
97
|
let normalized_entry_file = normalize_path(&entry);
|
|
79
98
|
let normalized_output_dir = normalize_path(&output);
|
|
80
99
|
|
|
81
|
-
let global_store =
|
|
82
|
-
|
|
83
|
-
if let Some(module) = global_store.modules.get(&normalized_entry_file) {
|
|
84
|
-
let mut module_clone = module.clone();
|
|
100
|
+
let mut global_store = GlobalStore::new();
|
|
101
|
+
let module_loader = ModuleLoader::new(&normalized_entry_file, &normalized_output_dir);
|
|
85
102
|
|
|
86
|
-
|
|
103
|
+
// SECTION Load
|
|
104
|
+
// NOTE: We use modules in the build command, so we need to load them
|
|
105
|
+
let modules = module_loader.load_all(&mut global_store);
|
|
87
106
|
|
|
88
|
-
|
|
107
|
+
// SECTION Build
|
|
108
|
+
let builder = Builder::new();
|
|
109
|
+
builder.build_ast(&modules);
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
write_ast_to_file(&ast, &ast_dir);
|
|
111
|
+
// TODO: Implement debugging
|
|
92
112
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
113
|
+
let success_message = format!(
|
|
114
|
+
"Build completed successfully in {:.2?}. Output files written to: '{}'",
|
|
115
|
+
duration.elapsed(),
|
|
116
|
+
normalized_output_dir
|
|
117
|
+
);
|
|
96
118
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
duration.elapsed(),
|
|
100
|
-
normalized_output_dir
|
|
101
|
-
);
|
|
102
|
-
log_message(&success_message, "SUCCESS");
|
|
103
|
-
}
|
|
119
|
+
let logger = Logger::new();
|
|
120
|
+
logger.log_message(LogLevel::Success, &success_message);
|
|
104
121
|
}
|
package/rust/cli/check.rs
CHANGED
|
@@ -1,29 +1,20 @@
|
|
|
1
|
-
use std::{ thread, time::Duration };
|
|
2
|
-
|
|
3
1
|
use crate::{
|
|
2
|
+
config::Config,
|
|
4
3
|
core::{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
config::{ DevalangConfig },
|
|
9
|
-
statement::{ StatementKind, StatementResolved, StatementResolvedValue },
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
runner::executer::execute_statements,
|
|
13
|
-
utils::{
|
|
14
|
-
loader::with_spinner,
|
|
15
|
-
logger::log_message,
|
|
16
|
-
path::{ find_entry_file, normalize_path },
|
|
17
|
-
watcher::watch_directory,
|
|
4
|
+
preprocessor::loader::ModuleLoader,
|
|
5
|
+
store::global::GlobalStore,
|
|
6
|
+
utils::path::{ find_entry_file, normalize_path },
|
|
18
7
|
},
|
|
8
|
+
utils::{ logger::{ LogLevel, Logger }, spinner::with_spinner, watcher::watch_directory },
|
|
19
9
|
};
|
|
10
|
+
use std::{ thread, time::Duration };
|
|
20
11
|
|
|
21
12
|
pub fn handle_check_command(
|
|
22
|
-
config: Option<
|
|
13
|
+
config: Option<Config>,
|
|
23
14
|
entry: Option<String>,
|
|
24
15
|
output: Option<String>,
|
|
25
16
|
watch: bool
|
|
26
|
-
)
|
|
17
|
+
) {
|
|
27
18
|
let fetched_entry = if entry.is_none() {
|
|
28
19
|
config
|
|
29
20
|
.as_ref()
|
|
@@ -51,36 +42,51 @@ pub fn handle_check_command(
|
|
|
51
42
|
.unwrap_or(false)
|
|
52
43
|
};
|
|
53
44
|
|
|
45
|
+
let logger = Logger::new();
|
|
46
|
+
|
|
54
47
|
if fetched_entry.is_empty() {
|
|
55
|
-
|
|
48
|
+
logger.log_message(
|
|
49
|
+
LogLevel::Error,
|
|
50
|
+
"Entry path is not specified. Please provide a valid entry path."
|
|
51
|
+
);
|
|
56
52
|
std::process::exit(1);
|
|
57
53
|
}
|
|
58
|
-
|
|
59
54
|
if fetched_output.is_empty() {
|
|
60
|
-
|
|
55
|
+
logger.log_message(
|
|
56
|
+
LogLevel::Error,
|
|
57
|
+
"Output directory is not specified. Please provide a valid output directory."
|
|
58
|
+
);
|
|
61
59
|
std::process::exit(1);
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
let entry_file = find_entry_file(&fetched_entry).unwrap_or_else(|| {
|
|
65
|
-
|
|
63
|
+
logger.log_message(
|
|
64
|
+
LogLevel::Error,
|
|
65
|
+
&format!("❌ index.deva not found in directory: {}", fetched_entry)
|
|
66
|
+
);
|
|
66
67
|
std::process::exit(1);
|
|
67
68
|
});
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
// SECTION Begin check
|
|
71
|
+
if fetched_watch {
|
|
72
|
+
begin_check(entry_file.clone(), fetched_output.clone());
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
logger.log_message(
|
|
75
|
+
LogLevel::Watcher,
|
|
76
|
+
&format!("Watching for changes in '{}'...", fetched_entry)
|
|
77
|
+
);
|
|
73
78
|
|
|
74
79
|
watch_directory(entry_file.clone(), move || {
|
|
75
|
-
log_message("
|
|
76
|
-
|
|
80
|
+
logger.log_message(LogLevel::Watcher, "Detected changes, re-checking...");
|
|
81
|
+
|
|
82
|
+
begin_check(entry_file.clone(), fetched_output.clone());
|
|
77
83
|
}).unwrap();
|
|
78
84
|
} else {
|
|
79
|
-
begin_check(entry_file.clone(), fetched_output.clone()
|
|
85
|
+
begin_check(entry_file.clone(), fetched_output.clone());
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
fn begin_check(entry: String, output: String
|
|
89
|
+
fn begin_check(entry: String, output: String) {
|
|
84
90
|
let spinner = with_spinner("Checking...", || {
|
|
85
91
|
thread::sleep(Duration::from_millis(800));
|
|
86
92
|
});
|
|
@@ -90,91 +96,21 @@ fn begin_check(entry: String, output: String, watch: bool) {
|
|
|
90
96
|
let normalized_entry_file = normalize_path(&entry);
|
|
91
97
|
let normalized_output_dir = normalize_path(&output);
|
|
92
98
|
|
|
93
|
-
let global_store =
|
|
94
|
-
|
|
95
|
-
if let Some(module) = global_store.modules.get(&normalized_entry_file) {
|
|
96
|
-
let mut module_clone = module.clone();
|
|
97
|
-
|
|
98
|
-
let resolved_statements = execute_statements(&mut module_clone);
|
|
99
|
-
|
|
100
|
-
let debugger = Debugger::new(&module_clone);
|
|
101
|
-
let debug_dir = format!("{}/debug/", normalized_output_dir.clone());
|
|
102
|
-
debugger.write_files(debug_dir.as_str(), resolved_statements.clone());
|
|
99
|
+
let mut global_store = GlobalStore::new();
|
|
100
|
+
let module_loader = ModuleLoader::new(&normalized_entry_file, &normalized_output_dir);
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
// SECTION Load
|
|
103
|
+
// NOTE: We don't use modules in the check command, but we still need to load them
|
|
104
|
+
let modules = module_loader.load_all(&mut global_store);
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
let warning_message = format!(
|
|
110
|
-
"Check completed with errors in {:.2?}. Output files written to: '{}'",
|
|
111
|
-
duration.elapsed(),
|
|
112
|
-
normalized_output_dir
|
|
113
|
-
);
|
|
106
|
+
// TODO: Implement debugging
|
|
114
107
|
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
normalized_output_dir
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
log_message(&success_message, "SUCCESS");
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
fn match_error_recursively_resolved(stmt: &StatementResolved) -> bool {
|
|
129
|
-
match stmt.value.clone() {
|
|
130
|
-
// TODO Other statement value types here
|
|
131
|
-
|
|
132
|
-
StatementResolvedValue::Map(map) => {
|
|
133
|
-
for (key, value) in map {
|
|
134
|
-
if match_error_recursively_resolved_value(&value) {
|
|
135
|
-
return true;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
StatementResolvedValue::Array(array) => {
|
|
141
|
-
for item in array {
|
|
142
|
-
if match_error_recursively_resolved(&item) {
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
_ => {
|
|
149
|
-
if let StatementKind::Error = stmt.kind {
|
|
150
|
-
eprintln!("❌ Error found in statement: {:?}", stmt);
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
false
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
fn match_error_recursively_resolved_value(value: &StatementResolvedValue) -> bool {
|
|
160
|
-
match value {
|
|
161
|
-
StatementResolvedValue::Map(map) => {
|
|
162
|
-
for (_, v) in map {
|
|
163
|
-
if match_error_recursively_resolved_value(v) {
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
StatementResolvedValue::Array(array) => {
|
|
170
|
-
for item in array {
|
|
171
|
-
if match_error_recursively_resolved(item) {
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
_ => {}
|
|
177
|
-
}
|
|
108
|
+
let success_message = format!(
|
|
109
|
+
"Check completed successfully in {:.2?}. Output files written to: '{}'",
|
|
110
|
+
duration.elapsed(),
|
|
111
|
+
normalized_output_dir
|
|
112
|
+
);
|
|
178
113
|
|
|
179
|
-
|
|
114
|
+
let logger = Logger::new();
|
|
115
|
+
logger.log_message(LogLevel::Success, &success_message);
|
|
180
116
|
}
|
package/rust/cli/init.rs
CHANGED
|
@@ -2,7 +2,7 @@ use std::{ fs, path::Path };
|
|
|
2
2
|
use include_dir::{ include_dir, Dir };
|
|
3
3
|
use inquire::{ Select, Confirm };
|
|
4
4
|
|
|
5
|
-
use crate::{ cli::template::
|
|
5
|
+
use crate::{ cli::template::get_available_templates, utils::file::copy_dir_recursive };
|
|
6
6
|
|
|
7
7
|
static TEMPLATES_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates");
|
|
8
8
|
|