packages feed

pec-0.1: test_cases/TestVariant.pec

module TestVariant exports all

where

import Prelude

main :: () -> W32
main () = do
  testEnum ()
  testNewtype ()
  testNewtypePoly ()
  testVariant ()
  testUnit ()
  0

type Color = | Red | Blue | Green // the standard enum example

unColor :: Color -> W32
unColor c = case c of
  Red -> 0
  Blue -> 1
  Green -> 2

sColor :: Color -> IString
sColor c = case c of // case on enums is by value
  Red -> "Red"
  Blue -> "Blue"
  Green -> "Green"

type Unit = | Unit // singleton type, isomorphic to ()

unitf :: () -> Unit
unitf () = Unit

unita :: Unit -> ()
unita _ = () // todo(?): unita Unit = ()

testUnit :: () -> ()
testUnit () = do
  putLn "testunit"
  x = Unit // singleton types are compiled into "void" in LLVM
  unita x
  unitf ()
  unita Unit
  putLn "done"

testEnum :: () -> ()
testEnum () = do
  putLn "testEnum"
  assert (Red == Red)
  x = Green // enum types are compiled into unsigned ints in LLVM
  putLn (sColor x)
  assert (Green == x)
  assert (x == Green)
  assert (x != Blue)
  p = new Blue
  assert (@p == Blue)
  putLn (sColor @p)
  p <- Red
  assert (@p != Blue)
  putLn (sColor @p)
  p <- x
  putLn (sColor @p)
  assert (@p == Green)
  assert (unColor @p == 2)
  assert (unColor Blue == 1)
  case Red of
    Green -> assert False
    Red -> assert True
    color -> assert (color != Blue)
  case x of
    Green -> assert True
    Red -> assert False
    Blue -> assert False
  putLn "done"

type Meters = | M W32 // newtype.  A variant with only one tag

>instance EQ Meters_ where
>  eq = unwrap2 eq
>  ne = unwrap2 ne

type MyA a = | My a // polymorphic newtype

testNewtype :: () -> ()
testNewtype () = do
  putLn "testNewtype"
  assert (M 7 == M 7)
// newtypes are constructed by juxtaposition like in Haskell
// newtypes are compiled into whatever the underlying type is in LLVM (i.e. the tag is eliminated)
  x = M 12
  assert (x == M 12)
  p = new (M 7)
  assert (@p != M 12)
  assert (@p == M 7)
  p <- M 47
  assert (@p == M 47)
  assert (47 == unwrap @p) // instead of using "case" to extract values from newtypes, pec provides the polymorphic "unwrap" function
  p <- M 1
  i = unwrap @p
  assert (i == 1)
  putLn "done"

testNewtypePoly :: () -> ()
testNewtypePoly () = do
  putLn "testNewtypePoly"
  x = My 'c'
  p = new x
  assert (unwrap @p == 'c')
  q = new (My True)
  assert (unwrap @q)
  putLn "done"

testVariant :: () -> ()
testVariant () = do
  putLn "testVariant"
  p = new (Left False)
  p <- Right 'c' // p :: Ptr (Either Bool Char)
// variants must be accessed via a pointer
  case p of
    Left a -> do
      assert @a
    Right b -> do // b :: Ptr Char, not Char
      putCh @b
      assert (@b == 'c')
  p <- Left True // store the value "Left True" in p
  case p of
    Left a -> assert @a
    Right b -> do
      putCh @b
      assert False
  q = new Nothing
  case q of
    Nothing -> assert True
    Just _ -> assert False
  q <- Just True
  case q of
    Just b -> assert @b
    _ -> assert False
  putLn "done"