packages feed

funcons-tools-0.1.0.0: manual/Funcons/Core/Values/Primitive/Numbers/Integers.hs

{-# LANGUAGE OverloadedStrings #-}

module Funcons.Core.Values.Primitive.Numbers.Integers where

import Funcons.EDSL
import Funcons.Types

library = libFromList [
        ("integer-add", ValueOp integer_add_op)
    ,   ("integer-multiply", ValueOp integer_multiply_op)
    ,   ("integer-divide", ValueOp integer_divide_op)
    ,   ("integer-subtract", ValueOp integer_subtract_op)
    ,   ("integer-power", ValueOp integer_power_op)
--    ,   ("integer-negate", ValueOp stepInteger_Negate)
    ,   ("integer-list", ValueOp stepInteger_List)
    ,   ("integer-modulo", ValueOp stepInteger_Modulo)
    ,   ("integer-absolute-value", ValueOp stepInteger_Absolute_Value) 
    ]

integer_op :: String -> ([Funcons] -> Funcons)
                     -> (Integer -> Integer -> Integer) 
                     -> Integer -> [Values] -> Rewrite Rewritten 
integer_op str cons f b vs | all isInt vs = 
    rewriteTo $ int_ $ fromInteger $ foldr f b $ map toInt vs
                           | otherwise = sortErr (cons (map FValue vs)) err
    where   isInt v | Int _ <- upcastIntegers v = True
                    | otherwise = False
            toInt v | Int i <- upcastIntegers v = i
                    | otherwise = error err
            err     = str ++ " not applied to integers"

integer_add_ = FApp "integer-add" . FTuple

integer_add_op vs = integer_op "integer-add" integer_add_ (+) 0 vs

integer_multiply_ = FApp "integer-multiple" . FTuple
integer_multiply_op vs = integer_op "integer-multiply" integer_multiply_ (*) 1 vs

integer_divide_ = FApp "integer-divide" . FTuple
integer_divide_op [vx,vy]
    | (Int x,Int y) <- (upcastIntegers vx, upcastIntegers vy) = 
        rewriteTo $ int_ $ fromInteger (x `div` y)
    | True = sortErr (integer_divide_ [FValue vx, FValue vy]) "integer-divide not applied to ints" 
integer_divide_op vx = sortErr (integer_divide_ (fvalues vx)) "integer-divide not applied to two arguments" 

integer_subtract = applyFuncon "integer-subtract"
integer_subtract_op [vx,vy]
    | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy)= 
        rewriteTo $ int_ $ fromInteger (x - y)
    | otherwise = sortErr (applyFuncon "integer-subtract" [FValue vx, FValue vy])
                            "integer-subtract not applied to ints"
integer_subtract_op v = sortErr (applyFuncon "integer-subtract" (fvalues v)) "integer-subtract should receive two integers"

integer_power = applyFuncon "integer-power"
integer_power_op [vx, vy]
    | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy) = 
        rewriteTo $ int_ $ fromInteger $(x ^ y)
integer_power_op vx = sortErr (applyFuncon "integer-power" (fvalues vx))
                            "integer-power not applied to two integers"

integer_negate = applyFuncon "integer-negate"
stepInteger_Negate [v]
    | (Int i) <- upcastIntegers v = rewriteTo $ int_ (- (fromInteger i))
stepInteger_Negate vs = sortErr (integer_negate (fvalues vs)) "integer-negate not applied to an integer"

integer_list = applyFuncon "integer-list"
stepInteger_List [vi1,vi2]
    | (Int i1, Int i2) <- (upcastIntegers vi1, upcastIntegers vi2)
            = rewriteTo $ FValue $ List (map mk_integers [i1.. i2])
stepInteger_List vs = sortErr (integer_list (fvalues vs)) "sort check: integer-list(I,J)"

integer_modulo = applyFuncon "integer-modulo"
stepInteger_Modulo [i1,i2] = integer_modulo_op i1 i2
stepInteger_Modulo vs = sortErr (integer_modulo (fvalues vs)) 
                            "sort check: integer-modulo(I1,I2)"
integer_modulo_op vx vy
    | (Int x,Int y) <- (upcastIntegers vx, upcastIntegers vy)= 
        rewriteTo $ int_ $ fromInteger (x `mod` y)
integer_modulo_op vx vy = sortErr (integer_modulo [FValue vx, FValue vy])
                         "integer-modulo not applied to ints"

integer_absolute_value = applyFuncon "integer-absolute-value"
stepInteger_Absolute_Value [v]
        | Int  i <- upcastIntegers v = rewriteTo $ FValue $ mk_integers (Prelude.abs i)
stepInteger_Absolute_Value vs = sortErr (integer_absolute_value $ fvalues vs) 
                                    "sort check: integer-absolute-value(I1)"