KiCS-debugger-0.1.0: biosphere/src/Curry/Debugger/DebugInfo.lhs
> {-# LANGUAGE DeriveDataTypeable #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE UndecidableInstances #-}
% DebugInfo.lhs
% Andreas Baldeau
% April 13, 2009
Overview
========
> module Curry.Debugger.DebugInfo (
> DI (..),
> StaticInfo (..),
> DynamicInfo (..),
> ModID,
> DefID,
> Term (..),
> GenTerm (..)
> ) where
> import Data.Generics
> import Curry.Debugger.Logic
The representation of debug information
=======================================
`DI`
----
Our debug information consist of two different kinds of information. The first
ones are static information i.e. information about the executed code.
> data DI = DebugInfo {
> staticInfo :: StaticInfo,
> dynamicInfo :: DynamicInfo
> }
> deriving Show
`StaticInfo`
------------
`SrcID` holds a reference to the position in code where the function / data
type / etc. of intrest is defined.
> data StaticInfo = SrcID {
> modID :: ModID,
> defID :: DefID
> }
> | SrcDescr String -- ???
> deriving (Show,Eq,Data,Typeable)
> type ModID = String -- for the moment its the file name
> --Integer
> type DefID = Integer
`DynamicInfo`
-------------
The second kind of information are dynamic ones. They hold concrete values as
arguments to a function call, local variables, etc.
> data DynamicInfo = DynamicInfo {
> context :: [(StaticInfo, Term)],
> currentValues :: [Term]
> }
> deriving Show
`Term`
------
> data Term = Term String StaticInfo [Term]
> | TermChar Char
> | TermInt Integer -- deprecated
> | TermFloat Float
> | TermExt StaticInfo ExternalValue
> | TermUnderscore StaticInfo
> | TermOr StaticInfo OrRef [Term]
> | TermFail StaticInfo
> deriving (Show,Eq,Data,Typeable)
> type ExternalValue = String
The class `GenTerm`
===================
The static information is generated during the transformation of the modules
whereas dynamic information has to be generated at runtime. To be able to get
a represantion e.g. of the value returned by a function one can call `genTerm`
as there is an instance of `GenTerm` generated for every data type.
> class Data a => GenTerm a where
> genTerm :: a -> Term
`underscore` returns a representation of a not evaluated expression.
> underscore :: a
The class `GenStaticInfo`
=========================
Provides a function to return the static information of a term for given constructor.
> class GenStaticInfo a where
> genStaticInfo :: a -> StaticInfo
The class `DebugType`
=====================
Class that has (is going to / GenTerm deprecated) to be available for all transformed types and provides functions for
- generating terms for given constructors
- returning a representation failed calculations
- creating non-deterministic branches for the type
- returning a representation of not evaluated terms
> class DebugType a where
> generateTerm :: a -> Term
> genfailed :: a
> makeOr :: OrRef -> [a] -> a
> genunderscore :: a
`DebugType` instance for `Data` and `GenStaticInfo` types
---------------------------------------------------------
Generic instance for all types providing an instance of `Data`.
> instance (Data a,GenStaticInfo a) => DebugType a where
> generateTerm x = let si = genStaticInfo x
> cons = toConstr x in
> case constrIndex cons of
Special terms for special constructors:
> 1 -> TermFail si
> 2 -> TermOr si (orRef x) (map generateTerm (branches x))
> 3 -> TermUnderscore si
Regular term for a regular constructor:
> _ -> Term (showConstr cons) si [] -- (map generateTerm (args x))
The failed representation is the 1st constructor of a transformed type:
> genfailed = let res = fromConstr $ indexConstr (dataTypeOf res) 1 in res
The or branch representation is the 2nd constructor of a transformed type:
> makeOr ref xs =
> let orWithUndefined = fromConstr $ indexConstr (dataTypeOf (head xs)) 2
> orWithArgs = gmapT (castArgs ref xs) orWithUndefined
> in orWithArgs
The representation for not evaluated calculations is the 3rd constructor of a transformed type:
> genunderscore = let res = fromConstr $ indexConstr (dataTypeOf res) 3 in res