@devaloop/devalang 0.0.1-alpha.7 → 0.0.1-alpha.9

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 (86) hide show
  1. package/Cargo.toml +1 -1
  2. package/README.md +31 -16
  3. package/docs/CHANGELOG.md +49 -2
  4. package/docs/ROADMAP.md +2 -2
  5. package/docs/SYNTAX.md +41 -7
  6. package/docs/TODO.md +3 -3
  7. package/examples/condition.deva +20 -0
  8. package/examples/group.deva +3 -3
  9. package/examples/index.deva +9 -8
  10. package/examples/loop.deva +10 -8
  11. package/examples/synth.deva +14 -0
  12. package/examples/variables.deva +2 -2
  13. package/out-tsc/bin/devalang.exe +0 -0
  14. package/out-tsc/scripts/version/fetch.js +1 -5
  15. package/package.json +1 -1
  16. package/project-version.json +3 -3
  17. package/rust/cli/build.rs +6 -1
  18. package/rust/core/audio/engine.rs +89 -12
  19. package/rust/core/audio/evaluator.rs +31 -0
  20. package/rust/core/audio/interpreter/arrow_call.rs +129 -0
  21. package/rust/core/audio/interpreter/call.rs +64 -0
  22. package/rust/core/audio/interpreter/condition.rs +69 -0
  23. package/rust/core/audio/interpreter/driver.rs +216 -0
  24. package/rust/core/audio/interpreter/let_.rs +19 -0
  25. package/rust/core/audio/interpreter/load.rs +18 -0
  26. package/rust/core/audio/interpreter/loop_.rs +67 -0
  27. package/rust/core/audio/interpreter/mod.rs +12 -0
  28. package/rust/core/audio/interpreter/sleep.rs +36 -0
  29. package/rust/core/audio/interpreter/spawn.rs +66 -0
  30. package/rust/core/audio/interpreter/tempo.rs +16 -0
  31. package/rust/core/audio/interpreter/trigger.rs +69 -0
  32. package/rust/core/audio/loader/mod.rs +1 -0
  33. package/rust/core/audio/{loader.rs → loader/trigger.rs} +3 -1
  34. package/rust/core/audio/mod.rs +2 -1
  35. package/rust/core/audio/renderer.rs +54 -0
  36. package/rust/core/builder/mod.rs +1 -1
  37. package/rust/core/debugger/lexer.rs +1 -1
  38. package/rust/core/debugger/mod.rs +1 -0
  39. package/rust/core/debugger/store.rs +25 -0
  40. package/rust/core/error/mod.rs +1 -1
  41. package/rust/core/lexer/handler/arrow.rs +31 -0
  42. package/rust/core/lexer/handler/driver.rs +226 -0
  43. package/rust/core/lexer/handler/identifier.rs +3 -0
  44. package/rust/core/lexer/handler/mod.rs +4 -227
  45. package/rust/core/lexer/handler/operator.rs +44 -0
  46. package/rust/core/lexer/mod.rs +25 -4
  47. package/rust/core/lexer/token.rs +40 -9
  48. package/rust/core/parser/driver.rs +331 -0
  49. package/rust/core/parser/handler/arrow_call.rs +126 -0
  50. package/rust/core/parser/handler/at.rs +3 -7
  51. package/rust/core/parser/handler/bank.rs +5 -2
  52. package/rust/core/parser/handler/condition.rs +74 -0
  53. package/rust/core/parser/handler/dot.rs +1 -1
  54. package/rust/core/parser/handler/identifier/call.rs +41 -0
  55. package/rust/core/parser/handler/identifier/group.rs +75 -0
  56. package/rust/core/parser/handler/identifier/let_.rs +133 -0
  57. package/rust/core/parser/handler/identifier/mod.rs +51 -0
  58. package/rust/core/parser/handler/identifier/sleep.rs +33 -0
  59. package/rust/core/parser/handler/identifier/spawn.rs +41 -0
  60. package/rust/core/parser/handler/identifier/synth.rs +65 -0
  61. package/rust/core/parser/handler/loop_.rs +25 -19
  62. package/rust/core/parser/handler/mod.rs +3 -1
  63. package/rust/core/parser/handler/tempo.rs +1 -1
  64. package/rust/core/parser/mod.rs +3 -237
  65. package/rust/core/parser/statement.rs +36 -35
  66. package/rust/core/preprocessor/loader.rs +64 -49
  67. package/rust/core/preprocessor/module.rs +3 -6
  68. package/rust/core/preprocessor/processor.rs +13 -4
  69. package/rust/core/preprocessor/resolver/call.rs +123 -0
  70. package/rust/core/preprocessor/resolver/condition.rs +92 -0
  71. package/rust/core/preprocessor/resolver/driver.rs +227 -0
  72. package/rust/core/preprocessor/resolver/group.rs +35 -87
  73. package/rust/core/preprocessor/resolver/let_.rs +31 -0
  74. package/rust/core/preprocessor/resolver/loop_.rs +62 -116
  75. package/rust/core/preprocessor/resolver/mod.rs +9 -153
  76. package/rust/core/preprocessor/resolver/spawn.rs +58 -0
  77. package/rust/core/preprocessor/resolver/synth.rs +50 -0
  78. package/rust/core/preprocessor/resolver/trigger.rs +51 -50
  79. package/rust/core/preprocessor/resolver/value.rs +78 -0
  80. package/rust/core/utils/path.rs +17 -32
  81. package/rust/core/utils/validation.rs +30 -28
  82. package/typescript/scripts/version/fetch.ts +1 -6
  83. package/rust/core/audio/interpreter.rs +0 -317
  84. package/rust/core/audio/render.rs +0 -53
  85. package/rust/core/lexer/handler/equal.rs +0 -32
  86. package/rust/core/parser/handler/identifier.rs +0 -260
