ALib C++ Framework
by
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 #"mainpage_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 #"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 the
27/// implementation 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/// - #"CompilerPlugin::TryCompilation(CIFunction&)",
33/// - #"CompilerPlugin::TryCompilation(CIUnaryOp&)",
34/// - #"CompilerPlugin::TryCompilation(CIBinaryOp&)", and
35/// - #"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 native C++ 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/// #"alib_expressions_cpcc_calculus"
50/// and tutorial section
51/// #"alib_expressions_tut_ffext"
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 fill the vector/hash map using
66/// the right combination of operator or function argument types, as well as providing a proper
67/// #"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 the table #"ConstantIdentifiers" which is
81/// a \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/// #"Calculus;ConstantIdentifierEntry".
84///
85/// Non-constant identifiers and functions are supported by populating the 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/// #"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 #"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 #"CALCULUS_CALLBACK" is defined.
105/// The macro creates a stringified version of the given function pointer, separated by a comma.
106/// - Flag #"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 the case of unary operators, static
125/// type specifier #"Types::Void;*" is to be given.
126///
127/// The compilation of unary and binary operators is supported by populating the hash map
128/// #"Operators".
129/// For feeding the map with entries, the following convenience types and methods are provided:
130/// - #"AddOperator"<br>
131/// This function adds compilation information for a single operator to the field #"Operators".
132///
133/// - #"OperatorTableEntry"<br>
134/// This is a type definition that allows defining tables with compilation information on
135/// operators. It is recommended to create such tables as \c constexpr data in an anonymous
136/// namespace of the compilation unit.
137///
138/// - #AddOperators<br>
139/// This is a pair of overloaded functions. One of them is templated and just used to deduce
140/// the length of the given table of static data. This table is then fed as a pointer, together
141/// with the table's size to the second method, which in turn feeds the table entries into
142/// field #Operators.
143///
144/// In other words: Method #AddOperator defines a single operator, while #AddOperators defines
145/// "bulk" data on operators which is defined in a static table.
146/// For details of the functions and types, consult the corresponding documentation.
147///
148/// As documented in user manual section
149/// #"alib_expressions_operators_aliases",
150/// module \alib_expressions_nl supports the use of alias operators.
151/// This is reflected by this class with:
152///
153/// - #OperatorAliases<br>
154/// A hash map that collects information about unary and binary operator aliases.
155///
156/// - #AddOperatorAlias<br>
157/// This function adds information about an operator alias to field #OperatorAliases.
158///
159/// - #OperatorAliasTableEntry
160/// A type definition that allows defining tables with information about operator aliases.
161/// It is recommended to create such tables as \c constexpr data in an anonymous
162/// namespace of the compilation unit.
163///
164/// - AddOperatorAliases<br>
165/// This is a pair of overloaded functions. One of them is templated and just used to deduce
166/// the length of the given table of static data. This table is then fed as a pointer, together
167/// with the table size to the second method, which in turn feeds the table entries into
168/// field #OperatorAliases.
169///
170///
171/// ### 4.2 Specifics For Binary Operators ###
172///
173/// #### Aliasing '==' With '=': ####
174/// With the use of this class it is \e not necessary to define alias <c>'='</c> for binary
175/// operator <c>'=='</c>, because this alias replacement is internally always made for any
176/// combination of argument types, when compilation flag
177/// #"Compilation::AliasEqualsOperatorWithAssignOperator;*" is set in field
178/// #"Compiler::CfgCompilation;*".
179///
180/// #### Aliasing Bitwise Boolean Operators: ####
181/// In contrast to the above, compilation flag #"Compilation::AllowBitwiseBooleanOperators;*"
182/// affects only built-in type \e boolean - just as the flag's name suggests.
183/// The flag is therefore tested only in derived plug-in #"plugins::Arithmetics;*".
184/// In other words: to allow, for example, operator <c>'&'</c> to be used as an alias for operator
185/// <c>'&&'</c> defined on custom types, this has to be explicitly added as a set alias definitions
186/// for each combination of types in question.
187///
188/// #### Support For Compile-Time Optimization: ####
189/// For binary operators, this class provides a mechanism to provide information on possible
190/// compile-time optimizations.
191/// Samples of possible binary operator optimizations are given in documentation of struct
192/// #"CompilerPlugin::CIBinaryOp;*".
193///
194/// The following fields and methods are provided:
195///
196/// - #BinaryOperatorOptimizations<br>
197/// A hash-map that collects information about possible optimizations of binary operators
198/// when either of the operands are a specific constant value.
199///
200/// - #BinaryOpOptimizationsTableEntry<br>
201/// A type definition that allows feeding tables (arrays of this type) with information about
202/// binary operator optimizations.
203/// It is recommended to create such tables as \c constexpr data in an anonymous
204/// namespace of the compilation unit.
205///
206/// - #AddBinaryOpOptimizations<br>
207/// A pair of overloaded functions. One of them is templated and just used to deduce
208/// the length of the given table of static data. This table is then fed as a pointer, together
209/// with the table size to the second method, which in turn feeds the table entries into
210/// hash map #BinaryOperatorOptimizations.
211///
212/// # Reference Documentation #
213//==================================================================================================
215{
216 /// Boolean to denote if a callback function allows compile-time invocation.
217 /// If \c true, on constant function input (either from expression string literals or sub-expressions
218 /// that have been optimized to constant input) the program can be optimized by invoking the
219 /// #"CallbackDecl" already at compile-time.
220 ///
221 /// This flag is set for most built-in functions, e.g., arithmetic calculations, but usually
222 /// cannot be set custom callbacks, as those usually rely on custom scope objects which are
223 /// available only at evaluation-time.
224 ///
225 /// \note
226 /// This type is used with helper-class #"plugins::Calculus;*" but exposed
227 /// as a namespace type for convenience, together with constants #CTI and
228 /// #ETI
229 ///
230 using CTInvokable= bool;
231
232
233 /// Used for values of #CTInvokable flags.<br>
234 /// The use of this constant makes code more readable.
235 static constexpr CTInvokable CTI = true;
236
237 /// Used for values of #CTInvokable flags to denote that a callback function
238 /// is only invokable at evaluation-time.<br>
239 /// The use of this constant makes code more readable.
240 static constexpr CTInvokable ETI = false;
241
242 /// This class uses monotonic allocation, which is well supported by the common way how this
243 /// type is used.
245
246 /// Constructor.
247 /// @param name Assigned to the field #"CompilerPlugin::Name;*".
248 /// @param compiler The compiler we will get attached to
249 /// @param pPriority The priority of this plugin.
250 Calculus( const NString& name, Compiler& compiler, CompilePriorities pPriority )
251 : CompilerPlugin( name, compiler, pPriority )
252 , allocator (ALIB_DBG("Calculus",) 4)
256 { ALIB_DBG( allocator.DbgName= NCString(allocator, name).Buffer(); ) }
257
258 /// Virtual destructor.
259 virtual ~Calculus() override {}
260
261
262 //################################################################################################
263 // Constant Identifiers, Identifiers and Functions
264 //################################################################################################
265
266 /// An entry of field #ConstantIdentifiers. Describes how the identifier is recognized and
267 /// the constant value to return for it.
269 {
270 /// The name, minimum length and letter case sensitivity of the function to recognize.
272
273 /// The constant result.
275 };
276
277 /// List of identifiers that return constant values to be compiled by this plug-in.
278 std::vector<ConstantIdentifierEntry> ConstantIdentifiers;
279
280 /// An entry of field #Functions. Describes how the function is recognized and
281 /// the callback function and return type for it.
283 {
284 /// The name, minimum length and letter case sensitivity of the function to recognize.
286
287 /// A pointer to list of pointers to sample boxes that describe the function signature.
288 /// If \c nullptr, then the function does not accept parameters (aka is an identifier).
289 ///
290 /// To denote variadic parameters (similar to C/C++ ellipsis operator \c "..." ), either
291 /// \c nullptr or a #"alib_boxing_more_void_void;void box" may be given as the last
292 /// array element. All prior provided boxes represent mandatory arguments, while the
293 /// function accepts an arbitrary number of arguments of arbitrary types in addition.
294 ///
295 /// The length of this list is given with field #SignatureLength.
296 ///
297 /// \see Macro #"CALCULUS_SIGNATURE" which is recommended to be used to pass both
298 /// fields (this and #SignatureLength). The macro accepts a C++ array of \b Box* and
299 /// deducts the array's length from the declaration type of the given array.
301
302 /// See #Signature for more information.
304
305 /// Callback function to add to the program. If \c nullptr, field #ResultType is
306 /// used as both: a constant value added to the program and the result type!
308
309
310 #if ALIB_DEBUG
311 /// The C++ name of the callback function (only available with debug-builds of the
312 /// library. Use preprocessor macro #"CALCULUS_CALLBACK" to provide this field
313 /// together with field #Callback. The macro selects to prune the name string
314 /// in release compilations.
315 const char* DbgCallbackName;
316 #endif
317
318 /// The result type given as a pointer to a #"alib_expressions_prereq_sb;sample box".
319 ///
320 /// \note
321 /// If #Callback is \c nullptr, this box changes its meaning from being just a sample that
322 /// provides the return type of the callback function, to being the 'real' constant
323 /// result value that the function represents. However, it is preferable, to
324 /// implement such constant functions using field
325 /// #"Calculus::ConstantIdentifiers"
327
328 /// Denotes, if the callback function is allowed to be invoked on the
329 /// #"expressions::Scope" object used at compile-time.
330 /// This scope object is of the same (eventually custom) type as the one for evaluation,
331 /// however the evaluation-specific data is not set.
332 /// If allowed, such invocation is performed, if all function arguments are constant and
333 /// instead of the function, the result is returned.
335 };
336
337 /// List of functions to be compiled by this plug-in.
338 std::vector<FunctionEntry> Functions;
339
340 /// Searches in vectors #Functions and #ConstantIdentifiers for an entry matching \p{name} and,
341 /// if found, adds either a constant value or a callback function to \p{ciFunction}.
342 ///
343 /// This plug-in corrects abbreviated and letter case differences in functions within
344 /// in/out parameter #"CIFunction::Name".
345 ///
346 /// @param[in,out] ciFunction The compilation result.
347 /// @return \c true if an entry was found in #Functions and a corresponding command
348 /// was added to \p{ciFunction}. \c false otherwise.
350 virtual bool TryCompilation( CIFunction& ciFunction ) override;
351
352 //################################################################################################
353 // Operators
354 //################################################################################################
355 protected:
356
357 /// Key type for operator hash maps #Operators and OperatorAliases.
359 {
360 const String op; ///< A string defining the operator.
361 const std::type_info& lhs; ///< Left-hand side type.
362 const std::type_info& rhs; ///< Right-hand side type. For unary operators
363 ///< equals to <c>typeid(void)</c>.
364
365 /// Hash functor for operator hash map.
366 struct Hash
367 {
368 /// Calculates a hash code for objects of type \b OperatorKey.
369 /// @param src The node to hash.
370 /// @return The hash code.
371 std::size_t operator()(const OperatorKey& src) const {
372 return src.op.Hashcode()
373 + 4026031ul * src.lhs.hash_code()
374 + 8175383ul * src.rhs.hash_code();
375 }
376
377 };
378
379 /// Equality functor for operator hash map.
380 struct EqualTo
381 {
382 /// Compares two objects of type \b OperatorKey.
383 /// @param left The left-hand side object.
384 /// @param right The left-hand side object.
385 /// @return The result of the comparison.
386 bool operator()(const OperatorKey& left, const OperatorKey& right ) const {
387 return left.op == right.op
388 && left.lhs == right.lhs
389 && left.rhs == right.rhs;
390 }
391 };
392 };
393
394
395 public:
396
397 /// Hash map assigning combinations of (unary and binary) operators and its argument types to a
398 /// tuple providing information about a callback function.
399 ///
400 /// The tuple stored, contains the function pointer and the functions' return type.
401 /// A third member of type #CTInvokable indicates whether the callback function is allowed to be
402 /// invoked on the #"expressions::Scope" object used at compile-time.
403 /// This scope object is of the same (eventually custom) type as the one for evaluation, however
404 /// the evaluation-specific data is not set. In other words, the third tuple member denotes
405 /// if during program compilation the function might be invoked when the operator's argument(s)
406 /// are constant.
407 ///
408 /// A fourth tuple member of type #"TString;String" is available only with debug-builds
409 /// and receives the name of the callback function.
410 ///
411 /// \note
412 /// This map, similar to map #OperatorAliases is best to be filled using corresponding
413 /// \e add-methods #AddOperator and #AddOperators.<br>
414 /// Usually this is done once in the constructor of derived classes.
416 OperatorKey,
417 std::tuple<CallbackDecl, Box, CTInvokable ALIB_DBG( , const char* ) >,
418 OperatorKey::Hash,
420
421 /// Hash map assigning combinations of alias versions of operators and their argument types to
422 /// the original operator.
423 ///
424 /// \note
425 /// This map, similar to map #Operators is best to be filled using corresponding
426 /// \e add-methods #AddOperatorAlias and #AddOperatorAliases.<br>
427 /// Usually this is done once in the constructor of derived classes.
430 String,
433
434
435 /// Entry of input tables (arrays) used with methods #AddOperators to perform bulk-loading of
436 /// compile definition data into map #Operators.<br>
437 /// The tuple elements are:
438 /// - The operator to compile.
439 /// - The type of the first argument of the operator.
440 /// - The type of the right-hand side argument of the operator.
441 /// For unary operators, value #"Types::Void;*" is to be provided.
442 /// - The callback function. Set to \c nullptr if operator evaluates constant.
443 /// - The C++ name of the callback function. (This tuple element is only available in debug
444 /// compilations of the library.)
445 /// - The result type sample box, respectively, if \b callback is \c nullptr, the constant result
446 /// value.
447 /// - Flag to denote if the callback function allows compile-time invocation and thus on constant
448 /// input the program can be optimized. This is true e.g., for arithmetic functions, but usually
449 /// not for custom operators that rely on scope objects available only at evaluation time.
450 using OperatorTableEntry= const std::tuple< String, Type, Type,
452 ALIB_DBG(const char* ,)
454
455 /// Entry of input tables (arrays) used with method #AddOperatorAliases to perform bulk-loading
456 /// of operator alias definition data into map #OperatorAliases.<br>
457 /// The tuple elements are:
458 /// - The alias operator.
459 /// - The type of first argument of the operator.
460 /// - The type of the right-hand side argument of the operator.
461 /// For unary operators, value #"Types::Void;*" is to be provided.
462 /// - The operator that gets aliased.
463 using OperatorAliasTableEntry= const std::tuple<String, Type, Type, String>;
464
465
466
467 #if DOXYGEN
468 //==============================================================================================
469 /// Adds an entry to the operator definition map #Operators.
470 ///
471 /// \see
472 /// If multiple operators are to be defined, consider the use of #AddOperators, which is a
473 /// variant of this method that allows effective bulk loading.
474 ///
475 /// @param op The operator.
476 /// @param lhsType The type of the first argument that the operator is defined for.
477 /// @param rhsType The type of the right-hand side argument that the operator is defined
478 /// for.
479 /// For unary operators, value #"Types::Void;*" is to be
480 /// provided.
481 /// @param callback The callback function to execute.
482 /// @param dbgCallbackName The name of the C++ name of the callback function.
483 /// \note This parameter is available (and to be passed) only in debug
484 /// version of the library.
485 /// @param cti See #CTInvokable for the meaning of this flag.
486 /// @param resultType The result type of the callback function.
487 //==============================================================================================
488 void AddOperator ( const String& op, Type lhsType, Type rhsType, CallbackDecl callback,
489 #if ALIB_DEBUG
490 const char* dbgCallbackName,
491 #endif
492 Type resultType,
493 CTInvokable cti );
494 #else // clang would complain about the doxing of parameter dbgCallbackName
496 void AddOperator ( const String& op, Type lhsType, Type rhsType, CallbackDecl callback,
497 #if ALIB_DEBUG
498 const char* dbgCallbackName,
499 #endif
500 Type resultType,
501 CTInvokable cti );
502 #endif
503
504
505 /// Templated helper method. Deduces the array size of the given table and passes it
506 /// to #"AddOperators(OperatorTableEntry*" table, size_t length).
507 ///
508 /// @tparam TCapacity Implicitly deferred size of the array provided.
509 /// @param table The table containing operator compilation information.
510 template<size_t TCapacity>
511 void AddOperators ( OperatorTableEntry (&table) [TCapacity] )
512 { AddOperators( &table[0], TCapacity ); }
513
514 /// Loads all entries of the given table into hash map #Operators.
515 ///
516 /// Note, that usually, the given table is a constexpr array located in an anonymous namespace
517 /// of a compilation unit.<br>
518 /// It can be passed as a reference to templated helper method, which defers the length of the
519 /// table implicitly.
520 ///
521 /// @param table The table containing operator compilation information.
522 /// @param length The table containing operator compilation information.
524 void AddOperators ( OperatorTableEntry* table, size_t length );
525
526 /// Adds an alias operator to hash table #OperatorAliases.
527 ///
528 /// \see
529 /// If multiple alias operators are to be defined, consider the use of #AddOperatorAliases,
530 /// which is a variant of this method that allows effective bulk loading.
531 ///
532 /// @param alias The alias for operator \p{op}.
533 /// @param lhsType The left-hand side argument type that the operator is defined for.
534 /// @param rhsType The right-hand side argument type that the operator is defined for.
535 /// @param op The operator aliased by \p{alias}.
536 void AddOperatorAlias ( const String& alias, Type lhsType, Type rhsType, const String& op );
537
538 /// Templated helper method. Deduces the array size of the given table and passes it
539 /// to #"AddOperatorAliases(OperatorAliasTableEntry*" table, size_t length).
540 ///
541 /// @tparam TCapacity Implicitly deferred size of the array provided.
542 /// @param table The table containing operator compilation information.
543 template<size_t TCapacity>
544 void AddOperatorAliases( OperatorAliasTableEntry (&table) [TCapacity] )
545 { AddOperatorAliases( &table[0], TCapacity ); }
546
547 /// Loads all entries of the given table into hash map #OperatorAliases.
548 ///
549 /// Note, that usually, the given table is a constexpr array located in an anonymous namespace
550 /// of a compilation unit.<br>
551 /// It can be passed as a reference to templated helper method, which defers the length of the
552 /// table implicitly.
553 ///
554 /// @param table The table containing operator compilation information.
555 /// @param length The table containing operator compilation information.
556 void AddOperatorAliases( OperatorAliasTableEntry* table, size_t length );
557
558
559 //################################################################################################
560 // Binary operator optimizations
561 //################################################################################################
562 protected:
563
564 /// Key type for operator hash maps #Operators and OperatorAliases.
566 {
567 const String op; ///< The operator to optimize.
568 lang::Side constSide; ///< Denotes a left- or right-hand side optimization.
569 const Box constVal; ///< The type and value of the constant argument.
570 const std::type_info& other; ///< The type of the non-constant argument.
571
572 /// Hash functor for operator hash map.
573 struct Hash
574 {
575 /// Calculates a hash code for objects of type \b OperatorKey.
576 /// @param src The node to hash.
577 /// @return The hash code.
578 std::size_t operator()(const BinOpOptKey& src) const {
579 return ( std::hash<String>()(src.op)
580 + 6949ul * std::hash<Box>()(src.constVal)
581 + 14033ul * src.other.hash_code()
582 ) ^ ( src.constSide == lang::Side::Left ? size_t( 0)
583 : size_t(-1) );
584 }
585 };
586
587 /// Equality functor for operator hash map.
588 struct EqualTo
589 {
590 /// Compares two objects of type \b OperatorKey.
591 /// @param lhs The left-hand side object.
592 /// @param rhs The left-hand side object.
593 /// @return The result of the comparison.
594 bool operator()(const BinOpOptKey& lhs, const BinOpOptKey& rhs ) const {
595 return lhs.op == rhs.op
596 && lhs.constSide== rhs.constSide
597 && lhs.constVal == rhs.constVal
598 && lhs.other == rhs.other;
599 }
600 };
601 };
602
603 public:
604 /// Hash map storing optimization information for binary operators where either argument is
605 /// constant.<br>
606 /// This map may be filled with #AddBinaryOpOptimizations, which is usually done in the.
607 /// constructor of derived classes.
608 ///
609 /// The stored element of type \b Box may contain either, a constant result value that replaces
610 /// the binary operator (as in <c> x || true</c>) or be a \e nulled box, which indicates that
611 /// the result equals the non-constant argument (as in <c>x && true</c>).
613 BinOpOptKey, Box,
614 BinOpOptKey::Hash,
616
617 /// Entry of arrays used with methods #AddBinaryOpOptimizations to perform bulk-loading of
618 /// optimization data to hash map #BinaryOperatorOptimizations.<br>
619 /// The tuple element's meanings are:
620 /// - The operator to optimize.
621 /// - Denotes if an optimization applies if the left-hand side or right-hand side argument
622 /// is constant.
623 /// - The type and value of the constant argument.
624 /// - The type of the non-constant argument.
625 /// - Either, a constant result value that replaces the binary operator
626 /// (as in <c> x || true</c>) or a \e nulled box, which indicates that the result equals the
627 /// non-constant argument (as in <c>x && true</c>).
628 using BinaryOpOptimizationsTableEntry= const std::tuple<String, lang::Side, Type, const Box&, const Box&>;
629
630
631 /// Templated helper method. Deduces the array size of the given table and passes it
632 /// to #"AddBinaryOpOptimizations(BinaryOpOptimizationsTableEntry*", size_t).
633 ///
634 /// @tparam TCapacity Implicitly deferred size of the array provided.
635 /// @param table The table containing operator compilation information.
636 template<size_t TCapacity>
638 { AddBinaryOpOptimizations( &table[0], TCapacity ); }
639
640 /// Loads all entries of the given table into hash map #BinaryOperatorOptimizations.
641 ///
642 /// Note, that usually, the given table is a constexpr array located in an anonymous namespace
643 /// of a compilation unit.<br>
644 /// It can be passed as a reference to templated helper method, which defers the length of the
645 /// table implicitly.
646 ///
647 /// @param table The table containing operator compilation information.
648 /// @param length The table containing operator compilation information.
650 void AddBinaryOpOptimizations( BinaryOpOptimizationsTableEntry* table, size_t length );
651
652 /// Searches in #Operators for an entry matching the combination of
653 /// #"CIUnaryOp::Operator"
654 /// and the argument type of operand found with iterator
655 /// #"CompilationInfo::ArgsBegin".
656 /// (The second argument type of the key of the hash map #Operators is set to
657 /// #"Types::Void;*").
658 /// If found, the corresponding callback function and result type are added the \p{CIUnaryOp}.
659 ///
660 /// Before the search, it is checked whether the given operator is an alias for another
661 /// operator. Operator aliases might be defined by filling map #OperatorAliases in the
662 /// constructor of the derived types.
663 /// If so, the corrected operator is returned with in/out parameter
664 /// #"CIUnaryOp::Operator".
665 ///
666 /// @param ciUnaryOp The compilation result.
667 /// @return \c true if an entry was found in #Operators and a corresponding command was added to
668 /// \p{ciUnaryOp}. \c false otherwise.
670 virtual bool TryCompilation( CIUnaryOp& ciUnaryOp ) override;
671
672
673 /// Searches in #Operators for an entry matching the combination of #"CIBinaryOp::Operator"
674 /// and the argument types of operands found with argument iterators
675 /// #"CompilationInfo::ArgsBegin"
676 /// and
677 /// #"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 /// #"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 #"Types::Integer;*" which is generated by
718 /// taking the #"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 #"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 #"CALCULUS_CALLBACK"
732 /// use macro #"CALCULUS_DEFAULT_AUTOCAST" instead.
733 const char* DbgCallbackName;
734 #endif
735
736 /// The result type given a #"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 #"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 /// #"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 /// #"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 /// #"AutoCastEntry::Type"
774 /// and
775 /// #"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]
#define ALIB_DLL
Definition alib.inl:573
#define ALIB_DEBUG
Definition alib.inl:39
#define ALIB_EXPORT
Definition alib.inl:562
#define ALIB_DBG(...)
Definition alib.inl:931
std::size_t Hashcode() const
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.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2181
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:408
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1135
containers::HashMap< TAllocator, TKey, TMapped, THash, TEqual, THashCaching, TRecycling > HashMap
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2172
strings::util::Token Token
Type alias in namespace alib.
Definition token.inl:398
expressions::plugins::Calculus Calculus
Type alias in namespace alib.
Definition calculus.inl:799
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:589
bool operator()(const BinOpOptKey &lhs, const BinOpOptKey &rhs) const
Definition calculus.inl:594
std::size_t operator()(const BinOpOptKey &src) const
Definition calculus.inl:578
Key type for operator hash maps Operators and OperatorAliases.
Definition calculus.inl:566
lang::Side constSide
Denotes a left- or right-hand side optimization.
Definition calculus.inl:568
const String op
The operator to optimize.
Definition calculus.inl:567
const Box constVal
The type and value of the constant argument.
Definition calculus.inl:569
const std::type_info & other
The type of the non-constant argument.
Definition calculus.inl:570
Token Descriptor
The name, minimum length and letter case sensitivity of the function to recognize.
Definition calculus.inl:271
size_t SignatureLength
See Signature for more information.
Definition calculus.inl:303
Token Descriptor
The name, minimum length and letter case sensitivity of the function to recognize.
Definition calculus.inl:285
Equality functor for operator hash map.
Definition calculus.inl:381
bool operator()(const OperatorKey &left, const OperatorKey &right) const
Definition calculus.inl:386
std::size_t operator()(const OperatorKey &src) const
Definition calculus.inl:371
Key type for operator hash maps Operators and OperatorAliases.
Definition calculus.inl:359
const std::type_info & lhs
Left-hand side type.
Definition calculus.inl:361
const String op
A string defining the operator.
Definition calculus.inl:360
void AddOperatorAlias(const String &alias, Type lhsType, Type rhsType, const String &op)
Definition calculus.cpp:107
static constexpr CTInvokable ETI
Definition calculus.inl:240
HashMap< MonoAllocator, OperatorKey, std::tuple< CallbackDecl, Box, CTInvokable ALIB_DBG(, const char *) >, OperatorKey::Hash, OperatorKey::EqualTo > Operators
Definition calculus.inl:419
const std::tuple< String, Type, Type, CallbackDecl, Type, CTInvokable > OperatorTableEntry
Definition calculus.inl:450
virtual bool TryCompilation(CIFunction &ciFunction) override
Definition calculus.cpp:336
Calculus(const NString &name, Compiler &compiler, CompilePriorities pPriority)
Definition calculus.inl:250
void AddOperatorAliases(OperatorAliasTableEntry(&table)[TCapacity])
Definition calculus.inl:544
const std::tuple< String, lang::Side, Type, const Box &, const Box & > BinaryOpOptimizationsTableEntry
Definition calculus.inl:628
std::vector< ConstantIdentifierEntry > ConstantIdentifiers
List of identifiers that return constant values to be compiled by this plug-in.
Definition calculus.inl:278
virtual ~Calculus() override
Virtual destructor.
Definition calculus.inl:259
static constexpr CTInvokable CTI
Definition calculus.inl:235
void AddBinaryOpOptimizations(BinaryOpOptimizationsTableEntry(&table)[TCapacity])
Definition calculus.inl:637
HashMap< MonoAllocator, BinOpOptKey, Box, BinOpOptKey::Hash, BinOpOptKey::EqualTo > BinaryOperatorOptimizations
Definition calculus.inl:615
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:511
std::vector< FunctionEntry > Functions
List of functions to be compiled by this plug-in.
Definition calculus.inl:338
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:432
const std::tuple< String, Type, Type, String > OperatorAliasTableEntry
Definition calculus.inl:463