Name Resolver Specification

Introduction

The goal of the name resolver in the Clafer compiler is to determine which clafer in the model is referred to by a given reference by name. In a Clafer model, names can repeat as each clafer declaration includes a new namespace. For example, there can be many clafers called X in various places in the model. The clafer X can be referred to in these two ways:

  1. as a super clafer: a : X (done in ResolveInheritance.hs), a -> X, and a ->> X (ResolveName.hs), and
  2. inside expressions in constraints and goals: [ some X ], X + 1, and << max sum X.ref >>.

The name resolver decides which of the potentially multiple Xs is being referred to. Clafer X can be resolved as

  • Specialthis, parent, children, ref
  • TypeSpecial – primitive type: integer, string, (need to add real, natural, etc.)
  • Binding – local variable (in constraints with quantifier)
  • Subclafers – in descendants (BFS)+ inheritance
  • Reference – same as Subclafers + reachable via references
  • Ancestor – in ancestors
  • AbsClafer – abstract , top-level clafer
  • TopClafer – concrete, top-level clafer

Currently (Clafer 0.3.3), the name resolver applies the following sequence of resolution strategies (in that exact order) given the current environment env and the clafer’s id:

resolve env id [resolveSpecial, resolveBind, resolveDescendants, resolveAncestor pos, resolveTopLevel pos, resolveNone pos]

The strategy resolveNone reports an error that the clafer with the given id was not found.

Test Cases

Resolving Special

  • this refers to S1
S1
[ this ]
  • parent refers to S2
S2
a
[ parent ]
  • children refers to a ++ b
S3
   a
   b
   [ children ]

results in resolver: unknown uid 'children'

Resolving TypeSpecial

  • integer, string, real resolve to primitive types
age -> integer
age2 -> int
name -> string
interestRate -> real
interestRate -> double

results in resolver: real not found within and resolver: double not found within

Resolving Binding

  • b in b.c resolves to b in b : B1. c in b.c resolves to B1.c via inheritance.
abstract B1
c ?
[ all b : B1 | b.c ]
[ all disj b1; b2 : B1 | b1.c && b2.c ]
[ some b : B1 | b.c ]
[ no b : B1 | b.c ]

Resolving Subclafers

  • b in some b resolves to a.b and not to a.b.b
Sub
[ some b ]
a ?
b ?
b ?

Resolving Reference

  • a in some a should resolve to A5.a
A5 *
a *
refA5 ->> A5
[ some this.a ]
  • B in -> A.B should resolve to A.B
refAB -> A.B *
  [ some B ]

results in an error B not found

Resolving Ancestor

  • A1 in some A1 resolves to the top-level A1
A1 ?
B
[ some A1 ]
  • A2 in some A2 resolves to A2.A2 and not the top-level A2
A2 ?
  A2 ?
    B 
      [ some A2 ]

results in an unexplained compilation error.

Resolving AbsClafer

  • Abs in : Abs, -> Abs, and ->> Abs resolves to abstract Abs
abstract Abs
AbsColon : Abs
AbsSet -> Abs
AbsMultiSet ->> Abs
  • nested abstract
abstract Year
abstract Month
y2013 : Year
month : Month 12

Resolving TopClafer

  • T in some T resolves to T ?
T ?
[ some T ]
// this is not allowed - improper nesting

// myMonth : Month

Resolving Redefinition

  • (this affects name resolution for inheritance)
abstract A
	d 0..1

/* redefines A.d, narrows cardinality */

abstract B : A
	d 1..1 
		b ?

refA -> A

[ refA.ref.d.b ] this should produce error 'b' not found

refB -> B

[ refB.ref.d.b ] // this should work

Related BugBot Issues

Issues 48 and 65 are just proposals, we have not decided yet.