Difference between revisions of "Language Reference/Predicates"
(→Predicates Sections: class-keyword) |
m (remove underscores in lang2) |
||
Line 28: | Line 28: | ||
<LowerCaseIdentifier></vipbnf> | <LowerCaseIdentifier></vipbnf> | ||
Here {{lang2|Domains| | Here {{lang2|Domains|Predicate Domains|predicateDomainName}} is the name of a predicate domain declared in the domains section. | ||
A predicate declaration states the name of the predicate, its type, mode, flow (see {{lang2|Domains| | A predicate declaration states the name of the predicate, its type, mode, flow (see {{lang2|Domains|Flow Pattern|predicate domains}}), and optionally a {{lang2|Domains|Calling Convention|link name}}. | ||
Only class predicates can have link names. If the link name is not stated then a link name is derived from the predicate name, the way this name is derived depends on the calling convention. | Only class predicates can have link names. If the link name is not stated then a link name is derived from the predicate name, the way this name is derived depends on the calling convention. | ||
If the calling convention is {{lang2|Domains| | If the calling convention is {{lang2|Domains|Calling Convention|apicall}} then the link name stated in the <vp>as</vp> clause is decorated anyway. If this decoration is unintended, use {{lang2|Domains|Calling Convention|stdcall}} instead. | ||
==== Decorated ==== | ==== Decorated ==== | ||
Line 61: | Line 61: | ||
=== Constructors Sections === | === Constructors Sections === | ||
A <vp>constructors</vp> section declares a set of constructors. The constructors belong to the scope in which the <vp>constructors</vp> section occurs (see {{lang2|Classes| | A <vp>constructors</vp> section declares a set of constructors. The constructors belong to the scope in which the <vp>constructors</vp> section occurs (see {{lang2|Classes|Class Declarations|class declaration}} and {{lang2|Implementations|Class Implementations|class implementation}}). | ||
<vipbnf><ConstructorsSection> : | <vipbnf><ConstructorsSection> : | ||
Line 184: | Line 184: | ||
A predicate that takes ''N'' arguments are said to be ''N-ary'', or to have arity ''N''. Predicates with different arity are always different predicates, even if they have the same name. | A predicate that takes ''N'' arguments are said to be ''N-ary'', or to have arity ''N''. Predicates with different arity are always different predicates, even if they have the same name. | ||
In most situations the arity of a predicate is obvious from the context in which the predicate is mentioned. But in, for example, {{lang2|Predicates| | In most situations the arity of a predicate is obvious from the context in which the predicate is mentioned. But in, for example, {{lang2|Predicates|Predicates from Interface|predicatesFromInterface}} sections and {{lang2|Implementations|Resolve Qualification|resolve qualifications}} the arity is not obvious. | ||
In order to distinguish between different arities of predicates in <vp>predicates from</vp> sections and in {{lang2|Implementations| | In order to distinguish between different arities of predicates in <vp>predicates from</vp> sections and in {{lang2|Implementations|Resolve Qualification|resolve qualifications}}, predicate names can (optionally) be stated with arity. | ||
The following arities are possible: | The following arities are possible: |
Revision as of 15:48, 17 March 2010
Predicates Sections
A predicates section declares a set of object or class predicates in the current scope.
PredicatesSection : class-opt predicates PredicateDeclaration-dot-term-list-opt
The keyword class can be used only inside class implementations, as predicates, declared in an interface, are always object predicates and predicates, declared in a class declaration, are always class predicates already.
The keyword class can be used only inside class implementations, since:
- predicates declared in an interface are always object predicates and
- predicates declared in a class declaration are always class predicates.
Predicate Declarations
The predicate declaration is used to declare the predicate in scopes in which the predicate declaration can be seen. When predicates are declared in an interface definition, this means that objects of the corresponding type must support these predicates. When predicates are declared in a class declaration, this means that the class publicly provides the declared predicates. And if predicates are declared in a class implementation, this means that the predicates are available locally. In all cases a corresponding definitions of the predicates must exist.
PredicateDeclaration : PredicateName : PredicateDomain LinkName-opt PredicateName : PredicateDomainName LinkName-opt
LinkName : as StringLiteral
PredicateName : LowerCaseIdentifier
Here predicateDomainName is the name of a predicate domain declared in the domains section.
A predicate declaration states the name of the predicate, its type, mode, flow (see predicate domains), and optionally a link name.
Only class predicates can have link names. If the link name is not stated then a link name is derived from the predicate name, the way this name is derived depends on the calling convention.
If the calling convention is apicall then the link name stated in the as clause is decorated anyway. If this decoration is unintended, use stdcall instead.
Decorated
Sometimes a name must have the _...@N decoration, but the default from apicall is wrong. In such cases decorated, decoratedA and decoratedW can be used to control the decoration:
predicates myPredicate : (string X) language stdcall as decorated.
In this case the link name will be "_MyPredicate@4", where apicall would make it "_MyPredicateW@4".
predicates myPredicate : (pointer X) language stdcall as decoratedA.
In this case the link name will be "_MyPredicateA@4", where apicall would make it "_MyPredicate@4".
predicates myPredicate : (pointer X) language stdcall as decoratedW.
In this case the link name will be "_MyPredicateW@4", where apicall would make it "_MyPredicate@4".
All of them change the start of the name from xxxx to _Xxxx and all of them put @N behind. The first never uses a suffix; the second always uses A and the third always uses W. This means that the programmer is responsible for deciding which suffix is needed. But he needs not to worry about calculating argument size and initial "_X".
Constructors Sections
A constructors section declares a set of constructors. The constructors belong to the scope in which the constructors section occurs (see class declaration and class implementation).
ConstructorsSection : constructors ConstructorDeclaration-dot-term-list-opt
Constructor sections can only occur in declarations and implementations of classes that construct objects.
Constructor Declarations
A constructor declaration declares a named constructor of a class.
A constructor actually has two associated predicates:
- A class function, which returns a new constructed object.
- An object predicate, which is used when initializing inherited objects.
An associated constructor object predicate is used to perform an object initialization. This predicate can only be called from the constructor in the class itself and from a constructor in a class that inherits from the class (i.e. base class initialization).
ConstructorDeclaration : ConstructorName : PredicateDomain
It is illegal to state a predicate mode for constructors, constructors always have procedure mode.
class test_class : test constructors new : (integer Argument). end class test_class
The associated class level predicate has the following signature:
class predicates new : (integer) -> test.
Whereas the associated object level predicate has the following signature:
predicates new : (integer).
Also consider the following implementation:
implement test2_class inherits test_class clauses new() :- test_class::new(7), % invoke the base class constructor on "This" p(test_class::new(8)). % create a new object of the base class and pass it to p(...) ...
The first call to test_class::new does not return a value, therefore it is a call to the non-function object version of the constructor. I.e. it is an invocation of the base class constructor on "This".
The second call on the other hand does return a value, therefore it is a call to the class function version of the constructor. I.e. we are creating a new object.
Predicates from Interface
An interface can support a subset of another interface by stating the predicates in a predicates from section. The predicates from section names the interface and all supported predicates. The predicates are stated by name or by name and arity.
If an interface supports a subset of another interface it is neither subtype or super-type related to the other interface.
The important thing about the predicates from section is that the mentioned predicates retain their origin interface. Therefore:
- there will be no support conflict with any predicates from the origin interface;
- they can be inherited as the predicates from the origin interface.
PredicatesFromInterface : predicates from InterfaceName PredicateNameWithArity-comma-sep-list-opt
PredicatesFromInterface can only be used in interface definitions.
interface aaa predicates ppp : (). qqq : (). end interface aaa interface bbb predicates from aaa ppp predicates rrr : (). end interface bbb interface ccc supports aaa, bbb end interface ccc
Even though aaa and bbb both declare a predicate ppp, ccc can support them both without any conflicts, because ppp has aaa as an origin interface in all cases.
interface aaa predicates ppp : (). qqq : (). end interface aaa interface bbb predicates from aaa ppp predicates rrr : (). end interface bbb class aaa_class : aaa end class aaa_class class bbb_class : bbb end class bbb_class implement aaa_class inherits bbb_class clauses qqq(). end implement aaa_class
aaa_class can inherit ppp from bbb_class, because ppp in both classes has aaa as origin interface.
Arity
A predicate that takes N arguments are said to be N-ary, or to have arity N. Predicates with different arity are always different predicates, even if they have the same name.
In most situations the arity of a predicate is obvious from the context in which the predicate is mentioned. But in, for example, predicatesFromInterface sections and resolve qualifications the arity is not obvious.
In order to distinguish between different arities of predicates in predicates from sections and in resolve qualifications, predicate names can (optionally) be stated with arity.
The following arities are possible:
- Name/N meaning an ordinary predicate (i.e. not a function) Name of arity N.
- Name/N-> meaning a function Name of arity N.
- Name/N... meaning an ordinary predicate Name with N arguments followed by an Ellipsis argument (i.e. a varying number of arguments). (Ellipsis "..." can be used in predicate and predicate domain declarations as the last formal argument. In this case it means that the declared predicate (predicate domain) can have a variable number of arguments. Ellipsis flow must match an ellipsis argument and can therefore be only the last flow in the flow pattern.)
- Name/N...-> meaning a function Name with N arguments followed by an ellipsis argument.
PredicateNameWithArity : PredicateName Arity-opt
Arity : one of / IntegerLiteral Ellipsis-opt / IntegerLiteral Ellipsis-opt ->
In Name/0... and Name/0...->. the zero is optional and can thus be written as Name/... and Name/...->, respectively.