+
+data Repr = ProdRepr {
+ prod_components :: [Type]
+ , prod_tycon :: TyCon
+ , prod_data_con :: DataCon
+ , prod_arr_tycon :: TyCon
+ , prod_arr_data_con :: DataCon
+ }
+
+ | SumRepr {
+ sum_components :: [Repr]
+ , sum_tycon :: TyCon
+ , sum_arr_tycon :: TyCon
+ , sum_arr_data_con :: DataCon
+ }
+
+ | IdRepr Type
+
+ | VoidRepr {
+ void_tycon :: TyCon
+ , void_bottom :: CoreExpr
+ }
+
+mkVoid :: VM Repr
+mkVoid = do
+ tycon <- builtin voidTyCon
+ var <- builtin voidVar
+ return $ VoidRepr {
+ void_tycon = tycon
+ , void_bottom = Var var
+ }
+
+mkProduct :: [Type] -> VM Repr
+mkProduct tys
+ = do
+ tycon <- builtin (prodTyCon arity)
+ let [data_con] = tyConDataCons tycon
+
+ (arr_tycon, _) <- parrayReprTyCon $ mkTyConApp tycon tys
+ let [arr_data_con] = tyConDataCons arr_tycon
+
+ return $ ProdRepr {
+ prod_components = tys
+ , prod_tycon = tycon
+ , prod_data_con = data_con
+ , prod_arr_tycon = arr_tycon
+ , prod_arr_data_con = arr_data_con
+ }
+ where
+ arity = length tys
+
+mkSubProduct :: [Type] -> VM Repr
+mkSubProduct [] = mkVoid
+mkSubProduct [ty] = return $ IdRepr ty
+mkSubProduct tys = mkProduct tys
+
+mkSum :: [Repr] -> VM Repr
+mkSum [repr] = return repr
+mkSum reprs
+ = do
+ tycon <- builtin (sumTyCon arity)
+ (arr_tycon, _) <- parrayReprTyCon
+ . mkTyConApp tycon
+ $ map reprType reprs
+
+ let [arr_data_con] = tyConDataCons arr_tycon
+
+ return $ SumRepr {
+ sum_components = reprs
+ , sum_tycon = tycon
+ , sum_arr_tycon = arr_tycon
+ , sum_arr_data_con = arr_data_con
+ }
+ where
+ arity = length reprs
+
+reprType :: Repr -> Type
+reprType (ProdRepr { prod_tycon = tycon, prod_components = tys })
+ = mkTyConApp tycon tys
+reprType (SumRepr { sum_tycon = tycon, sum_components = reprs })
+ = mkTyConApp tycon (map reprType reprs)
+reprType (IdRepr ty) = ty
+reprType (VoidRepr { void_tycon = tycon }) = mkTyConApp tycon []
+
+arrReprType :: Repr -> VM Type
+arrReprType = mkPArrayType . reprType
+
+arrShapeTys :: Repr -> VM [Type]
+arrShapeTys (SumRepr {})
+ = do
+ int_arr <- builtin parrayIntPrimTyCon
+ return [intPrimTy, mkTyConApp int_arr [], mkTyConApp int_arr []]
+arrShapeTys (ProdRepr {}) = return [intPrimTy]
+arrShapeTys (IdRepr _) = return []
+arrShapeTys (VoidRepr {}) = return [intPrimTy]
+
+arrShapeVars :: Repr -> VM [Var]
+arrShapeVars repr = mapM (newLocalVar FSLIT("sh")) =<< arrShapeTys repr
+
+replicateShape :: Repr -> CoreExpr -> CoreExpr -> VM [CoreExpr]
+replicateShape (ProdRepr {}) len _ = return [len]
+replicateShape (SumRepr {}) len tag
+ = do
+ rep <- builtin replicatePAIntPrimVar
+ up <- builtin upToPAIntPrimVar
+ return [len, Var rep `mkApps` [len, tag], Var up `App` len]
+replicateShape (IdRepr _) _ _ = return []
+replicateShape (VoidRepr {}) len _ = return [len]
+
+arrReprElemTys :: Repr -> VM [[Type]]
+arrReprElemTys (SumRepr { sum_components = prods })
+ = mapM arrProdElemTys prods
+arrReprElemTys prod@(ProdRepr {})
+ = do
+ tys <- arrProdElemTys prod
+ return [tys]
+arrReprElemTys (IdRepr ty) = return [[ty]]
+arrReprElemTys (VoidRepr { void_tycon = tycon })
+ = return [[mkTyConApp tycon []]]
+
+arrProdElemTys (ProdRepr { prod_components = [] })
+ = do
+ void <- builtin voidTyCon
+ return [mkTyConApp void []]
+arrProdElemTys (ProdRepr { prod_components = tys })
+ = return tys
+arrProdElemTys (IdRepr ty) = return [ty]
+arrProdElemTys (VoidRepr { void_tycon = tycon })
+ = return [mkTyConApp tycon []]
+
+arrReprTys :: Repr -> VM [[Type]]
+arrReprTys repr = mapM (mapM mkPArrayType) =<< arrReprElemTys repr
+
+arrReprVars :: Repr -> VM [[Var]]
+arrReprVars repr
+ = mapM (mapM (newLocalVar FSLIT("rs"))) =<< arrReprTys repr
+
+mkRepr :: TyCon -> VM Repr
+mkRepr vect_tc
+ | [tys] <- rep_tys = mkProduct tys
+ | otherwise = mkSum =<< mapM mkSubProduct rep_tys
+ where
+ rep_tys = map dataConRepArgTys $ tyConDataCons vect_tc
+