On this page ...
The Freon Scoper Definition
The scope provider (or scoper for short) is defined by a scoper definition, which must be in a file with
the extension .scope. The scoper definition holds all your DSL’s scoping rules. All files with the .scope extension in
the defs folder (i.e. the folder where you keep your definition files) are combined into one scoper definition.
Any .scope file should start by declaring the language for which the scoper is defined.
// Insurance/src/defs/scoper-docu.scope#L1-L2
scoper for language InsuranceModel
The default scoper, which is the scoper provided when no scoper definition is given, simply regards your user’s model as the one and only namespace, meaning that every node is visible everywhere.
Defining Namespaces
Often, much of the necessary scoping can be defined simply by stating that certain concepts are namespaces. This is done in a single statement, which must come
before any other rules. All metatypes that are regarded as namespaces are listed between curly brackets after the keyword isNamespace.
Model units and interfaces can be used as well. Any instance of a concept that implements a namespace interface will
be regarded as a namespace.
Have a look again at an earlier example:
// Insurance/src/defs/scoper-docu.scope#L3-L3
isNamespace { InsuranceProduct, BaseProduct, CalcFunction, Entity, AttributeRef } Defining Imports
The next parts of the scoper definition cover imports and alternatives; they may be mixed.
To define an import use the name of the concept, model unit, or interface that identifies the namespace,
and - between curly brackets - add the imported namespace after the keyword imports. You may add a
list of properties; all of them will be imported. The keyword recursive (See Recursive Imports) may
be added to each entry in the list individually.
InsuranceProduct {
imports {
self.basedOn;
recursive self.themes;
self.parts;
}
} Defining Alternatives
To define an alternative, you should use
the name of the concept, model unit or interface that identifies the namespace, and add the imported namespace after
the keyword alternative. Here too, you may add a list of properties to be included in the alternatives, and
use the keyword recursive for each entry in the list individually.
InsuranceProduct {
alternatives {
self.basedOn;
recursive self.themes;
self.parts;
}
} Overview of Possibilities in the Scope Definition
The Freon meta-language for scoping provides a number of options for building an expression to indicate the required namespace.
First, you may use dots to traverse the AST.
alternatives {
self.xxx.yyy.rrr;
} Second, you can use an instance of a limited concept. Put a # sign before the name of the limited concept, and
use the : sign as separator followed by the name of the limited instance.
imports {
#AttributeType:Integer;
} Third, you may want to use the owning namespace of a property. For this you should use the predefined function owner().
imports {
self.xxx.owner();
} Fourth, you can indicate that you want to use a certain property, but only
if it is of a certain metatype. To do this you use the predefined function if() which takes as its parameter the name of a
concept or model unit (no interfaces!). If the node is not of the required type, no namespace is added.
imports {
self.xxx.if(ConceptY);
self.if(Unit12);
} You can combine all the options and make a really complex statement. But be careful, it is easy to get confused.
In the following example, the namespace that is imported is the namespace indicated by the conceptA_prop instance of
the namespace that ‘owns’ the property self.xxx (i.e. self.xxx is
in the declared nodes of this namespace), but only if this owner is of (meta)type ConceptA.
imports {
self.xxx.owner().if(ConceptA).conceptA_prop;
} Finally, when you have also defined a typer (See Typing and Validating), you may
use the type of an instance as namespace. To do this you use the predefined function type(). Note that nothing may follow
a type() expression. Note also that the type of an instance is different from its metatype. The first is an instance of some
concept that is defined by the typer definition to represent the type of the node. The second is a concept, model unit, or
interface that is defined in the .ast file.
alternatives {
self.xxx.type();
self.type();
self.yyy.owner().type();
} Example Scope Definition
// Insurance/src/defs/scoper-docu.scope
scoper for language InsuranceModel
isNamespace { InsuranceProduct, BaseProduct, CalcFunction, Entity, AttributeRef }
InsuranceProduct {
imports {
self.basedOn;
}
}
AttributeRef {
alternatives {
self.owner().type();
}
}
Entity {
imports {
self.baseEntity;
}
}