user_guide:extend:rulefiles

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
reference:rulefiles [2018/09/08 22:01] – [Functions] gawrilowuser_guide:extend:rulefiles [2021/01/12 15:38] (current) – external edit 127.0.0.1
Line 22: Line 22:
   - scoped blocks like ''object'' or ''property_type'' Their body is enclosed in curly braces { ... } and can expand over arbitrarily many lines.  Scope-like blocks can be nested, but must not intersect with plain text blocks.   - scoped blocks like ''object'' or ''property_type'' Their body is enclosed in curly braces { ... } and can expand over arbitrarily many lines.  Scope-like blocks can be nested, but must not intersect with plain text blocks.
  
-[[reference:rules|Production rules]] constitute a special case in that they can be defined by a sequence of several blocks.  The first block, usually a scoped one, comprising the main rule subroutine, may be followed by further single-line and scoped blocks defining its weight and preconditions.  Empty lines and comments between the blocks in such a sequence are allowed and ignored.+[[user_guide:extend:rules|Production rules]] constitute a special case in that they can be defined by a sequence of several blocks.  The first block, usually a scoped one, comprising the main rule subroutine, may be followed by further single-line and scoped blocks defining its weight and preconditions.  Empty lines and comments between the blocks in such a sequence are allowed and ignored.
  
 ===== Compilation mode ===== ===== Compilation mode =====
Line 44: Line 44:
   .. Importing a polymorphic function has a side effect you should be aware of as well.  If you introduce further overloaded instances of a function in the current application, they will be also taken into account in the imported applications.  This is harmless as far as the new instances are overloaded for data types introduced in the current application, otherwise it can lead to a surprising effect that the code in one application starts to behave differently when another application is loaded.  Be careful.   .. Importing a polymorphic function has a side effect you should be aware of as well.  If you introduce further overloaded instances of a function in the current application, they will be also taken into account in the imported applications.  This is harmless as far as the new instances are overloaded for data types introduced in the current application, otherwise it can lead to a surprising effect that the code in one application starts to behave differently when another application is loaded.  Be careful.
   ? ''INCLUDE'' filename ...   ? ''INCLUDE'' filename ...
