-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathe_util_invoke_methods.e
102 lines (71 loc) · 2.97 KB
/
e_util_invoke_methods.e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
File : e_util_invoke_methods.e
Title : Invoke methods using reflection
Project : Utilities examples
Created : 2019
:
Description :
Iterating over units invoking methods, using reflection.
Assume some subtypes of a unit define some method, and some do not.
This utility goes over all the instances of the base unit, and for each
of them that defines the requested method - calls it.
Note that this utility has a parameter "params" which is a list of untyped
- as we do not know the type of the parameters of the methods we are about
to invoke. So, when calling this utility - have to "unsafe" each of the
parameters.
(There are other ways to design the environment. For example - define
'interface' containing the methods of interest, and define the relevant
subtypes as 'implementing the interface'. But here we want to demonstrate
'invoke')
To make your users life easier - wrap this method with a macro.
Usage example:
Calling invoke_methods_in_tree():
specman -c 'load e_util_invoke_methods; load sample_env; gen; sys.invoke_methods_in_tree(sys.env, "inject_data", {FALSE.unsafe(); 0xbb.unsafe()})'
Calling the wrapping macro:
specman -c 'load e_util_invoke_methods; load sample_env; gen; iterate sys.env inject_data( FALSE, 0xaa)'
or
specman -c 'load e_util_invoke_methods; load sample_env; load example;test'
invoke_methods_in_tree() implementation
<'
extend sys {
//
// invoke_methods_in_tree()
//
invoke_methods_in_tree(root_unit : any_unit,
method_name : string,
params : list of untyped) is {
var method_rf : rf_method;
var child_units_instances : list of any_unit;
child_units_instances = rf_manager.get_all_unit_instances(root_unit);
for each (u) in child_units_instances {
method_rf =
rf_manager.get_exact_subtype_of_instance(u).get_method(method_name);
if method_rf != NULL {
compute(method_rf.invoke_unsafe(u, params));
};
};
};
};
'>
macro wrapping the methods, saving users from writing "unsafe" in
parameters list
<'
define <e_util_iterate'action> "iterate <root'exp> <method'name>\(<exp>,...\)" as computed {
result = append(result, "sys.invoke_methods_in_tree(",
<root'exp>, ", \"", <method'name>,"\",{");
// Pass the parameters list, after converted to untyped, using unsafe()
if not (<exps>.is_empty()) {
for each (arg) in <exps> {
result = append(result,"(",arg,").unsafe();");
};
// remove last ";" from result
result = str_chop(result,str_len(result)-1);
};
result = append(result,"});");
};
'>
// Example of calling the macro from method:
extend env {
run() is also {
iterate me inject_data( FALSE, 0xcc);
};
};