ALib C++ Library
Library Version: 2510 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
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, const String& functionOrOp,
41 integer idxOriginal, integer idxNormalized )
42: bits ( int16_t(OpCodes::Subroutine) | int16_t(ListingTypes::NestedExpression) )
43, Parameter ( program )
44, ResultType ( resultType )
45, ExpressionPositions( (uinteger(idxNormalized) << (bitsof(integer)/2)) + uinteger(idxOriginal) )
46, DecompileSymbol ( functionOrOp )
47{}
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{ALIB_DCS_WITH(scope.DCS)
60 // If the scope.Stack is empty, this indicates, that this is an 'external' call and not a
61 // subroutine.
62 scope.Reset();
63
64 // attach the compile-time scope to the evaluation scope.
66
67 // run
68 run( program, scope );
69
70 // detach ct-scope
71 scope.EvalScopeVMMembers->CTScope= nullptr;
72
73 // Remove top element from the stack and return its result.
74 Box result= scope.Stack->back();
75 scope.Stack->pop_back();
76 return result;
77}
78
79void VirtualMachine::run( Program& program, Scope& scope )
80{ALIB_DCS_WITH(scope.DCS)
81
82 ALIB_DBG( using DCT= Command::ListingTypes; )
83 ALIB_DBG( auto initialStackSize= scope.Stack->size(); )
84
85 auto& stack= *scope.Stack;
86
87 // check circular calls
88 auto& nestedExpressions= scope.EvalScopeVMMembers->NestedExpressions;
89 for( auto* nestedExpression : nestedExpressions )
90 if( nestedExpression == &program.expression )
91 {
93 for( auto it2= nestedExpressions.begin() ; it2!= nestedExpressions.end(); ++it2 )
95 (*it2)->Name(),
96 it2 + 1 != nestedExpressions.end()
97 ? (*(it2+1))->Name()
98 : nestedExpression->Name() );
99 throw e;
100 }
101
102 nestedExpressions.emplace_back( &program.expression );
103
104
105 for( integer programCounter= 0; programCounter < program.Length() ; ++ programCounter )
106 {
107 const Command& cmd= program.At(programCounter);
110 switch( cmd.OpCode() )
111 {
113 stack.emplace_back( cmd.ResultType );
114
115 break;
116
118 {
119 try
120 {
121 // with no args, we need a new stack object
122 if( cmd.HasArgs() )
123 {
124 stack.emplace_back( cmd.Parameter.Callback( scope,
125 stack.end() ,
126 stack.end() ) );
127
128 ALIB_ASSERT_ERROR( cmd.ResultType.IsSameType(stack.back()), "EXPRVM",
129 "Result type mismatch during command execution:\n"
130 " In expression: \"{}\" {{{}}}\n"
131 " Plugin: {}\n"
132 " Identifier: {} ({})\n"
133 " Expected type: <{}> (aka {})\n"
134 " Result type: <{}> (aka {})\n"
135 " Result value: {}\n",
136 program.expression.Name(),
138 cmd.DbgInfo.Plugin->Name,
140 program.compiler.TypeName( cmd.ResultType ), &cmd.ResultType.TypeID(),
141 program.compiler.TypeName( stack.back() ), &stack.back() .TypeID(),
142 stack.back() )
143 }
144
145 // otherwise, we assign the position to the value of the first arg in the stack and
146 // delete the other args after the call
147 else
148 {
149 ALIB_DBG( Box arg1Saved= *(stack.end() - cmd.QtyArgs() ); )
150
151 *(stack.end() - cmd.QtyArgs() )=
152 cmd.Parameter.Callback( scope,
153 stack.end() - cmd.QtyArgs(),
154 stack.end() );
155
156 #if ALIB_DEBUG
157 if( !cmd.ResultType.IsSameType(*(stack.end() - cmd.QtyArgs() )) )
158 {
159 String128 description;
160 switch( cmd.TerminalType() )
161 {
162 case DCT::UnaryOp:
163 description << "Unary operator '" << cmd.DecompileSymbol << '\'';
164 break;
165 case DCT::BinaryOp:
166 description << "Binary operator '" << cmd.DecompileSymbol << '\'';
167 break;
168 case DCT::FunctionCall:
169 if( cmd.QtyArgs() < 0 )
170 description << "Identifier \"" << cmd.DecompileSymbol << '\"';
171 else if( cmd.QtyArgs() == 0 )
172 description << "Function \"" << cmd.DecompileSymbol << "()\"";
173 else
174 description << "Function \"" << cmd.DecompileSymbol << "(#"
175 << cmd.QtyArgs() << ")\"";
176 break;
177 case DCT::AutoCast:
178 description << "Auto-cast" << cmd.DecompileSymbol << '\'';
179 break;
180 case DCT::LiteralConstant: ALIB_FALLTHROUGH
181 case DCT::OptimizationConstant:
182 ALIB_ERROR("EXPRVM", "Must not be set with function calls")
183 break;
184 default: ALIB_ERROR("EXPR", "Illegal switch state." ) break;
185 }
186
187 String512 msg;
190 fmt.GetArgContainer();
191 fmt.Format( msg, "Result type mismatch during command execution:\n"
192 " In expression: {!Q} {{{}}}\n"
193 " Plugin: {}\n"
194 " Info: {}\n"
195 " Callback: {}\n"
196 " Expected type: {!Q<>} (aka {})\n"
197 " Result type: {!Q<>} (aka {})\n"
198 " Result value: {}\n"
199 " Parameter values: ",
200 program.expression.Name(),
202 cmd.DbgInfo.Plugin->Name,
203 description,
204 cmd.DbgInfo.Callback,
205 program.compiler.TypeName( cmd.ResultType ), cmd.ResultType.TypeID(),
206 program.compiler.TypeName( stack.back() ), stack.back() .TypeID(),
207 stack.back() );
208 fmt.Format( msg, "({!Q'} {!Q<>}",
209 arg1Saved,
210 program.compiler.TypeName( arg1Saved ) );
211 for( integer i= cmd.QtyArgs() - 1; i > 0 ; --i )
212 fmt.Format( msg, ", {!Q'} {!Q<>}",
213 *(stack.end() - i),
214 program.compiler.TypeName( *(stack.end()-i)) );
215 msg << ')';
216 ALIB_ERROR( "EXPRVM", msg )
217 }
218 #endif
219
220 for(integer i= 1; i < cmd.QtyArgs(); ++i )
221 stack.pop_back();
222 }
223 }
224 catch( Exception& e )
225 {
227 {
229 program.expression.Name() );
231 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
232 }
233 throw;
234 }
235 catch( std::exception& stdException )
236 {
238 {
240 program.expression.Name() );
242 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
244 stdException.what() );
245 throw e;
246 }
247 throw;
248 }
249 }
250 break;
251
253 {
254 if( !stack.back().Call<FIsTrue>() )
255 programCounter+= cmd.Parameter.Distance -1; //-1 due to loop increase
256 stack.pop_back();
257 }
258 break;
259
261 programCounter+= cmd.Parameter.Distance - 1; //-1 due to loop increase
262 break;
263
264
266 // evaluation time defined nested expression
267 if( cmd.Parameter.NestedProgram == nullptr
268 || cmd.Parameter.NestedProgram == &program)
269 {
270 Expression nested;
271 String nestedExpressionName= (stack.end()-2)->Unbox<String>();
272 try
273 {
274 nested= program.compiler.GetNamed( nestedExpressionName );
275 }
276 catch( Exception& e )
277 {
278 // 3rd parameter "throw" was not given
279 if( cmd.Parameter.NestedProgram == nullptr )
280 {
281 // not found? -> remove name parameter from stack and use result of
282 // second parameter.
284 {
285 stack.erase( stack.end() - 2 );
286 break;
287 }
288
290 nestedExpressionName );
292 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
293
294 throw;
295 }
296
297 // 3rd parameter "throw" was given
300 nestedExpressionName );
301 else
303 nestedExpressionName );
304 throw;
305 }
306
307 run( * static_cast<Program*>(nested.Get()->GetProgram()), scope);
308
309 if( !(stack.end()-2)->IsSameType(stack.back()) )
310 {
312 nestedExpressionName,
313 program.compiler.TypeName( *(stack.end()-2) ),
314 program.compiler.TypeName( stack.back() ) );
316 program.expression.GetOriginalString(), POS_IN_EXPR_STR );
317 throw e;
318 }
319
320 stack.erase( stack.end()-3, stack.end() -1 );
321 }
322
323 // compile-time defined nested expression: just call it
324 else
325 run( *cmd.Parameter.NestedProgram, scope );
326
327 break;
328
329 default: ALIB_ERROR("EXPR", "Illegal switch state." ) break;
330 }
333
334 } // command loop
335
336 nestedExpressions.pop_back();
337
338 // This assertion should never happen. It indicates rather a library error than an
339 // erroneous plug-in.
340 ALIB_ASSERT_ERROR( stack.size() == initialStackSize + 1, "EXPRVM",
341 "Internal error: Stack increased by {} (instead of 1) after run of expression program.",
342 stack.size() - initialStackSize )
343
344 // Usually a function did not return what it is defined to return.
345 ALIB_ASSERT_ERROR( program.ResultType().IsSameType(stack.back()), "EXPRVM",
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: \"{}\""
351 ,
352 program.compiler.TypeName( program.ResultType() ), &program.ResultType().TypeID(),
353 program.compiler.TypeName( stack.back() ), &stack.back() .TypeID(),
354 stack.back(),
355 program.expression.Name()
356 )
357}
358
359// #################################################################################################
360// Decompile()
361// #################################################################################################
363{
364 using DCT= Command::ListingTypes;
365
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()
371
372 std::vector<AST*> nodeStack;
373
374 std::stack <PC> conditionalStack; // Stores the target of jump commands behind the T of
375 // conditional term "Q : T : F". In other words, the
376 // end of 'F'
377
378 for( integer pc= 0 ; pc < program.Length() ; ++pc )
379 {
380 const Command& cmd= program.At(pc);
381 integer positionInExpression= POS_IN_EXPR_STR;
382
385 switch( cmd.OpCode() )
386 {
388 {
389 // Function "Expression(name, type, boolean)"
390 if( cmd.Parameter.NestedProgram == nullptr
391 || cmd.Parameter.NestedProgram == & program )
392 {
393 ASTFunction* node= allocator().New<ASTFunction>(cmd.DecompileSymbol, positionInExpression, allocator );
394 for( integer i= 0 ; i< 2 ; ++i )
395 {
396 node->Arguments.emplace( node->Arguments.begin(), Arg );
397 PopNode;
398 }
399
400 // if nullptr, third parameter "throw"
401 if( cmd.Parameter.NestedProgram != nullptr )
402 node->Arguments.emplace_back(
403 allocator().New<ASTIdentifier>( String(allocator, program.compiler.CfgNestedExpressionThrowIdentifier),
404 positionInExpression ) );
405
406 PushNode(node);
407 break;
408 }
409
410 // constant call (program was given)
411 ASTIdentifier* name = allocator().New<ASTIdentifier>(String( allocator, cmd.Parameter.NestedProgram->expression.Name() ),
412 positionInExpression );
413 ASTUnaryOp* nested= allocator().New<ASTUnaryOp>( program.compiler.CfgNestedExpressionOperator,
414 name,
415 positionInExpression );
416 PushNode( nested );
417 }
418 break;
419
421 {
422 ASTLiteral* node= allocator().New<ASTLiteral>( integer(0), positionInExpression );
423 node->Value= cmd.ResultType;
424 PushNode(node);
425 }
426 break;
427
429 {
430 if( cmd.TerminalType() == DCT::UnaryOp )
431 {
432 ASTUnaryOp* node= allocator().New<ASTUnaryOp>(cmd.DecompileSymbol, Arg, positionInExpression );
433 PopNode;
434 PushNode(node);
435 break;
436 }
437
438 if( cmd.TerminalType() == DCT::BinaryOp )
439 {
440 ASTBinaryOp* node= allocator().New<ASTBinaryOp>(cmd.DecompileSymbol, Lhs, Rhs, positionInExpression );
441 PopNode;
442 PopNode;
443 PushNode(node);
444 break;
445 }
446
447 if( cmd.QtyArgs() < 0 )
448 {
449 ASTIdentifier* node= allocator().New<ASTIdentifier>(cmd.DecompileSymbol, positionInExpression );
450 PushNode(node);
451 break;
452 }
453
454 ASTFunction* node= allocator().New<ASTFunction>(cmd.DecompileSymbol, positionInExpression, allocator );
455 for( integer i= 0 ; i< cmd.QtyArgs() ; ++i )
456 {
457 node->Arguments.emplace( node->Arguments.begin(), Arg );
458 PopNode;
459 }
460
461 PushNode(node);
462 }
463 break;
464
466 {
467 }
468 break;
469
470 case Command::OpCodes::Jump: // ':'
471 {
472 conditionalStack.emplace( pc + cmd.Parameter.Distance -1 );
473 }
474 break;
475
476 default: ALIB_ERROR("EXPR", "Illegal switch state.") break;
477 }
480
481 while( !conditionalStack.empty() && conditionalStack.top() == pc )
482 {
483 AST* F= Arg; PopNode;
484 AST* T= Arg; PopNode; // F-Pos -2 is a little vague. But we don't care!
485 Arg= allocator().New<ASTConditional>(Arg, T, F, positionInExpression, F->Position - 2 );
486 conditionalStack.pop();
487 }
488
489
490 } // command loop
491
492 #undef PushNode
493 #undef PopNode
494 #undef Lhs
495 #undef Rhs
496 #undef Arg
497
498 ALIB_ASSERT_ERROR( nodeStack.size() == 1, "EXPRVM",
499 "VM AST generation error: NodeImpl stack must contain one element. Elements: {}",
500 nodeStack.size())
501 ALIB_ASSERT_ERROR( conditionalStack.size() == 0, "EXPRVM",
502 "VM Program List error: Conditional stack after listing not 0 but {}",
503 conditionalStack.size())
504
505 return nodeStack.back();
506}
507
508
509
510// #################################################################################################
511// DbgList()
512// #################################################################################################
513#if ALIB_DEBUG
514
515//! @cond NO_DOX
516namespace{
517void writeArgPositions(AString& target, std::vector<VirtualMachine::PC>& resultStack, integer qtyArgs )
518{
519 for( integer argNo= qtyArgs ; argNo > 0 ; --argNo )
520 {
521 target << (argNo == qtyArgs ? "" : ", ")
522 << (qtyArgs-argNo) << "{"
523 << ( integer(resultStack.size()) == argNo ? 0
524 : *(resultStack.end() - argNo - 1) + 1 )
525 << ".." << *(resultStack.end() - argNo )
526 << "}";
527 }
528}
529}
530//! @endcond
531
532
534{
535 using DCT= Command::ListingTypes;
536
537 String fmtLine= EXPRESSIONS.GetResource( "ProgListLine" );
538 String fmtHeader= EXPRESSIONS.GetResource( "ProgListHeader");
539
540 Paragraphs text;
541 text.LineWidth=0;
543 text.Formatter->Reset(); // reset autosizes
544
545 // repeat the whole output until its size is stable and all auto-tabs are set
546 integer lastLineWidth = 0;
547 while(lastLineWidth == 0 || lastLineWidth != text.DetectedMaxLineWidth)
548 {
549 lastLineWidth= text.DetectedMaxLineWidth;
550 text.Buffer.Reset();
551
552 // write headline
554 text.AddMarked( fmtHeader,
555 program.expression.Name(),
557
558
559 text.LineWidth= 0;
560 NString hdlKey= "ProgListHdl";
561
562 Box hdlArgs[10];
563 hdlArgs[0]= fmtLine;
564 NString64 hdlKeyNumbered(hdlKey);
565 for( int i= 0 ; i < 7 ; ++i )
566 {
567 hdlArgs[i+1]= EXPRESSIONS.GetResource(hdlKeyNumbered << i );
568 hdlKeyNumbered.ShortenTo( hdlKey.Length() );
569 }
570
571 hdlArgs[8]= 1;
572 hdlArgs[9]= program.expression.GetNormalizedString();
573 text.AddMarked( hdlArgs );
575 text.AddMarked("@HL-");
576 text.LineWidth= 0;
577
578 #define FMT(qtyArgs) \
579 { if( cmd.DbgInfo.Plugin ) \
580 description << ", CP=\"" << cmd.DbgInfo.Plugin->Name<< '\"'; \
581 String256 argpos; \
582 writeArgPositions(argpos,resultStack,qtyArgs); \
583 text.Add( fmtLine, \
584 pc, \
585 program.compiler.TypeName( cmd.ResultType ), \
586 cmd.OpCode(), \
587 operation, \
588 stackSize, \
589 description, \
590 argpos, \
591 NORMPOS_IN_EXPR_STR, "_^_" ); }
592
593
594 #define PushResult resultStack.emplace_back( pc )
595 #define PopResult resultStack.pop_back()
596 #define ResultPos resultStack.back()
597
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
601 // end of 'F'
602
603 PC stackSize = 0;
604 for( integer pc= 0 ; pc < program.Length() ; ++pc )
605 {
606 const Command& cmd= program.At(pc);
607
608 String128 operation;
609 String128 description;
610 ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
611 ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
612 switch( cmd.OpCode() )
613 {
614 case Command::OpCodes::Subroutine:
615 {
616 if( cmd.Parameter.NestedProgram == nullptr
617 || cmd.Parameter.NestedProgram == &program )
618 {
619 --stackSize;
620 operation << ( cmd.Parameter.NestedProgram == nullptr ? "Expr(name, type)"
621 : "Expr(name, type, throw)" );
622 description << "Nested expr. searched at evaluation-time";
623 PopResult;
624 }
625 else
626 {
627 ++stackSize;
628 operation << cmd.DecompileSymbol
629 << "\"" << cmd.Parameter.NestedProgram->expression.Name() << '\"';
630 description << "Nested expr. searched at compile-time";
631 PushResult;
632 }
633 FMT(0)
634 }
635 break;
636
637 case Command::OpCodes::Constant:
638 {
639 ++stackSize;
640 char uetzelchen= cmd.ResultType.IsType<String>() ? '\"' : '\'';
641 operation << uetzelchen << cmd.ResultType << uetzelchen;
642 description << (cmd.TerminalType() == DCT::LiteralConstant ? "Literal constant"
643 : "Optimization constant" );
644 PushResult;
645 FMT(0)
646 }
647 break;
648
649 case Command::OpCodes::Function:
650 {
651 operation << cmd.DbgInfo.Callback
652 << "(#" << (cmd.QtyArgs() < 0 ? 0 : cmd.QtyArgs()) << ')';
653
654 NString descr= nullptr;
655 char decSym= '\0';
656 switch( cmd.TerminalType() )
657 {
658 case DCT::UnaryOp:
659 descr = "Unary operator";
660 decSym= '\'';
661 break;
662 case DCT::BinaryOp:
663 descr = "Binary operator";
664 decSym= '\'';
665 break;
666 case DCT::Identifier:
667 descr = "Identifier";
668 decSym= '"';
669 break;
670 case DCT::FunctionCall:
671 if( cmd.QtyArgs() < 0 )
672 {
673 descr = "Identifier";
674 decSym= '"';
675 break;
676 }
677 description << "Function \"";
678 if( cmd.QtyArgs() == 0 )
679 description << cmd.DecompileSymbol << "()\"";
680 else
681 description << cmd.DecompileSymbol << "(#"
682 << cmd.QtyArgs() << ")\"";
683 break;
684 case DCT::AutoCast:
685 descr = "Auto-cast";
686 decSym= '\'';
687 break;
688 case DCT::LiteralConstant: ALIB_FALLTHROUGH
689 case DCT::OptimizationConstant:
690 ALIB_ERROR("EXPRVM", "Must not be set with function calls")
691 break;
692 default: ALIB_ERROR("EXPR", "Illegal switch state.") break;
693 }
694 if( descr.IsNotNull() )
695 description << descr << ' ' << decSym << cmd.DecompileSymbol << decSym;
696
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 )
700 PopResult;
701 PushResult;
702 }
703 break;
704
706 {
707 operation << ( pc + cmd.Parameter.Distance ) << " (absolute)" ;
708 description << "'?'";
709 FMT( 1 ) // first print Q
710 ++ResultPos; // then have jump be included in T
711 }
712 break;
713
714 case Command::OpCodes::Jump: // ':'
715 {
716 conditionalStack.emplace( pc + cmd.Parameter.Distance -1 );
717 operation << ( pc + cmd.Parameter.Distance ) << " (absolute)" ;
718 description << "':'";
719 FMT( 1 ) // first print T
720 ++ResultPos; // then have jump be included in T
721 }
722 break;
723
724 default: ALIB_ERROR("EXPR", "Illegal switch state.") break;
725 }
728
729
730 while( !conditionalStack.empty() && conditionalStack.top() == pc )
731 {
732 PopResult;
733 PopResult;
734 ResultPos= pc;
735 conditionalStack.pop();
736 stackSize-= 2;
737 }
738
739 } // command loop
740
741
742 #undef PushResult
743 #undef PopResult
744 #undef ResultPos
745
746 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || stackSize == 1, "EXPRVM",
747 "VM Program List error: Stack size after listing not 1 but {}. Listing follows.\n",
748 stackSize, text.Buffer )
749
750 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || resultStack.size() == 1, "EXPRVM",
751 "VM Program List error: Resultstack after listing not 1 but {}. Listing follows.\n",
752 resultStack.size(), text.Buffer )
753
754 ALIB_ASSERT_ERROR( lastLineWidth!= 0 || conditionalStack.size() == 0, "EXPRVM",
755 "VM Program List error: Conditional stack after listing not 0 but {}. Listing follows.\n",
756 conditionalStack.size(), text.Buffer )
757 } // main loop
758
759 return std::move(text.Buffer);
760}
761#endif
762
763
764#undef POS_IN_EXPR_STR
765#undef PushResult
766#undef PopResult
767#undef ResultPos
768#undef FMT
769#undef PushNode
770#undef PopNode
771#undef Lhs
772#undef Rhs
773#undef Arg
774
775}}} // namespace [alib::expressions::detail]
776# include "ALib.Lang.CIMethods.H"
bool IsSameType(const Box &other) const
Definition box.inl:618
const std::type_info & TypeID() const
Definition box.inl:827
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
ALIB_DLL const Enum & Type() const
Compilation CfgCompilation
Compilation flags.
Definition compiler.inl:261
ALIB_DLL NString TypeName(Type box)
Definition compiler.cpp:436
virtual ALIB_DLL Expression GetNamed(const String &name)
Definition compiler.cpp:394
ExpressionVal & expression
The expression that this program evaluates.
Definition program.inl:33
ALIB_DLL const Box & ResultType() const
Definition program.inl:153
VM::Command & At(VM::PC pc)
Definition program.inl:167
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:816
constexpr integer Length() const
Definition string.inl:318
#define bitsof(type)
Definition alib.inl:1418
#define ALIB_FALLTHROUGH
Definition alib.inl:708
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
#define ALIB_CALLER_NULLED
Definition alib.inl:1010
#define ALIB_WARNINGS_ALLOW_BITWISE_SWITCH
Definition alib.inl:642
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:705
#define ALIB_ERROR(domain,...)
Definition alib.inl:1045
#define ALIB_WARNINGS_ALLOW_SPARSE_ENUM_SWITCH
Definition alib.inl:637
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1323
#define ALIB_DCS_WITH(CS)
Definition alib.inl:1377
#define ALIB_DBG(...)
Definition alib.inl:836
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
@ 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:2390
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:1216
exceptions::Exception Exception
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2381
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:87
StdVectorMono< 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
StdVectorMono< 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:87
Abstract syntax tree node representing binary operators.
Definition ast_impl.inl:211
Abstract syntax tree node representing ternary operator Q ? T : F.
Definition ast_impl.inl:244
Abstract syntax tree node representing a function call.
Definition ast_impl.inl:144
List< MonoAllocator, AST * > Arguments
The argument nodes.
Definition ast_impl.inl:146
Abstract syntax tree node representing identifiers.
Definition ast_impl.inl:117
Abstract syntax tree node representing identifiers.
Definition ast_impl.inl:53
Box Value
The value of the literal.
Definition ast_impl.inl:66
Abstract syntax tree node representing unary operators.
Definition ast_impl.inl:179
integer Position
Position in the original expression string.
Definition ast_impl.inl:18
static Scope * getExpressionCTScope(ExpressionVal &ev)
Definition compiler.inl:564
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.