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