ALib C++ Library
Library Version: 2402 R1
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
11#if !defined (HPP_ALIB_EXPRESSIONS_EXPRESSION)
13#endif
14
15#ifndef HPP_ALIB_ENUMS_UNDERLYING_INTEGRAL
17#endif
18
19
20
21namespace alib { namespace expressions {
22
23struct CompilerPlugin;
24
25namespace detail {
26
27class Program;
28struct AST;
29
30/** ************************************************************************************************
31 * This class implements a very simple stack machine that understands just four commands (!) plus
32 * a fifth to execute sub-programs.
33 *
34 * This class is part of module \alib_expressions_nl. It is not too well documented as it
35 * resides in a \c detail namespace and is not to be used from the outside expression API.
36 **************************************************************************************************/
38{
39 public:
40 /// Type definition for a program counter.
41 using PC = integer;
42
43 /**
44 * A command of the VM.
45 */
46 class Command
47 {
48 public:
49 /**
50 * The opcode type of VM commands. This is defined as a
51 * \alib{enums;T_EnumIsBitwise;bitwise enum type} as also flags may be set in
52 * addition to defining the type of operation.
53 */
54 enum class OpCodes
55 {
56 Constant = 1, ///< Pushes a constant to the stack.
57 Function = 2, ///< Invokes a C++ callback function.
58 JumpIfFalse = 3, ///< Jumps if top of the stack indicates \c false.
59 Jump = 4, ///< Jumps.
60 Subroutine = 5, ///< Invokes another program.
61
62 CmdMask = (1 << 16) - 1, ///< Used to mask the command out of an opcode.
63
64 FlagEOC = (1 << 17), ///< Flags a command to be the last of a conditional.
65 };
66
67 /**
68 * Denotes the two different jump types (used as constructor parameter only.)
69 */
70 enum class JumpType
71 {
72 Conditional, ///< Denotes \b %JumpIfFalse.
73 Unconditional, ///< Denotes \b %Jump.
74 };
75
76
77 /**
78 * Denotes the type of decompilation information attached to the command.
79 */
81 {
82 LiteralConstant, ///< Command results from a literal constant.
83 OptimizationConstant, ///< Command results from a constant resulting from an optimization.
84 UnaryOp, ///< Command results from an unary operator.
85 BinaryOp, ///< Command results from a binary operator.
86 Function, ///< Command results from a function call.
87 AutoCast, ///< Command results from an automatically inserted cast.
88 Subroutine, ///< Command results from a nested expression.
89 };
90
91 #if ALIB_DEBUG
92 /**
93 * Provides additional debug information for a command.
94 * Available only with debug builds of the module \alib_expressions_nl
95 * library. Used with \alib{expressions::detail;VirtualMachine::DbgList}
96 */
98 {
99 /// The plug-in that provided the callback or constant.
101
102 /// The native C++ name of the callback function.
103 const char* Callback;
104 };
105 #endif
106
107 /**
108 * A union of different parameter types for the commands.
109 */
111 {
112 PC Distance; ///< A distance to jump
113 CallbackDecl Callback; ///< A C++ callback function to invoke.
114 Box Value; ///< A constant value to push to the stack.
115 Program* NestedProgram; ///< The nested virtual machine program to invoke.
116
117 /**
118 * Union constructor.
119 * @param distance Stored in #Distance.
120 */
122 : Distance (distance )
123 {}
124
125 /**
126 * Union constructor.
127 * @param callback Stored in #Callback.
128 */
130 : Callback(callback)
131 {}
132
133 /**
134 * Union constructor.
135 * @param value Stored in #Value.
136 */
138 : Value (value )
139 {}
140
141 /**
142 * Union constructor.
143 * @param program Stored in #NestedProgram.
144 */
146 : NestedProgram( program )
147 {}
148 };
149
150 protected:
151 /** Operation code of this command. */
153
154 public:
155 /** The parameter of the operation. */
157
158 /**
159 * The number of function args.
160 * If negative, this indicates that the function name was given as an 'identifier',
161 * what means that no brackets '()' had been added. This piece of information (namely
162 * having a signed integer here which allows to differentiate between \c 0 and a negative
163 * number of arguments) is used when decompiling a program to back to an expression
164 * string. Hence, this piece of it logically belongs to #DecompileType.
165 */
167
168 /**
169 * The result type of a command. This is only needed during compilation.
170 * With debug builds of the library, it is furthermore used with
171 * \alib{expressions::detail;VirtualMachine::DbgList}. Hence for simplicity and
172 * shortness of the library code we keep it here, taking into account that after
173 * compilation each command is equipped with a then unnecessary box.
174 */
176
177 /**
178 * This encodes both, the position in the original and normalized expression string
179 * that resulted in this command. Used for generation of exception information and
180 * and debug listings.
181 */
183
184
185 /** Type of expression term used with decompilation. */
187
188 /** The operator symbol or function name used with decompilation to recreate an
189 * expression string. */
191
192
193 #if ALIB_DEBUG
194 /** Operation code of this command. Available only with debug builds. */
196 #endif
197
198 /**
199 * Constructor creating a constant.
200 * @param value The constant to add.
201 * @param isOptimization Denotes if the constant results from an optimization or
202 * from a literal of the expression string.
203 * @param idxOriginal Expression string index that imposed command.
204 * @param idxNormalized Normalized expression string index that imposed command.
205 */
206 Command( const Box& value, bool isOptimization,
207 integer idxOriginal, integer idxNormalized )
209 , Operation (value)
210 , ResultType(value)
211 , ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
212 + static_cast<uinteger>(idxOriginal ) )
215 {}
216
217
218 /**
219 * Constructor creating a native function call exposed from an identifier, function
220 * or operator.
221 * @param callback The callback function.
222 * @param qtyFunctionArgs The number of arguments that the callback function expects.
223 * @param resultType The result type of the function.
224 * @param functionOrOp The identifier, function or operator name/symbol.
225 * This is used for decompilation of programs.
226 * @param isOperator If \c true an unary operator was compiled, a binary operator
227 * otherwise.
228 * @param idxOriginal Expression string index that imposed command.
229 * @param idxNormalized Normalized expression string index that imposed command.
230 */
231 Command( CallbackDecl callback, integer qtyFunctionArgs, const Box& resultType,
232 const String& functionOrOp, bool isOperator,
233 integer idxOriginal, integer idxNormalized )
235 , Operation (callback )
236 , QtyFunctionArgs (qtyFunctionArgs )
237 , ResultType (resultType )
238 , ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
239 + static_cast<uinteger>(idxOriginal ) )
240 , DecompileType ( isOperator ? ( qtyFunctionArgs == 1 ? DecompileInfoType::UnaryOp
243 , DecompileSymbol (functionOrOp )
244 {}
245
246 /**
247 * Constructor creating a subroutine call.
248 * @param program The program to call.
249 * @param resultType The result type of the program.
250 * @param functionOrOp The function or operator that created the nested call.
251 * @param idxOriginal Expression string index that imposed command.
252 * @param idxNormalized Normalized expression string index that imposed command.
253 */
254 Command( Program* program, const Box& resultType, const String& functionOrOp,
255 integer idxOriginal, integer idxNormalized );
256
257 /**
258 * Constructor creating a jump. Note, the address is usually not known yet, hence not
259 * provided. With debug builds, this constructor asserts that it is used for jump
260 * commands only.
261 * @param jumpType The type of jump.
262 * @param idxOriginal Expression string index that imposed command.
263 * @param idxNormalized Normalized expression string index that imposed command.
264 */
265 Command( JumpType jumpType, integer idxOriginal, integer idxNormalized )
267 , Operation(-1)
268 , ResultType(nullptr)
269 , ExpressionPositions( (static_cast<uinteger>(idxNormalized) << (bitsof(integer)/2) )
270 + static_cast<uinteger>(idxOriginal ) )
271 {}
272
273
274 /**
275 * Returns \c true if the command represents a constant value.
276 * @return \c true if the command represents a constant value, \c false otherwise.
277 */
278 bool IsConstant() const
279 {
280 // this excludes OpCodes::Constant with FlagEOC set.
281 return opcode == OpCodes::Constant;
282 }
283
284 /**
285 * Returns \c true if the command represents a jump.
286 * @return \c true if the command represents a jump, \c false otherwise.
287 */
288 bool IsConditionalJump() const
289 {
291 || opcode == OpCodes::Jump ;
292 }
293
294 /**
295 * Marks the command as the end of an conditional term.
296 */
298 {
299 opcode = OpCodes( UnderlyingIntegral(opcode) | UnderlyingIntegral(OpCodes::FlagEOC) );
300 }
301
302 /**
303 * Returns the masked command part of the opcode.
304 * @return The masked command part of the opcode.
305 */
307 {
308 return OpCodes( UnderlyingIntegral(opcode) & UnderlyingIntegral(OpCodes::CmdMask) );
309 }
310 }; // inner struct Command
311
312
313 /** ********************************************************************************************
314 * Static method that runs an expression program.
315 * @param program The program to run.
316 * @param scope The scope to use.
317 * @return The result value of the expression program.
318 **********************************************************************************************/
319 ALIB_API static
320 alib::Box Run( Program& program, Scope& scope );
321
322 /** ********************************************************************************************
323 * Static method that decompiles a program into an abstract syntax tree.
324 * Used to generate optimized, normalized, parsable expression strings.
325 * @param program The program to decompile.
326 * @param allocator Allocator for AST objects (and their data).
327 * @return The abstract syntax tree as a result of decompilation.
328 **********************************************************************************************/
329 ALIB_API static
330 AST* Decompile( Program& program, MonoAllocator& allocator );
331
332
333 #if ALIB_DEBUG
334 /** ****************************************************************************************
335 * Lists a virtual machine program.
336 *
337 * Note: This method is available only with debug builds of the library.
338 * @param program The program to list.
339 * @return The program listing.
340 ******************************************************************************************/
341 ALIB_API static
342 AString DbgList( Program& program );
343
344 #endif
345
346 /** ********************************************************************************************
347 * The implementation of #Run, which itself is just initialization code
348 * @param program The program to run.
349 * @param scope The scope to use.
350 **********************************************************************************************/
351 ALIB_API static
352 void run( Program& program, Scope& scope );
353
354
355};
356
357}}} // namespace [alib::expressions::detail]
358
361#if ALIB_DEBUG
363#endif
364
365#endif // HPP_ALIB_EXPRESSIONS_DETAIL_VIRTUAL_MACHINE
@ FlagEOC
Flags a command to be the last of a conditional.
@ CmdMask
Used to mask the command out of an opcode.
@ JumpIfFalse
Jumps if top of the stack indicates false.
Command(CallbackDecl callback, integer qtyFunctionArgs, const Box &resultType, const String &functionOrOp, bool isOperator, integer idxOriginal, integer idxNormalized)
Command(const Box &value, bool isOptimization, integer idxOriginal, integer idxNormalized)
@ AutoCast
Command results from an automatically inserted cast.
@ OptimizationConstant
Command results from a constant resulting from an optimization.
Command(JumpType jumpType, integer idxOriginal, integer idxNormalized)
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)
#define bitsof(type)
Definition bits.hpp:52
#define ALIB_ENUMS_MAKE_BITWISE(TEnum)
Definition bitwise.hpp:120
#define ALIB_ENUMS_ASSIGN_RECORD(TEnum, TRecord)
Definition records.hpp:752
#define ALIB_API
Definition alib.hpp:538
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
Definition vtable.inl:477
Box(*)(Scope &scope, ArgIterator argsBegin, ArgIterator argsEnd) CallbackDecl
Definition alib.cpp:57
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.hpp:289
expressions::CompilerPlugin CompilerPlugin
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
const char * Callback
The native C++ name of the callback function.
CompilerPlugin * Plugin
The plug-in that provided the callback or constant.
Program * NestedProgram
The nested virtual machine program to invoke.
CallbackDecl Callback
A C++ callback function to invoke.