将函数式语言编译为C语言

时间:2011-08-08 08:43:32

标签: c compiler-construction functional-programming garbage-collection language-implementation

假设您正在为便携式C编译函数式语言,并且还假设出于各种原因您需要精确而非保守的垃圾回收。垃圾收集器没有可移植的方法(在一般情况下可能完全没有办法)来弄清楚什么是C堆栈上的指针而不是指针。在我看来,这个问题有两种解决方案:

  1. 影子堆栈。使每个C函数保持关于什么是指针和不是指针的簿记信息。这是例如推荐的方法。 LLVM。

  2. 利用您正在编译函数式语言的事实,这意味着主线代码没有副作用。当分配器检测到内存不足时,不是调用垃圾收集器本身,而是使用longjmp将当前操作中止回主循环,主循环调用垃圾收集器(在可能包含指针的变量集已知的上下文中)提前)然后重新开始操作。

  3. 在我看来,如果你正在处理第二种方法适用的纯函数式语言,它必须比第一种方法更有效,并且更容易与手写的C混合使用。

    我有什么问题可以忽略吗?对此技术的现有讨论或实现的任何引用?

2 个答案:

答案 0 :(得分:4)

可以使用单一数据结构设计纯FP语言:

typedef enum record_type { RT_SYMBOL, RT_NUMBER, RT_PAIR };

struct record
{
  record_type type;
  void *value;  
};

可以使用pairs的{​​{1}}代表程序和数据:

records

以下是使用struct pair { record *car; record *cdr; }; 表示简单表达式2 * 3 - 的方法:

records

这与Lisp表达式相同:record r1; r1.type = RT_NUMBER; r1.value = &two; record r2; r1.type = RT_NUMBER; r1.value = &three; record opr1; opr1.type = RT_NUMBER; opr1.value = &OP_MULT; /* A machine op-code for multiplication. */ pair p_oprnds; p_oprnds.car = &r1; p_oprnds.cdr = &r2; pair p; p.car = opr1; p.cdr = p_oprnds; 。现在,您可以定义一个在(* 2 3)上运行的计算机,将pairs视为运算符,将car视为操作数。由于我们只处理一种数据结构,因此可以使用精确的GC。有关此类VM的体系结构,请参阅Lispkit Lisp

在开始尝试编写FP之前,请先阅读Lisp in Small Pieces - > C编译器。

答案 1 :(得分:1)

我认为你没有描述的最明显的事情是如何处理持久的内存不足。正如您所描述的那样,假设我的操作使用的内存多于可用内存。最终我达到了:

  1. 开始操作的任何阶段超过限制。
  2. 跑一会儿。
  3. 内存不足。
  4. 释放此阶段分配的所有内存(没有其他内容可供免费使用)。
  5. 转到1.
  6. 即无限循环。所以至少你想要某种世代垃圾收集,它可以让你检测循环并退出。