使用参数预编译文本替换宏

Posted

技术标签:

【中文标题】使用参数预编译文本替换宏【英文标题】:Pre-compile textual replacement macro with arguments 【发布时间】:2021-08-05 14:09:28 【问题描述】:

我正在尝试创建某种dut_error 包装器。将接受一些参数并以特定方式将它们构造为dut_error 的东西。

我不能使用方法来替换对dut_error 的调用,因为据我了解,check that ... then ... else 之后只能出现dut_error(或dut_errorf)。事实上,如果我尝试做类似的事情:

my_dut_error(arg1: string, arg2: string) is 
    dut_error("first argument is ", arg, " and second argument is ", arg2);
;

check that FALSE else my_dut_error("check1", "check2");

我收到一个错误:

*** Error: Unrecognized exp
 [Unrecognized expression 'FALSE else my_dut_error("check1", "check2")']
     at line x in main.e
         check that FALSE else my_dut_error("check1", "check2");
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

所以我想定义一个宏来简单地将我的包装器的文本替换为实际的dut_error

define <my_dut_error'exp> "my_dut_error(<arg1'name>, <arg2'name>)" as 
    dut_error("first argument is ", <arg1'name>, " and second argument is ", <arg2'name>)
;

但是遇到了同样的错误。

然后我读到了预处理器指令#define 所以尝试了:

#define my_dut_error(arg1, arg2) dut_error("first argument is ", arg, " and second argument is ", arg2)

但这只是给出了一个语法错误。

我如何定义一个带参数的预编译文本替换宏,类似于 C?


我想这样做的原因是为了实现dut_error 的某种“接口”,因此所有错误都具有一致的结构。这样,不同的人编写不同的错误只会传递该接口所需的参数,并在内部创建适当的消息。

【问题讨论】:

【参考方案1】:

不确定我是否理解你想在包装器中做什么,但也许你可以通过使用 dut_error_struct 来实现你想要的。

它有一组 api,你可以将它们用作钩子(当错误被捕获时做一些事情)并查询特定的错误。 例如:

extend dut_error_struct 
   pre_error() is also 
      if source_method_name() == "post_generate" and 
         source_struct() is a BLUE packet 
         out("\nProblem in generation? ", source_location());
         // do something for error during generation
    ;
    write() is first 
       if get_mesage() ~ "AHB Error..." 
           ahb_monitor::increase_errors();
       ;
    ; 
    
;

【讨论】:

这看起来是我需要的一个非常好的选择。有没有办法以这种方式提取传递给dut_error 的参数?请参阅我编辑的问题以进行澄清【参考方案2】:

dut_error 接受一个参数,一个字符串。但是您可以决定一个“分隔符”,它将定义消息的两个部分。 例如- 指示人们在消息中在“第一个参数”和“第二个参数”之前写上“XXX”。

check that legal else dut_error("ONE thing", "XXX", "another thing");
check that x < 7 else dut_error("failure ", "XXX", "of x not 7 but is ", x);


extend dut_error_struct 
    write() is first 
        var message_parts := str_split(get_message(), "XXX");
    
    if message_parts.size() == 2 
        out ("First part of message is ", message_parts[0],
             "\nand second part of message is ", message_parts[1]
            );
    ;
;

【讨论】:

据我了解(不是专家专家),get_message() 返回将打印的完整消息。也就是说,即使我传递了多个参数,它们也会被连接到一个字符串并通过get_message() 返回。我希望能够在连接这些参数之前分别获得这些参数。当然,最好不要强制传递分隔符参数。难道没有一种简单的方法可以获取所有参数吗? 非常感谢您的回答!他们在这个问题的思考过程中帮助了我,我觉得这个问题可能是一个 XY 问题,我在这里问错了。我制定了另一个更具体到我需要的问题,所以如果你有答案,那就太好了。这是here【参考方案3】:

使用dut_errorf 方法结合定义格式字符串的预处理器指令,我可以非常接近我想要的:

#define DUT_FORMAT "first argument is %s and second argument is %s"

check that FALSE else dut_errorf(DUT_FORMAT, "check1", "check2");

但我仍然更喜欢不需要 DUT_FORMAT 指令的方式,而是使用 dut_error_struct 或类似的东西。

【讨论】:

以上是关于使用参数预编译文本替换宏的主要内容,如果未能解决你的问题,请参考以下文章

C语言宏定义宏替换

宏编程是啥?

第八章 编译预处理

c语言宏定义有无参数的区别

C++笔试常见问题

预编译时宏替换 见解