Currently, we have a default lookup strategy encoded in the implementation.

  1. Lookup name in current scope.
  2. Lookup name in imports to current scope.
  3. Go one scope level up and repeat 1-3.

I tried to add something to the concrete syntax to allow for more flexibility, but this does not seem to be sufficient.

Foo(x):
   refers to imported NS x in current scope
   otherwise refers to NS x in current scope
   otherwise refers to imported NS x in surrounding scope
   otherwise refers to NS x in surrounding scope

Does this mean to lookup imported x in all surrounding scopes first, before you look for normal x in the surrounding scopes? How would you express the other way?
But more important, I doubt that this is easy to understand. If one has a lookup strategy in mind, how can we enable him to get it right?

Is declarativity here still what we want, if it limits easy understanding and expressivity? Or is something like this what we want:

 Foo(x): x refers to innermost (imported NS <+ NS)
 Foo(x): x refers to innermost imported NS <+ innermost NS

The first one would look from the current scope level either for imported x or definitions of x and continues on the next level, again looking for imported things first and for definitions afterwards, until it finds something.
The second one would search for imported x on all levels, before it searches for definitions on all levels.

Such a syntax would break the “literate style” of NaBL, But might go well with operators known from Stratego. We might drop the refers to:

Foo(x): x -> innermost(imported(NS) <+ NS)
Foo(x): x -> innermost(imported(NS)) <+ innermost(NS)

How can we integrate constraining properties into that?

Foo(e, x): refers to NS x of type t where e has type t
Foo(e, x): x -> innermost(NS) where x.type = e.type
Foo(e, x): x -> innermost(NS where type(x) = type(e))
Foo(e, x): x -> innermost(NS where type = type(e))

What would be the syntax for definitions and imports then?

To be clear, this is not about implementation. We can easily achieve this or have already implementations. Actually, it is just a matter of how tasks are composed. But we have issues with lifting the power of the implementation to the expressivity of the language. I would prefer to keep the literate style, but then the key question is how the concrete syntax for the cases described should look like.

Submitted by Guido Wachsmuth on 8 March 2013 at 17:33

On 8 March 2013 at 18:44 Guido Wachsmuth tagged rfc

On 11 March 2013 at 10:23 Gabriël Konat commented:

Why is innermost there? Do we want to support others as well, like outermost?

What about this, instead of using the ‘scary’ <+ operator from Stratego:

Foo(x): x refers to imported NS, NS
Foo(x): x refers to imported NS, otherwise to NS

On 29 April 2013 at 18:56 Guido Wachsmuth commented:

We currently stick with the hard wired lookup strategy.


On 7 May 2013 at 23:00 Guido Wachsmuth closed this issue.

Log in to post comments