[英]Compiling functional languages to C
假設您正在為便攜式C編譯函數式語言,並且假設由於各種原因您需要精確而非保守的垃圾收集。 垃圾收集器沒有可移植的方法(在一般情況下可能完全沒有辦法)來弄清楚什么是C堆棧上的指針而不是指針。 在我看來,這個問題有兩個解決方案:
影子堆棧。 使每個C函數保持關於什么是指針和不是指針的簿記信息。 這是LLVM推薦的方法。
利用您正在編譯函數式語言的事實,這意味着主線代碼沒有副作用。 當分配器檢測到內存不足時,不是調用垃圾收集器本身,而是使用longjmp將當前操作中止回主循環,主循環調用垃圾收集器(在可能包含指針的變量集已知的上下文中)提前)然后重新開始操作。
在我看來,如果你正在處理第二種方法適用的純函數式語言,它必須比第一種方法更有效,並且更容易與手寫的C語言混合。
我有什么問題可以忽略嗎? 對此技術的現有討論或實現的任何引用?
可以使用單個數據結構設計純FP語言:
typedef enum record_type { RT_SYMBOL, RT_NUMBER, RT_PAIR };
struct record
{
record_type type;
void *value;
};
程序和數據可以使用records
pairs
表示:
struct pair
{
record *car;
record *cdr;
};
這是一個簡單的表達式 - 2 * 3
- 如何使用records
來表示:
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;
這與Lisp表達式相同: (* 2 3)
。 現在,您可以定義一pairs
在pairs
上運行的機器,將car
視為操作員,將cdr
視為操作數。 由於我們只處理一種數據結構,因此可以使用精確的GC。 有關此類VM的體系結構,請參閱Lispkit Lisp 。
在開始嘗試編寫FP - > C編譯器之前,還要閱讀Small Pieces中的Lisp 。
我認為你沒有描述的最明顯的事情是如何處理持久的內存不足。 正如您所描述的那樣,假設我的操作使用的內存多於可用內存。 最終我到達:
也就是說,一個無限循環。 所以至少你想要某種世代垃圾收集,它允許你檢測循環並退出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.