@devaloop/devalang 0.0.1-alpha.1 → 0.0.1-alpha.2

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 (49) hide show
  1. package/.devalang +4 -0
  2. package/Cargo.toml +3 -2
  3. package/README.md +30 -6
  4. package/docs/CHANGELOG.md +53 -0
  5. package/docs/COMMANDS.md +29 -6
  6. package/docs/CONFIG.md +28 -0
  7. package/docs/ROADMAP.md +1 -1
  8. package/docs/TODO.md +43 -15
  9. package/examples/index.deva +1 -1
  10. package/out-tsc/bin/devalang.exe +0 -0
  11. package/package.json +2 -2
  12. package/project-version.json +3 -3
  13. package/rust/cli/build.rs +58 -5
  14. package/rust/cli/check.rs +73 -17
  15. package/rust/cli/init.rs +77 -0
  16. package/rust/cli/mod.rs +2 -1
  17. package/rust/cli/template.rs +56 -0
  18. package/rust/core/lexer/at.rs +21 -0
  19. package/rust/core/lexer/brace.rs +41 -0
  20. package/rust/core/lexer/bracket.rs +41 -0
  21. package/rust/core/lexer/colon.rs +21 -0
  22. package/rust/core/lexer/comment.rs +30 -0
  23. package/rust/core/lexer/dot.rs +21 -0
  24. package/rust/core/lexer/driver.rs +286 -0
  25. package/rust/core/lexer/equal.rs +32 -0
  26. package/rust/core/lexer/identifier.rs +38 -0
  27. package/rust/core/lexer/indent.rs +47 -0
  28. package/rust/core/lexer/mod.rs +14 -333
  29. package/rust/core/lexer/newline.rs +23 -0
  30. package/rust/core/lexer/number.rs +31 -0
  31. package/rust/core/lexer/quote.rs +61 -0
  32. package/rust/core/parser/dot.rs +48 -18
  33. package/rust/core/preprocessor/module.rs +1 -1
  34. package/rust/core/types/cli.rs +53 -31
  35. package/rust/core/types/config.rs +15 -0
  36. package/rust/core/types/mod.rs +2 -1
  37. package/rust/main.rs +30 -19
  38. package/rust/utils/config.rs +13 -0
  39. package/rust/utils/file.rs +35 -0
  40. package/rust/utils/mod.rs +4 -1
  41. package/rust/utils/watcher.rs +25 -0
  42. package/templates/minimal/.devalang +4 -0
  43. package/templates/minimal/src/index.deva +2 -0
  44. package/templates/welcome/.devalang +4 -0
  45. package/templates/welcome/README.md +185 -0
  46. package/templates/welcome/samples/kick-808.wav +0 -0
  47. package/templates/welcome/src/index.deva +13 -0
  48. package/templates/welcome/src/variables.deva +5 -0
  49. package/rust/cli/new.rs +0 -1
