2013-04-26 11 views
5

私のクラスプロジェクトでは、(シンプルな)Schemeコンパイラを実装する必要があります。Scheme/Lisp実装でガベージコレクタを使用していません

この時点で、私はさまざまな機能を実装する方法をブレーンストーミングしています。

典型的なSchemeの実装が複雑なGCを悩ますのはなぜですか?コードが本当に機能している場合(副作用なし)、現在実行されていない関数は割り当てられたメモリを保持できません。今まで! (漏れがなければ!)

したがって、ほとんどの命令型言語の後に続くCのような戦略、つまりスタック割り当てを使用しないでください。新しい語彙コンテキスト(すなわち、(define (foo ..)または(letrec ...)が入力されるたびに、変数記憶域をスタックに割り当てて、コンテキストが終了したら単純にスタックポインタを調整します。

スキームにはmalloc()があり、事前定義された型だけの割り当てが許可されているため、単純な実装ではプールまたはゾーンのアロケータを使用できるため、「スタック」は決してフラグメント化しません。

私はクロージャを実装する必要はありませんが、バインディングされた値を別のスタックにコピーすることで、クロージャの状態を排他的に追跡するために使用することもできます。

思考?

+3

しかし、コードは本当に機能的ではないので、 'set!'、 'set-car!'や 'set-cdr!'のような状態を変更する操作は、標準Schemeの実装の一部です。あなたの(シンプルな)Schemeコンパイラがこれらの操作を許さず、クロージャを実装する必要がないなら、より簡単なGC戦略が可能かもしれません。 –

+5

単純な例を考えてみましょう:関数はリストを返します。関数は、元のリストのすべての2番目の要素からなる新しいリストを作成します。あなたの地域分析は、どのように元のリスト要素のどの部分が第2の機能の終了時にもはや必要ではないと推定するでしょうか?最も基本的なラムダ計算でさえも領域を推論する方法はまったくありません。 –

+0

Schemeコンパイラは、Schemeランタイムのガベージコレクタを実装するという問題からはるかに離れています。最初に「シンプルな」コンパイラに注目してください。 – GoZoner

答えて

6

クロージャなしでも、エイリアシングは難しい部分です。具体的には、プロシージャが構造化されたデータを作成し、その一部を返すとします。あなたはどの部分を解放するかをどのように決定しますか?この問題を解決できるのであれば...ガベージコレクションを再発明しただけです。

多少異なるところがありますが、プログラマーが地域を使ってすべてのGCを避け、プログラマーを要求することで、システムレベルの言語であるRust(www.rust-lang.org)異なるポインタ型を使用して所有権を明示的に追跡できます。

+0

OPはGCを使用しません。だから、あなたはそれのどの部分も解放しない:P。これは、GCなしで他の言語でやっていることと変わらず、GCを再発明する必要はありません。ちょうどC/C++プログラマのようにする必要はありませんでした。 – MasterMastic

+0

C&C++のような言語では、プログラマは通常free()を使ってメモリを解放する責任があります。だから、あなたがfree()(あるいは、おそらく、(無料))、あるいは単にメモリを解放しないようなスキームを提案していない限り、あなたの答えは私には意味がありません。 –

+0

ええ、フリー機能は、まさに私が言っていることです。 GCを使用しないと、最終的に私が個人的にメモリを解放する唯一の方法です。そして、いいえ、私は決して記憶を解放しない言語を提案しません。 – MasterMastic

5

呼び出し元への戻りオブジェクトの実行を終了する関数。それらのオブジェクトは、それらの関数のスタックフレームに割り振ることができません。

したがって、値の返却を禁止する必要があります(この場合、関数型プログラミングではないプロシージャがあります。有用な操作を行うには、これらのプロシージャに副作用が必要です)。

また、オブジェクトを返すと、返された関数のスタックフレーム(後で割り当て解除される)から呼び出し元のスタックフレームにコピーされます。

価値システムには、パフォーマンスと意味の制限があります。

関連する問題