@devaloop/devalang 0.0.1-alpha.8 → 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.
- package/Cargo.toml +1 -1
- package/README.md +4 -8
- package/docs/CHANGELOG.md +27 -0
- package/examples/condition.deva +8 -12
- package/examples/group.deva +3 -3
- package/examples/index.deva +10 -8
- package/examples/loop.deva +10 -8
- package/examples/synth.deva +14 -0
- package/examples/variables.deva +1 -1
- package/out-tsc/bin/devalang.exe +0 -0
- package/out-tsc/scripts/version/fetch.js +1 -5
- package/package.json +1 -1
- package/project-version.json +3 -3
- package/rust/core/audio/engine.rs +89 -12
- package/rust/core/audio/interpreter/arrow_call.rs +129 -0
- package/rust/core/audio/interpreter/call.rs +29 -7
- package/rust/core/audio/interpreter/condition.rs +5 -1
- package/rust/core/audio/interpreter/driver.rs +41 -29
- package/rust/core/audio/interpreter/loop_.rs +11 -3
- package/rust/core/audio/interpreter/mod.rs +1 -0
- package/rust/core/audio/interpreter/spawn.rs +43 -42
- package/rust/core/audio/interpreter/trigger.rs +1 -1
- package/rust/core/audio/renderer.rs +15 -18
- package/rust/core/lexer/handler/arrow.rs +31 -0
- package/rust/core/lexer/handler/driver.rs +12 -1
- package/rust/core/lexer/handler/identifier.rs +1 -0
- package/rust/core/lexer/handler/mod.rs +1 -0
- package/rust/core/lexer/mod.rs +24 -3
- package/rust/core/lexer/token.rs +4 -0
- package/rust/core/parser/driver.rs +23 -4
- package/rust/core/parser/handler/arrow_call.rs +126 -0
- package/rust/core/parser/handler/identifier/call.rs +41 -0
- package/rust/core/parser/handler/identifier/group.rs +75 -0
- package/rust/core/parser/handler/identifier/let_.rs +133 -0
- package/rust/core/parser/handler/identifier/mod.rs +51 -0
- package/rust/core/parser/handler/identifier/sleep.rs +33 -0
- package/rust/core/parser/handler/identifier/spawn.rs +41 -0
- package/rust/core/parser/handler/identifier/synth.rs +65 -0
- package/rust/core/parser/handler/loop_.rs +24 -18
- package/rust/core/parser/handler/mod.rs +2 -1
- package/rust/core/parser/statement.rs +8 -0
- package/rust/core/preprocessor/loader.rs +57 -43
- package/rust/core/preprocessor/module.rs +3 -6
- package/rust/core/preprocessor/processor.rs +13 -4
- package/rust/core/preprocessor/resolver/call.rs +99 -29
- package/rust/core/preprocessor/resolver/condition.rs +38 -12
- package/rust/core/preprocessor/resolver/driver.rs +74 -29
- package/rust/core/preprocessor/resolver/group.rs +24 -81
- package/rust/core/preprocessor/resolver/let_.rs +31 -0
- package/rust/core/preprocessor/resolver/loop_.rs +62 -116
- package/rust/core/preprocessor/resolver/mod.rs +5 -1
- package/rust/core/preprocessor/resolver/spawn.rs +41 -36
- package/rust/core/preprocessor/resolver/synth.rs +50 -0
- package/rust/core/preprocessor/resolver/trigger.rs +51 -50
- package/rust/core/preprocessor/resolver/value.rs +78 -0
- package/rust/core/utils/path.rs +17 -32
- package/rust/core/utils/validation.rs +30 -28
- package/typescript/scripts/version/fetch.ts +1 -6
- package/rust/core/parser/handler/identifier.rs +0 -262
|
@@ -3,101 +3,33 @@ use std::collections::HashMap;
|
|
|
3
3
|
use crate::{
|
|
4
4
|
core::{
|
|
5
5
|
parser::statement::{ Statement, StatementKind },
|
|
6
|
-
preprocessor::{ module::Module, resolver::
|
|
6
|
+
preprocessor::{ module::Module, resolver::driver::resolve_statement },
|
|
7
7
|
shared::value::Value,
|
|
8
|
-
store::global::GlobalStore,
|
|
8
|
+
store::{ global::GlobalStore, variable::VariableTable },
|
|
9
9
|
},
|
|
10
|
-
utils::logger::Logger,
|
|
10
|
+
utils::logger::{ LogLevel, Logger },
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
pub fn resolve_group(
|
|
14
14
|
stmt: &Statement,
|
|
15
15
|
module: &Module,
|
|
16
16
|
path: &str,
|
|
17
|
-
global_store: &GlobalStore
|
|
17
|
+
global_store: &mut GlobalStore
|
|
18
18
|
) -> Statement {
|
|
19
19
|
let logger = Logger::new();
|
|
20
20
|
|
|
21
|
-
let Value::Map(
|
|
22
|
-
return type_error(&logger, module, stmt, "Expected a map
|
|
21
|
+
let Value::Map(group_map) = &stmt.value else {
|
|
22
|
+
return type_error(&logger, module, stmt, "Expected a map in group statement".to_string());
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
let
|
|
26
|
-
Some(Value::String(name)) => name.clone(),
|
|
27
|
-
Some(other) => {
|
|
28
|
-
return type_error(
|
|
29
|
-
&logger,
|
|
30
|
-
module,
|
|
31
|
-
stmt,
|
|
32
|
-
format!("Group name must be a string, found {:?}", other)
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
None => {
|
|
36
|
-
return type_error(&logger, module, stmt, "Group name is required".to_string());
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
let resolved_body = match value_map.get("body") {
|
|
41
|
-
Some(Value::Block(statements)) => {
|
|
42
|
-
let mut resolved = Vec::new();
|
|
43
|
-
|
|
44
|
-
for stmt in statements {
|
|
45
|
-
match &stmt.kind {
|
|
46
|
-
StatementKind::Trigger { entity, duration } => {
|
|
47
|
-
let resolved_trigger = resolve_trigger(
|
|
48
|
-
&mut stmt.clone(),
|
|
49
|
-
entity,
|
|
50
|
-
&mut duration.clone(),
|
|
51
|
-
module,
|
|
52
|
-
path,
|
|
53
|
-
global_store
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
resolved.push(resolved_trigger);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
StatementKind::If => {
|
|
60
|
-
let resolved_condition = resolve_condition(
|
|
61
|
-
&mut stmt.clone(),
|
|
62
|
-
module,
|
|
63
|
-
path,
|
|
64
|
-
global_store
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
resolved.push(resolved_condition);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
_ => {
|
|
71
|
-
println!("Unhandled group body statement: {:?}", stmt);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
Value::Block(resolved)
|
|
77
|
-
}
|
|
25
|
+
let mut resolved_map = group_map.clone();
|
|
78
26
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
None => {
|
|
89
|
-
return type_error(
|
|
90
|
-
&logger,
|
|
91
|
-
module,
|
|
92
|
-
stmt,
|
|
93
|
-
"Missing 'body' key in group statement".to_string()
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
let mut resolved_map = HashMap::new();
|
|
99
|
-
resolved_map.insert("identifier".to_string(), Value::String(group_name));
|
|
100
|
-
resolved_map.insert("body".to_string(), resolved_body);
|
|
27
|
+
if let Some(Value::Block(body)) = group_map.get("body") {
|
|
28
|
+
let resolved_body = resolve_block_statements(body, module, path, global_store);
|
|
29
|
+
resolved_map.insert("body".to_string(), Value::Block(resolved_body));
|
|
30
|
+
} else {
|
|
31
|
+
logger.log_message(LogLevel::Warning, "group without a body");
|
|
32
|
+
}
|
|
101
33
|
|
|
102
34
|
Statement {
|
|
103
35
|
kind: StatementKind::Group,
|
|
@@ -106,6 +38,17 @@ pub fn resolve_group(
|
|
|
106
38
|
}
|
|
107
39
|
}
|
|
108
40
|
|
|
41
|
+
fn resolve_block_statements(
|
|
42
|
+
body: &[Statement],
|
|
43
|
+
module: &Module,
|
|
44
|
+
path: &str,
|
|
45
|
+
global_store: &mut GlobalStore
|
|
46
|
+
) -> Vec<Statement> {
|
|
47
|
+
body.iter()
|
|
48
|
+
.map(|stmt| resolve_statement(stmt, module, path, global_store))
|
|
49
|
+
.collect()
|
|
50
|
+
}
|
|
51
|
+
|
|
109
52
|
fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
|
|
110
53
|
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
111
54
|
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
use crate::
|
|
2
|
+
core::{
|
|
3
|
+
parser::statement:: Statement ,
|
|
4
|
+
preprocessor::{
|
|
5
|
+
module::Module,
|
|
6
|
+
resolver:: value::resolve_value ,
|
|
7
|
+
},
|
|
8
|
+
store:: global::GlobalStore ,
|
|
9
|
+
}
|
|
10
|
+
;
|
|
11
|
+
|
|
12
|
+
pub fn resolve_let(
|
|
13
|
+
stmt: &Statement,
|
|
14
|
+
name: &str,
|
|
15
|
+
module: &Module,
|
|
16
|
+
path: &str,
|
|
17
|
+
global_store: &mut GlobalStore
|
|
18
|
+
) -> Statement {
|
|
19
|
+
let resolved_value = resolve_value(&stmt.value, module, global_store);
|
|
20
|
+
|
|
21
|
+
if let Some(current_mod) = global_store.modules.get_mut(path) {
|
|
22
|
+
current_mod.variable_table.set(name.to_string(), resolved_value.clone());
|
|
23
|
+
} else {
|
|
24
|
+
eprintln!("[resolve_statement] ❌ Module path not found: {path}");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Statement {
|
|
28
|
+
value: resolved_value,
|
|
29
|
+
..stmt.clone()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -3,7 +3,10 @@ use std::collections::HashMap;
|
|
|
3
3
|
use crate::{
|
|
4
4
|
core::{
|
|
5
5
|
parser::statement::{ Statement, StatementKind },
|
|
6
|
-
preprocessor::{
|
|
6
|
+
preprocessor::{
|
|
7
|
+
module::Module,
|
|
8
|
+
resolver::{ driver::resolve_statement, value::resolve_value },
|
|
9
|
+
},
|
|
7
10
|
shared::value::Value,
|
|
8
11
|
store::global::GlobalStore,
|
|
9
12
|
},
|
|
@@ -14,132 +17,75 @@ pub fn resolve_loop(
|
|
|
14
17
|
stmt: &Statement,
|
|
15
18
|
module: &Module,
|
|
16
19
|
path: &str,
|
|
17
|
-
global_store: &GlobalStore
|
|
20
|
+
global_store: &mut GlobalStore
|
|
18
21
|
) -> Statement {
|
|
19
22
|
let logger = Logger::new();
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
let iterator_value = match value_map.get("iterator") {
|
|
23
|
-
Some(Value::Identifier(ident)) => {
|
|
24
|
-
match module.variable_table.get(ident) {
|
|
25
|
-
Some(Value::Number(n)) => Value::Number(*n),
|
|
26
|
-
Some(_) => {
|
|
27
|
-
log_type_error(
|
|
28
|
-
&logger,
|
|
29
|
-
module,
|
|
30
|
-
stmt,
|
|
31
|
-
format!("Loop iterator '{ident}' must resolve to a number")
|
|
32
|
-
);
|
|
33
|
-
Value::Null
|
|
34
|
-
}
|
|
35
|
-
None => {
|
|
36
|
-
// Value is not a variable so we assume it's a number
|
|
37
|
-
if let Ok(n) = ident.parse::<f32>() {
|
|
38
|
-
Value::Number(n)
|
|
39
|
-
} else {
|
|
40
|
-
log_type_error(
|
|
41
|
-
&logger,
|
|
42
|
-
module,
|
|
43
|
-
stmt,
|
|
44
|
-
format!("Loop iterator '{ident}' is not a valid number")
|
|
45
|
-
);
|
|
46
|
-
Value::Null
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
Some(Value::Number(n)) => Value::Number(*n),
|
|
52
|
-
Some(other) => {
|
|
53
|
-
log_type_error(
|
|
54
|
-
&logger,
|
|
55
|
-
module,
|
|
56
|
-
stmt,
|
|
57
|
-
format!("Unexpected value for loop iterator: {:?}", other)
|
|
58
|
-
);
|
|
59
|
-
Value::Null
|
|
60
|
-
}
|
|
61
|
-
None => {
|
|
62
|
-
log_type_error(
|
|
63
|
-
&logger,
|
|
64
|
-
module,
|
|
65
|
-
stmt,
|
|
66
|
-
"Missing 'iterator' key in loop statement map".to_string()
|
|
67
|
-
);
|
|
68
|
-
Value::Null
|
|
69
|
-
}
|
|
70
|
-
};
|
|
24
|
+
let resolved_value = resolve_value(&stmt.value, module, global_store);
|
|
71
25
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
for ref statement in block.clone() {
|
|
76
|
-
match &statement.kind {
|
|
77
|
-
StatementKind::Trigger { entity, duration } => {
|
|
78
|
-
let resolved = resolve_trigger(
|
|
79
|
-
&mut statement.clone(),
|
|
80
|
-
&entity,
|
|
81
|
-
&mut duration.clone(),
|
|
82
|
-
module,
|
|
83
|
-
path,
|
|
84
|
-
global_store
|
|
85
|
-
);
|
|
86
|
-
resolved_block.push(resolved);
|
|
87
|
-
}
|
|
88
|
-
_ => {
|
|
89
|
-
println!("Unhandled loop body statement: {:?}", statement);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
Value::Block(resolved_block)
|
|
94
|
-
}
|
|
95
|
-
Some(other) => {
|
|
96
|
-
log_type_error(
|
|
97
|
-
&logger,
|
|
98
|
-
module,
|
|
99
|
-
stmt,
|
|
100
|
-
format!("Unexpected value for loop body: {:?}", other)
|
|
101
|
-
);
|
|
102
|
-
Value::Null
|
|
103
|
-
}
|
|
104
|
-
None => {
|
|
105
|
-
log_type_error(
|
|
106
|
-
&logger,
|
|
107
|
-
module,
|
|
108
|
-
stmt,
|
|
109
|
-
"Missing 'body' key in loop statement map".to_string()
|
|
110
|
-
);
|
|
111
|
-
Value::Null
|
|
112
|
-
}
|
|
113
|
-
};
|
|
26
|
+
let Value::Map(value_map) = &resolved_value else {
|
|
27
|
+
return error_stmt(&logger, module, stmt, "Expected a map for loop value");
|
|
28
|
+
};
|
|
114
29
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
resolved_map.insert(
|
|
30
|
+
let mut resolved_map: HashMap<String, Value> = HashMap::new();
|
|
31
|
+
for (key, val) in value_map {
|
|
32
|
+
resolved_map.insert(key.clone(), resolve_value(val, module, global_store));
|
|
33
|
+
}
|
|
118
34
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
35
|
+
let iterator_value = match resolved_map.get("iterator") {
|
|
36
|
+
Some(Value::Number(n)) => Value::Number(*n),
|
|
37
|
+
Some(other) => {
|
|
38
|
+
error_value(
|
|
39
|
+
&logger,
|
|
40
|
+
module,
|
|
41
|
+
stmt,
|
|
42
|
+
&format!("Loop iterator must be a number, found: {:?}", other)
|
|
43
|
+
);
|
|
44
|
+
Value::Number(1.0)
|
|
45
|
+
}
|
|
46
|
+
None => {
|
|
47
|
+
error_value(&logger, module, stmt, "Missing 'iterator' in loop");
|
|
48
|
+
Value::Number(1.0)
|
|
123
49
|
}
|
|
124
|
-
}
|
|
125
|
-
log_type_error(
|
|
126
|
-
&logger,
|
|
127
|
-
module,
|
|
128
|
-
stmt,
|
|
129
|
-
format!("Expected a map for loop value, found {:?}", stmt.value)
|
|
130
|
-
);
|
|
50
|
+
};
|
|
131
51
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
52
|
+
let body_value = match resolved_map.remove("body") {
|
|
53
|
+
Some(Value::Block(stmts)) => {
|
|
54
|
+
let resolved = stmts
|
|
55
|
+
.iter()
|
|
56
|
+
.map(|s| resolve_statement(s, module, path, global_store))
|
|
57
|
+
.collect();
|
|
58
|
+
Value::Block(resolved)
|
|
138
59
|
}
|
|
60
|
+
_ => {
|
|
61
|
+
error_value(&logger, module, stmt, "Invalid or missing loop body");
|
|
62
|
+
Value::Block(vec![])
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
let mut final_map = HashMap::new();
|
|
67
|
+
final_map.insert("iterator".to_string(), iterator_value);
|
|
68
|
+
final_map.insert("body".to_string(), body_value);
|
|
69
|
+
|
|
70
|
+
Statement {
|
|
71
|
+
kind: StatementKind::Loop,
|
|
72
|
+
value: Value::Map(final_map),
|
|
73
|
+
..stmt.clone()
|
|
139
74
|
}
|
|
140
75
|
}
|
|
141
76
|
|
|
142
|
-
fn
|
|
77
|
+
fn error_value(logger: &Logger, module: &Module, stmt: &Statement, msg: &str) {
|
|
143
78
|
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
144
|
-
logger.log_error_with_stacktrace(
|
|
79
|
+
logger.log_error_with_stacktrace(msg, &stacktrace);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fn error_stmt(logger: &Logger, module: &Module, stmt: &Statement, msg: &str) -> Statement {
|
|
83
|
+
error_value(logger, module, stmt, msg);
|
|
84
|
+
Statement {
|
|
85
|
+
kind: StatementKind::Error {
|
|
86
|
+
message: msg.to_string(),
|
|
87
|
+
},
|
|
88
|
+
value: Value::Null,
|
|
89
|
+
..stmt.clone()
|
|
90
|
+
}
|
|
145
91
|
}
|
|
@@ -1,53 +1,58 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
core::{
|
|
3
|
-
parser::statement::{Statement, StatementKind},
|
|
4
|
-
preprocessor::
|
|
3
|
+
parser::statement::{ Statement, StatementKind },
|
|
4
|
+
preprocessor::{
|
|
5
|
+
module::Module,
|
|
6
|
+
resolver::driver::resolve_statement,
|
|
7
|
+
resolver::value::resolve_value,
|
|
8
|
+
},
|
|
5
9
|
shared::value::Value,
|
|
6
10
|
store::global::GlobalStore,
|
|
7
11
|
},
|
|
8
|
-
utils::logger::Logger,
|
|
12
|
+
utils::logger::{ Logger, LogLevel },
|
|
9
13
|
};
|
|
10
14
|
|
|
11
15
|
pub fn resolve_spawn(
|
|
12
16
|
stmt: &Statement,
|
|
13
17
|
module: &Module,
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
path: &str,
|
|
19
|
+
global_store: &mut GlobalStore
|
|
16
20
|
) -> Statement {
|
|
17
21
|
let logger = Logger::new();
|
|
18
22
|
|
|
19
|
-
let
|
|
20
|
-
return type_error(&logger, module, stmt, "Spawn expects a group name as string.".to_string());
|
|
21
|
-
};
|
|
23
|
+
let resolved_value = resolve_value(&stmt.value, module, global_store);
|
|
22
24
|
|
|
23
|
-
match
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
format!("Group '{}' not found in module '{}'", name, module.path),
|
|
40
|
-
),
|
|
41
|
-
}
|
|
42
|
-
}
|
|
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
|
+
}
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
+
);
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
Statement {
|
|
50
|
+
kind: StatementKind::Error {
|
|
51
|
+
message: "Invalid spawn value".to_string(),
|
|
52
|
+
},
|
|
53
|
+
value: Value::Null,
|
|
54
|
+
..stmt.clone()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
|
-
}
|
|
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
|
-
|
|
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) =
|
|
28
|
+
if let Some(val) = resolve_identifier(ident, module, global_store) {
|
|
43
29
|
match val {
|
|
44
|
-
Value::Number(
|
|
45
|
-
final_duration = Duration::Number(
|
|
30
|
+
Value::Number(n) => {
|
|
31
|
+
final_duration = Duration::Number(n);
|
|
46
32
|
}
|
|
47
33
|
Value::String(s) => {
|
|
48
|
-
final_duration = Duration::Identifier(s
|
|
34
|
+
final_duration = Duration::Identifier(s);
|
|
49
35
|
}
|
|
50
|
-
Value::Identifier(
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
75
|
-
let
|
|
57
|
+
for (k, v) in map {
|
|
58
|
+
let resolved = match v {
|
|
76
59
|
Value::Identifier(id) => {
|
|
77
|
-
|
|
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(),
|
|
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
|
-
|
|
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
|
}
|