Skip to content

Commit 1766134

Browse files
committed
PS: expr-to-stmt conversions.
1 parent 0b4a7f9 commit 1766134

File tree

1 file changed

+101
-0
lines changed
  • powershell/ql/lib/semmle/code/powershell/ast/internal

1 file changed

+101
-0
lines changed

powershell/ql/lib/semmle/code/powershell/ast/internal/Synthesis.qll

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,104 @@ private module ParameterSynth {
272272
}
273273
}
274274
}
275+
276+
/**
277+
* Holds if `child` is a child of `n` that is a `Stmt` in the raw AST, but should
278+
* be mapped to an `Expr` in the synthesized AST.
279+
*/
280+
private predicate mustHaveExprChild(Raw::Ast n, Raw::Stmt child) {
281+
n.(Raw::AssignStmt).getRightHandSide() = child
282+
or
283+
n.(Raw::Pipeline).getAComponent() = child
284+
or
285+
n.(Raw::ReturnStmt).getPipeline() = child
286+
or
287+
n.(Raw::HashTableExpr).getAStmt() = child
288+
or
289+
n.(Raw::ParenExpr).getBase() = child
290+
or
291+
n.(Raw::DoUntilStmt).getCondition() = child
292+
or
293+
n.(Raw::DoWhileStmt).getCondition() = child
294+
or
295+
n.(Raw::ExitStmt).getPipeline() = child
296+
or
297+
n.(Raw::ForEachStmt).getIterableExpr() = child
298+
or
299+
// TODO: What to do about initializer and iterator?
300+
exists(Raw::ForStmt for | n = for | for.getCondition() = child)
301+
or
302+
n.(Raw::IfStmt).getACondition() = child
303+
or
304+
n.(Raw::SwitchStmt).getCondition() = child
305+
or
306+
n.(Raw::ThrowStmt).getPipeline() = child
307+
or
308+
n.(Raw::WhileStmt).getCondition() = child
309+
}
310+
311+
private class RawStmtThatShouldBeExpr extends Raw::Stmt {
312+
RawStmtThatShouldBeExpr() {
313+
this instanceof Raw::Cmd or
314+
this instanceof Raw::Pipeline or
315+
this instanceof Raw::PipelineChain or
316+
this instanceof Raw::IfStmt
317+
}
318+
319+
Expr getExpr() {
320+
result = TCmd(this)
321+
or
322+
result = TPipeline(this)
323+
or
324+
result = TPipelineChain(this)
325+
or
326+
result = TIf(this)
327+
}
328+
}
329+
330+
/**
331+
* Insert expr-to-stmt conversions where needed.
332+
*/
333+
private module ExprToStmtSynth {
334+
private class ExprToStmtSynth extends Synthesis {
335+
private predicate exprToSynthStmtChild(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt, Expr e) {
336+
this.child(parent, i, SynthChild(ExprStmtKind()), stmt) and
337+
e = stmt.(RawStmtThatShouldBeExpr).getExpr()
338+
}
339+
340+
private predicate child(Raw::Ast parent, ChildIndex i, Child child, Raw::Stmt stmt) {
341+
// Synthesize the expr-to-stmt conversion
342+
child = SynthChild(ExprStmtKind()) and
343+
stmt instanceof RawStmtThatShouldBeExpr and
344+
parent.getChild(toRawChildIndex(i)) = stmt and
345+
not mustHaveExprChild(parent, stmt)
346+
}
347+
348+
final override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
349+
this.child(parent, i, child, _)
350+
}
351+
352+
final override predicate exprStmtExpr(ExprStmt e, Expr expr) {
353+
exists(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt |
354+
e = TExprStmtSynth(parent, i) and
355+
this.exprToSynthStmtChild(parent, i, stmt, expr)
356+
)
357+
}
358+
359+
final override Location getLocation(Ast n) {
360+
exists(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt |
361+
n = TExprStmtSynth(parent, i) and
362+
this.exprToSynthStmtChild(parent, i, stmt, _) and
363+
result = stmt.getLocation()
364+
)
365+
}
366+
367+
final override string toString(Ast n) {
368+
exists(Raw::Ast parent, ChildIndex i, Raw::Stmt stmt |
369+
n = TExprStmtSynth(parent, i) and
370+
this.exprToSynthStmtChild(parent, i, stmt, _) and
371+
result = stmt.toString()
372+
)
373+
}
374+
}
375+
}

0 commit comments

Comments
 (0)