Skip to content

Commit ed2b94e

Browse files
authored
Merge pull request #527 from SteveL-MSFT/expression-index
Add ability to use expression as array index within an expression
2 parents d6d4b26 + db8c86a commit ed2b94e

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

dsc/tests/dsc_expressions.tests.ps1

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Describe 'Expressions tests' {
1010
@{ text = "[parameters('test').objectArray[0].name]"; expected = 'one' }
1111
@{ text = "[parameters('test').objectArray[1].value[0]]"; expected = '2' }
1212
@{ text = "[parameters('test').objectArray[1].value[1].name]"; expected = 'three' }
13+
@{ text = "[parameters('test').index]"; expected = '1' }
14+
@{ text = "[parameters('test').objectArray[parameters('test').index].name]"; expected = 'two' }
1315
) {
1416
param($text, $expected)
1517
$yaml = @"
@@ -18,6 +20,7 @@ parameters:
1820
test:
1921
type: object
2022
defaultValue:
23+
index: 1
2124
hello:
2225
world: there
2326
array:
@@ -38,9 +41,9 @@ resources:
3841
properties:
3942
output: "$text"
4043
"@
41-
$debug = $yaml | dsc -l debug config get -f yaml 2>&1 | Out-String
44+
$debug = $yaml | dsc -l trace config get -f yaml 2>&1 | Out-String
4245
$out = $yaml | dsc config get | ConvertFrom-Json
43-
$LASTEXITCODE | Should -Be 0
46+
$LASTEXITCODE | Should -Be 0 -Because $debug
4447
$out.results[0].result.actualState.output | Should -Be $expected -Because $debug
4548
}
4649

dsc_lib/src/parser/expressions.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::parser::functions::Function;
1414
pub enum Accessor {
1515
Member(String),
1616
Index(Value),
17+
IndexExpression(Expression),
1718
}
1819

1920
#[derive(Clone)]
@@ -73,7 +74,8 @@ impl Expression {
7374
Accessor::Index(value)
7475
},
7576
"expression" => {
76-
return Err(DscError::Parser("Expression index not supported".to_string()));
77+
let expression = Expression::new(statement_bytes, &index_value)?;
78+
Accessor::IndexExpression(expression)
7779
},
7880
_ => {
7981
return Err(DscError::Parser(format!("Invalid accessor kind: '{accessor_kind}'")));
@@ -118,6 +120,7 @@ impl Expression {
118120
debug!("Evaluating accessors");
119121
let mut value = result;
120122
for accessor in &self.accessors {
123+
let mut index = Value::Null;
121124
match accessor {
122125
Accessor::Member(member) => {
123126
if let Some(object) = value.as_object() {
@@ -129,20 +132,31 @@ impl Expression {
129132
return Err(DscError::Parser("Member access on non-object value".to_string()));
130133
}
131134
},
132-
Accessor::Index(index) => {
133-
if let Some(array) = value.as_array() {
134-
let Some(index) = index.as_u64() else {
135-
return Err(DscError::Parser("Index is not a valid number".to_string()));
136-
};
137-
let index = usize::try_from(index)?;
138-
if index >= array.len() {
139-
return Err(DscError::Parser("Index out of bounds".to_string()));
140-
}
141-
value = array[index].clone();
142-
} else {
143-
return Err(DscError::Parser("Index access on non-array value".to_string()));
144-
}
135+
Accessor::Index(index_value) => {
136+
index = index_value.clone();
145137
},
138+
Accessor::IndexExpression(expression) => {
139+
index = expression.invoke(function_dispatcher, context)?;
140+
trace!("Expression result: '{:?}'", index);
141+
},
142+
}
143+
144+
if index.is_number() {
145+
if let Some(array) = value.as_array() {
146+
let Some(index) = index.as_u64() else {
147+
return Err(DscError::Parser("Index is not a valid number".to_string()));
148+
};
149+
let index = usize::try_from(index)?;
150+
if index >= array.len() {
151+
return Err(DscError::Parser("Index out of bounds".to_string()));
152+
}
153+
value = array[index].clone();
154+
} else {
155+
return Err(DscError::Parser("Index access on non-array value".to_string()));
156+
}
157+
}
158+
else if !index.is_null() {
159+
return Err(DscError::Parser("Invalid index type".to_string()));
146160
}
147161
}
148162

0 commit comments

Comments
 (0)