OK, after SPJ's mail and a few beers I'm now convinced that typing the foreign construct is not as simple and orthogonal as I initially hoped. After a close look into GHC's internals, H/Direct and Hugs I propose the following in the hope that it's backwards compatible and not too confusing: ------------------------------------------------------------------------ Syntax for the 'foreign' language construct ------------------------------------------------------------------------ topdecl : 'foreign' fkind modifier* var '::' type -- even this could be merged into modifier somehow, but... :-P fkind : 'import' | 'export' | 'label' modifier : mode | callconv | safety | ext_ent -- allowed for import/export mode : 'static' -- default | 'dynamic' -- allowed for import/export callconv : 'ccall' -- default | 'wincall' | 'stdcall' -- deprecated, same as wincall | 'cplusplus' | 'jvm' | 'dotnet' -- allowed for import safety : 'safe' -- default | 'unsafe' -- allowed for static import/export and label ext_ent : string -- default: the string rep. of var | string string -- deprecated, first string ignored ------------------------------------------------------------------------ Types related to the FFI ------------------------------------------------------------------------ Note that data type renamings are completely "transparent", just like type synonyms. prim_type_i : ['IO'] prim_result_i | prim_arg_i '->' prim_type_i prim_arg_i : prim_arg | foreign_ty | unsafe_arr_ty -- GHC extension | unlifted_prim_ty -- GHC extension prim_result_i : prim_result | ['IO'] unlifted_prim_ty -- GHC extension prim_type : ['IO'] prim_result | prim_arg '->' prim_type prim_result : prim_arg | '()' prim_arg : int_ty | word_ty | float_ty | ptr_ty | 'Bool' | 'Char' | 'StablePtr' a int_ty : 'Int' | 'Int8' | 'Int16' | 'Int32' | 'Int64' word_ty : 'Word8' | 'Word16' | 'Word32' | 'Word64' | 'Word' -- GHC extension float_ty : 'Float' | 'Double' ptr_ty : 'Addr' -- deprecated | 'Ptr' prim_result_i | 'FunPtr' prim_type_i -- arguments of this type are kept alive automagically across FFI calls. foreign_ty : 'ForeignObj' -- deprecated | 'ForeignPtr' prim_result -- GHC extension, only in conjunction with 'unsafe' modifier unsafe_arr_ty : 'ByteArray' a | 'MutableByteArray' i s a -- GHC extension unlifted_prim_ty : <any unlifted primary type> ------------------------------------------------------------------------ Typing rules for the ccall/wincall/stdcall calling convention ------------------------------------------------------------------------ Note that safety and ext_ent can be ignored for typing purposes, and that prim_type{,_i}1 and prime_type{,_i}2 must be equal. foreign import static :: prim_type_i foreign import dynamic :: 'FunPtr' prim_type_i1 '->' prim_type_i2 foreign export static :: prim_type foreign export dynamic :: prim_type1 -> 'IO' ('FunPtr' prim_type2) foreign label :: ptr_ty Cheers, Sven
participants (1)
-
Sven Panne