genWrapper (desc, tag) =  ret ++ " " ++ wrapperName tag ++ "(" ++
                          renderArgs argList ++")\n"  ++
                          "{\n" ++
                          (if ret /= "void" then indent 1 ++ ret ++ " ret;\n" else "") ++
                          indent 1 ++ "VM* vm = get_vm();\n" ++
                          indent 1 ++ "if (vm == NULL) {\n" ++
                          indent 2 ++ "vm = idris_vm();\n" ++
                          indent 1 ++ "}\n" ++
                          indent 1 ++ "INITFRAME;\n" ++
                          indent 1 ++ "RESERVE(" ++ show (len + 1) ++ ");\n" ++
                          indent 1 ++ "allocCon(REG1, vm, " ++ show tag ++ ",0 , 0);\n" ++
                          indent 1 ++ "TOP(0) = REG1;\n" ++
                          applyArgs argList ++
                          if ret /= "void"
                            then indent 1 ++ "ret = " ++ irts_c (toFType ft) "RVAL" ++ ";\n"
                                          ++ indent 1 ++ "return ret;\n}\n\n"
                            else "}\n\n"
                    where
                        (ret, ft) = rty desc
                        argList = zip (args desc) [0..]
                        len = length argList

                        applyArgs (x:y:xs) = push 1 [x] ++
                                            indent 1 ++ "STOREOLD;\n" ++
                                            indent 1 ++ "BASETOP(0);\n" ++
                                            indent 1 ++ "ADDTOP(2);\n" ++
                                            indent 1 ++ "CALL(_idris__123_APPLY_95_0_125_);\n" ++
                                            indent 1 ++ "TOP(0)=REG1;\n" ++
                                            applyArgs (y:xs)
                        applyArgs x = push 1 x ++
                                      indent 1 ++ "STOREOLD;\n" ++
                                      indent 1 ++ "BASETOP(0);\n" ++
                                      indent 1 ++ "ADDTOP(" ++ show (length x + 1) ++ ");\n" ++
                                      indent 1 ++ "CALL(_idris__123_APPLY_95_0_125_);\n"
                        renderArgs [] = "void"
                        renderArgs [((s, _), n)] = s ++ " a" ++ (show n)
                        renderArgs (((s, _), n):xs) = s ++ " a" ++ (show n) ++ ", " ++
                                    renderArgs xs
                        rty (FApp c [_,ty])
                            | c == sUN "C_FnBase" = (ctype ty, ty)
                            | c == sUN "C_FnIO" = (ctype ty, ty)
                            | c == sUN "C_FnT" = rty ty
                        rty (FApp c [_,_,ty,fn])
                            | c == sUN "C_Fn" = rty fn
                        rty x = ("", x)
                        args (FApp c [_,ty])
                            | c == sUN "C_FnBase" = []
                            | c == sUN "C_FnIO" = []
                            | c == sUN "C_FnT" = args ty
                        args (FApp c [_,_,ty,fn])
                            | toFType ty == FUnit = []
                            | c == sUN "C_Fn" = (ctype ty, ty) : args fn
                        args _ = []
                        push i [] = ""
                        push i (((c, t), n) : ts) = indent 1 ++ c_irts (toFType t)
                                      ("TOP(" ++ show i ++ ") = ") ("a" ++ show n)
                                   ++ ";\n" ++ push (i + 1) ts
