+25
src/ast.rs
+25
src/ast.rs
···
81
81
DeclareImmutable(DeclareImmutable),
82
82
DeclareMutable(DeclareMutable),
83
83
Assign(Assign),
84
+
Expr(ExpressionStatement),
84
85
// Graph nodes
85
86
CreateGraphNode(CreateGraphNode),
86
87
AddGraphNodeAttribute(AddGraphNodeAttribute),
···
103
104
Self::DeclareImmutable(stmt) => stmt.fmt(f),
104
105
Self::DeclareMutable(stmt) => stmt.fmt(f),
105
106
Self::Assign(stmt) => stmt.fmt(f),
107
+
Self::Expr(stmt) => stmt.fmt(f),
106
108
Self::CreateGraphNode(stmt) => stmt.fmt(f),
107
109
Self::AddGraphNodeAttribute(stmt) => stmt.fmt(f),
108
110
Self::CreateEdge(stmt) => stmt.fmt(f),
···
161
163
write!(f, " {}", attr)?;
162
164
}
163
165
write!(f, " at {}", self.location)
166
+
}
167
+
}
168
+
169
+
/// An `expression` statement whose output is ignored
170
+
#[derive(Debug, Eq, PartialEq)]
171
+
pub struct ExpressionStatement {
172
+
pub value: Expression,
173
+
pub location: Location,
174
+
}
175
+
176
+
impl From<ExpressionStatement> for Statement {
177
+
fn from(statement: ExpressionStatement) -> Statement {
178
+
Statement::Expr(statement)
179
+
}
180
+
}
181
+
182
+
impl std::fmt::Display for ExpressionStatement {
183
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
184
+
write!(
185
+
f,
186
+
"{} at {}",
187
+
self.value, self.location,
188
+
)
164
189
}
165
190
}
166
191
+10
src/checker.rs
+10
src/checker.rs
···
220
220
Self::DeclareImmutable(stmt) => stmt.check(ctx),
221
221
Self::DeclareMutable(stmt) => stmt.check(ctx),
222
222
Self::Assign(stmt) => stmt.check(ctx),
223
+
Self::Expr(stmt) => stmt.check(ctx),
223
224
Self::CreateGraphNode(stmt) => stmt.check(ctx),
224
225
Self::AddGraphNodeAttribute(stmt) => stmt.check(ctx),
225
226
Self::CreateEdge(stmt) => stmt.check(ctx),
···
261
262
used_captures.extend(value.used_captures.iter().cloned());
262
263
let var_result = self.variable.check_set(ctx, value.into())?;
263
264
used_captures.extend(var_result.used_captures);
265
+
Ok(StatementResult { used_captures })
266
+
}
267
+
}
268
+
269
+
impl ast::ExpressionStatement {
270
+
fn check(&mut self, ctx: &mut CheckContext) -> Result<StatementResult, CheckError> {
271
+
let mut used_captures = HashSet::new();
272
+
let value = self.value.check(ctx)?;
273
+
used_captures.extend(value.used_captures.iter().cloned());
264
274
Ok(StatementResult { used_captures })
265
275
}
266
276
}
+1
src/execution/lazy.rs
+1
src/execution/lazy.rs
···
231
231
Self::DeclareImmutable(statement) => statement.execute_lazy(exec),
232
232
Self::DeclareMutable(statement) => statement.execute_lazy(exec),
233
233
Self::Assign(statement) => statement.execute_lazy(exec),
234
+
Self::Expr(statement) => statement.value.evaluate_lazy(exec).map(|_| ()),
234
235
Self::CreateGraphNode(statement) => statement.execute_lazy(exec),
235
236
Self::AddGraphNodeAttribute(statement) => statement.execute_lazy(exec),
236
237
Self::CreateEdge(statement) => statement.execute_lazy(exec),
+9
src/execution/strict.rs
+9
src/execution/strict.rs
···
16
16
use crate::ast::AddEdgeAttribute;
17
17
use crate::ast::AddGraphNodeAttribute;
18
18
use crate::ast::Assign;
19
+
use crate::ast::ExpressionStatement;
19
20
use crate::ast::Attribute;
20
21
use crate::ast::AttributeShorthand;
21
22
use crate::ast::AttributeShorthands;
···
232
233
Statement::DeclareImmutable(s) => s.location,
233
234
Statement::DeclareMutable(s) => s.location,
234
235
Statement::Assign(s) => s.location,
236
+
Statement::Expr(s) => s.location,
235
237
Statement::CreateGraphNode(s) => s.location,
236
238
Statement::AddGraphNodeAttribute(s) => s.location,
237
239
Statement::CreateEdge(s) => s.location,
···
249
251
Statement::DeclareImmutable(statement) => statement.execute(exec),
250
252
Statement::DeclareMutable(statement) => statement.execute(exec),
251
253
Statement::Assign(statement) => statement.execute(exec),
254
+
Statement::Expr(statement) => statement.execute(exec),
252
255
Statement::CreateGraphNode(statement) => statement.execute(exec),
253
256
Statement::AddGraphNodeAttribute(statement) => statement.execute(exec),
254
257
Statement::CreateEdge(statement) => statement.execute(exec),
···
279
282
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
280
283
let value = self.value.evaluate(exec)?;
281
284
self.variable.set(exec, value)
285
+
}
286
+
}
287
+
288
+
impl ExpressionStatement {
289
+
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
290
+
self.value.evaluate(exec).map(|_| ())
282
291
}
283
292
}
284
293
+8
src/parser.rs
+8
src/parser.rs
···
482
482
}
483
483
484
484
fn parse_statement(&mut self) -> Result<ast::Statement, ParseError> {
485
+
if matches!(self.peek(), Ok( '#' | '"' | '@' | '$' | '(' | '[' | '{')) {
486
+
if let Ok(value) = self.parse_expression() {
487
+
return Ok(ast::Statement::Expr(ast::ExpressionStatement {
488
+
location: self.location,
489
+
value,
490
+
}));
491
+
}
492
+
}
485
493
let keyword_location = self.location;
486
494
let keyword = self.parse_name("keyword")?;
487
495
self.consume_whitespace();