ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
virtualmachine.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10#if !defined (HPP_ALIB_EXPRESSIONS_DETAIL_VIRTUAL_MACHINE)
12#endif
13
14#if !defined (HPP_ALIB_LANG_FORMAT_PARAGRAPHS)
16#endif
17
18#if !defined (HPP_ALIB_EXPRESSIONS_COMPILERPLUGIN)
20#endif
21
22#if !defined (HPP_ALIB_EXPRESSIONS_DETAIL_PROGRAM)
24#endif
25
26#if !defined (HPP_ALIB_EXPRESSIONS_DETAIL_AST)
28#endif
29# if !defined (HPP_ALIB_LANG_CAMP_INLINES)
31# endif
32#endif // !defined(ALIB_DOX)
33
34namespace alib { namespace expressions { namespace detail {
35
36
37VirtualMachine::Command::Command( Program* program, const Box& resultType, const String& functionOrOp,
38 integer idxOriginal, integer idxNormalized )
39: opcode ( OpCodes::Subroutine )
40, Operation ( program )
41, ResultType ( resultType )
42, ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
43 + static_cast<uinteger>(idxOriginal ) )
44, DecompileType ( DecompileInfoType::Subroutine )
45, DecompileSymbol ( functionOrOp )
46{}
47
48
49#define POS_IN_EXPR_STR (cmd.ExpressionPositions & ( (1UL << (bitsof(integer) / 2 - 1) ) -1 ) )
50#if ALIB_DEBUG
51# define NORMPOS_IN_EXPR_STR (cmd.ExpressionPositions >> (bitsof(integer)/2 ) )
52#endif
53
54// #################################################################################################
55// Run()
56// #################################################################################################
58{
59 // If the scope.Stack is empty, this indicates, that this is an 'external' call and not a
60 // subroutine.
61 scope.Reset();
62
63 // attach the compile-time scope to the evaluation scope.
64 scope.CTScope= program.expression.ctScope;
65
66 // run
67 run( program, scope );
68
69 // unset ctscope
70 scope.CTScope= nullptr;
71
72 // Remove top element from the stack and return its result.
73 Box result= scope.Stack.back();
74 scope.Stack.pop_back();
75 return result;
76}
77
78
79void VirtualMachine::run( Program& program, Scope& scope )
80{
81
83 ALIB_DBG( auto initialStackSize= scope.Stack.size(); )
84
85 auto& stack= scope.Stack;
86
87 // check circular calls
88 for( auto* nestedExpression : scope.NestedExpressions )
89 if( nestedExpression == &program.expression )
90 {
92 for( auto it2= scope.NestedExpressions.begin() ; it2!= scope.NestedExpressions.end(); ++it2 )
94 (*it2)->Name(),
95 it2 + 1 != scope.NestedExpressions.end()
96 ? (*(it2+1))->Name()
97 : nestedExpression->Name() );
98 throw e;
99 }
100
101 scope.NestedExpressions.emplace_back( &program.expression );
102
103
104 for( integer programCounter= 0; programCounter < program.Length() ; ++ programCounter )
105 {
106 const Command& cmd= program.At(programCounter);
108 switch( cmd.Which() )
109 {
111 stack.emplace_back( cmd.Operation.Value );
112
113 break;
114
116 {
117 try
118 {
119 // with no args, we need a new stack object
120 if( cmd.QtyFunctionArgs <= 0 )
121 {
122 stack.emplace_back( cmd.Operation.Callback( scope,
123 stack.end() ,
124 stack.end() ) );
125
126 ALIB_ASSERT_ERROR( cmd.ResultType.IsSameType(stack.back()), "EXPRVM",
127 "Result type mismatch during command execution:\n"
128 " In expression: {!Q} {{{}}}\n"
129 " Plugin: {}\n"
130 " Identifier: {} ({})\n"
131 " Expected type: {!Q<>} (aka {})\n"
132 " Result type: {!Q<>} (aka {})\n"
133 " Result value: {}\n",
134 program.expression.Name(),
136 cmd.DbgInfo.Plugin->Name,
138 program.compiler.TypeName( cmd.ResultType ), cmd.ResultType.TypeID(),
139 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
140 stack.back() )
141 }
142
143 // otherwise, we assign the value the position of the first arg in the stack and
144 // delete the other args after the call
145 else
146 {
147 ALIB_DBG( Box arg1Saved= *(stack.end() - static_cast<ptrdiff_t >( cmd.QtyFunctionArgs ) ); )
148
149 *(stack.end() - static_cast<ptrdiff_t>( cmd.QtyFunctionArgs ) )=
150 cmd.Operation.Callback( scope,
151 stack.end() - static_cast<ptrdiff_t>( cmd.QtyFunctionArgs ),
152 stack.end() );
153
154 #if ALIB_DEBUG
155 if( !cmd.ResultType.IsSameType(*(stack.end() - static_cast<ptrdiff_t>( cmd.QtyFunctionArgs ) )) )
156 {
157 String128 description;
158 switch( cmd.DecompileType )
159 {
160 case DCT::UnaryOp:
161 description << "Unary operator '" << cmd.DecompileSymbol << '\'';
162 break;
163 case DCT::BinaryOp:
164 description << "Binary operator '" << cmd.DecompileSymbol << '\'';
165 break;
166 case DCT::Function:
167 if( cmd.QtyFunctionArgs < 0 )
168 description << "Identifier \"" << cmd.DecompileSymbol << '\"';
169 else if( cmd.QtyFunctionArgs == 0 )
170 description << "Function \"" << cmd.DecompileSymbol << "()\"";
171 else
172 description << "Function \"" << cmd.DecompileSymbol << "(#"
173 << cmd.QtyFunctionArgs << ")\"";
174 break;
175 case DCT::AutoCast:
176 description << "Auto-cast" << cmd.DecompileSymbol << '\'';
177 break;
178 case DCT::LiteralConstant: ALIB_FALLTHROUGH
179 case DCT::OptimizationConstant:
180 ALIB_ERROR("EXPRVM", "Must not be set with function calls")
181 }
182
183 String512 msg;
185 fmt->Format( msg, "Result type mismatch during command execution:\n"
186 " In expression: {!Q} {{{}}}\n"
187 " Plugin: {}\n"
188 " Info: {}\n"
189 " Callback: {}\n"
190 " Expected type: {!Q<>} (aka {})\n"
191 " Result type: {!Q<>} (aka {})\n"
192 " Result value: {}\n"
193 " Parameter values: ",
194 program.expression.Name(),
196 cmd.DbgInfo.Plugin->Name,
197 description,
198 cmd.DbgInfo.Callback,
199 program.compiler.TypeName( cmd.ResultType ), cmd.ResultType.TypeID(),
200 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
201 stack.back() );
202 fmt->Format( msg, "({!Q'} {!Q<>}",
203 arg1Saved,
204 program.compiler.TypeName( arg1Saved ) );
205 for( integer i= cmd.QtyFunctionArgs - 1; i > 0 ; --i )
206 fmt->Format( msg, ", {!Q'} {!Q<>}",
207 *(stack.end() - i),
208 program.compiler.TypeName( *(stack.end()-i)) );
209 msg << ')';
210 fmt->Release();
211 ALIB_ERROR( "EXPRVM", msg )
212 }
213 #endif
214
215 for(integer i= 1; i < cmd.QtyFunctionArgs; ++i )
216 stack.pop_back();
217 }
218 }
219 catch( Exception& e )
220 {
222 {
224 program.expression.Name() );
226 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
227 }
228 throw;
229 }
230 catch( std::exception& stdException )
231 {
233 {
235 program.expression.Name() );
237 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
239 stdException.what() );
240 throw e;
241 }
242 throw;
243 }
244 }
245 break;
246
248 {
249 if( !stack.back().Call<FIsTrue>() )
250 programCounter+= cmd.Operation.Distance -1; //-1 due to loop increase
251 stack.pop_back();
252 }
253 break;
254
256 programCounter+= cmd.Operation.Distance - 1; //-1 due to loop increase
257 break;
258
259
261 // evaluation time defined nested expression
262 if( cmd.Operation.NestedProgram == nullptr
263 || cmd.Operation.NestedProgram == &program)
264 {
265 SPExpression nested;
266 String nestedExpressionName= (stack.end()-2)->Unbox<String>();
267 try
268 {
269 nested= program.compiler.GetNamed( nestedExpressionName );
270 }
271 catch( Exception& e )
272 {
273 // 3rd parameter "throw" was not given
274 if( cmd.Operation.NestedProgram == nullptr )
275 {
276 // not found? -> remove name parameter from stack and use result of
277 // second parameter.
278 if( e.Type().Integral() == UnderlyingIntegral( Exceptions::NamedExpressionNotFound ) )
279 {
280 stack.erase( stack.end() - 2 );
281 break;
282 }
283
285 nestedExpressionName );
287 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
288
289 throw;
290 }
291
292 // 3rd parameter "throw" was given
293 if( e.Type().Integral() == UnderlyingIntegral( Exceptions::NamedExpressionNotFound ) )
295 nestedExpressionName );
296 else
298 nestedExpressionName );
299 throw;
300 }
301
302 run( * dynamic_cast<Program*>(nested.get()->GetProgram()), scope);
303
304 if( !(stack.end()-2)->IsSameType(stack.back()) )
305 {
307 nestedExpressionName,
308 program.compiler.TypeName( *(stack.end()-2) ),
309 program.compiler.TypeName( stack.back() ) );
311 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
312 throw e;
313 }
314
315 stack.erase( stack.end()-3, stack.end() -1 );
316 }
317
318 // compile-time defined nested expression: just call it
319 else
320 run( *cmd.Operation.NestedProgram, scope );
321
322 break;
323 }
325
326 } // command loop
327
328 scope.NestedExpressions.pop_back();
329
330 // This assertion should never happen. It indicates rather a library error than an
331 // erroneous plug-in.
332 ALIB_ASSERT_ERROR( stack.size() == initialStackSize + 1, "EXPRVM",
333 "Internal error: Stack increased by {} (instead of 1) after run of expression program.",
334 stack.size() - initialStackSize )
335
336 // Usually a function did not return what it is defined to return.
337 ALIB_ASSERT_ERROR( program.ResultType().IsSameType(stack.back()), "EXPRVM",
338 "Wrong result type of program execution:\n"
339 " Expected Type: {!Q<>} (aka {})\n"
340 " Result Type: {!Q<>} (aka {})\n"
341 " Result value: {}\n"
342 " In expression: {!Q}"
343 ,
344 program.compiler.TypeName( program.ResultType() ), program.ResultType().TypeID(),
345 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
346 stack.back(),
347 program.expression.Name()
348 )
349}
350
351// #################################################################################################
352// Decompile()
353// #################################################################################################
355{
357
358 #define PushNode(node) nodeStack.emplace_back( node )
359 #define PopNode nodeStack.pop_back()
360 #define Lhs (*(nodeStack.end() - 2) )
361 #define Rhs nodeStack.back()
362 #define Arg nodeStack.back()
363
364 std::vector<AST*> nodeStack;
365
366 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
367 // conditional term "Q : T : F". In other words, the
368 // end of 'F'
369
370 for( integer pc= 0 ; pc < program.Length() ; ++pc )
371 {
372 const Command& cmd= program.At(pc);
373 integer positionInExpression= POS_IN_EXPR_STR;
374
376 switch( cmd.Which() )
377 {
379 {
380 // Function "Expression(name, type, boolean)"
381 if( cmd.Operation.NestedProgram == nullptr
382 || cmd.Operation.NestedProgram == & program )
383 {
384 ASTFunction* node= allocator.Emplace<ASTFunction>( cmd.DecompileSymbol, positionInExpression, allocator );
385 for( integer i= 0 ; i< 2 ; ++i )
386 {
387 node->Arguments.Emplace( node->Arguments.begin(), Arg );
388 PopNode;
389 }
390
391 // if nullptr, third parameter "throw"
392 if( cmd.Operation.NestedProgram != nullptr )
393 node->Arguments.EmplaceBack(
395 positionInExpression ) );
396
397 PushNode(node);
398 break;
399 }
400
401 // constant call (program was given)
403 positionInExpression );
405 name,
406 positionInExpression );
407 PushNode( nested );
408 }
409 break;
410
412 {
413 ASTLiteral* node= allocator.Emplace<ASTLiteral>( static_cast<integer>(0), positionInExpression );
414 node->Value= cmd.Operation.Value;
415 PushNode(node);
416 }
417 break;
418
420 {
421 if( cmd.DecompileType == DCT::UnaryOp )
422 {
423 ASTUnaryOp* node= allocator.Emplace<ASTUnaryOp>( cmd.DecompileSymbol, Arg, positionInExpression );
424 PopNode;
425 PushNode(node);
426 break;
427 }
428
429 if( cmd.DecompileType == DCT::BinaryOp )
430 {
431 ASTBinaryOp* node= allocator.Emplace<ASTBinaryOp>( cmd.DecompileSymbol, Lhs, Rhs, positionInExpression );
432 PopNode;
433 PopNode;
434 PushNode(node);
435 break;
436 }
437
438 if( cmd.QtyFunctionArgs < 0 )
439 {
440 ASTIdentifier* node= allocator.Emplace<ASTIdentifier>( cmd.DecompileSymbol, positionInExpression );
441 PushNode(node);
442 break;
443 }
444
445 ASTFunction* node= allocator.Emplace<ASTFunction>( cmd.DecompileSymbol, positionInExpression, allocator );
446 for( integer i= 0 ; i< cmd.QtyFunctionArgs ; ++i )
447 {
448 node->Arguments.Emplace( node->Arguments.begin(), Arg );
449 PopNode;
450 }
451
452 PushNode(node);
453 }
454 break;
455
457 {
458 }
459 break;
460
461 case Command::OpCodes::Jump: // ':'
462 {
463 conditionalStack.emplace( pc + cmd.Operation.Distance -1 );
464 }
465 break;
466
467 }
469
470 while( !conditionalStack.empty() && conditionalStack.top() == pc )
471 {
472 AST* F= Arg; PopNode;
473 AST* T= Arg; PopNode; // F-Pos -2 is a little vague. But we don't care!
474 Arg= allocator.Emplace<ASTConditional>( Arg, T, F, positionInExpression, F->Position - 2 );
475 conditionalStack.pop();
476 }
477
478
479 } // command loop
480
481 #undef PushNode
482 #undef PopNode
483 #undef Lhs
484 #undef Rhs
485 #undef Arg
486
487 ALIB_ASSERT_ERROR( nodeStack.size() == 1, "EXPRVM",
488 "VM AST generation error: NodeImpl stack must contain one element. Elements: {}", nodeStack.size())
489 ALIB_ASSERT_ERROR( conditionalStack.size() == 0, "EXPRVM",
490 "VM Program List error: Conditional stack after listing not 0 but {}", conditionalStack.size())
491
492 return nodeStack.back();
493}
494
495
496
497// #################################################################################################
498// DbgList()
499// #################################################################################################
500#if ALIB_DEBUG
501
502//! @cond NO_DOX
503namespace{
504void writeArgPositions(AString& target, std::vector<VirtualMachine::PC>& resultStack, integer qtyArgs )
505{
506 for( integer argNo= qtyArgs ; argNo > 0 ; --argNo )
507 {
508 target << (argNo == qtyArgs ? "" : ", ")
509 << (qtyArgs-argNo) << "{"
510 << ( static_cast<integer>(resultStack.size()) == argNo ? 0
511 : *(resultStack.end() - argNo - 1) + 1 )
512 << ".." << *(resultStack.end() - argNo )
513 << "}";
514 }
515}
516}
517//! @endcond
518
519
521{
523
524 String fmtLine= EXPRESSIONS.GetResource( "ProgListLine" );
525 String fmtHeader= EXPRESSIONS.GetResource( "ProgListHeader");
526
527 Paragraphs text;
528 text.LineWidth=0;
529 text.Formatter= program.expression.ctScope->Formatter;
530 text.Formatter->Acquire( ALIB_CALLER_PRUNED ); // get formatter once to keep autosizes!
531
532 // repeat the whole output until its size is stable and all auto-tabs are set
533 integer lastLineWidth = 0;
534 while(lastLineWidth == 0 || lastLineWidth != text.DetectedMaxLineWidth)
535 {
536 lastLineWidth= text.DetectedMaxLineWidth;
537 text.Buffer.Reset();
538
539 // write headline
541 text.AddMarked( fmtHeader,
542 program.expression.Name(),
544
545
546 text.LineWidth= 0;
547 NString hdlKey= "ProgListHdl";
548
550 Box hdlArgs[10];
551 hdlArgs[0]= fmtLine;
552 NString64 hdlKeyNumbered(hdlKey);
553 for( int i= 0 ; i < 7 ; ++i )
554 {
555 hdlArgs[i+1]= EXPRESSIONS.GetResource(hdlKeyNumbered << i );
556 hdlKeyNumbered.ShortenTo( hdlKey.Length() );
557 }
558
559 hdlArgs[8]= 1;
560 hdlArgs[9]= program.expression.GetNormalizedString();
561 text.AddMarked( hdlArgs );
563 text.AddMarked("@HL-");
564 text.LineWidth= 0;
566
567
568 #define FMT(qtyArgs) \
569 { if( cmd.DbgInfo.Plugin ) description << ", CP=\"" << cmd.DbgInfo.Plugin->Name<< '\"'; \
570 String256 argpos; writeArgPositions(argpos,resultStack,qtyArgs); \
571 text.Add( fmtLine, \
572 pc, \
573 program.compiler.TypeName( cmd.ResultType ), \
574 cmd.Which(), \
575 operation, \
576 stackSize, \
577 description, \
578 argpos, \
579 NORMPOS_IN_EXPR_STR, "_^_" ); }
580
581
582 #define PushResult resultStack.emplace_back( pc )
583 #define PopResult resultStack.pop_back()
584 #define ResultPos resultStack.back()
585
586 std::vector<PC> resultStack; // The last command of the current results on the stack
587 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
588 // conditional term "Q : T : F". In other words, the
589 // end of 'F'
590
591 PC stackSize = 0;
592 for( integer pc= 0 ; pc < program.Length() ; ++pc )
593 {
594 const Command& cmd= program.At(pc);
595
596 String128 operation;
597 String128 description;
598 ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
599 switch( cmd.Which() )
600 {
601 case Command::OpCodes::Subroutine:
602 {
603 if( cmd.Operation.NestedProgram == nullptr
604 || cmd.Operation.NestedProgram == &program )
605 {
606 --stackSize;
607 operation << ( cmd.Operation.NestedProgram == nullptr ? "Expr(name, type)"
608 : "Expr(name, type, throw)" );
609 description << "Nested expr. searched at evaluation-time";
610 PopResult;
611 }
612 else
613 {
614 ++stackSize;
615 operation << cmd.DecompileSymbol
616 << "\"" << cmd.Operation.NestedProgram->expression.Name() << '\"';
617 description << "Nested expr. searched at compile-time";
618 PushResult;
619 }
620 FMT(0)
621 }
622 break;
623
624 case Command::OpCodes::Constant:
625 {
626 ++stackSize;
627 char uetzelchen= cmd.Operation.Value.IsType<String>() ? '\"' : '\'';
628 operation << uetzelchen << cmd.Operation.Value << uetzelchen;
629 description << (cmd.DecompileType == DCT::LiteralConstant ? "Literal constant"
630 : "Optimization constant" );
631 PushResult;
632 FMT(0)
633 }
634 break;
635
636 case Command::OpCodes::Function:
637 {
638 operation << cmd.DbgInfo.Callback
639 << "(#" << (cmd.QtyFunctionArgs < 0 ? 0 : cmd.QtyFunctionArgs) << ')';
640
641 NString descr= nullptr;
642 char decSym= '\0';
643 switch( cmd.DecompileType )
644 {
645 case DCT::UnaryOp:
646 descr = "Unary operator";
647 decSym= '\'';
648 break;
649 case DCT::BinaryOp:
650 descr = "Binary operator";
651 decSym= '\'';
652 break;
653 case DCT::Function:
654 if( cmd.QtyFunctionArgs < 0 )
655 {
656 descr = "Identifier";
657 decSym= '"';
658 break;
659 }
660 description << "Function \"";
661 if( cmd.QtyFunctionArgs == 0 )
662 description << cmd.DecompileSymbol << "()\"";
663 else
664 description << cmd.DecompileSymbol << "(#"
665 << cmd.QtyFunctionArgs << ")\"";
666 break;
667 case DCT::AutoCast:
668 descr = "Auto-cast";
669 decSym= '\'';
670 break;
671 case DCT::LiteralConstant: ALIB_FALLTHROUGH
672 case DCT::OptimizationConstant:
673 ALIB_ERROR("EXPRVM", "Must not be set with function calls")
674 }
675 if( descr.IsNotNull() )
676 description << descr << ' ' << decSym << cmd.DecompileSymbol << decSym;
677
678 stackSize+= 1 - (cmd.QtyFunctionArgs > 0 ? cmd.QtyFunctionArgs : 0 );
679 FMT(cmd.QtyFunctionArgs < 0 ? 0 : cmd.QtyFunctionArgs)
680 for( integer i= 0 ; i< cmd.QtyFunctionArgs ; ++i )
681 PopResult;
682 PushResult;
683 }
684 break;
685
686 case Command::OpCodes::JumpIfFalse: // '?'
687 {
688 operation << ( pc + cmd.Operation.Distance ) << " (absolute)" ;
689 description << "'?'";
690 FMT( 1 ) // first print Q
691 ++ResultPos; // then have jump be included in T
692 }
693 break;
694
695 case Command::OpCodes::Jump: // ':'
696 {
697 conditionalStack.emplace( pc + cmd.Operation.Distance -1 );
698 operation << ( pc + cmd.Operation.Distance ) << " (absolute)" ;
699 description << "':'";
700 FMT( 1 ) // first print T
701 ++ResultPos; // then have jump be included in T
702 }
703 break;
704
705 }
707
708
709 while( !conditionalStack.empty() && conditionalStack.top() == pc )
710 {
711 PopResult;
712 PopResult;
713 ResultPos= pc;
714 conditionalStack.pop();
715 stackSize-= 2;
716 }
717
718 } // command loop
719
720
721 #undef PushResult
722 #undef PopResult
723 #undef ResultPos
724
725 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || stackSize == 1, "EXPRVM",
726 "VM Program List error: Stack size after listing not 1 but {}. Listing follows.\n",
727 stackSize, text.Buffer )
728
729 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || resultStack.size() == 1, "EXPRVM",
730 "VM Program List error: Resultstack after listing not 1 but {}. Listing follows.\n",
731 resultStack.size(), text.Buffer )
732
733 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || conditionalStack.size() == 0, "EXPRVM",
734 "VM Program List error: Conditional stack after listing not 0 but {}.Listing follows.\n",
735 conditionalStack, text.Buffer )
736 } // main loop
737
738 text.Formatter->Release();
739
740 return std::move(text.Buffer);
741}
742#endif
743
744
745#undef POS_IN_EXPR_STR
746#undef PushResult
747#undef PopResult
748#undef ResultPos
749#undef FMT
750#undef PushNode
751#undef PopNode
752#undef Lhs
753#undef Rhs
754#undef Arg
755
756}}} // namespace [alib::expressions::detail]
bool IsSameType(const Box &other) const
Definition box.inl:761
const std::type_info & TypeID() const
Definition box.inl:902
virtual ALIB_API SPExpression GetNamed(const String &name)
Definition compiler.cpp:389
ALIB_API NString TypeName(Type box)
Definition compiler.cpp:432
ALIB_API const Box & ResultType() const
Definition program.cpp:55
VM::Command & At(VM::PC pc)
Definition program.hpp:221
@ JumpIfFalse
Jumps if top of the stack indicates false.
Command(const Box &value, bool isOptimization, integer idxOriginal, integer idxNormalized)
static ALIB_API void run(Program &program, Scope &scope)
static ALIB_API alib::Box Run(Program &program, Scope &scope)
static ALIB_API AString DbgList(Program &program)
static ALIB_API AST * Decompile(Program &program, MonoAllocator &allocator)
const String & GetResource(const NString &name)
ALIB_API const Enum & Type() const
Exception & Add(const NCString &file, int line, const NCString &func, TEnum type, TArgs &&... args)
static SPFormatter AcquireDefault(const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
ALIB_API void AddMarked(Boxes &args)
ALIB_FORCE_INLINE T * Emplace(TArgs &&... args)
strings::TString< TChar > EmplaceString(const strings::TString< TChar > &src)
TAString & ShortenTo(integer newLength)
Definition astring.hpp:908
constexpr integer Length() const
Definition string.hpp:357
#define bitsof(type)
Definition bits.hpp:52
#define ALIB_FALLTHROUGH
Definition alib.hpp:718
#define ALIB_CALLER_NULLED
Definition alib.hpp:846
#define ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
Definition alib.hpp:674
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_ERROR(...)
Definition alib.hpp:980
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_DBG(...)
Definition alib.hpp:457
#define ALIB_CALLER_PRUNED
Definition alib.hpp:845
std::shared_ptr< Expression > SPExpression
@ NamedExpressionNotFound
Compile-time exception thrown when an expression refers to an unknown named nested expression.
Definition alib.cpp:57
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:289
expressions::Expressions EXPRESSIONS
monomem::List< T, TRecycling > List
Type alias in namespace alib.
Definition list.hpp:829
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
integer Integral() const
Definition enum.hpp:123
virtual ALIB_API void Reset()
Definition compiler.cpp:67
SPFormatter Formatter
Definition scope.hpp:139
std::vector< alib::Box > Stack
Definition scope.hpp:108
std::vector< Expression *, StdContMA< Expression * > > NestedExpressions
Definition scope.hpp:111
List< AST * > Arguments
The argument nodes.
Definition ast.hpp:205
Box Value
The value of the literal.
Definition ast.hpp:105
const char * Callback
The native C++ name of the callback function.
CompilerPlugin * Plugin
The plug-in that provided the callback or constant.
Program * NestedProgram
The nested virtual machine program to invoke.
CallbackDecl Callback
A C++ callback function to invoke.