ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
calculus.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_expressions of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace expressions {
9
10/// This inner namespace of module \alib_expressions_nl contains the implementations
11/// of built-in compiler plug-ins.
12///
13/// In addition, helper-class \b %Calculus is defined here, which is the foundation for most of
14/// the built-in functionality.
15///
16/// It is strongly recommended to use this helper-class for the creation of custom compiler plug-ins
17/// instead of deriving such from class \alib{expressions;CompilerPlugin} directly.
18///
19/// \note Sibling \alib module \alib_files, provides a compiler plug-in dedicated to file and
20/// directory trees.
21namespace plugins {
22
23
24//==================================================================================================
25/// ## 1. Introduction ##
26/// This struct specializes \b %CompilerPlugin and provides generic approaches and implementation
27/// of variants of method \b %TryCompilation.
28/// Consequently, this is the base type of most built-in compiler plug-ins, and is strongly
29/// recommended to consider this struct as the preferred base when implementing custom plug-ins.
30///
31/// The class implements virtual, overloaded methods
32/// - \alib{expressions::CompilerPlugin;TryCompilation(CIFunction&)},
33/// - \alib{expressions::CompilerPlugin;TryCompilation(CIUnaryOp&)},
34/// - \alib{expressions::CompilerPlugin;TryCompilation(CIBinaryOp&)}, and
35/// - \alib{expressions::CompilerPlugin;TryCompilation(CIAutoCast&)}.
36///
37/// For each <em>AST</em> node type to compile, this class holds a vector or a hash map to store
38/// all information needed for compilation.
39///
40/// The simple schema of using this class is:
41/// 1. Derive a custom type from this class.
42/// 2. Create constant value objects and C++ native callback functions.
43/// 3. Create constant (\c constexpr) tables with all compilation information.
44/// 4. In the constructor of the derived class, feed the tables into to this struct, using the
45/// corresponding helper methods.
46///
47/// \note
48/// Sample code and detailed explanations are given with user manual section
49/// \ref alib_expressions_cpcc_calculus "5.4 Class Calculus"
50/// and tutorial section
51/// \ref alib_expressions_tut_ffext "6. Extending The File Filter Sample"
52///
53/// <p>
54/// \note
55/// The name "Calculus" seems a little overstated, we admit.
56///
57/// ## 2. Choose Anonymous Namespaces ##
58///
59/// A good design pattern is to put the callback functions, constant values and compilation information
60/// tables into an anonymous namespace at the start of the compilation unit (.cc or .cpp file) of
61/// your custom plug-in. This way, the linker is not bothered with the function and object names,
62/// which solely are referenced by their address and never need to get linked to other units.
63///
64/// Just after this anonymous namespace, the implementation of the constructor of the custom
65/// plug-in, should be placed. As explained above, its duty is to fills in the vector/hash map using
66/// the right combination of operator or function argument types, as well as providing a proper
67/// \ref alib_expressions_prereq_sb "sample box" that corresponds to the type of the
68/// output parameter of the native function.
69///
70/// When implementing a custom plug-in, it may be helpful to have a look at the source code of
71/// the built-in plug-ins provided with module \alib_expressions.
72/// You will see that these implementations are quite straight forward and use some 'handy' local
73/// preprocessor macros that may be copied and used for custom implementations.
74///
75/// ## 3. Implementing Identifiers and Functions ##
76/// While parent class \b %CompilerPlugin does not make any direct distinction between functions
77/// that are always returning a constant value and those that don't, this class does.
78/// Arguably such functions are always parameterless, hence identifiers. Samples for such constants
79/// are \b "PI" or \b "True".<br>
80/// Such constant identifiers are supported by populating table #ConstantIdentifiers which is a
81/// \c std::vector of elements of type \b %ConstantIdentifiersEntry.
82/// For details on each "table column", refer to the documentation of the fields of
83/// \alib{expressions::plugins::Calculus;ConstantIdentifierEntry}.
84///
85/// Non-constant identifiers and functions are supported by populating table
86/// #Functions, which is a \c std::vector of elements of type \b %FunctionEntry.
87/// For details on each "table column", refer to the documentation of the fields of
88/// \alib{expressions::plugins::Calculus;FunctionEntry}.
89///
90/// Some notes:
91/// - It can be specified if function names are case-sensitive and whether they might be abbreviated.
92/// - The list of arguments (their types) accepted by a function is to be provided as a
93/// \c std::vector of \ref alib_expressions_prereq_sb "sample boxes". It is
94/// recommended to define such vectors once per unique function "signature" in the anonymous
95/// namespace section of the compilation unit and fill its contents once in the constructor of the
96/// custom plug-in. Such vectors can then be reused for each function that shares the same
97/// signature.
98/// - Variadic functions are supported by adding a final \e nulled \b %Box to the argument list.
99/// All sample argument types before this box are mandatory, but an arbitrary number of arguments
100/// of likewise arbitrary types may be followed. It is also allowed to add just that one \e nulled
101/// \b %Box to the signature vector, which leads to functions that accept just any number of any
102/// type of argument, including zero arguments.
103/// - With debug-builds, besides the callback function pointer, the C++ name of the callback
104/// function is to be provided. For this, macro \ref CALCULUS_CALLBACK is defined.
105/// The macro creates a stringified version of the given function pointer, separated by a comma.
106/// - Flag \doxlinkproblem{structalib_1_1expressions_1_1plugins_1_1Calculus_1_1FunctionEntry.html;a6bdb2157e6bb046c17b9d8ef7dd5969a;FunctionEntry::IsCTInvokable}
107/// is a boolean value
108/// that denotes whether a function can be evaluated at compile-time in the case that all of the
109/// parameters given in the expression are constant.
110/// If so, this struct will do the invocation at compile-time and return the constant result value
111/// instead of the function call.<br>
112/// Most built-in functions are compile-time invokable. For example, most mathematical functions
113/// like \c log(Float) or \c sin(Float) can be evaluated at compile-time (again, only in the case
114/// that the given parameters are constant). The reason is that
115/// these functions are independent of custom scope data.
116/// In contrast to this, custom functions, especially even parameterless identifiers usually are
117/// dependent on scope information and thus often cannot be evaluated at compile-time.
118///
119/// ## 4. Implementing Operators ##
120///
121/// ### 4.1 Unary And Binary Operators ###
122/// Apart from some specialities for binary operators documented in the next section, this class
123/// treats unary and binary the same.
124/// Wherever a second operator argument's type is requested, in case of unary operators static
125/// type specifier \alib{expressions;Types::Void} is to be given.
126///
127/// The compilation of unary and binary operators is supported by populating hash map #Operators.
128/// For feeding the map with entries, the following convenience types and methods are provided:
129/// - #AddOperator<br>
130/// This function adds compilation information for a single operator to field #Operators.
131///
132/// - #OperatorTableEntry<br>
133/// This is a type definition that allows defining tables with compilation information on
134/// operators. It is recommended to create such tables as \c constexpr data in an anonymous
135/// namespace of the compilation unit.
136///
137/// - #AddOperators<br>
138/// This is a pair of overloaded functions. One of them is templated and just used to deduce
139/// the length of the given table of static data. This table is then fed as a pointer, together
140/// with the table's size to the second method, which in turn feeds the table entries into
141/// field #Operators.
142///
143/// In other words: Method #AddOperator defines a single operator, while #AddOperators defines
144/// "bulk" data on operators which is defined in a static table.
145/// For details of the functions and types, consult the corresponding documentation.
146///
147/// As documented in user manual section
148/// \ref alib_expressions_operators_aliases "9.4 Type-Specific Operator Aliases",
149/// module \alib_expressions_nl supports the use of alias operators.
150/// This is reflected by this class with:
151///
152/// - #OperatorAliases<br>
153/// A hash map that collects information about unary and binary operator aliases.
154///
155/// - #AddOperatorAlias<br>
156/// This function adds information about an operator alias to field #OperatorAliases.
157///
158/// - #OperatorAliasTableEntry
159/// A type definition that allows defining tables with information about operator aliases.
160/// It is recommended to create such tables as \c constexpr data in an anonymous
161/// namespace of the compilation unit.
162///
163/// - AddOperatorAliases<br>
164/// This is a pair of overloaded functions. One of them is templated and just used to deduce
165/// the length of the given table of static data. This table is then fed as a pointer, together
166/// with the table size to the second method, which in turn feeds the table entries into
167/// field #OperatorAliases.
168///
169///
170/// ### 4.2 Specifics For Binary Operators ###
171///
172/// #### Aliasing '==' With '=': ####
173/// With the use of this class it is \e not necessary to define alias <c>'='</c> for binary
174/// operator <c>'=='</c>, because this alias replacement is internally always made for any
175/// combination of argument types, when compilation flag
176/// \alib{expressions;Compilation::AliasEqualsOperatorWithAssignOperator} is set in field
177/// \alib{expressions;Compiler::CfgCompilation}.
178///
179/// #### Aliasing Bitwise Boolean Operators: ####
180/// In contrast to the above, compilation flag \alib{expressions;Compilation::AllowBitwiseBooleanOperators}
181/// affects only built-in type \e boolean - just as the flag's name suggests.
182/// The flag is therefore tested only in derived plug-in \alib{expressions;plugins::Arithmetics}.
183/// In other words: to allow, for example, operator <c>'&'</c> to be used as an alias for operator
184/// <c>'&&'</c> defined on custom types, this has to be explicitly added as a set alias definitions
185/// for each combination of types in question.
186///
187/// #### Support For Compile-Time Optimization: ####
188/// For binary operators, this class provides a mechanism to provide information on possible
189/// compile-time optimizations.
190/// Samples of possible binary operator optimizations are given in documentation of struct
191/// \alib{expressions;CompilerPlugin::CIBinaryOp}.
192///
193/// The following fields and methods are provided:
194///
195/// - #BinaryOperatorOptimizations<br>
196/// A hash-map that collects information about possible optimizations of binary operators
197/// when either of the operands are a specific constant value.
198///
199/// - #BinaryOpOptimizationsTableEntry<br>
200/// A type definition that allows feeding tables (arrays of this type) with information about
201/// binary operator optimizations.
202/// It is recommended to create such tables as \c constexpr data in an anonymous
203/// namespace of the compilation unit.
204///
205/// - #AddBinaryOpOptimizations<br>
206/// A pair of overloaded functions. One of them is templated and just used to deduce
207/// the length of the given table of static data. This table is then fed as a pointer, together
208/// with the table size to the second method, which in turn feeds the table entries into
209/// hash map #BinaryOperatorOptimizations.
210///
211/// # Reference Documentation #
212//==================================================================================================
214{
215 /// Boolean to denote if a callback function allows compile-time invocation.
216 /// If \c true, on constant function input (either from expression string literals or sub-expressions
217 /// that have been optimized to constant input) the program can be optimized by invoking the
218 /// \alib{expressions;CallbackDecl} already at compile-time.
219 ///
220 /// This flag is set for most built-in functions, e.g., arithmetic calculations, but usually
221 /// cannot be set custom callbacks, as those usually rely on custom scope objects which are
222 /// available only at evaluation-time.
223 ///
224 /// \note
225 /// This type is used with helper-class \alib{expressions;plugins::Calculus} but exposed
226 /// as a namespace type for convenience, together with constants #CTI and
227 /// #ETI
228 ///
229 using CTInvokable= bool;
230
231
232 /// Used for values of #CTInvokable flags.<br>
233 /// The use of this constant makes code more readable.
234 static constexpr CTInvokable CTI = true;
235
236 /// Used for values of #CTInvokable flags to denote that a callback function
237 /// is only invokable at evaluation-time.<br>
238 /// The use of this constant makes code more readable.
239 static constexpr CTInvokable ETI = false;
240
241 /// This class uses monotonic allocation, which is well supported by the common way how this
242 /// type is used.
244
245 /// Constructor.
246 /// @param name Assigned to the field \alib{expressions;CompilerPlugin::Name}.
247 /// @param compiler The compiler we will get attached to
248 /// @param pPriority The priority of this plugin.
249 Calculus( const NString& name, Compiler& compiler, CompilePriorities pPriority )
250 : CompilerPlugin( name, compiler, pPriority )
251 , allocator (ALIB_DBG("Calculus",) 4)
255 { ALIB_DBG( allocator.DbgName= NCString(allocator, name).Buffer(); ) }
256
257 /// Virtual destructor.
258 virtual ~Calculus() override {}
259
260
261 //################################################################################################
262 // Constant Identifiers, Identifiers and Functions
263 //################################################################################################
264
265 /// An entry of field #ConstantIdentifiers. Describes how the identifier is recognized and
266 /// the constant value to return for it.
268 {
269 /// The name, minimum length and letter case sensitivity of the function to recognize.
271
272 /// The constant result.
274 };
275
276 /// List of identifiers that return constant values to be compiled by this plug-in.
277 std::vector<ConstantIdentifierEntry> ConstantIdentifiers;
278
279 /// An entry of field #Functions. Describes how the function is recognized and
280 /// the callback function and return type for it.
282 {
283 /// The name, minimum length and letter case sensitivity of the function to recognize.
285
286 /// A pointer to list of pointers to sample boxes that describe the function signature.
287 /// If \c nullptr, then the function does not accept parameters (aka is an identifier).
288 ///
289 /// To denote variadic parameters (similar to C/C++ ellipsis operator \c "..." ), either
290 /// \c nullptr or a \ref alib_boxing_more_void_void "void box" may be given as the last
291 /// array element. All prior provided boxes represent mandatory arguments, while the
292 /// function accepts an arbitrary number of arguments of arbitrary types in addition.
293 ///
294 /// The length of this list is given with field #SignatureLength.
295 ///
296 /// \see Macro \ref CALCULUS_SIGNATURE which is recommended to be used to pass both
297 /// fields (this and #SignatureLength). The macro accepts a C++ array of \b Box* and
298 /// deducts the array's length from the declaration type of the given array.
300
301 /// See #Signature for more information.
303
304 /// Callback function to add to the program. If \c nullptr, field #ResultType is
305 /// used as both: a constant value added to the program and the result type!
307
308
309 #if ALIB_DEBUG
310 /// The C++ name of the callback function (only available with debug-builds of the
311 /// library. Use preprocessor macro \ref CALCULUS_CALLBACK to provide this field
312 /// together with field #Callback. The macro selects to prune the name string
313 /// in release compilations.
314 const char* DbgCallbackName;
315 #endif
316
317 /// The result type given as a pointer to a \ref alib_expressions_prereq_sb "sample box".
318 ///
319 /// \note
320 /// If #Callback is \c nullptr, this box changes its meaning from being just a sample that
321 /// provides the return type of the callback function, to being the 'real' constant
322 /// result value that the function represents. However, it is preferable, to
323 /// implement such constant functions using field
324 /// \alib{expressions::plugins;Calculus::ConstantIdentifiers}
326
327 /// Denotes, if the callback function is allowed to be invoked on the
328 /// \alib{expressions;Scope} object used at compile-time.
329 /// This scope object is of the same (eventually custom) type as the one for evaluation,
330 /// however the evaluation-specific data is not set.
331 /// If allowed, such invocation is performed, if all function arguments are constant and
332 /// instead of the function, the result is returned.
334 };
335
336 /// List of functions to be compiled by this plug-in.
337 std::vector<FunctionEntry> Functions;
338
339 /// Searches in vectors #Functions and #ConstantIdentifiers for an entry matching \p{name} and,
340 /// if found, adds either a constant value or a callback function to \p{ciFunction}.
341 ///
342 /// This plug-in corrects abbreviated and letter case differences in functions within
343 /// in/out parameter \alib{expressions::CompilerPlugin;CIFunction::Name}.
344 ///
345 /// @param[in,out] ciFunction The compilation result.
346 /// @return \c true if an entry was found in #Functions and a corresponding command
347 /// was added to \p{ciFunction}. \c false otherwise.
349 virtual bool TryCompilation( CIFunction& ciFunction ) override;
350
351 //################################################################################################
352 // Operators
353 //################################################################################################
354 protected:
355
356 /// Key type for operator hash maps #Operators and OperatorAliases.
358 {
359 const String op; ///< A string defining the operator.
360 const std::type_info& lhs; ///< Left-hand side type.
361 const std::type_info& rhs; ///< Right-hand side type. For unary operators
362 ///< equals to <c>typeid(void)</c>.
363
364 /// Hash functor for operator hash map.
365 struct Hash
366 {
367 /// Calculates a hash code for objects of type \b OperatorKey.
368 /// @param src The node to hash.
369 /// @return The hash code.
370 std::size_t operator()(const OperatorKey& src) const {
371 return src.op.Hashcode()
372 + 4026031ul * src.lhs.hash_code()
373 + 8175383ul * src.rhs.hash_code();
374 }
375
376 };
377
378 /// Equality functor for operator hash map.
379 struct EqualTo
380 {
381 /// Compares two objects of type \b OperatorKey.
382 /// @param left The left-hand side object.
383 /// @param right The left-hand side object.
384 /// @return The result of the comparison.
385 bool operator()(const OperatorKey& left, const OperatorKey& right ) const {
386 return left.op == right.op
387 && left.lhs == right.lhs
388 && left.rhs == right.rhs;
389 }
390 };
391 };
392
393
394 public:
395
396 /// Hash map assigning combinations of (unary and binary) operators and its argument types to a
397 /// tuple providing information about a callback function.
398 ///
399 /// The tuple stored, contains the function pointer and the functions' return type.
400 /// A third member of type #CTInvokable indicates whether the callback function is allowed to be
401 /// invoked on the \alib{expressions;Scope} object used at compile-time.
402 /// This scope object is of the same (eventually custom) type as the one for evaluation, however
403 /// the evaluation-specific data is not set. In other words, the third tuple member denotes
404 /// if during program compilation the function might be invoked when the operator's argument(s)
405 /// are constant.
406 ///
407 /// A fourth tuple member of type \alib{strings;TString;String} is available only with debug-builds
408 /// and receives the name of the callback function.
409 ///
410 /// \note
411 /// This map, similar to map #OperatorAliases is best to be filled using corresponding
412 /// \e add-methods #AddOperator and #AddOperators.<br>
413 /// Usually this is done once in the constructor of derived classes.
415 OperatorKey,
416 std::tuple<CallbackDecl, Box, CTInvokable ALIB_DBG( , const char* ) >,
417 OperatorKey::Hash,
419
420 /// Hash map assigning combinations of alias versions of operators and their argument types to
421 /// the original operator.
422 ///
423 /// \note
424 /// This map, similar to map #Operators is best to be filled using corresponding
425 /// \e add-methods #AddOperatorAlias and #AddOperatorAliases.<br>
426 /// Usually this is done once in the constructor of derived classes.
429 String,
432
433
434 /// Entry of input tables (arrays) used with methods #AddOperators to perform bulk-loading of
435 /// compile definition data into map #Operators.<br>
436 /// The tuple elements are:
437 /// - The operator to compile.
438 /// - The type of the first argument of the operator.
439 /// - The type of the right-hand side argument of the operator.
440 /// For unary operators, value \alib{expressions;Types::Void} is to be provided.
441 /// - The callback function. Set to \c nullptr if operator evaluates constant.
442 /// - The C++ name of the callback function. (This tuple element is only available in debug
443 /// compilations of the library.)
444 /// - The result type sample box, respectively, if \b callback is \c nullptr, the constant result
445 /// value.
446 /// - Flag to denote if the callback function allows compile-time invocation and thus on constant
447 /// input the program can be optimized. This is true e.g., for arithmetic functions, but usually
448 /// not for custom operators that rely on scope objects available only at evaluation time.
449 using OperatorTableEntry= const std::tuple< String, Type, Type,
451 ALIB_DBG(const char* ,)
453
454 /// Entry of input tables (arrays) used with method #AddOperatorAliases to perform bulk-loading
455 /// of operator alias definition data into map #OperatorAliases.<br>
456 /// The tuple elements are:
457 /// - The alias operator.
458 /// - The type of first argument of the operator.
459 /// - The type of the right-hand side argument of the operator.
460 /// For unary operators, value \alib{expressions;Types::Void} is to be provided.
461 /// - The operator that gets aliased.
462 using OperatorAliasTableEntry= const std::tuple<String, Type, Type, String>;
463
464
465
466 #if DOXYGEN
467 //==============================================================================================
468 /// Adds an entry to the operator definition map #Operators.
469 ///
470 /// \see
471 /// If multiple operators are to be defined, consider the use of #AddOperators, which is a
472 /// variant of this method that allows effective bulk loading.
473 ///
474 /// @param op The operator.
475 /// @param lhsType The type of the first argument that the operator is defined for.
476 /// @param rhsType The type of the right-hand side argument that the operator is defined
477 /// for.
478 /// For unary operators, value \alib{expressions;Types::Void} is to be
479 /// provided.
480 /// @param callback The callback function to execute.
481 /// @param dbgCallbackName The name of the C++ name of the callback function.
482 /// \note This parameter is available (and to be passed) only in debug
483 /// version of the library.
484 /// @param cti See #CTInvokable for the meaning of this flag.
485 /// @param resultType The result type of the callback function.
486 //==============================================================================================
487 void AddOperator ( const String& op, Type lhsType, Type rhsType, CallbackDecl callback,
488 #if ALIB_DEBUG
489 const char* dbgCallbackName,
490 #endif
491 Type resultType,
492 CTInvokable cti );
493 #else // clang would complain about the doxing of parameter dbgCallbackName
495 void AddOperator ( const String& op, Type lhsType, Type rhsType, CallbackDecl callback,
496 #if ALIB_DEBUG
497 const char* dbgCallbackName,
498 #endif
499 Type resultType,
500 CTInvokable cti );
501 #endif
502
503
504 /// Templated helper method. Deduces the array size of the given table and passes it
505 /// to \ref AddOperators(OperatorTableEntry* table, size_t length).
506 ///
507 /// @tparam TCapacity Implicitly deferred size of the array provided.
508 /// @param table The table containing operator compilation information.
509 template<size_t TCapacity>
510 void AddOperators ( OperatorTableEntry (&table) [TCapacity] )
511 { AddOperators( &table[0], TCapacity ); }
512
513 /// Loads all entries of the given table into hash map #Operators.
514 ///
515 /// Note, that usually, the given table is a constexpr array located in an anonymous namespace
516 /// of a compilation unit.<br>
517 /// It can be passed as a reference to templated helper method, which defers the length of the
518 /// table implicitly.
519 ///
520 /// @param table The table containing operator compilation information.
521 /// @param length The table containing operator compilation information.
523 void AddOperators ( OperatorTableEntry* table, size_t length );
524
525 /// Adds an alias operator to hash table #OperatorAliases.
526 ///
527 /// \see
528 /// If multiple alias operators are to be defined, consider the use of #AddOperatorAliases,
529 /// which is a variant of this method that allows effective bulk loading.
530 ///
531 /// @param alias The alias for operator \p{op}.
532 /// @param lhsType The left-hand side argument type that the operator is defined for.
533 /// @param rhsType The right-hand side argument type that the operator is defined for.
534 /// @param op The operator aliased by \p{alias}.
535 void AddOperatorAlias ( const String& alias, Type lhsType, Type rhsType, const String& op );
536
537 /// Templated helper method. Deduces the array size of the given table and passes it
538 /// to \ref AddOperatorAliases(OperatorAliasTableEntry* table, size_t length).
539 ///
540 /// @tparam TCapacity Implicitly deferred size of the array provided.
541 /// @param table The table containing operator compilation information.
542 template<size_t TCapacity>
543 void AddOperatorAliases( OperatorAliasTableEntry (&table) [TCapacity] )
544 { AddOperatorAliases( &table[0], TCapacity ); }
545
546 /// Loads all entries of the given table into hash map #OperatorAliases.
547 ///
548 /// Note, that usually, the given table is a constexpr array located in an anonymous namespace
549 /// of a compilation unit.<br>
550 /// It can be passed as a reference to templated helper method, which defers the length of the
551 /// table implicitly.
552 ///
553 /// @param table The table containing operator compilation information.
554 /// @param length The table containing operator compilation information.
555 void AddOperatorAliases( OperatorAliasTableEntry* table, size_t length );
556
557
558 //################################################################################################
559 // Binary operator optimizations
560 //################################################################################################
561 protected:
562
563 /// Key type for operator hash maps #Operators and OperatorAliases.
565 {
566 const String op; ///< The operator to optimize.
567 lang::Side constSide; ///< Denotes a left- or right-hand side optimization.
568 const Box constVal; ///< The type and value of the constant argument.
569 const std::type_info& other; ///< The type of the non-constant argument.
570
571 /// Hash functor for operator hash map.
572 struct Hash
573 {
574 /// Calculates a hash code for objects of type \b OperatorKey.
575 /// @param src The node to hash.
576 /// @return The hash code.
577 std::size_t operator()(const BinOpOptKey& src) const {
578 return ( std::hash<String>()(src.op)
579 + 6949ul * std::hash<Box>()(src.constVal)
580 + 14033ul * src.other.hash_code()
581 ) ^ ( src.constSide == lang::Side::Left ? size_t( 0)
582 : size_t(-1) );
583 }
584 };
585
586 /// Equality functor for operator hash map.
587 struct EqualTo
588 {
589 /// Compares two objects of type \b OperatorKey.
590 /// @param lhs The left-hand side object.
591 /// @param rhs The left-hand side object.
592 /// @return The result of the comparison.
593 bool operator()(const BinOpOptKey& lhs, const BinOpOptKey& rhs ) const {
594 return lhs.op == rhs.op
595 && lhs.constSide== rhs.constSide
596 && lhs.constVal == rhs.constVal
597 && lhs.other == rhs.other;
598 }
599 };
600 };
601
602 public:
603 /// Hash map storing optimization information for binary operators where either argument is
604 /// constant.<br>
605 /// This map may be filled with #AddBinaryOpOptimizations, which is usually done in the.
606 /// constructor of derived classes.
607 ///
608 /// The stored element of type \b Box may contain either, a constant result value that replaces
609 /// the binary operator (as in <c> x || true</c>) or be a \e nulled box, which indicates that
610 /// the result equals the non-constant argument (as in <c>x && true</c>).
612 BinOpOptKey, Box,
613 BinOpOptKey::Hash,
615
616 /// Entry of arrays used with methods #AddBinaryOpOptimizations to perform bulk-loading of
617 /// optimization data to hash map #BinaryOperatorOptimizations.<br>
618 /// The tuple element's meanings are:
619 /// - The operator to optimize.
620 /// - Denotes if an optimization applies if the left-hand side or right-hand side argument
621 /// is constant.
622 /// - The type and value of the constant argument.
623 /// - The type of the non-constant argument.
624 /// - Either, a constant result value that replaces the binary operator
625 /// (as in <c> x || true</c>) or a \e nulled box, which indicates that the result equals the
626 /// non-constant argument (as in <c>x && true</c>).
627 using BinaryOpOptimizationsTableEntry= const std::tuple<String, lang::Side, Type, const Box&, const Box&>;
628
629
630 /// Templated helper method. Deduces the array size of the given table and passes it
631 /// to \ref AddBinaryOpOptimizations(BinaryOpOptimizationsTableEntry*, size_t).
632 ///
633 /// @tparam TCapacity Implicitly deferred size of the array provided.
634 /// @param table The table containing operator compilation information.
635 template<size_t TCapacity>
637 { AddBinaryOpOptimizations( &table[0], TCapacity ); }
638
639 /// Loads all entries of the given table into hash map #BinaryOperatorOptimizations.
640 ///
641 /// Note, that usually, the given table is a constexpr array located in an anonymous namespace
642 /// of a compilation unit.<br>
643 /// It can be passed as a reference to templated helper method, which defers the length of the
644 /// table implicitly.
645 ///
646 /// @param table The table containing operator compilation information.
647 /// @param length The table containing operator compilation information.
649 void AddBinaryOpOptimizations( BinaryOpOptimizationsTableEntry* table, size_t length );
650
651 /// Searches in #Operators for an entry matching the combination of
652 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CIUnaryOp.html;a2eba8729cc1606107496dbd797966b5c;CIUnaryOp::Operator}
653 /// and the argument type of operand found with iterator
654 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CompilationInfo.html;afbf28a2c7a1396f91fa6a120a4f65d06;CompilationInfo::ArgsBegin}.
655 /// (The second argument type of the key of the hash map #Operators is set to
656 /// \alib{expressions;Types::Void}).
657 /// If found, the corresponding callback function and result type are added the \p{CIUnaryOp}.
658 ///
659 /// Before the search, it is checked whether the given operator is an alias for another
660 /// operator. Operator aliases might be defined by filling map #OperatorAliases in the
661 /// constructor of the derived types.
662 /// If so, the corrected operator is returned with in/out parameter
663 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CIUnaryOp.html;a2eba8729cc1606107496dbd797966b5c;CIUnaryOp::Operator}.
664 ///
665 /// @param ciUnaryOp The compilation result.
666 /// @return \c true if an entry was found in #Operators and a corresponding command was added to
667 /// \p{ciUnaryOp}. \c false otherwise.
669 virtual bool TryCompilation( CIUnaryOp& ciUnaryOp ) override;
670
671
672 /// Searches in #Operators for an entry matching the combination of
673 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CIBinaryOp.html;a2eba8729cc1606107496dbd797966b5c;CIBinaryOp::Operator}
674 /// and the argument types of operands found with argument iterators
675 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CompilationInfo.html;afbf28a2c7a1396f91fa6a120a4f65d06;CompilationInfo::ArgsBegin}
676 /// and
677 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CompilationInfo.html;a28ed4e83d13c904617e09c519bee73df;CompilationInfo::ArgsBegin}.
678 /// If found, the corresponding callback function and result type are added the \p{CIBinaryOp}.
679 ///
680 /// Before the search, it is checked whether the given operator is an alias for another
681 /// operator. Operator aliases might be defined by filling map #OperatorAliases in the
682 /// constructor of the derived types.
683 /// If so, the corrected operator is returned with in/out parameter
684 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CIBinaryOp.html;a2eba8729cc1606107496dbd797966b5c;CIBinaryOp::Operator}.
685 ///
686 /// @param ciBinaryOp The compilation info struct.
687 /// @return \c true if an entry was found in #Operators and a corresponding command was added
688 /// to \p{ciBinaryOp}. \c false otherwise.
690 virtual bool TryCompilation( CIBinaryOp& ciBinaryOp ) override;
691
692
693 //################################################################################################
694 // Auto-Casts
695 //################################################################################################
696
697 /// An entry of the field #AutoCasts. Defines auto-casts for custom types.
699 {
700 /// The type that is to be automatically cast.
702
703 /// List of operators that the auto-cast accepts.
704 /// If \e nulled, then just any operator that is not in #OperatorsDeclined is accepted.
705 std::vector<String>* OperatorsAccepted;
706
707 /// List of operators that the auto-cast does not accept. An operator should not appear
708 /// in both lists, this one and list #OperatorsAccepted. However, it is does, then the
709 /// operator is not accepted.
710 ///
711 /// A value of \c nullptr is allowed to indicate no declined operators.
712 std::vector<String>* OperatorsDeclined;
713
714 /// Callback function to add to the program that performs the auto-cast.
715 ///
716 /// If \c nullptr is given, then an internal, predefined callback is used, which
717 /// returns a value of type \alib{expressions;Types::Integer} which is generated by
718 /// taking the \alib{boxing;Box::Data;raw value} of the argument box. This is
719 /// especially useful for any boxed enum type that is to be made compatible
720 /// with bitwise boolean operators (and other integral calculations and functions).
722
723
724 #if ALIB_DEBUG
725 /// The C++ name of the callback function (only available with debug-builds of the
726 /// library. Use preprocessor macro \ref CALCULUS_CALLBACK to provide this field
727 /// together with field #Callback. The macro selects to prune the name string
728 /// in release compilations.
729 ///
730 /// If #Callback is set to nullptr, the name of the internal function (\e "any2int")
731 /// is inserted automatically. Instead of the aforementioned macro \ref CALCULUS_CALLBACK
732 /// use macro \ref CALCULUS_DEFAULT_AUTOCAST instead.
733 const char* DbgCallbackName;
734 #endif
735
736 /// The result type given a \ref alib_expressions_prereq_sb "sample box".
737 ///
738 /// If field #Callback is \c nullptr to specify the use of the internal, default cast
739 /// function, this field will be ignored and \alib{expressions;Types::Integer}, will
740 /// be set instead. Hence, in this case, this field can be specified as \c nullptr.
742
743 /// This is the name of the function that reverses the cast. The function is used when an
744 /// expression with an auto-cast function is \e decompiled to generate compilable,
745 /// optimized expression strings.
746 ///
747 /// \note
748 /// This method is needed only if "normalized, optimized expression strings" are
749 /// to be generated. For more information on this topic consult manual section
750 /// \ref alib_expressions_details_optimizations_norm.
751 ///
752 /// \note
753 /// If the aforementioned feature is used, then this function name has to be
754 /// provided together with the implementation of the expression function itself,
755 /// even if the internal default cast implementation (activated by setting field
756 /// #Callback to \c nullptr) is used. The rationale is, that this library cannot
757 /// automatically convert integral types back to a custom type. This is even true
758 /// for simple enumeration types.
760 };
761
762 /// List of auto-casts to be compiled by this plug-in.
763 std::vector<AutoCastEntry> AutoCasts;
764
765
766 /// Searches in #AutoCasts for an entry matching the combination of
767 /// \doxlinkproblem{structalib_1_1expressions_1_1CompilerPlugin_1_1CIAutoCast.html;a2eba8729cc1606107496dbd797966b5c;CIAutoCast::Operator} and the type(s) that might be auto-cast.
768 ///
769 /// An entry in #AutoCasts might also be defined to work on just all operators.
770 ///
771 /// For the very frequent use case of auto-casting custom enum types to integral types, only
772 /// fields
773 /// \doxlinkproblem{structalib_1_1expressions_1_1plugins_1_1Calculus_1_1AutoCastEntry.html;ac127c6ab57163304f334a48751db6897;AutoCastEntry::Type}
774 /// and
775 /// \doxlinkproblem{structalib_1_1expressions_1_1plugins_1_1Calculus_1_1AutoCastEntry.html;a1b78ad7a906e7c8e0f3d5b471ecb8fbf;AutoCastEntry::ReverseCastFunctionName}
776 /// have to be provided.
777 ///
778 /// \note
779 /// This method of this helper-class is not applicable if one of the following conditions apply
780 /// to a use case:
781 /// - Different auto-casts are to be applied for the first and second arguments of binary
782 /// operators.
783 /// - The custom auto-cast method is not compile-time invokable.
784 ///
785 /// \note
786 /// In this case, a custom implementation of this method has to be provided to fetch
787 /// these cases. The custom method might then invoke this base implementation.
788 ///
789 /// @param autoCast The compilation info struct.
790 /// @return \c true if a matching entry was found in #AutoCasts and a corresponding command
791 /// was added to \p{autoCast}. \c false otherwise.
793 virtual bool TryCompilation(CIAutoCast& autoCast) override;
794};
795
796}} // namespace alib[::expressions::plugin]
797
798/// Type alias in namespace \b alib.
800
801} // namespace [alib]
std::size_t Hashcode() const
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_DBG(...)
Definition alib.inl:853
#define ALIB_DEBUG
Definition prepro.dox.md:21
Box(*)(Scope &scope, ArgIterator argsBegin, ArgIterator argsEnd) CallbackDecl
const alib::boxing::Box & Type
Side
Denotes if something is left or right.
@ Left
Denotes the left side of something.
expressions::plugins::Calculus Calculus
Type alias in namespace alib.
Definition calculus.inl:799
strings::util::Token Token
Type alias in namespace alib.
Definition token.inl:398
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2198
containers::HashMap< TAllocator, TKey, TMapped, THash, TEqual, THashCaching, TRecycling > HashMap
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:484
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1149
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
CompilerPlugin(const NString &name, Compiler &compiler, CompilePriorities pPriority)
An entry of the field AutoCasts. Defines auto-casts for custom types.
Definition calculus.inl:699
Box Type
The type that is to be automatically cast.
Definition calculus.inl:701
Equality functor for operator hash map.
Definition calculus.inl:588
bool operator()(const BinOpOptKey &lhs, const BinOpOptKey &rhs) const
Definition calculus.inl:593
std::size_t operator()(const BinOpOptKey &src) const
Definition calculus.inl:577
Key type for operator hash maps Operators and OperatorAliases.
Definition calculus.inl:565
lang::Side constSide
Denotes a left- or right-hand side optimization.
Definition calculus.inl:567
const String op
The operator to optimize.
Definition calculus.inl:566
const Box constVal
The type and value of the constant argument.
Definition calculus.inl:568
const std::type_info & other
The type of the non-constant argument.
Definition calculus.inl:569
Token Descriptor
The name, minimum length and letter case sensitivity of the function to recognize.
Definition calculus.inl:270
size_t SignatureLength
See Signature for more information.
Definition calculus.inl:302
Token Descriptor
The name, minimum length and letter case sensitivity of the function to recognize.
Definition calculus.inl:284
Equality functor for operator hash map.
Definition calculus.inl:380
bool operator()(const OperatorKey &left, const OperatorKey &right) const
Definition calculus.inl:385
std::size_t operator()(const OperatorKey &src) const
Definition calculus.inl:370
Key type for operator hash maps Operators and OperatorAliases.
Definition calculus.inl:358
const std::type_info & lhs
Left-hand side type.
Definition calculus.inl:360
const String op
A string defining the operator.
Definition calculus.inl:359
void AddOperatorAlias(const String &alias, Type lhsType, Type rhsType, const String &op)
Definition calculus.cpp:107
static constexpr CTInvokable ETI
Definition calculus.inl:239
HashMap< MonoAllocator, OperatorKey, std::tuple< CallbackDecl, Box, CTInvokable ALIB_DBG(, const char *) >, OperatorKey::Hash, OperatorKey::EqualTo > Operators
Definition calculus.inl:418
virtual ALIB_DLL bool TryCompilation(CIFunction &ciFunction) override
Definition calculus.cpp:336
Calculus(const NString &name, Compiler &compiler, CompilePriorities pPriority)
Definition calculus.inl:249
void AddOperatorAliases(OperatorAliasTableEntry(&table)[TCapacity])
Definition calculus.inl:543
const std::tuple< String, lang::Side, Type, const Box &, const Box & > BinaryOpOptimizationsTableEntry
Definition calculus.inl:627
std::vector< ConstantIdentifierEntry > ConstantIdentifiers
List of identifiers that return constant values to be compiled by this plug-in.
Definition calculus.inl:277
virtual ~Calculus() override
Virtual destructor.
Definition calculus.inl:258
static constexpr CTInvokable CTI
Definition calculus.inl:234
void AddBinaryOpOptimizations(BinaryOpOptimizationsTableEntry(&table)[TCapacity])
Definition calculus.inl:636
HashMap< MonoAllocator, BinOpOptKey, Box, BinOpOptKey::Hash, BinOpOptKey::EqualTo > BinaryOperatorOptimizations
Definition calculus.inl:614
std::vector< AutoCastEntry > AutoCasts
List of auto-casts to be compiled by this plug-in.
Definition calculus.inl:763
void AddOperators(OperatorTableEntry(&table)[TCapacity])
Definition calculus.inl:510
std::vector< FunctionEntry > Functions
List of functions to be compiled by this plug-in.
Definition calculus.inl:337
void AddOperator(const String &op, Type lhsType, Type rhsType, CallbackDecl callback, const char *dbgCallbackName, Type resultType, CTInvokable cti)
Definition calculus.cpp:35
HashMap< MonoAllocator, OperatorKey, String, OperatorKey::Hash, OperatorKey::EqualTo > OperatorAliases
Definition calculus.inl:431
const std::tuple< String, Type, Type, String > OperatorAliasTableEntry
Definition calculus.inl:462
const std::tuple< String, Type, Type, CallbackDecl, Type, CTInvokable > OperatorTableEntry
Definition calculus.inl:449