-  :: Includes further rulefiles before proceeding with the rest of the current rulefile.  Normally the additional rulefiles are residing in the same ''rules'' subdirectory, but they also may come from [[reference:extensions|an extension]].  You can also include rulefiles from other applications, provided these applications are //used// or //imported// by the current one.  To this end, the filename must be prefixed with ''appname::'' .+  :: Includes further rulefiles before proceeding with the rest of the current rulefile.  Normally the additional rulefiles are residing in the same ''rules'' subdirectory, but they also may come from [[user_guide:extend:extensions|an extension]].  You can also include rulefiles from other applications, provided these applications are //used// or //imported// by the current one.  To this end, the filename must be prefixed with ''appname::'' .
   .. Each rulefile is included only once, even if it occurs in multiple INCLUDE blocks.  It is a fatal error if the given filename can't be found.  Rulefiles excluded by [[#configuration|configuration]] are not loaded but silently ignored.  You can provide a fallback rulefile as an alternative to one or more configurable rulefiles:   .. Each rulefile is included only once, even if it occurs in multiple INCLUDE blocks.  It is a fatal error if the given filename can't be found.  Rulefiles excluded by [[#configuration|configuration]] are not loaded but silently ignored.  You can provide a fallback rulefile as an alternative to one or more configurable rulefiles:
   .. ''%%rulefile | fallbackfile%%''\\ if ''rulefile'' is successfully configured, it will be loaded and ''fallbackfile'' disabled; otherwise ''rulefile'' will be silently skipped and ''fallbackfile'' will be loaded.   .. ''%%rulefile | fallbackfile%%''\\ if ''rulefile'' is successfully configured, it will be loaded and ''fallbackfile'' disabled; otherwise ''rulefile'' will be silently skipped and ''fallbackfile'' will be loaded.
Line 59: Line 59:
   .. Note that applications the current one really depends on, that is, //imported// or //used// ones, must not be listed in such guard.   .. Note that applications the current one really depends on, that is, //imported// or //used// ones, must not be listed in such guard.
 ==== Configuration ==== ==== Configuration ====
-Rulefiles may contain configurable settings, which can be filled automatically and manipulated by the user.  There are two kinds of items related to configuration: [[:general#custom_variables|custom variables]] and auto-configuration blocks.  Declarations of custom variables should be preceded with comments, which are copied into the user's settings files for the sake of better legibility.+Rulefiles may contain configurable settings, which can be filled automatically and manipulated by the user.  There are two kinds of items related to configuration: [[:user_guide:howto:shell_custom#custom_variables|custom variables]] and auto-configuration blocks.  Declarations of custom variables should be preceded with comments, which are copied into the user's settings files for the sake of better legibility.
  
   ? ''custom $var = default_value;''   ? ''custom $var = default_value;''
Line 79: Line 79:
   ? ''label'' name   ? ''label'' name
   :: Introduces a top-level name for labels, used in definitions of production rules and user methods.   :: Introduces a top-level name for labels, used in definitions of production rules and user methods.
-  ? ''prefer'' [[:general#preferences|label expression]]+  ? ''prefer'' [[:user_guide:howto:shell_custom#preferences|label expression]]
   :: Establishes a default preference list for a certain group of competing rules or user methods.  The syntax of the //label expression// is the same as in the interactive commands ''prefer'' and ''prefer_now'', but here you should not enclose it in quotes nor put a trailing semicolon.  These are the lists that are re-established upon execution of a ''reset_preference'' command.   :: Establishes a default preference list for a certain group of competing rules or user methods.  The syntax of the //label expression// is the same as in the interactive commands ''prefer'' and ''prefer_now'', but here you should not enclose it in quotes nor put a trailing semicolon.  These are the lists that are re-established upon execution of a ''reset_preference'' command.
      
Line 103: Line 103:
   ? ''declare property_type'' name [ '':'' super_class ] [ '': upgrades( '' simpler_type, ... '')'' ] [ '': c++ ('' [[cpp_type_binding|attributes]] '')'' ] ...   ? ''declare property_type'' name [ '':'' super_class ] [ '': upgrades( '' simpler_type, ... '')'' ] [ '': c++ ('' [[cpp_type_binding|attributes]] '')'' ] ...
   :: Introduces a new property type with an optional binding to a C++ class or built-in type.  The optional //super_class// designates another property type to inherit methods from.   :: Introduces a new property type with an optional binding to a C++ class or built-in type.  The optional //super_class// designates another property type to inherit methods from.
-  .. //simpler_types// named in the optional //upgrades// clause must be already defined property types that can be coerced to the currently defined type without any loss of information.  In more formal words, the value domain of each //simpler_type// must be isomorphic to a subset of the value domain of currently defined type.  For example, type ''Integer'' upgrades the built-in type ''Int'', type ''Rational'' upgrades ''Integer'', polynomial ''Term'' upgrades the corresponding ''Monomial'' and ''Coefficient'' types, etc.  Type upgrade relations play an important role in [[reference:polymorphic#type_parameter_deduction|flexible type deduction]] of polymorphic functions, but otherwise do not incur any implicit data conversions performed by polymake.+  .. //simpler_types// named in the optional //upgrades// clause must be already defined property types that can be coerced to the currently defined type without any loss of information.  In more formal words, the value domain of each //simpler_type// must be isomorphic to a subset of the value domain of currently defined type.  For example, type ''Integer'' upgrades the built-in type ''Int'', type ''Rational'' upgrades ''Integer'', polynomial ''Term'' upgrades the corresponding ''Monomial'' and ''Coefficient'' types, etc.  Type upgrade relations play an important role in [[user_guide:extend:polymorphic#type_parameter_deduction|flexible type deduction]] of polymorphic functions, but otherwise do not incur any implicit data conversions performed by polymake.
   .. The name of each type must be unique in the enclosing application.  It may be redefined in other applications //using// this one, but generally reusing names leads to more confusion and should be avoided.  In some rare cases where reusing the same type name seems less harmful than introducing unnatural different names, you can disambiguate it in your code by prefixing it with the name of application where it is defined, or with a special prefix ''props::'', to distinguish it from "big" object type names.   .. The name of each type must be unique in the enclosing application.  It may be redefined in other applications //using// this one, but generally reusing names leads to more confusion and should be avoided.  In some rare cases where reusing the same type name seems less harmful than introducing unnatural different names, you can disambiguate it in your code by prefixing it with the name of application where it is defined, or with a special prefix ''props::'', to distinguish it from "big" object type names.
   .. The attribute list keyed with ''c++'' means that the data are to be kept in a native C++ object attached to the so called perl magic storage.  The interplay between property types visible on the perl side and C++ classes is explained [[cpp_type_binding|in more details here]].   .. The attribute list keyed with ''c++'' means that the data are to be kept in a native C++ object attached to the so called perl magic storage.  The interplay between property types visible on the perl side and C++ classes is explained [[cpp_type_binding|in more details here]].
Line 138: Line 138:
   :: Reopens the definition scope of a named partial/restricted specialization of the given "big" object type.   :: Reopens the definition scope of a named partial/restricted specialization of the given "big" object type.
 ==== Functions ==== ==== Functions ====
-  ? ''function'' [label : ] name ''('' [[reference:polymorphic#signature|signature]] '') {'' \\ ... \\ ''}'' +  ? ''function'' [label : ] name ''('' [[user_guide:extend:polymorphic#signature|signature]] '') {'' \\ ... \\ ''}'' 
-  :: Defines a [[reference:polymorphic|polymorphic]] (overloaded) function. +  :: Defines a [[user_guide:extend:polymorphic|polymorphic]] (overloaded) function. 
-  ? ''function'' [label : ] name ''('' [[reference:polymorphic#signature|signature]] '') : c++('' [[reference:polymorphic#attributes|options]] '');''+  ? ''function'' [label : ] name ''('' [[user_guide:extend:polymorphic#signature|signature]] '') : c++('' [[user_guide:extend:polymorphic#attributes|options]] '');''
   :: Defines a wrapper for a C++ function.  ''function'' without user-visible comments can be defined as well.   :: Defines a wrapper for a C++ function.  ''function'' without user-visible comments can be defined as well.
-  ? ''function'' [label : ] name ''('' [[reference:polymorphic#signature|signature]] '') : c++('' [[reference:polymorphic#attributes|options]] '') {'' \\ ... \\ ''}'' +  ? ''function'' [label : ] name ''('' [[user_guide:extend:polymorphic#signature|signature]] '') : c++('' [[user_guide:extend:polymorphic#attributes|options]] '') {'' \\ ... \\ ''}'' 
-  :: Defines a [[reference:polymorphic#hybrid_functions|hybrid function]] implemented partially in perl, partially in C++.+  :: Defines a [[user_guide:extend:polymorphic#hybrid_functions|hybrid function]] implemented partially in perl, partially in C++.
  
 In all definition flavors you can change the leading keyword from ''function'' to ''user_function'' Then the comment block preceding the definition will be converted into a help topic accessible via the interactive ''help'' function, ''F1'' help, and the HTML documentation pages; besides this, the function name and keyword options (if any) will appear in the suggestion lists produced by TAB completion. In all definition flavors you can change the leading keyword from ''function'' to ''user_function'' Then the comment block preceding the definition will be converted into a help topic accessible via the interactive ''help'' function, ''F1'' help, and the HTML documentation pages; besides this, the function name and keyword options (if any) will appear in the suggestion lists produced by TAB completion.
 ==== Option lists ==== ==== Option lists ====
   ? ''options %table_name = ('' \\ ''%list_to_inherit_from,'' \\ ''%%#%%'' Comment ... \\ ''%%key => default value,%%'' \\ ... \\ '');''   ? ''options %table_name = ('' \\ ''%list_to_inherit_from,'' \\ ''%%#%%'' Comment ... \\ ''%%key => default value,%%'' \\ ... \\ '');''
-  :: Defines a named list of keywords to be used in [[reference:polymorphic#signature|signatures]] of polymorphic functions and methods.  The declaration syntax is similar to that of the custom hash tables.+  :: Defines a named list of keywords to be used in [[user_guide:extend:polymorphic#signature|signatures]] of polymorphic functions and methods.  The declaration syntax is similar to that of the custom hash tables.
  
 Options lists can be easily built up hierarchically, extending each other much like a derived class extends a base class.  The extension relation is expressed by mere inclusion.  The names of lists to be extended upon are listed in the beginning of the definition body. Options lists can be easily built up hierarchically, extending each other much like a derived class extends a base class.  The extension relation is expressed by mere inclusion.  The names of lists to be extended upon are listed in the beginning of the definition body.
Line 158: Line 158:
 The definition of a type checking function is identical to that of a polymorphic function: The definition of a type checking function is identical to that of a polymorphic function:
  
-''function'' name ''('' [[reference:polymorphic|signature]] '') {'' \\ ''%%...%%'' \\ ''}''+''function'' name ''('' [[user_guide:extend:polymorphic|signature]] '') {'' \\ ''%%...%%'' \\ ''}''
  
 Usually type checking functions are only referred in the check clauses (parts enclosed in square brackets) and default type parameter expressions in definitions of parametrized property and object types, like in this example: Usually type checking functions are only referred in the check clauses (parts enclosed in square brackets) and default type parameter expressions in definitions of parametrized property and object types, like in this example:
Line 164: Line 164:
 This type checking function is defined in application common, where it accepts Rational, Float, and QuadraticExtension as valid types, but rejects anything else. This type checking function is defined in application common, where it accepts Rational, Float, and QuadraticExtension as valid types, but rejects anything else.
  
-Besides definitions of parametrized types, type checking can also participate in overload resolution of [[reference:polymorphic|polymorphic functions]].+Besides definitions of parametrized types, type checking can also participate in overload resolution of [[user_guide:extend:polymorphic|polymorphic functions]].
 ==== Miscellaneous ==== ==== Miscellaneous ====
   ? ''file_suffix'' suffix   ? ''file_suffix'' suffix
Line 172: Line 172:
 A property type may have several constructors with arbitrary combinations of arguments.  All constructor instances are defined as usual overloaded methods: A property type may have several constructors with arbitrary combinations of arguments.  All constructor instances are defined as usual overloaded methods:
  
-''method construct('' [[reference:polymorphic|signature]] '')'' \\ PropertyType, ... => value+''method construct('' [[user_guide:extend:polymorphic|signature]] '')'' \\ PropertyType, ... => value
  
 The only special case is the parsing constructor taking a single ''String'' argument, it should be defined as ''type_method parse'' described in the next paragraph. The only special case is the parsing constructor taking a single ''String'' argument, it should be defined as ''type_method parse'' described in the next paragraph.
Line 219: Line 219:
 Constructors for big objects are defined much like constructors for property types: Constructors for big objects are defined much like constructors for property types:
  
-''method construct('' [[reference:polymorphic|signature]] '')'' \\ ObjectType, ... => new Object+''method construct('' [[user_guide:extend:polymorphic|signature]] '')'' \\ ObjectType, ... => new Object
  
 Only special cases like conversion from unrelated object types must be handled in user-defined constructors.  Every big object type automatically inherits all [[scripting:start#construction|standard constructors]]. Only special cases like conversion from unrelated object types must be handled in user-defined constructors.  Every big object type automatically inherits all [[scripting:start#construction|standard constructors]].
Line 242: Line 242:
     :: specifies a prerequisite property of the owning object (or one of its subobjects) needed for proper construction of the property value.  The value of the prerequisite property is passed to the ''construct'' method of the property type together with the value being assigned to this property.  For example, values of type NodeMap or EdgeMap need a Graph object to be attached to, therefore such properties of "big" objects graph::Graph or graph::FaceLattice usually have an attribute ''construct(ADJACENCY)''.     :: specifies a prerequisite property of the owning object (or one of its subobjects) needed for proper construction of the property value.  The value of the prerequisite property is passed to the ''construct'' method of the property type together with the value being assigned to this property.  For example, values of type NodeMap or EdgeMap need a Graph object to be attached to, therefore such properties of "big" objects graph::Graph or graph::FaceLattice usually have an attribute ''construct(ADJACENCY)''.
   ? ''property NAME = override INHERITED_NAME;''   ? ''property NAME = override INHERITED_NAME;''
-  :: introduces an alias for an inherited property.  The alias name will appear everywhere you ask for properties, e.g. in XML data files and in lists produced by ''list_properties'' method; but the value of the property stays accessible over both alias name and inherited original name.  The inherited production rules for this property are in effect as well; if you want to disable them, see the [[reference:rules#overrides|override option for rules]].+  :: introduces an alias for an inherited property.  The alias name will appear everywhere you ask for properties, e.g. in XML data files and in lists produced by ''list_properties'' method; but the value of the property stays accessible over both alias name and inherited original name.  The inherited production rules for this property are in effect as well; if you want to disable them, see the [[user_guide:extend:rules#overrides|override option for rules]].
   .. For obvious reasons, a property can't be overridden in the same object type where it has been defined, nor within a partial or conditional specialization of an object type.   .. For obvious reasons, a property can't be overridden in the same object type where it has been defined, nor within a partial or conditional specialization of an object type.
   ? ''property NAME = override ''['' INHERITED_NAME '']'' : Type;''   ? ''property NAME = override ''['' INHERITED_NAME '']'' : Type;''
Line 271: Line 271:
  
 ==== Rules ==== ==== Rules ====
-The syntax of rules is so manifold that it deserves a description [[reference:rules|on a separate page]].+The syntax of rules is so manifold that it deserves a description [[user_guide:extend:rules|on a separate page]].
  
 ==== User methods ==== ==== User methods ====
  
-  ? ''user_method'' [labels :] name ''('' [[reference:polymorphic|signature]] '') {'' \\ ... \\ ''}''+  ? ''user_method'' [labels :] name ''('' [[user_guide:extend:polymorphic|signature]] '') {'' \\ ... \\ ''}''
   :: defines a method to be called from scripts and interactive shell.  It should be accompanied by a properly formatted comment block.  The syntax rules for the signature and overload resolution rules are the same as for user_functions, apart from the fact that the leading argument, a reference to an object of the current type, may not appear in the signature.  As the name //method// says, it is inherited by all derived object types.  Methods defined in derived classes completely override inherited methods of the same name only if they possess compatible signatures (that is, accept the same or broader sets of arguments than the inherited instance).   :: defines a method to be called from scripts and interactive shell.  It should be accompanied by a properly formatted comment block.  The syntax rules for the signature and overload resolution rules are the same as for user_functions, apart from the fact that the leading argument, a reference to an object of the current type, may not appear in the signature.  As the name //method// says, it is inherited by all derived object types.  Methods defined in derived classes completely override inherited methods of the same name only if they possess compatible signatures (that is, accept the same or broader sets of arguments than the inherited instance).
-  .. //labels// can be used in [[:general#preferences|preference]] settings controlling the favorites among several overloaded instances with equivalent signatures.  The first limb of each label must be defined earlier in this application, or in a //used// or //imported// one.+  .. //labels// can be used in [[:user_guide:howto:shell_custom#preferences|preference]] settings controlling the favorites among several overloaded instances with equivalent signatures.  The first limb of each label must be defined earlier in this application, or in a //used// or //imported// one.
   .. If the routine is declared as ''method'' instead of ''user_method'', it does not appear in the interactive help, TAB completion, or auto-generated documentation, but in all other aspects both flavors behave identically.   .. If the routine is declared as ''method'' instead of ''user_method'', it does not appear in the interactive help, TAB completion, or auto-generated documentation, but in all other aspects both flavors behave identically.
-  ? ''user_method'' [labels :] name ''('' [[reference:polymorphic|signature]] '') : '' property, ... '' {'' \\ ... \\ ''}'' +  ? ''user_method'' [labels :] name ''('' [[user_guide:extend:polymorphic|signature]] '') : '' property, ... '' {'' \\ ... \\ ''}'' 
-  :: defines a rule-like method.  This is a hybrid creature between a polymorphic method and a [[reference:rules|rule]].  Like a normal production rule, it specifies a list of required input properties and, optionally, preconditions, which must follow the main code block.+  :: defines a rule-like method.  This is a hybrid creature between a polymorphic method and a [[user_guide:extend:rules|rule]].  Like a normal production rule, it specifies a list of required input properties and, optionally, preconditions, which must follow the main code block.
   .. When such a method is called, suitable candidates are first chosen depending on the argument list.  Then they are handled much like production rules: the input property lists and preconditions are evaluated and the cheapest feasible candidate is executed.  However, unlike for real production rules, if the chosen method instance throws an exception, no alternative candidates are tried any more.   .. When such a method is called, suitable candidates are first chosen depending on the argument list.  Then they are handled much like production rules: the input property lists and preconditions are evaluated and the cheapest feasible candidate is executed.  However, unlike for real production rules, if the chosen method instance throws an exception, no alternative candidates are tried any more.
   .. Rule-like methods can also be defined without signatures.  In this case the choice of a suitable instance is performed solely by analyzing input properties and preconditions.   .. Rule-like methods can also be defined without signatures.  In this case the choice of a suitable instance is performed solely by analyzing input properties and preconditions.
Line 304: Line 304:
 As mentioned in the preamble, a rulefile may contain arbitrary perl code, which also includes the possibility to define new packages (=classes).  While feature-rich classes should be better defined in separate module files residing in ''apps/APPNAME/perllib/'', small auxiliary classes can be more conveniently defined just in the rulefile using it.  Moreover, some syntactical elements can only be recognized in rulefiles but not in separate module files.  These are custom variables, auto-configuration blocks, polymorphic functions, and option lists.  Therefore, in some situations you might even decide to divide the class definition in two parts, one in the rulefile, other one in a module file ''require'''d from it. As mentioned in the preamble, a rulefile may contain arbitrary perl code, which also includes the possibility to define new packages (=classes).  While feature-rich classes should be better defined in separate module files residing in ''apps/APPNAME/perllib/'', small auxiliary classes can be more conveniently defined just in the rulefile using it.  Moreover, some syntactical elements can only be recognized in rulefiles but not in separate module files.  These are custom variables, auto-configuration blocks, polymorphic functions, and option lists.  Therefore, in some situations you might even decide to divide the class definition in two parts, one in the rulefile, other one in a module file ''require'''d from it.
  
-There is also one sort of definition elements which is specific for packages not belonging to the "big" object hierarchy: so called //global methods// They are defined exactly the same way as polymorphic user_methods, just using the keyword ''global_method'' The main difference lies in the [[reference:polymorphic#labels|overload resolution]]: it usually takes place before the object of the class is created.  The global methods from different classes having an identical signature are bundled together by preference lists and the current favorite is used to determine the class to create the object which is then passed to the chosen method.  This is how all the visualization methods work.  If, for example, you are going to draw a graph, all known global methods having signatures compatible to ''draw(Visual::Graph)'' are ordered according to the active preference settings, then the definition package of the method in the "pole position" determines which visualization back-end object is to be created, and finally the ''draw'' method is called with this object and the graph.+There is also one sort of definition elements which is specific for packages not belonging to the "big" object hierarchy: so called //global methods// They are defined exactly the same way as polymorphic user_methods, just using the keyword ''global_method'' The main difference lies in the [[user_guide:extend:polymorphic#labels|overload resolution]]: it usually takes place before the object of the class is created.  The global methods from different classes having an identical signature are bundled together by preference lists and the current favorite is used to determine the class to create the object which is then passed to the chosen method.  This is how all the visualization methods work.  If, for example, you are going to draw a graph, all known global methods having signatures compatible to ''draw(Visual::Graph)'' are ordered according to the active preference settings, then the definition package of the method in the "pole position" determines which visualization back-end object is to be created, and finally the ''draw'' method is called with this object and the graph. 
  • user_guide/extend/rulefiles.txt
  • Last modified: 2021/01/12 15:38
  • by 127.0.0.1