genWrapper (desc, tag) =  ret ++ " " ++ wrapperName tag ++ "(" ++
                          renderArgs argList ++")\n"  ++
                          "{\n" ++
                          (if ret /= "void" then indent 1 ++ ret ++ " ret;\n" else "") ++
                          indent 1 ++ "VM* vm = get_vm();\n" ++
                          indent 1 ++ "if (vm == NULL) {\n" ++
                          indent 2 ++ "vm = idris_vm();\n" ++
                          indent 1 ++ "}\n" ++
                          indent 1 ++ "INITFRAME;\n" ++
                          indent 1 ++ "RESERVE(" ++ show (len + 1) ++ ");\n" ++
                          indent 1 ++ "allocCon(REG1, vm, " ++ show tag ++ ",0 , 0);\n" ++
                          indent 1 ++ "TOP(0) = REG1;\n" ++
                          applyArgs argList ++
                          if ret /= "void"
                            then indent 1 ++ "ret = " ++ irts_c (toFType ft) "RVAL" ++ ";\n"
                                          ++ indent 1 ++ "return ret;\n}\n\n"
                            else "}\n\n"
                    where
                        (ret, ft) = rty desc
                        argList = zip (args desc) [0..]
                        len = length argList

                        applyArgs (x:y:xs) = push 1 [x] ++
                                            indent 1 ++ "STOREOLD;\n" ++
                                            indent 1 ++ "BASETOP(0);\n" ++
                                            indent 1 ++ "ADDTOP(2);\n" ++
                                            indent 1 ++ "CALL(_idris__123_APPLY_95_0_125_);\n" ++
                                            indent 1 ++ "TOP(0)=REG1;\n" ++
                                            applyArgs (y:xs)
                        applyArgs x = push 1 x ++
                                      indent 1 ++ "STOREOLD;\n" ++
                                      indent 1 ++ "BASETOP(0);\n" ++
                                      indent 1 ++ "ADDTOP(" ++ show (length x + 1) ++ ");\n" ++
                                      indent 1 ++ "CALL(_idris__123_APPLY_95_0_125_);\n"
                        renderArgs [] = "void"
                        renderArgs [((s, _), n)] = s ++ " a" ++ (show n)
                        renderArgs (((s, _), n):xs) = s ++ " a" ++ (show n) ++ ", " ++
                                    renderArgs xs
                        rty (FApp c [_,ty])
                            | c == sUN "C_FnBase" = (ctype ty, ty)
                            | c == sUN "C_FnIO" = (ctype ty, ty)
                            | c == sUN "C_FnT" = rty ty
                        rty (FApp c [_,_,ty,fn])
                            | c == sUN "C_Fn" = rty fn
                        rty x = ("", x)
                        args (FApp c [_,ty])
                            | c == sUN "C_FnBase" = []
                            | c == sUN "C_FnIO" = []
                            | c == sUN "C_FnT" = args ty
                        args (FApp c [_,_,ty,fn])
                            | toFType ty == FUnit = []
                            | c == sUN "C_Fn" = (ctype ty, ty) : args fn
                        args _ = []
                        push i [] = ""
                        push i (((c, t), n) : ts) = indent 1 ++ c_irts (toFType t)
                                      ("TOP(" ++ show i ++ ") = ") ("a" ++ show n)
                                   ++ ";\n" ++ push (i + 1) ts
genWrapper (desc, tag) =  ret ++ " " ++ wrapperName tag ++ "(" ++
                          renderArgs argList ++")\n"  ++
                          "{\n" ++
                          (if ret /= "void" then indent 1 ++ ret ++ " ret;\n" else "") ++
                          indent 1 ++ "VM* vm = get_vm();\n" ++
                          indent 1 ++ "if (vm == NULL) {\n" ++
                          indent 2 ++ "vm = idris_vm();\n" ++
                          indent 1 ++ "}\n" ++
                          indent 1 ++ "INITFRAME;\n" ++
                          indent 1 ++ "RESERVE(" ++ show (len + 1) ++ ");\n" ++
                          indent 1 ++ "allocCon(REG1, vm, " ++ show tag ++ ",0 , 0);\n" ++
                          indent 1 ++ "TOP(0) = REG1;\n" ++
                          applyArgs argList ++
                          if ret /= "void"
                            then indent 1 ++ "ret = " ++ irts_c (toFType ft) "RVAL" ++ ";\n"
                                          ++ indent 1 ++ "return ret;\n}\n\n"
                            else "}\n\n"
                    where
                        (ret, ft) = rty desc
                        argList = zip (args desc) [0..]
                        len = length argList

                        applyArgs (x:y:xs) = push 1 [x] ++
                                            indent 1 ++ "STOREOLD;\n" ++
                                            indent 1 ++ "BASETOP(0);\n" ++
                                            indent 1 ++ "ADDTOP(2);\n" ++
                                            indent 1 ++ "CALL(_idris__123_APPLY_95_0_125_);\n" ++
                                            indent 1 ++ "TOP(0)=REG1;\n" ++
                                            applyArgs (y:xs)
                        applyArgs x = push 1 x ++
                                      indent 1 ++ "STOREOLD;\n" ++
                                      indent 1 ++ "BASETOP(0);\n" ++
                                      indent 1 ++ "ADDTOP(" ++ show (length x + 1) ++ ");\n" ++
                                      indent 1 ++ "CALL(_idris__123_APPLY_95_0_125_);\n"
                        renderArgs [] = "void"
                        renderArgs [((s, _), n)] = s ++ " a" ++ (show n)
                        renderArgs (((s, _), n):xs) = s ++ " a" ++ (show n) ++ ", " ++
                                    renderArgs xs
                        rty (FApp c [_,ty])
                            | c == sUN "C_FnBase" = (ctype ty, ty)
                            | c == sUN "C_FnIO" = (ctype ty, ty)
                            | c == sUN "C_FnT" = rty ty
                        rty (FApp c [_,_,ty,fn])
                            | c == sUN "C_Fn" = rty fn
                        rty x = ("", x)
                        args (FApp c [_,ty])
                            | c == sUN "C_FnBase" = []
                            | c == sUN "C_FnIO" = []
                            | c == sUN "C_FnT" = args ty
                        args (FApp c [_,_,ty,fn])
                            | toFType ty == FUnit = []
                            | c == sUN "C_Fn" = (ctype ty, ty) : args fn
                        args _ = []
                        push i [] = ""
                        push i (((c, t), n) : ts) = indent 1 ++ c_irts (toFType t)
                                      ("TOP(" ++ show i ++ ") = ") ("a" ++ show n)
                                   ++ ";\n" ++ push (i + 1) ts