@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
80 lines • 3.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.loops = void 0;
const common_syntax_probability_1 = require("../../common-syntax-probability");
const post_process_1 = require("./post-process");
const type_1 = require("../../../../r-bridge/lang-4.x/ast/model/type");
const statistics_file_1 = require("../../../output/statistics-file");
const visitor_1 = require("../../../../r-bridge/lang-4.x/ast/model/processing/visitor");
const initialLoopInfo = {
forLoops: (0, common_syntax_probability_1.emptyCommonSyntaxTypeCounts)(),
forLoopVar: (0, common_syntax_probability_1.emptyCommonSyntaxTypeCounts)(),
forBody: (0, common_syntax_probability_1.emptyCommonSyntaxTypeCounts)(),
whileLoops: (0, common_syntax_probability_1.emptyCommonSyntaxTypeCounts)(),
whileBody: (0, common_syntax_probability_1.emptyCommonSyntaxTypeCounts)(),
repeatLoops: 0n,
repeatBody: (0, common_syntax_probability_1.emptyCommonSyntaxTypeCounts)(),
breakStatements: 0,
nextStatements: 0,
/** apply, tapply, lapply, ...*/
implicitLoops: 0,
nestedExplicitLoops: 0,
deepestExplicitNesting: 0
};
const isImplicitLoop = /[lsvmt]?apply/;
function visitLoops(info, input) {
// holds number of loops and their nesting depths
const loopStack = [];
(0, visitor_1.visitAst)(input.normalizedRAst.ast, node => {
switch (node.type) {
case type_1.RType.Next:
info.nextStatements++;
return;
case type_1.RType.Break:
info.breakStatements++;
return;
case type_1.RType.FunctionCall:
if (node.named && isImplicitLoop.test(node.functionName.lexeme)) {
info.implicitLoops++;
(0, statistics_file_1.appendStatisticsFile)(exports.loops.name, 'implicit-loop', [node.functionName.info.fullLexeme ?? node.functionName.lexeme], input.filepath);
}
return;
case type_1.RType.ForLoop:
(0, common_syntax_probability_1.updateCommonSyntaxTypeCounts)(info.forLoops, node.vector);
(0, common_syntax_probability_1.updateCommonSyntaxTypeCounts)(info.forLoopVar, node.variable);
(0, common_syntax_probability_1.updateCommonSyntaxTypeCounts)(info.forBody, ...node.body.children);
break;
case type_1.RType.WhileLoop:
(0, common_syntax_probability_1.updateCommonSyntaxTypeCounts)(info.whileLoops, node.condition);
(0, common_syntax_probability_1.updateCommonSyntaxTypeCounts)(info.whileBody, ...node.body.children);
break;
case type_1.RType.RepeatLoop:
info.repeatLoops++;
(0, common_syntax_probability_1.updateCommonSyntaxTypeCounts)(info.repeatBody, ...node.body.children);
break;
default: return;
}
(0, statistics_file_1.appendStatisticsFile)(exports.loops.name, 'all-loops', [node.info.fullLexeme ?? node.lexeme], input.filepath);
if (loopStack.length > 0) {
info.nestedExplicitLoops++;
info.deepestExplicitNesting = Math.max(info.deepestExplicitNesting, loopStack.length);
}
loopStack.push(node);
}, node => {
// drop again :D
if (node.type === type_1.RType.ForLoop || node.type === type_1.RType.WhileLoop || node.type === type_1.RType.RepeatLoop) {
loopStack.pop();
}
});
}
exports.loops = {
name: 'Loops',
description: 'All looping structures in the document',
process(existing, input) {
visitLoops(existing, input);
return existing;
},
initialValue: initialLoopInfo,
postProcess: post_process_1.postProcess
};
//# sourceMappingURL=loops.js.map