- | null data_cons
- -- oops! can't see the data constructors
- = can't_see_datacons_error "result" result_ty
-
- -- Data types with a single constructor, which has a single, primitive-typed arg
- | (maybeToBool maybe_data_type) && -- Data type
- (null other_data_cons) && -- Just one constr
- not (null data_con_arg_tys) && null other_args_tys && -- Just one arg
- isPrimType the_prim_result_ty -- of primitive type
- =
- newSysLocalDs realWorldStatePrimTy `thenDs` \ prim_state_id ->
- newSysLocalDs the_prim_result_ty `thenDs` \ prim_result_id ->
-
- mkCoConDs stateDataCon [realWorldTy] [CoVar prim_state_id] `thenDs` \ new_state ->
- mkCoConDs the_data_con tycon_arg_tys [CoVar prim_result_id] `thenDs` \ the_result ->
-
- mkCoConDs tuple_con_2
- [result_ty, realWorldStateTy]
- [the_result, new_state] `thenDs` \ the_pair ->
- let
- the_alt = (state_and_prim_datacon, [prim_state_id, prim_result_id], the_pair)
- in
- returnDs (state_and_prim_ty,
- \prim_app -> CoCase prim_app (CoAlgAlts [the_alt] CoNoDefault)
- )
-
- -- Data types with a single nullary constructor
- | (maybeToBool maybe_data_type) && -- Data type
- (null other_data_cons) && -- Just one constr
- (null data_con_arg_tys)
- =
- newSysLocalDs realWorldStatePrimTy `thenDs` \ prim_state_id ->
-
- mkCoConDs stateDataCon [realWorldTy] [CoVar prim_state_id] `thenDs` \ new_state ->
-
- mkCoConDs tuple_con_2
- [result_ty, realWorldStateTy]
- [covar_tuple_con_0, new_state] `thenDs` \ the_pair ->
-
- let
- the_alt = (stateDataCon, [prim_state_id], the_pair)
- in
- returnDs (realWorldStateTy,
- \prim_app -> CoCase prim_app (CoAlgAlts [the_alt] CoNoDefault)
- )
-
-#if 0
- -- MAYBE LATER???
-
- -- Data types with several nullary constructors (Enumerated types)
- | isEnumerationType result_ty && -- Enumeration
- (length data_cons) <= 5 -- fairly short
- =
- newSysLocalDs realWorldStatePrimTy `thenDs` \ prim_state_id ->
- newSysLocalDs intPrimTy `thenDs` \ prim_result_id ->
-
- mkCoConDs stateDataCon [realWorldTy] [CoVar prim_state_id] `thenDs` \ new_state ->
-
- let
- alts = [ (mkMachInt i, con) | (i, con) <- [0..] `zip` data_cons ]
- the_result = CoCase prim_result_id (CoPrimAlts alts) CoNoDefault
+ = case splitAlgTyConApp_maybe result_ty of
+
+ -- The result is IO t, so wrap the result in an IO constructor
+ Just (io_tycon, [io_res_ty], [io_data_con]) | io_tycon `hasKey` ioTyConKey
+ -> mk_alt return_result
+ (resultWrapper io_res_ty) `thenDs` \ (ccall_res_ty, the_alt) ->
+ newSysLocalDs realWorldStatePrimTy `thenDs` \ state_id ->
+ let
+ wrap = \ the_call -> mkApps (Var (dataConWrapId io_data_con))
+ [Type io_res_ty, Lam state_id $
+ Case (App the_call (Var state_id))
+ (mkWildId ccall_res_ty)
+ [the_alt]]
+ in
+ returnDs (realWorldStatePrimTy `mkFunTy` ccall_res_ty, wrap)
+ where
+ return_result state ans = mkConApp unboxedPairDataCon
+ [Type realWorldStatePrimTy, Type io_res_ty,
+ state, ans]
+
+ -- It isn't, so do unsafePerformIO
+ -- It's not conveniently available, so we inline it
+ other -> mk_alt return_result
+ (resultWrapper result_ty) `thenDs` \ (ccall_res_ty, the_alt) ->
+ let
+ wrap = \ the_call -> Case (App the_call (Var realWorldPrimId))
+ (mkWildId ccall_res_ty)
+ [the_alt]
+ in
+ returnDs (realWorldStatePrimTy `mkFunTy` ccall_res_ty, wrap)
+ where
+ return_result state ans = ans
+ where
+ mk_alt return_result (Nothing, wrap_result)
+ = -- The ccall returns ()
+ newSysLocalDs realWorldStatePrimTy `thenDs` \ state_id ->
+ let
+ the_rhs = return_result (Var state_id) (wrap_result (panic "boxResult"))
+ ccall_res_ty = mkTyConApp unboxedSingletonTyCon [realWorldStatePrimTy]
+ the_alt = (DataAlt unboxedSingletonDataCon, [state_id], the_rhs)
+ in
+ returnDs (ccall_res_ty, the_alt)
+
+ mk_alt return_result (Just prim_res_ty, wrap_result)
+ = -- The ccall returns a non-() value
+ newSysLocalDs realWorldStatePrimTy `thenDs` \ state_id ->
+ newSysLocalDs prim_res_ty `thenDs` \ result_id ->
+ let
+ the_rhs = return_result (Var state_id) (wrap_result (Var result_id))
+ ccall_res_ty = mkTyConApp unboxedPairTyCon [realWorldStatePrimTy, prim_res_ty]
+ the_alt = (DataAlt unboxedPairDataCon, [state_id, result_id], the_rhs)
+ in
+ returnDs (ccall_res_ty, the_alt)
+
+
+resultWrapper :: Type
+ -> (Maybe Type, -- Type of the expected result, if any
+ CoreExpr -> CoreExpr) -- Wrapper for the result
+resultWrapper result_ty
+ -- Base case 1: primitive types
+ | isUnLiftedType result_ty
+ = (Just result_ty, \e -> e)
+
+ -- Base case 1: the unit type ()
+ | result_ty == unitTy
+ = (Nothing, \e -> Var unitDataConId)
+
+ | result_ty == boolTy
+ = (Just intPrimTy, \e -> Case e (mkWildId intPrimTy)
+ [(LitAlt (mkMachInt 0),[],Var falseDataConId),
+ (DEFAULT ,[],Var trueDataConId )])
+
+ -- Data types with a single constructor, which has a single arg
+ | is_product_type && data_con_arity == 1
+ = let
+ (maybe_ty, wrapper) = resultWrapper unwrapped_res_ty
+ (unwrapped_res_ty : _) = data_con_arg_tys