@devaloop/devalang 0.0.1-alpha.17 → 0.0.1-alpha.18

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 (44) hide show
  1. package/.devalang +5 -1
  2. package/Cargo.toml +4 -4
  3. package/README.md +9 -6
  4. package/docs/CHANGELOG.md +46 -1
  5. package/docs/TODO.md +1 -1
  6. package/examples/index.deva +9 -6
  7. package/examples/pattern.deva +5 -5
  8. package/out-tsc/pkg/devalang_core.d.ts +1 -1
  9. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +7 -7
  10. package/package.json +1 -1
  11. package/project-version.json +3 -3
  12. package/rust/cli/build/commands.rs +10 -0
  13. package/rust/cli/install/addon.rs +84 -38
  14. package/rust/cli/telemetry/event_creator.rs +17 -17
  15. package/rust/core/audio/engine/helpers.rs +21 -9
  16. package/rust/core/audio/engine/sample.rs +68 -7
  17. package/rust/core/audio/engine/synth.rs +19 -4
  18. package/rust/core/audio/evaluator.rs +64 -26
  19. package/rust/core/audio/interpreter/arrow_call.rs +21 -16
  20. package/rust/core/audio/interpreter/call.rs +156 -1
  21. package/rust/core/audio/interpreter/spawn.rs +145 -1
  22. package/rust/core/audio/special/math.rs +22 -2
  23. package/rust/core/lexer/driver.rs +61 -0
  24. package/rust/core/lexer/handler/identifier.rs +3 -2
  25. package/rust/core/lexer/mod.rs +1 -62
  26. package/rust/core/lexer/token.rs +1 -0
  27. package/rust/core/parser/driver.rs +12 -9
  28. package/rust/core/parser/handler/dot.rs +3 -2
  29. package/rust/core/parser/handler/loop_.rs +2 -2
  30. package/rust/core/parser/handler/mod.rs +1 -0
  31. package/rust/core/parser/handler/pattern.rs +74 -0
  32. package/rust/core/preprocessor/loader.rs +87 -127
  33. package/rust/core/preprocessor/processor.rs +7 -7
  34. package/rust/core/preprocessor/resolver/call.rs +28 -0
  35. package/rust/core/preprocessor/resolver/driver.rs +15 -13
  36. package/rust/core/preprocessor/resolver/mod.rs +1 -0
  37. package/rust/core/preprocessor/resolver/pattern.rs +75 -0
  38. package/rust/core/preprocessor/resolver/spawn.rs +27 -0
  39. package/rust/core/store/variable.rs +15 -1
  40. package/rust/main.rs +4 -1
  41. package/rust/types/Cargo.toml +3 -0
  42. package/rust/types/src/ast.rs +4 -0
  43. package/rust/utils/Cargo.toml +4 -1
  44. package/rust/web/api.rs +2 -2
@@ -1,64 +1,3 @@
1
1
  pub mod handler;
2
2
  pub mod token;
