@devaloop/devalang 0.0.1-alpha.2 → 0.0.1-alpha.4
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/.devalang +1 -1
- package/Cargo.toml +46 -46
- package/README.md +48 -30
- package/docs/CHANGELOG.md +28 -6
- package/docs/COMMANDS.md +31 -0
- package/docs/CONFIG.md +6 -4
- package/docs/ROADMAP.md +5 -1
- package/docs/TODO.md +10 -35
- package/examples/exported.deva +1 -1
- package/examples/index.deva +8 -1
- package/examples/samples/hat-808.wav +0 -0
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +41 -42
- package/project-version.json +5 -5
- package/rust/audio/engine.rs +130 -0
- package/rust/audio/interpreter.rs +143 -0
- package/rust/audio/loader.rs +46 -0
- package/rust/audio/mod.rs +5 -1
- package/rust/audio/player.rs +54 -0
- package/rust/audio/render.rs +57 -0
- package/rust/cli/build.rs +73 -45
- package/rust/cli/check.rs +47 -111
- package/rust/cli/init.rs +1 -1
- package/rust/cli/mod.rs +203 -2
- package/rust/cli/play.rs +191 -0
- package/rust/{utils/config.rs → config/loader.rs} +3 -2
- package/rust/config/mod.rs +16 -0
- package/rust/core/builder/mod.rs +69 -27
- package/rust/core/debugger/lexer.rs +27 -0
- package/rust/core/debugger/mod.rs +12 -49
- package/rust/core/debugger/preprocessor.rs +27 -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 +116 -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/bank.rs +38 -51
- package/rust/core/preprocessor/resolver/loop_.rs +126 -65
- package/rust/core/preprocessor/resolver/mod.rs +119 -80
- package/rust/core/preprocessor/resolver/tempo.rs +40 -61
- package/rust/core/preprocessor/resolver/trigger.rs +93 -155
- 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 +22 -18
- package/rust/utils/logger.rs +69 -34
- package/rust/utils/mod.rs +3 -5
- package/rust/utils/watcher.rs +10 -2
- package/templates/minimal/.devalang +1 -1
- package/templates/welcome/.devalang +1 -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/types/cli.rs +0 -182
- package/rust/core/types/config.rs +0 -15
- 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
|
@@ -1,70 +1,51 @@
|
|
|
1
1
|
use crate::core::{
|
|
2
|
-
lexer::
|
|
3
|
-
parser::
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
lexer::token::Token,
|
|
3
|
+
parser::statement::Statement,
|
|
4
|
+
store::{
|
|
5
|
+
export::ExportTable,
|
|
6
|
+
global::GlobalStore,
|
|
7
|
+
import::ImportTable,
|
|
8
|
+
variable::VariableTable,
|
|
7
9
|
},
|
|
8
|
-
types::{ module::Module, parser::Parser, store::{ ExportTable, GlobalStore, ImportTable } },
|
|
9
10
|
};
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
#[derive(Debug, Clone)]
|
|
13
|
+
pub struct Module {
|
|
14
|
+
pub path: String,
|
|
15
|
+
pub resolved: bool,
|
|
16
|
+
pub tokens: Vec<Token>,
|
|
17
|
+
pub statements: Vec<Statement>,
|
|
18
|
+
pub variable_table: VariableTable,
|
|
19
|
+
pub export_table: ExportTable,
|
|
20
|
+
pub import_table: ImportTable,
|
|
21
|
+
}
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
impl Module {
|
|
24
|
+
pub fn new(path: &str) -> Self {
|
|
25
|
+
Module {
|
|
26
|
+
path: path.to_string(),
|
|
27
|
+
tokens: Vec::new(),
|
|
28
|
+
statements: Vec::new(),
|
|
29
|
+
variable_table: VariableTable::new(),
|
|
30
|
+
export_table: ExportTable::new(),
|
|
31
|
+
import_table: ImportTable::new(),
|
|
32
|
+
resolved: false,
|
|
18
33
|
}
|
|
19
34
|
}
|
|
20
35
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
let imports = resolve_imports(module, &mut global_store);
|
|
24
|
-
module.import_table = imports.clone();
|
|
25
|
-
|
|
26
|
-
let global_store_module = global_store.modules.get(&file.clone().to_string());
|
|
27
|
-
if let Some(global_store_module_found) = global_store_module {
|
|
28
|
-
global_store.insert_module(file.to_string(), module.clone());
|
|
29
|
-
} else {
|
|
30
|
-
eprintln!("❌ Module {} not found in global store after import resolution", file);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
36
|
+
pub fn is_resolved(&self) -> bool {
|
|
37
|
+
self.resolved
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
pub fn load_module_into_global_store(
|
|
39
|
-
path: &str,
|
|
40
|
-
global_store: &mut GlobalStore
|
|
41
|
-
) -> Result<(), String> {
|
|
42
|
-
if global_store.modules.contains_key(path) {
|
|
43
|
-
return Ok(());
|
|
40
|
+
pub fn set_resolved(&mut self, resolved: bool) {
|
|
41
|
+
self.resolved = resolved;
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let mut parser = Parser::new(tokens.clone());
|
|
51
|
-
|
|
52
|
-
parser.current_module = path.to_string();
|
|
53
|
-
|
|
54
|
-
let raw_statements = parse_without_resolving(tokens.clone(), &mut parser, global_store);
|
|
55
|
-
|
|
56
|
-
let export_table = resolve_exports(&raw_statements, &mut parser);
|
|
57
|
-
|
|
58
|
-
let mut module = Module {
|
|
59
|
-
path: path.to_string(),
|
|
60
|
-
tokens: tokens.clone(),
|
|
61
|
-
statements: raw_statements,
|
|
62
|
-
variable_table: parser.variable_table.clone(),
|
|
63
|
-
export_table: export_table.clone(),
|
|
64
|
-
import_table: parser.import_table.clone(),
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
global_store.insert_module(path.to_string(), module.clone());
|
|
44
|
+
pub fn add_token(&mut self, token: Token) {
|
|
45
|
+
self.tokens.push(token);
|
|
46
|
+
}
|
|
68
47
|
|
|
69
|
-
|
|
48
|
+
pub fn add_statement(&mut self, statement: Statement) {
|
|
49
|
+
self.statements.push(statement);
|
|
50
|
+
}
|
|
70
51
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
use crate::core::{
|
|
2
|
+
parser::{ statement::StatementKind, Parser },
|
|
3
|
+
preprocessor::loader::ModuleLoader,
|
|
4
|
+
shared::value::Value,
|
|
5
|
+
store::global::GlobalStore,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
9
|
+
for module in global_store.modules.values_mut() {
|
|
10
|
+
for stmt in &module.statements {
|
|
11
|
+
match &stmt.kind {
|
|
12
|
+
StatementKind::Let { name } => {
|
|
13
|
+
module.variable_table.variables.insert(name.clone(), stmt.value.clone());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
StatementKind::Load { source, alias } => {
|
|
17
|
+
module.variable_table.variables.insert(
|
|
18
|
+
alias.clone(),
|
|
19
|
+
Value::Sample(source.clone())
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
StatementKind::Export { names, source } => {
|
|
24
|
+
for name in names {
|
|
25
|
+
if let Some(val) = module.variable_table.get(name) {
|
|
26
|
+
module.export_table.add_export(name.clone(), val.clone());
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
StatementKind::Import { names, source } => {
|
|
32
|
+
for name in names {
|
|
33
|
+
module.import_table.add_import(name.clone(), Value::String(source.clone()));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_ => {}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,59 +1,46 @@
|
|
|
1
|
-
use crate::core::{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
use crate::{core::{
|
|
2
|
+
parser::statement::{Statement, StatementKind},
|
|
3
|
+
preprocessor::module::Module,
|
|
4
|
+
shared::value::Value,
|
|
5
|
+
store::global::GlobalStore,
|
|
6
|
+
}, utils::logger::Logger};
|
|
6
7
|
|
|
7
|
-
pub fn
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let statement_value: StatementResolvedValue = match value {
|
|
16
|
-
VariableValue::Array(arr) => {
|
|
17
|
-
StatementResolvedValue::Array(
|
|
18
|
-
parse_with_resolving_with_module(arr.clone(), module)
|
|
19
|
-
)
|
|
20
|
-
}
|
|
21
|
-
VariableValue::Text(text) => StatementResolvedValue::String(text.clone()),
|
|
22
|
-
VariableValue::Number(num) => StatementResolvedValue::Number(*num),
|
|
23
|
-
VariableValue::Boolean(b) => StatementResolvedValue::Boolean(*b),
|
|
24
|
-
_ => {
|
|
25
|
-
eprintln!("⚠️ Unsupported variable type for Bank: {:?}", value);
|
|
26
|
-
StatementResolvedValue::Unknown
|
|
27
|
-
}
|
|
28
|
-
};
|
|
8
|
+
pub fn resolve_bank(
|
|
9
|
+
stmt: &Statement,
|
|
10
|
+
module: &Module,
|
|
11
|
+
path: &str,
|
|
12
|
+
_global_store: &GlobalStore
|
|
13
|
+
) -> Statement {
|
|
14
|
+
let mut new_stmt = stmt.clone();
|
|
15
|
+
let logger = Logger::new();
|
|
29
16
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
line: stmt.line,
|
|
35
|
-
column: stmt.column,
|
|
36
|
-
}
|
|
17
|
+
match &stmt.value {
|
|
18
|
+
Value::Identifier(ident) => {
|
|
19
|
+
if let Some(val) = module.variable_table.get(ident) {
|
|
20
|
+
new_stmt.value = val.clone();
|
|
37
21
|
} else {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
column: stmt.column,
|
|
45
|
-
}
|
|
22
|
+
let message = format!("Bank identifier '{ident}' not found in variable table");
|
|
23
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
24
|
+
new_stmt.kind = StatementKind::Error {
|
|
25
|
+
message: message.clone(),
|
|
26
|
+
};
|
|
27
|
+
new_stmt.value = Value::Null;
|
|
46
28
|
}
|
|
47
29
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
30
|
+
|
|
31
|
+
Value::String(_) => {
|
|
32
|
+
// Pas de résolution nécessaire
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
other => {
|
|
36
|
+
let message = format!("Expected a string or identifier for bank, found {:?}", other);
|
|
37
|
+
logger.log_error_with_stacktrace(&message, &module.path);
|
|
38
|
+
new_stmt.kind = StatementKind::Error {
|
|
39
|
+
message: "Expected a string or identifier for bank".to_string(),
|
|
40
|
+
};
|
|
41
|
+
new_stmt.value = Value::Null;
|
|
57
42
|
}
|
|
58
43
|
}
|
|
44
|
+
|
|
45
|
+
new_stmt
|
|
59
46
|
}
|
|
@@ -1,82 +1,143 @@
|
|
|
1
|
-
use crate::
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Statement,
|
|
8
|
-
StatementIterator,
|
|
9
|
-
StatementKind,
|
|
10
|
-
StatementResolved,
|
|
11
|
-
StatementResolvedValue,
|
|
12
|
-
},
|
|
13
|
-
variable::VariableValue,
|
|
1
|
+
use crate::{
|
|
2
|
+
core::{
|
|
3
|
+
parser::statement::{ Statement, StatementKind },
|
|
4
|
+
preprocessor::{ module::Module, resolver::trigger::resolve_trigger },
|
|
5
|
+
shared::value::Value,
|
|
6
|
+
store::global::GlobalStore,
|
|
14
7
|
},
|
|
8
|
+
utils::logger::Logger,
|
|
15
9
|
};
|
|
16
10
|
|
|
17
|
-
pub fn
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
11
|
+
pub fn resolve_loop(
|
|
12
|
+
stmt: &Statement,
|
|
13
|
+
module: &Module,
|
|
14
|
+
path: &str,
|
|
15
|
+
global_store: &GlobalStore
|
|
16
|
+
) -> Statement {
|
|
17
|
+
let logger = Logger::new();
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
// Vérifie que stmt.value est bien une Map
|
|
20
|
+
if let Value::Map(value_map) = &stmt.value {
|
|
21
|
+
// Résolution de l'iterator
|
|
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")
|
|
31
32
|
);
|
|
33
|
+
Value::Null
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
None => {
|
|
36
|
+
log_type_error(
|
|
37
|
+
&logger,
|
|
38
|
+
module,
|
|
39
|
+
stmt,
|
|
40
|
+
format!("Loop iterator '{ident}' not found")
|
|
41
|
+
);
|
|
42
|
+
Value::Null
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
|
-
} else {
|
|
42
|
-
eprintln!("⚠️ Loop iterator variable '{}' not found", id);
|
|
43
|
-
resolved_iterator = StatementIterator::Unknown;
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
Some(Value::Number(n)) => Value::Number(*n),
|
|
47
|
+
Some(other) => {
|
|
48
|
+
log_type_error(
|
|
49
|
+
&logger,
|
|
50
|
+
module,
|
|
51
|
+
stmt,
|
|
52
|
+
format!("Unexpected value for loop iterator: {:?}", other)
|
|
53
|
+
);
|
|
54
|
+
Value::Null
|
|
55
|
+
}
|
|
56
|
+
None => {
|
|
57
|
+
log_type_error(
|
|
58
|
+
&logger,
|
|
59
|
+
module,
|
|
60
|
+
stmt,
|
|
61
|
+
"Missing 'iterator' key in loop statement map".to_string()
|
|
62
|
+
);
|
|
63
|
+
Value::Null
|
|
64
|
+
}
|
|
65
|
+
};
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
// Résolution du body
|
|
68
|
+
let body_value = match value_map.get("body") {
|
|
69
|
+
Some(Value::Block(block)) => {
|
|
70
|
+
let mut resolved_block = Vec::new();
|
|
71
|
+
for ref statement in block.clone() {
|
|
72
|
+
match &statement.kind {
|
|
73
|
+
StatementKind::Trigger { entity, duration } => {
|
|
74
|
+
let resolved = resolve_trigger(
|
|
75
|
+
&mut statement.clone(),
|
|
76
|
+
&entity,
|
|
77
|
+
&mut duration.clone(),
|
|
78
|
+
module,
|
|
79
|
+
path,
|
|
80
|
+
global_store
|
|
81
|
+
);
|
|
82
|
+
resolved_block.push(resolved);
|
|
83
|
+
}
|
|
84
|
+
_ => {
|
|
85
|
+
println!("Unhandled loop body statement: {:?}", statement);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
Value::Block(resolved_block)
|
|
90
|
+
}
|
|
91
|
+
Some(other) => {
|
|
92
|
+
log_type_error(
|
|
93
|
+
&logger,
|
|
94
|
+
module,
|
|
95
|
+
stmt,
|
|
96
|
+
format!("Unexpected value for loop body: {:?}", other)
|
|
97
|
+
);
|
|
98
|
+
Value::Null
|
|
65
99
|
}
|
|
100
|
+
None => {
|
|
101
|
+
log_type_error(
|
|
102
|
+
&logger,
|
|
103
|
+
module,
|
|
104
|
+
stmt,
|
|
105
|
+
"Missing 'body' key in loop statement map".to_string()
|
|
106
|
+
);
|
|
107
|
+
Value::Null
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// ✅ Reconstruit proprement la valeur résolue
|
|
112
|
+
let mut resolved_map = std::collections::HashMap::new();
|
|
113
|
+
resolved_map.insert("iterator".to_string(), iterator_value);
|
|
114
|
+
resolved_map.insert("body".to_string(), body_value);
|
|
66
115
|
|
|
67
|
-
|
|
116
|
+
// ✅ Reconstruit le StatementLoop à partir des éléments résolus
|
|
117
|
+
Statement {
|
|
118
|
+
kind: StatementKind::Loop,
|
|
119
|
+
value: Value::Map(resolved_map),
|
|
120
|
+
..stmt.clone()
|
|
68
121
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
122
|
+
} else {
|
|
123
|
+
log_type_error(
|
|
124
|
+
&logger,
|
|
125
|
+
module,
|
|
126
|
+
stmt,
|
|
127
|
+
format!("Expected a map for loop value, found {:?}", stmt.value)
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
Statement {
|
|
131
|
+
kind: StatementKind::Error {
|
|
132
|
+
message: "Expected a map for loop value".to_string(),
|
|
133
|
+
},
|
|
134
|
+
value: Value::Null,
|
|
135
|
+
..stmt.clone()
|
|
72
136
|
}
|
|
73
137
|
}
|
|
138
|
+
}
|
|
74
139
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
indent: loop_statement.indent,
|
|
79
|
-
line: loop_statement.line,
|
|
80
|
-
column: loop_statement.column,
|
|
81
|
-
};
|
|
140
|
+
fn log_type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) {
|
|
141
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
142
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
82
143
|
}
|