Adapter provides another interface to an object, i.e. adapts an object to another object’s type.
There are multiple situations when adapter can be useful. For example, adapter can be substituted instead of an object containing it, when implicit type conversion required. One such situation is an integer-to-float conversion:
Float (= 12) ~~ This conversion occurs implicitly, ~~ because integer has an adapter to float. ~~ The same can be written explicitly: Float (= 12 @@float)
The adapter declaration syntax is following:
'@' <interface> ['@' ['('] <ascendant> [')'] | ':'] '=' ['<'] <definition>
<interface>is a reference to an object to adapt the enclosing object to;
<ascendant>is a reference to an object’s ascendant, the overridden adapter is present in;
<definition>is an expression either constructing a new object or referring to it’s ancestor.
Other tokens interpreted similarly to the field declaration.
Note that the adapter can not be declared as prototype. So, the
tokens are prohibited in adapter declarations.
Interface :=> integer Object := void ( Value := 12 @Interface := interface (= Value) )
There is another form of field declaration and override syntax:
'@' <interface> ['@' ['('] <ascendant> [')']] <definition>
This is a shorter way to write the following:
'@' <interface> ['@' ['('] <ascendant> [')']] [':'] '=' * <definition>
<definition> here consists of zero or more
When short syntax is used, a new adapter is declared, unless
specified, or adapter with the given interface already present in ancestor,
in which case the statement overrides an existing adapter.
One := void ( @Integer (= 1) ~~ Declare adapter to `integer`. ) Two := one ( @Integer (= 2) ~~ Override adapter to `integer`. )
Access to The Field of Adapter
There is a special syntax for accessing fields of object’s adapter. It is similar to qualified field access, where adapter interface is used instead of object’s ascendant:
<owner> ':' <name> ['@' ['('] <interface> [')'] ]
<owner>is an arbitrary expression resolving to an object with adapter;
<name>is an adapter’s field name;
<interface>is a reference to adapter interface object.
Adapter := void ( Foo := 1 ) Object := void ( @Adapter := * ( Foo = * (= 2) ) ) Object: foo @adapter ~~ Field `foo` of adapter to `adapter` of `object`. (Object @@adapter): foo ~~ The same as above, but using ugly parentheses.
Similarly, a qualified form of adapter access can access an adapter within adapter.
Note, that the qualified field access has a precedence over adapter’s field access. So, when the object both derived from some other object and has an adapter to it, the field of the object itself will be accessed instead of the field of it’s adapter.
To access an adapter itself the following syntax can be used:
<owner> '@@' ['('] <interface> [')'] ['@' ['('] <ascendant> [')'] ]
<owner>is an arbitrary expression resolving to object with adapter;
<interface>is a reference to adapter’s interface object;
<ascendant>is the owner’s ascendant reference the adapter is present in.
foo @@type foo @@container: type foo @@type @foo ascendant foo @@container: type @foo ascendant
An identification conflicts are resolved similarly to the fields.
Adapters are Fields
An adapter is a kind of a field, identified by its interface instead of the name. Adapters are always public.
Also, the adapter is implicitly derived from its interface (adapter is
propagated from its interface. This interface is used as a very
first sample). So, an implied reference (
*) can be used in the adapter
definition to either indicate that adapter’s definition is the same as the one
of it’s interface:
Type := 1 @Type := * ~~ `1`
or as a placeholder in #constructor expression:
Type := void ( Foo := 2 ) @Type := * ( Foo = * (= 4) )
to indicate that adapter has the same ancestor as its interface.