Saya sedang mengerjakan penerjemah bahasa pemrograman sederhana di Haskell dan saya memiliki sedikit masalah saat mendefinisikan perpustakaan standar. Saya ingin itu didefinisikan sebagai string statis di tingkat atas dan dikompilasi bersama dengan penerjemah saya:

stdLibStr :: String
stdLibStr = "id a := a;;"

parse :: String -> Either Error UntypedModule
typecheck :: UntypedModule -> Either Error TypedModule

-- constexpr
stdLib :: TypedModule
stdLib = either (error . show) id $ parse stdLibStr >>= typecheck

Namun, model di atas tidak akan mengevaluasi stdLib selama waktu kompilasi. Selain itu, itu tidak akan memberi saya umpan balik tentang kesalahan penguraian atau pengecekan ketik. Saya ingin juru bahasa saya tidak mengkompilasi jika parse atau typecheck mengembalikan Left seperti pada contoh berikut:

stdLibString = "≠²³¢©œęæśð"

-- Compilation error: "cannot parse definition"
stdLib = either (error . show) id $ parse stdLibStr >>= typecheck

Saya mencoba untuk mencapai ini menggunakan fail saat mendefinisikan QuasiQuotation untuk bahasa saya, tetapi karena beberapa masalah lain tidak mungkin untuk memiliki kutipan seperti itu.

Bagaimana melakukannya dengan cara yang paling nyaman?

1
radrow 20 Maret 2019, 17:50

1 menjawab

Jawaban Terbaik

Seperti yang disarankan dalam komentar, Template Haskell adalah cara untuk melakukan ini. Fungsi di bawah ini menangani dua kasus:

compileTime :: Lift a => Either String a -> Q Exp
compileTime (Right a) = lift a
compileTime (Left err) = fail err

Itu dapat dipanggil sebagai $(compileTime (typecheck =<< parse stdLibStr)). Atau cukup pendek untuk inline sebagai either fail lift sebagai gantinya.

Untuk menggunakan ini, fungsi apa pun yang dipanggil dalam $() harus didefinisikan dalam modul terpisah dari tempat ia dipanggil.

1
bergey 21 Maret 2019, 22:02