-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Backward slicing #300
Comments
@min-nguyen Let’s meet at our usual time on Friday, but feel to ping me in the meantime. On Friday we can look at some of the examples I’ve sketched out to try to understand what we want from projection (= extracting subcomputations). |
@min-nguyen Added eliminator join rules (which are probably what you expected). |
@min-nguyen The approach I’ve settled on is based on “annotations”: one bit per term constructor to identify whether that node is “selected” or not. Going forward, “selected” means “available”. Going backward, “selected” means “needed”. From the projectional experiment, I’ve retained the idea that the slicing relations take an additional α which tracks whether input resources (parts of values that get consumed by pattern-matching) are available (going forward) or needed (going backwards). The projectional idea itself is trickier than I thought and something we will probably have to come back to in another paper. To implement backward slicing as specified, you’ll need to make some minor changes to the representation of traces, so that you can implement the var, op, nil and int cases. These rules need the know the ρ that the original expression was evaluated in. In the formal setting (which you can basically read in a dependently typed way), a trace T is a term (in the metalanguage) of type ρ, e \eval v. In other words, \eval is an inductively defined relation and ρ, e and v are “indices” that are all mentioned in the type of the relation. For example in Agda one could obtain these by simply extract the relevant part of the type of T. In a simply-typed setting such as PureScript or Haskell 98, we need to make explicit in the value some of that information that would otherwise be carried by the type. That means the var, op, nil and int constructors all need to have an explicit ρ argument. A similar consideration applies to the apply-prim and binary-apply rules, which need to access the value of the original computation (the v that occurs in the type of T). Again, in a simply-typed setting this means enriching the respective trace constructors with values. For example, the apply-prim trace form T U needs to record the value associated with T and the value associated with U. Ping me if this doesn’t make much sense! |
@min-nguyen Here are some notes/comments on your latest commit. Overall looks good. I realise this is WIP, so some of these may already be in hand:
Let’s chat tomorrow if any of these would benefit from some discussion. |
I’ve finished migrating the old code to arbitrary data types, so the parameterised version of
The recursive stuff isn’t easy to grok and I wouldn’t worry if it’s hard to intuit what’s going on initially. Ironically (perhaps) it’s a case where the imperative implementation is almost trivial by comparison, so I guess the difficulty will come trying to prove that the two are equivalent. Luckily, join imposes a hard constraint on the things being joined (namely that they are the same thing modulo annotations) so you’ll discover quickly enough if you’re trying to merge two environments, or two lists of recusive definitions, that aren’t compatible in this sense. |
@min-nguyen Thanks for the latest commit - looking pretty close now. Some additional comments:
I’ve pushed a minor commit that applies some of the above suggestions. I didn’t manage to convince myself that we have is correct yet – in particular it looks like It might also be able to factor In terms of how to proceed after that, my suggestion would be to look at |
@min-nguyen Just some tidying up to do and then we can close this task:
|
@min-nguyen Implemented #376, which solves the performance issue to the point where backward slicing can work. Did some other tidying up/bug-fixes; can’t do any thorough testing of backward slicing until #382, but at least we are now exercising |
Implement the bwd slicing rules from the paper draft. (I’ve parked the “projectional” idea for now and gone back to a very simple system that just tracks data dependencies – let’s implement this and then revisit projection.) We’ll also need to implement the join operation to merge environments.
Failing test cases:
arithmetic.fld
:BinaryApp
case needs to push binding of operator name back into environmentcompose.fld
Let
should useNone
rather thane2
as the continuation(+1) 1
has become1 (+)
evalArgs_bwd
in terms ofzip
andfold
AppOp
andBinaryApp
cases should demand arguments according to demand on resultThe text was updated successfully, but these errors were encountered: