+mk_fam_inst :: TyCon -> TyCon -> (TyCon, [Type])
+mk_fam_inst fam_tc arg_tc
+ = (fam_tc, [mkTyConApp arg_tc . mkTyVarTys $ tyConTyVars arg_tc])
+
+buildPReprTyCon :: TyCon -> TyCon -> VM TyCon
+buildPReprTyCon orig_tc vect_tc
+ = do
+ name <- cloneName mkPReprTyConOcc (tyConName orig_tc)
+ rhs_ty <- buildPReprType vect_tc
+ prepr_tc <- builtin preprTyCon
+ liftDs $ buildSynTyCon name
+ tyvars
+ (SynonymTyCon rhs_ty)
+ (Just $ mk_fam_inst prepr_tc vect_tc)
+ where
+ tyvars = tyConTyVars vect_tc
+
+
+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
+ }
+
+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
+
+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)
+
+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 repr = 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]
+
+arrReprElemTys :: Repr -> [[Type]]
+arrReprElemTys (SumRepr { sum_components = prods })
+ = map arrProdElemTys prods
+arrReprElemTys prod@(ProdRepr {})
+ = [arrProdElemTys prod]
+
+arrProdElemTys (ProdRepr { prod_components = [] })
+ = [unitTy]
+arrProdElemTys (ProdRepr { prod_components = tys })
+ = tys
+
+arrReprTys :: Repr -> VM [[Type]]
+arrReprTys = mapM (mapM mkPArrayType) . arrReprElemTys
+
+arrReprVars :: Repr -> VM [[Var]]
+arrReprVars repr
+ = mapM (mapM (newLocalVar FSLIT("rs"))) =<< arrReprTys repr
+
+mkRepr :: TyCon -> VM Repr
+mkRepr vect_tc
+ = mkSum
+ =<< mapM mkProduct (map dataConRepArgTys $ tyConDataCons vect_tc)
+
+buildPReprType :: TyCon -> VM Type
+buildPReprType = liftM reprType . mkRepr
+
+buildToPRepr :: Repr -> TyCon -> TyCon -> TyCon -> VM CoreExpr
+buildToPRepr repr vect_tc prepr_tc _
+ = do
+ arg <- newLocalVar FSLIT("x") arg_ty
+ result <- to_repr repr (Var arg)
+
+ return . Lam arg
+ . wrapFamInstBody prepr_tc var_tys
+ $ result
+ where
+ var_tys = mkTyVarTys $ tyConTyVars vect_tc
+ arg_ty = mkTyConApp vect_tc var_tys
+ res_ty = reprType repr
+
+ cons = tyConDataCons vect_tc
+ [con] = cons
+
+ to_repr (SumRepr { sum_components = prods
+ , sum_tycon = tycon })
+ expr
+ = do
+ (vars, bodies) <- mapAndUnzipM prod_alt prods
+ return . Case expr (mkWildId (exprType expr)) res_ty
+ $ zipWith4 mk_alt cons vars (tyConDataCons tycon) bodies
+ where
+ mk_alt con vars sum_con body
+ = (DataAlt con, vars, mkConApp sum_con (ty_args ++ [body]))
+
+ ty_args = map (Type . reprType) prods
+
+ to_repr prod expr
+ = do
+ (vars, body) <- prod_alt prod
+ return $ Case expr (mkWildId (exprType expr)) res_ty
+ [(DataAlt con, vars, body)]
+
+ prod_alt (ProdRepr { prod_components = tys
+ , prod_data_con = data_con })
+ = do
+ vars <- mapM (newLocalVar FSLIT("r")) tys
+ return (vars, mkConApp data_con (map Type tys ++ map Var vars))
+
+buildFromPRepr :: Repr -> TyCon -> TyCon -> TyCon -> VM CoreExpr
+buildFromPRepr repr vect_tc prepr_tc _
+ = do
+ arg_ty <- mkPReprType res_ty
+ arg <- newLocalVar FSLIT("x") arg_ty
+
+ liftM (Lam arg)
+ . from_repr repr
+ $ unwrapFamInstScrut prepr_tc var_tys (Var arg)
+ where
+ var_tys = mkTyVarTys $ tyConTyVars vect_tc
+ res_ty = mkTyConApp vect_tc var_tys
+
+ cons = map (`mkConApp` map Type var_tys) (tyConDataCons vect_tc)
+ [con] = cons
+
+ from_repr repr@(SumRepr { sum_components = prods
+ , sum_tycon = tycon })
+ expr
+ = do
+ vars <- mapM (newLocalVar FSLIT("x")) (map reprType prods)
+ bodies <- sequence . zipWith3 from_prod prods cons
+ $ map Var vars
+ return . Case expr (mkWildId (reprType repr)) res_ty
+ $ zipWith3 sum_alt (tyConDataCons tycon) vars bodies
+ where
+ sum_alt data_con var body = (DataAlt data_con, [var], body)
+
+ from_repr repr expr = from_prod repr con expr
+
+ from_prod prod@(ProdRepr { prod_components = tys
+ , prod_data_con = data_con })
+ con
+ expr
+ = do
+ vars <- mapM (newLocalVar FSLIT("y")) tys
+ return $ Case expr (mkWildId (reprType prod)) res_ty
+ [(DataAlt data_con, vars, con `mkVarApps` vars)]
+
+buildToArrPRepr :: Repr -> TyCon -> TyCon -> TyCon -> VM CoreExpr
+buildToArrPRepr repr vect_tc prepr_tc arr_tc
+ = do
+ arg_ty <- mkPArrayType el_ty
+ arg <- newLocalVar FSLIT("xs") arg_ty
+
+ res_ty <- mkPArrayType (reprType repr)
+
+ shape_vars <- arrShapeVars repr
+ repr_vars <- arrReprVars repr
+
+ parray_co <- mkBuiltinCo parrayTyCon
+
+ let Just repr_co = tyConFamilyCoercion_maybe prepr_tc
+ co = mkAppCoercion parray_co
+ . mkSymCoercion
+ $ mkTyConApp repr_co var_tys
+
+ scrut = unwrapFamInstScrut arr_tc var_tys (Var arg)
+
+ result <- to_repr shape_vars repr_vars repr
+
+ return . Lam arg
+ . mkCoerce co
+ $ Case scrut (mkWildId (mkTyConApp arr_tc var_tys)) res_ty
+ [(DataAlt arr_dc, shape_vars ++ concat repr_vars, result)]
+ where
+ var_tys = mkTyVarTys $ tyConTyVars vect_tc
+ el_ty = mkTyConApp vect_tc var_tys
+
+ [arr_dc] = tyConDataCons arr_tc
+
+ to_repr shape_vars@(len_var : _)
+ repr_vars
+ (SumRepr { sum_components = prods
+ , sum_arr_tycon = tycon
+ , sum_arr_data_con = data_con })
+ = do
+ exprs <- zipWithM (to_prod len_var) repr_vars prods
+
+ return . wrapFamInstBody tycon tys
+ . mkConApp data_con
+ $ map Type tys ++ map Var shape_vars ++ exprs
+ where
+ tys = map reprType prods
+
+ to_repr [len_var] [repr_vars] prod = to_prod len_var repr_vars prod
+
+ to_prod len_var
+ repr_vars
+ (ProdRepr { prod_components = tys
+ , prod_arr_tycon = tycon
+ , prod_arr_data_con = data_con })
+ = return . wrapFamInstBody tycon tys
+ . mkConApp data_con
+ $ map Type tys ++ map Var (len_var : repr_vars)
+
+buildFromArrPRepr :: Repr -> TyCon -> TyCon -> TyCon -> VM CoreExpr
+buildFromArrPRepr repr vect_tc prepr_tc arr_tc
+ = do
+ arg_ty <- mkPArrayType =<< mkPReprType el_ty
+ arg <- newLocalVar FSLIT("xs") arg_ty
+
+ res_ty <- mkPArrayType el_ty
+
+ shape_vars <- arrShapeVars repr
+ repr_vars <- arrReprVars repr
+
+ parray_co <- mkBuiltinCo parrayTyCon
+
+ let Just repr_co = tyConFamilyCoercion_maybe prepr_tc
+ co = mkAppCoercion parray_co
+ $ mkTyConApp repr_co var_tys
+
+ scrut = mkCoerce co (Var arg)
+
+ result = wrapFamInstBody arr_tc var_tys
+ . mkConApp arr_dc
+ $ map Type var_tys ++ map Var (shape_vars ++ concat repr_vars)
+
+ liftM (Lam arg)
+ (from_repr repr scrut shape_vars repr_vars res_ty result)
+ where
+ var_tys = mkTyVarTys $ tyConTyVars vect_tc
+ el_ty = mkTyConApp vect_tc var_tys
+
+ [arr_dc] = tyConDataCons arr_tc
+
+ from_repr (SumRepr { sum_components = prods
+ , sum_arr_tycon = tycon
+ , sum_arr_data_con = data_con })
+ expr
+ shape_vars
+ repr_vars
+ res_ty
+ body
+ = do
+ vars <- mapM (newLocalVar FSLIT("xs")) =<< mapM arrReprType prods
+ result <- go prods repr_vars vars body
+
+ let scrut = unwrapFamInstScrut tycon ty_args expr
+ return . Case scrut (mkWildId scrut_ty) res_ty
+ $ [(DataAlt data_con, shape_vars ++ vars, result)]
+ where
+ ty_args = map reprType prods
+ scrut_ty = mkTyConApp tycon ty_args
+
+ go [] [] [] body = return body
+ go (prod : prods) (repr_vars : rss) (var : vars) body
+ = do
+ shape_vars <- mapM (newLocalVar FSLIT("s")) =<< arrShapeTys prod
+
+ from_prod prod (Var var) shape_vars repr_vars res_ty
+ =<< go prods rss vars body
+
+ from_repr repr expr shape_vars [repr_vars] res_ty body
+ = from_prod repr expr shape_vars repr_vars res_ty body
+
+ from_prod prod@(ProdRepr { prod_components = tys
+ , prod_arr_tycon = tycon
+ , prod_arr_data_con = data_con })
+ expr
+ shape_vars
+ repr_vars
+ res_ty
+ body
+ = do
+ let scrut = unwrapFamInstScrut tycon tys expr
+ scrut_ty = mkTyConApp tycon tys
+ ty <- arrReprType prod
+
+ return $ Case scrut (mkWildId scrut_ty) res_ty
+ [(DataAlt data_con, shape_vars ++ repr_vars, body)]
+
+buildPRDictRepr :: Repr -> VM CoreExpr
+buildPRDictRepr (ProdRepr {
+ prod_components = tys
+ , prod_tycon = tycon
+ })
+ = do
+ prs <- mapM mkPR tys
+ dfun <- prDFunOfTyCon tycon
+ return $ dfun `mkTyApps` tys `mkApps` prs
+
+buildPRDictRepr (SumRepr {
+ sum_components = prods
+ , sum_tycon = tycon })
+ = do
+ prs <- mapM buildPRDictRepr prods
+ dfun <- prDFunOfTyCon tycon
+ return $ dfun `mkTyApps` map reprType prods `mkApps` prs
+
+buildPRDict :: Repr -> TyCon -> TyCon -> TyCon -> VM CoreExpr
+buildPRDict repr vect_tc prepr_tc _
+ = do
+ dict <- buildPRDictRepr repr
+
+ pr_co <- mkBuiltinCo prTyCon
+ let co = mkAppCoercion pr_co
+ . mkSymCoercion
+ $ mkTyConApp arg_co var_tys
+
+ return $ mkCoerce co dict
+ where
+ var_tys = mkTyVarTys $ tyConTyVars vect_tc
+
+ Just arg_co = tyConFamilyCoercion_maybe prepr_tc
+
+buildPArrayTyCon :: TyCon -> TyCon -> VM TyCon
+buildPArrayTyCon orig_tc vect_tc = fixV $ \repr_tc ->