How to model conflicting trait member imports?

  trait Named {
    name : String
  }
  
  trait HasName {
    name : String
  }
  
  entity Foo extends Named, HasName {
//    name : String
  }
  [[ Entity(e, parents, as) ^ (module_scope) ]] :=
    distinct V(entity_scope)/Member | error "Duplicate member." @NAMES,
    distinct (W(entity_scope)/Member minus V(entity_scope)/Member) | error $[Conflicting trait member: [NAME]] @parents, 
    ...

The above example gives two errors in the traits, but if one uncomments the definition inside the entity we properly get an error message on the extends ....

The issue is that I’m using visible and reachable, and if there is no local definition these conflicting trait imports are both visible rather than both reachable and not visible. So using visible and reachable minus visible is not a good solution.

Possible solution #1, use path expressions

V(entity_scope, I*)/Member
W(entity_scope, E.E*.I*)/Member //but this wont work because it gives all ancestor member definitions

Possible solution #2, visible if some things would not be there

Currently the sets that can be created with the syntax include:

  • visible(scope)
  • reachable(scope)
  • reachable(scope) - visible(scope)

But what if we allow:

  • visible(scope - visible(scope))

Give me all things that would be visible if all visible things are not there anymore.

Workaround (or maybe better solution?), create multiple scopes per entity

  [[ Entity(e, parents, as) ^ (module_scope) ]] :=
    distinct V(entity_scope_local)/Member | error "Duplicate member." @NAMES,
    distinct V(entity_scope_super)/Member | error $[Conflicting trait member: [NAME]] @parents,
    entity_scope_local ---> entity_scope,
    entity_scope_super ---> entity_scope,
    ...
Submitted by Daco Harkes on 27 October 2016 at 11:50

On 28 October 2016 at 19:48 Daco Harkes commented:

Multiple scopes try

I tried modeling with multiple scopes:

  [[ Entity(e, parents, as) ^ (module_scope) ]] :=
    distinct W(entity_scope_local)/Member | error "Duplicate attribute, relation, role, inverse, or shortcut names." @NAMES,
    distinct V(entity_scope_inherit)/Member | error "Duplicate inherited attribute, relation, role, inverse, or shortcut names." @parents,
    Entity{e} <- module_scope,
    new entity_scope,
    new entity_scope_inherit,
    new entity_scope_local,
    entity_scope -I-> entity_scope_local,
    entity_scope -E-> entity_scope_inherit,
    entity_scope -P-> module_scope,
    Entity{e} =I=> entity_scope,
    ...

  [[ Attribute(a, t, m) ^ (entity_scope, entity_scope_local, module_scope) ]] :=
    Member{a} <- entity_scope_local,
    ...

  [[ Extends(parent) ^ (entity_scope, entity_scope_inherit) ]] :=
    Entity{parent} -> entity_scope,
    Entity{parent} <=I= entity_scope_inherit,
    ...

It still requires an extra label to get the priorities correct.

It allows for proper error messages, distinguishing external local definitions from inherited definitions.

However multiple scopes introduce other problems:

  • A complicated scope graph
  • Attributes are declared in entity_scope_local, but entity_scope_localhas no associated label, only the scope connected trough <-I- (inverted) has an associated name.

Name set queries

So how can we get the same name sets as in W(entity_scope_local) and V(entity_scope_inherit) without auxiliary scopes…

  [[ Entity(e, parents, as) ^ (module_scope) ]] :=
    distinct W(entity_scope, E* )/Member | error "Duplicate attribute, relation, role, inverse, or shortcut names." @NAMES,
    distinct V(entity_scope, I.I*.E* )/Member | error "Duplicate inherited attribute, relation, role, inverse, or shortcut names." @parents,

The V in V(entity_scope, I.I*.E* ) would mean, provided you only resolve through I.I*.E* what would then be visible? First go through an import edge (meaning must go to inherited things).
The W in V(entity_scope, E* ) would mean, provided you only resolve through E* what would then be reachable? (do not go through the inheritance import with label I).

For reference

Implementation without auxiliary scopes, that has the issue described in the starting post: https://github.com/MetaBorgCube/IceDust/blob/c4ee05ecf200b7f52a5fe55926804585f32aade1/icedust2/trans/analysis/model.nabl2

Implementation with auxiliary scopes: https://github.com/MetaBorgCube/IceDust/blob/6e8cecf325d805cd10015102a22c170c042bd35b/icedust2/trans/analysis/model.nabl2

Log in to post comments