2013-04-12 35 views
6

Tôi đang cố gắng bắt đầu với việc ràng buộc LLVM cho Haskell. Một nơi tuyệt vời để bắt đầu là Hello World.Haskell LLVM ràng buộc Loại mơ hồ

Sau đây là từ một blog của tác giả về ràng buộc.

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 

Nó không biên dịch.
Thay vào đó tôi nhận được "loại mơ hồ biến n0' in the constraint: (type-level-0.2.4:Data.TypeLevel.Num.Sets.NatI n0) arising from a use of getElementPtr0' sửa chữa dự kiến: thêm một chữ ký kiểu đó sửa chữa các loại biến (s)"

Đây là một biến thể mà làm việc

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 

Đầu tiên dường như tự nhiên hơn. Câu hỏi tôi có là sự mơ hồ trong lần đầu tiên, và làm cách nào để khắc phục nó. Câu hỏi thứ hai tôi có là tại sao thứ hai không mơ hồ.

+0

nó có thể là lỗi đánh máy và quên 0 không? getElementPtr0 <-? Tôi chỉ đoán ở đây. –

+0

Không. Có hai chức năng khác nhau. getElementPtr0 sử dụng một mặc định, trong đó getElementPtr không - vì thế đối số thừa. Ngoài ra, lỗi là, tôi khá chắc chắn, một điều typeclass. Nó (GHC) muốn tôi nói điều gì đó cụ thể hơn về typeclass. Tôi chỉ không tìm ra những gì nó muốn. –

+0

Có lẽ http://hpaste.org/ điều hoàn chỉnh để người chuyên nghiệp có thể thích thú với nó :) –

Trả lời

1

OK. Vì vậy, tôi đã giải quyết được vấn đề. Nó thực sự là một điều typeclass. Và nó chỉ làm tôi bối rối hơn. Tuy nhiên, tôi có một câu trả lời cho giải pháp. Nhưng hãy cảm thấy tự do để giúp tôi hiểu. Đầu tiên, một số đào. Hàm createStringNul có loại

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

Phạt tiền. Vấn đề trình biên dịch đã có là "n" trong loại mảng là mơ hồ. Nó thực sự có thể là bất cứ thứ gì trên thế giới. Lookup, Array, và bạn thấy

newtype Array n a 

Bây giờ nó không phải là quá rõ ràng, nhưng khi một đào nhỏ, đặc biệt là wrt cuộc gọi đến getElementPtr, người ta thấy rằng n, thực sự phải là một n Nat, đó là một loại cấp độ để sửa kích thước của mảng. Bây giờ, định nghĩa của mảng a, không thực sự quan tâm nó thực sự chỉ là một từ đồng nghĩa kiểu cho [a]. Vì vậy, bạn có thể sử dụng D0 hoặc D9 hoặc bất kỳ thứ gì bạn muốn từ gói Data.TypeLevel.Num.Reps . Chỉnh sửa kích thước của mảng, trong khi ý tưởng tốt không thực sự được xem xét bởi hàm này. Nhưng dù sao, thay đổi greetz < - createStringNul "Xin chào, Thế giới!" đến greetz < - createStringNul "Xin chào, thế giới!" :: TGlobal (Array D0 Word8) hoạt động.

Đây là phần thú vị ... Tôi không mong đợi nó hoạt động. D0 được cho là 0, vì vậy tôi không hiểu tại sao nó cho phép tôi lưu trữ quá nhiều ký tự trong một kích thước 0 "Mảng" Tuy nhiên, nếu bạn nhìn vào mã nguồn, rõ ràng là giới hạn kiểu không thực sự chú ý đến.

Tốt, bất cứ điều gì, khi biên dịch một người nhận ra rằng createStringNul không được dùng nữa và thay vào đó, withStringNul được ưu tiên. Ngoại trừ tôi không hoàn toàn hiểu cách các loại của StringNul hoạt động.

1

createStringNulis marked as deprecated trong phiên bản hiện tại llvm (3.0.1.0). Sử dụng 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 

Như những gì gây ra lỗi trong ví dụ đầu tiên, nó liên quan đến thực tế là withStringNul có một loại thông tin mới hơn: withStringNul :: String -> (forall n . Nat n => Global (Array n Word8) -> a) -> a - cf. đến createStringNul :: String -> TGlobal (Array n Word8). Đối số chức năng của withStringNul có một số higher-rank type - điều đó có nghĩa là hàm hoạt động cho tất cả n trong đó n là số tự nhiên.

Nếu bạn thực sự muốn sử dụng createStringNul, bạn có thể làm ví dụ đầu tiên biên dịch bằng cách thêm một chữ ký kiểu tường minh cho 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 

Các :* loại constructor comes from the type-level package và được sử dụng để xây dựng số loại cấp. D1 :* D3 có nghĩa là mảng có kích thước 13.

+0

Dường như bạn đã đăng ngay sau khi tôi đã làm. Tôi đã tìm ra cơ bản những gì bạn nói. Tuy nhiên, vấn đề là sử dụng hàm withStringNul ... đối số thứ hai phải là toàn bộ CodeGenModule đang được xây dựng. Nếu cảm thấy khá bất thường khi sử dụng. –

+0

@ArmUser Đối số hàm của 'withStringNul' có kiểu' (forall n. Nat n => Toàn cầu (Mảng n Word8) -> a) '. Kiểu trả về của nó là 'a', có thể là bất kỳ kiểu nào - không nhất thiết là' CodeGenModule'. 'CodeGenModule' trong kiểu' createFunction' là ngữ cảnh tính toán đơn điệu. Bản thân 'createFunction' trả về một' hàm' - nhưng vì bạn không thể tạo ra một hàm bên ngoài một mô-đun, 'createFunction' chạy bên trong một đơn vị' CodeGenModule'. –

+0

@ArmUser Nói chung, đây là một thành ngữ Haskell khá tự nhiên. Cf. với ['withFile'] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO.html#v:withFile) trong' System.IO'. –