-
Notifications
You must be signed in to change notification settings - Fork 11
Implementing a new edit type or template
For the purposes of this discussion, an edit (currently!) consists of:
The editType, corresponding to a value of the Mutation enumeration
the location at which the edit will be applied
the source code that is used to fill in any "holes" in the mutation.
So for deletion, the editType is Mutation.DELETE, the location is the atom ID in the buggy program that will be deleted, and there is no necessary source code (because you don't need to fill in any holes in a deletion).
For an append, the editType is Mutation.APPEND, the location is the atom ID after which some potential fix code will be inserted, and the source code is the statement that is inserted after that location.
...and so on.
Given that, if you want to implement a new edit type, the following steps are necessary (these were always necessary, but it's rather easier to explain/follow with this new organization):
(0) If necessary, add a value to the Mutation enumeration. You may not need to do this if you're implementing existing Par templates; just reuse the appropriate value. If you add something, you'll need to update the configure code in Search (see below).
(1) Update both the doesEditApply and editSources functions. The first function says whether an edit applies at a location; the second returns a list of possible "fix code" to use to fill in the "holes" of an edit. If the edit does not apply at a location, it should return the empty set.
To illustrate, for deletion, the edit currently always applies (you can always delete a statement). Note that this may not actually be optimal, it's just what we're currently doing; for example, it may not be appropriate to delete a return statement in a non-void function.
This step may involve changing other parts of the GenProg4J codebase. For example, perhaps you need additional semantic information to determine if a statement is a reasonable source for an edit. In this case, you may need to edit the analyses/visitors we apply when parsing the source file, mostly in the genprog4java.java package, with info mostly stored in the JavaRepresentation module. Depends on what kind of info you need to help identify legal sources.
(2) Update the functions in Search that choose between and apply mutations, especially mutate (but also bruteForceOne, if you're feeling kind to me). You may not need to do much, here, since I've abstracted away much of the differences between edit types at this level; the real difference is whether you need to select "fix code" or not. For deletion, for example, you don't. For many others, you do.
(3) Update performEdit in JavaRepresentation. Again, much of the differences between the edits is abstracted away at this level, but there are minor distinctions that may manifest here.
Note that I probably "broke" templates that you've written by declaring fatal the application of edit types that I did not see explicit handling for in the code so far. I did not want to assume that the default behavior was correct, since some of it seemed like boilerplate code that was not mindful.
(4) Update the edit function in JavaEditOperation. This is the place where the edit is actually applied to an actual java program, and thus the place where much of the hard work is done.
Applicable edits in config files are specified using one of two flags, or the default. The flags are:
edits = semicolon separated list of edits you'd like to include editsWithWeights = semicolon separated lists of edit,weight pairs. The pairs are separated by commas.
So, if you wanted to do just a null check, you'd do edits=nullcheck
If you wanted null check and delete with equal weight, you could do: editsWithWeights = nullcheck,1.0;delete,1.0
And so on. Check out the configure function near the top of Search to see your edit options.
The third option is the "default", which includes append, delete, and replace, with equal weighting. This is what happens if you don't specify either edits or editsWithWeights in your config file.