• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Expression evaluation feature in debugger for ArkTS language
2
3To provide expression evaluation functionality for ArkTS language in the debugger, it is necessary to have the ability to compile expressions in the current execution context.
4The approach is implemented in the `ScopedDebugInfoPlugin` in `es2panda` and is concluded in compiling expressions with debug information from the given .abc file.
5
6Note that apart from debugging information the plugin also uses other information from the given .abc files, e.g. information about classes records.
7
8## List of supported features
9
10Notes:
111. Currently, it is not possible to supports imports, so all features work only if the entity is located in the file where evaluation takes place.
12
132. In expression that will be evaluated, user can access private and protected fields and methods of objects.
14
153. Access to all standard classes is supported.
16
17List of features:
181. Local variables
192. Global variables
203. Functions
214. Classes
22
23## Evaluating expression principal scheme
24
25![image info](./images/arkts-expression-evaluation-principle-scheme.svg)
26
27## Explanation
28
29The main problem in expression evaluation feature is compilation with debugging information, so let's look at it in more detail.
30
31The first logical step after starting to execute es2panda in evaluation mode is to wrap the given expression in a class with a static function.
32The name of class and name of static function are generated from file name and random number.
33This step is necessary, because several evaluations are possible in a single file.
34It is necessary to distinguish between generated classes when loading them into the Runtime.
35If the last line of an expression received from the user potentially returns a primitive value, then a return statement of this value will be generated in the evaluation method during compilation.
36
37**There are two main ideas that help in solving the problem of expression compilation:**
38
391. It is enough to insert intrinsic calls in order to recover the context of local variables.
40
41For example, if we have declared an integer variable with name `a` in source code and want to evaluate expression `a = a + 1`, then the following code will be generated:
42
43```ts
44let a = DebuggerAPIGetLocalInt(reg_number); // get variable from register
45
46a = a + 1;
47
48DebuggerAPISetLocalInt(reg_number, a); // update register state
49```
50
51`reg_number` and type of intrinsic are obtained from debugging information due to find local variable in `ScopedDebugInfoPlugin::FindLocalVariable`.
52
53Note that plugin inserts intrinsics calls directly into the AST, but not into the source code.
54
55When bytecode with such intrinsic calls is executed, a local variable of the correct type is obtained from a register.
56Then, this local variable may be modified by a given expression, so after modifications, the variable is written back to the register.
57
582. In case of evaluating an expression containing a class, a class type variable, etc., it is enough to deserialize the class declaration from the debugging information into the class definition in the AST with empty method bodies and empty fields.
59
60Consider the following source code as an example:
61
62```ts
63class A {
64   public static foo(): int
65   {
66      return 10 * 10;
67   }
68   public static x: int = 100;
69}
70
71let a = new A();
72```
73
74with expression to evaluate after declaration of `a` variable `a.foo() == a.x`.
75
76The plugin deserializes a class from debugging information into an AST class consisting of empty methods and fields, which is equivalent to the following code:
77```ts
78class A {
79   public static foo(): int {}
80   public static x: int;
81}
82```
83
84The following bytecode will be generated:
85```
86.record A <external> {
87   i32 x <external>
88}
89
90.function i32 A.foo(A a0) <external, access.function=public>
91```
92
93In other words, we create an empty entity for class A in the AST to pass all frontend checks in order to make it possible to address variable of type, that don't exists in current context.
94After the frontend emits the bytecode, the bytecode will contain record of class A with `external` annotation for the class itself and for all used fields and methods.
95
96## ScopedDebugPlugin architecture
97
98![image info](./images/arkts-debugger-expression-evaluation.svg)
99
100Note that `PathResolver` can't obtain information from the `ImportExportTable`, because this information currently is not recorded in the debug information.
101