8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
19 module ALib.Expressions.Impl;
20 import ALib.Characters.Functions;
38# define DBG_SET_CALLBACK_INFO \
39 prg.act().DbgInfo.Callback= cInfo.DbgCallbackName; \
40 prg.act().DbgInfo.Plugin = ppp.plugin;
42# define DBG_SET_CALLBACK_INFO
72 : assembly ( pAssembly )
73 , resultStack( pResultStack) {}
82 VM::Command& at( VM::PC pc ) {
return *assembly[size_t(pc)]; }
86 VM::Command& act() {
return *assembly.back(); }
90 VM::Command& prev() {
return **( assembly.end() - 2 ); }
94 VM::PC actPC() {
return static_cast<VM::PC
>( assembly.size() - 1); }
97 void eraseLast() { assembly.pop_back(); }
101 void erase( VM::PC pc ) { assembly.erase( assembly.begin() + pc ); }
106 void erase( VM::PC begin, VM::PC end )
108 assembly.erase( assembly.begin() + begin,
109 assembly.begin() + end );
118 template<
typename... TArgs>
119 VM::Command& insertAt( VM::PC pc, TArgs && ... args ) {
120 auto* cmd= assembly.get_allocator().AI().New<VM::Command>(std::forward<TArgs>( args )... );
121 assembly.emplace( assembly.begin() + pc, cmd );
129 template<
typename... TArgs>
130 VM::Command& add( TArgs && ... args )
132 assembly.emplace_back( assembly.get_allocator().AI().New<VM::Command>( std::forward<TArgs>( args )... ) );
133 return *assembly.back();
138 void pushResultPC() { resultStack.push_back( actPC() ); }
141 void popResultPC() { resultStack.pop_back(); }
144 VM::PC & resultPC() {
return resultStack.back(); }
147 VM::PC & lhsResultPC() {
return resultStack[resultStack.size() - 2]; }
151 VM::PC lhsResultStartPC() {
152 auto qtyResults = resultStack.size();
153 return qtyResults == 2 ? 0
154 : resultStack[qtyResults - 3] + 1;
164#define ASSERT_ASSEMBLE \
165 ALIB_ASSERT_ERROR( prg.resultStack.empty() \
166 || prg.resultPC() == prg.actPC() \
167 || prg.act().IsJump() , \
168 "EXPR", "Internal error: Last in result stack is not last command." )
173 "EXPR",
"Internal error. This should never happen." )
177 stack->reserve(
size_t( qty ));
179 bool allAreConst=
true;
180 for(
integer i= qty; i > 0 ; --i ) {
182 bool isConstant= cmd.IsConstant();
183 stack->emplace_back( cmd.ResultType );
184 allAreConst&= isConstant;
200 false, idxInOriginal, idxInNormalized ) );
213 if(
compiler.CfgNestedExpressionFunction.GetDefinitionName().IsNotEmpty()
214 &&
compiler.CfgNestedExpressionFunction.Match(functionName ) )
220 || !prg.at( *(prg.resultStack.end() - ( qtyArgs == 3 ? 2 : qtyArgs) ) )
221 .ResultType.IsType<
String>() )
224 compiler.CfgNestedExpressionFunction );
233 expression.GetOriginalString(), idxInOriginal );
238 String nestedExpressionName= prg.at(prg.resultStack.back()).ResultType.Unbox<
String>();
241 nested=
compiler.GetNamed( nestedExpressionName );
247 nestedExpressionName );
257 nested->ResultType(),
258 compiler.CfgNestedExpressionFunction.GetDefinitionName(),
259 idxInOriginal, idxInNormalized );
265 prg.add(
static_cast<Program*
>(
nullptr ),
Box(
nullptr ),
266 compiler.CfgNestedExpressionFunction.GetDefinitionName(),
267 idxInOriginal, idxInNormalized );
268 prg.act().ResultType= prg.prev().ResultType;
274 prg.add(
dynamic_cast<Program*
>(
this ),
275 prg.act().ResultType,
276 compiler.CfgNestedExpressionFunction.GetDefinitionName(),
277 idxInOriginal, idxInNormalized );
280 prg.resultPC()= prg.actPC();
291 functionName, isIdentifier,
298 if( !ppp.plugin->TryCompilation( cInfo ) )
315 prg.resultPC()= prg.actPC();
319 DBG_SET_CALLBACK_INFO
327 idxInOriginal, idxInNormalized );
335 prg.resultPC()= prg.actPC();
338 DBG_SET_CALLBACK_INFO
350 catch( std::exception& stdException )
355 expression.GetOriginalString(), idxInOriginal );
391 auto globalAliasIt=
compiler.AlphabeticUnaryOperatorAliases.Find(op);
392 if( globalAliasIt !=
compiler.AlphabeticUnaryOperatorAliases.end() ) {
394 opReference= globalAliasIt.Mapped();
401 && opReference ==
compiler.CfgNestedExpressionOperator
407 expression.GetOriginalString(), idxInOriginal );
415 nested=
compiler.GetNamed( expressionName );
432 op= globalAliasIt->first;
438 idxInOriginal, idxInNormalized );
445 for(
int pass= 0; pass < 2 ; ++pass ) {
449 opReference, isConstant );
453 if( !ppp.plugin->TryCompilation( cInfo ) )
460 op= globalAliasIt->first;
469 DBG_SET_CALLBACK_INFO
475 prg.add( cInfo.
Callback,
false, 1, cInfo.
TypeOrValue, op,
true, idxInOriginal, idxInNormalized );
478 DBG_SET_CALLBACK_INFO
490 prg.at( prg.resultPC() ).IsConstant(),
false );
492 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
498 if( ciAutoCast.
Callback ==
nullptr ) {
509 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
Callback,
false, 1,
512 idxInOriginal, idxInNormalized );
516 newCmd.DbgInfo.Plugin = pppAutoCast.plugin; )
533 catch( std::exception& stdException )
562 auto globalAliasIt=
compiler.AlphabeticBinaryOperatorAliases.Find(op);
563 if( globalAliasIt !=
compiler.AlphabeticBinaryOperatorAliases.end() ) {
565 opReference= globalAliasIt.Mapped();
568 bool foundOperator=
false;
569 bool triedToAutoCast=
false;
571 Box lhsOrigType= prg.at(prg.lhsResultPC()).ResultType;
572 Box rhsOrigType= prg.at(prg. resultPC()).ResultType;
582 opReference, lhsIsConstant, rhsIsConstant );
587 if( !ppp.plugin->TryCompilation( cInfo ) )
594 op= globalAliasIt->first;
603 prg.erase( prg.lhsResultStartPC() );
608 prg.resultPC()= prg.actPC();
619 prg.erase( prg.lhsResultStartPC(), prg.resultPC() );
622 prg.resultPC()= prg.actPC();
633 prg.add( cInfo.
Callback,
false, 2, cInfo.
TypeOrValue, op,
true, idxInOriginal, idxInNormalized );
634 prg.resultPC()= prg.actPC();
636 DBG_SET_CALLBACK_INFO
647 if( !foundOperator && triedToAutoCast ) {
657 triedToAutoCast=
true;
661 prg.at( prg.lhsResultPC() ).IsConstant(),
662 prg.at( prg. resultPC() ).IsConstant() );
665 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
671 if( ciAutoCast.
Callback ==
nullptr ) {
673 VM::Command& cmdToPatch= prg.at( prg.lhsResultPC() );
682 prg.insertAt( prg.lhsResultPC() + 1, ciAutoCast.
Callback,
false, 1,
685 idxInOriginal, idxInNormalized );
690 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
699 ALIB_DBG( prg.act().DbgInfo.Plugin= pppAutoCast.plugin; )
706 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
CallbackRhs,
false, 1,
709 idxInOriginal, idxInNormalized );
713 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
727 catch( std::exception& stdException )
760 Box& condition= prg.act().ResultType;
766 prg.add( idxInOriginal, idxInNormalized, Command::JumpType::Conditional );
767 compileStorage->ConditionalStack.emplace_back( prg.actPC(), 0, constQ );
779 prg.add( idxInOriginal, idxInNormalized, Command::JumpType::Unconditional );
786 prg.at(actCond.QJumpPos).Parameter.Distance= prg.length() - actCond.QJumpPos;
789 actCond.TJumpPos= prg.actPC();
805 prg.at( actCond.TJumpPos ).Parameter.Distance= prg.length() - actCond.TJumpPos;
809 if( !prg.at( prg.lhsResultPC() ).ResultType.IsSameType( prg.at( prg.resultPC() ).ResultType ) ) {
815 prg.at( prg.lhsResultPC() ).IsConstant(),
816 prg.at( prg. resultPC() ).IsConstant() );
821 if( ppp.plugin->TryCompilation( ciAutoCast ) ) {
824 if( ciAutoCast.
Callback ==
nullptr ) {
826 prg.at(prg.lhsResultPC()).ResultType = ciAutoCast.
TypeOrValue;
828 ALIB_DBG( prg.at(prg.lhsResultPC()).DbgInfo.Plugin= ppp.plugin; )
834 ++prg.at(actCond.QJumpPos).Parameter.Distance;
835 ++prg.at(actCond.TJumpPos).Parameter.Distance;
839 prg.insertAt( actCond.TJumpPos++, ciAutoCast.
Callback,
false, 1,
843 idxInOriginal, idxInNormalized );
845 newCmd.DbgInfo.Plugin= ppp.plugin; )
851 if( ciAutoCast.
Callback ==
nullptr ) {
856 prg.act().DbgInfo.Plugin= ppp.plugin; )
865 idxInOriginal, idxInNormalized );
867 ++prg.at(actCond.TJumpPos).Parameter.Distance;
870 prg.act().DbgInfo.Plugin= ppp.plugin; )
884 catch( std::exception& stdException )
906 if( actCond.ConstFlags ) {
908 if( (actCond.ConstFlags & 1) == 0 ) {
909 prg.erase( actCond.QJumpPos, actCond.TJumpPos + 1 );
914 prg.erase( actCond.TJumpPos, prg.actPC() + 1 );
915 prg.erase( actCond.QJumpPos );
919 prg.act().SetEndOfConditionalFlag();
928 prg.resultPC()= prg.actPC();
940 "Finalizing program, while conditional stack is of size {}.",
943 "Finalizing program, while result stack is of size {}.",
958#undef ASSERT_ASSEMBLE
959#undef DBG_SET_CALLBACK_INFO
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
ALIB_DLL const Enum & Type() const
Scope * getExpressionCTScope(ExpressionVal &ev)
MonoAllocator & getExpressionAllocator(ExpressionVal &ev)
Compiler::PluginList & getCompilerPlugins(Compiler &cmp)
ExpressionVal & expression
The expression that this program evaluates.
ALIB_DLL void AssembleUnaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
int qtyOptimizations
Counter of the number of optimization made during program assembly.
ALIB_DLL void AssembleFinalize()
ALIB_DLL const Box & ResultType() const
ALIB_DLL void AssembleFunction(AString &functionName, bool isIdentifier, int qtyArgs, integer idxInOriginal, integer idxInNormalized)
ALIB_DLL void AssembleBinaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
ALIB_DLL void AssembleCondFinalize_Q(integer idxInOriginal, integer idxInNormalized)
ALIB_DLL Program(Compiler &pCompiler, ExpressionVal &pExpression, MonoAllocator *ctAlloc)
ALIB_DLL void AssembleConstant(Box &value, integer idxInOriginal, integer idxInNormalized)
Compiler & compiler
The compiler that created this object.
StdVectorMA< Expression > ctNestedExpressions
ALIB_DLL void AssembleCondFinalize_F(integer idxInOriginal, integer idxInNormalized)
CompileStorage * compileStorage
ALIB_DLL ~Program()
Destructor.
ALIB_DLL bool collectArgs(integer qty)
integer commandsCount
The number of commands.
VM::Command * commands
The array of commands.
ALIB_DLL void AssembleCondFinalize_T(integer idxInOriginal, integer idxInNormalized)
DbgInformation DbgInfo
Operation code of this command. Available only with debug-builds.
void DbgDisableBufferReplacementWarning()
#define ALIB_CALLER_NULLED
#define ALIB_ERROR(domain,...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
@ ReplaceVerbalOperatorsToDefinedLetterCase
See sibling flag ReplaceVerbalOperatorsToSymbolic.
@ ReplaceVerbalOperatorsToSymbolic
@ PluginExceptionFallThrough
@ AllowCompileTimeNestedExpressions
@ NestedExpressionCallArgumentMismatch
@ UnknownIdentifier
Compile-time exception thrown when an expression uses an unknown identifier name.
@ UnaryOperatorNotDefined
@ UnknownFunction
Compile-time exception thrown when an expression uses an unknown function name.
@ NamedExpressionNotFound
Compile-time exception thrown when an expression refers to an unknown named nested expression.
@ IncompatibleTypesInConditional
@ NamedExpressionNotConstant
@ NestedExpressionNotFoundCT
@ BinaryOperatorNotDefined
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
LocalString< 128 > String128
Type alias name for TLocalString<character,128>.
std::vector< T, StdMA< T > > StdVectorMA
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
boxing::Box Box
Type alias in namespace alib.
exceptions::Exception Exception
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
boxing::FIsTrue FIsTrue
Type alias in namespace alib.
String ReverseCastFunctionNameRhs
String ReverseCastFunctionName
const nchar * DbgCallbackNameRhs
bool NonConstArgIsResult
Output: Used with optimization, see this struct's documentation for more information.
ListMA< String > & FunctionsWithNonMatchingArguments
const nchar * DbgCallbackName
CallbackDecl Callback
Output: The native C++ callback function to be set by one of the plug-ins.
StdVectorMA< Box > * Stack