Make some more progress on the Alloy article.

This commit is contained in:
2023-05-14 16:00:55 -07:00
parent 9ae4798d80
commit 384f5de765
2 changed files with 298 additions and 47 deletions

View File

@@ -10,8 +10,7 @@ sig Bitfield {
/* A filter state has filterFlags and excludeFlags, both represented as conjunctions. */
sig FilterState {
, include: Bitfield
, exclude: Bitfield
, curFilter: Bitfield
}
/* Initially, no search has happeneed for a scope, so its 'found' is not set to anything. */
@@ -111,41 +110,43 @@ matchingBitfieldExists3: run {
}
}
pred configureState[filterState: FilterState] {
pred possibleState[filterState: FilterState] {
some initialState: FilterState {
// Each lookup in scope starts with empty filter and exclude flags
bitfieldEmpty[initialState.include] and bitfieldEmpty[initialState.exclude]
// Each lookup in scope starts with empty filter flags
bitfieldEmpty[initialState.curFilter]
// The intermediate states (bf1) are used for sequencing of operations.
some bf1 : Bitfield {
// The intermediate states (bitfieldMiddle) are used for sequencing of operations.
some bitfieldMiddle : Bitfield {
// Add "Public" depending on skipPrivateVisibilities
addBitfieldFlag[initialState.include, bf1, Public] or
bitfieldEqual[initialState.include, bf1]
addBitfieldFlag[initialState.curFilter, bitfieldMiddle, Public] or
bitfieldEqual[initialState.curFilter, bitfieldMiddle]
// If it's a method receiver, add method or field restriction
addBitfieldFlag[bf1, filterState.include, MethodOrField] or
addBitfieldFlag[bitfieldMiddle, filterState.curFilter, MethodOrField] or
// if it's not a receiver, filter to non-methods (could be overridden)
addBitfieldFlagNeg[bf1, filterState.include, Method] or
// Maybe methods are not being included but it's not a receiver, so no change.
bitfieldEqual[bf1, filterState.include]
addBitfieldFlagNeg[bitfieldMiddle, filterState.curFilter, Method] or
// Maybe methods are not being curFilterd but it's not a receiver, so no change.
bitfieldEqual[bitfieldMiddle, filterState.curFilter]
}
// Exclude filter doesn't change here
initialState.exclude = filterState.exclude
}
}
pred oldUpdate[toSet: Bitfield + NotSet, setTo: FilterState] {
toSet' in Bitfield and bitfieldIntersection[toSet, setTo.include, toSet']
possibleStateExists: run {
some filterState : FilterState | possibleState[filterState] and #filterState.curFilter.positiveFlags = 1
}
pred update[toSet: Bitfield + NotSet, setTo: FilterState] {
toSet' in Bitfield and bitfieldIntersection[toSet, setTo.curFilter, toSet']
}
pred newUpdate[toSet: Bitfield + NotSet, setTo: FilterState] {
(not bitfieldIncomparable[toSet, setTo.include] and oldUpdate[toSet, setTo]) or
(bitfieldIncomparable[toSet, setTo.include] and toSet = toSet')
(not bitfieldIncomparable[toSet, setTo.curFilter] and update[toSet, setTo]) or
(bitfieldIncomparable[toSet, setTo.curFilter] and toSet = toSet')
}
pred updateOrSet[toSet: Bitfield + NotSet, setTo: FilterState] {
(toSet in NotSet and toSet' = setTo.include) or
(toSet not in NotSet and oldUpdate[toSet, setTo])
(toSet in NotSet and toSet' = setTo.curFilter) or
(toSet not in NotSet and update[toSet, setTo])
}
pred excludeBitfield[found: Bitfield + NotSet, exclude: Bitfield] {
@@ -163,7 +164,7 @@ fact step {
all searchState: SearchState {
some fs: FilterState {
// This is a possible combination of lookup flags
configureState[fs]
possibleState[fs]
// If a search has been performed before, take the intersection; otherwise,
// just insert the current filter flags.
@@ -178,21 +179,21 @@ example: run {
// a way that subsequent results of searching it will miss things.
eventually some symbol: Symbol, fs: FilterState, fsBroken: FilterState, exclude: Bitfield {
// Some search (fs) will cause a transition / modification of the search state...
configureState[fs]
possibleState[fs]
updateOrSet[searchState.found, fs]
// Such that a later, valid search... (fsBroken)
configureState[fsBroken]
possibleState[fsBroken]
excludeBitfield[searchState.found', exclude]
// Will allow for a symbol ...
// ... that are left out of the original search...
not bitfieldMatchesProperties[searchState.found, symbol]
// ... and out of the current search
not (bitfieldMatchesProperties[fs.include, symbol] and not bitfieldMatchesProperties[searchState.found, symbol])
not (bitfieldMatchesProperties[fs.curFilter, symbol] and not bitfieldMatchesProperties[searchState.found, symbol])
// But would be matched by the broken search...
bitfieldMatchesProperties[fsBroken.include, symbol]
bitfieldMatchesProperties[fsBroken.curFilter, symbol]
// ... to not be matched by a search with the new state:
not (bitfieldMatchesProperties[fsBroken.include, symbol] and not bitfieldMatchesProperties[exclude, symbol])
not (bitfieldMatchesProperties[fsBroken.curFilter, symbol] and not bitfieldMatchesProperties[exclude, symbol])
}
}
}