10#if !defined (HPP_ALIB_EXPRESSIONS_DETAIL_PROGRAM)
14#if !defined (HPP_ALIB_EXPRESSIONS_COMPILERPLUGIN)
19namespace alib {
namespace expressions {
namespace detail {
22using Command= VirtualMachine::Command;
30# define DBG_SET_CALLBACK_INFO \
31 prg.act().DbgInfo.Callback= cInfo.DbgCallbackName; \
32 prg.act().DbgInfo.Plugin = ppp.plugin;
34# define DBG_SET_CALLBACK_INFO
40: compiler ( pCompiler )
41, expression ( pExpression )
42, ctNestedExpressions( pExpression.ctScope->Allocator )
45, compileStorage ( compileTimeAlloc ? compileTimeAlloc->Emplace<
CompileStorage>( *compileTimeAlloc )
71 std::vector<VirtualMachine::Command*, StdContMA<VirtualMachine::Command*>>& assembly;
72 std::vector<VM::PC , StdContMA<VM::PC >>& resultStack;
77 : assembly ( pAssembly )
78 , resultStack( pResultStack)
88 return static_cast<integer>(assembly.size());
97 VM::Command& at( VM::PC pc )
99 return *assembly[
static_cast<size_t>(pc)];
109 return *assembly.back();
119 return **( assembly.end() - 2 );
129 return static_cast<VM::PC
>( assembly.size() - 1);
146 void erase( VM::PC pc )
148 assembly.erase( assembly.begin() + pc );
158 void erase( VM::PC begin, VM::PC end )
160 assembly.erase( assembly.begin() + begin,
161 assembly.begin() + end );
172 template<
typename... TArgs>
174 VM::Command& insertAt( VM::PC pc, TArgs && ... args )
176 auto* cmd= assembly.get_allocator().allocator.Emplace<VM::Command>( std::forward<TArgs>( args )... );
177 assembly.emplace( assembly.begin() + pc, cmd );
187 template<
typename... TArgs>
189 VM::Command& add( TArgs && ... args )
191 assembly.emplace_back( assembly.get_allocator().allocator.Emplace<VM::Command>(std::forward<TArgs>( args )... ) );
192 return *assembly.back();
200 resultStack.push_back( actPC() );
207 resultStack.pop_back();
214 return resultStack.back();
219 VM::PC & lhsResultPC()
221 return resultStack[resultStack.size() - 2];
227 VM::PC lhsResultStartPC()
229 auto qtyResults = resultStack.size();
230 return qtyResults == 2 ? 0
231 : resultStack[qtyResults - 3] + 1;
241#define ASSERT_ASSEMBLE \
242 ALIB_ASSERT_ERROR( prg.resultStack.empty() \
243 || prg.resultPC() == prg.actPC() \
244 || prg.act().IsConditionalJump() , \
245 "EXPR", "Internal error: Last in result stack is not last command." )
250 "EXPR",
"Not enough arguments on the stack. This should never happen (internal error)." )
256 bool allAreConst=
true;
257 for(
integer i= qty; i > 0 ; --i )
260 bool isConstant= cmd.IsConstant();
263 allAreConst&= isConstant;
279 false, idxInOriginal, idxInNormalized ) );
300 || !prg.at( *(prg.resultStack.end() - ( qtyArgsOrNoParentheses == 3 ? 2 : qtyArgsOrNoParentheses) ) )
309 if( qtyArgsOrNoParentheses == 1 )
320 String nestedExpressionName= prg.at(prg.resultStack.back()).ResultType.Unbox<
String>();
330 nestedExpressionName );
342 nested->ResultType(),
344 idxInOriginal, idxInNormalized );
349 if( qtyArgsOrNoParentheses == 2 )
351 prg.add(
static_cast<Program*
>(
nullptr ),
Box(
nullptr ),
353 idxInOriginal, idxInNormalized );
354 prg.act().ResultType= prg.prev().ResultType;
360 prg.add(
dynamic_cast<Program*
>(
this ),
361 prg.act().ResultType,
363 idxInOriginal, idxInNormalized );
366 prg.resultPC()= prg.actPC();
372 bool allAreConstant=
collectArgs(qtyArgsOrNoParentheses);
378 (qtyArgsOrNoParentheses < 0),
386 if( !ppp.plugin->TryCompilation( cInfo ) )
392 if( qtyArgsOrNoParentheses > 0 )
408 prg.resultPC()= prg.actPC();
412 DBG_SET_CALLBACK_INFO
420 idxInOriginal, idxInNormalized );
429 prg.resultPC()= prg.actPC();
432 DBG_SET_CALLBACK_INFO
445 catch( std::exception& stdException )
460 if( qtyArgsOrNoParentheses < 0 )
491 opReference= globalAliasIt.Mapped();
531 op= globalAliasIt->first;
535 nested->ResultType(),
537 idxInOriginal, idxInNormalized );
544 for(
int pass= 0; pass < 2 ; ++pass )
549 opReference, isConstant );
554 if( !ppp.plugin->TryCompilation( cInfo ) )
561 op= globalAliasIt->first;
571 DBG_SET_CALLBACK_INFO
580 DBG_SET_CALLBACK_INFO
592 prg.at( prg.resultPC() ).IsConstant(),
false );
595 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
602 if( ciAutoCast.
Callback ==
nullptr )
615 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
Callback, 1,
618 idxInOriginal, idxInNormalized );
622 newCmd.DbgInfo.Plugin = pppAutoCast.plugin; )
640 catch( std::exception& stdException )
675 opReference= globalAliasIt.Mapped();
678 bool foundOperator=
false;
679 bool triedToAutoCast=
false;
681 Box lhsOrigType= prg.at(prg.lhsResultPC()).ResultType;
682 Box rhsOrigType= prg.at(prg. resultPC()).ResultType;
693 opReference, lhsIsConstant, rhsIsConstant );
699 if( !ppp.plugin->TryCompilation( cInfo ) )
706 op= globalAliasIt->first;
716 prg.erase( prg.lhsResultStartPC() );
721 prg.resultPC()= prg.actPC();
733 prg.erase( prg.lhsResultStartPC(), prg.resultPC() );
736 prg.resultPC()= prg.actPC();
748 prg.resultPC()= prg.actPC();
750 DBG_SET_CALLBACK_INFO
761 if( !foundOperator && triedToAutoCast )
772 triedToAutoCast=
true;
776 prg.at( prg.lhsResultPC() ).IsConstant(),
777 prg.at( prg. resultPC() ).IsConstant() );
781 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
788 if( ciAutoCast.
Callback ==
nullptr )
791 VM::Command& cmdToPatch= prg.at( prg.lhsResultPC() );
801 prg.insertAt( prg.lhsResultPC() + 1, ciAutoCast.
Callback, 1,
804 idxInOriginal, idxInNormalized );
809 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
821 ALIB_DBG( prg.act().DbgInfo.Plugin= pppAutoCast.plugin; )
829 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
CallbackRhs, 1,
832 idxInOriginal, idxInNormalized );
836 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
851 catch( std::exception& stdException )
887 Box& condition= prg.act().Operation.Value;
893 prg.add( Command::JumpType::Conditional, idxInOriginal, idxInNormalized );
907 prg.add( Command::JumpType::Unconditional, idxInOriginal, idxInNormalized );
914 prg.at(actCond.QJumpPos).Operation.Distance= prg.length() - actCond.QJumpPos;
917 actCond.TJumpPos= prg.actPC();
934 prg.at( actCond.TJumpPos ).Operation.Distance= prg.length() - actCond.TJumpPos;
938 if( !prg.at( prg.lhsResultPC() ).ResultType.IsSameType( prg.at( prg.resultPC() ).ResultType ) )
945 prg.at( prg.lhsResultPC() ).IsConstant(),
946 prg.at( prg. resultPC() ).IsConstant() );
951 if( ppp.plugin->TryCompilation( ciAutoCast ) )
956 if( ciAutoCast.
Callback ==
nullptr )
959 prg.at(prg.lhsResultPC()).Operation.Value=
962 ALIB_DBG( prg.at(prg.lhsResultPC()).DbgInfo.Plugin= ppp.plugin; )
969 ++prg.at(actCond.QJumpPos).Operation.Distance;
970 ++prg.at(actCond.TJumpPos).Operation.Distance;
974 prg.insertAt( actCond.TJumpPos++, ciAutoCast.
Callback, 1,
978 idxInOriginal, idxInNormalized );
980 newCmd.DbgInfo.Plugin= ppp.plugin; )
988 if( ciAutoCast.
Callback ==
nullptr )
991 prg.act().Operation.Value=
995 prg.act().DbgInfo.Plugin= ppp.plugin; )
1005 idxInOriginal, idxInNormalized );
1007 ++prg.at(actCond.TJumpPos).Operation.Distance;
1010 prg.act().DbgInfo.Plugin= ppp.plugin; )
1026 catch( std::exception& stdException )
1051 if( actCond.ConstFlags )
1054 if( (actCond.ConstFlags & 1) == 0 )
1056 prg.erase( actCond.QJumpPos, actCond.TJumpPos + 1 );
1062 prg.erase( actCond.TJumpPos, prg.actPC() + 1 );
1063 prg.erase( actCond.QJumpPos );
1068 prg.act().SetEndOfConditionalFlag();
1077 prg.resultPC()= prg.actPC();
1090 "Finalizing program, while conditional stack is of size {}.",
1093 "Finalizing program, while result stack is of size {}.",
1110#undef ASSERT_ASSEMBLE
1111#undef DBG_SET_CALLBACK_INFO
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
const TUnboxable Unbox() const
HashMap< String, String, alib::hash_string_ignore_case< character >, alib::equal_to_string_ignore_case< character > > AlphabeticUnaryOperatorAliases
virtual ALIB_API SPExpression GetNamed(const String &name)
ALIB_API NString TypeName(Type box)
String CfgNestedExpressionOperator
Compilation CfgCompilation
strings::util::Token CfgNestedExpressionFunction
Normalization CfgNormalization
ALIB_API void WriteFunctionSignature(Box **boxArray, size_t qty, AString &target)
HashMap< String, String, alib::hash_string_ignore_case< character >, alib::equal_to_string_ignore_case< character > > AlphabeticBinaryOperatorAliases
String GetOriginalString() const
ALIB_API void AssembleCondFinalize_T(integer idxInOriginal, integer idxInNormalized)
ALIB_API const Box & ResultType() const
CompileStorage * compileStorage
ALIB_API bool collectArgs(integer qty)
ALIB_API Program(Compiler &pCompiler, Expression &pExpression, MonoAllocator *compileTimeAllocator)
ALIB_API void AssembleCondFinalize_F(integer idxInOriginal, integer idxInNormalized)
ALIB_API void AssembleUnaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
ALIB_API void AssembleFunction(AString &functionName, integer qtyArgsOrNoParentheses, integer idxInOriginal, integer idxInNormalized)
ALIB_API void AssembleConstant(Box &value, integer idxInOriginal, integer idxInNormalized)
ALIB_API void AssembleCondFinalize_Q(integer idxInOriginal, integer idxInNormalized)
std::vector< SPExpression, StdContMA< SPExpression > > ctNestedExpressions
ALIB_API void AssembleFinalize()
ALIB_API void AssembleBinaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
ALIB_API const Enum & Type() const
Exception & Add(const NCString &file, int line, const NCString &func, TEnum type, TArgs &&... args)
std::vector< Slot > plugins
strings::TString< TChar > EmplaceString(const strings::TString< TChar > &src)
ALIB_FORCE_INLINE T * AllocArray(TSize length)
void DbgDisableBufferReplacementWarning()
constexpr bool IsNotEmpty() const
const String & GetRawName() const
ALIB_API bool Match(const String &needle)
#define ALIB_CALLER_NULLED
#define ALIB_WARNINGS_RESTORE
#define ALIB_FORCE_INLINE
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
@ PluginExceptionFallThrough
@ AllowCompileTimeNestedExpressions
@ ReplaceVerbalOperatorsToDefinedLetterCase
@ ReplaceVerbalOperatorsToSymbolic
std::shared_ptr< Expression > SPExpression
@ NestedExpressionCallArgumentMismatch
@ UnaryOperatorNotDefined
@ NamedExpressionNotFound
Compile-time exception thrown when an expression refers to an unknown named nested expression.
@ IncompatibleTypesInConditional
@ NamedExpressionNotConstant
@ NestedExpressionNotFoundCT
@ BinaryOperatorNotDefined
static ALIB_FORCE_INLINE void Destruct(T *object)
lang::Exception Exception
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
String ReverseCastFunctionName
const nchar * DbgCallbackNameRhs
String ReverseCastFunctionNameRhs
List< String > & FunctionsWithNonMatchingArguments
const nchar * DbgCallbackName
std::vector< alib::Box > Stack
std::vector< ConditionalInfo, StdContMA< ConditionalInfo > > ConditionalStack
List< String > FunctionsWithNonMatchingArguments
std::vector< VirtualMachine::Command *, StdContMA< VirtualMachine::Command * > > Assembly
std::vector< VM::PC, StdContMA< VM::PC > > ResultStack
Box Value
A constant value to push to the stack.