Closed cblp closed 7 years ago
The main question is: how to write type-safe generic C procedure calling passed in procedure via a type-erasured function pointer?
@cblp thank you for bringing this up; this issue goes a bit deeper so it might be a while until we can hammer out a good design. (cc @elliottt @leepike)
FYI: associated pull request from @cblp: https://github.com/GaloisInc/ivory/pull/84
I'm trying to call a procedure and pass it a pointer to another procedure via some generic interface. In real life it may be
qsort
or any other procedure with callback. Here is a simplified example.In C it works like so:
(checked with
gcc -Wall -Wextra -Werror -ansi -pedantic
)Let's reproduce this in Ivory!
Works good with concrete type
uint32_t
. Now let's generalize it tovoid *
.But we can't
call_ apply (procPtr print) (constRef str)
, because Haskell can't unifyUint32
inprint
's type and()
inapply
's type.In C we used type cast to solve this problem. Can we cast these types in Haskell/Ivory language?
We can't use
safeCast
, because there are noSafeCast
instances for anything like pointer types. Looks like casting pointers in considered unsafe. Seem rational.Let's try unsafe
ivoryCast
.The cast for
str
works, but the first one throws an error:There is no IvoryExpr instance for ProcPtr!
Why? Because, unlike majority of Ivory types, ProcPtr is not a wrapper around Expr and so cannot be constructed by wrapping around Expr.
A strange thing
Under some assumptions, we can cast to a secondary function pointer in Ivory.
Assumption 1. Make
apply
function external.(Unfortunately, we can't implement it in Ivory, because there is no instance of IvoryStore neither for Def nor for ProcPtr.)
Assumption 2. Relax requirements of ivoryCast.
Now we can use pointers to function pointers!
And Ivory generates the following code:
The result is incorrect, but the
IvoryExpr
instance works as expected!Is primary function pointer cast impossible in Ivory when the secondary one is possible?