14namespace alib {
namespace expressions {
namespace detail {
17using Command= VirtualMachine::Command;
25# define DBG_SET_CALLBACK_INFO \
26 prg.act().DbgInfo.Callback= cInfo.DbgCallbackName; \
27 prg.act().DbgInfo.Plugin = ppp.plugin;
29# define DBG_SET_CALLBACK_INFO
35: compiler ( pCompiler )
36, expression ( pExpression )
37, ctNestedExpressions( pExpression.allocator )
40, compileStorage ( ctAlloc ? (*ctAlloc)().New<
CompileStorage>(*ctAlloc) : nullptr )
65 : assembly ( pAssembly )
66 , resultStack( pResultStack) {}
73 return static_cast<integer>(assembly.size());
80 VM::Command& at( VM::PC pc )
82 return *assembly[size_t(pc)];
90 return *assembly.back();
98 return **( assembly.end() - 2 );
106 return static_cast<VM::PC
>( assembly.size() - 1);
119 void erase( VM::PC pc )
121 assembly.erase( assembly.begin() + pc );
129 void erase( VM::PC begin, VM::PC end )
131 assembly.erase( assembly.begin() + begin,
132 assembly.begin() + end );
141 template<
typename... TArgs>
143 VM::Command& insertAt( VM::PC pc, TArgs && ... args )
145 auto* cmd= assembly.get_allocator().AI().New<VM::Command>(std::forward<TArgs>( args )... );
146 assembly.emplace( assembly.begin() + pc, cmd );
154 template<
typename... TArgs>
156 VM::Command& add( TArgs && ... args )
158 assembly.emplace_back( assembly.get_allocator().AI().New<VM::Command>( std::forward<TArgs>( args )... ) );
159 return *assembly.back();
167 resultStack.push_back( actPC() );
174 resultStack.pop_back();
181 return resultStack.back();
186 VM::PC & lhsResultPC()
188 return resultStack[resultStack.size() - 2];
194 VM::PC lhsResultStartPC()
196 auto qtyResults = resultStack.size();
197 return qtyResults == 2 ? 0
198 : resultStack[qtyResults - 3] + 1;
208#define ASSERT_ASSEMBLE \
209 ALIB_ASSERT_ERROR( prg.resultStack.empty() \
210 || prg.resultPC() == prg.actPC() \
211 || prg.act().IsJump() , \
212 "EXPR", "Internal error: Last in result stack is not last command." )
218 "EXPR",
"Internal error. This should never happen." )
222 stack->reserve(
size_t( qty ));
224 bool allAreConst=
true;
225 for(
integer i= qty; i > 0 ; --i )
228 bool isConstant= cmd.IsConstant();
229 stack->emplace_back( cmd.ResultType );
230 allAreConst&= isConstant;
246 false, idxInOriginal, idxInNormalized ) );
267 || !prg.at( *(prg.resultStack.end() - ( qtyArgs == 3 ? 2 : qtyArgs) ) )
268 .ResultType.IsType<
String>() )
287 String nestedExpressionName= prg.at(prg.resultStack.back()).ResultType.Unbox<
String>();
297 nestedExpressionName );
309 nested->ResultType(),
311 idxInOriginal, idxInNormalized );
318 prg.add(
static_cast<Program*
>(
nullptr ),
Box(
nullptr ),
320 idxInOriginal, idxInNormalized );
321 prg.act().ResultType= prg.prev().ResultType;
327 prg.add(
dynamic_cast<Program*
>(
this ),
328 prg.act().ResultType,
330 idxInOriginal, idxInNormalized );
333 prg.resultPC()= prg.actPC();
344 functionName, isIdentifier,
352 if( !ppp.plugin->TryCompilation( cInfo ) )
374 prg.resultPC()= prg.actPC();
378 DBG_SET_CALLBACK_INFO
386 idxInOriginal, idxInNormalized );
395 prg.resultPC()= prg.actPC();
398 DBG_SET_CALLBACK_INFO
411 catch( std::exception& stdException )
458 opReference= globalAliasIt.Mapped();
498 op= globalAliasIt->first;
502 nested->ResultType(),
504 idxInOriginal, idxInNormalized );
511 for(
int pass= 0; pass < 2 ; ++pass )
516 opReference, isConstant );
521 if( !ppp.plugin->TryCompilation( cInfo ) )
528 op= globalAliasIt->first;
538 DBG_SET_CALLBACK_INFO
544 prg.add( cInfo.
Callback,
false, 1, cInfo.
TypeOrValue, op,
true, idxInOriginal, idxInNormalized );
547 DBG_SET_CALLBACK_INFO
559 prg.at( prg.resultPC() ).IsConstant(),
false );
562 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
569 if( ciAutoCast.
Callback ==
nullptr )
582 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
Callback,
false, 1,
585 idxInOriginal, idxInNormalized );
589 newCmd.DbgInfo.Plugin = pppAutoCast.plugin; )
607 catch( std::exception& stdException )
642 opReference= globalAliasIt.Mapped();
645 bool foundOperator=
false;
646 bool triedToAutoCast=
false;
648 Box lhsOrigType= prg.at(prg.lhsResultPC()).ResultType;
649 Box rhsOrigType= prg.at(prg. resultPC()).ResultType;
660 opReference, lhsIsConstant, rhsIsConstant );
666 if( !ppp.plugin->TryCompilation( cInfo ) )
673 op= globalAliasIt->first;
683 prg.erase( prg.lhsResultStartPC() );
688 prg.resultPC()= prg.actPC();
700 prg.erase( prg.lhsResultStartPC(), prg.resultPC() );
703 prg.resultPC()= prg.actPC();
714 prg.add( cInfo.
Callback,
false, 2, cInfo.
TypeOrValue, op,
true, idxInOriginal, idxInNormalized );
715 prg.resultPC()= prg.actPC();
717 DBG_SET_CALLBACK_INFO
728 if( !foundOperator && triedToAutoCast )
739 triedToAutoCast=
true;
743 prg.at( prg.lhsResultPC() ).IsConstant(),
744 prg.at( prg. resultPC() ).IsConstant() );
748 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
755 if( ciAutoCast.
Callback ==
nullptr )
758 VM::Command& cmdToPatch= prg.at( prg.lhsResultPC() );
768 prg.insertAt( prg.lhsResultPC() + 1, ciAutoCast.
Callback,
false, 1,
771 idxInOriginal, idxInNormalized );
776 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
788 ALIB_DBG( prg.act().DbgInfo.Plugin= pppAutoCast.plugin; )
796 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
CallbackRhs,
false, 1,
799 idxInOriginal, idxInNormalized );
803 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
818 catch( std::exception& stdException )
854 Box& condition= prg.act().ResultType;
860 prg.add( idxInOriginal, idxInNormalized, Command::JumpType::Conditional );
874 prg.add( idxInOriginal, idxInNormalized, Command::JumpType::Unconditional );
881 prg.at(actCond.QJumpPos).Parameter.Distance= prg.length() - actCond.QJumpPos;
884 actCond.TJumpPos= prg.actPC();
901 prg.at( actCond.TJumpPos ).Parameter.Distance= prg.length() - actCond.TJumpPos;
905 if( !prg.at( prg.lhsResultPC() ).ResultType.IsSameType( prg.at( prg.resultPC() ).ResultType ) )
912 prg.at( prg.lhsResultPC() ).IsConstant(),
913 prg.at( prg. resultPC() ).IsConstant() );
918 if( ppp.plugin->TryCompilation( ciAutoCast ) )
923 if( ciAutoCast.
Callback ==
nullptr )
926 prg.at(prg.lhsResultPC()).ResultType = ciAutoCast.
TypeOrValue;
928 ALIB_DBG( prg.at(prg.lhsResultPC()).DbgInfo.Plugin= ppp.plugin; )
935 ++prg.at(actCond.QJumpPos).Parameter.Distance;
936 ++prg.at(actCond.TJumpPos).Parameter.Distance;
940 prg.insertAt( actCond.TJumpPos++, ciAutoCast.
Callback,
false, 1,
944 idxInOriginal, idxInNormalized );
946 newCmd.DbgInfo.Plugin= ppp.plugin; )
954 if( ciAutoCast.
Callback ==
nullptr )
960 prg.act().DbgInfo.Plugin= ppp.plugin; )
970 idxInOriginal, idxInNormalized );
972 ++prg.at(actCond.TJumpPos).Parameter.Distance;
975 prg.act().DbgInfo.Plugin= ppp.plugin; )
991 catch( std::exception& stdException )
1016 if( actCond.ConstFlags )
1019 if( (actCond.ConstFlags & 1) == 0 )
1021 prg.erase( actCond.QJumpPos, actCond.TJumpPos + 1 );
1027 prg.erase( actCond.TJumpPos, prg.actPC() + 1 );
1028 prg.erase( actCond.QJumpPos );
1033 prg.act().SetEndOfConditionalFlag();
1042 prg.resultPC()= prg.actPC();
1055 "Finalizing program, while conditional stack is of size {}.",
1058 "Finalizing program, while result stack is of size {}.",
1075#undef ASSERT_ASSEMBLE
1076#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< MonoAllocator, String, String, alib::hash_string_ignore_case< character >, alib::equal_to_string_ignore_case< character > > AlphabeticUnaryOperatorAliases
HashMap< MonoAllocator, String, String, alib::hash_string_ignore_case< character >, alib::equal_to_string_ignore_case< character > > AlphabeticBinaryOperatorAliases
ALIB_API NString TypeName(Type box)
String CfgNestedExpressionOperator
Compilation CfgCompilation
Compilation flags.
strings::util::Token CfgNestedExpressionFunction
Normalization CfgNormalization
ALIB_API void WriteFunctionSignature(Box **boxArray, size_t qty, AString &target)
virtual ALIB_API Expression GetNamed(const String &name)
String GetOriginalString() const
MonoAllocator & allocator
ALIB_API void AssembleCondFinalize_T(integer idxInOriginal, integer idxInNormalized)
ALIB_API ~Program()
Destructor.
CompileStorage * compileStorage
ALIB_API bool collectArgs(integer qty)
ALIB_API void AssembleCondFinalize_F(integer idxInOriginal, integer idxInNormalized)
ALIB_API void AssembleUnaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
integer commandsCount
The number of commands.
Compiler & compiler
The compiler that created this object.
int qtyOptimizations
Counter of the number of optimization made during program assembly.
ALIB_API Program(Compiler &pCompiler, ExpressionVal &pExpression, MonoAllocator *ctAlloc)
ALIB_API void AssembleConstant(Box &value, integer idxInOriginal, integer idxInNormalized)
ALIB_API void AssembleCondFinalize_Q(integer idxInOriginal, integer idxInNormalized)
StdVectorMono< Expression > ctNestedExpressions
VM::Command * commands
The array of commands.
ALIB_API void AssembleFunction(AString &functionName, bool isIdentifier, int qtyArgs, integer idxInOriginal, integer idxInNormalized)
ExpressionVal & expression
The expression that this program evaluates.
ALIB_API void AssembleFinalize()
ALIB_API void AssembleBinaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
DbgInformation DbgInfo
Operation code of this command. Available only with debug-builds.
ALIB_API const Enum & Type() const
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
std::vector< Slot > plugins
The plug-ins we have attached in descending priority order.
void DbgDisableBufferReplacementWarning()
constexpr bool IsNotEmpty() const
const String & GetDefinitionName() 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
See sibling flag ReplaceVerbalOperatorsToSymbolic.
@ ReplaceVerbalOperatorsToSymbolic
@ 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
static ALIB_FORCE_INLINE void Destruct(T &object)
lang::Exception Exception
Type alias in namespace alib.
std::vector< T, SCAMono< T > > StdVectorMono
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
bool NonConstArgIsResult
Output: Used with optimization, see this struct's documentation for more information.
List< MonoAllocator, String > & FunctionsWithNonMatchingArguments
const nchar * DbgCallbackName
CallbackDecl Callback
Output: The native C++ callback function to be set by one of the plug-ins.
StdVectorMono< Box > * Stack
StdVectorMono< VM::PC > ResultStack
List< MonoAllocator, String > FunctionsWithNonMatchingArguments
StdVectorMono< ConditionalInfo > ConditionalStack
StdVectorMono< VirtualMachine::Command * > Assembly