我想实现以下功能:
延长RED GREEN BLUE包{...}
此行将导致大括号中的struct成员, 要添加到某个枚举类型的所有指定子类型。 结果将如下所示:
extend RED packet {...}
extend BLUE packet {...}
extend GREEN packet {...}
延长BIG MEDIUM RED BLUE GREEN包{...}
这一行将扩展所有可能的组合 具有struct成员的每个枚举类型的项目 出现在花括号中。 结果将如下所示:
extend MEDIUM RED packet {...}
extend MEDIUM BLUE packet {...}
extend MEDIUM GREEN packet {...}
extend BIG RED packet {...}
extend BIG BLUE packet {...}
extend BIG GREEN packet {...}
谢谢,
答案 0 :(得分:2)
这个宏解决了这个问题,但是存在一个小的限制。 由于此宏是“定义为计算”,因此应将其应用于的结构应定义在与使用宏的文件不同的文件中。 这里显示了一个简单的用例:(假设此宏位于名为dac.e的文件中):
define <multi_when'statement> "ext_s \[<detr'name>,...\] <base'type> \{<sm'exp>,...\}" as computed {
var our_struct:rf_struct=rf_manager.get_type_by_name(<base'type>).as_a(rf_struct);
var fields:list of rf_field = our_struct.as_a(rf_struct).get_declared_fields();
var rf_type_list:list of rf_type;
var list_of_0_index:list of uint;
var field_names:list of string;
var list_of_enums:list of rf_enum;
var temp_index:uint=0;
var used_types_list:list of rf_type;
var enumerations:list of string;
var indices:list of uint;
var num_of_each_enum:list of uint;
var size_of_final_list_of_enumerations_to_be_used:uint=1;
var enum_items_list:list of rf_enum_item;
var final_list_of_enumerations_to_be_used: list of string;
var multiplication_list_algrtm1:list of uint;
var multiplication_list_algrtm2:list of uint;
var multiplication_uint_algrtm:uint=1;
if (<detr'names>.is_empty()){
error("you did not supply any when subtypes");
};
for each (field) in fields{
rf_type_list.add(field.get_type());
field_names.add(field.get_name());
};
for each (typ) in rf_type_list{
if (rf_type_list[index] is not a rf_enum){
rf_type_list.delete(index);
field_names.delete(index);
};
};
if (rf_type_list.is_empty()){
error("the type ",<base'type>," does not have any enumerated type fields.");
};
for each (typ) using index (typ_index) in rf_type_list {
num_of_each_enum.add(0);
if(indices.is_empty()){
indices.add(0);
}else {
indices.add(indices[typ_index-1])
};
enum_items_list = typ.as_a(rf_enum).get_items();
for each (enum_item) in <detr'names> {
if (enum_items_list.has(it.get_name()==enum_item)){
out(enum_item, " is found in ",typ.get_name());
enumerations.add(append(enum_item,"'",field_names[typ_index]));
indices[typ_index]+=1;
num_of_each_enum[typ_index]+=1;
};
};
};
for each in num_of_each_enum do { // avoid enums that are not used - to
if (it==0){
list_of_0_index.add(index);
};
};
if (!list_of_0_index.is_empty()){
list_of_0_index=list_of_0_index.reverse();
for each in list_of_0_index {
num_of_each_enum.delete(it);
indices.delete(it);
field_names.delete(it);
}
};
enumerations=enumerations.unique(it);
if (enumerations.is_empty()){
error("no legal enumerated values were used in the ext_s macro, please check that the arguments in square brackets are in the form of [<enum_item1>,<enum_item2>,...]");
};
//remove the last index (not relevant - and add 0 in the indices[0]
indices.add0(0);
indices.delete(indices.size()-1);
for each in num_of_each_enum do {
size_of_final_list_of_enumerations_to_be_used*=it;
};
for each in num_of_each_enum do {
multiplication_uint_algrtm*=it;
multiplication_list_algrtm1.add(size_of_final_list_of_enumerations_to_be_used/multiplication_uint_algrtm);
multiplication_list_algrtm2.add(size_of_final_list_of_enumerations_to_be_used/multiplication_list_algrtm1[index]);
};
//build the final list of string to be used in the extend statement:
for i from 1 to size_of_final_list_of_enumerations_to_be_used{
final_list_of_enumerations_to_be_used.add("");
};
for k from 0 to indices.size()-1 do {
temp_index=0;
for j from 0 to multiplication_list_algrtm2[k]-1 do {
for i from 0 to multiplication_list_algrtm1[k]-1 do {
final_list_of_enumerations_to_be_used[temp_index]=append(final_list_of_enumerations_to_be_used[temp_index]," ",enumerations[indices[k]+j%num_of_each_enum[k]]);
temp_index+=1;
};
};
};
for each in final_list_of_enumerations_to_be_used do {
result = appendf("%s extend %s %s {",result,it, <base'type> );
for each in <sm'exps> do {
result= appendf("%s %s;",result,it);
};
result = append(result , "};");
};
print result;
};
请注意,此宏解决了一个有趣的问题: 假设你有一堆特定类型的项目列表(例如:{a1,a2,b1,b2,c1,c2,c3 ...}), 而且你没有初步知道这个列表中有多少类型(在这个例子中有3种类型-a,b,c - 但可能有更多或更少)。所以问题是,如何创建所有类型的所有项目的所有可能组合的列表(例如:0. a1-b1-c1 1.a1-b1-c2 ... ..11.a2-b2-c3),不知道列表中有多少种类型?您可以按照代码并找出算法来做到这一点(使用索引列表,每种类型有多少项,等等......)。 应在宏(dac.e)之前加载的文件是:
Struct.e:
<'
type t1:[A1,A2,A3,A4,A5];
type t2:[B1,B2,B3];
type t3:[C1,C2,C3];
struct s{
a:uint(bits:4);
t_1:t1;
t_2:t2;
t_3:t3;
};
'>
测试文件是:
<'
Import dac.e;
import struct.e;
//use the macro
ext_s [A1,A2,B1,B2] s {x:int,keep x==6,y:int,keep y==10};
extend sys{
s1:A1 B1 s;
s2:A2 B1 s;
s3:A1 s;
run() is also{
print s1;
print s2;
print s3;
};
};
'>
如果您有任何疑问,请发表评论。