Multiple contributions in single contributes declaration

Issue #209 resolved
Jesper Öqvist created an issue

Current version: JastAdd2 2.1.11-7-g910ba89

#Motivation

The contributes declaration is currently used to either contribute a single item to one collection attribute, or a single item to multiple attributes.

For example, we could create a collection attribute to find supertypes of class declarations and write a contribution statement for the superclass like this:

ClassDecl contributes getSuperclass() when hasSuperclass() to CompilationUnit.supertypes() for compilationUnit();

If we want to contribute multiple things for a single node it gets trickier, for example if we want to contribute all interfaces implemented by a class declaration it would be useful if an Iterable contribution could be specified, something like this:

ClassDecl contributes each getImplementsList() to CompilationUnit.supertypes() for compilationUnit();

The addition of the each keyword here indicates that the contribution is an Iterable containing individual contributions. Using this keyword should work well since it is already a JastAdd reserved word.

One may argue that the given example is slightly unrealistic because one would probably not want to mix Access (from the implements list) and TypeDecl (as returned by superclass()) in a single collection, however it seems like similar cases where multiple contributions for a single node are needed could easily occur in practice.

#Workarounds

One workaround for this use case is to add contributions for Access or TypeAccess, however this is problematic because such nodes occur in many other places than only the implements list of a ClassDecl, so such contributions would have to have a when clause to figure out if the Access is in an Implements list.

Another workaround is to let each contribution be a Collection, and use addAll as the mutation method. This then requires creating singleton wrapper collections for each non-collection contribution, also this does not work with non-collection iterable value-expressions such as AST lists.

#Proposed Changes

##Additions to Parser

Allow an each keyword after contributes. This should flag the contribution as an iterable contribution.

##Changes to Code Generation

Code generation must be modified to support the new iterable contribution declaration. This should be simple since we do not need to modify the computation of contributors, only the way a contribution is added to the collection value, by generating a loop to iterate over the contribution values.

##Additions to Documentation

Contribution declaration

N1 contributes each value-exp
  when cond-exp
  to N2.a()
  for N2-ref-exp;

The each keyword indicates that value-exp is an iterable collection of single contributions which should all be added to the target collection attribute by iterating over the result of value-exp and adding each to the collection.

##References:

Comments (3)

  1. Jesper Öqvist reporter
    • edited description

    Fixed error in example: each was used in the wrong contribution.

  2. Log in to comment