ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
virtualmachine.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header file is part of module \alib_expressions of the \aliblong.
4///
5/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef HPP_ALIB_EXPRESSIONS_DETAIL_VIRTUAL_MACHINE
9#define HPP_ALIB_EXPRESSIONS_DETAIL_VIRTUAL_MACHINE
10#pragma once
13
14namespace alib::expressions {
15
16struct CompilerPlugin;
17
18namespace detail {
19
20class Program;
21struct AST;
22
23//==================================================================================================
24/// This type implements a very simple stack machine that understands just four commands (!) plus
25/// a fifth to execute sub-programs.
26///
27/// This class is part of module \alib_expressions_nl. It is not too well documented as it
28/// resides in a \c detail namespace and is not to be used from the outside expression API.
29//==================================================================================================
31{
32 /// Type definition for a program counter.
33 using PC = integer;
34
35 /// A command of the VM.
36 class Command
37 {
38 public:
39 /// Some meanings and masks of field #bits.
40 enum Bits
41 {
42 CMD_MASK = 0x07, ///< Used to mask the command out of an opcode.
43 FlagEOC = 0x08, ///< Flags a command to be the last of a conditional.
44 CMD_MASK_WITH_EOC = 0x0F, ///< Used to mask the command out of an opcode,
45 ///< including the EOC flag.
46 TYPE_MASK = 0xF0 ///< The mask for the \b ListingTypes.
47 };
48
49 /// The opcode type of VM commands.
51 {
52 Constant = 0, ///< Pushes a constant to the stack.
53 Function = 1, ///< Invokes a C++ callback function.
54 Subroutine = 2, ///< Invokes another program.
55
56 // leaving out one, so that jumps have bit 3 set.
57 JumpIfFalse = 4, ///< Jumps if top of the stack indicates \c false.
58 Jump = 5, ///< Jumps.
59 };
60
61 /// Denotes the type of parsing de-compilation information attached to the command.
63 {
64 LiteralConstant = 0x00, ///< Command results from a literal constant.
65 OptimizationConstant= 0x10, ///< Command results from a constant resulting from an optimization.
66 UnaryOp = 0x20, ///< Command results from an unary operator.
67 BinaryOp = 0x30, ///< Command results from a binary operator.
68 Identifier = 0x40, ///< Command results from a function call with no parenthesis given.
69 FunctionCall = 0x50, ///< Command results from a function call.
70 AutoCast = 0x60, ///< Command results from an automatically inserted cast.
71 NestedExpression = 0x70, ///< Command results from a nested expression.
72 };
73
74 /// Denotes the two different jump types (used only as parameter, not stored.)
75 enum class JumpType
76 {
77 Conditional, ///< Denotes \b %JumpIfFalse.
78 Unconditional, ///< Denotes \b %Jump.
79 };
80
81
82 #if ALIB_DEBUG
83 /// Provides additional debug information for a command.
84 /// Available only with debug-builds of the library.
85 /// Used with \alib{expressions::detail;VirtualMachine::DbgList}
87 {
88 /// The plug-in that provided the callback or constant.
90
91 /// The native C++ name of the callback function.
92 const char* Callback;
93 };
94 #endif
95
96 /// A union of different parameter types for the commands.
98 {
99 PC Distance; ///< A distance to jump
100 CallbackDecl Callback; ///< A C++ callback function to invoke.
101 Program* NestedProgram; ///< The nested virtual machine program to invoke.
102
103 /// Default constructor leaving this instance uninitialized.
105
106 /// Union constructor.
107 /// @param distance Stored in #Distance.
108 OperationParam( integer distance ) : Distance(distance) {}
109
110 /// Union constructor.
111 /// @param callback Stored in #Callback.
112 OperationParam( CallbackDecl callback ) : Callback(callback) {}
113
114 /// Union constructor.
115 /// @param program Stored in #NestedProgram.
116 OperationParam ( Program* program) : NestedProgram(program) {}
117 };
118
119 protected:
120 /// Operation code of this command.
121 int16_t bits;
122
123 /// The number of function args.
124 /// If negative, this indicates that the function name was given as an 'identifier',
125 /// what means that no brackets '()' had been added. This piece of information (namely
126 /// having a signed integer here which allows differentiating between \c 0 and a negative
127 /// number of arguments) is used when decompiling a program back to an expression
128 /// string. Hence, this piece of it logically belongs to #ListingTypes.
129 uint16_t qtyArgs;
130
131 public:
132 /// The parameter of the operation.
134
135 /// With every command, this box contains the result type.
136 /// For constants, also the commands' value is contained.
138
139 /// This encodes both, the position in the original and in the normalized expression
140 /// string that resulted in this command.
141 /// Used for generation of exception information and debug listings.
143
144
145 /// The operator symbol or function name used with de-compilation to recreate an
146 /// expression string.
148
149
150 #if ALIB_DEBUG
151 /// Operation code of this command. Available only with debug-builds.
153 #endif
154
155 /// Constructor creating a constant.
156 /// @param value The constant to add.
157 /// @param isOptimization Denotes if the constant results from an optimization or
158 /// from a literal of the expression string.
159 /// @param idxOriginal Expression string index that imposed command.
160 /// @param idxNormalized Normalized expression string index that imposed command.
161 Command( const Box& value, bool isOptimization,
162 integer idxOriginal, integer idxNormalized )
163 : bits ( int16_t(OpCodes::Constant)
164 | ( isOptimization ? int16_t(ListingTypes::OptimizationConstant)
165 : int16_t(ListingTypes::LiteralConstant ) ) )
166 , ResultType(value)
167 , ExpressionPositions( (uinteger(idxNormalized) << (bitsof(integer)/2) )
168 + uinteger(idxOriginal ) )
169 {}
170
171
172 /// Constructor creating a native function call exposed from an identifier, function
173 /// or operator.
174 /// @param callback The callback function.
175 /// @param isIdentifier If no parentheses were given, this has to be \c true.
176 /// Otherwise it is a function call.
177 /// @param qtyFunctionArgs The number of arguments that the callback function expects.
178 /// @param resultType The result type of the function.
179 /// @param functionOrOp The identifier, function or operator name/symbol.
180 /// This is used for de-compilation of programs.
181 /// @param isOperator If \c true an unary operator was compiled, a binary operator
182 /// otherwise.
183 /// @param idxOriginal Expression string index that imposed command.
184 /// @param idxNormalized Normalized expression string index that imposed command.
185 Command( CallbackDecl callback, bool isIdentifier, int qtyFunctionArgs,
186 const Box& resultType,
187 const String& functionOrOp, bool isOperator,
188 integer idxOriginal, integer idxNormalized )
189 : bits ( int16_t(OpCodes::Function)
190 | ( isOperator ? ( qtyFunctionArgs == 1 ? int16_t(ListingTypes::UnaryOp )
191 : int16_t(ListingTypes::BinaryOp) )
192 : ( isIdentifier ? int16_t(ListingTypes::Identifier )
193 : int16_t(ListingTypes::FunctionCall) ) ) )
194 , qtyArgs (uint16_t(qtyFunctionArgs) )
195 , Parameter (callback )
196 , ResultType (resultType )
197 , ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
198 + static_cast<uinteger>(idxOriginal ) )
199 , DecompileSymbol (functionOrOp )
200 {}
201
202 /// Constructor creating a subroutine call.
203 /// @param program The program to call.
204 /// @param resultType The result type of the program.
205 /// @param functionOrOp The function or operator that created the nested call.
206 /// @param idxOriginal Expression string index that imposed command.
207 /// @param idxNormalized Normalized expression string index that imposed command.
209 Command( Program* program, const Box& resultType, const String& functionOrOp,
210 integer idxOriginal, integer idxNormalized );
211
212 /// Constructor creating a jump. Note, the address is usually not known yet, hence not
213 /// provided.
214 /// @param jumpType The type of jump.
215 /// @param idxOriginal Expression string index that imposed command.
216 /// @param idxNormalized Normalized expression string index that imposed command.
217 Command( integer idxOriginal, integer idxNormalized, JumpType jumpType )
218 : bits (int16_t(jumpType == JumpType::Conditional ? OpCodes::JumpIfFalse : OpCodes::Jump ))
219 , Parameter (-1)
220 , ResultType(nullptr)
221 , ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
222 | static_cast<uinteger>(idxOriginal ) )
223 {}
224
225
226 /// Returns the opcode of this command.
227 /// @return The masked command part of the opcode.
228 constexpr OpCodes OpCode() const { return OpCodes(bits & Bits::CMD_MASK); }
229
230 /// Returns the decompile type of this command.
231 /// @return The masked command part of the opcode.
233
234 /// Returns \c true if the command represents a constant value, but is not the end
235 /// of a conditional jump.
236 /// @return \c true if the command represents a constant value, \c false otherwise.
239
240 /// Returns \c true if the command represents a conditional or unconditional jump.
241 /// @return \c true if the command represents a jump, \c false otherwise.
242 bool IsJump() const { return (bits & 4) == 4; }
243
244 /// Marks the command as the end of a conditional term.
246
247 /// @return \c true if the function has arguments, \c false otherwise.
248 bool HasArgs() const { return qtyArgs <= 0; }
249
250 /// @return \c true if the function has arguments, \c false otherwise.
251 bool IsIdentifier() const { return qtyArgs <= 0; }
252
253 /// @return The number of arguments of a function call.
254 int QtyArgs() const { return int(qtyArgs); }
255 }; // inner struct Command
256
257 //==============================================================================================
258 /// Static method that runs an expression program.
259 /// @param program The program to run.
260 /// @param scope The scope to use.
261 /// @return The result value of the expression program.
262 //==============================================================================================
263 ALIB_API static
264 alib::Box Run( Program& program, Scope& scope );
265
266 //==============================================================================================
267 /// Static method that decompiles a program into an abstract syntax tree.
268 /// Used to generate optimized, normalized, parsable expression strings.
269 /// @param program The program to decompile.
270 /// @param allocator Allocator for AST objects (and their data).
271 /// @return The abstract syntax tree as a result of de-compilation.
272 //==============================================================================================
273 ALIB_API static
274 AST* Decompile( Program& program, MonoAllocator& allocator );
275
276
277 #if ALIB_DEBUG
278 //==========================================================================================
279 /// Lists a virtual machine program.
280 ///
281 /// Note: This method is available only with debug-builds of the library.
282 /// @param program The program to list.
283 /// @return The program listing.
284 //==========================================================================================
285 ALIB_API static
286 AString DbgList( Program& program );
287
288 #endif
289
290 //==============================================================================================
291 /// The implementation of #Run, which itself is just initialization code.
292 /// @param program The program to run.
293 /// @param scope The scope to use.
294 //==============================================================================================
295 ALIB_API static
296 void run( Program& program, Scope& scope );
297
298}; // struct VirtualMachine
299
300}} // namespace [alib::expressions::detail]
301
303#if ALIB_DEBUG
305#endif
306
307
308
309#endif // HPP_ALIB_EXPRESSIONS_DETAIL_VIRTUAL_MACHINE
310
Command(integer idxOriginal, integer idxNormalized, JumpType jumpType)
@ JumpIfFalse
Jumps if top of the stack indicates false.
DbgInformation DbgInfo
Operation code of this command. Available only with debug-builds.
void SetEndOfConditionalFlag()
Marks the command as the end of a conditional term.
Command(CallbackDecl callback, bool isIdentifier, int qtyFunctionArgs, const Box &resultType, const String &functionOrOp, bool isOperator, integer idxOriginal, integer idxNormalized)
Bits
Some meanings and masks of field bits.
@ FlagEOC
Flags a command to be the last of a conditional.
@ CMD_MASK
Used to mask the command out of an opcode.
Command(const Box &value, bool isOptimization, integer idxOriginal, integer idxNormalized)
int16_t bits
Operation code of this command.
OperationParam Parameter
The parameter of the operation.
JumpType
Denotes the two different jump types (used only as parameter, not stored.)
ListingTypes
Denotes the type of parsing de-compilation information attached to the command.
@ UnaryOp
Command results from an unary operator.
@ NestedExpression
Command results from a nested expression.
@ BinaryOp
Command results from a binary operator.
@ LiteralConstant
Command results from a literal constant.
@ Identifier
Command results from a function call with no parenthesis given.
@ AutoCast
Command results from an automatically inserted cast.
@ OptimizationConstant
Command results from a constant resulting from an optimization.
@ FunctionCall
Command results from a function call.
#define bitsof(type)
Definition bits.hpp:49
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
Definition records.hpp:712
#define ALIB_API
Definition alib.hpp:639
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
Definition vtable.inl:460
Box(*)(Scope &scope, ArgIterator argsBegin, ArgIterator argsEnd) CallbackDecl
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:276
expressions::CompilerPlugin CompilerPlugin
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
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)
integer PC
Type definition for a program counter.
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)
A union of different parameter types for the commands.
Program * NestedProgram
The nested virtual machine program to invoke.
OperationParam()
Default constructor leaving this instance uninitialized.
CallbackDecl Callback
A C++ callback function to invoke.