Assume we have an entity language where the properties of the entities are defined outside of the entities, like this:

Start.Module = <module <ID> <Definition*>>
Definition.Entity = <entity <ID>>
Definition.Property = <entity <ID> has property <ID>>

Is it possible to define a corresponding name binding?

The name binding below is not possible. defines Property p in e has a different meaning: it makes the definition p visible in term e.

Module(m, _) : 
  defines Module m
  scopes Entity

Entity(e) :
  defines Entity e

Property(e, p) :
  refers to Entity e
  defines Property p in e

If there is no way to express this in NaBL, how can this be achieved using the interfaces in lib/runtime/nabl/interface.str?

Note: a solution would be to do some desugaring before name analysis, and make the properties subterms of their entities such that name binding would be straightforward again. However, my actual use case is more complex and doing so would require me to do a lot of name binding analysis in the desugaring, which I hope to avoid.

Asked by Oskar van Rest on 11 December 2013 at 03:17

This is a tough one, because URIs at definition sites are known before task execution, but URIs at use sites are not. I see the following options to model your problem:

  1. Make the entity a NaBL property of the property.

    Property(e, p): defines Property p of entity e
    

    You can refer to a property of a given entity with refers to Property p of entity e.

  2. Handle each property declaration like a partial class declaration. Assume, its abstract syntax is something like Entity(e, Property(p)):

    Entity(e, _): defines non-unique PartialEntity e scopes Property
    Property(p): defines unique Property p
    

    You can also try the following additional rule:

    Entity(e): defines unique Entity e scopes Property imports Property from PartialEntity e
    
  3. We can think about

    Property(e, p): defines Property p in Entity e
    

    which is basically an import.

Answered by Guido Wachsmuth on 11 December 2013 at 09:00

Thanks for your quick reply. In my case, 1 and 2 won’t work unfortunately.

  1. This one fails because there can be multiple entities with the same name in different modules. When referring to a property, we need to figure out the entity it belongs to by looking at the URI of the entity. The name of the entity alone is not enough. For example:

    module m1
    entity User
    
    module m2
    entity User
    entity m1.User has property name
    

    Having m1.User as the property value is not possible either because inside module m1, the property can be referred to by either m1.User or User.

  2. This one fails for a similar reason.

  3. This would be great.

  4. Another workaround for me is to do two consecutive name analyses, but this sounds unnecessary complex. In the first analysis, we figure out the URIs of the entity references. Then with Stratego we transform all EntityRef(name) to EntityRef(moduleName, name) or simply perform desugaring to place all properties inside the entities they belong to. Then do a second name analysis to figure out the URIs for property references.

Note: the actual case is even more complex in that entities and properties can also be defined outside of modules. This makes it even harder to put properties inside their entities (in desugar-before) before doing any name analysis).

Answered by Oskar van Rest on 11 December 2013 at 09:42

Also, you may think that the language is flawed, but it is an actual use case: in Flujo, relationships between classes are (syntactically) first class citizens and are defined next to classes. Yet, a relationship belongs to two classes from a name binding perspective.

Answered by Oskar van Rest on 11 December 2013 at 09:56

Problem is solved now by transforming all EntityRef(name) into EntityRef(moduleName, name) in the desugar-before transformation, essentially doing a little bit of name analysis manually. Then I use properties like in your first suggestion.

Answered by Oskar van Rest on 13 December 2013 at 08:43