2013-04-12 14 views
6

Próbuję zacząć od wiązania LLVM dla Haskell. Świetnym miejscem na rozpoczęcie jest Hello World.Haskell LLVM binding Niejednoznaczny Typ

Poniżej znajduje się na blogu autora wiążące.

bldGreet :: CodeGenModule (Function (IO())) 
bldGreet = do 
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32) 
    greetz <- createStringNul "Hello, World!" 
    func <- createFunction ExternalLinkage $ do 
     tmp <- getElementPtr greetz (0::Word32, (0::Word32,())) 
     call puts tmp -- Throw away return value. 
     ret() 
    return func 

Nie kompiluje się.
Zamiast dostać „Niejednoznaczne typ zmiennej n0' in the constraint: (type-level-0.2.4:Data.TypeLevel.Num.Sets.NatI n0) arising from a use of getElementPtr0' Prawdopodobna fix: dodać podpis typu, która rozwiązuje te zmienną (y) Typ”

Oto odmiana, która działa

llvmModule :: TFunction (IO Word32) 
llvmModule = 
    withStringNul "Hello world!" $ \s -> do 
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32) 
    main <- newNamedFunction ExternalLinkage "main" :: TFunction (IO Word32) 
    defineFunction main $ do 
     tmp <- getElementPtr0 s (0::Word32,()) 
     _ <- call puts tmp 
     ret (0::Word32) 
    return main 

Pierwszy wydaje bardziej naturalne. Pytanie, które mam, to jaka jest niejednoznaczność w pierwszym i jak to naprawić. Drugie pytanie, jakie mam, brzmi: dlaczego drugi nie jest dwuznaczny.

+0

czy to może być literówka i zapomniałem 0? getElementPtr0 <-? Po prostu zgaduję. –

+0

Nie. Istnieją dwie różne funkcje. getElementPtr0 używa wartości domyślnej, gdzie getElementPtr nie ma - stąd dodatkowy argument. Ponadto, błąd jest, jestem prawie pewny, rzeczą typograficzną. To (GHC) chce, żebym powiedział mu coś bardziej szczegółowego na temat typografii. Po prostu nie zrozumiałem, czego chce. –

+0

Może http://hpaste.org/ kompletne rzeczy, więc profesjonaliści mogą się z nim bawić :) –

Odpowiedz

1

OK. Więc rozwiązałem problem. Rzeczywiście jest to typ typograficzny. I tylko bardziej mnie to zdezorientowało. Jednak mam odpowiedź na rozwiązanie. Ale nie wahaj się pomóc mi zrozumieć. Najpierw trochę kopania. Funkcja createStringNul ma typ

createString :: String -> TGlobal (Array n Word8) 

Dobrze. Problem, jaki kompilator miał, polega na tym, że "n" w rodzaju tablicy jest niejednoznaczne. Może to być dosłownie wszystko na świecie. Lookup, Array, a zobaczysz

newtype Array n a 

Teraz nie jest to tak oczywiste, ale po trochę kopania, zwłaszcza wrt wezwanie do getElementPtr, jeden stwierdza, że ​​n, naprawdę powinno być Nat n, która jest typowy sposób na ustalenie rozmiaru tablicy. Definicja Array n a, właściwie nie obchodzi, że jest tak naprawdę synonimem typu dla [a]. Możesz więc użyć D0, D9 lub cokolwiek chcesz z pakietu Data.TypeLevel.Num.Reps . Naprawiono rozmiar tablicy, podczas gdy dobry pomysł nie był faktycznie brany pod uwagę przez tę funkcję. Ale tak czy inaczej, zmieniając greetz < - createStringNul "Hello, World!" do greetz < - createStringNul "Hello, World!" :: TGlobal (Array D0 Word8) działa.

Oto interesująca część ... Nie oczekiwałem, że zadziała. D0 ma wynosić 0, więc nie rozumiem, dlaczego pozwalało mi na przechowywanie tylu znaków w rozmiarze 0 "Array". Jednak jeśli spojrzysz na kod źródłowy, od razu wiadomo, że ograniczenie typu nie jest tak naprawdę zwrócił uwagę na.

Dobrze, cokolwiek, po kompilacji zdaje sobie sprawę, że createStringNul jest przestarzałe, a zamiast tego preferowany jestStringNul. Z tym, że nie do końca rozumiem, jak działają typy withStringNul.

1

createStringNulis marked as deprecated w aktualnej wersji llvm (3.0.1.0). Użyj withStringNul:

import Data.Word 
import LLVM.Core 

bldGreet :: CodeGenModule (Function (IO())) 
bldGreet = do 
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32) 
    func <- withStringNul "Hello, World!" $ \greetz -> 
     createFunction ExternalLinkage $ do 
     tmp <- getElementPtr greetz (0::Word32, (0::Word32,())) 
     _ <- call puts tmp -- Throw away return value. 
     ret() 
    return func 

, co powoduje błąd w pierwszym przykładzie jest to związane z faktem, że withStringNul ma typ bardziej pouczające: withStringNul :: String -> (forall n . Nat n => Global (Array n Word8) -> a) -> a - por do createStringNul :: String -> TGlobal (Array n Word8). Argument funkcji withStringNul ma higher-rank type - oznacza to, że funkcja działa dla wszystkich n gdzie n jest liczbą naturalną.

Jeśli naprawdę chcesz używać createStringNul można uczynić pierwszy przykład kompilacji dodając wyraźny podpis typu dla greetz:

{-# LANGUAGE TypeOperators #-} 
module Test 
     where 

import Data.Word 
import Data.TypeLevel.Num.Reps 
import LLVM.Core 

bldGreet :: CodeGenModule (Function (IO())) 
bldGreet = do 
    puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32) 
    greetz <- createStringNul "Hello, World!" 
    func <- createFunction ExternalLinkage $ do 
     tmp <- getElementPtr (greetz :: Global (Array (D1 :* D3) Word8)) (0::Word32, (0::Word32,())) 
     call puts tmp -- Throw away return value. 
     ret() 
    return func 

Konstruktor :* typ comes from the type-level package i jest używany do konstruowania liczb typ poziomu. D1 :* D3 oznacza, że ​​tablica ma rozmiar 13.

+0

Wygląda na to, że napisałeś zaraz po tym. Zasadniczo zrozumiałem, co powiedziałeś. Problem polega jednak na tym, że użycie funkcji zStringNul ... drugim argumentem musi być cały tworzony moduł CodeGenModule. Jeśli czujesz się zupełnie nienaturalnie w użyciu. –

+0

@ArmUser Argument funkcji 'withStringNul' ma typ' (forall n. Nat n => Global (Array n Word8) -> a) '. Jego typem zwracanym jest 'a', który może być dowolnego typu - niekoniecznie" CodeGenModule ". 'CodeGenModule' w typie' createFunction' jest monadycznym kontekstem obliczeniowym. Samo 'createFunction' zwraca' funkcję' - ale ponieważ nie można utworzyć funkcji poza modułem, 'createFunction' działa wewnątrz monadę' CodeGenModule'. –

+0

@ArmUser Ogólnie rzecz biorąc, jest to dość naturalny idiom Haskell. Cf. z ['withFile'] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#v:withFile) w' System.IO'. –