ステートメントのブロックを使用する手続き型 EDSL があります。
これらのステートメントは、特定の順序でブロックに追加されませんが、ステートメント間に依存関係がある場合があります。
ただし、EDSL のコンパイル中は、ステートメントが依存の順序で並べられていることを確認する必要があります。
B := A
C := B
E := D
すべてのステートメントに依存関係があるわけではないため、完全な順序はありません (たとえばE := D
、上記は独立しており、どこにでも配置できます)。循環的な依存関係がないため、リストの順序付けが可能になるはずです。
ステートメントに依存関係がないことを意味するwhich を使用Data.List.sortBy
して定義することにより、ソリューションをハックしようとしました。これはいくつかの例では機能しましたが、一般的なケースでは機能しませんでした。たとえば、次の順序で何もしませんでした:Ordering
EQ
C := B B := A
D := C = should produce => C := B
B := A D := C
これは、デフォルトの並べ替え挿入並べ替えが、挿入されたアイテムが次のものより小さいか等しいことを確認するためです。
インターネットでPosetの実装を検索しましたが、該当するものは見つかりませんでした:
altfloat:Data.PosetはOrdering = LT | GT | EQ | NC
( NC
Non-comparable の場合) を定義しますが、提供されたものは-like非比較項目をsort
想定し、単にそれらを破棄します。NaN
logfloat:Data.Number.PartialOrdは、使用法を除いて上記と似ておりMaybe Ordering
、パッケージのどこにもソート機能がありませんでした。
Math.Combinatorics.Poset使用方法や適用可能かどうかはわかりません。
以下は、拘束力のあるステートメントと拘束力のないステートメントの両方を持つ最小限の例です。非バインド ステートメントの順序は重要であり、それらは元の順序を維持する必要があります (つまり、並べ替えは、依存関係を持たない wrt ステートメントに対して安定している必要があります)。
本格的な依存グラフを使用せずに、これに対する簡単な解決策があることを願っています...
module Stmts where
import Data.List ( sortBy )
data Var = A | B | C | D | E | F | G | H deriving (Eq, Show)
data Stmt = Var := Var
| Inc Var
deriving (Show)
-- LHS variable
binds :: Stmt -> Maybe Var
binds (v := _) = Just v
binds _ = Nothing
-- RHS variables
references :: Stmt -> [Var]
references (_ := v) = [v]
references (Inc v) = [v]
order :: [Stmt] -> [Stmt]
order = sortBy orderStmts
orderStmts :: Stmt -> Stmt -> Ordering
orderStmts s1 s2 = ord mbv1 mbv2
where
ord Nothing Nothing = EQ -- No dep since they don't bind vars
ord (Just v1) Nothing = LT -- Binding statements have precedence
ord Nothing (Just v2) = GT -- ^^^
ord (Just v1) (Just v2) -- Both statements are binding:
| v1 `elem` refs2 = LT -- * s2 depends on s1
| v2 `elem` refs1 = GT -- * s1 depends on s2
| otherwise = EQ -- * neither
-- *Maybe* they bind variables
mbv1 = binds s1
mbv2 = binds s2
-- Variables they reference
refs1 = references s1
refs2 = references s2
-- The following should return [B := A, C := B, D := C, Inc F, Inc G]
test = order [Inc F, Inc G, C := B, D := C, B := A]