packages feed

pec-0.2.0: lib/Prelude.pec

module Prelude

where

type W8 = W #8 //An unsigned 8-bit word.
type W16 = W #16
type W32 = W #32
type W64 = W #64
type I8 = I #8 // a signed 8-bit int
type I16 = I #16
type I32 = I #32
type I64 = I #64

type Bool = | False | True
// enum type
// the "|" is used to specify "or"

instance Eq Bool // eq and ne can be derived for enums

type Maybe a = | Nothing | Just a // polymorphic variant
// order doesn't matter
// type Maybe a = | Just a | Nothing would be compiled exactly the same way

is_nothing :: { Load p } => Pointer p (Maybe a) -> Bool
is_nothing x => case x of
  Nothing -> True
  _ -> False

type Either a b = | Left a | Right b // polymorphic variant

type Ordering = | LT | EQ | GT // another enum

instance Eq Ordering

// externally defined names.  name on the left, type on the right

// external C calls
new :: a -> Ptr a
new a => do
  p = unsafe_alloca
  p <- a
  p

extern unsafe_alloca :: Ptr a

unsafe_alloca_array :: #cnt -> Ptr (Array #cnt a)
unsafe_alloca_array _ => unsafe_alloca

extern store :: { Store p } => Pointer p a -> a -> ()
extern load :: { Load p } => Pointer p a -> a
extern idx :: Pointer p (Array #cnt a) -> Idx #cnt -> Pointer p a
extern then :: () -> a -> a

extern exit :: I32 -> a

// language primitives
extern add :: { Arith a } => a -> a -> a
extern sub :: { Arith a } => a -> a -> a
extern mul :: { Arith a } => a -> a -> a
extern div :: { Arith a } => a -> a -> a
extern rem :: { Arith a } => a -> a -> a
extern gt :: { Ord a } => a -> a -> Bool
extern gte :: { Ord a } => a -> a -> Bool
extern lt :: { Ord a } => a -> a -> Bool
extern lte :: { Ord a } => a -> a -> Bool
extern eq :: { Eq a } => a -> a -> Bool
extern ne :: { Eq a } => a -> a -> Bool
extern shl :: W #a -> W #a -> W #a
extern shr :: W #a -> W #a -> W #a
extern band :: W #a -> W #a -> W #a
extern bor :: W #a -> W #a -> W #a
extern bxor :: W #a -> W #a -> W #a
extern bnot :: W #a -> W #a -> W #a
// BAL: support ashr?

extern if :: Bool -> a -> a -> a
extern when :: Bool -> () -> ()
extern while :: Bool -> () -> ()

eq_eq => eq
bang_eq => ne
gt_eq => gte
lt_eq => lte
add_eq p x => p <- @p + x
sub_eq p x => p <- @p - x
mul_eq p x => p <- @p * x
div_eq p x => p <- @p / x

and :: Bool -> Bool -> Bool
and a b => if a b False
band_band => and

or :: Bool -> Bool -> Bool
or a b => if a True b
bor_bor => or

lt_lt => shl
gt_gt => shr

extern abs :: { Arith a } => a -> a
extern acos :: { Floating a } => a -> a
extern asin :: { Floating a } => a -> a
extern atan :: { Floating a } => a -> a
extern atan2 :: { Floating a } => a -> a
extern ceil :: { Floating a } => a -> a
extern cos :: { Floating a } => a -> a
extern cosh :: { Floating a } => a -> a
extern exp :: { Floating a } => a -> a
extern floor :: { Floating a } => a -> a
extern log :: { Floating a } => a -> a
extern log10 :: { Floating a } => a -> a
extern pow :: { Floating a } => a -> a -> a
extern sin :: { Floating a } => a -> a
extern sinh :: { Floating a } => a -> a
extern sqrt :: { Floating a } => a -> a
extern tan :: { Floating a } => a -> a
extern tanh :: { Floating a } => a -> a

sqrtw :: W #cnt -> W #cnt
sqrtw x => unsafe_cast (floor (sqrt ((unsafe_cast x) :: Double)))

extern "printf" unsafe_printf :: { Load p } => Pointer p Char -> a -> ()

putW :: W #cnt -> ()
putW => unsafe_putS "%u"

putI :: I #cnt -> ()
putI => unsafe_putS "%i"

putF :: Float -> ()
putF => unsafe_putS "%f"

putD :: Double -> ()
putD => unsafe_putS "%f"

inc :: { Arith a } => Ptr a -> ()
inc x => x <- @x + 1

dec :: { Arith a } => Ptr a -> ()
dec x => x <- @x - 1

for :: a -> (a -> Bool) -> (a -> a) -> (a -> ()) -> ()
for a f g h => do
  p = new a
  while (f @p)
    (do
      h @p
      p <- g @p
    )

times :: { Arith a, Ord a } => a -> (a -> ()) -> ()
times n f => for 0 (\i -> i < n) succ f

succ :: { Arith a } => a -> a
succ a => a + 1

flip :: (a -> b -> c) -> b -> a -> c
flip f b a => f a b

chr :: W8 -> Char
chr => unsafe_cast

ord :: Char -> W8
ord => unsafe_cast

from_idx :: Idx #cnt -> W32
from_idx => unsafe_cast

unsafe_to_idx :: W32 -> Idx #cnt
unsafe_to_idx => unsafe_cast

to_ordering :: I32 -> Ordering
to_ordering x = branch
  x < 0 -> LT
  x > 0 -> GT
  | EQ

putCh :: Char -> ()
putCh => unsafe_putS "%c"

putElem :: { Load p } => (a -> ()) -> Pointer p a -> ()
putElem f p => do
  f @p
  putCh ' '

putBrackets :: () -> ()
putBrackets f => do
  putCh '['
  putCh ' '
  f
  putCh ']'

assert :: Bool -> ()
assert x = when (not x) (error "assertion failed")

not :: Bool -> Bool
not x => if x False True

error :: IString -> a
error x => do
  putLn x
  exit -1
  unsafe_alpha

undefined :: a
undefined => error "undefined"

extern unsafe_alpha :: a

putS :: IString -> ()
putS x => unsafe_putS "%s" x

unsafe_putS :: IString -> a -> ()
unsafe_putS x => unsafe_printf (iString_unwrapptr x)

putLn :: IString -> ()
putLn x => do
  putS x
  putS "\n"

// different pointer types
type Ptr a = Pointer LoadStoreP a
type RPtr a = Pointer LoadP a
type WPtr a = Pointer StoreP a

type LoadP
type StoreP
type LoadStoreP

instance Load LoadP
instance Store StoreP
instance Load LoadStoreP
instance Store LoadStoreP

iString_unwrapptr :: IString -> RPtr Char
iString_unwrapptr => unsafe_cast

is_upper :: Char -> Bool
is_upper c = (c >= 'A') && (c <= 'Z') // operators don't have precedence, parens are required

is_lower :: Char -> Bool
is_lower c = (c >= 'a') && (c <= 'z')

is_digit :: Char -> Bool
is_digit c = (c >= '0') && (c <= '9')

to_lower :: Char -> Char
to_lower c = branch
  is_upper c -> chr (ord c + 32)
  | c

to_upper :: Char -> Char
to_upper c = branch
  is_lower c -> chr (ord c - 32)
  | c

otherwise :: Bool
otherwise => True

min :: { Ord a } => a -> a -> a
min a b => do
  x = a
  y = b
  if (x < y) x y

max :: { Ord a } => a -> a -> a
max a b => do
  x = a
  y = b
  if (x > y) x y

max_idx :: Idx #cnt -> Idx #cnt
max_idx _ => idx_max

count_idx :: Idx #cnt -> W32
count_idx x => from_idx (max_idx x) + 1

id :: a -> a
id x => x

type Pair a b = { fst :: a, snd :: b }

pair :: a -> b -> (a,b)
pair a b => (a,b) // same as { fst = a, snd = b }

fst :: Pointer p (a,b) -> Pointer p a
fst (a,_) => a

snd :: Pointer p (a,b) -> Pointer p b
snd (_,b) => b

ignore :: a -> b -> b
ignore _ b => b

extern void :: ()

fold_ptr :: { Load p } => (b -> a -> b) -> Ptr b -> Pointer p a -> ()
fold_ptr f pb pa => pb <- f @pb @pa