Skip to content

Commit f21d593

Browse files
committed
refactor: robustify with parameters
1 parent 20caa02 commit f21d593

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

src/dataflow/eval/resolve/alias-tracking.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { BuiltInIdentifierConstant } from '../../environments/built-in';
1010
import { type IEnvironment, type REnvironmentInformation } from '../../environments/environment';
1111
import { Identifier, ReferenceType } from '../../environments/identifier';
1212
import { resolveByName, resolveByNameAnyType } from '../../environments/resolve-by-name';
13-
import { EdgeType } from '../../graph/edge';
13+
import { DfEdge, EdgeType } from '../../graph/edge';
1414
import type { DataflowGraph } from '../../graph/graph';
1515
import { onReplacementOperator, type ReplacementOperatorHandlerArgs } from '../../graph/unknown-replacement';
1616
import { onUnknownSideEffect } from '../../graph/unknown-side-effect';
@@ -21,7 +21,7 @@ import { setFrom } from '../values/sets/set-constants';
2121
import { resolveNode } from './resolve';
2222
import type { ReadOnlyFlowrAnalyzerContext } from '../../../project/context/flowr-analyzer-context';
2323
import type { RSymbol } from '../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
24-
import { RLoopConstructs } from '../../../r-bridge/lang-4.x/ast/model/model';
24+
import { RLoopConstructs, RNode } from '../../../r-bridge/lang-4.x/ast/model/model';
2525
import { RoleInParent } from '../../../r-bridge/lang-4.x/ast/model/processing/role';
2626

2727
export type ResolveResult = Lift<ValueSet<Value[]>>;
@@ -294,21 +294,7 @@ onReplacementOperator((args: ReplacementOperatorHandlerArgs) => {
294294
});
295295

296296
function isNestedInLoop(node: RNodeWithParent | undefined, ast: AstIdMap): boolean {
297-
const parent = node?.info.parent;
298-
if(node === undefined || !parent) {
299-
return false;
300-
}
301-
302-
const parentNode = ast.get(parent);
303-
if(parentNode === undefined) {
304-
return false;
305-
}
306-
307-
if(parentNode.type === RType.WhileLoop || parentNode.type === RType.RepeatLoop || parentNode.type === RType.ForLoop) {
308-
return true;
309-
}
310-
311-
return isNestedInLoop(parentNode, ast);
297+
return RNode.iterateParents(node, ast).some(RLoopConstructs.is);
312298
}
313299

314300
/**
@@ -368,19 +354,24 @@ export function trackAliasesInGraph(id: NodeId, graph: DataflowGraph, ctx: ReadO
368354

369355
const isFn = t === VertexType.FunctionCall;
370356
const outgoingEdges = graph.outgoingEdges(id) ?? [];
357+
let foundRetuns = false;
371358
// travel all read and defined-by edges
372359
for(const [targetId, { types }] of outgoingEdges) {
373360
if(isFn) {
374361
if(types === EdgeType.Returns || types === EdgeType.DefinedByOnCall || types === EdgeType.DefinedBy) {
375362
queue.add(targetId, baseEnvironment, cleanFingerprint, false);
376363
}
364+
foundRetuns ||= DfEdge.includesType({ types }, EdgeType.Returns);
377365
continue;
378366
}
379367
// currently, they have to be exact!
380368
if(types === EdgeType.Reads || types === EdgeType.DefinedBy || types === EdgeType.DefinedByOnCall) {
381369
queue.add(targetId, baseEnvironment, cleanFingerprint, false);
382370
}
383371
}
372+
if(isFn && !foundRetuns) {
373+
return Top;
374+
}
384375
}
385376

386377
if(forceTop || resultIds.length === 0) {
@@ -391,7 +382,7 @@ export function trackAliasesInGraph(id: NodeId, graph: DataflowGraph, ctx: ReadO
391382
for(const id of resultIds) {
392383
const node = idMap.get(id);
393384
if(node !== undefined) {
394-
if(node.info.role === RoleInParent.ParameterDefaultValue) {
385+
if(node.info.role === RoleInParent.ParameterDefaultValue || RNode.iterateParents(node, idMap).some(p => p.info.role === RoleInParent.ParameterDefaultValue)) {
395386
return Top;
396387
}
397388
values.add(valueFromRNodeConstant(node));

src/r-bridge/lang-4.x/ast/model/model.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,19 +344,32 @@ export const RNode = {
344344
* Returns the direct parent of a node.
345345
* Usually, only root nodes do not have a parent, and you can assume that there is a
346346
* linear chain of parents leading to the root node.
347+
* @see {@link iterateParents} - to get all parents of a node
347348
*/
348-
directParent<OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation>, idMap: Map<NodeId, RNode<OtherInfo>>): RNode<OtherInfo> | undefined {
349+
directParent<OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation>, idMap: Map<NodeId, RNode<OtherInfo & ParentInformation>>): RNode<OtherInfo & ParentInformation> | undefined {
349350
const parentId = node.info.parent;
350351
if(parentId === undefined) {
351352
return undefined;
352353
}
353354
return idMap.get(parentId);
354355
},
356+
/**
357+
* Returns an iterable of all parents of a node, starting with the direct parent and ending with the root node.
358+
*/
359+
*iterateParents<OtherInfo>(this: void, node: RNode<OtherInfo & ParentInformation> | undefined, idMap: Map<NodeId, RNode<OtherInfo & ParentInformation>>): Generator<RNode<OtherInfo & ParentInformation>> {
360+
let currentNode: RNode<OtherInfo & ParentInformation> | undefined = node;
361+
while(currentNode) {
362+
currentNode = RNode.directParent(currentNode, idMap);
363+
if(currentNode) {
364+
yield currentNode;
365+
}
366+
}
367+
},
355368
/**
356369
* In contrast to the nesting stored in the {@link RNode} structure,
357370
* this function calculates the depth of a node by counting the number of parents until the root node is reached.
358371
*/
359-
depth(this: void, node: RNode, idMap: Map<NodeId, RNode>): number {
372+
depth(this: void, node: RNode<ParentInformation>, idMap: Map<NodeId, RNode<ParentInformation>>): number {
360373
let depth = 0;
361374
let currentNode: RNode | undefined = node;
362375
while(currentNode) {

test/functionality/dataflow/query/resolve-value-query.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ describe('Resolve Value Query', withTreeSitter( parser => {
5757
testQuery('No call-sites with parameter', 'f <- function(x=42) { \nprint(x)}', ['2@x'], [[Top]]);
5858
testQuery('No call-sites with calculated parameter', 'f <- function(x=42+1) { \nprint(x)}', ['2@x'], [[Top]]);
5959
testQuery('No call-sites with maybe parameter', 'f <- function(x=42) { if(u) x <- 2\nprint(x)}', ['2@x'], [[Top]]);
60+
testQuery('No call-sites with maybe parameter and calc', 'f <- function(x=42+1) { if(u) x <- 2\nprint(x)}', ['2@x'], [[Top]]);
6061
});
6162

6263
describe('For now suboptimal', () => {

0 commit comments

Comments
 (0)