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