+-----------------------------------------------------------------------------
+-- Foreign import and export declarations
+
+-- for the time being, the following accepts foreign declarations conforming
+-- to the FFI Addendum, Version 1.0 as well as pre-standard declarations
+--
+-- * a flag indicates whether pre-standard declarations have been used and
+-- triggers a deprecation warning further down the road
+--
+-- NB: The first two rules could be combined into one by replacing `safety1'
+-- with `safety'. However, the combined rule conflicts with the
+-- DEPRECATED rules.
+--
+fdecl :: { RdrNameHsDecl }
+fdecl : srcloc 'import' callconv safety1 fspec {% mkImport $3 $4 $5 $1 }
+ | srcloc 'import' callconv fspec {% mkImport $3 (PlaySafe False) $4 $1 }
+ | srcloc 'export' callconv fspec {% mkExport $3 $4 $1 }
+ -- the following syntax is DEPRECATED
+ | srcloc fdecl1DEPRECATED { ForD ($2 True $1) }
+ | srcloc fdecl2DEPRECATED { $2 $1 }
+
+fdecl1DEPRECATED :: { Bool -> SrcLoc -> ForeignDecl RdrName }
+fdecl1DEPRECATED
+ ----------- DEPRECATED label decls ------------
+ : 'label' ext_name varid '::' sigtype
+ { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) nilFS nilFS
+ (CLabel ($2 `orElse` mkExtName $3))) }
+
+ ----------- DEPRECATED ccall/stdcall decls ------------
+ --
+ -- NB: This business with the case expression below may seem overly
+ -- complicated, but it is necessary to avoid some conflicts.
+
+ -- DEPRECATED variant #1: lack of a calling convention specification
+ -- (import)
+ | 'import' {-no callconv-} ext_name safety varid_no_unsafe '::' sigtype
+ { let
+ target = StaticTarget ($2 `orElse` mkExtName $4)
+ in
+ ForeignImport $4 $6 (CImport defaultCCallConv $3 nilFS nilFS
+ (CFunction target)) }
+
+ -- DEPRECATED variant #2: external name consists of two separate strings
+ -- (module name and function name) (import)
+ | 'import' callconv STRING STRING safety varid_no_unsafe '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ let
+ imp = CFunction (StaticTarget $4)
+ in
+ ForeignImport $6 $8 (CImport cconv $5 nilFS nilFS imp) }
+
+ -- DEPRECATED variant #3: `unsafe' after entity
+ | 'import' callconv STRING 'unsafe' varid_no_unsafe '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ let
+ imp = CFunction (StaticTarget $3)
+ in
+ ForeignImport $5 $7 (CImport cconv PlayRisky nilFS nilFS imp) }
+
+ -- DEPRECATED variant #4: use of the special identifier `dynamic' without
+ -- an explicit calling convention (import)
+ | 'import' {-no callconv-} 'dynamic' safety varid_no_unsafe '::' sigtype
+ { ForeignImport $4 $6 (CImport defaultCCallConv $3 nilFS nilFS
+ (CFunction DynamicTarget)) }
+
+ -- DEPRECATED variant #5: use of the special identifier `dynamic' (import)
+ | 'import' callconv 'dynamic' safety varid_no_unsafe '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ ForeignImport $5 $7 (CImport cconv $4 nilFS nilFS
+ (CFunction DynamicTarget)) }
+
+ -- DEPRECATED variant #6: lack of a calling convention specification
+ -- (export)
+ | 'export' {-no callconv-} ext_name varid '::' sigtype
+ { ForeignExport $3 $5 (CExport (CExportStatic ($2 `orElse` mkExtName $3)
+ defaultCCallConv)) }
+
+ -- DEPRECATED variant #7: external name consists of two separate strings
+ -- (module name and function name) (export)
+ | 'export' callconv STRING STRING varid '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ ForeignExport $5 $7
+ (CExport (CExportStatic $4 cconv)) }
+
+ -- DEPRECATED variant #8: use of the special identifier `dynamic' without
+ -- an explicit calling convention (export)
+ | 'export' {-no callconv-} 'dynamic' varid '::' sigtype
+ { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) nilFS nilFS
+ CWrapper) }
+
+ -- DEPRECATED variant #9: use of the special identifier `dynamic' (export)
+ | 'export' callconv 'dynamic' varid '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ ForeignImport $4 $6 (CImport cconv (PlaySafe False) nilFS nilFS CWrapper) }
+
+ ----------- DEPRECATED .NET decls ------------
+ -- NB: removed the .NET call declaration, as it is entirely subsumed
+ -- by the new standard FFI declarations
+
+fdecl2DEPRECATED :: { SrcLoc -> RdrNameHsDecl }
+fdecl2DEPRECATED
+ : 'import' 'dotnet' 'type' ext_name tycon
+ { \loc -> TyClD (ForeignType $5 $4 DNType loc) }
+ -- left this one unchanged for the moment as type imports are not
+ -- covered currently by the FFI standard -=chak
+
+
+callconv :: { CallConv }
+ : 'stdcall' { CCall StdCallConv }
+ | 'ccall' { CCall CCallConv }
+ | 'dotnet' { DNCall }
+
+safety :: { Safety }
+ : 'unsafe' { PlayRisky }
+ | 'safe' { PlaySafe False }
+ | 'threadsafe' { PlaySafe True }
+ | {- empty -} { PlaySafe False }
+
+safety1 :: { Safety }
+ : 'unsafe' { PlayRisky }
+ | 'safe' { PlaySafe False }
+ | 'threadsafe' { PlaySafe True }
+ -- only needed to avoid conflicts with the DEPRECATED rules
+
+fspec :: { (FastString, RdrName, RdrNameHsType) }
+ : STRING var '::' sigtype { ($1 , $2, $4) }
+ | var '::' sigtype { (nilFS, $1, $3) }
+ -- if the entity string is missing, it defaults to the empty string;
+ -- the meaning of an empty entity string depends on the calling
+ -- convention
+
+-- DEPRECATED syntax
+ext_name :: { Maybe CLabelString }
+ : STRING { Just $1 }
+ | STRING STRING { Just $2 } -- Ignore "module name" for now
+ | {- empty -} { Nothing }
+