ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
calculus.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10# ifndef HPP_ALIB_EXPRESSIONS_PLUGINS_CALCULUS
12# endif
13
14# if !defined(HPP_ALIB_COMPATIBILITY_STD_BOXING_FUNCTIONAL)
16# endif
17#endif // !defined(ALIB_DOX)
18
20
21namespace alib { namespace expressions { namespace plugins {
22
23// #################################################################################################
24// Operator setup helpers (unary and binary)
25// #################################################################################################
27 Type lhsType,
28 Type rhsType,
29 CallbackDecl callback,
30 #if ALIB_DEBUG
31 const char* dbgCallbackName,
32 #endif
33 Type resultType,
34 CTInvokable cti )
35{
36 #if ALIB_DEBUG
37 auto result=
38 Operators.EmplaceIfNotExistent(
39 OperatorKey { op, lhsType.TypeID(), rhsType.TypeID() },
40 std::make_tuple( callback, resultType, cti ALIB_DBG(, dbgCallbackName) ) );
41
42 ALIB_ASSERT_ERROR( result.second == true, "EXPR", // assert this was an insert!
43 "Binary operator {!Q'} already defined for types {!Q<>} (aka {})\n"
44 " and {!Q<>} (aka {}).",
45 op, Cmplr.TypeName( lhsType ), lhsType.TypeID(),
46 Cmplr.TypeName( rhsType ), rhsType.TypeID() )
47 #else
48 Operators.EmplaceUnique(
49 OperatorKey { op, lhsType.TypeID(), rhsType.TypeID() },
50 std::make_tuple( callback, resultType, cti ALIB_DBG(, dbgCallbackName) ) );
51 #endif
52}
53
55void Calculus::AddOperators( OperatorTableEntry* table, size_t length )
56{
58 ALIB_DBG( auto actBucketCount= Operators.BucketCount(); )
59
60 #define OP std::get<0>( *(table + i) )
61 #define LHS_TYPE std::get<1>( *(table + i) ).TypeID()
62 #define RHS_TYPE std::get<2>( *(table + i) ).TypeID()
63 #define CBFUNC std::get<3>( *(table + i) )
64 #define RESULTTYPE std::get<ALIB_REL_DBG(4,5)>( *(table + i) )
65 #define CTINVOKE std::get<ALIB_REL_DBG(5,6)>( *(table + i) )
66
67 for( size_t i= 0 ; i < length ; ++i )
68 {
69 #if ALIB_DEBUG
70 auto result=
71 Operators.EmplaceIfNotExistent(
72 OperatorKey { OP, LHS_TYPE, RHS_TYPE },
73 std::make_tuple( CBFUNC, RESULTTYPE, CTINVOKE
74 ALIB_DBG(, std::get<4>( *(table + i) )) ) );
75
76 ALIB_ASSERT_ERROR( result.second == true, "EXPR",// assert this was an insert!
77 "Binary operator {!Q'} already defined for types {!Q<>} (aka {})\n"
78 " and {!Q<>} (aka {}).",
79 OP, Cmplr.TypeName(std::get<1>( *(table+i))), LHS_TYPE,
80 Cmplr.TypeName(std::get<2>( *(table+i))), RHS_TYPE )
81 #else
82 Operators.EmplaceUnique(
83 OperatorKey { OP, LHS_TYPE, RHS_TYPE },
84 std::make_tuple( CBFUNC, RESULTTYPE, CTINVOKE
85 ALIB_DBG(, std::get<4>( *(table + i) )) ) );
86 #endif
87 }
88
89 ALIB_ASSERT_ERROR( actBucketCount == Operators.BucketCount(), "EXPR",
90 "This is rather an internal error of HashTable: The number of buckets "
91 "of hash map 'Operators' increased, although it was reserved above." )
92
93 #undef OP
94 #undef LHS_TYPE
95 #undef RHS_TYPE
96 #undef CBFUNC
97 #undef RESULTTYPE
98 #undef CTINVOKE
99}
101
102void Calculus::AddOperatorAlias( const String& alias, Type lhs, Type rhs, const String& op )
103{
104 #if ALIB_DEBUG
105 auto result=
106 OperatorAliases.EmplaceIfNotExistent( OperatorKey { alias, lhs.TypeID(), rhs.TypeID() },
107 op );
108
109 ALIB_ASSERT_ERROR( result.second == true, "EXPR",// assert this was an insert!
110 "Binary operator alias {!Q'} already defined for types {!Q<>} (aka {})\n"
111 "and {!Q<>} (aka {}).",
112 alias, Cmplr.TypeName( lhs ), lhs.TypeID(),
113 Cmplr.TypeName( rhs ), rhs.TypeID() )
114 #else
115 OperatorAliases.EmplaceUnique( OperatorKey { alias, lhs.TypeID(), rhs.TypeID() },
116 op );
117 #endif
118}
119
122{
124
125 #define ALIAS std::get<0>( *(table + i) )
126 #define LHS_TYPE std::get<1>( *(table + i) ).TypeID()
127 #define RHS_TYPE std::get<2>( *(table + i) ).TypeID()
128 #define OP std::get<3>( *(table + i) )
129
130 for( size_t i= 0 ; i < length ; ++i )
131 {
132 #if ALIB_DEBUG
133 auto result=
134 OperatorAliases.EmplaceIfNotExistent( OperatorKey { ALIAS, LHS_TYPE, RHS_TYPE }, OP );
135
136 ALIB_ASSERT_ERROR( result.second == true, "EXPR",// assert this was an insert!
137 "Binary operator alias {!Q'} already defined for types {!Q<>} (aka {})\n"
138 "and {!Q<>} (aka {}).",
139 ALIAS, Cmplr.TypeName( std::get<1>( *(table + i) ) ), LHS_TYPE,
140 Cmplr.TypeName( std::get<2>( *(table + i) ) ), RHS_TYPE )
141 #else
142 OperatorAliases.EmplaceUnique( OperatorKey { ALIAS, LHS_TYPE, RHS_TYPE },
143 OP );
144 #endif
145 }
146
147 #undef ALIAS
148 #undef LHS_TYPE
149 #undef RHS_TYPE
150 #undef OP
151}
153
154// #################################################################################################
155// Unary operators
156// #################################################################################################
158{
159 Box& arg= ciUnaryOp.CompileTimeScope.Stack[0];
160 OperatorKey key = { ciUnaryOp.Operator, arg.TypeID(), typeid(void) };
161 auto hashCode= OperatorKey::Hash()( key );
162
163 // search alias first
164 {
165 auto aliasIt= OperatorAliases.Find( key, hashCode );
166 if( aliasIt != OperatorAliases.end() )
167 ciUnaryOp.Operator= aliasIt.Mapped();
168 }
169
170
171 // search callback
172 auto opIt= Operators.Find( key, hashCode );
173 if( opIt == Operators.end() )
174 return false;
175
176 auto& op= opIt.Mapped();
177
178 // for constants, the callback might b invoked right away (optimizing cal out)
179 if( ciUnaryOp.ArgIsConst && std::get<2>(op) )
180 {
181 // calculate constant value
182 ciUnaryOp.TypeOrValue= std::get<0>(op)( ciUnaryOp.CompileTimeScope,
183 ciUnaryOp.ArgsBegin,
184 ciUnaryOp.ArgsEnd );
185ALIB_DBG(ciUnaryOp.DbgCallbackName= std::get<3>(op);)
186 ALIB_ASSERT_ERROR(ciUnaryOp.TypeOrValue.IsSameType(std::get<1>(op)), "EXPR",
187 "Type mismatch in definition of unary operator {!Q} ({}) in plugin {!Q}.\n"
188 " Type specified: {!Q<>} (aka {})\n"
189 " Type returned by callback: {!Q<>} (aka {})",
190 ciUnaryOp.Operator, ciUnaryOp.DbgCallbackName, CompilerPlugin::Name,
191 CompilerPlugin::Cmplr.TypeName(std::get<1>(op)),
192 std::get<1>(op).TypeID(),
194 ciUnaryOp.TypeOrValue.TypeID() )
195 return true;
196 }
197 ciUnaryOp.Callback = std::get<0>(op);
198 ciUnaryOp.TypeOrValue = std::get<1>(op);
199ALIB_DBG(ciUnaryOp.DbgCallbackName= std::get<3>(op);)
200
201 return true;
202}
203
204// #################################################################################################
205// Binary operators
206// #################################################################################################
209{
211
212 #define OP std::get<0>( *(table + i) )
213 #define SIDE std::get<1>( *(table + i) )
214 #define CONSTVAL std::get<2>( *(table + i) )
215 #define CONSTTYPE std::get<2>( *(table + i) ).TypeID()
216 #define OTHERBOX std::get<3>( *(table + i) )
217 #define OTHERTYPE std::get<3>( *(table + i) ).TypeID()
218 #define RESULT std::get<4>( *(table + i) )
219
220 for( size_t i= 0 ; i < length ; ++i )
221 {
222 #if ALIB_DEBUG
223 auto result=
224 BinaryOperatorOptimizations.EmplaceIfNotExistent( BinOpOptKey { OP, SIDE, CONSTVAL, OTHERTYPE }, RESULT );
225
226 ALIB_ASSERT_ERROR( result.second == true, "EXPR", // assert this was an insert!
227 "Optimization already defined for operator {!Q} with {!Lower}-hand "
228 "constant value {!Q} of type {!Q<>} (aka {}) and with "
229 "{!L}-hand type {!Q<>} (aka {}).",
230 OP, SIDE, CONSTVAL, Cmplr.TypeName(CONSTVAL), CONSTTYPE,
232 : lang::Side::Left, Cmplr.TypeName(OTHERBOX), OTHERTYPE )
233 #else
234 BinaryOperatorOptimizations.EmplaceUnique( BinOpOptKey { OP, SIDE, CONSTVAL, OTHERTYPE },
235 RESULT );
236 #endif
237 }
238
239 #undef OP
240 #undef TYPE
241 #undef CONSTVAL
242 #undef RESULT
243}
245
246
248{
249 Box& lhs= * ciBinaryOp.ArgsBegin;
250 Box& rhs= *(ciBinaryOp.ArgsBegin + 1);
251
252 OperatorKey key = { ciBinaryOp.Operator, lhs.TypeID(), rhs.TypeID() };
253 auto hashCode= OperatorKey::Hash()( key );
254
255 // search alias first
256 if( ciBinaryOp.Operator == A_CHAR("=")
257 && HasBits( Cmplr.CfgCompilation, Compilation::AliasEqualsOperatorWithAssignOperator ) )
258 {
259 ciBinaryOp.Operator= A_CHAR("==");
260 }
261 else
262 {
263 auto aliasIt = OperatorAliases.Find( key, hashCode );
264 if( aliasIt != OperatorAliases.end() )
265 ciBinaryOp.Operator= aliasIt.Mapped();
266 }
267
268 #define CBFUNC std::get<0>(op)
269 #define RESULTTYPE std::get<1>(op)
270 #define CT_INVOKABLE std::get<2>(op)
271 #if ALIB_DEBUG
272 # define DBG_CB_NAME std::get<3>(op)
273 #endif
274
275// search callback
276 auto opIt = Operators.Find( key, hashCode );
277 if( opIt == Operators.end() )
278 return false;
279
280 auto& op= opIt.Mapped();
281
282 // if both are constant, the callback might be invoked right away (optimizing the call out)
283 if( ciBinaryOp.LhsIsConst && ciBinaryOp.RhsIsConst )
284 {
285 if( CT_INVOKABLE )
286 {
287 // calculate constant value
288 ciBinaryOp.TypeOrValue= CBFUNC ( ciBinaryOp.CompileTimeScope,
289 ciBinaryOp.ArgsBegin,
290 ciBinaryOp.ArgsEnd );
291ALIB_DBG( ciBinaryOp.DbgCallbackName= DBG_CB_NAME; )
292 ALIB_ASSERT_ERROR(ciBinaryOp.TypeOrValue.IsSameType(RESULTTYPE), "EXPR",
293 "Type mismatch in definition of binary operator {!Q} ({}) of plugin {!Q}.\n"
294 " Type specified: {!Q<>} (aka {})\n"
295 " Type returned by callback: {!Q<>} (aka {})",
296 ciBinaryOp.Operator, ciBinaryOp.DbgCallbackName, CompilerPlugin::Name,
297 CompilerPlugin::Cmplr.TypeName(RESULTTYPE ),
298 RESULTTYPE .TypeID(),
300 ciBinaryOp.TypeOrValue.TypeID() )
301 return true;
302 }
303 }
304
305
306 // if one is constant, we may find an entry in BinaryOpConsL/RHSOptimizations
307 else if( ciBinaryOp.LhsIsConst || ciBinaryOp.RhsIsConst )
308 {
309 auto& nonConstType= (ciBinaryOp.LhsIsConst ? *(ciBinaryOp.ArgsBegin + 1 )
310 : *(ciBinaryOp.ArgsBegin ) ).TypeID();
311 auto& constValue= ciBinaryOp.LhsIsConst ? *(ciBinaryOp.ArgsBegin )
312 : *(ciBinaryOp.ArgsBegin + 1 );
313
314 auto entryIt= BinaryOperatorOptimizations.Find( { ciBinaryOp.Operator,
316 constValue,
317 nonConstType
318 } );
319 if( entryIt != BinaryOperatorOptimizations.end() )
320 {
321 // found! If it is an unset box, this tells us, that the result is the other side
322 // (identity operation). Otherwise it is a constant.
323 if( entryIt.Mapped().IsType<void>() )
324 ciBinaryOp.NonConstArgIsResult= true;
325 else
326 ciBinaryOp.TypeOrValue = entryIt.Mapped();
327 return true;
328 }
329 }
330
331
332 ciBinaryOp.Callback = CBFUNC;
333 ciBinaryOp.TypeOrValue = RESULTTYPE;
335 ciBinaryOp.DbgCallbackName= DBG_CB_NAME; )
336 return true;
337
338
339 #undef CBFUNC
340 #undef RESULTTYPE
341 #undef CT_INVOKABLE
342 #if ALIB_DEBUG
343 #undef DBG_CB_NAME
344 #endif
345}
346
347
348// #################################################################################################
349// Functions
350// #################################################################################################
352{
353 String& name= ciFunction.Name;
354
355 // search in constant identifiers
356 if( ciFunction.QtyArgs() == 0 )
357 {
358 for( auto& entry : ConstantIdentifiers )
359 {
360 if ( entry.Descriptor.Match( name ) )
361 {
362 // check for wrong parentheses
363 if( ciFunction.NoParentheses
364 && !HasBits(Cmplr.CfgCompilation, Compilation::AllowOmittingParenthesesOfParameterlessFunctions ) )
366 entry.Descriptor );
367
368 if( !ciFunction.NoParentheses
369 && !HasBits(Cmplr.CfgCompilation, Compilation::AllowEmptyParenthesesForIdentifierFunctions ) )
371 entry.Descriptor );
372
373
374 // accept
375 ciFunction.Name.Reset( entry.Descriptor );
376 ciFunction.TypeOrValue= entry.Result;
377 return true;
378 }
379 }
380 }
381
382 // search in functions
383 for( auto& entry : Functions )
384 {
385 if( entry.Descriptor.Match( name ) )
386 {
387 // collect information about given and requested parameters
389 size_t qtyGiven = ciFunction.QtyArgs();
390 size_t qtyRequired = entry.SignatureLength;
391 bool isVariadic = false;
392 if( entry.SignatureLength > 0 && ( entry.Signature[entry.SignatureLength - 1] == nullptr
393 || entry.Signature[entry.SignatureLength - 1]->IsType<void>() ) )
394 {
395 isVariadic= true;
396 --qtyRequired;
397 }
398
399 size_t qtyShared = (std::min)( qtyGiven, qtyRequired );
400 bool sharedAreSameType = true;
401 for( size_t i= 0; i != qtyShared ; ++i )
402 sharedAreSameType&= ciFunction.Arg(i).IsSameType( *entry.Signature[i] );
404
405 // check if given parameter don't match
406 if( !sharedAreSameType
407 || ( isVariadic ? qtyGiven < qtyRequired
408 : qtyGiven != qtyRequired ) )
409 {
410 String256 buffer( entry.Descriptor );
411 if( qtyRequired )
412 Cmplr.WriteFunctionSignature( entry.Signature,
413 entry.SignatureLength,
414 buffer );
415 ciFunction.AddFunctionsWithNonMatchingArguments( buffer );
416
417 // search next
418 continue;
419 }
420
421 // check for wrong parentheses
422 if( ciFunction.NoParentheses
423 && entry.Signature != nullptr
424 && !HasBits(Cmplr.CfgCompilation, Compilation::AllowOmittingParenthesesOfParameterlessFunctions ) )
426 entry.Descriptor );
427
428 if( !ciFunction.NoParentheses
429 && entry.Signature == nullptr
430 && !HasBits(Cmplr.CfgCompilation, Compilation::AllowEmptyParenthesesForIdentifierFunctions ) )
432 entry.Descriptor );
433
434
435
436 // accept
437 ciFunction.Name.Reset( entry.Descriptor );
438
439 if( !entry.Callback )
440 {
441 ciFunction.TypeOrValue = *entry.ResultType;
442 ALIB_DBG( ciFunction.DbgCallbackName = entry.DbgCallbackName; )
443 return true;
444 }
445
446 // for constants, the callback might b invoked right away (optimizing cal out)
447 if( ciFunction.AllArgsAreConst && entry.IsCTInvokable )
448 {
449 // calculate constant value
450 ciFunction.TypeOrValue = entry.Callback( ciFunction.CompileTimeScope,
451 ciFunction.ArgsBegin,
452 ciFunction.ArgsEnd );
453 ALIB_ASSERT_ERROR(ciFunction.TypeOrValue.IsSameType(*entry.ResultType), "EXPR",
454 "Type mismatch in definition of function {!Q} ({}) in plugin {!Q}.\n"
455 " Type specified: {!Q<>} (aka {})\n"
456 " Type returned by callback: {!Q<>} (aka {})",
457 entry.Descriptor, entry.DbgCallbackName, CompilerPlugin::Name,
458 CompilerPlugin::Cmplr.TypeName(*entry.ResultType),
459 entry.ResultType->TypeID(),
461 ciFunction.TypeOrValue.TypeID() )
462 ALIB_DBG( ciFunction.DbgCallbackName = entry.DbgCallbackName; )
463 return true;
464 }
465
466 ciFunction.Callback = entry.Callback;
467 ciFunction.TypeOrValue = *entry.ResultType;
468 ALIB_DBG( ciFunction.DbgCallbackName = entry.DbgCallbackName; )
469 return true;
470 }
471 }
472
473 return false;
474}
475
476// #################################################################################################
477// Auto-Casts
478// #################################################################################################
479//! @cond NO_DOX
480namespace {
481 Calculus::AutoCastEntry* findAutoCastEntry( std::vector<Calculus::AutoCastEntry>& table,
482 Calculus::CIAutoCast& ciAutoCast,
483 int argNo )
484 {
485 Box& valueToCast= *(ciAutoCast.ArgsBegin + argNo);
486
487 // main loop over all table entries
488 for( auto& entry : table )
489 {
490 // first check for source type
491 if( !entry.Type.IsSameType( valueToCast ) )
492 continue;
493
494 // operator included in list of accepted (if list given)?
495 bool operatorIsIn= true;
496 if( entry.OperatorsAccepted != nullptr
497 && entry.OperatorsAccepted->size() > 0 )
498 {
499 operatorIsIn= false;
500 for( auto& op : *entry.OperatorsAccepted )
501 if( op.Equals<false>( ciAutoCast.Operator ) )
502 {
503 operatorIsIn= true;
504 break;
505 }
506 }
507
508 // operator included in decline list?
509 if( operatorIsIn
510 && entry.OperatorsDeclined != nullptr
511 && entry.OperatorsDeclined->size() > 0 )
512 {
513 for( auto& op : *entry.OperatorsDeclined )
514 if( op.Equals<false>( ciAutoCast.Operator ) )
515 {
516 operatorIsIn= false;
517 break;
518 }
519 }
520
521 // found?
522 if( operatorIsIn )
523 return &entry;
524 }
525
526 return nullptr;
527 }
528
529 Box any2Int ( expressions::Scope&, ArgIterator argsBegin, ArgIterator )
530 {
531 return argsBegin->Data().GetInteger(0);
532 }
533
534} //anonymous namespace
535//! @endcond
536
537
539{
540 bool result= false;
541
542 //-------- cast first arg -------
543 AutoCastEntry* entry= findAutoCastEntry( AutoCasts, ciAutoCast, 0 );
544 if( entry != nullptr )
545 {
546 result= true;
548
549 CallbackDecl callback;
550 if( entry->Callback == nullptr )
551 {
552 callback = any2Int;
553ALIB_DBG( ciAutoCast.DbgCallbackName= "any2Int"; )
554 ciAutoCast.TypeOrValue = Types::Integer;
555 }
556 else
557 {
558 callback = entry->Callback;
559ALIB_DBG( ciAutoCast.DbgCallbackName= entry->DbgCallbackName; )
560 ciAutoCast.TypeOrValue = entry->ResultType;
561 }
562
563 if( ciAutoCast.IsConst )
564 ciAutoCast.TypeOrValue= callback( ciAutoCast.CompileTimeScope,
565 ciAutoCast.ArgsBegin,
566 ciAutoCast.ArgsEnd );
567 else
568 ciAutoCast.Callback = callback;
569 }
570
571 // no RHS given?
572 if( ciAutoCast.ArgsBegin + 1 >= ciAutoCast.ArgsEnd )
573 return result;
574
575 //-------- cast second arg (rhs) -------
576 entry= findAutoCastEntry( AutoCasts, ciAutoCast, 1 );
577 if( entry != nullptr )
578 {
579 //
580 result= true;
582
583 CallbackDecl callback;
584 if( entry->Callback == nullptr )
585 {
586 callback = any2Int;
587ALIB_DBG( ciAutoCast.DbgCallbackNameRhs= "any2Int"; )
588 ciAutoCast.TypeOrValueRhs = Types::Integer;
589 }
590 else
591 {
592 callback = entry->Callback;
593ALIB_DBG( ciAutoCast.DbgCallbackNameRhs= entry->DbgCallbackName; )
594 ciAutoCast.TypeOrValueRhs = entry->ResultType;
595 }
596
597 if( ciAutoCast.RhsIsConst )
598 ciAutoCast.TypeOrValueRhs= callback( ciAutoCast.CompileTimeScope,
599 ciAutoCast.ArgsBegin + 1,
600 ciAutoCast.ArgsEnd );
601 else
602 ciAutoCast.CallbackRhs = callback;
603 }
604
605
606 return result;
607}
608
609}}} // namespace [alib::expressions::plugin]
610
bool IsSameType(const Box &other) const
Definition box.inl:761
const std::type_info & TypeID() const
Definition box.inl:902
const Placeholder & Data() const
Definition box.inl:843
ALIB_API NString TypeName(Type box)
Definition compiler.cpp:432
#define ALIB_CALLER_NULLED
Definition alib.hpp:846
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_WARNINGS_IGNORE_UNUSED_MACRO
Definition alib.hpp:687
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_DBG(...)
Definition alib.hpp:457
#define ALIB_DEBUG
Definition prepro.dox:21
std::vector< Box >::iterator ArgIterator
@ Equals
Verbal alias "Equals" to operator '=='.
Box(*)(Scope &scope, ArgIterator argsBegin, ArgIterator argsEnd) CallbackDecl
@ Relative
Referring to a relative value.
@ Right
Denotes the right side of something.
@ Left
Denotes the left side of something.
Definition alib.cpp:57
lang::Exception Exception
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
String & Operator
Input/Output: The binary operator symbol.
void AddFunctionsWithNonMatchingArguments(const String &signature)
String & Operator
Input/Output: The unary operator.
std::vector< alib::Box > Stack
Definition scope.hpp:108
static ALIB_API Box Integer
void AddOperatorAliases(OperatorAliasTableEntry(&table)[TCapacity])
Definition calculus.hpp:612
virtual ALIB_API bool TryCompilation(CIFunction &ciFunction) override
Definition calculus.cpp:351
HashMap< OperatorKey, String, OperatorKey::Hash, OperatorKey::EqualTo > OperatorAliases
Definition calculus.hpp:486
HashMap< BinOpOptKey, Box, BinOpOptKey::Hash, BinOpOptKey::EqualTo > BinaryOperatorOptimizations
Definition calculus.hpp:690
void AddOperators(OperatorTableEntry(&table)[TCapacity])
Definition calculus.hpp:571
void AddBinaryOpOptimizations(BinaryOpOptimizationsTableEntry(&table)[TCapacity])
Definition calculus.hpp:716
const std::tuple< String, Type, Type, CallbackDecl, Type, CTInvokable > OperatorTableEntry
Definition calculus.hpp:506
HashMap< OperatorKey, std::tuple< CallbackDecl, Box, CTInvokable ALIB_DBG(, const char *) >, OperatorKey::Hash, OperatorKey::EqualTo > Operators
Definition calculus.hpp:472
void AddOperator(const String &op, Type lhsType, Type rhsType, CallbackDecl callback, const char *dbgCallbackName, Type resultType, CTInvokable cti)
Definition calculus.cpp:26
const std::tuple< String, lang::Side, Type, const Box &, const Box & > BinaryOpOptimizationsTableEntry
Definition calculus.hpp:705
const std::tuple< String, Type, Type, String > OperatorAliasTableEntry
Definition calculus.hpp:521
void AddOperatorAlias(const String &alias, Type lhsType, Type rhsType, const String &op)
Definition calculus.cpp:102
ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE constexpr integer GetInteger(int idx) const