julian-klode/lingolang

Merging branches

julian-klode opened this issue · 2 comments

In the abstract interpreter, we will have branches, and depending on which branches were taken, there might be different states afterwards. For example, one branch might consume a variable a, and the other might consume a variable b. After joining the branches again, either a or b might have no permissions left.

There are a few ways to deal with this:

  1. Let the abstract interpreter map states to multiple states, essentially building a tree of states rather than a list.
  2. Let the states maintain lists of possible permissions per variable
  3. Intersect the permissions

1 would "easily" allow us to use per-branch information later, so if we enter into a branch with the same conditions as a previous branch, we only need to check that, so we could do stuff like if ... { consume a } else { consume b}; if ... { consume b } else { consume a }. This really requires us to abstractly interpret a lot of aspects of the program, and seems a bit out of scope though. We could do a similar thing in 2, by annotating each possible state with branch information.

3 seems to be easy. We'll have to introduce two new operations, one for intersecting values, and one equivalent to the union operation. The first one solves most cases, the latter one is needed for function parameters om func (om) om and or func(or) or = or func(om) or - while the result is an intersection (you can only do stuff with it you can do in all branches), the parameters are unions, as the different branches have different requirements on parameters, and you need to fulfill them both.

AFAICT, both operations are monoids, so that's nice.

1 is most likely the easiest option, but I believe it is not necessarily the cleanest or most efficient one.

Intersection / Union was implemented in in 7e146b1