{-# LANGUAGE DeriveDataTypeable #-}------------------------------------------------------------------------------- |-- Module : Language.C.Data.Ident-- Copyright : (c) [1995..1999] Manuel M. T. Chakravarty-- (c) 2008 Benedikt Huber-- License : BSD-style-- Maintainer : benedikt.huber@gmail.com-- Stability : experimental-- Portability : ghc---- This module provides the notion of identifiers in C, speed up using hashing.-- Identifiers are associated optionally associated with a 'NodeInfo', i.e. with -- a unique 'Name' and a source location ('Position'). The ordering relation on-- identifiers is based on the hash and does not follow the lexical order.-----------------------------------------------------------------------------moduleLanguage.C.Data.Ident(Ident(..),SUERef(..),isAnonymousRef,mkIdent,builtinIdent,internalIdent,internalIdentAt,isInternalIdent,identToString,dumpIdent)where-- TODO (comment from manuel):-- * Hashing is not 8bit clean.importData.CharimportLanguage.C.Data.PositionimportLanguage.C.Data.NodeimportLanguage.C.Data.Name(Name,nameId)importData.Generics-- | References uniquely determining a struct, union or enum type.-- Those are either identified by an string identifier, or by a unique-- name (anonymous types).dataSUERef=AnonymousRefName|NamedRefIdentderiving(Typeable,Data,Ord,Eq)instanceShowSUERefwhereshow(AnonymousRefname)="$"++show(nameIdname)show(NamedRefident)=identToStringident-- | Return true if the struct\/union\/enum reference is anonymous.isAnonymousRef::SUERef->BoolisAnonymousRef(AnonymousRef_)=TrueisAnonymousRef_=False-- | C identifiersdataIdent=IdentString-- lexeme{-# UNBOXED #-}!Int-- hash to speed up equality checkNodeInfo-- attributes of this ident. incl. positionderiving(Data,Typeable)-- the definition of the equality allows identifiers to be equal that are-- defined at different source text positions, and aims at speeding up the-- equality test, by comparing the lexemes only if the two numbers are equal--instanceEqIdentwhere(Identsh_)==(Idents'h'_)=(h==h')&&(s==s')-- this does *not* follow the alphanumerical ordering of the lexemes--instanceOrdIdentwherecompare(Identsh_)(Idents'h'_)=compare(h,s)(h',s')-- for displaying identifiersinstanceShowIdentwhereshowsPrec_ide=showString("`"++identToStringide++"'")-- identifiers are attributedinstanceCNodeIdentwherenodeInfo(Ident__at)=atinstancePosIdentwhereposOf=posOfNode.nodeInfo-- to speed up the equality test we compute some hash-like value for each-- identifiers lexeme and store it in the identifiers representation-- hash function from the dragon book pp437; assumes 7 bit characters and needs-- the (nearly) full range of values guaranteed for `Int' by the Haskell-- language definition; can handle 8 bit characters provided we have 29 bit-- for the `Int's without sign--quad::String->Intquad(c1:c2:c3:c4:s)=((ordc4*bits21+ordc3*bits14+ordc2*bits7+ordc1)`mod`bits28)+(quads`mod`bits28)quad(c1:c2:c3:[])=ordc3*bits14+ordc2*bits7+ordc1quad(c1:c2:[])=ordc2*bits7+ordc1quad(c1:[])=ordc1quad([])=0bits7::Intbits7=2^(7::Int)bits14::Intbits14=2^(14::Int)bits21::Intbits21=2^(21::Int)bits28::Intbits28=2^(28::Int)-- | build an identifier from a string.---- * only minimal error checking, e.g., the characters of the identifier are-- not checked for being alphanumerical only; the correct lexis of the-- identifier should be ensured by the caller, e.g., the scanner.---- * for reasons of simplicity the complete lexeme is hashed.mkIdent::Position->String->Name->IdentmkIdentpossname=Idents(quads)(mkNodeInfoposname)-- | returns an /internal/ identifier (has internal position and no unique name)internalIdent::String->IdentinternalIdents=Idents(quads)(mkNodeInfoOnlyPosinternalPos)-- | return an /internal/ identifier with position infointernalIdentAt::Position->String->IdentinternalIdentAtposs=Idents(quads)(mkNodeInfoOnlyPospos)-- | returns a /builtin/ identifier (has builtin position and no unique name)builtinIdent::String->IdentbuiltinIdents=Idents(quads)(mkNodeInfoOnlyPosbuiltinPos)-- | return @True@ if the given identifier is /internal/isInternalIdent::Ident->BoolisInternalIdent(Ident__nodeinfo)=isInternalPos(posOfNodenodeinfo)-- | string of an identifieridentToString::Ident->StringidentToString(Idents__)=s-- | dump the identifier string and its positions for debugging purposesdumpIdent::Ident->StringdumpIdentide=identToStringide++" at "++show(nodeInfoide)