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"
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
77 : assembly ( pAssembly )
78 , resultStack( pResultStack) {}
84 return integer(assembly.size());
90 VM::Command& at( VM::PC pc )
92 return *assembly[size_t(pc)];
99 return *assembly.back();
106 return **( assembly.end() - 2 );
113 return static_cast<VM::PC
>( assembly.size() - 1);
124 void erase( VM::PC pc )
126 assembly.erase( assembly.begin() + pc );
133 void erase( VM::PC begin, VM::PC end )
135 assembly.erase( assembly.begin() + begin,
136 assembly.begin() + end );
145 template<
typename... TArgs>
146 VM::Command& insertAt( VM::PC pc, TArgs && ... args )
148 auto* cmd= assembly.get_allocator().AI().New<VM::Command>(std::forward<TArgs>( args )... );
149 assembly.emplace( assembly.begin() + pc, cmd );
157 template<
typename... TArgs>
158 VM::Command& add( TArgs && ... args )
160 assembly.emplace_back( assembly.get_allocator().AI().New<VM::Command>( std::forward<TArgs>( args )... ) );
161 return *assembly.back();
168 resultStack.push_back( actPC() );
174 resultStack.pop_back();
180 return resultStack.back();
184 VM::PC & lhsResultPC()
186 return resultStack[resultStack.size() - 2];
191 VM::PC lhsResultStartPC()
193 auto qtyResults = resultStack.size();
194 return qtyResults == 2 ? 0
195 : resultStack[qtyResults - 3] + 1;
205#define ASSERT_ASSEMBLE \
206 ALIB_ASSERT_ERROR( prg.resultStack.empty() \
207 || prg.resultPC() == prg.actPC() \
208 || prg.act().IsJump() , \
209 "EXPR", "Internal error: Last in result stack is not last command." )
215 "EXPR",
"Internal error. This should never happen." )
219 stack->reserve(
size_t( qty ));
221 bool allAreConst=
true;
222 for(
integer i= qty; i > 0 ; --i )
225 bool isConstant= cmd.IsConstant();
226 stack->emplace_back( cmd.ResultType );
227 allAreConst&= isConstant;
244 false, idxInOriginal, idxInNormalized ) );
258 if(
compiler.CfgNestedExpressionFunction.GetDefinitionName().IsNotEmpty()
259 &&
compiler.CfgNestedExpressionFunction.Match(functionName ) )
265 || !prg.at( *(prg.resultStack.end() - ( qtyArgs == 3 ? 2 : qtyArgs) ) )
266 .ResultType.IsType<
String>() )
269 compiler.CfgNestedExpressionFunction );
280 expression.GetOriginalString(), idxInOriginal );
285 String nestedExpressionName= prg.at(prg.resultStack.back()).ResultType.Unbox<
String>();
288 nested=
compiler.GetNamed( nestedExpressionName );
295 nestedExpressionName );
307 nested->ResultType(),
308 compiler.CfgNestedExpressionFunction.GetDefinitionName(),
309 idxInOriginal, idxInNormalized );
316 prg.add(
static_cast<Program*
>(
nullptr ),
Box(
nullptr ),
317 compiler.CfgNestedExpressionFunction.GetDefinitionName(),
318 idxInOriginal, idxInNormalized );
319 prg.act().ResultType= prg.prev().ResultType;
325 prg.add(
dynamic_cast<Program*
>(
this ),
326 prg.act().ResultType,
327 compiler.CfgNestedExpressionFunction.GetDefinitionName(),
328 idxInOriginal, idxInNormalized );
331 prg.resultPC()= prg.actPC();
342 functionName, isIdentifier,
350 if( !ppp.plugin->TryCompilation( cInfo ) )
372 prg.resultPC()= prg.actPC();
376 DBG_SET_CALLBACK_INFO
384 idxInOriginal, idxInNormalized );
393 prg.resultPC()= prg.actPC();
396 DBG_SET_CALLBACK_INFO
409 catch( std::exception& stdException )
415 expression.GetOriginalString(), idxInOriginal );
452 auto globalAliasIt=
compiler.AlphabeticUnaryOperatorAliases.Find(op);
453 if( globalAliasIt !=
compiler.AlphabeticUnaryOperatorAliases.end() )
456 opReference= globalAliasIt.Mapped();
463 && opReference ==
compiler.CfgNestedExpressionOperator
470 expression.GetOriginalString(), idxInOriginal );
478 nested=
compiler.GetNamed( expressionName );
496 op= globalAliasIt->first;
502 idxInOriginal, idxInNormalized );
509 for(
int pass= 0; pass < 2 ; ++pass )
514 opReference, isConstant );
519 if( !ppp.plugin->TryCompilation( cInfo ) )
526 op= globalAliasIt->first;
536 DBG_SET_CALLBACK_INFO
542 prg.add( cInfo.
Callback,
false, 1, cInfo.
TypeOrValue, op,
true, idxInOriginal, idxInNormalized );
545 DBG_SET_CALLBACK_INFO
557 prg.at( prg.resultPC() ).IsConstant(),
false );
560 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
567 if( ciAutoCast.
Callback ==
nullptr )
580 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
Callback,
false, 1,
583 idxInOriginal, idxInNormalized );
587 newCmd.DbgInfo.Plugin = pppAutoCast.plugin; )
605 catch( std::exception& stdException )
636 auto globalAliasIt=
compiler.AlphabeticBinaryOperatorAliases.Find(op);
637 if( globalAliasIt !=
compiler.AlphabeticBinaryOperatorAliases.end() )
640 opReference= globalAliasIt.Mapped();
643 bool foundOperator=
false;
644 bool triedToAutoCast=
false;
646 Box lhsOrigType= prg.at(prg.lhsResultPC()).ResultType;
647 Box rhsOrigType= prg.at(prg. resultPC()).ResultType;
658 opReference, lhsIsConstant, rhsIsConstant );
664 if( !ppp.plugin->TryCompilation( cInfo ) )
671 op= globalAliasIt->first;
681 prg.erase( prg.lhsResultStartPC() );
686 prg.resultPC()= prg.actPC();
698 prg.erase( prg.lhsResultStartPC(), prg.resultPC() );
701 prg.resultPC()= prg.actPC();
712 prg.add( cInfo.
Callback,
false, 2, cInfo.
TypeOrValue, op,
true, idxInOriginal, idxInNormalized );
713 prg.resultPC()= prg.actPC();
715 DBG_SET_CALLBACK_INFO
726 if( !foundOperator && triedToAutoCast )
737 triedToAutoCast=
true;
741 prg.at( prg.lhsResultPC() ).IsConstant(),
742 prg.at( prg. resultPC() ).IsConstant() );
746 if( !pppAutoCast.plugin->TryCompilation( ciAutoCast ) )
753 if( ciAutoCast.
Callback ==
nullptr )
756 VM::Command& cmdToPatch= prg.at( prg.lhsResultPC() );
766 prg.insertAt( prg.lhsResultPC() + 1, ciAutoCast.
Callback,
false, 1,
769 idxInOriginal, idxInNormalized );
774 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
786 ALIB_DBG( prg.act().DbgInfo.Plugin= pppAutoCast.plugin; )
794 prg.insertAt( prg.resultPC() + 1, ciAutoCast.
CallbackRhs,
false, 1,
797 idxInOriginal, idxInNormalized );
801 newCmd.DbgInfo.Plugin= pppAutoCast.plugin; )
816 catch( std::exception& stdException )
852 Box& condition= prg.act().ResultType;
858 prg.add( idxInOriginal, idxInNormalized, Command::JumpType::Conditional );
859 compileStorage->ConditionalStack.emplace_back( prg.actPC(), 0, constQ );
872 prg.add( idxInOriginal, idxInNormalized, Command::JumpType::Unconditional );
879 prg.at(actCond.QJumpPos).Parameter.Distance= prg.length() - actCond.QJumpPos;
882 actCond.TJumpPos= prg.actPC();
899 prg.at( actCond.TJumpPos ).Parameter.Distance= prg.length() - actCond.TJumpPos;
903 if( !prg.at( prg.lhsResultPC() ).ResultType.IsSameType( prg.at( prg.resultPC() ).ResultType ) )
910 prg.at( prg.lhsResultPC() ).IsConstant(),
911 prg.at( prg. resultPC() ).IsConstant() );
916 if( ppp.plugin->TryCompilation( ciAutoCast ) )
921 if( ciAutoCast.
Callback ==
nullptr )
924 prg.at(prg.lhsResultPC()).ResultType = ciAutoCast.
TypeOrValue;
926 ALIB_DBG( prg.at(prg.lhsResultPC()).DbgInfo.Plugin= ppp.plugin; )
933 ++prg.at(actCond.QJumpPos).Parameter.Distance;
934 ++prg.at(actCond.TJumpPos).Parameter.Distance;
938 prg.insertAt( actCond.TJumpPos++, ciAutoCast.
Callback,
false, 1,
942 idxInOriginal, idxInNormalized );
944 newCmd.DbgInfo.Plugin= ppp.plugin; )
952 if( ciAutoCast.
Callback ==
nullptr )
958 prg.act().DbgInfo.Plugin= ppp.plugin; )
968 idxInOriginal, idxInNormalized );
970 ++prg.at(actCond.TJumpPos).Parameter.Distance;
973 prg.act().DbgInfo.Plugin= ppp.plugin; )
989 catch( std::exception& stdException )
1014 if( actCond.ConstFlags )
1017 if( (actCond.ConstFlags & 1) == 0 )
1019 prg.erase( actCond.QJumpPos, actCond.TJumpPos + 1 );
1025 prg.erase( actCond.TJumpPos, prg.actPC() + 1 );
1026 prg.erase( actCond.QJumpPos );
1031 prg.act().SetEndOfConditionalFlag();
1040 prg.resultPC()= prg.actPC();
1053 "Finalizing program, while conditional stack is of size {}.",
1056 "Finalizing program, while result stack is of size {}.",
1071#undef ASSERT_ASSEMBLE
1072#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()
StdVectorMono< Expression > ctNestedExpressions
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.
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.
std::vector< T, SCAMono< T > > StdVectorMono
Type alias in namespace alib.
LocalString< 128 > String128
Type alias name for TLocalString<character,128>.
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.
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