ALib C++ Library
Library Version: 2412 R0
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 !DOXYGEN
16#endif // !DOXYGEN
17
20
21namespace alib { namespace expressions { namespace detail {
22
23
24VirtualMachine::Command::Command( Program* program, const Box& resultType, const String& functionOrOp,
25 integer idxOriginal, integer idxNormalized )
26: bits ( int16_t(OpCodes::Subroutine) | int16_t(ListingTypes::NestedExpression) )
27, Parameter ( program )
28, ResultType ( resultType )
29, ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
30 + static_cast<uinteger>(idxOriginal ) )
31, DecompileSymbol ( functionOrOp )
32{}
33
34
35#define POS_IN_EXPR_STR (cmd.ExpressionPositions & ( (1UL << (bitsof(integer) / 2 - 1) ) -1 ) )
36#if ALIB_DEBUG
37# define NORMPOS_IN_EXPR_STR (cmd.ExpressionPositions >> (bitsof(integer)/2 ) )
38#endif
39
40// #################################################################################################
41// Run()
42// #################################################################################################
44{ALIB_DCS_WITH(scope.dcs)
45 // If the scope.Stack is empty, this indicates, that this is an 'external' call and not a
46 // subroutine.
47 scope.reset();
48
49 // attach the compile-time scope to the evaluation scope.
50 scope.vmMembers->CTScope= program.expression.ctScope;
51
52 // run
53 run( program, scope );
54
55 // detach ct-scope
56 scope.vmMembers->CTScope= nullptr;
57
58 // Remove top element from the stack and return its result.
59 Box result= scope.Stack->back();
60 scope.Stack->pop_back();
61 return result;
62}
63
64void VirtualMachine::run( Program& program, Scope& scope )
65{ALIB_DCS_WITH(scope.dcs)
66
67 ALIB_DBG( using DCT= Command::ListingTypes; )
68 ALIB_DBG( auto initialStackSize= scope.Stack->size(); )
69
70 auto& stack= *scope.Stack;
71
72 // check circular calls
73 auto& nestedExpressions= scope.vmMembers->NestedExpressions;
74 for( auto* nestedExpression : nestedExpressions )
75 if( nestedExpression == &program.expression )
76 {
78 for( auto it2= nestedExpressions.begin() ; it2!= nestedExpressions.end(); ++it2 )
80 (*it2)->Name(),
81 it2 + 1 != nestedExpressions.end()
82 ? (*(it2+1))->Name()
83 : nestedExpression->Name() );
84 throw e;
85 }
86
87 nestedExpressions.emplace_back( &program.expression );
88
89
90 for( integer programCounter= 0; programCounter < program.Length() ; ++ programCounter )
91 {
92 const Command& cmd= program.At(programCounter);
95 switch( cmd.OpCode() )
96 {
98 stack.emplace_back( cmd.ResultType );
99
100 break;
101
103 {
104 try
105 {
106 // with no args, we need a new stack object
107 if( cmd.HasArgs() )
108 {
109 stack.emplace_back( cmd.Parameter.Callback( scope,
110 stack.end() ,
111 stack.end() ) );
112
113 ALIB_ASSERT_ERROR( cmd.ResultType.IsSameType(stack.back()), "EXPRVM",
114 "Result type mismatch during command execution:\n"
115 " In expression: {!Q} {{{}}}\n"
116 " Plugin: {}\n"
117 " Identifier: {} ({})\n"
118 " Expected type: {!Q<>} (aka {})\n"
119 " Result type: {!Q<>} (aka {})\n"
120 " Result value: {}\n",
121 program.expression.Name(),
123 cmd.DbgInfo.Plugin->Name,
125 program.compiler.TypeName( cmd.ResultType ), cmd.ResultType.TypeID(),
126 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
127 stack.back() )
128 }
129
130 // otherwise, we assign the position to the value of the first arg in the stack and
131 // delete the other args after the call
132 else
133 {
134 ALIB_DBG( Box arg1Saved= *(stack.end() - cmd.QtyArgs() ); )
135
136 *(stack.end() - cmd.QtyArgs() )=
137 cmd.Parameter.Callback( scope,
138 stack.end() - cmd.QtyArgs(),
139 stack.end() );
140
141 #if ALIB_DEBUG
142 if( !cmd.ResultType.IsSameType(*(stack.end() - cmd.QtyArgs() )) )
143 {
144 String128 description;
145 switch( cmd.TerminalType() )
146 {
147 case DCT::UnaryOp:
148 description << "Unary operator '" << cmd.DecompileSymbol << '\'';
149 break;
150 case DCT::BinaryOp:
151 description << "Binary operator '" << cmd.DecompileSymbol << '\'';
152 break;
153 case DCT::FunctionCall:
154 if( cmd.QtyArgs() < 0 )
155 description << "Identifier \"" << cmd.DecompileSymbol << '\"';
156 else if( cmd.QtyArgs() == 0 )
157 description << "Function \"" << cmd.DecompileSymbol << "()\"";
158 else
159 description << "Function \"" << cmd.DecompileSymbol << "(#"
160 << cmd.QtyArgs() << ")\"";
161 break;
162 case DCT::AutoCast:
163 description << "Auto-cast" << cmd.DecompileSymbol << '\'';
164 break;
165 case DCT::LiteralConstant: ALIB_FALLTHROUGH
166 case DCT::OptimizationConstant:
167 ALIB_ERROR("EXPRVM", "Must not be set with function calls")
168 break;
169 default: ALIB_ERROR("Illegal switch state.") break;
170 }
171
172 String512 msg;
175 fmt.GetArgContainer();
176 fmt.Format( msg, "Result type mismatch during command execution:\n"
177 " In expression: {!Q} {{{}}}\n"
178 " Plugin: {}\n"
179 " Info: {}\n"
180 " Callback: {}\n"
181 " Expected type: {!Q<>} (aka {})\n"
182 " Result type: {!Q<>} (aka {})\n"
183 " Result value: {}\n"
184 " Parameter values: ",
185 program.expression.Name(),
187 cmd.DbgInfo.Plugin->Name,
188 description,
189 cmd.DbgInfo.Callback,
190 program.compiler.TypeName( cmd.ResultType ), cmd.ResultType.TypeID(),
191 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
192 stack.back() );
193 fmt.Format( msg, "({!Q'} {!Q<>}",
194 arg1Saved,
195 program.compiler.TypeName( arg1Saved ) );
196 for( integer i= cmd.QtyArgs() - 1; i > 0 ; --i )
197 fmt.Format( msg, ", {!Q'} {!Q<>}",
198 *(stack.end() - i),
199 program.compiler.TypeName( *(stack.end()-i)) );
200 msg << ')';
201 ALIB_ERROR( "EXPRVM", msg )
202 }
203 #endif
204
205 for(integer i= 1; i < cmd.QtyArgs(); ++i )
206 stack.pop_back();
207 }
208 }
209 catch( Exception& e )
210 {
212 {
214 program.expression.Name() );
216 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
217 }
218 throw;
219 }
220 catch( std::exception& stdException )
221 {
223 {
225 program.expression.Name() );
227 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
229 stdException.what() );
230 throw e;
231 }
232 throw;
233 }
234 }
235 break;
236
238 {
239 if( !stack.back().Call<FIsTrue>() )
240 programCounter+= cmd.Parameter.Distance -1; //-1 due to loop increase
241 stack.pop_back();
242 }
243 break;
244
246 programCounter+= cmd.Parameter.Distance - 1; //-1 due to loop increase
247 break;
248
249
251 // evaluation time defined nested expression
252 if( cmd.Parameter.NestedProgram == nullptr
253 || cmd.Parameter.NestedProgram == &program)
254 {
255 Expression nested;
256 String nestedExpressionName= (stack.end()-2)->Unbox<String>();
257 try
258 {
259 nested= program.compiler.GetNamed( nestedExpressionName );
260 }
261 catch( Exception& e )
262 {
263 // 3rd parameter "throw" was not given
264 if( cmd.Parameter.NestedProgram == nullptr )
265 {
266 // not found? -> remove name parameter from stack and use result of
267 // second parameter.
268 if( e.Type().Integral() == UnderlyingIntegral( Exceptions::NamedExpressionNotFound ) )
269 {
270 stack.erase( stack.end() - 2 );
271 break;
272 }
273
275 nestedExpressionName );
277 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
278
279 throw;
280 }
281
282 // 3rd parameter "throw" was given
283 if( e.Type().Integral() == UnderlyingIntegral( Exceptions::NamedExpressionNotFound ) )
285 nestedExpressionName );
286 else
288 nestedExpressionName );
289 throw;
290 }
291
292 run( * dynamic_cast<Program*>(nested.Get()->GetProgram()), scope);
293
294 if( !(stack.end()-2)->IsSameType(stack.back()) )
295 {
297 nestedExpressionName,
298 program.compiler.TypeName( *(stack.end()-2) ),
299 program.compiler.TypeName( stack.back() ) );
301 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
302 throw e;
303 }
304
305 stack.erase( stack.end()-3, stack.end() -1 );
306 }
307
308 // compile-time defined nested expression: just call it
309 else
310 run( *cmd.Parameter.NestedProgram, scope );
311
312 break;
313
314 default: ALIB_ERROR("Illegal switch state.") break;
315 }
318
319 } // command loop
320
321 nestedExpressions.pop_back();
322
323 // This assertion should never happen. It indicates rather a library error than an
324 // erroneous plug-in.
325 ALIB_ASSERT_ERROR( stack.size() == initialStackSize + 1, "EXPRVM",
326 "Internal error: Stack increased by {} (instead of 1) after run of expression program.",
327 stack.size() - initialStackSize )
328
329 // Usually a function did not return what it is defined to return.
330 ALIB_ASSERT_ERROR( program.ResultType().IsSameType(stack.back()), "EXPRVM",
331 "Wrong result type of program execution:\n"
332 " Expected Type: {!Q<>} (aka {})\n"
333 " Result Type: {!Q<>} (aka {})\n"
334 " Result value: {}\n"
335 " In expression: {!Q}"
336 ,
337 program.compiler.TypeName( program.ResultType() ), program.ResultType().TypeID(),
338 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
339 stack.back(),
340 program.expression.Name()
341 )
342}
343
344// #################################################################################################
345// Decompile()
346// #################################################################################################
348{
349 using DCT= Command::ListingTypes;
350
351 #define PushNode(node) nodeStack.emplace_back( node )
352 #define PopNode nodeStack.pop_back()
353 #define Lhs (*(nodeStack.end() - 2) )
354 #define Rhs nodeStack.back()
355 #define Arg nodeStack.back()
356
357 std::vector<AST*> nodeStack;
358
359 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
360 // conditional term "Q : T : F". In other words, the
361 // end of 'F'
362
363 for( integer pc= 0 ; pc < program.Length() ; ++pc )
364 {
365 const Command& cmd= program.At(pc);
366 integer positionInExpression= POS_IN_EXPR_STR;
367
370 switch( cmd.OpCode() )
371 {
373 {
374 // Function "Expression(name, type, boolean)"
375 if( cmd.Parameter.NestedProgram == nullptr
376 || cmd.Parameter.NestedProgram == & program )
377 {
378 ASTFunction* node= allocator().New<ASTFunction>(cmd.DecompileSymbol, positionInExpression, allocator );
379 for( integer i= 0 ; i< 2 ; ++i )
380 {
381 node->Arguments.Emplace( node->Arguments.begin(), Arg );
382 PopNode;
383 }
384
385 // if nullptr, third parameter "throw"
386 if( cmd.Parameter.NestedProgram != nullptr )
387 node->Arguments.EmplaceBack(
388 allocator().New<ASTIdentifier>( String(allocator, program.compiler.CfgNestedExpressionThrowIdentifier),
389 positionInExpression ) );
390
391 PushNode(node);
392 break;
393 }
394
395 // constant call (program was given)
396 ASTIdentifier* name = allocator().New<ASTIdentifier>(String( allocator, cmd.Parameter.NestedProgram->expression.Name() ),
397 positionInExpression );
398 ASTUnaryOp* nested= allocator().New<ASTUnaryOp>( program.compiler.CfgNestedExpressionOperator,
399 name,
400 positionInExpression );
401 PushNode( nested );
402 }
403 break;
404
406 {
407 ASTLiteral* node= allocator().New<ASTLiteral>( static_cast<integer>(0), positionInExpression );
408 node->Value= cmd.ResultType;
409 PushNode(node);
410 }
411 break;
412
414 {
415 if( cmd.TerminalType() == DCT::UnaryOp )
416 {
417 ASTUnaryOp* node= allocator().New<ASTUnaryOp>(cmd.DecompileSymbol, Arg, positionInExpression );
418 PopNode;
419 PushNode(node);
420 break;
421 }
422
423 if( cmd.TerminalType() == DCT::BinaryOp )
424 {
425 ASTBinaryOp* node= allocator().New<ASTBinaryOp>(cmd.DecompileSymbol, Lhs, Rhs, positionInExpression );
426 PopNode;
427 PopNode;
428 PushNode(node);
429 break;
430 }
431
432 if( cmd.QtyArgs() < 0 )
433 {
434 ASTIdentifier* node= allocator().New<ASTIdentifier>(cmd.DecompileSymbol, positionInExpression );
435 PushNode(node);
436 break;
437 }
438
439 ASTFunction* node= allocator().New<ASTFunction>(cmd.DecompileSymbol, positionInExpression, allocator );
440 for( integer i= 0 ; i< cmd.QtyArgs() ; ++i )
441 {
442 node->Arguments.Emplace( node->Arguments.begin(), Arg );
443 PopNode;
444 }
445
446 PushNode(node);
447 }
448 break;
449
451 {
452 }
453 break;
454
455 case Command::OpCodes::Jump: // ':'
456 {
457 conditionalStack.emplace( pc + cmd.Parameter.Distance -1 );
458 }
459 break;
460
461 default: ALIB_ERROR("Illegal switch state.") break;
462 }
465
466 while( !conditionalStack.empty() && conditionalStack.top() == pc )
467 {
468 AST* F= Arg; PopNode;
469 AST* T= Arg; PopNode; // F-Pos -2 is a little vague. But we don't care!
470 Arg= allocator().New<ASTConditional>(Arg, T, F, positionInExpression, F->Position - 2 );
471 conditionalStack.pop();
472 }
473
474
475 } // command loop
476
477 #undef PushNode
478 #undef PopNode
479 #undef Lhs
480 #undef Rhs
481 #undef Arg
482
483 ALIB_ASSERT_ERROR( nodeStack.size() == 1, "EXPRVM",
484 "VM AST generation error: NodeImpl stack must contain one element. Elements: {}", nodeStack.size())
485 ALIB_ASSERT_ERROR( conditionalStack.size() == 0, "EXPRVM",
486 "VM Program List error: Conditional stack after listing not 0 but {}", conditionalStack.size())
487
488 return nodeStack.back();
489}
490
491
492
493// #################################################################################################
494// DbgList()
495// #################################################################################################
496#if ALIB_DEBUG
497
498//! @cond NO_DOX
499namespace{
500void writeArgPositions(AString& target, std::vector<VirtualMachine::PC>& resultStack, integer qtyArgs )
501{
502 for( integer argNo= qtyArgs ; argNo > 0 ; --argNo )
503 {
504 target << (argNo == qtyArgs ? "" : ", ")
505 << (qtyArgs-argNo) << "{"
506 << ( static_cast<integer>(resultStack.size()) == argNo ? 0
507 : *(resultStack.end() - argNo - 1) + 1 )
508 << ".." << *(resultStack.end() - argNo )
509 << "}";
510 }
511}
512}
513//! @endcond
514
515
517{
518 using DCT= Command::ListingTypes;
519
520 String fmtLine= EXPRESSIONS.GetResource( "ProgListLine" );
521 String fmtHeader= EXPRESSIONS.GetResource( "ProgListHeader");
522
523 Paragraphs text;
524 text.LineWidth=0;
525 text.Formatter= program.expression.ctScope->Formatter;
526 text.Formatter->Reset(); // reset autosizes
527
528 // repeat the whole output until its size is stable and all auto-tabs are set
529 integer lastLineWidth = 0;
530 while(lastLineWidth == 0 || lastLineWidth != text.DetectedMaxLineWidth)
531 {
532 lastLineWidth= text.DetectedMaxLineWidth;
533 text.Buffer.Reset();
534
535 // write headline
537 text.AddMarked( fmtHeader,
538 program.expression.Name(),
540
541
542 text.LineWidth= 0;
543 NString hdlKey= "ProgListHdl";
544
546 Box hdlArgs[10];
547 hdlArgs[0]= fmtLine;
548 NString64 hdlKeyNumbered(hdlKey);
549 for( int i= 0 ; i < 7 ; ++i )
550 {
551 hdlArgs[i+1]= EXPRESSIONS.GetResource(hdlKeyNumbered << i );
552 hdlKeyNumbered.ShortenTo( hdlKey.Length() );
553 }
554
555 hdlArgs[8]= 1;
556 hdlArgs[9]= program.expression.GetNormalizedString();
557 text.AddMarked( hdlArgs );
559 text.AddMarked("@HL-");
560 text.LineWidth= 0;
562
563
564 #define FMT(qtyArgs) \
565 { if( cmd.DbgInfo.Plugin ) \
566 description << ", CP=\"" << cmd.DbgInfo.Plugin->Name<< '\"'; \
567 String256 argpos; \
568 writeArgPositions(argpos,resultStack,qtyArgs); \
569 text.Add( fmtLine, \
570 pc, \
571 program.compiler.TypeName( cmd.ResultType ), \
572 cmd.OpCode(), \
573 operation, \
574 stackSize, \
575 description, \
576 argpos, \
577 NORMPOS_IN_EXPR_STR, "_^_" ); }
578
579
580 #define PushResult resultStack.emplace_back( pc )
581 #define PopResult resultStack.pop_back()
582 #define ResultPos resultStack.back()
583
584 std::vector<PC> resultStack; // The last command of the current results on the stack
585 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
586 // conditional term "Q : T : F". In other words, the
587 // end of 'F'
588
589 PC stackSize = 0;
590 for( integer pc= 0 ; pc < program.Length() ; ++pc )
591 {
592 const Command& cmd= program.At(pc);
593
594 String128 operation;
595 String128 description;
596 ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
597 ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
598 switch( cmd.OpCode() )
599 {
600 case Command::OpCodes::Subroutine:
601 {
602 if( cmd.Parameter.NestedProgram == nullptr
603 || cmd.Parameter.NestedProgram == &program )
604 {
605 --stackSize;
606 operation << ( cmd.Parameter.NestedProgram == nullptr ? "Expr(name, type)"
607 : "Expr(name, type, throw)" );
608 description << "Nested expr. searched at evaluation-time";
609 PopResult;
610 }
611 else
612 {
613 ++stackSize;
614 operation << cmd.DecompileSymbol
615 << "\"" << cmd.Parameter.NestedProgram->expression.Name() << '\"';
616 description << "Nested expr. searched at compile-time";
617 PushResult;
618 }
619 FMT(0)
620 }
621 break;
622
623 case Command::OpCodes::Constant:
624 {
625 ++stackSize;
626 char uetzelchen= cmd.ResultType.IsType<String>() ? '\"' : '\'';
627 operation << uetzelchen << cmd.ResultType << uetzelchen;
628 description << (cmd.TerminalType() == DCT::LiteralConstant ? "Literal constant"
629 : "Optimization constant" );
630 PushResult;
631 FMT(0)
632 }
633 break;
634
635 case Command::OpCodes::Function:
636 {
637 operation << cmd.DbgInfo.Callback
638 << "(#" << (cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs()) << ')';
639
640 NString descr= nullptr;
641 char decSym= '\0';
642 switch( cmd.TerminalType() )
643 {
644 case DCT::UnaryOp:
645 descr = "Unary operator";
646 decSym= '\'';
647 break;
648 case DCT::BinaryOp:
649 descr = "Binary operator";
650 decSym= '\'';
651 break;
652 case DCT::Identifier:
653 descr = "Identifier";
654 decSym= '"';
655 break;
656 case DCT::FunctionCall:
657 if( cmd.QtyArgs() < 0 )
658 {
659 descr = "Identifier";
660 decSym= '"';
661 break;
662 }
663 description << "Function \"";
664 if( cmd.QtyArgs() == 0 )
665 description << cmd.DecompileSymbol << "()\"";
666 else
667 description << cmd.DecompileSymbol << "(#"
668 << cmd.QtyArgs() << ")\"";
669 break;
670 case DCT::AutoCast:
671 descr = "Auto-cast";
672 decSym= '\'';
673 break;
674 case DCT::LiteralConstant: ALIB_FALLTHROUGH
675 case DCT::OptimizationConstant:
676 ALIB_ERROR("EXPRVM", "Must not be set with function calls")
677 break;
678 default: ALIB_ERROR("Illegal switch state.") break;
679 }
680 if( descr.IsNotNull() )
681 description << descr << ' ' << decSym << cmd.DecompileSymbol << decSym;
682
683 stackSize+= 1 - (cmd.QtyArgs() > 0 ? cmd.QtyArgs() : 0 );
684 FMT(cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs() )
685 for( integer i= 0 ; i< cmd.QtyArgs() ; ++i )
686 PopResult;
687 PushResult;
688 }
689 break;
690
692 {
693 operation << ( pc + cmd.Parameter.Distance ) << " (absolute)" ;
694 description << "'?'";
695 FMT( 1 ) // first print Q
696 ++ResultPos; // then have jump be included in T
697 }
698 break;
699
700 case Command::OpCodes::Jump: // ':'
701 {
702 conditionalStack.emplace( pc + cmd.Parameter.Distance -1 );
703 operation << ( pc + cmd.Parameter.Distance ) << " (absolute)" ;
704 description << "':'";
705 FMT( 1 ) // first print T
706 ++ResultPos; // then have jump be included in T
707 }
708 break;
709
710 default: ALIB_ERROR("Illegal switch state.") break;
711 }
714
715
716 while( !conditionalStack.empty() && conditionalStack.top() == pc )
717 {
718 PopResult;
719 PopResult;
720 ResultPos= pc;
721 conditionalStack.pop();
722 stackSize-= 2;
723 }
724
725 } // command loop
726
727
728 #undef PushResult
729 #undef PopResult
730 #undef ResultPos
731
732 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || stackSize == 1, "EXPRVM",
733 "VM Program List error: Stack size after listing not 1 but {}. Listing follows.\n",
734 stackSize, text.Buffer )
735
736 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || resultStack.size() == 1, "EXPRVM",
737 "VM Program List error: Resultstack after listing not 1 but {}. Listing follows.\n",
738 resultStack.size(), text.Buffer )
739
740 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || conditionalStack.size() == 0, "EXPRVM",
741 "VM Program List error: Conditional stack after listing not 0 but {}.Listing follows.\n",
742 conditionalStack, text.Buffer )
743 } // main loop
744
745 return std::move(text.Buffer);
746}
747#endif
748
749
750#undef POS_IN_EXPR_STR
751#undef PushResult
752#undef PopResult
753#undef ResultPos
754#undef FMT
755#undef PushNode
756#undef PopNode
757#undef Lhs
758#undef Rhs
759#undef Arg
760
761}}} // namespace [alib::expressions::detail]
762#include "alib/lang/callerinfo_methods.hpp"
bool IsSameType(const Box &other) const
Definition box.inl:762
const std::type_info & TypeID() const
Definition box.inl:941
ALIB_API NString TypeName(Type box)
Definition compiler.cpp:434
Compilation CfgCompilation
Compilation flags.
Definition compiler.hpp:273
virtual ALIB_API Expression GetNamed(const String &name)
Definition compiler.cpp:392
Compiler & compiler
The compiler that created this object.
Definition program.hpp:39
ALIB_API const Box & ResultType() const
Definition program.hpp:168
ExpressionVal & expression
The expression that this program evaluates.
Definition program.hpp:42
VM::Command & At(VM::PC pc)
Definition program.hpp:191
@ JumpIfFalse
Jumps if top of the stack indicates false.
DbgInformation DbgInfo
Operation code of this command. Available only with debug-builds.
Command(const Box &value, bool isOptimization, integer idxOriginal, integer idxNormalized)
OperationParam Parameter
The parameter of the operation.
ListingTypes
Denotes the type of parsing de-compilation information attached to the command.
const String & GetResource(const NString &name)
ALIB_API const Enum & Type() const
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
static ALIB_API threads::RecursiveLock DefaultLock
static ALIB_API SPFormatter Default
virtual BoxesMA & Reset()
Formatter & Format(AString &target, TArgs &&... args)
virtual BoxesMA & GetArgContainer()
void AddMarked(boxing::TBoxes< TAllocatorArgs > &args)
integer LineWidth
Used as parameter lineWidth of static method invocations.
TAString & ShortenTo(integer newLength)
Definition tastring.inl:971
constexpr integer Length() const
Definition string.hpp:326
#define bitsof(type)
Definition bits.hpp:49
#define ALIB_FALLTHROUGH
Definition alib.hpp:852
#define ALIB_CALLER_NULLED
Definition alib.hpp:1173
#define ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
Definition alib.hpp:790
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
Definition alib.hpp:785
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition owner.hpp:457
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
#define ALIB_DCS_WITH(CS)
#define ALIB_DBG(...)
Definition alib.hpp:390
@ NamedExpressionNotFound
Compile-time exception thrown when an expression refers to an unknown named nested expression.
Definition alib.cpp:69
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:276
expressions::ExpressionsCamp EXPRESSIONS
The singleton instance of ALib Camp class ExpressionsCamp.
containers::List< TAllocator, T, TRecycling > List
Type alias in namespace alib.
Definition list.hpp:842
strings::TString< character > String
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
integer Integral() const
Definition enum.hpp:119
StdVectorMono< ExpressionVal * > NestedExpressions
Stack of nested expressions called during evaluation. Used to detect cyclic expressions.
Definition scope.hpp:99
lang::DbgCriticalSections dcs
Definition scope.hpp:169
StdVectorMono< Box > * Stack
Definition scope.hpp:140
VMMembers * vmMembers
The members used for the virtual machine. Available only with evaluation-time instances.
Definition scope.hpp:157
virtual ALIB_API void reset()
Definition compiler.cpp:81
SPFormatter Formatter
Definition scope.hpp:154
Abstract syntax tree node representing binary operators.
Definition ast.hpp:234
Abstract syntax tree node representing ternary operator Q ? T : F.
Definition ast.hpp:267
Abstract syntax tree node representing a function call.
Definition ast.hpp:167
List< MonoAllocator, AST * > Arguments
The argument nodes.
Definition ast.hpp:169
Abstract syntax tree node representing identifiers.
Definition ast.hpp:140
Abstract syntax tree node representing identifiers.
Definition ast.hpp:76
Box Value
The value of the literal.
Definition ast.hpp:89
Abstract syntax tree node representing unary operators.
Definition ast.hpp:202
integer Position
Position in original expression string.
Definition ast.hpp:41
const char * Callback
The native C++ name of the callback function.
CompilerPlugin * Plugin
The plug-in that provided the callback or constant.
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)
Program * NestedProgram
The nested virtual machine program to invoke.
CallbackDecl Callback
A C++ callback function to invoke.