1

已解决:我想出了一个干净的方法来使用setjmp()/ longjmp(),只需要一个最小的包装器,比如:

int jump(jmp_buf j, int i) { longjmp(j, i); return 0; }

这允许jump()在条件表达式中使用。所以现在代码:

if (A == 0) return;
output << "Nonzero.\n";

正确翻译为:

return
((A == 0) && jump(caller, 1)),
(output << "Nonzero.\n"),
0;

回到调用函数中的调用点在caller哪里。jmp_buf清洁、简单和高效,其程度远低于异常的实现定义。感谢您的帮助!


有没有办法在表达式中间模拟流控制结构的使用?是否有可能在逗号分隔的表达式x, yy导致 a return?

编辑:我正在为类似于功能语言的东西开发编译器,目标语言是 C++。一切都是源语言中的表达,而最理智、最简单的目标语言翻译会留下尽可能多的表达。基本上,目标语言中的分号变成了 C++ 逗号。到目前为止,语言内流控制结构没有出现任何问题。它只是return。我只需要一种过早退出逗号分隔表达式的方法,并且我不希望使用异常,除非有人可以告诉我他们在这种情况下没有过多的开销。

问题当然是大多数流控制结构不是 C++ 中的合法表达式。到目前为止,我发现的唯一解决方案是这样的:

try {

    return
    x(),                        // x();
    (1 ? throw Return(0) : 0);  // return 0;

} catch (Return& ret) {

    return ref.value;

}

return语句始终存在(在Return未达到构造的情况下),因此throw必须将其包装起来?:以使编译器关闭其void在表达式中使用的结果。

我真的很想避免使用异常来进行流控制,除非在这种情况下可以证明不会产生特别的开销;抛出异常会导致展开或任何事情吗?此代码需要以合理的效率运行。我只需要一个相当于exit().

4

3 回答 3

1

做什么的?C++ 是命令式语言。表达式只是表达式。如果您想将所有内容都用作表达式/函数,请使用函数式语言。

于 2010-04-21T12:21:52.263 回答
1

您可能想研究一下cfront,这是一个 80 年代末/90 年代初将 C++ 翻译成 C 的程序(当时没有模板或异常),因为本地 C++ 编译器(如果有的话)很少。

它处理内联函数的方式与您尝试做的非常相似:大量的三元 ( ?:) 运算符、逗号和括号。但是,它不能将具有比 if/then 更复杂的控制流的内联函数(例如fororwhile循环)转换为表达式,并且必须将该函数实现为非内联函数。

“过早退出逗号分隔的表达式”的唯一方法是使用三元运算符和括号。例如:

(
    first thing,
    second thing,
    test expression?
    (
        next thing if successful,
        another thing,
        return value
    )
    :( // How often can you use an emoticon as an operator, anyway?
        something to do if unsuccessful,
        more cleanup,
        return value
    )
)

如果编译器没有短路三元运算符的 then 和 else 子句,那么你就不走运了。

于 2010-04-21T12:58:47.087 回答
0

我觉得您只有一个关于必须如何执行翻译过程的功能规范(例如,在前置条件和后置条件方面)。由于 C++不是一种声明性语言,而是一种命令性语言,因此您必须在开始编码之前为自己推导出该翻译过程的程序实现。而且,正如您已经看到的,这并不像使用逗号连接所有原始表达式那么简单。

您要做的是让 C++ 编译器为您完成工作。这是行不通的,因为 C++ 不是一种声明性语言,它的编译器不会动态地尝试从规范中解释您的意思。而且,如果这可行,C++ 将不得不只是另一种动态声明性语言,而您可能会针对另一种静态语言。

关于可行的提示:完全分析每个原始表达式(及其可能的副作用),然后才输出代码。如果你的表达式是复合的(它有子表达式),在你分析了更大的表达式之前不要输出任何东西。

于 2010-04-21T13:05:48.490 回答