When you write a define-as or define-as-computede macro, you sometimes need the replacement code to contain or to depend on the source information regarding the specific macro call, including the source module and the source line number.
For example, a macro may need to print source information, or it may need to create different code when used in one module than it needs to create when used in other modules.
You can achieve this as follows.
Define-as macro
In a define-as macro, you can use the following two special kinds of replacement terms inside the replacement block:
<current_line_num> | This is replaced with the decimal numeric representation of the source line number in which the macro is called. |
<current_module_name> | This is replaced with the name of the module in which the macro is called. |
For example, the following macro modifies the given left hand side expression (such as a field or a variable) to the given value, and prints an informational message reporting this change.
<'
define <my'action> "modify_and_print <field'exp> <value'exp>" as {
<field'exp> = <value'exp>;
out("*** The value of <field'exp> was changed to ", <value'exp>,
" at line <current_line_num> in @<current_module_name>");
};
‘>
Assume the following code is then written in a module called my_module.e:
<'
extend sys {
!x: int;
run() is also {
modify_and_print x 10;
};
};
‘>
This code will assign the value 10 to the field x, and will print the following output:
*** The value of x was changed to 10 at line 5 in @my_module
Define-as-computed macro
In a define-as-computed macro, the following two pre-defined routines can be used to query the current source line number and the current module.
get_current_line_num(): int | This routine returns the source line number in which the macro is called. |
get_current_module(): rf_module | This routine returns the reflection representation of the module in which the macro is called. |
To get the module name string, similarly to <current_module_name> in define-as macros, use the get_name() method of rf_module.
For example, the following macro adds a new field of type int to the struct in the context of which it is called. The field name is constructed from the current module name and line number. However, if the module name has the "_xxx" suffix, no field is added.
<'
define <my_field'struct_member> "special_field" as computed {
var m_name: string = get_current_module().get_name();
if m_name !~ "/_xxx$/" then {
result = append("f_", m_name, "_",
get_current_line_num(), ": int");
};
};
‘>
The following code, if written in a module called some_module.e, adds two integer fields to sys: f_some_module_3 and f_some_module_4:
<'
extend sys {
special_field;
special_field;
};
‘>
Note however that if the same code is written in a module called some_module_xxx.e, nothing is done.
Yuri Tsoglin
e Language team, Specman R&D