3
-
4
- use crate::core::{
5
- lexer::{handler::driver::handle_content_lexing, token::Token},
6
- utils::path::normalize_path,
7
- };
8
- use std::fs;
9
- use std::path::Path;
10
-
11
- pub struct Lexer {}
12
-
13
- impl Default for Lexer {
14
- fn default() -> Self {
15
- Self::new()
16
- }
17
- }
18
-
19
- impl Lexer {
20
- pub fn new() -> Self {
21
- Lexer {}
22
- }
23
-
24
- pub fn lex_from_source(&self, source: &str) -> Result<Vec<Token>, String> {
25
- handle_content_lexing(source.to_string())
26
- }
27
-
28
- pub fn lex_tokens(&self, entrypoint: &str) -> Result<Vec<Token>, String> {
29
- let path = normalize_path(entrypoint);
30
- let resolved_path = Self::resolve_entry_path(&path)?;
31
-
32
- let file_content = fs::read_to_string(&resolved_path).map_err(|e| {
33
- format!(
34
- "Failed to read the entrypoint file '{}': {}",
35
- resolved_path, e
36
- )
37
- })?;
38
-
39
- handle_content_lexing(file_content).map_err(|e| format!("Failed to lex the content: {}", e))
40
- }
41
-
42
- fn resolve_entry_path(path: &str) -> Result<String, String> {
43
- let candidate = Path::new(path);
44
-
45
- if candidate.is_dir() {
46
- let index_path = candidate.join("index.deva");
47
- if index_path.exists() {
48
- Ok(index_path.to_string_lossy().replace("\\", "/"))
49
- } else {
50
- Err(format!(
51
- "Expected 'index.deva' in directory '{}', but it was not found",
52
- path
53
- ))
54
- }
55
- } else if candidate.is_file() {
56
- return Ok(path.to_string());
57
- } else {
58
- return Err(format!(
59
- "Provided entrypoint '{}' is not a valid file or directory",
60
- path
61
- ));
62
- }
63
- }
64
- }
3
+ pub mod driver;
@@ -21,6 +21,7 @@ pub enum TokenKind {
21
21
  At,
22
22
  Tempo,
23
23
  Bank,
24
+ Pattern,
24
25
  Loop,
25
26
  Function,
26
27
  As,
@@ -9,6 +9,7 @@ use crate::core::{
9
9
  bank::parse_bank_token,
10
10
  condition::parse_condition_token,
11
11
  dot::parse_dot_token,
12
+ pattern::parse_pattern_token,
12
13
  identifier::{
13
14
  emit::parse_emit_token, function::parse_function_token, on::parse_on_token,
14
15
  parse_identifier_token,
@@ -156,6 +157,7 @@ impl Parser {
156
157
  TokenKind::Dot => parse_dot_token(self, global_store),
157
158
  TokenKind::Tempo => parse_tempo_token(self, global_store),
158
159
  TokenKind::Bank => parse_bank_token(self, global_store),
160
+ TokenKind::Pattern => parse_pattern_token(self, global_store),
159
161
  TokenKind::Loop => parse_loop_token(self, global_store),
160
162
  TokenKind::If => parse_condition_token(self, global_store),
161
163
  TokenKind::Function => parse_function_token(self, global_store),
@@ -202,6 +204,8 @@ impl Parser {
202
204
  }
203
205
 
204
206
  pub fn parse_map_value(&mut self) -> Option<Value> {
207
+ let logger = devalang_utils::logger::Logger::new();
208
+ use devalang_utils::logger::LogLevel;
205
209
  if !self.match_token(TokenKind::LBrace) {
206
210
  return None;
207
211
  }
@@ -244,7 +248,7 @@ impl Parser {
244
248
  }
245
249
 
246
250
  if !self.match_token(TokenKind::Colon) {
247
- println!("Expected ':' after map key '{}'", key);
251
+ logger.log_message(LogLevel::Error, &format!("Expected ':' after map key '{}'", key));
248
252
  break;
249
253
  }
250
254
 
@@ -278,14 +282,11 @@ impl Parser {
278
282
  number_str.push('.');
279
283
  number_str.push_str(&decimal_token.lexeme);
280
284
  } else {
281
- println!(
282
- "Expected number after dot, got {:?}",
283
- decimal_token
284
- );
285
+ logger.log_message(LogLevel::Error, &format!("Expected number after dot, got {:?}", decimal_token));
285
286
  return Some(Value::Null);
286
287
  }
287
288
  } else {
288
- println!("Expected number after dot, but reached EOF");
289
+ logger.log_message(LogLevel::Error, "Expected number after dot, but reached EOF");
289
290
  return Some(Value::Null);
290
291
  }
291
292
  }
@@ -325,7 +326,7 @@ impl Parser {
325
326
  Value::Identifier(parts.join("."))
326
327
  }
327
328
  _ => {
328
- println!("Unexpected token in map value: {:?}", token);
329
+ logger.log_message(LogLevel::Error, &format!("Unexpected token in map value: {:?}", token));
329
330
  Value::Null
330
331
  }
331
332
  }
@@ -345,7 +346,7 @@ impl Parser {
345
346
  }
346
347
 
347
348
  if !self.match_token(TokenKind::RBrace) {
348
- println!("Expected '}}' at end of map");
349
+ logger.log_message(LogLevel::Error, "Expected '}' at end of map");
349
350
  }
350
351
 
351
352
  Some(Value::Map(map))
@@ -353,6 +354,8 @@ impl Parser {
353
354
 
354
355
  // Parse an array value like [1, 2, 3] or ["a", b]
355
356
  pub fn parse_array_value(&mut self) -> Option<Value> {
357
+ let logger = devalang_utils::logger::Logger::new();
358
+ use devalang_utils::logger::LogLevel;
356
359
  if !self.match_token(TokenKind::LBracket) {
357
360
  return None;
358
361
  }
@@ -436,7 +439,7 @@ impl Parser {
436
439
  }
437
440
 
438
441
  if !self.match_token(TokenKind::RBracket) {
439
- println!("Expected ']' at end of array");
442
+ logger.log_message(LogLevel::Error, "Expected ']' at end of array");
440
443
  }
441
444
 
442
445
  Some(Value::Array(arr))
@@ -13,7 +13,8 @@ pub fn parse_dot_token(
13
13
  _global_store: &mut crate::core::store::global::GlobalStore,
14
14
  ) -> Statement {
15
15
  parser.advance(); // consume '.'
16
-
16
+ let logger = devalang_utils::logger::Logger::new();
17
+ use devalang_utils::logger::LogLevel;
17
18
  let Some(dot_token) = parser.previous_clone() else {
18
19
  return Statement::unknown();
19
20
  };
@@ -56,7 +57,7 @@ pub fn parse_dot_token(
56
57
  let entity = if !parts.is_empty() {
57
58
  parts.join(".") // only join within the same line
58
59
  } else {
59
- eprintln!("⚠️ Empty entity after '.' at line {}", dot_token.line);
60
+ logger.log_message(LogLevel::Warning, &format!("Empty entity after '.' at line {}", dot_token.line));
60
61
  String::new()
61
62
  };
62
63
 
@@ -100,7 +100,7 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
100
100
  }
101
101
 
102
102
  let tokens =
103
- parser.collect_until(|t| (t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF));
103
+ parser.collect_until(|t| t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF);
104
104
  let loop_body = parser.parse_block(tokens.clone(), global_store);
105
105
  if let Some(token) = parser.peek() {
106
106
  if token.kind == TokenKind::Dedent {
@@ -173,7 +173,7 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
173
173
  }
174
174
 
175
175
  let tokens =
176
- parser.collect_until(|t| (t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF));
176
+ parser.collect_until(|t| t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF);
177
177
  let loop_body = parser.parse_block(tokens.clone(), global_store);
178
178
  if let Some(token) = parser.peek() {
179
179
  if token.kind == TokenKind::Dedent {
@@ -1,6 +1,7 @@
1
1
  pub mod arrow_call;
2
2
  pub mod at;
3
3
  pub mod bank;
4
+ pub mod pattern;
4
5
  pub mod condition;
5
6
  pub mod dot;
6
7
  pub mod identifier;
@@ -0,0 +1,74 @@
1
+ use devalang_types::Value;
2
+
3
+ use crate::core::{
4
+ lexer::token::TokenKind,
5
+ parser::{
6
+ driver::Parser,
7
+ statement::{Statement, StatementKind},
8
+ },
9
+ store::global::GlobalStore,
10
+ };
11
+
12
+ pub fn parse_pattern_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
13
+ // consume 'pattern'
14
+ parser.advance();
15
+
16
+ let Some(tok) = parser.previous_clone() else {
17
+ return Statement::unknown();
18
+ };
19
+
20
+ // Parse pattern name
21
+ let mut name = String::new();
22
+ if let Some(next) = parser.peek_clone() {
23
+ if next.kind == TokenKind::Identifier {
24
+ parser.advance();
25
+ name = next.lexeme.clone();
26
+ }
27
+ }
28
+
29
+ // optional 'with <target>' sequence
30
+ let mut target: Option<String> = None;
31
+ if parser.peek_is("with") {
32
+ parser.advance(); // consume 'with'
33
+ if let Some(tok2) = parser.peek_clone() {
34
+ // target can be identifier or dotted identifier
35
+ if tok2.kind == TokenKind::Identifier {
36
+ parser.advance();
37
+ let mut base = tok2.lexeme.clone();
38
+ if let Some(dot) = parser.peek_clone() {
39
+ if dot.kind == TokenKind::Dot {
40
+ parser.advance();
41
+ if let Some(suf) = parser.peek_clone() {
42
+ if suf.kind == TokenKind::Identifier || suf.kind == TokenKind::Number {
43
+ parser.advance();
44
+ base.push('.');
45
+ base.push_str(&suf.lexeme);
46
+ }
47
+ }
48
+ }
49
+ }
50
+ target = Some(base);
51
+ }
52
+ }
53
+ }
54
+
55
+ // optional '=' and pattern string
56
+ let mut value: Value = Value::Null;
57
+ if parser.peek_is("=") {
58
+ parser.advance();
59
+ if let Some(tok3) = parser.peek_clone() {
60
+ if tok3.kind == TokenKind::String {
61
+ parser.advance();
62
+ value = Value::String(tok3.lexeme.clone());
63
+ }
64
+ }
65
+ }
66
+
67
+ Statement {
68
+ kind: StatementKind::Pattern { name, target },
69
+ value,
70
+ indent: tok.indent,
71
+ line: tok.line,
72
+ column: tok.column,
73
+ }
74
+ }