packages feed

KiCS-debugger-0.1.0: biosphere/src/Curry/Module/FlatToAbstractCurry.lcurry

Flat Curry to Abstract Curry
============================

This module provides some constants and converters from Flat Curry to Abstract Curry.

Imports:
--------

> import FlatCurry as FC
> import FlatCurryGoodies
> import AbstractHaskell
> import AbstractCurry as AC
> import Assertion
> import AbstractCurryPrinter
> import List

Variables
=========

Converts a flat curry variable index (single `Int`) to a `CVarIName` as
parameter for `CTVar`, `CVar` and `CPVar`.

> convertVariable :: VarIndex -> CVarIName
> convertVariable i | i < 0     = (i,'y':show (-i))
>                   | otherwise = (i,'x':show i)

> convertTypeVariable :: VarIndex -> CVarIName
> convertTypeVariable i | i < 0                  = (i, 'y':show (-i))
>                       | i <= ord 'z' - ord 'a' = (i,[chr (i + ord 'a')])
>                       | otherwise              = (i, 'x':show i)

Creating variables

> xx :: Int -> CExpr
> xx = CVar . convertVariable

> px :: Int -> CPattern
> px = CPVar . convertVariable

> tx :: Int -> CTypeExpr
> tx = CTVar . convertTypeVariable

Returns the index from the first fresh variable for the given FC expression.

> freshVariable :: Expr -> Int
> freshVariable = (+1) . maximum . allVars where
>   maximum []            = -1
>   maximum [x]           = x
>   maximum (x:xs@(_:_))  = max x (maximum xs)

Extracts all type variable indices contained in the given type.

> extractTVars (TVar index)     = [index]
> extractTVars (TCons _ argts)  = nub $ concat (map extractTVars argts)
> extractTVars (FuncType t1 t2) = nub $ (extractTVars t1) ++ (extractTVars t2)


Converts flat curry visibility in abstract curry visibilty.

> convertVisibility FC.Public  = AC.Public
> convertVisibility FC.Private = AC.Private


Converts a flat curry operator into a abstract curry operator.

> convertOperator :: OpDecl -> COpDecl
> convertOperator (Op name p n) = (COp name (convertFixity p) n)


Converts flat curry fixity in abstract curry fixity.

> convertFixity InfixOp  = CInfixOp
> convertFixity InfixlOp = CInfixlOp
> convertFixity InfixrOp = CInfixrOp


Converts a flat curry type declaration to abstract curry.

> convertTypeDecl :: TypeDecl -> CTypeDecl
> convertTypeDecl (Type name vis vars conss) =
>   (CType name
>          (convertVisibility vis)
>          (map convertVariable vars)
>          (map convertConsDecl conss))

> convertTypeDecl (TypeSyn name vis vars typeexpr) =
>   (CTypeSyn name
>             (convertVisibility vis)
>             (map convertVariable vars)
>             (convertType typeexpr))


Converts a flat curry type expression to abstract curry without transformation!

> convertType :: TypeExpr -> CTypeExpr
> convertType (TVar i)           = tx i
> convertType (FuncType te1 te2) = CFuncType (convertType te1) (convertType te2)
> convertType (TCons name tes)   = CTCons name (map convertType tes)


Converts a flat curry constructor declaration to abstract curry.

> convertConsDecl :: ConsDecl -> CConsDecl
> convertConsDecl (Cons  name arity vis args) =
>                 (CCons name arity (convertVisibility vis) (map convertType args))


Converts a flat curry literal to abstract curry.

> convertLiteral (Intc i)   = CIntc i
> convertLiteral (Floatc f) = CFloatc f
> convertLiteral (Charc c)  = CCharc c


Converts a flat curry pattern to abstract curry.

> convertPattern (Pattern name is) = CPComb name $ map (CPVar . convertVariable) is
> convertPattern (LPattern lit)    = CPLit $ convertLiteral lit


Abstract curry symbol for an empty guard:

> csuccess :: CExpr
> csuccess = presym "success"


Some useful abstractions:
-------------------------

Create a rule with no guard 

> noGuardRule :: [CPattern] -> CExpr -> [CLocalDecl] -> CRule
> noGuardRule ps e = CRule ps [(csuccess,e)] 

Create a simple rule with no guard and no local declarations

> simpleRule :: [CPattern] -> CExpr -> CRule
> simpleRule ps e = noGuardRule ps e []

Create a rule without pattern

> constantRule :: CExpr -> CRule
> constantRule = simpleRule []

there is no need for eval annotations anymore

> rules :: [CRule] -> CRules
> rules = CRules CFlex

some simplifications and security in building a function declaration

