@@ -5,9 +5,11 @@ Copyright :
55License : BSD3
66Maintainer : The Idris Community.
77-}
8+{-# LANGUAGE FlexibleContexts #-}
9+
810module IRTS.CodegenC (codegenC) where
911
10−import Idris.AbsSyntax
12+import Idris.AbsSyntax hiding (getBC)
1113import Idris.Core.TT
1214import IRTS.Bytecode
1315import IRTS.CodegenCommon
@@ -19,10 +21,12 @@ import IRTS.System
1921import Util.System
2022
2123import Control.Monad
24+import Control.Monad
25+import Control.Monad.RWS
2226import Data.Bits
2327import Data.Char
24−import Data.List (intercalate, nubBy)
25−import Debug.Trace
28+import Data.List (find, intercalate, nubBy, partition)
29+import qualified Data.Text as T
2630import Numeric
2731import System.Directory
2832import System.Exit
@@ -30,6 +34,8 @@ import System.FilePath ((<.>), (</>))
3034import System.IO
3135import System.Process
3236
37+import Debug.Trace
38+
3339codegenC :: CodeGenerator
3440codegenC ci = do codegenC' (simpleDecls ci)
3541 (outputFile ci)
@@ -64,7 +70,9 @@ codegenC' defs out exec incs objs libs flags exports iface dbg
6470 let bc = map toBC defs
6571 let wrappers = genWrappers bc
6672 let h = concatMap toDecl (map fst bc)
67− let cc = concatMap (uncurry toC) bc
73+ let (state, cc) = execRWS (generateSrc bc) 0
74+ (CS { fnName = Nothing,
75+ level = 1 })
6876 let hi = concatMap ifaceC (concatMap getExp exports)
6977 d <- getIdrisCRTSDir
7078 mprog <- readFile (d </> "idris_main" <.> "c")
@@ -134,12 +142,17 @@ creg Tmp = "REG1"
134142toDecl :: Name -> String
135143toDecl f = "void " ++ cname f ++ "(VM*, VAL*);\n"
136144
137−toC :: Name -> [BC] -> String
138−toC f code
139− = -- "/* " ++ show code ++ "*/\n\n" ++
140− "void " ++ cname f ++ "(VM* vm, VAL* oldbase) {\n" ++
141− indent 1 ++ "INITFRAME;\n" ++
142− concatMap (bcc 1) code ++ "}\n\n"
145+generateSrc :: [(Name, [BC])] -> RWS Int String CState ()
146+generateSrc bc = mapM_ toC bc
147+
148+toC :: (Name, [BC]) -> RWS Int String CState ()
149+toC (f, code) = do
150+ modify (\s -> s { fnName = Just f })
151+ s <- get
152+ tell $ "void " ++ cname f ++ "(VM* vm, VAL* oldbase) {\n"
153+ tell $ indent (level s) ++ "INITFRAME;\n"
154+ bcc code
155+ tell $ "}\n\n"
143156
144157showCStr :: String -> String
145158showCStr s = '"' : foldr ((++) . showChar) "\"" s
@@ -151,34 +164,46 @@ showCStr s = '"' : foldr ((++) . showChar) "\"" s
151164 -- Note: we need the double quotes around the codes because otherwise
152165 -- "\n3" would get encoded as "\x0a3", which is incorrect.
153166 -- Instead, we opt for "\x0a""3" and let the C compiler deal with it.
154− | ord c < 0x10 = "\"\"\\x0" ++ showHex (ord c) "\"\""
155− | ord c < 0x20 = "\"\"\\x" ++ showHex (ord c) "\"\""
167+ | ord c < 0x20 = showUTF8 (ord c)
156168 | ord c < 0x7f = [c] -- 0x7f = \DEL
157169 | otherwise = showHexes (utf8bytes (ord c))
158170
159− utf8bytes :: Int -> [Int]
160− utf8bytes x = let (h : bytes) = split [] x in
161− headHex h (length bytes) : map toHex bytes
162− where
163− split acc 0 = acc
164− split acc x = let xbits = x .&. 0x3f
165− xrest = shiftR x 6 in
166− split (xbits : acc) xrest
167−
168− headHex h 1 = h + 0xc0
169− headHex h 2 = h + 0xe0
170− headHex h 3 = h + 0xf0
171− headHex h n = error "Can't happen: Invalid UTF8 character"
172−
173− toHex i = i + 0x80
174−
171+ showUTF8 c = "\"\"\\x" ++ pad (showHex c "") ++ "\"\""
175172 showHexes = foldr ((++) . showUTF8) ""
176− showUTF8 c = "\"\"\\x" ++ showHex c "\"\""
177173
178−bcc :: Int -> BC -> String
179−bcc i (ASSIGN l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
180−bcc i (ASSIGNCONST l c)
181− = indent i ++ creg l ++ " = " ++ mkConst c ++ ";\n"
174+ utf8bytes :: Int -> [Int]
175+ utf8bytes x
176+ | x <= 0x7f = [x]
177+ | x <= 0x7ff = let (y : ys) = split [] 2 x in (y .|. 0xc0) : map (.|. 0x80) ys
178+ | x <= 0xffff = let (y : ys) = split [] 3 x in (y .|. 0xe0) : map (.|. 0x80) ys
179+ | x <= 0x10ffff = let (y : ys) = split [] 4 x in (y .|. 0xf0) : map (.|. 0x80) ys
180+ | otherwise = error $ "Invalid Unicode code point U+" ++ showHex x ""
181+ where
182+ split acc 1 x = x : acc
183+ split acc i x = split (x .&. 0x3f : acc) (i - 1) (shiftR x 6)
184+
185+ pad :: String -> String
186+ pad s = case length s of
187+ 1 -> "0" ++ s
188+ 2 -> s
189+ _ -> error $ "Can't happen: String of invalid length " ++ show s
190+
191+data CState = CS {
192+ fnName :: Maybe Name,
193+ level :: Int
194+}
195+
196+
197+bcc :: [BC] -> RWS Int String CState ()
198+bcc [] = return ()
199+bcc ((ASSIGN l r):xs) = do
200+ i <- get
201+ tell $ indent (level i) ++ creg l ++ " = " ++ creg r ++ ";\n"
202+ bcc xs
203+bcc ((ASSIGNCONST l c):xs) = do
204+ i <- get
205+ tell $ indent (level i) ++ creg l ++ " = " ++ mkConst c ++ ";\n"
206+ bcc xs
182207 where
183208 mkConst (I i) = "MKINT(" ++ show i ++ ")"
184209 mkConst (BI i) | i < (2^30) = "MKINT(" ++ show i ++ ")"
@@ -196,16 +221,21 @@ bcc i (ASSIGNCONST l c)
196221 mkConst c | isTypeConst c = "MKINT(42424242)"
197222 mkConst c = error $ "mkConst of (" ++ show c ++ ") not implemented"
198223
199−bcc i (UPDATE l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
200−bcc i (MKCON l loc tag []) | tag < 256
201− = indent i ++ creg l ++ " = NULL_CON(" ++ show tag ++ ");\n"
202−bcc i (MKCON l loc tag args)
203− = indent i ++ alloc loc tag ++
204− indent i ++ setArgs 0 args ++ "\n" ++
205− indent i ++ creg l ++ " = " ++ creg Tmp ++ ";\n"
206−
207−-- "MKCON(vm, " ++ creg l ++ ", " ++ show tag ++ ", " ++
208−-- show (length args) ++ concatMap showArg args ++ ");\n"
224+bcc ((UPDATE l r):xs) = do
225+ i <- get
226+ tell $ indent (level i) ++ creg l ++ " = " ++ creg r ++ ";\n"
227+ bcc xs
228+bcc ((MKCON l loc tag []):xs) | tag < 256 = do
229+ i <- get
230+ tell $ indent (level i) ++ creg l ++ " = NULL_CON(" ++ show tag ++ ");\n"
231+ bcc xs
232+bcc ((MKCON l loc tag args):xs) = do
233+ i <- get
234+ let tab = indent (level i)
235+ tell $ tab ++ alloc loc tag ++
236+ tab ++ setArgs 0 args ++ "\n" ++
237+ tab ++ creg l ++ " = " ++ creg Tmp ++ ";\n"
238+ bcc xs
209239 where showArg r = ", " ++ creg r
210240 setArgs i [] = ""
211241 setArgs i (x : xs) = "SETARG(" ++ creg Tmp ++ ", " ++ show i ++ ", " ++ creg x ++
@@ -217,52 +247,94 @@ bcc i (MKCON l loc tag args)
217247 = "updateCon(" ++ creg Tmp ++ ", " ++ creg old ++ ", " ++ show tag ++ ", " ++
218248 show (length args) ++ ");\n"
219249
220−bcc i (PROJECT l loc a) = indent i ++ "PROJECT(vm, " ++ creg l ++ ", " ++ show loc ++
221− ", " ++ show a ++ ");\n"
222−bcc i (PROJECTINTO r t idx)
223− = indent i ++ creg r ++ " = GETARG(" ++ creg t ++ ", " ++ show idx ++ ");\n"
224−bcc i (CASE True r code def)
225− | length code < 4 = showCase i def code
250+bcc ((PROJECT l loc a):xs) = do
251+ i <- get
252+ tell $ indent (level i) ++ "PROJECT(vm, " ++ creg l ++ ", "
253+ ++ show loc ++ ", " ++ show a ++ ");\n"
254+ bcc xs
255+bcc ((PROJECTINTO r t idx):xs) = do
256+ i <- get
257+ tell $ indent (level i) ++ creg r ++ " = GETARG(" ++ creg t
258+ ++ ", " ++ show idx ++ ");\n"
259+ bcc xs
260+bcc ((CASE True r code def):xs)
261+ | length code < 4 = do
262+ showCases def code
263+ bcc xs
226264 where
227− showCode :: Int -> [BC] -> String
228− showCode i bc = "{\n" ++ concatMap (bcc (i + 1)) bc ++
229− indent i ++ "}\n"
230−
231− showCase :: Int -> Maybe [BC] -> [(Int, [BC])] -> String
232− showCase i Nothing [(t, c)] = indent i ++ showCode i c
233− showCase i (Just def) [] = indent i ++ showCode i def
234− showCase i def ((t, c) : cs)
235− = indent i ++ "if (CTAG(" ++ creg r ++ ") == " ++ show t ++ ") " ++ showCode i c
236− ++ indent i ++ "else\n" ++ showCase i def cs
237−
238−bcc i (CASE safe r code def)
239− = indent i ++ "switch(" ++ ctag safe ++ "(" ++ creg r ++ ")) {\n" ++
240− concatMap (showCase i) code ++
241− showDef i def ++
242− indent i ++ "}\n"
265+ showCode bc = do
266+ w <- getBC bc xs
267+ i <- get
268+ tell $ "{\n" ++ w ++ indent (level i) ++ "}\n"
269+
270+ showCases Nothing [(t, c)] = do
271+ i <- get
272+ tell $ indent (level i)
273+ showCode c
274+ showCases (Just def) [] = do
275+ i <- get
276+ tell $ indent (level i)
277+ showCode def
278+ showCases def ((t, c) : cs) = do
279+ i <- get
280+ tell $ indent (level i) ++ "if (CTAG(" ++ creg r ++ ") == "
281+ ++ show t ++ ") "
282+ showCode c
283+ tell $ indent (level i) ++ "else\n"
284+ showCases def cs
285+
286+bcc ((CASE safe r code def):xs) = do
287+ i <- get
288+ tell $ indent (level i) ++ "switch(" ++ ctag safe ++ "(" ++ creg r ++ ")) {\n"
289+ mapM showCase code
290+ showDef def
291+ tell $ indent (level i) ++ "}\n"
292+ bcc xs
243293 where
244294 ctag True = "CTAG"
245295 ctag False = "TAG"
246296
247− showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
248− ++ concatMap (bcc (i+1)) bc ++ indent (i + 1) ++ "break;\n"
249− showDef i Nothing = ""
250− showDef i (Just c) = indent i ++ "default:\n"
251− ++ concatMap (bcc (i+1)) c ++ indent (i + 1) ++ "break;\n"
252−bcc i (CONSTCASE r code def)
297+ showCase (t, bc) = do
298+ w <- getBC bc xs
299+ is <- get
300+ let i = level is
301+ tell $ indent i ++ "case " ++ show t ++ ":\n"
302+ ++ w ++ indent (i + 1) ++ "break;\n"
303+ showDef Nothing = return $ ()
304+ showDef (Just c) = do
305+ w <- getBC c xs
306+ is <- get
307+ let i = level is
308+ tell $ indent i ++ "default:\n" ++ w ++ indent (i + 1) ++ "break;\n"
309+
310+bcc ((CONSTCASE r code def):xs)
253311 | intConsts code
254−-- = indent i ++ "switch(GETINT(" ++ creg r ++ ")) {\n" ++
255−-- concatMap (showCase i) code ++
256−-- showDef i def ++
257−-- indent i ++ "}\n"
258− = concatMap (iCase (creg r)) code ++
259− indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
312+ = do
313+ is <- get
314+ let i = level is
315+ codes <- mapM getCode code
316+ defs <- showDefS def
317+ tell $ concatMap (iCase i (creg r)) codes
318+ tell $ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
319+ bcc xs
260320 | strConsts code
261− = concatMap (strCase ("GETSTR(" ++ creg r ++ ")")) code ++
262− indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
321+ = do
322+ is <- get
323+ let i = level is
324+ codes <- mapM getCode code
325+ defs <- showDefS def
326+ tell $ concatMap (strCase i ("GETSTR(" ++ creg r ++ ")")) codes
327+ ++ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
328+ bcc xs
263329 | bigintConsts code
264− = concatMap (biCase (creg r)) code ++
265− indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
330+ = do
331+ is <- get
332+ let i = level is
333+ codes <- mapM getCode code
334+ defs <- showDefS def
335+ tell $ concatMap (biCase i (creg r)) codes ++
336+ indent i ++ "{\n" ++ defs ++ indent i ++ "}\n"
337+ bcc xs
266338 | otherwise = error $ "Can't happen: Can't compile const case " ++ show code
267339 where
268340 intConsts ((I _, _ ) : _) = True
@@ -279,72 +351,119 @@ bcc i (CONSTCASE r code def)
279351 strConsts ((Str _, _ ) : _) = True
280352 strConsts _ = False
281353
282− strCase sv (s, bc) =
354+ getCode (x, code) = do
355+ c <- getBC code xs
356+ return (x, c)
357+
358+ strCase i sv (s, bc) =
283359 indent i ++ "if (strcmp(" ++ sv ++ ", " ++ show s ++ ") == 0) {\n" ++
284− concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
285− biCase bv (BI b, bc) =
360+ bc ++ indent i ++ "} else\n"
361+ biCase i bv (BI b, bc) =
286362 indent i ++ "if (bigEqConst(" ++ bv ++ ", " ++ show b ++ ")) {\n"
287− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
288− iCase v (I b, bc) =
363+ ++ bc ++ indent i ++ "} else\n"
364+ iCase i v (I b, bc) =
289365 indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show b ++ ") {\n"
290− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
291− iCase v (Ch b, bc) =
366+ ++ bc ++ indent i ++ "} else\n"
367+ iCase i v (Ch b, bc) =
292368 indent i ++ "if (GETINT(" ++ v ++ ") == " ++ show (fromEnum b) ++ ") {\n"
293− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
294− iCase v (B8 w, bc) =
369+ ++ bc ++ indent i ++ "} else\n"
370+ iCase i v (B8 w, bc) =
295371 indent i ++ "if (GETBITS8(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
296− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
297− iCase v (B16 w, bc) =
372+ ++ bc ++ indent i ++ "} else\n"
373+ iCase i v (B16 w, bc) =
298374 indent i ++ "if (GETBITS16(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
299− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
300− iCase v (B32 w, bc) =
375+ ++ bc ++ indent i ++ "} else\n"
376+ iCase i v (B32 w, bc) =
301377 indent i ++ "if (GETBITS32(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
302− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
303− iCase v (B64 w, bc) =
378+ ++ bc ++ indent i ++ "} else\n"
379+ iCase i v (B64 w, bc) =
304380 indent i ++ "if (GETBITS64(" ++ v ++ ") == " ++ show (fromEnum w) ++ ") {\n"
305− ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
306− showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
307− ++ concatMap (bcc (i+1)) bc ++
308− indent (i + 1) ++ "break;\n"
309− showDef i Nothing = ""
310− showDef i (Just c) = indent i ++ "default:\n"
311− ++ concatMap (bcc (i+1)) c ++
312− indent (i + 1) ++ "break;\n"
313− showDefS i Nothing = ""
314− showDefS i (Just c) = concatMap (bcc (i+1)) c
315−
316−bcc i (CALL n) = indent i ++ "CALL(" ++ cname n ++ ");\n"
317−bcc i (TAILCALL n) = indent i ++ "TAILCALL(" ++ cname n ++ ");\n"
318−bcc i (SLIDE n) = indent i ++ "SLIDE(vm, " ++ show n ++ ");\n"
319−bcc i REBASE = indent i ++ "REBASE;\n"
320−bcc i (RESERVE 0) = ""
321−bcc i (RESERVE n) = indent i ++ "RESERVE(" ++ show n ++ ");\n"
322−bcc i (ADDTOP 0) = ""
323−bcc i (ADDTOP n) = indent i ++ "ADDTOP(" ++ show n ++ ");\n"
324−bcc i (TOPBASE n) = indent i ++ "TOPBASE(" ++ show n ++ ");\n"
325−bcc i (BASETOP n) = indent i ++ "BASETOP(" ++ show n ++ ");\n"
326−bcc i STOREOLD = indent i ++ "STOREOLD;\n"
327−bcc i (OP l fn args) = indent i ++ doOp (creg l ++ " = ") fn args ++ ";\n"
328−bcc i (FOREIGNCALL l rty (FStr fn@('&':name)) [])
329− = indent i ++
330− c_irts (toFType rty) (creg l ++ " = ") fn ++ ";\n"
331−bcc i (FOREIGNCALL l rty (FStr fn) (x:xs)) | fn == "%wrapper"
332− = indent i ++
333− c_irts (toFType rty) (creg l ++ " = ")
381+ ++ bc ++ indent i ++ "} else\n"
382+
383+ showDefS Nothing = return ""
384+ showDefS (Just c) = getBC c xs
385+
386+bcc (CALL n:xs) = do
387+ i <- get
388+ tell $ indent (level i) ++ "CALL(" ++ cname n ++ ");\n"
389+ bcc xs
390+bcc (TAILCALL n:xs) = do
391+ i <- get
392+ tell $ indent (level i) ++ "TAILCALL(" ++ cname n ++ ");\n"
393+ bcc xs
394+bcc ((SLIDE n):xs) = do
395+ i <- get
396+ tell $ indent (level i) ++ "SLIDE(vm, " ++ show n ++ ");\n"
397+ bcc xs
398+bcc (REBASE:xs) = do
399+ i <- get
400+ tell $ indent (level i)++ "REBASE;\n"
401+ bcc xs
402+bcc ((RESERVE 0):xs) = bcc xs
403+bcc ((RESERVE n):xs) = do
404+ i <- get
405+ tell $ indent (level i) ++ "RESERVE(" ++ show n ++ ");\n"
406+ bcc xs
407+bcc ((ADDTOP 0):xs) = bcc xs
408+bcc ((ADDTOP n):xs) = do
409+ i <- get
410+ tell $ indent (level i) ++ "ADDTOP(" ++ show n ++ ");\n"
411+ bcc xs
412+bcc ((TOPBASE n):xs) = do
413+ i <- get
414+ tell $ indent (level i) ++ "TOPBASE(" ++ show n ++ ");\n"
415+ bcc xs
416+bcc ((BASETOP n):xs) = do
417+ i <- get
418+ tell $ indent (level i) ++ "BASETOP(" ++ show n ++ ");\n"
419+ bcc xs
420+bcc (STOREOLD:xs) = do
421+ i <- get
422+ tell $ indent (level i) ++ "STOREOLD;\n"
423+ bcc xs
424+bcc ((OP l fn args):xs) = do
425+ i <- get
426+ tell $ indent (level i) ++ doOp (creg l ++ " = ") fn args ++ ";\n"
427+ bcc xs
428+bcc ((FOREIGNCALL l rty (FStr fn@('&':name)) []):xs) = do
429+ i <- get
430+ tell $ indent (level i) ++ c_irts (toFType rty) (creg l ++ " = ") fn ++ ";\n"
431+ bcc xs
432+bcc ((FOREIGNCALL l rty (FStr fn) (x:xs)):zs) | fn == "%wrapper"
433+ = do
434+ i <- get
435+ tell $ indent (level i) ++ c_irts (toFType rty) (creg l ++ " = ")
334436 ("_idris_get_wrapper(" ++ creg (snd x) ++ ")") ++ ";\n"
335−bcc i (FOREIGNCALL l rty (FStr fn) (x:xs)) | fn == "%dynamic"
336− = indent i ++ c_irts (toFType rty) (creg l ++ " = ")
437+ bcc zs
438+bcc ((FOREIGNCALL l rty (FStr fn) (x:xs)):zs) | fn == "%dynamic"
439+ = do
440+ i <- get
441+ tell $ indent (level i) ++ c_irts (toFType rty) (creg l ++ " = ")
337442 ("(*(" ++ cFnSig "" rty xs ++ ") GETPTR(" ++ creg (snd x) ++ "))" ++
338443 "(" ++ showSep "," (map fcall xs) ++ ")") ++ ";\n"
339−bcc i (FOREIGNCALL l rty (FStr fn) args)
340− = indent i ++
341− c_irts (toFType rty) (creg l ++ " = ")
342− (fn ++ "(" ++ showSep "," (map fcall args) ++ ")") ++ ";\n"
343−bcc i (FOREIGNCALL l rty _ args) = error "Foreign Function calls cannot be partially applied, without being inlined."
344−bcc i (NULL r) = indent i ++ creg r ++ " = NULL;\n" -- clear, so it'll be GCed
345−bcc i (ERROR str) = indent i ++ "fprintf(stderr, " ++ show str ++ "); fprintf(stderr, \"\\n\"); exit(-1);\n"
444+ bcc zs
445+bcc ((FOREIGNCALL l rty (FStr fn) args):xs) = do
446+ i <- get
447+ tell $ indent (level i) ++ c_irts (toFType rty) (creg l ++ " = ")
448+ (fn ++ "(" ++ showSep "," (map fcall args) ++ ")") ++ ";\n"
449+ bcc xs
450+bcc ((FOREIGNCALL l rty _ args):_) = error "Foreign Function calls cannot be partially applied, without being inlined."
451+bcc ((NULL r):xs) = do
452+ i <- get
453+ tell $ indent (level i) ++ creg r ++ " = NULL;\n" -- clear, so it'll be GCed
454+ bcc xs
455+bcc ((ERROR str):xs) = do
456+ i <- get
457+ tell $ indent (level i) ++ "fprintf(stderr, "
458+ ++ show str ++ "); fprintf(stderr, \"\\n\"); exit(-1);\n"
459+ bcc xs
346460-- bcc i c = error (show c) -- indent i ++ "// not done yet\n"
347461
462+getBC code xs = do
463+ i <- get
464+ let (a, s, w) = runRWS (bcc code) 0 (i { level = level i + 1 })
465+ return w
466+
348467fcall (t, arg) = irts_c (toFType t) (creg arg)
349468-- Deconstruct the Foreign type in the defunctionalised expression and build
350469-- a foreign type description for c_irts and irts_c