helium-1.8: lib/simple/HeliumLang.core
{- The (type) constructors and functions in this module are
used in the translation of language constructs.
-}
module HeliumLang
( Bool(True, False), '':[]''('':[]'', (:)), '':()''('':()''), '':->''
, String, Int, Float, IO, Char
, showFunction, showIO, showPolymorphic
, showChar, showString, showInt, showList, showBool, showUnit, showFloat
, showTuple2, showTuple3, showTuple4, showTuple5, showTuple6, showTuple7
, showTuple8, showTuple9, showTuple10
, ''$primPutChar'', ''$primPutStr'', ''$primPutStrLn''
, ''$primBindIO'', ''$primUnsafePerformIO''
, ''$primErrorPacked'', ''$primPatternFailPacked''
, ''$primNegInt'', ''$primNegFloat'', ''$primStringToFloat'', ''$primEqFloat''
, ''$primConcat'', ''$primConcatMap''
, ''$primPackedToString''
, ''$negate'', ''$floatUnaryMinus''
, ''$enumFrom'', ''$enumFromThen'', ''$enumFromTo'', ''$enumFromThenTo''
, ''$show'' , ''$showList''
) where
import LvmLang
( Int(), Float(), IO()
, custom "typedecl" String
, Bool(True, False)
, '':[]''('':[]'', (:))
, '':()''('':()'')
, ''$primBindIO'' = bindIO, ''$primReturnIO'' = returnIO
, negInt
, negFloat, ''$primEqFloat'' = (==.)
, (+), (-), (>), (<), (>=), quot, rem, (==)
, stringFromPacked
, unsafePerformIO
)
import LvmIO
( stdin, stdout, stderr, flush, outputChar, outputPacked
)
import LvmException
( errorPacked
, patternFailPacked
)
{----------------------------------------------------------
Fixities
----------------------------------------------------------}
custom infix (:) : public [5,"right"]
{--------------------------------------------------------------------------
built into the language
--------------------------------------------------------------------------}
''$negate'' :: Int -> Int
''$negate'' i = negInt i
''$floatUnaryMinus'' :: Float -> Float
''$floatUnaryMinus'' f = ''$primNegFloat'' f
''$show'' :: "showDict -> a -> String"
''$show'' dShow
= errorPacked "internal error: show called in the simple prelude!"
''$showList'' :: "(a -> String) -> [a] -> String"
''$showList'' = showList
-- the enumeration functions are used in the translation of the .. notation
-- [1..10] === enumFromTo 1 10
-- [1..] === enumFrom 1
-- [1,3..10] === enumFromThenTo 1 3 10
-- [1,3..] === enumFromThen 1 3
''$enumFrom'' :: Int -> [Int]
''$enumFrom'' n = (:) n (''$enumFrom'' ((+) n 1))
''$enumFromTo'' :: Int -> Int -> [Int]
''$enumFromTo'' n m =
case (>) n m of
{ True -> []
; _ -> (:) n (''$enumFromTo'' ((+) n 1) m)
}
''$enumFromThen'' :: Int -> Int -> [Int]
''$enumFromThen'' n a = (:) n (''$enumFromThen'' a ((+) a ((-) a n)))
''$enumFromThenTo'' :: Int -> Int -> Int -> [Int]
''$enumFromThenTo'' n a m =
case (>) a n of
{ True -> ''$primAscendToWithStep'' n m ((-) a n)
; _ -> ''$primDescendToWithStep'' n m ((-) a n)
}
{----------------------------------------------------------
Basic data types
----------------------------------------------------------}
data '':->'' x y
-- Daan has type Char = Int
data Char
''$primPackedToString'' :: PackedString -> String
''$primPackedToString'' p
= stringFromPacked p
''$primUnsafePerformIO'' :: IO a -> a
''$primUnsafePerformIO'' io
= unsafePerformIO io
''$primPatternFailPacked'' :: PackedString -> a
''$primPatternFailPacked'' p
= patternFailPacked p
''$primErrorPacked'' :: PackedString -> a
''$primErrorPacked'' p
= errorPacked p
''$primPutChar'' :: Char -> IO ()
''$primPutChar'' c =
''$primBindIO''
(outputChar stdout c)
(flush stdout)
''$primPutChars'' :: String -> IO ()
''$primPutChars'' xs =
case xs of {
'':[]'' -> ''$primReturnIO'' '':()'' ;
(:) y ys -> ''$primBindIO''
(''$primPutChar'' y) -- if you don't want to flush each character: (outputChar stdout y)
(''$primPutChars'' ys) }
''$primPutStr'' :: String -> IO ()
''$primPutStr'' xs =
''$primBindIO''
(''$primPutChars'' xs)
(flush stdout)
''$primPutStrLn'' :: String -> IO ()
''$primPutStrLn'' xs =
''$primBindIO''
(''$primPutChars'' xs)
(''$primPutChar'' '\n') -- does the flush
''$primNegInt'' :: Int -> Int!
''$primNegInt'' = negInt
''$primConcat'' :: [[a]] -> [a]
''$primConcat'' xss =
case xss of
{ '':[]'' -> []
; (:) ys yss -> ''$primAppend'' ys (''$primConcat'' yss)
}
''$primConcatMap'' :: (a -> [b]) -> [a] -> [b]
''$primConcatMap'' f xs =
case xs of
{ '':[]'' -> []
; (:) y ys -> ''$primAppend'' (f y) (''$primConcatMap'' f ys)
}
''$primAppend'' :: [a] -> [a] -> [a] -- is '++'
''$primAppend'' xs ys =
case xs of
{ '':[]'' -> ys
; (:) z zs -> (:) z (''$primAppend'' zs ys)
}
''$primAscendToWithStep'' :: Int -> Int -> Int -> [Int]
''$primAscendToWithStep'' n m step =
case (>) n m of
{ True -> []
; _ -> (:) n (''$primAscendToWithStep'' ((+) n step) m step)
}
''$primDescendToWithStep'' :: Int -> Int -> Int -> [Int]
''$primDescendToWithStep'' n m step =
case (<) n m of
{ True -> []
; _ -> (:) n (''$primDescendToWithStep'' ((+) n step) m step)
}
-- Show
showBool :: Bool -> String
showBool b =
case b of
{ True -> stringFromPacked "True"
; _ -> stringFromPacked "False"
}
showUnit :: () -> String
showUnit u =
case u of
{ '':()'' -> stringFromPacked "()"
}
showFunction :: (a -> String) -> (b -> String) -> (a->b) -> String
showFunction a b x = let! x = x in stringFromPacked "<<function>>"
showIO :: (a -> String) -> IO a -> String
showIO a x = let! x = x in stringFromPacked "<<IO action>>"
showChar :: Char -> String
showChar c =
(:) '\'' (''$primAppend'' (safeShowChar True c)
[ '\'' ])
safeShowChar :: Bool -> Char -> String
safeShowChar inChar c =
case c of
{ '\a' -> stringFromPacked "\\a"
; '\b' -> stringFromPacked "\\b"
; '\f' -> stringFromPacked "\\f"
; '\n' -> stringFromPacked "\\n"
; '\r' -> stringFromPacked "\\r"
; '\t' -> stringFromPacked "\\t"
; '\\' -> stringFromPacked "\\\\"
; '\'' -> case inChar of { True -> stringFromPacked "\\'"
; _ -> [c]
}
; '\"' -> case inChar of { True -> [c]
; _ -> stringFromPacked "\\\""
}
; _ ->
case logicalAnd ((>=) c 32) ((<) c 127) of
{ True -> [c]
; _ -> (:) '\\' (showInt c)
}
}
logicalAnd :: Bool -> Bool -> Bool
logicalAnd b1 b2 =
case b1 of
{ True -> b2
; _ -> False
}
showString :: String -> String
showString s =
(:) '\"' (''$primAppend'' (''$primConcatMap'' (safeShowChar False) s)
(stringFromPacked "\""))
showInt :: Int -> String
showInt n =
case (<) n 0 of
{ True -> (:) '(' ((:) '-'
(''$primAppend''
(showPositiveInt (''$primNegInt'' n))
(stringFromPacked ")")
))
; _ -> showPositiveInt n
}
showPositiveInt :: Int -> String
showPositiveInt i =
let
rest = quot i 10
digit = [ (+) '0' (rem i 10) ]
in
case (==) rest 0 of
{ True -> digit
; _ -> ''$primAppend'' (showPositiveInt rest) digit
}
showList :: (a -> String) -> [a] -> String
showList showElem list =
''$primConcat'' [ ['['], commaList (''$primMap'' showElem list), [']'] ]
''$primMap'' f xs =
case xs of
{ '':[]'' -> []
; (:) y ys -> (:) (f y) (''$primMap'' f ys)
}
showPolymorphic :: a -> String
showPolymorphic x =
let! x = x in stringFromPacked "<<polymorphic value>>"
showTuple2 s1 s2 t : public [custom "type" ["(a -> String) -> (b -> String) -> (a, b) -> String" ]] =
case t of
(@0, 2) x1 x2 ->
showTupleList [ s1 x1, s2 x2 ]
showTuple3 s1 s2 s3 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (a, b, c) -> String" ]] =
case t of
(@0, 3) x1 x2 x3 ->
showTupleList [ s1 x1, s2 x2, s3 x3 ]
showTuple4 s1 s2 s3 s4 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (a, b, c, d) -> String" ]] =
case t of
(@0, 4) x1 x2 x3 x4 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4 ]
showTuple5 s1 s2 s3 s4 s5 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (e -> String) -> (a, b, c, d, e) -> String" ]] =
case t of
(@0, 5) x1 x2 x3 x4 x5 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4, s5 x5 ]
showTuple6 s1 s2 s3 s4 s5 s6 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (e -> String) -> (f -> String) -> (a, b, c, d, e, f) -> String" ]] =
case t of
(@0, 6) x1 x2 x3 x4 x5 x6 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4, s5 x5, s6 x6 ]
showTuple7 s1 s2 s3 s4 s5 s6 s7 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (e -> String) -> (f -> String) -> (g -> String) -> (a, b, c, d, e, f, g) -> String" ]] =
case t of
(@0, 7) x1 x2 x3 x4 x5 x6 x7 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4, s5 x5, s6 x6, s7 x7 ]
showTuple8 s1 s2 s3 s4 s5 s6 s7 s8 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (e -> String) -> (f -> String) -> (g -> String) -> (h -> String) -> (a, b, c, d, e, f, g, h) -> String" ]] =
case t of
(@0, 8) x1 x2 x3 x4 x5 x6 x7 x8 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4, s5 x5, s6 x6, s7 x7, s8 x8 ]
showTuple9 s1 s2 s3 s4 s5 s6 s7 s8 s9 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (e -> String) -> (f -> String) -> (g -> String) -> (h -> String) -> (i -> String) -> (a, b, c, d, e, f, g, h, i) -> String" ]] =
case t of
(@0, 9) x1 x2 x3 x4 x5 x6 x7 x8 x9 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4, s5 x5, s6 x6, s7 x7, s8 x8, s9 x9 ]
showTuple10 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 t : public [custom "type" ["(a -> String) -> (b -> String) -> (c -> String) -> (d -> String) -> (e -> String) -> (f -> String) -> (g -> String) -> (h -> String) -> (i -> String) -> (j -> String) -> (a, b, c, d, e, f, g, h, i, j) -> String" ]]=
case t of
(@0, 10) x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 ->
showTupleList [ s1 x1, s2 x2, s3 x3, s4 x4, s5 x5, s6 x6, s7 x7, s8 x8, s9 x9, s10 x10 ]
showTupleList :: [String] -> String
showTupleList xs =
''$primConcat'' [ ['('], commaList xs, [')'] ]
commaList :: [String] -> String
commaList list =
case list of
{ '':[]'' -> []
; (:) x xs ->
case xs of
{ '':[]'' -> x
; _ -> ''$primAppend'' x (''$primConcatMap'' (''$primAppend'' [ ',' ]) xs)
}
}
-- Float
''$primNegFloat'' :: Float -> Float!
''$primNegFloat'' = negFloat
''$primStringToFloat'' :: String -> Float
''$primStringToFloat'' = float_of_string_extern
extern float_of_string_extern "float_of_string" :: "Fz"
''$primShowFloat'' :: Float -> String
''$primShowFloat'' x = let! x = x in stringFromPacked (stringFromFloat x 6 'g')
extern stringFromFloat "string_of_float" :: "aFII"
showFloat : public [custom "type" ["Float -> String"]]
= \f -> safeMinus (addPointZero (''$primShowFloat'' f))
safeMinus : private [custom "type" ["String -> String"]]
= \s ->
case s of
{ (:) x xs ->
case x of
{ '-' -> ''$primAppend'' (stringFromPacked "(-.") (''$primAppend'' xs (stringFromPacked ")"))
; _ -> s
}
; _ -> s
}
addPointZero : private [custom "type" ["String -> String"]]
= \s ->
case hasPointOrE s of
{ True -> s
; _ -> ''$primAppend'' s (stringFromPacked ".0")
}
hasPointOrE : private []
= \xs ->
case xs of
{ [] -> False
; (:) y ys ->
case y of
{ '.' -> True
; 'e' -> True
; _ -> hasPointOrE ys
}
}