@@ -1,158 +1,14 @@
1
+ pub mod driver;
2
+
3
+ pub mod value;
4
+
1
5
  pub mod trigger;
2
6
  pub mod loop_;
3
7
  pub mod bank;
4
8
  pub mod tempo;
5
9
  pub mod group;
6
-
7
- use std::collections::HashMap;
8
- use crate::{
9
- core::{
10
- parser::statement::{ self, Statement, StatementKind },
11
- preprocessor::{
12
- loader::ModuleLoader,
13
- resolver::{
14
- bank::resolve_bank,
15
- group::resolve_group,
16
- loop_::resolve_loop,
17
- tempo::resolve_tempo,
18
- trigger::resolve_trigger,
19
- },
20
- },
21
- shared::{ duration::Duration, value::Value },
22
- store::global::GlobalStore,
23
- utils::validation::{ is_valid_entity, is_valid_identifier },
24
- },
25
- utils::logger::Logger,
26
- };
27
-
28
- pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
29
- for module in global_store.clone().modules.values_mut() {
30
- resolve_imports(module_loader, global_store);
31
- }
32
- }
33
-
34
- pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
35
- for (module_path, module) in global_store.clone().modules.iter_mut() {
36
- for (name, source_path) in &module.import_table.imports {
37
- match source_path {
38
- Value::String(source_path) => {
39
- if let Some(source_module) = global_store.modules.get(source_path) {
40
- if let Some(value) = source_module.export_table.get_export(name) {
41
- module.variable_table.set(name.clone(), value.clone());
42
- } else {
43
- println!(
44
- "[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
45
- );
46
- }
47
- } else {
48
- println!(
49
- "[warn] '{module_path}': cannot find source module '{source_path}'"
50
- );
51
- }
52
- }
53
- _ => {
54
- println!(
55
- "[warn] '{module_path}': expected string for import source, found {:?}",
56
- source_path
57
- );
58
- }
59
- }
60
- }
61
- }
62
- }
63
-
64
- pub fn resolve_and_flatten_all_modules(
65
- global_store: &mut GlobalStore
66
- ) -> HashMap<String, Vec<Statement>> {
67
- let logger = Logger::new();
68
- let snapshot = global_store.clone();
69
-
70
- // 1. Imports resolution
71
- for (module_path, module) in global_store.modules.iter_mut() {
72
- for (name, source_path) in &module.import_table.imports {
73
- if let Value::String(source_path_str) = source_path {
74
- match snapshot.modules.get(source_path_str) {
75
- Some(source_module) => {
76
- if let Some(value) = source_module.export_table.get_export(name) {
77
- module.variable_table.set(name.clone(), value.clone());
78
- } else {
79
- logger.log_error_with_stacktrace(
80
- &format!("'{name}' not found in exports of '{source_path_str}'"),
81
- module_path
82
- );
83
- }
84
- }
85
- None => {
86
- logger.log_error_with_stacktrace(
87
- &format!("Cannot find source module '{source_path_str}'"),
88
- module_path
89
- );
90
- }
91
- }
92
- } else {
93
- logger.log_error_with_stacktrace(
94
- &format!("Expected string for import source, found {:?}", source_path),
95
- module_path
96
- );
97
- }
98
- }
99
- }
100
-
101
- // 2. Statements resolution
102
- let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
103
- let store_snapshot = global_store.clone();
104
-
105
- for (path, module) in &store_snapshot.modules {
106
- let mut resolved = Vec::new();
107
-
108
- for stmt in &module.statements {
109
- let mut stmt = stmt.clone();
110
-
111
- match &stmt.kind {
112
- StatementKind::Trigger { entity, duration } => {
113
- let resolved_stmt = resolve_trigger(
114
- &stmt,
115
- entity.as_str(),
116
- &mut duration.clone(),
117
- &module,
118
- &path,
119
- &store_snapshot
120
- );
121
- resolved.push(resolved_stmt);
122
- }
123
-
124
- StatementKind::Loop => {
125
- let resolved_stmt = resolve_loop(&stmt, &module, &path, &store_snapshot);
126
- resolved.push(resolved_stmt);
127
- }
128
-
129
- StatementKind::Bank => {
130
- let resolved_stmt = resolve_bank(&stmt, &module, &path, &store_snapshot);
131
- resolved.push(resolved_stmt);
132
- }
133
-
134
- StatementKind::Tempo => {
135
- let resolved_stmt = resolve_tempo(&stmt, &module, &path, &store_snapshot);
136
- resolved.push(resolved_stmt);
137
- }
138
-
139
- StatementKind::Import { .. } | StatementKind::Export { .. } => {
140
- resolved.push(stmt.clone());
141
- }
142
-
143
- StatementKind::Group => {
144
- let resolved_stmt = resolve_group(&stmt, &module, &path, &store_snapshot);
145
- resolved.push(resolved_stmt);
146
- }
147
-
148
- _ => {
149
- resolved.push(stmt);
150
- }
151
- }
152
- }
153
-
154
- resolved_map.insert(path.clone(), resolved);
155
- }
156
-
157
- resolved_map
158
- }
10
+ pub mod condition;
11
+ pub mod spawn;
12
+ pub mod call;
13
+ pub mod synth;
14
+ pub mod let_;
@@ -0,0 +1,58 @@
1
+ use crate::{
2
+ core::{
3
+ parser::statement::{ Statement, StatementKind },
4
+ preprocessor::{
5
+ module::Module,
6
+ resolver::driver::resolve_statement,
7
+ resolver::value::resolve_value,
8
+ },
9
+ shared::value::Value,
10
+ store::global::GlobalStore,
11
+ },
12
+ utils::logger::{ Logger, LogLevel },
13
+ };
14
+
15
+ pub fn resolve_spawn(
16
+ stmt: &Statement,
17
+ module: &Module,
18
+ path: &str,
19
+ global_store: &mut GlobalStore
20
+ ) -> Statement {
21
+ let logger = Logger::new();
22
+
23
+ let resolved_value = resolve_value(&stmt.value, module, global_store);
24
+
25
+ match resolved_value {
26
+ Value::Map(mut map) => {
27
+ if let Some(Value::Block(stmts)) = map.get("body") {
28
+ let resolved_block = stmts
29
+ .iter()
30
+ .map(|s| resolve_statement(s, module, path, global_store))
31
+ .collect();
32
+ map.insert("body".to_string(), Value::Block(resolved_block));
33
+ }
34
+
35
+ Statement {
36
+ kind: StatementKind::Spawn,
37
+ value: Value::Map(map),
38
+ ..stmt.clone()
39
+ }
40
+ }
41
+
42
+ _ => {
43
+ let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
44
+ logger.log_message(
45
+ LogLevel::Error,
46
+ &format!("Expected a map in spawn statement\n → at {stacktrace}")
47
+ );
48
+
49
+ Statement {
50
+ kind: StatementKind::Error {
51
+ message: "Invalid spawn value".to_string(),
52
+ },
53
+ value: Value::Null,
54
+ ..stmt.clone()
55
+ }
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,50 @@
1
+ use crate::{
2
+ core::{
3
+ parser::statement::{ Statement, StatementKind },
4
+ preprocessor::{ module::Module, resolver::driver::resolve_statement },
5
+ shared::value::Value,
6
+ store::global::GlobalStore,
7
+ },
8
+ utils::logger::{ LogLevel, Logger },
9
+ };
10
+
11
+ pub fn resolve_synth(
12
+ stmt: &Statement,
13
+ module: &Module,
14
+ path: &str,
15
+ global_store: &mut GlobalStore
16
+ ) -> Statement {
17
+ let logger = Logger::new();
18
+
19
+ let Value::Map(synth_map) = &stmt.value else {
20
+ return type_error(&logger, module, stmt, "Expected a map in synth statement".to_string());
21
+ };
22
+
23
+ let mut resolved_map = synth_map.clone();
24
+
25
+ if let Some(Value::Block(body)) = synth_map.get("body") {
26
+ let resolved_body = body.iter()
27
+ .map(|s| resolve_statement(s, module, path, global_store))
28
+ .collect::<Vec<_>>();
29
+ resolved_map.insert("body".to_string(), Value::Block(resolved_body));
30
+ } else {
31
+ logger.log_message(LogLevel::Warning, "synth without a body");
32
+ }
33
+
34
+ Statement {
35
+ kind: StatementKind::Synth,
36
+ value: Value::Map(resolved_map),
37
+ ..stmt.clone()
38
+ }
39
+ }
40
+
41
+ fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
42
+ let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
43
+ logger.log_error_with_stacktrace(&message, &stacktrace);
44
+
45
+ Statement {
46
+ kind: StatementKind::Error { message },
47
+ value: Value::Null,
48
+ ..stmt.clone()
49
+ }
50
+ }
@@ -6,7 +6,6 @@ use crate::{
6
6
  preprocessor::module::Module,
7
7
  shared::{ duration::Duration, value::Value },
8
8
  store::global::GlobalStore,
9
- utils::validation::is_valid_entity,
10
9
  },
11
10
  utils::logger::Logger,
12
11
  };
@@ -24,30 +23,17 @@ pub fn resolve_trigger(
24
23
  let mut final_duration = duration.clone();
25
24
  let mut final_value = stmt.value.clone();
26
25
 
27
- if !is_valid_entity(entity, module, global_store) {
28
- let message = format!("Invalid entity '{}', expected a valid identifier", entity);
29
- let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
30
- logger.log_error_with_stacktrace(&message, &stacktrace);
31
-
32
- return Statement {
33
- kind: stmt.kind.clone(),
34
- value: Value::Null,
35
- line: stmt.line,
36
- column: stmt.column,
37
- indent: stmt.indent,
38
- };
39
- }
40
-
26
+ // Duration resolution
41
27
  if let Duration::Identifier(ident) = duration {
42
- if let Some(val) = module.variable_table.get(ident) {
28
+ if let Some(val) = resolve_identifier(ident, module, global_store) {
43
29
  match val {
44
- Value::Number(num) => {
45
- final_duration = Duration::Number(*num);
30
+ Value::Number(n) => {
31
+ final_duration = Duration::Number(n);
46
32
  }
47
33
  Value::String(s) => {
48
- final_duration = Duration::Identifier(s.clone());
34
+ final_duration = Duration::Identifier(s);
49
35
  }
50
- Value::Identifier(id) if id == "auto" => {
36
+ Value::Identifier(s) if s == "auto" => {
51
37
  final_duration = Duration::Auto;
52
38
  }
53
39
  _ => {}
@@ -55,50 +41,34 @@ pub fn resolve_trigger(
55
41
  }
56
42
  }
57
43
 
44
+ // Params value resolution
58
45
  final_value = match &stmt.value {
59
46
  Value::Identifier(ident) => {
60
- match module.variable_table.get(ident) {
61
- Some(val) => val.clone(),
62
- None => {
63
- let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
64
- let message = format!(
65
- "'{path}': value identifier '{ident}' not found in variable table"
66
- );
67
- logger.log_error_with_stacktrace(&message, &stacktrace);
68
- Value::Null
69
- }
70
- }
47
+ resolve_identifier(ident, module, global_store).unwrap_or_else(|| {
48
+ logger.log_error_with_stacktrace(
49
+ &format!("'{path}': value identifier '{ident}' not found"),
50
+ &format!("{}:{}:{}", module.path, stmt.line, stmt.column)
51
+ );
52
+ Value::Null
53
+ })
71
54
  }
72
55
  Value::Map(map) => {
73
56
  let mut resolved_map = HashMap::new();
74
- for (k, v) in map.iter() {
75
- let resolved_v = match v {
57
+ for (k, v) in map {
58
+ let resolved = match v {
76
59
  Value::Identifier(id) => {
77
- module.variable_table.get(id).cloned().unwrap_or(Value::Null)
60
+ resolve_identifier(id, module, global_store).unwrap_or(Value::Null)
78
61
  }
79
62
  other => other.clone(),
80
63
  };
81
- resolved_map.insert(k.clone(), resolved_v);
64
+ resolved_map.insert(k.clone(), resolved);
82
65
  }
83
66
  Value::Map(resolved_map)
84
67
  }
85
68
  other => other.clone(),
86
69
  };
87
70
 
88
- if let StatementKind::Trigger { entity, .. } = &stmt.kind {
89
- return Statement {
90
- kind: StatementKind::Trigger {
91
- entity: entity.to_string(),
92
- duration: final_duration,
93
- },
94
- value: final_value,
95
- line: stmt.line,
96
- column: stmt.column,
97
- indent: stmt.indent,
98
- };
99
- }
100
-
101
- return Statement {
71
+ Statement {
102
72
  kind: StatementKind::Trigger {
103
73
  entity: entity.to_string(),
104
74
  duration: final_duration,
@@ -107,5 +77,36 @@ pub fn resolve_trigger(
107
77
  line: stmt.line,
108
78
  column: stmt.column,
109
79
  indent: stmt.indent,
110
- };
80
+ }
81
+ }
82
+
83
+ fn resolve_identifier(ident: &str, module: &Module, global_store: &GlobalStore) -> Option<Value> {
84
+ if let Some(val) = module.variable_table.get(ident) {
85
+ return Some(resolve_value(val, module, global_store));
86
+ }
87
+
88
+ for (_, other_mod) in &global_store.modules {
89
+ if let Some(val) = other_mod.export_table.get_export(ident) {
90
+ return Some(resolve_value(val, other_mod, global_store));
91
+ }
92
+ }
93
+
94
+ None
95
+ }
96
+
97
+ fn resolve_value(val: &Value, module: &Module, global_store: &GlobalStore) -> Value {
98
+ match val {
99
+ Value::Identifier(inner) =>
100
+ resolve_identifier(inner, module, global_store).unwrap_or(
101
+ Value::Identifier(inner.clone())
102
+ ),
103
+ Value::Map(map) => {
104
+ let mut resolved = HashMap::new();
105
+ for (k, v) in map {
106
+ resolved.insert(k.clone(), resolve_value(v, module, global_store));
107
+ }
108
+ Value::Map(resolved)
109
+ }
110
+ other => other.clone(),
111
+ }
111
112
  }
@@ -0,0 +1,78 @@
1
+ use std::collections::HashMap;
2
+
3
+ use crate::{
4
+ core::{
5
+ parser::statement::{ Statement, StatementKind },
6
+ preprocessor::{ module::Module, resolver::driver::resolve_statement },
7
+ shared::value::Value,
8
+ store::{ global::GlobalStore, variable::VariableTable },
9
+ },
10
+ utils::logger::{ LogLevel, Logger },
11
+ };
12
+
13
+ fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
14
+ for (_path, module) in &global_store.modules {
15
+ if let Some(val) = module.export_table.get_export(name) {
16
+ return Some(val.clone());
17
+ }
18
+ }
19
+ None
20
+ }
21
+
22
+ pub fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalStore) -> Value {
23
+ match value {
24
+ Value::Identifier(name) => {
25
+ if let Some(original_val) = module.variable_table.get(name) {
26
+ return resolve_value(original_val, module, global_store);
27
+ }
28
+
29
+ if let Some(export_val) = find_export_value(name, global_store) {
30
+ return resolve_value(&export_val, module, global_store);
31
+ }
32
+
33
+ eprintln!("⚠️ Unresolved identifier '{}'", name);
34
+ Value::Null
35
+ }
36
+
37
+ Value::Map(map) => {
38
+ if let Some(Value::Identifier(entity)) = map.get("entity") {
39
+ // SECTION Synth
40
+ if entity == "synth" {
41
+ if let Some(Value::Map(synth_data)) = map.get("value") {
42
+ let resolved_waveform = synth_data
43
+ .get("waveform")
44
+ .map(|wf| resolve_value(wf, module, global_store))
45
+ .unwrap_or(Value::Null);
46
+
47
+ let resolved_params = synth_data
48
+ .get("parameters")
49
+ .map(|p| resolve_value(p, module, global_store))
50
+ .unwrap_or(Value::Map(HashMap::new()));
51
+
52
+ let mut result = HashMap::new();
53
+ result.insert("waveform".to_string(), resolved_waveform);
54
+ result.insert("parameters".to_string(), resolved_params);
55
+
56
+ return Value::Map(result);
57
+ }
58
+ }
59
+ }
60
+
61
+ let mut resolved = HashMap::new();
62
+ for (k, v) in map {
63
+ resolved.insert(k.clone(), resolve_value(v, module, global_store));
64
+ }
65
+ Value::Map(resolved)
66
+ }
67
+
68
+ Value::Block(stmts) => {
69
+ let resolved_stmts = stmts
70
+ .iter()
71
+ .map(|stmt| resolve_statement(stmt, module, &module.path, global_store))
72
+ .collect();
73
+ Value::Block(resolved_stmts)
74
+ }
75
+
76
+ other => other.clone(),
77
+ }
78
+ }
@@ -1,46 +1,31 @@
1
- use std::path::{ Component, Path };
1
+ use std::path::{ Component, Path, PathBuf };
2
2
 
3
- pub fn find_entry_file(path: &str) -> Option<String> {
4
- let path = Path::new(path);
3
+ pub fn find_entry_file(entry: &str) -> Option<String> {
4
+ let path = Path::new(entry);
5
5
 
6
- // Check if the path is a file
7
6
  if path.is_file() {
8
- return Some(path.to_string_lossy().to_string());
7
+ return Some(normalize_path(entry));
9
8
  }
10
9
 
11
- // Check if the path is a directory
12
10
  if path.is_dir() {
13
- // Look for an index.deva file in the directory
14
- let index_path = path.join("index.deva");
15
- if index_path.is_file() {
16
- return Some(index_path.to_string_lossy().to_string());
11
+ let candidate = path.join("index.deva");
12
+ if candidate.exists() {
13
+ return Some(normalize_path(&candidate));
17
14
  }
18
15
  }
19
16
 
20
17
  None
21
18
  }
22
19
 
23
- pub fn normalize_path(path: &str) -> String {
24
- let mut components = Vec::new();
25
-
26
- // Iterate through the components of the path
27
- for comp in Path::new(path).components() {
28
- match comp {
29
- Component::CurDir => {
30
- continue;
31
- }
32
- Component::Normal(c) => components.push(c),
33
- Component::RootDir => components.clear(),
34
- _ => {}
35
- }
36
- }
37
-
38
- // Join the components into a normalized path
39
- let normalized = components
40
- .iter()
41
- .map(|c| c.to_string_lossy())
42
- .collect::<Vec<_>>()
43
- .join("/");
20
+ pub fn normalize_path<P: AsRef<Path>>(path: P) -> String {
21
+ let path_buf = PathBuf::from(path.as_ref());
22
+ path_buf.components().collect::<PathBuf>().to_string_lossy().replace('\\', "/")
23
+ }
44
24
 
45
- format!("./{}", normalized)
25
+ pub fn resolve_relative_path(base: &str, import: &str) -> String {
26
+ let base_path = Path::new(base)
27
+ .parent()
28
+ .unwrap_or_else(|| Path::new(""));
29
+ let full_path = base_path.join(import);
30
+ full_path.components().collect::<PathBuf>().to_string_lossy().replace("\\", "/")
46
31
  }
@@ -1,35 +1,37 @@
1
1
  use crate::core::{ preprocessor::module::Module, shared::value::Value, store::global::GlobalStore };
2
2
 
3
- pub fn is_valid_entity(entity: &str, module: &Module, global_store: &GlobalStore) -> bool {
4
- let built_ins = ["kick", "snare", "hat", "clap"];
3
+ // NOTE: Deprecated functions, kept for reference
5
4
 
6
- if built_ins.contains(&entity) {
7
- return true;
8
- }
5
+ // pub fn is_valid_entity(entity: &str, module: &Module, global_store: &GlobalStore) -> bool {
6
+ // let built_ins = ["kick", "snare", "hat", "clap"];
9
7
 
10
- if let Some(val) = module.variable_table.get(entity) {
11
- match val {
12
- Value::Sample(_) => true,
13
- _ => false,
14
- }
15
- } else {
16
- false
17
- }
18
- }
8
+ // if built_ins.contains(&entity) {
9
+ // return true;
10
+ // }
19
11
 
20
- pub fn is_valid_identifier(ident: &str, module: &Module) -> bool {
21
- let built_ins = ["auto"];
12
+ // if let Some(val) = module.variable_table.get(entity) {
13
+ // match val {
14
+ // Value::Sample(_) => true,
15
+ // _ => false,
16
+ // }
17
+ // } else {
18
+ // false
19
+ // }
20
+ // }
22
21
 
23
- if built_ins.contains(&ident) {
24
- return true;
25
- }
22
+ // pub fn is_valid_identifier(ident: &str, module: &Module) -> bool {
23
+ // let built_ins = ["auto"];
26
24
 
27
- if let Some(val) = module.variable_table.get(ident) {
28
- match val {
29
- Value::Identifier(_) => true,
30
- _ => false,
31
- }
32
- } else {
33
- false
34
- }
35
- }
25
+ // if built_ins.contains(&ident) {
26
+ // return true;
27
+ // }
28
+
29
+ // if let Some(val) = module.variable_table.get(ident) {
30
+ // match val {
31
+ // Value::Identifier(_) => true,
32
+ // _ => false,
33
+ // }
34
+ // } else {
35
+ // false
36
+ // }
37
+ // }
@@ -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