> funcDecl :: AC.QName -> CVisibility -> CTypeExpr -> [CRule] -> HFuncDecl
> funcDecl _ _   _ [] = error "no rules to create function"
> funcDecl n vis t rrs@(r:rs)
>  | not (all (==arity r) (map arity rs)) = error "rules have different arity"
>  | otherwise = HFunc n (arity r) vis [] t (rules rrs)
>  where
>    arity (CRule ps _ _) = length ps

> pubFunc :: AC.QName -> CTypeExpr -> [CRule] -> HFuncDecl
> pubFunc n = funcDecl n AC.Public

> untypedFunc :: AC.QName -> [CRule] -> HFuncDecl
> untypedFunc n = pubFunc n untyped

> constantFunc :: AC.QName -> CExpr -> HFuncDecl
> constantFunc n expr = untypedFunc n [constantRule expr]

name of the prelude 

> prelude :: String
> prelude = "Prelude" 

Constructing a QName of the prelude

> prename :: String -> AC.QName
> prename s = (prelude,s)

A symbol of the prelude:

> presym :: String -> CExpr
> presym s = CSymbol (prename s)

Apply an expression to an expression and to a list of expressions.

> ($$) :: CExpr -> CExpr -> CExpr
> ($$) = CApply

> ($$$) :: CExpr -> [CExpr] -> CExpr
> ($$$) = foldl ($$)

> comb :: FC.QName -> [CExpr] -> CExpr
> comb sym = ($$$) (CSymbol sym)

Creating lists

> (:!:) :: CExpr -> CExpr -> CExpr
> a :!: b = (presym ":") $$$ [a,b] 

> list :: [CExpr] -> CExpr
> list []     = presym "[]"
> list (e:es) = e :!: (list es)

> acyStr :: String -> CExpr
> acyStr []     = presym "[]"
> acyStr (c:cs) = (presym ":") $$$ [(CLit (CCharc c)),(acyStr cs)]

Creating lambdas

> (->>) :: [CPattern] -> CExpr -> CExpr
> (->>) = CLambda

> (->-) :: CPattern -> CExpr -> CExpr
> (->-) = CLambda . (:[])


Higher Order is done with two concepts: 
1) returning a partial call
2) a lifting operation which is applied as many times as arguments are missing

> higherOrder :: CExpr -> Int ->  CExpr 
> higherOrder wrapper n = construct (map wrap [1 .. n])
>   where
>    construct [x]          = x
>    construct (x:xs@(_:_)) = point $$$ [x,construct xs]
>    
>    wrap m | m==1      = wrapper
>           | otherwise = point $$ wrap (m-1)

The initial wrapper for monads

> monadWrap :: CExpr
> monadWrap = point $$ presym "return"

The application `(.)` in AbstractCurry

> point :: CExpr
> point = presym "."

a type expression representing "untyped" -- what an ugly hack :o(

> untyped :: CTypeExpr
> untyped = CTCons (prename "untyped") []

Creates a constraint for given variable and qualified name of class.

> constraint :: AC.QName -> CVarIName -> TypeClass
> constraint clazz var = (TypeClass clazz [CTVar var])


Tests
------

> test1 = AssertEqual "rules with no guard" 
>                     (noGuardRule [] csuccess []) 
>                     (simpleRule [] csuccess)
>

	> test2 = AssertEqual "see? no guard"
	>                     (showFuncDecl (untypedFunc ("","f") [simpleRule [] csuccess]))
	>                     "\nf = success"
	>

> test3 = AssertEqual "applying something"
>                     (showExpr (presym "f" $$$ map (CVar . convertVariable) [1..3]))
>                     "f x1 x2 x3"
>
>
> test4 = AssertEqual "a nice lambda" 
>                     (showExpr (px 1 ->- xx 1))
>                     "\\x1 -> x1" 
>

should be equal to: return . (\x->x)

> test5 = AssertEqual "higher order 1"
>                     (showExpr $ higherOrder monadWrap 1 $$ (px 1 ->- xx 1))
>                     "((.)) return (\\x1 -> x1)"

should be equal to: ((return.) . ((return.).)) (\ x y ->x)

> test6 = AssertEqual "higher order 2"
>                     (showExpr $ higherOrder monadWrap 2 $$ ([px 1,px 2] ->> xx 1))
>                     "((.)) (((.)) return) (((.)) (((.)) return)) (\\x1 x2 -> x1)"

should be equal to: ((return.) . ((return.).) . (((return .) .) .)) (\ x y z -> x)

> test7 = AssertEqual "higher order 3"
>                     (showExpr $ higherOrder monadWrap 3 $$ ([px 1,px 2,px 3] ->> xx 1))
>                     "((.)) (((.)) return) (((.)) (((.)) (((.)) return)) (((.)) (((.)) (((.)) return)))) (\\x1 x2 x3 -> x1)"