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"
50#define POS_IN_EXPR_STR (cmd.ExpressionPositions & ( (1UL << (bitsof(integer) / 2 - 1) ) -1 ) )
52# define NORMPOS_IN_EXPR_STR (cmd.ExpressionPositions >> (bitsof(integer)/2 ) )
68 run( program, scope );
75 scope.
Stack->pop_back();
85 auto& stack= *scope.
Stack;
89 for(
auto* nestedExpression : nestedExpressions )
93 for(
auto it2= nestedExpressions.begin() ; it2!= nestedExpressions.end(); ++it2 )
96 it2 + 1 != nestedExpressions.end()
98 : nestedExpression->Name() );
102 nestedExpressions.emplace_back( &program.
expression );
105 for(
integer programCounter= 0; programCounter < program.
Length() ; ++ programCounter )
107 const Command& cmd= program.
At(programCounter);
129 "Result type mismatch during command execution:\n"
130 " In expression: \"{}\" {{{}}}\n"
132 " Identifier: {} ({})\n"
133 " Expected type: <{}> (aka {})\n"
134 " Result type: <{}> (aka {})\n"
135 " Result value: {}\n",
151 *(stack.end() - cmd.
QtyArgs() )=
168 case DCT::FunctionCall:
181 case DCT::OptimizationConstant:
182 ALIB_ERROR(
"EXPRVM",
"Must not be set with function calls")
184 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state." )
break;
191 fmt.
Format( msg,
"Result type mismatch during command execution:\n"
192 " In expression: {!Q} {{{}}}\n"
196 " Expected type: {!Q<>} (aka {})\n"
197 " Result type: {!Q<>} (aka {})\n"
198 " Result value: {}\n"
199 " Parameter values: ",
208 fmt.
Format( msg,
"({!Q'} {!Q<>}",
212 fmt.
Format( msg,
", {!Q'} {!Q<>}",
235 catch( std::exception& stdException )
244 stdException.what() );
254 if( !stack.back().Call<
FIsTrue>() )
271 String nestedExpressionName= (stack.end()-2)->Unbox<
String>();
285 stack.erase( stack.end() - 2 );
290 nestedExpressionName );
300 nestedExpressionName );
303 nestedExpressionName );
307 run( *
static_cast<Program*
>(nested.
Get()->GetProgram()), scope);
309 if( !(stack.end()-2)->IsSameType(stack.back()) )
312 nestedExpressionName,
320 stack.erase( stack.end()-3, stack.end() -1 );
329 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state." )
break;
336 nestedExpressions.pop_back();
341 "Internal error: Stack increased by {} (instead of 1) after run of expression program.",
342 stack.size() - initialStackSize )
346 "Wrong result type of program execution:\n"
347 " Expected Type: <{}> (aka {})\n"
348 " Result Type: <{}> (aka {})\n"
349 " Result value: {}\n"
350 " In expression: \"{}\""
366 #define PushNode(node) nodeStack.emplace_back( node )
367 #define PopNode nodeStack.pop_back()
368 #define Lhs (*(nodeStack.end() - 2) )
369 #define Rhs nodeStack.back()
370 #define Arg nodeStack.back()
372 std::vector<AST*> nodeStack;
374 std::stack <PC> conditionalStack;
381 integer positionInExpression= POS_IN_EXPR_STR;
394 for(
integer i= 0 ; i< 2 ; ++i )
404 positionInExpression ) );
412 positionInExpression );
415 positionInExpression );
476 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state.")
break;
481 while( !conditionalStack.empty() && conditionalStack.top() == pc )
483 AST* F= Arg; PopNode;
484 AST* T= Arg; PopNode;
486 conditionalStack.pop();
499 "VM AST generation error: NodeImpl stack must contain one element. Elements: {}",
502 "VM Program List error: Conditional stack after listing not 0 but {}",
503 conditionalStack.size())
505 return nodeStack.back();
517void writeArgPositions(
AString& target, std::vector<VirtualMachine::PC>& resultStack,
integer qtyArgs )
519 for(
integer argNo= qtyArgs ; argNo > 0 ; --argNo )
521 target << (argNo == qtyArgs ?
"" :
", ")
522 << (qtyArgs-argNo) <<
"{"
523 << (
integer(resultStack.size()) == argNo ? 0
524 : *(resultStack.end() - argNo - 1) + 1 )
525 <<
".." << *(resultStack.end() - argNo )
565 for(
int i= 0 ; i < 7 ; ++i )
567 hdlArgs[i+1]=
EXPRESSIONS.GetResource(hdlKeyNumbered << i );
578 #define FMT(qtyArgs) \
579 { if( cmd.DbgInfo.Plugin ) \
580 description << ", CP=\"" << cmd.DbgInfo.Plugin->Name<< '\"'; \
582 writeArgPositions(argpos,resultStack,qtyArgs); \
585 program.compiler.TypeName( cmd.ResultType ), \
591 NORMPOS_IN_EXPR_STR, "_^_" ); }
594 #define PushResult resultStack.emplace_back( pc )
595 #define PopResult resultStack.pop_back()
596 #define ResultPos resultStack.back()
598 std::vector<PC> resultStack; // The last command of the current results on the stack
599 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
600 // conditional term "Q : T : F". In other words, the
604 for( integer pc= 0 ; pc < program.Length() ; ++pc )
606 const Command& cmd= program.At(pc);
609 String128 description;
610 ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
611 ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
612 switch( cmd.OpCode() )
614 case Command::OpCodes::Subroutine:
616 if( cmd.Parameter.NestedProgram == nullptr
617 || cmd.Parameter.NestedProgram == &program )
620 operation << ( cmd.Parameter.NestedProgram == nullptr ? "Expr(name, type)"
621 : "Expr(name, type, throw)" );
622 description << "Nested expr. searched at evaluation-time";
628 operation << cmd.DecompileSymbol
629 << "\"" << cmd.Parameter.NestedProgram->expression.Name() << '\"';
630 description << "Nested expr. searched at compile-time";
637 case Command::OpCodes::Constant:
640 char uetzelchen= cmd.ResultType.IsType<String>() ? '\"' : '\'';
641 operation << uetzelchen << cmd.ResultType << uetzelchen;
642 description << (cmd.TerminalType() == DCT::LiteralConstant ? "Literal constant"
643 : "Optimization constant" );
649 case Command::OpCodes::Function:
651 operation << cmd.DbgInfo.Callback
652 << "(#" << (cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs()) << ')';
654 NString descr= nullptr;
656 switch( cmd.TerminalType() )
659 descr = "Unary operator";
663 descr = "Binary operator";
666 case DCT::Identifier:
667 descr = "Identifier";
670 case DCT::FunctionCall:
671 if( cmd.QtyArgs() < 0 )
673 descr =
"Identifier";
677 description <<
"Function \"";
678 if( cmd.QtyArgs() == 0 )
679 description << cmd.DecompileSymbol <<
"()\"";
681 description << cmd.DecompileSymbol <<
"(#"
682 << cmd.QtyArgs() <<
")\"";
689 case DCT::OptimizationConstant:
690 ALIB_ERROR(
"EXPRVM",
"Must not be set with function calls")
692 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state.")
break;
694 if( descr.IsNotNull() )
695 description << descr <<
' ' << decSym << cmd.DecompileSymbol << decSym;
697 stackSize+= 1 - (cmd.QtyArgs() > 0 ? cmd.QtyArgs() : 0 );
698 FMT(cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs() )
699 for(
integer i= 0 ; i< cmd.QtyArgs() ; ++i )
707 operation << ( pc + cmd.Parameter.Distance ) <<
" (absolute)" ;
708 description <<
"'?'";
716 conditionalStack.emplace( pc + cmd.Parameter.Distance -1 );
717 operation << ( pc + cmd.Parameter.Distance ) <<
" (absolute)" ;
718 description <<
"':'";
724 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state.") break;
730 while( !conditionalStack.empty() && conditionalStack.top() == pc )
735 conditionalStack.pop();
747 "VM Program List error: Stack size after listing not 1 but {}. Listing follows.\n",
748 stackSize, text.Buffer )
751 "VM Program List error: Resultstack after listing not 1 but {}. Listing follows.\n",
752 resultStack.size(), text.Buffer )
755 "VM Program List error: Conditional stack after listing not 0 but {}. Listing follows.\n",
756 conditionalStack.size(), text.Buffer )
759 return std::move(text.Buffer);
764#undef POS_IN_EXPR_STR
bool IsSameType(const Box &other) const
const std::type_info & TypeID() const
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
ALIB_DLL const Enum & Type() const
Compilation CfgCompilation
Compilation flags.
ALIB_DLL NString TypeName(Type box)
virtual ALIB_DLL Expression GetNamed(const String &name)
String CfgNestedExpressionThrowIdentifier
String CfgNestedExpressionOperator
String GetNormalizedString() const
String GetOriginalString() const
ExpressionVal & expression
The expression that this program evaluates.
ALIB_DLL const Box & ResultType() const
VM::Command & At(VM::PC pc)
Compiler & compiler
The compiler that created this object.
ListingTypes
Denotes the type of parsing de-compilation information attached to the command.
@ NestedExpression
Command results from a nested expression.
DbgInformation DbgInfo
Operation code of this command. Available only with debug-builds.
OperationParam Parameter
The parameter of the operation.
OpCodes
The opcode type of VM commands.
@ Subroutine
Invokes another program.
@ Function
Invokes a C++ callback function.
@ JumpIfFalse
Jumps if top of the stack indicates false.
@ Constant
Pushes a constant to the stack.
uinteger ExpressionPositions
Command(const Box &value, bool isOptimization, integer idxOriginal, integer idxNormalized)
constexpr OpCodes OpCode() const
int16_t bits
Operation code of this command.
constexpr ListingTypes TerminalType() const
TAString & ShortenTo(integer newLength)
constexpr integer Length() const
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
#define ALIB_CALLER_NULLED
#define ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
#define ALIB_WARNINGS_RESTORE
#define ALIB_ERROR(domain,...)
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_DCS_WITH(CS)
#define ALIB_ASSERT_ERROR(cond, domain,...)
@ CallbackExceptionFallThrough
@ NestedExpressionResultTypeError
@ CircularNestedExpressions
@ NamedExpressionNotFound
Compile-time exception thrown when an expression refers to an unknown named nested expression.
@ NestedExpressionNotFoundET
@ WhenEvaluatingNestedExpression
@ CircularNestedExpressionsInfo
LocalString< 512 > String512
Type alias name for TLocalString<character,512>.
NLocalString< 64 > NString64
Type alias name for TLocalString<nchar,64>.
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
LocalString< 128 > String128
Type alias name for TLocalString<character,128>.
lang::integer integer
Type alias in namespace alib.
strings::TString< nchar > NString
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
format::Paragraphs Paragraphs
Type alias in namespace alib.
format::Formatter Formatter
Type alias in namespace alib.
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.
expressions::ExpressionsCamp EXPRESSIONS
The singleton instance of ALib Camp class ExpressionsCamp.
boxing::FIsTrue FIsTrue
Type alias in namespace alib.
lang::uinteger uinteger
Type alias in namespace alib.
StdVectorMono< ExpressionVal * > NestedExpressions
Stack of nested expressions called during evaluation. Used to detect cyclic expressions.
VMMembers * EvalScopeVMMembers
The members used for the virtual machine. Available only with evaluation-time instances.
StdVectorMono< Box > * Stack
lang::DbgCriticalSections DCS
virtual ALIB_DLL void Reset()
Abstract syntax tree node representing binary operators.
Abstract syntax tree node representing ternary operator Q ? T : F.
Abstract syntax tree node representing a function call.
List< MonoAllocator, AST * > Arguments
The argument nodes.
Abstract syntax tree node representing identifiers.
Abstract syntax tree node representing identifiers.
Box Value
The value of the literal.
Abstract syntax tree node representing unary operators.
integer Position
Position in the original expression string.
static Scope * getExpressionCTScope(ExpressionVal &ev)
static ALIB_DLL AST * Decompile(Program &program, MonoAllocator &allocator)
static ALIB_DLL alib::Box Run(Program &program, Scope &scope)
static ALIB_DLL void run(Program &program, Scope &scope)
static ALIB_DLL AString DbgList(Program &program)
PC Distance
A distance to jump.
CallbackDecl Callback
A C++ callback function to invoke.
Program * NestedProgram
The nested virtual machine program to invoke.