|
|
|
|
|
|
|
|
|
|
|
|
Introduction to Macros
|
|
|
Macro definitions specify a name or a pattern that is to be replaced by e code text. e is a truly extensible language. It can be extended all the way down to its syntax and lexicon using macros declared by define-as statements. Unlike macros in languages such as C, which are preprocessor-based, e macros are real syntactic rules. They actually modify the grammar of the language, introducing new derivation rules. Macros are used to add new construct to the language, possibly with new keywords and operators. The newly declared constructs are implemented by defining a syntactic expansion, reducing them to existing constructs.
|
|
|
|
|
|
define as
|
|
|
You can use replacement macros to extend the e language, by defining new syntactic elements (actions, commands, and so on). The define as statement creates a new syntactic element for the e parser.
|
|
|
|
|
|
Example - define as
|
|
|
|
|
|
1 <'
2 struct frame {
3 size : uint;
4 dest_address : uint;
5 source_address : uint;
6 // Method to print the frame
7 send() is {
8 print me using hex;
9 };
10 };
11
12 define <simple_frame'action>
13 "send simple frame <dest_addr'num> <source_addr'num> <size'num>"
14 as {
15 var f: frame;
16 gen f keeping {
17 .size == <size'num>;
18 .dest_address == <dest_addr'num>;
19 .source_address == <source_addr'num>;
20 };
21 f.send();
22 };
23
24 extend sys {
25 run() is also {
26 send simple frame 0x00fe 0x0010 0xff;
27 send simple frame 0x00ff 0x0011 0x0f;
28 };
29 };
30 '>
You could download file macros1.e
here
|
|
|
|
|
|
|
|
|
|
|
|
Output - define as
|
|
|
|
|
|
me = frame-@0: frame
---------------------------------------------- @macros1
0 size: 0xff
1 dest_address: 0xfe
2 source_address: 0x10
me = frame-@1: frame
---------------------------------------------- @macros1
0 size: 0xf
1 dest_address: 0xff
2 source_address: 0x11
|
|
|
|
|
|
define as computed
|
|
|
This statement creates a new syntactic element that constructs a block of actions based on the inputs to the macro. These actions are executed like a method when the macro is encountered. The actions produce an output string that replaces the match string. The output string is a set of actions that are executed as e code.
|
|
|
|
|
|
Syntax : define <macro-name`nonterminal-type> match-string as computed {action; ...}
|
|
|
|
|
|
Example - define as computed
|
|
|
|
|
|
1 <'
2 extend sys {
3 ! keyed_list: list (key: it) of string;
4 adder() is empty;
5 ! num_list: list of int (bits: 5);
6 run() is also {
7 adder();
8 print num_list;
9 };
10 };
11
12 define <num_adder'statement> "add <exp> to list" as computed {
13 if sys.keyed_list.key_exists(<1>) {
14 return("{}");
15 } else {
16 sys.keyed_list.add(<1>);
17 result = append( "extend sys { adder() is also \
" 18 {num_list.add(",<1>,")};}");
" 19 };
20 };
21
22 '>
You could download file macros2.e
here
|
|
|
|
|
|
1 <'
2
3 import macros2.e;
4
5 add 1 to list;
6 add 2 to list;
7 add 3 to list;
8 add 4 to list;
9 add 5 to list;
10
11 '>
You could download file macros3.e
here
|
|
|
|
|
|
Output - define as computed
|
|
|
|
|
|
num_list = (5 items, dec):
5 4 3 2 1 .0
|
|
|
|
|
|
debuging macros
|
|
|
Debugging macros is one of the most painful part of using them, One of the way the Specman Manual says is use of command.
|
|
|
|
|
|
trace reparse
|
|
|
|
|
|
Personally I hated macros more then anything else in e language. Simple text replacements works great, but "define as" or "define as computed" waste lot of time in writing them and also in debugging them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Copyright © 1998-2014 |
Deepak Kumar Tala - All rights reserved |
Do you have any Comment? mail me at:deepak@asic-world.com
|
|