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 revisionBoth sides next revision
reference:rulefiles [2018/09/08 22:01] – [Functions] gawrilowuser_guide:extend:rulefiles [2019/01/25 16:02] – ↷ Page moved from reference:rulefiles to user_guide:extend:rulefiles oroehrig
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 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 134: Line 134:
   .. An optional //spec_name// can be assigned to the partial specialization in order to be able to reopen it later elsewhere in the rulebase.  For the sake of well-formed documentation, it is required that any partial specialization that introduces any user-visible features (properties or user-methods) must be given an own name.  Apart from that, the specialization name can't be used for anything; in particular, it can't be used as a type designator in property declarations, constructors, typeof expressions, etc.  The specialization names are localized by the object type, so that it is possible to reuse the same name for similar specializations of distinct object types.   .. An optional //spec_name// can be assigned to the partial specialization in order to be able to reopen it later elsewhere in the rulebase.  For the sake of well-formed documentation, it is required that any partial specialization that introduces any user-visible features (properties or user-methods) must be given an own name.  Apart from that, the specialization name can't be used for anything; in particular, it can't be used as a type designator in property declarations, constructors, typeof expressions, etc.  The specialization names are localized by the object type, so that it is possible to reuse the same name for similar specializations of distinct object types.
   ? ''declare object_specialization'' spec_name '' = '' object_type ''{'' \\ ''precondition : '' SOURCE, ... { ... } \\ ... \\ ''}''   ? ''declare object_specialization'' spec_name '' = '' object_type ''{'' \\ ''precondition : '' SOURCE, ... { ... } \\ ... \\ ''}''
-  :: Introduces a //restricted// specialization for the given "big" object type.  The rules, properties, and methods defined herein are only defined for objects fulfilling one or more [[rules#preconditions|preconditions]].  The preconditions are written in exactly the same way as for production rules.  Note that a partial specialization can be restricted by preconditions as well.+  :: Introduces a //restricted// specialization for the given "big" object type.  The rules, properties, and methods defined herein are only defined for objects fulfilling one or more [[reference:rules#preconditions|preconditions]].  The preconditions are written in exactly the same way as for production rules.  Note that a partial specialization can be restricted by preconditions as well.
   ? ''object_specialization'' object_name''::''spec_name ''{'' \\ ... \\ ''}''   ? ''object_specialization'' object_name''::''spec_name ''{'' \\ ... \\ ''}''
   :: 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 275: Line 275:
 ==== 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 [[: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.
   .. 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 [[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.
   .. 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.
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