@@ -194,6 +194,143 @@ void Pkb::deriveTables() {
194
194
NAME_SET (callsTable.keys .begin (), callsTable.keys .end ());
195
195
this ->invertCallsTableIndexesProcNames =
196
196
NAME_SET (invertCallsTable.keys .begin (), invertCallsTable.keys .end ());
197
+
198
+ // clear cache after all tables are derived to ensure cache is empty at start
199
+ // of query.
200
+ this ->clearCache ();
201
+ }
202
+
203
+ void Pkb::deriveAllNextBipRelatedTables () {
204
+ this ->nextBipTable = deriveNextBipTable ();
205
+ this ->invertNextBipTable =
206
+ PkbTableTransformers::pseudoinvertFlattenKeys<LINE_NO, LINE_NO>(
207
+ this ->nextBipTable );
208
+ this ->nextBipTableIndexes =
209
+ LINE_SET (nextBipTable.keys .begin (), nextBipTable.keys .end ());
210
+ this ->invertNextBipTableIndexes =
211
+ LINE_SET (invertNextBipTable.keys .begin (), invertNextBipTable.keys .end ());
212
+ this ->areAllNextBipRelatedTablesDerived = true ;
213
+ }
214
+
215
+ void Pkb::deriveAllCloseNextBipRelatedTables () {
216
+ this ->closeNextBipTable = deriveCloseNextBipTable ();
217
+ this ->closeInvertNextBipTable =
218
+ PkbTableTransformers::pseudoinvertFlattenKeys<LINE_NO, LINE_NO>(
219
+ this ->closeNextBipTable );
220
+ this ->areAllCloseNextBipRelatedTablesDerived = true ;
221
+ }
222
+
223
+ KeysTable<PkbTables::LINE_NO, PkbTables::LINE_NOS> Pkb::deriveNextBipTable () {
224
+ KeysTable<PkbTables::LINE_NO, PkbTables::LINE_NOS> nextBipTable;
225
+
226
+ for (auto entry : nextBipsTable.map ) {
227
+ NEXTS nexts;
228
+
229
+ for (NEXT_BIP nextBip : entry.second ) {
230
+ if (std::holds_alternative<NEXT>(nextBip)) {
231
+ nexts.insert (std::get<NEXT>(nextBip));
232
+ } else if (std::holds_alternative<
233
+ std::tuple<LINE_NO, CallBranch, CALL_BRANCH_LABEL>>(
234
+ nextBip)) {
235
+ std::tuple tuple =
236
+ std::get<std::tuple<LINE_NO, CallBranch, CALL_BRANCH_LABEL>>(
237
+ nextBip);
238
+ nexts.insert (std::get<0 >(tuple));
239
+ }
240
+ }
241
+ nextBipTable.insert (std::pair (entry.first , nexts));
242
+ }
243
+ return nextBipTable;
244
+ }
245
+
246
+ KeysTable<PkbTables::LINE_NO, PkbTables::LINE_NOS>
247
+ Pkb::deriveCloseNextBipTable () {
248
+ KeysTable<PkbTables::LINE_NO, PkbTables::LINE_NOS> closeNextBipTable;
249
+ LINE_NOS allCallStmts = invertStatementTypeTable.map [StatementType::Call];
250
+
251
+ for (LINE_NO line : statementTypeTable.keys ) {
252
+ LINE_SET closeNextBips;
253
+ LINE_NOS callStmtsVisited;
254
+
255
+ // if stmt is a call, then include all lines in the called procedure as
256
+ // well.
257
+ if (statementTypeTable.map [line] == StatementType::Call) {
258
+ PROC calledProc = std::get<PROC>(usesTable.map [line]);
259
+ closeNextBips.merge (getAllStmtsOfTransitiveCall (calledProc));
260
+ }
261
+
262
+ // get transitive next bip of current line up to the end of the procedure
263
+ // the line is in.
264
+ closeNextBips.merge (getTransitiveNextBip (line));
265
+
266
+ // get transitive next bip of lines that call the procedure the initial line
267
+ // is in.
268
+ PROC procOfLine = statementProcTable.map [line];
269
+
270
+ for (LINE_NO callStmt : allCallStmts) {
271
+ PROC procCalledOnStmt = std::get<PROC>(usesTable.map [callStmt]);
272
+ if (procCalledOnStmt == procOfLine) {
273
+ callStmtsVisited.insert (callStmt);
274
+ closeNextBips.merge (getTransitiveNextBip (callStmt));
275
+ }
276
+ }
277
+
278
+ // get transitive next bip of all lines that directly/indirectly call the
279
+ // procedure the initial line is in.
280
+ PROCS allProcsThatTransitivelyCallProcOfLine =
281
+ closeInvertCallsTable.map [procOfLine];
282
+
283
+ for (PROC proc : allProcsThatTransitivelyCallProcOfLine) {
284
+ for (LINE_NO callStmt : allCallStmts) {
285
+ PROC procCalledOnStmt = std::get<PROC>(usesTable.map [callStmt]);
286
+ if (procCalledOnStmt == proc) {
287
+ callStmtsVisited.insert (callStmt);
288
+ closeNextBips.merge (getTransitiveNextBip (callStmt));
289
+ }
290
+ }
291
+ }
292
+
293
+ closeNextBipTable.insert (std::pair (line, closeNextBips));
294
+ }
295
+ return closeNextBipTable;
296
+ }
297
+
298
+ LINE_SET Pkb::getTransitiveNextBip (LINE_NO line) {
299
+ PROCS procsVisited;
300
+ LINE_SET result;
301
+ NEXTS transitiveNexts = getTransitiveNextStatements (line, {});
302
+
303
+ for (NEXT next : transitiveNexts) {
304
+ if (statementTypeTable.map [next] == StatementType::Call) {
305
+ PROC calledProc = std::get<PROC>(usesTable.map [next]);
306
+
307
+ if (procsVisited.find (calledProc) == procsVisited.end ()) {
308
+ procsVisited.insert (calledProc);
309
+
310
+ PROCS transitiveCalls = closeCallsTable.map [calledProc];
311
+ procsVisited.merge (transitiveCalls);
312
+ result.merge (getAllStmtsOfTransitiveCall (calledProc));
313
+ }
314
+ }
315
+ }
316
+ result.merge (transitiveNexts);
317
+ return result;
318
+ }
319
+
320
+ LINE_SET Pkb::getAllStmtsOfTransitiveCall (PROC proc) {
321
+ LINE_SET result;
322
+
323
+ // add all stmts of the input proc.
324
+ LINE_NOS stmtsInProc = invertStatementProcTable.map [proc];
325
+ result.merge (stmtsInProc);
326
+ PROCS transitiveCalls = closeCallsTable.map [proc];
327
+
328
+ for (PROC proc : transitiveCalls) {
329
+ // add all stmts of transitive procs called.
330
+ LINE_NOS stmtsInTransitiveProc = invertStatementProcTable.map [proc];
331
+ result.merge (stmtsInTransitiveProc);
332
+ }
333
+ return result;
197
334
}
198
335
199
336
void Pkb::deriveAllAffectsBipRelatedTables () {
0 commit comments