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