1
1
{-# LANGUAGE FlexibleContexts, TemplateHaskell #-}
2
2
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
3
3
{-# LANGUAGE LambdaCase, OverloadedStrings #-}
4
- -- module Language.Pcf (Ty(..), Exp(..), compile, output) where
5
- module Language.Pcf where
4
+ module Language.Pcf (Ty (.. ), Exp (.. ), compile , output ) where
5
+
6
6
import Bound
7
7
import Control.Applicative
8
8
import Control.Monad
@@ -17,7 +17,7 @@ import Data.Maybe (fromJust)
17
17
import qualified Data.Set as S
18
18
import Data.String
19
19
import Data.Traversable hiding (mapM )
20
- -- import Language.C.DSL
20
+ import Language.C.DSL
21
21
import Paths_pcf
22
22
import Data.Deriving
23
23
@@ -218,97 +218,97 @@ fauxc (LetL binds e) = do
218
218
--------------- Conversion to Real C -------------------
219
219
--------------------------------------------------------
220
220
221
- -- type RealCM = WriterT [CBlockItem] (Gen Integer)
222
-
223
- -- i2d :: Integer -> CDeclr
224
- -- i2d = fromString . ('_':) . show
225
-
226
- -- i2e :: Integer -> CExpr
227
- -- i2e = var . fromString . ('_':) . show
228
-
229
- -- taggedTy :: CDeclSpec
230
- -- taggedTy = CTypeSpec "tagged_ptr"
231
-
232
- -- tellDecl :: CExpr -> RealCM CExpr
233
- -- tellDecl e = do
234
- -- i <- gen
235
- -- tell [CBlockDecl $ decl taggedTy (i2d i) $ Just e]
236
- -- return (i2e i)
237
-
238
- -- realc :: FauxC CExpr -> RealCM CExpr
239
- -- realc (VFC e) = return e
240
- -- realc (AppFC f a) = ("apply" #) <$> mapM realc [f, a] >>= tellDecl
241
- -- realc ZeroFC = tellDecl $ "mkZero" # []
242
- -- realc (SucFC e) = realc e >>= tellDecl . ("inc"#) . (:[])
243
- -- realc (IfzFC i t e) = do
244
- -- outi <- realc i
245
- -- deci <- tellDecl ("dec" # [outi])
246
- -- let e' = instantiate1 (VFC deci) e
247
- -- (outt, blockt) <- lift . runWriterT $ (realc t)
248
- -- (oute, blocke) <- lift . runWriterT $ (realc e')
249
- -- out <- tellDecl "EMPTY"
250
- -- let branch b tempOut =
251
- -- CCompound [] (b ++ [CBlockStmt . liftE $ out <-- tempOut]) undefNode
252
- -- ifStat =
253
- -- cifElse ("isZero"#[outi]) (branch blockt outt) (branch blocke oute)
254
- -- tell [CBlockStmt ifStat]
255
- -- return out
256
- -- realc (LetFC binds bind) = do
257
- -- bindings <- mapM goBind binds
258
- -- realc $ instantiate (VFC . (bindings !!)) bind
259
- -- where sizeOf Int = "INT_SIZE"
260
- -- sizeOf Clos = "CLOS_SIZE"
261
- -- goBind (NRecFC i cs) =
262
- -- ("mkClos" #) <$> (i2e i :) . (fromIntegral (length cs) :)
263
- -- <$> mapM realc cs
264
- -- >>= tellDecl
265
- -- goBind (RecFC t i cs) = do
266
- -- f <- ("mkClos" #) <$> (i2e i :) . (fromIntegral (length cs) :)
267
- -- <$> mapM realc cs
268
- -- >>= tellDecl
269
- -- tellDecl ("fixedPoint"#[f, sizeOf t])
270
-
271
- -- topc :: FauxCTop CExpr -> Gen Integer CFunDef
272
- -- topc (FauxCTop i numArgs body) = do
273
- -- binds <- gen
274
- -- let getArg = (!!) (args (i2e binds) numArgs)
275
- -- (out, block) <- runWriterT . realc $ instantiate getArg body
276
- -- return $
277
- -- fun [taggedTy] ('_' : show i) [decl taggedTy $ ptr (i2d binds)] $
278
- -- CCompound [] (block ++ [CBlockStmt . creturn $ out]) undefNode
279
- -- where indexArg binds i = binds ! fromIntegral i
280
- -- args binds na = map (VFC . indexArg binds) [0..na - 1]
281
-
282
- -- -- | Given an expression where free variables are integers, convert it
283
- -- -- to C. This function doesn't include all of the runtime system in
284
- -- -- the translation unit which makes it unsuitable for running all on
285
- -- -- its own. It's primarly for inspecting the copmiled result of a
286
- -- -- given expression.
287
- -- compile :: Exp Integer -> Maybe CTranslUnit
288
- -- compile e = runGen . runMaybeT $ do
289
- -- assertTy M.empty e Nat
290
- -- funs <- lift $ pipe e
291
- -- return . transUnit . map export $ funs
292
- -- where pipe e = do
293
- -- simplified <- closConv e >>= llift
294
- -- (main, funs) <- runWriterT $ fauxc simplified
295
- -- i <- gen
296
- -- let topMain = FauxCTop i 1 (abstract (const Nothing) main)
297
- -- funs' = map (i2e <$>) (funs ++ [topMain])
298
- -- (++ [makeCMain i]) <$> mapM topc funs'
299
- -- makeCMain entry =
300
- -- fun [intTy] "main"[] $ hBlock ["call"#[i2e entry]]
301
-
302
- -- -- | Compiles ane expression using 'compile'. If we can compile
303
- -- -- program this function returns an @Just s@ action which returns this
304
- -- -- where @s@ is a runnable C program which outputs the result. If
305
- -- -- there was a type error, this gives back 'Nothing'.
306
- -- output :: Exp Integer -> IO (Maybe String)
307
- -- output e = case compile e of
308
- -- Nothing -> return Nothing
309
- -- Just p -> do
310
- -- rts <- getDataFileName "src/preamble.c" >>= readFile
311
- -- return . Just $ rts ++ '\n' : show (pretty p)
221
+ type RealCM = WriterT [CBlockItem ] (Gen Integer )
222
+
223
+ i2d :: Integer -> CDeclr
224
+ i2d = fromString . (' _' : ) . show
225
+
226
+ i2e :: Integer -> CExpr
227
+ i2e = var . fromString . (' _' : ) . show
228
+
229
+ taggedTy :: CDeclSpec
230
+ taggedTy = CTypeSpec " tagged_ptr"
231
+
232
+ tellDecl :: CExpr -> RealCM CExpr
233
+ tellDecl e = do
234
+ i <- gen
235
+ tell [CBlockDecl $ decl taggedTy (i2d i) $ Just e]
236
+ return (i2e i)
237
+
238
+ realc :: FauxC CExpr -> RealCM CExpr
239
+ realc (VFC e) = return e
240
+ realc (AppFC f a) = (" apply" # ) <$> mapM realc [f, a] >>= tellDecl
241
+ realc ZeroFC = tellDecl $ " mkZero" # []
242
+ realc (SucFC e) = realc e >>= tellDecl . (" inc" # ) . (: [] )
243
+ realc (IfzFC i t e) = do
244
+ outi <- realc i
245
+ deci <- tellDecl (" dec" # [outi])
246
+ let e' = instantiate1 (VFC deci) e
247
+ (outt, blockt) <- lift . runWriterT $ (realc t)
248
+ (oute, blocke) <- lift . runWriterT $ (realc e')
249
+ out <- tellDecl " EMPTY"
250
+ let branch b tempOut =
251
+ CCompound [] (b ++ [CBlockStmt . liftE $ out <-- tempOut]) undefNode
252
+ ifStat =
253
+ cifElse (" isZero" # [outi]) (branch blockt outt) (branch blocke oute)
254
+ tell [CBlockStmt ifStat]
255
+ return out
256
+ realc (LetFC binds bind) = do
257
+ bindings <- mapM goBind binds
258
+ realc $ instantiate (VFC . (bindings !! )) bind
259
+ where sizeOf Int = " INT_SIZE"
260
+ sizeOf Clos = " CLOS_SIZE"
261
+ goBind (NRecFC i cs) =
262
+ (" mkClos" # ) <$> (i2e i : ) . (fromIntegral (length cs) : )
263
+ <$> mapM realc cs
264
+ >>= tellDecl
265
+ goBind (RecFC t i cs) = do
266
+ f <- (" mkClos" # ) <$> (i2e i : ) . (fromIntegral (length cs) : )
267
+ <$> mapM realc cs
268
+ >>= tellDecl
269
+ tellDecl (" fixedPoint" # [f, sizeOf t])
270
+
271
+ topc :: FauxCTop CExpr -> Gen Integer CFunDef
272
+ topc (FauxCTop i numArgs body) = do
273
+ binds <- gen
274
+ let getArg = (!!) (args (i2e binds) numArgs)
275
+ (out, block) <- runWriterT . realc $ instantiate getArg body
276
+ return $
277
+ fun [taggedTy] (' _' : show i) [decl taggedTy $ ptr (i2d binds)] $
278
+ CCompound [] (block ++ [CBlockStmt . creturn $ out]) undefNode
279
+ where indexArg binds i = binds ! fromIntegral i
280
+ args binds na = map (VFC . indexArg binds) [0 .. na - 1 ]
281
+
282
+ -- | Given an expression where free variables are integers, convert it
283
+ -- to C. This function doesn't include all of the runtime system in
284
+ -- the translation unit which makes it unsuitable for running all on
285
+ -- its own. It's primarly for inspecting the copmiled result of a
286
+ -- given expression.
287
+ compile :: Exp Integer -> Maybe CTranslUnit
288
+ compile e = runGen . runMaybeT $ do
289
+ assertTy M. empty e Nat
290
+ funs <- lift $ pipe e
291
+ return . transUnit . map export $ funs
292
+ where pipe e = do
293
+ simplified <- closConv e >>= llift
294
+ (main, funs) <- runWriterT $ fauxc simplified
295
+ i <- gen
296
+ let topMain = FauxCTop i 1 (abstract (const Nothing ) main)
297
+ funs' = map (i2e <$> ) (funs ++ [topMain])
298
+ (++ [makeCMain i]) <$> mapM topc funs'
299
+ makeCMain entry =
300
+ fun [intTy] " main" [] $ hBlock [" call" # [i2e entry]]
301
+
302
+ -- | Compiles ane expression using 'compile'. If we can compile
303
+ -- program this function returns an @Just s@ action which returns this
304
+ -- where @s@ is a runnable C program which outputs the result. If
305
+ -- there was a type error, this gives back 'Nothing'.
306
+ output :: Exp Integer -> IO (Maybe String )
307
+ output e = case compile e of
308
+ Nothing -> return Nothing
309
+ Just p -> do
310
+ rts <- getDataFileName " src/preamble.c" >>= readFile
311
+ return . Just $ rts ++ ' \n ' : show (pretty p)
312
312
313
313
314
314
-------------------------------------------------------------------
0 commit comments