Difference between revisions of "Yhc/Primitives"

From HaskellWiki
< Yhc
Jump to navigation Jump to search
 
m (Minor formatting changes)
 
Line 1: Line 1:
TODO: Clean up the formatting!
 
   
 
* <code>foreign import ccall …</code>
   
  +
:Import the primitive exactly as if it were a standard FFI C-call. This allows for the possibility that the primitive might block and so it is run in a separate OS thread.
foreign import ccall
 
   
 
* <code>foreign import fastccall …</code>
Import the primitive exactly as if it were a standard
 
FFI c-call. This allows for the possibility that the
 
primitive might block and so it is run in a seperate OS
 
thread.
 
   
 
:Same as <code>ccall</code> but don't run the primitive call in a separate OS-level thread because we promise it won't block.
foreign import fastccall
 
   
 
* <code>foreign import primitive …</code>
Same as ccall but don't run the primitive call in a
 
seperate OS-level thread because we promise it won't
 
block.
 
   
  +
:Make a call to the C-function but don't try and convert the arguments or result to/from Haskell nodes. This is necessary because some primitives are so low level they need to work on the Haskell nodes directly.
foreign import primitive
 
   
 
* <code>foreign import cast …</code>
make a call to the C-function but don't try and convert
 
the arguments or result to/from Haskell nodes. This is
 
necessary because some primitives are so low level they
 
need to work on the Haskell nodes directly.
 
   
  +
:This is a standard part of the FFI. Essentially it says this might look like we're importing something but actually just cast the argument to the result and forget about it. You can implement this as a 'fastccall' but it's quicker and standard FFI in any case.
foreign import cast
 
   
 
* <code>foreign import builtin …</code>
this is a standard part of the FFI. Essentially it says
 
this might look like we're importing something but
 
actually just cast the argument to the result and forget
 
about it. You can implement this as a 'fastccall' but
 
it's quicker and standard FFI in any case.
 
   
  +
:The primitive uses EVAL or APPLY internally and thus can't be implemented as C code - it has to be written as byte code. Nor can the function be written in Haskell. Currently there is only one primitive in this category which is <code>primCatch</code>:
foreign import builtin
 
  +
:{|
  +
|<tt><pre>
 
primCatch :: a -> (b -> a) -> a
 
primCatch e h:
 
CATCH_BEGIN handler
 
PUSH_ZAP_ARG e
 
EVAL
 
CATCH_END
 
RETURN
 
handler:
 
PUSH_ARG h
 
APPLY 1
 
RETURN_EVAL
  +
</pre></tt>
  +
|}
   
 
:It would be possible to implement this as compiler magic i.e. define <code>primCatch</code> as:
the primitive uses EVAL or APPLY internally and thus
 
  +
:{|
can't be implemented as C code - it has to be written as
 
  +
|<tt><pre>
byte code. Nor can the function be written in Haskell.
 
 
primCatch e h = undefined -- MAGIC!!
Currently there is only one primitive in this category
 
  +
</pre></tt>
which is primCatch.
 
  +
|}
 
 
:and have the compiler rewrite it as the above bytecode, but I figured you wouldn't fancy that ;-)
primCatch :: a -> (b -> a) -> a
 
primCatch e h
 
CATCH_BEGIN handler
 
PUSH_ZAP_ARG e
 
EVAL
 
CATCH_END
 
RETURN
 
handler:
 
PUSH_ARG h
 
APPLY 1
 
RETURN_EVAL
 
 
it would be possible to implement this as compiler
 
magic. i.e. define primCatch as
 
 
primCatch e h = undefined -- MAGIC!!
 
 
and have the compiler rewrite it as the above bytecode,
 
but I figured you wouldn't fancy that ;-)
 

Latest revision as of 01:58, 9 April 2021

  • foreign import ccall …
Import the primitive exactly as if it were a standard FFI C-call. This allows for the possibility that the primitive might block and so it is run in a separate OS thread.
  • foreign import fastccall …
Same as ccall but don't run the primitive call in a separate OS-level thread because we promise it won't block.
  • foreign import primitive …
Make a call to the C-function but don't try and convert the arguments or result to/from Haskell nodes. This is necessary because some primitives are so low level they need to work on the Haskell nodes directly.
  • foreign import cast …
This is a standard part of the FFI. Essentially it says this might look like we're importing something but actually just cast the argument to the result and forget about it. You can implement this as a 'fastccall' but it's quicker and standard FFI in any case.
  • foreign import builtin …
The primitive uses EVAL or APPLY internally and thus can't be implemented as C code - it has to be written as byte code. Nor can the function be written in Haskell. Currently there is only one primitive in this category which is primCatch:
primCatch :: a -> (b -> a) -> a
    primCatch e h:
           CATCH_BEGIN handler
           PUSH_ZAP_ARG e
           EVAL
           CATCH_END
           RETURN
    handler:
           PUSH_ARG h
           APPLY 1
           RETURN_EVAL
It would be possible to implement this as compiler magic i.e. define primCatch as:
             
primCatch e h = undefined -- MAGIC!!
and have the compiler rewrite it as the above bytecode, but I figured you wouldn't fancy that ;-)