I am thinking static analysis – that can be run to get all baked-in choice points.
It reminds me a bit of virtual methods and tables — each virtual method is a choice by design – that would have been an if-then-else in a procedural language – and hence part of the core program logic.
Choice points are somewhat dynamic, depending on the arguments – for example, append(A,B,[1,2,3]) leaves choicepoints but append([1],[2,3],X) doesn’t. So, what would you expect static analysis to do for append/3?
I was thinking that choice points and indexing is tightly interrelated and that indexing is only established after bound arguments leave call choices open – that is, if i understood this correctly.
An open call choice is in effect another case in the search tree …
And, if i think about this now, its also made (more) explicit in Single Sided Unification (SSUs) which expects an exhaustive clause list of cases in the head – from a choice point / indexing perspective – and flags an error otherwise – which is very useful information at compile time.
Hence, a static analysis would in effect (dummy) bind arguments and check if these leave choice points when indexed.
So, such a static analysis would largely (or completely?) provide a view into how the program is indexed … which is a reflection of baked-in decision points.
Currently, such an understanding can only be derived by running the program and inspecting choice points during execution with the debugger – or by identifying left over choice points – which may or may not be desired.
(more) Edit:
Also, the → construct plays a role when used to remove alternative goal definitions, and bake choices inside of goal predicate – not visible to indexing – as far as i can tell.
It seems that the designer can thereby decide which choices to leave to indexing and which to remove – hence, not all design choices show up as choice points, but many (non-deterministic ones) do
p(a,X) leaves a choicepoint but p(b,X) doesn’t. (With first-argument indexing).
BTW, you can “force” the just-in-time-indexing by calling with a nonsense argument, e.g. ?-p(-,-). But you can’t use the result of jiti_list/1 to check for potential backtracking because there are other considerations – e.g., an index requires a certain number of clauses (I think it’s 10 or so) because otherwise sequential search is faster.
I guess, it also depends whether by design there could exist another p(b, n) or not – what the “cardinality” of the p’ relationship between its first and second argument (and vice-versa) is – hence, perhaps the designation of the predicate as deterministic or non-deterministic-- is much more relevant that choice points for mapping out the decision-space.