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