2011-03-11 72 views
1

我正在編寫一個程序,它解析用某種編寫語言編寫的腳本,並使用該腳本執行一些計算。該語言有一個特殊的結構,用於調用'a -> bool類型的外部OCaml函數。所以,在語言中,我們可以有OCaml:僅從函數標識符返回函數

blah blah function (foo 45) blah blah 

,我想解析器使用構造函數如

OCamlFunction of ('a -> bool) * 'a 

來解析該位爲價值

OCamlFunction (foo,45) 

其中'foo'是用戶必須在單獨的.ml文件中提供並且解析器事先不知道的函數;只有定義了「foo」的OCaml文件的名稱在運行時傳遞給解析器。所以,我需要定義一個類型爲string->('a->bool)的函數,該函數接受某個函數的名稱並返回該函數。

我的問題是:

(1)我假設的代碼動態加載應該使用DynLink.loadfile。這是要走的路嗎? (2)如何從其標識符的知識中獲取函數「foo」? (這會導致我到camlp5嗎?)

回答

2

您不能直接按名稱加載函數,因爲OCaml沒有這種類型的支持,並且loadfile函數只是運行代碼,它不提供對名稱的訪問。

您需要在加載的代碼使用的主程序中支持某種函數註冊API。因此,加載代碼會做類似

ParserEngine.register_function "foo" foo_impl 

你可以使用Camlp {4,5}自動完成這個樣板代碼生成,或者你可以有一個register_functions調用需要的關聯列表,以儘量減少它。

register_functions然後將函數存儲在某些內部結構中,如散列表或可變關聯列表,以供您的分析器代碼訪問。

+1

聽起來不錯!我沒有想到提供函數的實際ml文件可以在編譯器/解析器中調用一個註冊函數。我知道DynLink只用於加載代碼。我建議DynLink加載實際功能的部分,然後您需要通過camlp5從標識符中獲得。但功能註冊機制實際上更簡單並且很有意義。謝謝! – Surikator 2011-03-11 01:13:19

2

另一種解決方案是將整個腳本放在引號中,並將每個ocaml值放入反引號中。例如,可以使用Camlp4完成此操作,但語法成本很低(圍繞代碼的<<>>,圍繞OCaml值的$$)。然後腳本的解析將在編譯時運行,所以OCaml typer本身可以檢查您引用的OCaml值是否已定義好。另外,你可以得到更好的類型控制。