@@ -1,333 +1,14 @@
1
- use crate::core::types::token::{ Token, TokenKind };
2
-
3
- pub fn lex(input: String) -> Vec<Token> {
4
- let mut tokens = Vec::new();
5
-
6
- let mut line = 1;
7
- let mut column = 1;
8
-
9
- let mut indent_stack: Vec<usize> = vec![0];
10
- let mut current_indent = 0;
11
- let mut at_line_start = true;
12
-
13
- let mut chars = input.chars().peekable();
14
-
15
- while let Some(_) = chars.peek() {
16
- if at_line_start {
17
- current_indent = 0;
18
-
19
- while let Some(&c) = chars.peek() {
20
- if c == ' ' {
21
- current_indent += 1;
22
- chars.next();
23
- column += 1;
24
- } else {
25
- break;
26
- }
27
- }
28
-
29
- let last_indent = *indent_stack.last().unwrap();
30
- if current_indent > last_indent {
31
- indent_stack.push(current_indent);
32
- tokens.push(Token {
33
- kind: TokenKind::Indent,
34
- lexeme: String::new(),
35
- line,
36
- column,
37
- indent: current_indent,
38
- });
39
- } else {
40
- while current_indent < *indent_stack.last().unwrap() {
41
- indent_stack.pop();
42
- tokens.push(Token {
43
- kind: TokenKind::Dedent,
44
- lexeme: String::new(),
45
- line,
46
- column,
47
- indent: current_indent,
48
- });
49
- }
50
- }
51
-
52
- at_line_start = false;
53
- }
54
-
55
- let Some(ch) = chars.next() else {
56
- break;
57
- };
58
-
59
- if ch == '\n' {
60
- tokens.push(Token {
61
- kind: TokenKind::Newline,
62
- lexeme: ch.to_string(),
63
- line,
64
- column,
65
- indent: current_indent,
66
- });
67
-
68
- line += 1;
69
- column = 1;
70
- at_line_start = true;
71
-
72
- continue;
73
- }
74
-
75
- if ch == ' ' || ch == '\t' {
76
- column += if ch == '\t' { 4 } else { 1 };
77
- continue;
78
- }
79
-
80
- if ch == '#' {
81
- let mut comment = String::new();
82
- while let Some(&c) = chars.peek() {
83
- if c == '\n' {
84
- break;
85
- }
86
- comment.push(c);
87
- chars.next();
88
- column += 1;
89
- }
90
- tokens.push(Token {
91
- kind: TokenKind::Comment(comment.trim().to_string()),
92
- lexeme: ch.to_string(),
93
- line,
94
- column,
95
- indent: current_indent,
96
- });
97
- continue;
98
- }
99
-
100
- if ch == ':' {
101
- tokens.push(Token {
102
- kind: TokenKind::Colon,
103
- lexeme: ch.to_string(),
104
- line,
105
- column,
106
- indent: current_indent,
107
- });
108
- column += 1;
109
- continue;
110
- }
111
-
112
- if ch == '=' {
113
- if let Some('=') = chars.peek() {
114
- chars.next();
115
- tokens.push(Token {
116
- kind: TokenKind::DoubleEquals,
117
- lexeme: ch.to_string(),
118
- line,
119
- column,
120
- indent: current_indent,
121
- });
122
- column += 2;
123
- } else {
124
- tokens.push(Token {
125
- kind: TokenKind::Equals,
126
- lexeme: ch.to_string(),
127
- line,
128
- column,
129
- indent: current_indent,
130
- });
131
- column += 1;
132
- }
133
- continue;
134
- }
135
-
136
- if ch == '[' {
137
- tokens.push(Token {
138
- kind: TokenKind::LBracket,
139
- lexeme: ch.to_string(),
140
- line,
141
- column,
142
- indent: current_indent,
143
- });
144
- column += 1;
145
- continue;
146
- }
147
-
148
- if ch == ']' {
149
- tokens.push(Token {
150
- kind: TokenKind::RBracket,
151
- lexeme: ch.to_string(),
152
- line,
153
- column,
154
- indent: current_indent,
155
- });
156
- column += 1;
157
- continue;
158
- }
159
-
160
- if ch == '{' {
161
- tokens.push(Token {
162
- kind: TokenKind::LBrace,
163
- lexeme: ch.to_string(),
164
- line,
165
- column,
166
- indent: current_indent,
167
- });
168
- column += 1;
169
- continue;
170
- }
171
-
172
- if ch == '}' {
173
- tokens.push(Token {
174
- kind: TokenKind::RBrace,
175
- lexeme: ch.to_string(),
176
- line,
177
- column,
178
- indent: current_indent,
179
- });
180
- column += 1;
181
- continue;
182
- }
183
-
184
- if ch == '"' {
185
- let mut string_content = String::new();
186
- column += 1; // skip the opening quote
187
-
188
- while let Some(next_ch) = chars.next() {
189
- column += 1;
190
- if next_ch == '"' {
191
- break; // closing quote reached
192
- } else {
193
- string_content.push(next_ch);
194
- }
195
- }
196
-
197
- tokens.push(Token {
198
- kind: TokenKind::String,
199
- lexeme: string_content,
200
- line,
201
- column,
202
- indent: current_indent,
203
- });
204
-
205
- continue;
206
- }
207
-
208
- if ch == '\'' {
209
- let mut string_content = String::new();
210
- column += 1;
211
-
212
- while let Some(next_ch) = chars.next() {
213
- column += 1;
214
- if next_ch == '\'' {
215
- break;
216
- } else {
217
- string_content.push(next_ch);
218
- }
219
- }
220
-
221
- tokens.push(Token {
222
- kind: TokenKind::String,
223
- lexeme: string_content,
224
- line,
225
- column,
226
- indent: current_indent,
227
- });
228
-
229
- continue;
230
- }
231
-
232
- if ch == '.' {
233
- tokens.push(Token {
234
- kind: TokenKind::Dot,
235
- lexeme: ch.to_string(),
236
- line,
237
- column,
238
- indent: current_indent,
239
- });
240
- column += 1;
241
- continue;
242
- }
243
-
244
- if ch == '@' {
245
- tokens.push(Token {
246
- kind: TokenKind::At,
247
- lexeme: ch.to_string(),
248
- line,
249
- column,
250
- indent: current_indent,
251
- });
252
- column += 1;
253
- continue;
254
- }
255
-
256
- if ch.is_ascii_digit() {
257
- let mut number = ch.to_string();
258
- while let Some(&c) = chars.peek() {
259
- if c.is_ascii_digit() {
260
- number.push(c);
261
- chars.next();
262
- column += 1;
263
- } else {
264
- break;
265
- }
266
- }
267
-
268
- // let value = number.parse::<f32>().unwrap();
269
- tokens.push(Token {
270
- kind: TokenKind::Number,
271
- lexeme: number,
272
- line,
273
- column,
274
- indent: current_indent,
275
- });
276
- continue;
277
- }
278
-
279
- if ch.is_ascii_alphabetic() {
280
- let mut ident = ch.to_string();
281
- while let Some(&c) = chars.peek() {
282
- if c.is_ascii_alphanumeric() || c == '_' {
283
- ident.push(c);
284
- chars.next();
285
- column += 1;
286
- } else {
287
- break;
288
- }
289
- }
290
-
291
- let kind = match ident.as_str() {
292
- "bank" => TokenKind::Bank,
293
- "bpm" => TokenKind::Tempo,
294
- "loop" => TokenKind::Loop,
295
- _ => TokenKind::Identifier,
296
- };
297
-
298
- tokens.push(Token {
299
- kind,
300
- lexeme: ident,
301
- line,
302
- column,
303
- indent: current_indent,
304
- });
305
- continue;
306
- }
307
-
308
- // Skip unknown char
309
- column += 1;
310
- }
311
-
312
- while indent_stack.len() > 1 {
313
- indent_stack.pop();
314
- current_indent = *indent_stack.last().unwrap();
315
- tokens.push(Token {
316
- kind: TokenKind::Dedent,
317
- lexeme: String::new(),
318
- line,
319
- column,
320
- indent: current_indent,
321
- });
322
- }
323
-
324
- tokens.push(Token {
325
- kind: TokenKind::EOF,
326
- lexeme: String::new(),
327
- line: line + 1, // EOF is considered to be on the next line
328
- column: 0, // EOF has no column
329
- indent: 0, // EOF has no indent
330
- });
331
-
332
- tokens
333
- }
1
+ pub mod indent;
2
+ pub mod identifier;
3
+ pub mod number;
4
+ pub mod at;
5
+ pub mod dot;
6
+ pub mod quote;
7
+ pub mod brace;
8
+ pub mod newline;
9
+ pub mod comment;
10
+ pub mod bracket;
11
+ pub mod colon;
12
+ pub mod equal;
13
+
14
+ pub mod driver;
@@ -0,0 +1,23 @@
1
+ use crate::core::types::token::{Token, TokenKind};
2
+
3
+ pub fn handle_newline_lexer(
4
+ char: char,
5
+ chars: &mut std::iter::Peekable<std::str::Chars>,
6
+ tokens: &mut Vec<Token>,
7
+ line: &mut usize,
8
+ column: &mut usize,
9
+ at_line_start: &mut bool,
10
+ current_indent: &mut usize,
11
+ ) {
12
+ tokens.push(Token {
13
+ kind: TokenKind::Newline,
14
+ lexeme: char.to_string(),
15
+ line: *line,
16
+ column: *column,
17
+ indent: *current_indent,
18
+ });
19
+
20
+ *line += 1;
21
+ *column = 1;
22
+ *at_line_start = true;
23
+ }
@@ -0,0 +1,31 @@
1
+ use crate::core::types::token::{Token, TokenKind};
2
+
3
+ pub fn handle_number_lexer(
4
+ char: char,
5
+ chars: &mut std::iter::Peekable<std::str::Chars>,
6
+ current_indent: &mut usize,
7
+ indent_stack: &mut Vec<usize>,
8
+ tokens: &mut Vec<Token>,
9
+ line: &mut usize,
10
+ column: &mut usize
11
+ ) {
12
+ let mut number = char.to_string();
13
+
14
+ while let Some(&c) = chars.peek() {
15
+ if c.is_ascii_digit() {
16
+ number.push(c);
17
+ chars.next();
18
+ *column += 1;
19
+ } else {
20
+ break;
21
+ }
22
+ }
23
+
24
+ tokens.push(Token {
25
+ kind: TokenKind::Number,
26
+ lexeme: number,
27
+ line: *line,
28
+ column: *column,
29
+ indent: *current_indent,
30
+ });
31
+ }
@@ -0,0 +1,61 @@
1
+ use crate::core::types::token::{Token, TokenKind};
2
+
3
+ pub fn handle_single_quote_lexer(
4
+ char: char,
5
+ chars: &mut std::iter::Peekable<std::str::Chars>,
6
+ current_indent: &mut usize,
7
+ indent_stack: &mut Vec<usize>,
8
+ tokens: &mut Vec<Token>,
9
+ line: &mut usize,
10
+ column: &mut usize
11
+ ) {
12
+ let mut string_content = String::new();
13
+ *column += 1;
14
+
15
+ while let Some(next_ch) = chars.next() {
16
+ *column += 1;
17
+ if next_ch == '\'' {
18
+ break;
19
+ } else {
20
+ string_content.push(next_ch);
21
+ }
22
+ }
23
+
24
+ tokens.push(Token {
25
+ kind: TokenKind::String,
26
+ lexeme: string_content,
27
+ line: *line,
28
+ column: *column,
29
+ indent: *current_indent,
30
+ });
31
+ }
32
+
33
+ pub fn handle_double_quote_lexer(
34
+ char: char,
35
+ chars: &mut std::iter::Peekable<std::str::Chars>,
36
+ current_indent: &mut usize,
37
+ indent_stack: &mut Vec<usize>,
38
+ tokens: &mut Vec<Token>,
39
+ line: &mut usize,
40
+ column: &mut usize
41
+ ) {
42
+ let mut string_content = String::new();
43
+ *column += 1; // skip the opening quote
44
+
45
+ while let Some(next_ch) = chars.next() {
46
+ *column += 1;
47
+ if next_ch == '"' {
48
+ break; // closing quote reached
49
+ } else {
50
+ string_content.push(next_ch);
51
+ }
52
+ }
53
+
54
+ tokens.push(Token {
55
+ kind: TokenKind::String,
56
+ lexeme: string_content,
57
+ line: *line,
58
+ column: *column,
59
+ indent: *current_indent,
60
+ });
61
+ }
@@ -1,9 +1,12 @@
1
1
  use std::{ collections::HashMap, hash::Hash };
