15#define POS_IN_EXPR_STR (cmd.ExpressionPositions & ( (1UL << (bitsof(integer) / 2 - 1) ) -1 ) )
17# define NORMPOS_IN_EXPR_STR (cmd.ExpressionPositions >> (bitsof(integer)/2 ) )
32 run( program, scope );
39 scope.
Stack->pop_back();
48 auto& stack= *scope.
Stack;
52 for(
auto* nestedExpression : nestedExpressions )
53 if( nestedExpression == &program.
expression ) {
55 for(
auto it2= nestedExpressions.begin() ; it2!= nestedExpressions.end(); ++it2 )
58 it2 + 1 != nestedExpressions.end()
60 : nestedExpression->Name() );
64 nestedExpressions.emplace_back( &program.
expression );
67 for(
integer programCounter= 0; programCounter < program.
Length() ; ++ programCounter ) {
68 const Command& cmd= program.
At(programCounter);
88 "Result type mismatch during command execution:\n"
89 " In expression: \"{}\" {{{}}}\n"
91 " Identifier: {} ({})\n"
92 " Expected type: <{}> (aka {})\n"
93 " Result type: <{}> (aka {})\n"
94 " Result value: {}\n",
109 *(stack.end() - cmd.
QtyArgs() )=
124 case DCT::FunctionCall:
137 case DCT::OptimizationConstant:
138 ALIB_ERROR(
"EXPRVM",
"Must not be set with function calls")
140 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state." )
break;
147 fmt.
Format( msg,
"Result type mismatch during command execution:\n"
148 " In expression: {!Q} {{{}}}\n"
152 " Expected type: {!Q<>} (aka {})\n"
153 " Result type: {!Q<>} (aka {})\n"
154 " Result value: {}\n"
155 " Parameter values: ",
164 fmt.
Format( msg,
"({!Q'} {!Q<>}",
168 fmt.
Format( msg,
", {!Q'} {!Q<>}",
189 catch( std::exception& stdException )
197 stdException.what() );
206 if( !stack.back().Call<
FIsTrue>() )
223 String nestedExpressionName= (stack.end()-2)->Unbox<
String>();
235 stack.erase( stack.end() - 2 );
240 nestedExpressionName );
250 nestedExpressionName );
253 nestedExpressionName );
257 run( *
static_cast<Program*
>(nested.
Get()->GetProgram()), scope);
259 if( !(stack.end()-2)->IsSameType(stack.back()) ) {
261 nestedExpressionName,
269 stack.erase( stack.end()-3, stack.end() -1 );
278 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state." )
break;
285 nestedExpressions.pop_back();
290 "Internal error: Stack increased by {} (instead of 1) after run of expression program.",
291 stack.size() - initialStackSize )
295 "Wrong result type of program execution:\n"
296 " Expected Type: <{}> (aka {})\n"
297 " Result Type: <{}> (aka {})\n"
298 " Result value: {}\n"
299 " In expression: \"{}\""
314 #define PushNode(node) nodeStack.emplace_back( node )
315 #define PopNode nodeStack.pop_back()
316 #define Lhs (*(nodeStack.end() - 2) )
317 #define Rhs nodeStack.back()
318 #define Arg nodeStack.back()
320 std::vector<AST*> nodeStack;
322 std::stack <PC> conditionalStack;
328 integer positionInExpression= POS_IN_EXPR_STR;
340 for(
integer i= 0 ; i< 2 ; ++i ) {
349 positionInExpression ) );
357 positionInExpression );
360 positionInExpression );
417 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state.")
break;
422 while( !conditionalStack.empty() && conditionalStack.top() == pc ) {
423 AST* F= Arg; PopNode;
424 AST* T= Arg; PopNode;
426 conditionalStack.pop();
439 "VM AST generation error: NodeImpl stack must contain one element. Elements: {}",
442 "VM Program List error: Conditional stack after listing not 0 but {}",
443 conditionalStack.size())
445 return nodeStack.back();
457void writeArgPositions(
AString& target, std::vector<VirtualMachine::PC>& resultStack,
459 for(
integer argNo= qtyArgs ; argNo > 0 ; --argNo ) {
460 target << (argNo == qtyArgs ?
"" :
", ")
461 << (qtyArgs-argNo) <<
"{"
462 << (
integer(resultStack.size()) == argNo ? 0
463 : *(resultStack.end() - argNo - 1) + 1 )
464 <<
".." << *(resultStack.end() - argNo )
500 for(
int i= 0 ; i < 7 ; ++i ) {
501 hdlArgs[i+1]=
EXPRESSIONS.GetResource(hdlKeyNumbered << i );
512 #define FMT(qtyArgs) \
513 { if( cmd.DbgInfo.Plugin ) \
514 description << ", CP=\"" << cmd.DbgInfo.Plugin->Name<< '\"'; \
516 writeArgPositions(argpos,resultStack,qtyArgs); \
519 program.compiler.TypeName( cmd.ResultType ), \
525 NORMPOS_IN_EXPR_STR, "_^_" ); }
528 #define PushResult resultStack.emplace_back( pc )
529 #define PopResult resultStack.pop_back()
530 #define ResultPos resultStack.back()
532 std::vector<PC> resultStack; // The last command of the current results on the stack
533 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
534 // conditional term "Q : T : F". In other words, the
538 for( integer pc= 0 ; pc < program.Length() ; ++pc ) {
539 const Command& cmd= program.At(pc);
542 String128 description;
543 ALIB_ALLOW_BITWISE_SWITCH
544 ALIB_ALLOW_SPARSE_ENUM_SWITCH
545 switch( cmd.OpCode() ) {
546 case Command::OpCodes::Subroutine:
548 if( cmd.Parameter.NestedProgram == nullptr
549 || cmd.Parameter.NestedProgram == &program )
552 operation << ( cmd.Parameter.NestedProgram == nullptr ? "Expr(name, type)"
553 : "Expr(name, type, throw)" );
554 description << "Nested expr. searched at evaluation-time";
558 operation << cmd.DecompileSymbol
559 << "\"" << cmd.Parameter.NestedProgram->expression.Name() << '\"';
560 description << "Nested expr. searched at compile-time";
567 case Command::OpCodes::Constant:
570 char uetzelchen= cmd.ResultType.IsType<String>() ? '\"' : '\'';
571 operation << uetzelchen << cmd.ResultType << uetzelchen;
572 description << (cmd.TerminalType() == DCT::LiteralConstant ? "Literal constant"
573 : "Optimization constant" );
579 case Command::OpCodes::Function:
581 operation << cmd.DbgInfo.Callback
582 << "(#" << (cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs()) << ')';
584 NString descr= nullptr;
586 switch( cmd.TerminalType() ) {
588 descr = "Unary operator";
592 descr = "Binary operator";
595 case DCT::Identifier:
596 descr = "Identifier";
599 case DCT::FunctionCall:
600 if( cmd.QtyArgs() < 0 ) {
601 descr =
"Identifier";
605 description <<
"Function \"";
606 if( cmd.QtyArgs() == 0 )
607 description << cmd.DecompileSymbol <<
"()\"";
609 description << cmd.DecompileSymbol <<
"(#"
610 << cmd.QtyArgs() <<
")\"";
617 case DCT::OptimizationConstant:
618 ALIB_ERROR(
"EXPRVM",
"Must not be set with function calls")
620 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state.")
break;
622 if( descr.IsNotNull() )
623 description << descr <<
' ' << decSym << cmd.DecompileSymbol << decSym;
625 stackSize+= 1 - (cmd.QtyArgs() > 0 ? cmd.QtyArgs() : 0 );
626 FMT(cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs() )
627 for(
integer i= 0 ; i< cmd.QtyArgs() ; ++i )
635 operation << ( pc + cmd.Parameter.Distance ) <<
" (absolute)" ;
636 description <<
"'?'";
644 conditionalStack.emplace( pc + cmd.Parameter.Distance -1 );
645 operation << ( pc + cmd.Parameter.Distance ) <<
" (absolute)" ;
646 description <<
"':'";
652 default:
ALIB_ERROR(
"EXPR",
"Illegal switch state.") break;
658 while( !conditionalStack.empty() && conditionalStack.top() == pc ) {
662 conditionalStack.pop();
674 "VM Program List error: Stack size after listing not 1 but {}. Listing follows.\n",
675 stackSize, text.Buffer )
678 "VM Program List error: Resultstack after listing not 1 but {}. Listing follows.\n",
679 resultStack.size(), text.Buffer )
682 "VM Program List error: Conditional stack after listing not 0 but {}. Listing follows.\n",
683 conditionalStack.size(), text.Buffer )
686 return std::move(text.Buffer);
691#undef POS_IN_EXPR_STR
#define ALIB_ALLOW_SPARSE_ENUM_SWITCH
#define ALIB_CALLER_NULLED
#define ALIB_ERROR(domain,...)
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_POP_ALLOWANCE
#define ALIB_DCS_WITH(CS)
#define ALIB_ASSERT_ERROR(cond, domain,...)
#define ALIB_ALLOW_BITWISE_SWITCH
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
bool IsSameType(const Box &other) const
const std::type_info & TypeID() const
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
const Enum & Type() const
Compilation CfgCompilation
Compilation flags.
NString TypeName(Type box)
virtual Expression GetNamed(const String &name)
String CfgNestedExpressionThrowIdentifier
String CfgNestedExpressionOperator
String GetNormalizedString() const
String GetOriginalString() const
ExpressionVal & expression
The expression that this program evaluates.
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
@ CallbackExceptionFallThrough
@ NestedExpressionResultTypeError
@ CircularNestedExpressions
@ NamedExpressionNotFound
Compile-time exception thrown when an expression refers to an unknown named nested expression.
@ NestedExpressionNotFoundET
@ WhenEvaluatingNestedExpression
@ CircularNestedExpressionsInfo
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TString< nchar > NString
Type alias in namespace #"%alib".
format::Formatter Formatter
Type alias in namespace #"%alib".
lang::integer integer
Type alias in namespace #"%alib".
boxing::Box Box
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".
exceptions::Exception Exception
Type alias in namespace #"%alib".
LocalString< 128 > String128
Type alias name for #"TLocalString;TLocalString<character,128>".
boxing::FIsTrue FIsTrue
Type alias in namespace #"%alib".
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace #"%alib".
format::Paragraphs Paragraphs
Type alias in namespace #"%alib".
lang::uinteger uinteger
Type alias in namespace #"%alib".
NLocalString< 64 > NString64
Type alias name for #"TLocalString;TLocalString<nchar,64>".
LocalString< 512 > String512
Type alias name for #"TLocalString;TLocalString<character,512>".
TIntegral Integral() const
StdVectorMA< 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.
StdVectorMA< Box > * Stack
lang::DbgCriticalSections DCS
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.
ListMA< 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 AST * Decompile(Program &program, MonoAllocator &allocator)
static alib::Box Run(Program &program, Scope &scope)
static void run(Program &program, Scope &scope)
static 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.