packages feed

ivory-examples-0.1.0.3: examples/FibLoop.hs

{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE CPP #-}

module FibLoop where

import Prelude ()
import Prelude.Compat

import Ivory.Compile.C.CmdlineFrontend
import Ivory.Language

-- Recursive implementation of fib
fib_rec :: Def ('[Uint32] ':-> Uint64)
fib_rec  = proc "fib_rec" (\n -> body (ret =<< call fib_rec_aux 0 1 n))

fib_rec_aux :: Def ('[Uint32,Uint32,Uint32] ':-> Uint64)
fib_rec_aux  = proc "fib_rec_aux" $ \ a b n -> body $ do
  ifte_ (n ==? 0)
    (ret (safeCast a))
    (ret . safeCast =<< call fib_rec_aux b (a + b) (n - 1))

-- Loop implementation of fib.

fib_loop :: Def ('[Ix 1000] ':-> Uint32)
fib_loop  = proc "fib_loop" $ \ n -> body $ do
  a <- local (ival 0)
  b <- local (ival 1)
  comment "before loop"
  n `times` \ _ix -> do
    comment "inside top of loop"
    a' <- deref a
    b' <- deref b
    store a b'
    store b (a' + b')
    comment "inside end of loop"
  comment "after end of loop"

  result <- deref a
  ret result
  -- comment "after return"

-- Loop implementation of fib, using a structure instead
-- of two discrete variables.
[ivory|
struct Fibstate
  { sa :: Stored Uint32
  ; sb :: Stored Uint32
  }
|]

fib_struct_loop :: Def ('[Ix 1000] ':-> Uint32)
fib_struct_loop  = proc "fib_struct_loop" $ \ n -> body $ do
  state <- local (istruct [ sa .= ival 0 , sb .= ival 0 ])

  let update = (+) <$> deref (state ~> sa) <*> deref (state ~> sb)

  n `times` \ _ -> do
    store (state ~> sa) =<< deref (state ~> sb)
    store (state ~> sb) =<< update

  ret =<< deref (state ~> sa)

cmodule :: Module
cmodule = package "FibLoop" $ do
  incl fib_rec
  incl fib_rec_aux
  incl fib_loop

  defStruct (Proxy :: Proxy "Fibstate")
  incl fib_struct_loop

runFibLoop :: IO ()
runFibLoop  = runCompiler [cmodule] [] initialOpts { outDir = Nothing, constFold = True }