Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
375 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
%% define set operations, negation as failure etc. | ||
%% :- include('utils.pl'). | ||
:- ensure_loaded('utils.pl'). | ||
|
||
%% filter invalid source ranges | ||
isInvalid(X) :- sourceRange(X, B, E, _), B >= E. | ||
|
||
%% nested sourceRanges | ||
containedWithin(X, Y) :- | ||
sourceRange(X, B1, E1, F), | ||
sourceRange(Y, B2, E2, F), | ||
B1 >= B2, | ||
E2 >= E1. | ||
|
||
%% valid replacements | ||
replaceWith(X, ';') :- isInitializer(X). | ||
replaceWith(X, ';') :- isFunction(X), not(isMain(X)). | ||
replaceWith(X, ';') :- isCompoundStatement(X). | ||
replaceWith(X, '') :- isDeclaration(X). | ||
replaceWith(X, '') :- isStatement(X). | ||
replaceWith(X, '0') :- isCondition(X). | ||
%% replaceWith(X, '1') :- isCondition(X). | ||
replaceWith(X, '') :- isExpr(X). | ||
|
||
|
||
isElement(X) :- sourceRange(X, _, _, _), not(isInvalid(X)). | ||
allElements(L) :- safeSetOf(X, isElement(X), L). | ||
clearLabel(X) :- retractall(hasBeenDeleted(X)), | ||
retractall(hasBeenPermanentlyDeleted(X)), | ||
retractall(hasUntrackedDependency(X)), | ||
retractall(isEssentialForFailure(X)). | ||
clearAllLabels(L) :- allElements(L), maplist(clearLabel, L). | ||
%% valid to remove | ||
isRemovable(X) :- replaceWith(X, _), sourceRange(X, _, _, _), | ||
not(hasBeenPermanentlyDeleted(X)), not(isEssentialForFailure(X)), | ||
not(isInvalid(X)), not(isMain(X)). | ||
|
||
%% finer level dependencies | ||
explicitDependsOn(X, Y) :- dependsOn(X, Y), not(containedWithin(X, Y)). | ||
%% not sure if i can trust the statement level dependencies so will have this | ||
%% for a sanity check | ||
implicitDependsOn(X, Y) :- explicitDependsOn(X, Y). | ||
implicitDependsOn(X, Y) :- containedWithin(X, Y). | ||
|
||
implicitLiveDependsOn(X, Y) :- implicitDependsOn(X, Y), not(hasBeenPermanentlyDeleted(X)). | ||
|
||
immediateDependsOn(X, Y) :- explicitDependsOn(X, Y). | ||
immediateDependsOn(X, Y) :- explicitDependsOn(X, Z), containedWithin(Z, Y), | ||
not(containedWithin(X, Y)). | ||
|
||
%% this needs tabling. swipl doesn't have that. | ||
%% transitiveImplicitDependsOn(X, Y) :- implicitDependsOn(X, Y). | ||
%% transitiveImplicitDependsOn(X, Y) :- implicitDependsOn(X, Z), | ||
%% transitiveImplicitDependsOn(Z, Y). | ||
%% allDependingOn(X, L) :- safeSetOf(Y, transitiveImplicitDependsOn(Y, X), S), | ||
%% exclude(hasBeenPermanentlyDeleted, S, L). | ||
%% allDependsOn(X, L) :- safeSetOf(Y, transitiveImplicitDependsOn(X, Y), S), | ||
%% exclude(hasBeenPermanentlyDeleted, S, L). | ||
%% transitiveRemovalList(X, L) :- allDependingOn(X, L1), append([X], L1, L). | ||
|
||
%% these will work without tabling (essential performing graph reachability) | ||
expandCurrentFrontierWorker([], NF, NF). | ||
expandCurrentFrontierWorker([H|T], PF, NF) :- safeSetOf(Y, implicitDependsOn(Y, | ||
H), S), merge_set(S, PF, PF1), expandCurrentFrontierWorker(T, PF1, NF). | ||
expandCurrentFrontier(CF, NF) :- expandCurrentFrontierWorker(CF, [], NF). | ||
allDependingOnWorker([], L, L). | ||
allDependingOnWorker([H|T], PL, L) :- expandCurrentFrontier([H|T], CF1), | ||
ord_subtract(CF1, PL, NF), merge_set(NF, PL, PL1), | ||
allDependingOnWorker(NF, PL1, L). | ||
allDependingOn(X, L) :- allDependingOnWorker([X], [], L1), ord_subtract(L1, [X], | ||
L2), include(isRemovable, L2, L). | ||
transitiveRemovalList(X, L) :- allDependingOnWorker([X], [X], L1), | ||
include(isRemovable, L1, L). | ||
|
||
expandCurrentFrontierBackwardWorker([], NF, NF). | ||
expandCurrentFrontierBackwardWorker([H|T], PF, NF) :- safeSetOf(Y, | ||
implicitDependsOn(H, Y), S), merge_set(S, PF, PF1), | ||
expandCurrentFrontierBackwardWorker(T, PF1, NF). | ||
expandCurrentFrontierBackward(CF, NF) :- expandCurrentFrontierBackwardWorker(CF, | ||
[], NF). | ||
allDependsOnWorker([], L, L). | ||
allDependsOnWorker([H|T], PL, L) :- expandCurrentFrontierBackward([H|T], CF1), | ||
ord_subtract(CF1, PL, NF), merge_set(NF, PL, PL1), | ||
allDependsOnWorker(NF, PL1, L). | ||
allDependsOn(X, L) :- allDependsOnWorker([X], [], L1), ord_subtract(L1, [X], | ||
L2), include(isRemovable, L2, L). | ||
|
||
|
||
%% transitiveImplicitLiveDependsOn(X, Y) :- implicitLiveDependsOn(X, Y). | ||
%% transitiveImplicitLiveDependsOn(X, Y) :- implicitLiveDependsOn(X, Z), | ||
%% transitiveImplicitLiveDependsOn(Z, Y). | ||
|
||
|
||
|
||
%% X has to be bound for these to work | ||
%% isTopLevel(X) :- not(implicitDependsOn(X, Y)), not(isInvalid(X)). | ||
%% isBottomLevel(X) :- not(implicitDependsOn(Y, X)), not(isInvalid(X)). | ||
isTopLevel(X) :- allDependsOn(X, L), length(L, 0). | ||
filterOutContainedWithin(_, [], L, L). | ||
filterOutContainedWithin(X, [H|T], L, R) :- ( | ||
containedWithin(H, X) -> filterOutContainedWithin(X, T, L, R); | ||
filterOutContainedWithin(X, T, [H|L], R)). | ||
isBottomLevel(X) :- allDependingOn(X, L1), filterOutContainedWithin(X, L1, [], L), | ||
length(L, 0). | ||
|
||
assertDeletion(X) :- assert(hasBeenDeleted(X)). | ||
assertUndoDeletion(X) :- retractall(hasBeenDeleted(X)). | ||
assertPermanentDeletion(X) :- assert(hasBeenPermanentlyDeleted(X)), retractall(hasBeenDeleted(X)). | ||
assertIsEssentialForFailure(X) :- assert(isEssentialForFailure(X)). | ||
assertHasUntrackedDependency(X) :- assert(hasUntrackedDependency(X)). | ||
|
||
recursivelyDelete(X) :- transitiveRemovalList(X, L), maplist(assertDeletion, L). | ||
delete(X) :- ( isRemovable(X) -> recursivelyDelete(X); true ). | ||
recursivelyUndoDelete(X) :- transitiveRemovalList(X, L), maplist(assertUndoDeletion, | ||
L). | ||
undoDelete(X) :- ( isRemovable(X) -> recursivelyUndoDelete(X); | ||
false ). | ||
undoAllDelete(L) :- safeSetOf(X, hasBeenDeleted(X), L), maplist(undoDelete, L). | ||
recursivelyPermanentlyDelete(X) :- transitiveRemovalList(X, L), | ||
maplist(assertPermanentDeletion, L). | ||
permanentlyDelete(X) :- ( isRemovable(X) -> recursivelyPermanentlyDelete(X); | ||
true ). | ||
recursivelyMarkEssential(X) :- assertIsEssentialForFailure(X), allDependsOn(X, | ||
L1), exclude(isEssentialForFailure, L1, L), | ||
maplist(assertIsEssentialForFailure, L). | ||
|
||
|
||
deleteList(L) :- maplist(assertDeletion, L). | ||
undoDeleteList(L) :- maplist(assertUndoDeletion, L). | ||
permanentlyDeleteList(L) :- maplist(assertPermanentDeletion, L). | ||
|
||
%% source range metric. is flawed, not sure if that reall matters though. | ||
sourceRangeSize(X, NumChar) :- sourceRange(X, B, E, _), NumChar is E - B. | ||
|
||
sourceRangesSizeWorker([], Total, Total). | ||
sourceRangesSizeWorker([H|T], A, B) :- sourceRangeSize(H, C), X is A + C, | ||
sourceRangesSizeWorker(T, X, B). | ||
sourceRangesSize(X, NumChar) :- sourceRangesSizeWorker(X, 0, NumChar). | ||
|
||
transitiveRemovalSize(X, NumChar) :- transitiveRemovalList(X, S), sourceRangeSize(X, | ||
A), sourceRangesSizeWorker(S, A, NumChar). | ||
|
||
|
||
%% dependency metric | ||
allTopLevelDependsOn(X, L) :- allDependsOn(X, L1), include(isTopLevel, L1, | ||
L). | ||
allBottomLevelDependingOn(X, L) :- allDependingOn(X, L1), include(isBottomLevel, L1, | ||
L). | ||
|
||
%% predicate to sort sourceranges in decreasing order by size | ||
%% sourceRangeCompare(Order, Term1, Term2) :- transitiveRemovalSize(Term1, A), | ||
%% transitiveRemovalSize(Term2, B), compare(Order, B, A). | ||
|
||
%% sort terms in ascending order based on number of dependants | ||
%% sortDependingOnAsc(Order, Term1, Term2) :- allDependingOn(Term1, L1), | ||
%% allDependingOn(Term2, L2), length(L1, Len1), length(L2, Len2), | ||
%% ( Len1 == Len2 -> compare(Order, Term1, Term2); | ||
%% compare(Order, Len1, Len2)). | ||
|
||
sortDependingOnAsc(Order, Term1, Term2) :- allBottomLevelDependingOn(Term1, | ||
BL1), length(BL1, BL1len), allBottomLevelDependingOn(Term2, BL2), | ||
length(BL2, BL2len), | ||
( BL1len == BL2len -> compare(Order, Term1, Term2); | ||
compare(Order, BL1len, BL2len)). | ||
|
||
sortDependsOnDescDependingOnAsc(Order, Term1, Term2) :- | ||
allTopLevelDependsOn(Term1, TL1), length(TL1, TL1len), | ||
allTopLevelDependsOn(Term2, TL2), length(TL2, TL2len), | ||
( TL1len == TL2len -> sortDependingOnAsc(Order, Term1, Term2); | ||
compare(Order, TL2len, TL1len)). | ||
|
||
sortDependsOnDescDependingOnDesc(Order, Term1, Term2) :- | ||
allTopLevelDependsOn(Term1, TL1), length(TL1, TL1len), | ||
allTopLevelDependsOn(Term2, TL2), length(TL2, TL2len), | ||
( TL1len == TL2len -> sortDependingOnAsc(Order, Term2, Term1); | ||
compare(Order, TL2len, TL1len)). | ||
|
||
sortAllDependingOnAsc(Order, Term1, Term2) :- allDependingOn(Term1, | ||
BL1), length(BL1, BL1len), allDependingOn(Term2, BL2), | ||
length(BL2, BL2len), | ||
( BL1len == BL2len -> compare(Order, Term1, Term2); | ||
compare(Order, BL1len, BL2len)). | ||
|
||
sortAllDependsOnAsc(Order, Term1, Term2) :- allDependsOn(Term1, | ||
BL1), length(BL1, BL1len), allDependsOn(Term2, BL2), | ||
length(BL2, BL2len), | ||
( BL1len == BL2len -> compare(Order, Term1, Term2); | ||
compare(Order, BL1len, BL2len)). | ||
|
||
|
||
sortAllDependsOnDescAllDependingOnDesc(Order, Term1, Term2) :- | ||
allDependsOn(Term1, TL1), length(TL1, TL1len), | ||
allDependsOn(Term2, TL2), length(TL2, TL2len), | ||
( TL1len == TL2len -> sortAllDependingOnAsc(Order, Term2, Term1); | ||
compare(Order, TL2len, TL1len)). | ||
|
||
sortAllDependingOnDescAllDependsOnDesc(Order, Term1, Term2) :- | ||
allDependingOn(Term1, TL1), length(TL1, TL1len), | ||
allDependingOn(Term2, TL2), length(TL2, TL2len), | ||
( TL1len == TL2len -> sortAllDependsOnAsc(Order, Term2, Term1); | ||
compare(Order, TL2len, TL1len)). | ||
|
||
sortAllHarmonicDesc(Order, Term1, Term2) :- | ||
allDependingOn(Term1, TLDO1), length(TLDO1, TLDO1len), | ||
allDependingOn(Term2, TLDO2), length(TLDO2, TLDO2len), | ||
allDependsOn(Term1, TLD1), length(TLD1, TLD1len), | ||
allDependsOn(Term2, TLD2), length(TLD2, TLD2len), | ||
H1 is (TLDO1len * TLD1len)/(TLDO1len + TLD1len), | ||
H2 is (TLDO2len * TLD2len)/(TLDO2len + TLD2len), | ||
( H1 == H2 -> compare(Order, Term1, Term2); | ||
compare(Order, H2, H1)). | ||
|
||
sortAllAverageDesc(Order, Term1, Term2) :- | ||
allDependingOn(Term1, TLDO1), length(TLDO1, TLDO1len), | ||
allDependingOn(Term2, TLDO2), length(TLDO2, TLDO2len), | ||
allDependsOn(Term1, TLD1), length(TLD1, TLD1len), | ||
allDependsOn(Term2, TLD2), length(TLD2, TLD2len), | ||
A1 is (TLDO1len + TLD1len), | ||
A2 is (TLDO2len + TLD2len), | ||
( A1 == A2 -> compare(Order, Term1, Term2); | ||
compare(Order, A2, A1)). | ||
|
||
|
||
sortSourceRangeSize(Order, Term1, Term2) :- sourceRangeSize(Term1, T1Size), | ||
sourceRangeSize(Term2, T2Size), | ||
( T1Size == T2Size -> compare(Order, Term1, Term2); | ||
compare(Order, T2Size, T1Size)). | ||
|
||
%% containedWithinList(X, Y) :- safeSetOf(Z, containedWithin(Z, Y), X). | ||
%% containedWithinListSorted(X, Y) :- safeSetOf(Z, containedWithin(Z, Y), L), | ||
%% predsort(sourceRangeCompare, L, X). | ||
|
||
allRemovable(L) :- safeSetOf(X, isRemovable(X), L). | ||
allRemovableWUD(L) :- setof(X, isRemovable(X), L1), | ||
exclude(hasUntrackedDependency, L1, L). | ||
allRemovableDeleted(L) :- safeSetOf(X, isRemovable(X), L1), | ||
include(hasBeenDeleted, L1, L). | ||
allRemovableDeletedWUD(L) :- setof(X, isRemovable(X), L1), | ||
include(hasBeenDeleted, L1, L2), exclude(hasUntrackedDependency, L2, | ||
L). | ||
allRemovableTopLevels(L) :- allRemovable(L1), include(isTopLevel, L1, L). | ||
allRemovableBottomLevels(L) :- allRemovable(L1), include(isBottomLevel, L1, L). | ||
|
||
allUntrackedDependencies(L) :- safeSetOf(X, hasUntrackedDependency(X), S), | ||
include(isRemovable, S, L1), predsort(sortSourceRangeSize, L1, L). | ||
allNotPermanentlyDeleted(L) :- allRemovable(L1), safeSetOf(X, | ||
isEssentialForFailure(X), S), merge_set(L1, S, L2), | ||
predsort(sortSourceRangeSize, L2, L). | ||
|
||
topScoringRemovable(X) :- allRemovable(L), !, | ||
findMin(sortAllDependsOnDescAllDependingOnDesc, L, X), !. | ||
topScoringRemovableWUD(X) :- allRemovableWUD(L), !, | ||
findMin(sortAllDependingOnDescAllDependsOnDesc, L, X), !. | ||
topScoringRemovableWUDH(X) :- allRemovableWUD(L), !, | ||
findMin(sortAllHarmonicDesc, L, X), !. | ||
topScoringRemovableWUDA(X) :- allRemovableWUD(L), !, | ||
findMin(sortAllAverageDesc, L, X), !. | ||
topScoringRemovableWUDR(X) :- allRemovableWUD(L), !, choose(L, X), !. | ||
topScoringRemovableWUD2(X) :- allRemovableWUD(L), !, | ||
findMin(sortAllDependsOnDescAllDependingOnDesc, L, X), !. | ||
topScoringRemovableDeleted(X) :- allRemovableDeleted(L), !, | ||
findMin(sortAllDependsOnDescAllDependingOnDesc, L, X), !. | ||
topScoringRemovableDeletedWUD(X) :- allRemovableDeletedWUD(L), !, | ||
findMin(sortAllDependingOnDescAllDependsOnDesc, L, X), !. | ||
topScoringRemovableDeletedWUD2(X) :- allRemovableDeletedWUD(L), !, | ||
findMin(sortAllDependsOnDescAllDependingOnDesc, L, X), !. | ||
|
||
|
||
markAllUntrackedDependencies(L) :- allRemovable(L), | ||
maplist(assertHasUntrackedDependency, L). | ||
|
||
%% compute stuff which prolog driver has to do. Only works for 1 file | ||
computeDeletionAction(X, (B, E, R)) :- sourceRange(X, B, E, _), replaceWith(X, | ||
R). | ||
computeDeletionActionForList(L, L1) :- maplist(computeDeletionAction, L, L1), !. | ||
recursivelyComputeDeletionAction(X, L1, L2) :- transitiveRemovalList(X, L1),!, | ||
maplist(computeDeletionAction, L1, L2), !. | ||
transitiveRemovalListSorted(X, L) :- transitiveRemovalList(X, L1), !, | ||
predsort(sortAllDependsOnDescAllDependingOnDesc, L1, L). | ||
transitiveRemovalListWUD(X, L) :- transitiveRemovalList(X, L1), !, | ||
exclude(hasUntrackedDependency, L1, L), !. | ||
transitiveRemovalListWUDSorted(X, L) :- transitiveRemovalListWUD(X, L1), | ||
predsort(sortAllDependsOnDescAllDependingOnDesc, L1, L). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
:- dynamic hasBeenDeleted/1, hasBeenPermanentlyDeleted/1, | ||
isEssentialForFailure/1, hasUntrackedDependency/1. | ||
|
||
%% :- multifile isInitializer/1, isFunction/1, isCompoundStatement/1, | ||
%% isDeclaration/1, isStatement/1, isCondition/1, isExpr/1, isMain/1, | ||
%% isInvalid/1, sourceRange/4, dependsOn/2. | ||
|
||
:- ensure_loaded('test.P'). | ||
:- ensure_loaded('inferenceRules.P'). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
isDeclaration(d1). | ||
sourceRange(d1, 1, 34, 'hello.cpp'). | ||
dependsOn(d1, s1). | ||
|
||
isInitializer(i1). | ||
sourceRange(i1, 10, 34, 'hello.cpp'). | ||
|
||
isStatement(s1). | ||
sourceRange(s1, 1, 34, 'hello.c'). | ||
|
||
isStatement(s2). | ||
sourceRange(s2, 1, 34, 'hello.cpp'). | ||
|
||
isStatement(s3). | ||
sourceRange(s3, 48, 56, 'hello.cpp'). | ||
|
||
isFunction(f1). | ||
sourceRange(f1, 46, 59, 'hello.cpp'). | ||
isMain(f1). | ||
|
||
isFunction(f2). | ||
sourceRange(f2, 63, 78, 'hello.cpp'). | ||
|
||
|
||
isCompoundStatement(c1). | ||
sourceRange(c1, 46, 58, 'hello.cpp'). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
%% define negation as failure | ||
%% not(P) :- (call(P) -> fail ; true). | ||
|
||
%% define set operations | ||
|
||
%% always succeeds | ||
safeSetOf(Template, Goal, Set) :- ( | ||
setof(Template, Goal, X) -> Set = X; | ||
Set = [] | ||
). | ||
|
||
|
||
%% define include and exclude | ||
%% include(:Goal, +List1, ?List2) | ||
include(_, [], []). | ||
include(P, [H|T], L) :- | ||
( call(P, H) -> | ||
L = [H|L1] | ||
; | ||
L = L1 | ||
), | ||
include(P, T, L1). | ||
exclude(_, [], []). | ||
exclude(P, [H|T], L) :- | ||
( call(P, H) -> | ||
L = L1 | ||
; | ||
L = [H|L1] | ||
), | ||
exclude(P, T, L1). | ||
:- import length/2, ith/3 from basics. | ||
nth0(R, List, Elt) :- R1 is R + 1, ith(R1, List, Elt). | ||
|
||
%% fails on an empty list | ||
findMaxW(_, [], CurrentFav, CurrentFav). | ||
findMaxW(Comparator, [H|T], CurrentFav, Result) :- ( | ||
call(Comparator, >, H, CurrentFav) -> findMaxW(Comparator, T, H, Result); | ||
findMaxW(Comparator, T, CurrentFav, Result)). | ||
findMax(Comparator, [H|T], X) :- findMaxW(Comparator, T, H, X). | ||
|
||
findMinW(_, [], CurrentFav, CurrentFav). | ||
findMinW(Comparator, [H|T], CurrentFav, Result) :- ( | ||
call(Comparator, <, H, CurrentFav) -> findMinW(Comparator, T, H, Result); | ||
findMinW(Comparator, T, CurrentFav, Result)). | ||
findMin(Comparator, [H|T], X) :- findMinW(Comparator, T, H, X). | ||
|
||
%% pick random element from list | ||
choose([], []). | ||
%% choose(List, Elt) :- | ||
%% length(List, Length), | ||
%% R is random(Length), | ||
%% nth0(R, List, Elt). | ||
:- import random/3 from random. | ||
choose(List, Elt) :- | ||
length(List, Length), | ||
random(0, Length, R), | ||
nth0(R, List, Elt). |