2
2
 
3
- use crate::core::types::{
4
- statement::{ Statement, StatementKind },
5
- token::{ Token, TokenDuration, TokenKind, TokenParamValue },
6
- variable::{ Variable, VariableValue },
3
+ use crate::{
4
+ core::types::{
5
+ statement::{ Statement, StatementKind },
6
+ token::{ Token, TokenDuration, TokenKind, TokenParamValue },
7
+ variable::{ Variable, VariableValue },
8
+ },
9
+ utils::logger::log_message,
7
10
  };
8
11
 
9
12
  pub fn parse_dot(
@@ -19,12 +22,43 @@ pub fn parse_dot(
19
22
 
20
23
  parser.next();
21
24
 
22
- let next_token = parser.peek().ok_or("Expected identifier after dot")?.clone();
23
- if next_token.kind != crate::core::types::token::TokenKind::Identifier {
24
- return Err(format!("Expected Identifier after Dot, found {:?}", next_token.kind));
25
+ let identifier_token = parser.peek().ok_or("Expected identifier after dot")?.clone();
26
+ if identifier_token.kind != crate::core::types::token::TokenKind::Identifier {
27
+ return Err(format!("Expected Identifier after Dot, found {:?}", identifier_token.kind));
25
28
  }
26
29
 
27
- parser.next();
30
+ match identifier_token.lexeme.as_str() {
31
+ // TODO Execute each trigger logic
32
+
33
+ "kick" => {
34
+ trigger_value = String::from("Kick");
35
+ }
36
+ "snare" => {
37
+ trigger_value = String::from("Snare");
38
+ }
39
+ "hihat" => {
40
+ trigger_value = String::from("HiHat");
41
+ }
42
+ "tom" => {
43
+ trigger_value = String::from("Tom");
44
+ }
45
+ "clap" => {
46
+ trigger_value = String::from("Clap");
47
+ }
48
+ "crash" => {
49
+ trigger_value = String::from("Crash");
50
+ }
51
+ "ride" => {
52
+ trigger_value = String::from("Ride");
53
+ }
54
+
55
+ _ => {
56
+ log_message("Custom triggers are experimental", "WARNING");
57
+ trigger_value = identifier_token.lexeme.clone();
58
+ }
59
+ }
60
+
61
+ parser.next();
28
62
 
29
63
  let duration_token = parser.peek().ok_or("Expected duration after identifier")?.clone();
30
64
  let mut duration = TokenDuration::Unknown;
@@ -50,10 +84,8 @@ pub fn parse_dot(
50
84
  }
51
85
 
52
86
  parser.next();
53
-
54
- let dot_params: Vec<Token> = parser.collect_until(|t| {
55
- t.kind == TokenKind::Newline
56
- });
87
+
88
+ let dot_params: Vec<Token> = parser.collect_until(|t| { t.kind == TokenKind::Newline });
57
89
 
58
90
  let mut params_value: VariableValue = VariableValue::Null;
59
91
 
@@ -79,24 +111,22 @@ pub fn parse_dot(
79
111
  }
80
112
  VariableValue::Map(map)
81
113
  }
82
- TokenKind::Identifier => {
83
- VariableValue::Text(param.lexeme.clone())
84
- }
114
+ TokenKind::Identifier => { VariableValue::Text(param.lexeme.clone()) }
85
115
  TokenKind::Unknown => {
86
116
  Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
87
117
  VariableValue::Null
88
- },
118
+ }
89
119
  _ => {
90
120
  Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
91
121
  VariableValue::Unknown
92
- },
122
+ }
93
123
  };
94
124
  params_value = token_value;
95
125
  }
96
126
 
97
127
  Ok(Statement {
98
128
  kind: StatementKind::Trigger {
99
- entity: next_token.lexeme.clone(),
129
+ entity: identifier_token.lexeme.clone(),
100
130
  duration: duration.clone(),
101
131
  },
102
132
  value: params_value,
@@ -1,5 +1,5 @@
1
1
  use crate::core::{
2
- lexer::lex,
2
+ lexer::driver::lex,
3
3
  parser::{ parse_without_resolving },
4
4
  preprocessor::{
5
5
  collect_dependencies_recursively,