module LowLevel ( openHatFile -- :: CString -> IO () , openBridgeFile -- :: CString -> IO () , getBridgeValue -- :: IO FileNode , getErrorLoc -- :: IO FileNode , getErrorMessage -- :: IO CString , FileNode(..) , nil -- :: FileNode , NodeType(..) , TraceType(..) , nodeType -- :: FileNode -> NodeType , traceType -- :: FileNode -> TraceType , getParentNode -- :: FileNode -> FileNode , getIdent -- :: FileNode -> String , getIdentMod -- :: FileNode -> String , getFixity -- :: FileNode -> Int , isLiteral -- :: FileNode -> Bool , isConstructor -- :: FileNode -> Bool , getApArgs -- :: FileNode -> [FileNode] , getSrcRef -- :: FileNode -> FileNode , srcRefFile -- :: FileNode -> String , srcRefLine -- :: FileNode -> Int , srcRefCol -- :: FileNode -> Int , getDefnRef -- :: FileNode -> FileNode , defnFile -- :: FileNode -> String , defnLine -- :: FileNode -> Int , defnCol -- :: FileNode -> Int , peekTrace -- :: FileNode -> FileNode , getResult -- :: FileNode -> FileNode ) where import FFI -- Reference into the .hat file newtype FileNode = FileNode {int::Int} deriving (Eq) nil = FileNode 0 -- There are four basic types of node, encoded in the upper 3 bits of the tag data NodeType = Trace | ModuleInfo | NmType | SR deriving (Eq,Enum) -- There are ten types of trace node, encoded in the lower 5 bits of the tag -- We don't bother with subdividing other types of node (ModuleInfo etc) -- at this level (although we do in C). data TraceType = TAp | TNm | TInd | THidden | TSatA | TSatB | TSatC | TSatAL | TSatBL | TSatCL deriving (Eq) instance Enum TraceType where toEnum 0 = TAp toEnum 1 = TNm toEnum 2 = TInd toEnum 3 = THidden toEnum 4 = TSatA toEnum 5 = TSatB toEnum 6 = TSatC toEnum 12 = TSatAL toEnum 13 = TSatBL toEnum 14 = TSatCL -- For opening files, and and collecting values from the bridge file. foreign import openHatFile :: CString -> IO () foreign import openBridgeFile :: CString -> IO () foreign import getBridgeValue :: IO FileNode foreign import getErrorLoc :: IO FileNode foreign import errorMessage :: IO CString getErrorMessage :: IO String getErrorMessage = do msg <- errorMessage peekCString msg -- Find out what node type we have a reference to. nodeType :: FileNode -> NodeType nodeType n = toEnum (getNodeType n) foreign import getNodeType :: FileNode -> Int -- Only for Trace nodes, find out what kind we have a reference to. traceType :: FileNode -> TraceType traceType n = toEnum (getTraceType n) foreign import getTraceType :: FileNode -> Int -- For any node type, get its parent. If it doesn't have one, the -- zero node is returned. foreign import parentNode :: FileNode -> FileNode getParentNode :: FileNode -> FileNode getParentNode n = peekTrace (parentNode n) -- Only for Trace nodes of kind TNm, we follow the NmType pointer and get -- back a string representation of the name (identifier, Integer, Double, etc), -- and its fixity. The predicate isLiteral reports True for values of basic -- types like Int, Char, Double etc, and isConstructor identifies Constrs. foreign import getNm :: FileNode -> CString foreign import getNmMod :: FileNode -> CString foreign import getFixity :: FileNode -> Int foreign import isLiteral :: FileNode -> Bool foreign import isConstructor :: FileNode -> Bool getIdent :: FileNode -> String getIdent n = unsafePerformIO (peekCString (getNm n)) getIdentMod :: FileNode -> String getIdentMod n = unsafePerformIO (peekCString (getNmMod n)) -- For Trace nodes excluding kind TNm, get any arguments. getApArgs :: FileNode -> [FileNode] getApArgs n = let arity = getApArity n in (map (getApArg n) [0..arity]) foreign import getApArity :: FileNode -> Int foreign import getApArg :: FileNode -> Int -> FileNode -- For any node type, get its source reference. If it doesn't have one, -- we get a null pointer (0) back. foreign import getSrcRef :: FileNode -> FileNode -- For a NmType node, get its definition information. If it isn't a -- NmType Id, we get a null pointer (0) back. foreign import getDefnRef :: FileNode -> FileNode -- Only for an SR node, get the module name, line or column. -- If the node is null, return dummy values ("", 0, 0). foreign import getSrcRefFile :: FileNode -> CString foreign import srcRefLine :: FileNode -> Int foreign import srcRefCol :: FileNode -> Int srcRefFile :: FileNode -> String srcRefFile n = unsafePerformIO (peekCString (getSrcRefFile n)) -- Only for an Ident node, get the definition module name, line or column. -- If the node is null, return dummy values ("", 0, 0). foreign import getDefnFile :: FileNode -> CString foreign import defnLine :: FileNode -> Int foreign import defnCol :: FileNode -> Int defnFile :: FileNode -> String defnFile n = unsafePerformIO (peekCString (getDefnFile n)) -- Look past any SATs, indirections, or hidden nodes, to `real' trace. foreign import peekTrace :: FileNode -> FileNode -- Only for a TAp node, look for an immediately following (non-lonely) -- SAT, which therefore points to the result of the application. Return -- the result pointer. If there is no SAT, or the result is undefined, -- return 0. foreign import getResult :: FileNode -> FileNode