Changeset 7190 for src/Pugs/Types.hs

Show
Ignore:
Timestamp:
09/28/05 23:08:26 (3 years ago)
Author:
autrijus
Message:

r7196@not: autrijus | 2005-09-28 11:04:59 +0300


r7197@not: autrijus | 2005-09-28 11:28:35 +0300

  • beginning of the main pugs cabal file r7198@not: autrijus | 2005-09-28 12:36:41 +0300
  • some more metadata for Pugs.cabal. r7211@not: autrijus | 2005-09-28 21:27:14 +0300
  • releng: normalize and todoize tests. r7221@not: autrijus | 2005-09-29 00:05:29 +0300
  • Remove the unreferenced Pugs.AST.Types.
  • Move the ill-named Pugs.Context back inside Pugs.Types.
  • Reuse its Tolkien quote for the underquoted Pugs.Version.
Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Types.hs

    r6826 r7190  
    1212 
    1313module Pugs.Types ( 
    14     Type(..), mkType, anyType, showType, 
    15     ClassTree, 
     14    Type(..), mkType, anyType, showType, isaType, isaType', deltaType, 
     15    ClassTree, initTree, addNode, 
    1616 
    1717    Cxt(..),  
     
    169169    show _ = "<tmvar>" 
    170170 
     171{-| 
     172Count the total number of types in a class tree, including both internal and 
     173leaf nodes. 
     174 
     175This is used by 'deltaType' to ensure that incompatible types are always 
     176further apart than compatible types. 
     177-} 
     178countTree :: ClassTree -> Int 
     179countTree (Node _ []) = 1 
     180countTree (Node _ cs) = 1 + sum (map countTree cs) 
     181 
     182{-| 
     183Find the \'difference\' between two types in the given class tree (for MMD 
     184purposes and such). 
     185 
     186Identical types (that exist in the class tree) produce 0. Compatible types 
     187will produce a small positive number representing their distance. 
     188Incompatible will produce a distance larger 
     189than any two compatible types. If one (or both) of the types doesn't exist in 
     190the tree, the result is a very large number. 
     191 
     192> <scook0> is deltaType supposed to be returning large positive numbers for  
     193>            types that are actually incompatible? 
     194> <autrijus> that is a open design question. 
     195> <autrijus> it is that way because we want 
     196> <autrijus> '1'+'2' 
     197> <autrijus> to work 
     198> <scook0> I see 
     199> <autrijus> without having to define <+> as Scalar Scalar 
     200> <autrijus> I think I did think of leaving a compatibleTypes as remedy 
     201> <autrijus> to specify things that are fundamentally uncastable 
     202> <scook0> I think I'll just document the current behaviour for now 
     203> <autrijus> nod. it is a mess. it really wants a rewrite. 
     204-} 
     205deltaType :: ClassTree -- ^ Class tree to use for the comparison 
     206          -> Type      -- ^ Base type 
     207          -> Type      -- ^ Possibly-derived type 
     208          -> Int 
     209deltaType = junctivate min max $ \tree base target -> 
     210    let distance = distanceType tree base target in 
     211    if distance < 0 
     212        then countTree tree - distance 
     213        else distance 
     214 
     215{-| 
     216Autothreading of comparisons between junctive types. 
     217 
     218Just as autothreading over value junctions will perform an operation on all 
     219junction elements and combine the results back into a junction, this function 
     220autothreads some type comparison over all the possible type permutations, 
     221then combines the results using two user-specified /functions/. 
     222 
     223E.g. if we want to check whether the type @(Int|Str)@ is a @Num@, we first 
     224check whether @Int@ is a @Num@ (@True@), then check whether @Str@ is a num 
     225(@False@), then combine the results using the specified disjunctive combiner 
     226(in this case Haskell's @(||)@). The result is thus @True@. 
     227-} 
     228junctivate :: (t -> t -> t) -- ^ Function to combine results over disjunctive  
     229                            --     (@|@) types 
     230           -> (t -> t -> t) -- ^ Function to combine results over conjunctive  
     231                            --     (@\&@) types 
     232           -> (ClassTree -> Type -> Type -> t) 
     233                            -- ^ Function that will actually perform the  
     234                            --     comparison (on non-junctive types) 
     235           -> ClassTree     -- ^ Class tree to pass to the comparison function 
     236           -> Type          -- ^ First type to compare 
     237           -> Type          -- ^ Second type to compare 
     238           -> t 
     239junctivate or and f tree base target 
     240    | TypeOr t1 t2 <- target 
     241    = redo base t1 `or` redo base t2 
     242    | TypeOr b1 b2 <- base 
     243    = redo b1 target `or` redo b2 target 
     244    | TypeAnd t1 t2 <- target 
     245    = redo base t1 `and` redo base t2 
     246    | TypeAnd b1 b2 <- base 
     247    = redo b1 target `and` redo b2 target 
     248    | otherwise 
     249    = f tree base target 
     250    where 
     251    redo = junctivate or and f tree 
     252 
     253-- When saying Int.isa(Scalar), Scalar is the base, Int is the target 
     254{-| 
     255A more convenient version of 'isaType\'' that automatically converts the base 
     256type string into an actual 'Type' value. 
     257-} 
     258isaType :: ClassTree -- ^ Class tree to use for the comparison 
     259        -> String    -- ^ Base type 
     260        -> Type      -- ^ Possibly-derived type 
     261        -> Bool 
     262isaType tree base target = isaType' tree (mkType base) target 
     263 
     264{-| 
     265Return true if the second type (the \'target\') is derived-from or equal-to the  
     266first type (the \'base\'), in the context of the given class tree. 
     267 
     268This function will autothread over junctive types. 
     269-} 
     270isaType' :: ClassTree -- ^ Class tree to use for the comparison 
     271         -> Type      -- ^ Base type 
     272         -> Type      -- ^ Possibly-derived type 
     273         -> Bool 
     274isaType' = junctivate (||) (&&) $ \tree base target -> 
     275    distanceType tree base target >= 0 
     276 
     277{-| 
     278Compute the \'distance\' between two types by applying 'findList' to each of 
     279them, and passing the resulting type chains to 'compareList'. 
     280 
     281See 'compareList' for further details. 
     282-} 
     283distanceType :: ClassTree -> Type -> Type -> Int 
     284distanceType tree base target = compareList l1 l2 
     285--  | not (castOk base target)  = 0 
     286--  | otherwise = compareList l1 l2 
     287    where 
     288    l1 = findList base tree 
     289    l2 = findList target tree 
     290 
     291{- 
     292-- | (This is currently unused...) 
     293castOk :: a -> b -> Bool 
     294castOk _ _ = True 
     295-} 
     296 
     297{-| 
     298Take two inheritance chains produced by 'findList', and determine how 
     299\'compatible\' the first one is with the second. 
     300 
     301Compatible types will produce a number indicating how distant they are. 
     302Incompatible types produce a negative number indicating how much the base type 
     303would need to be relaxed. If one (or both) types doesn't exist in the tree, a  
     304large negative number is produced 
     305 
     306E.g.: 
     307 
     308* comparing @Int@ and @Int@ will produce 0 
     309 
     310* comparing @Scalar@ and @String@ will produce 1 
     311 
     312* comparing @Num@ and @Scalar@ will produce -2 
     313 
     314* comparing @Blorple@ and @Method@ will produce -999 (or similar) 
     315-} 
     316compareList :: [Type] -- ^ Base type's chain 
     317            -> [Type] -- ^ Possibly-derived type's chain 
     318            -> Int 
     319compareList [] _ = -999 -- XXX hack (nonexistent base type?) 
     320compareList _ [] = -999 -- XXX hack (incompatible types) 
     321compareList l1 l2 
     322    | last l1 `elem` l2 =   length(l2 \\ l1) -- compatible types 
     323    | last l2 `elem` l1 = - length(l1 \\ l2) -- anti-compatible types 
     324    | otherwise = compareList l1 (init l2) 
     325 
     326{-| 
     327Produce the type \'inheritance\' chain leading from the base type (@Any@) to 
     328the given type. 
     329 
     330e.g. 
     331 
     332@ 
     333'findList' ('MkType' \"Num\") 'initTree' 
     334@ 
     335 
     336will produce the list of types 
     337 
     338@ 
     339Any, Void, Object, Scalar, Complex, Num 
     340@ 
     341 
     342This function does /not/ expect to be given junctive types. 
     343-} 
     344findList :: Type      -- ^ 'Type' to find the inheritance chain of 
     345         -> ClassTree -- ^ Class tree to look in 
     346         -> [Type] 
     347findList base (Node l cs) 
     348    | base == l                             = [l] 
     349    | Just ls <- find (not . null) found    = l:ls 
     350    | otherwise                             = [] 
     351    where 
     352    found :: [[Type]] 
     353    found = map (findList base) cs 
     354 
     355{- 
     356{-| 
     357Pretty-print the initial class tree, using @Tree@'s @drawTree@. 
     358 
     359(This seems to be a debugging aid, since it's not actually used anywhere.) 
     360-} 
     361prettyTypes :: String 
     362prettyTypes = drawTree $ fmap show initTree 
     363-} 
     364 
     365{-| 
     366Add a new \'top-level\' type to the class tree, under @Object@. 
     367-} 
     368addNode :: ClassTree -> Type -> ClassTree 
     369addNode (Node obj [Node any (Node item ns:rest), junc]) typ = 
     370    Node obj [Node any (Node item ((Node typ []):ns):rest), junc] 
     371addNode _ _ = error "malformed tree" 
     372 
     373{-| 
     374Default class tree, containing all built-in types. 
     375-} 
     376initTree :: ClassTree 
     377initTree = fmap MkType $ Node "Object" 
     378    [ Node "Any" 
     379        [ Node "Item" 
     380            [ Node "List" 
     381                [ Node "Lazy" 
     382                    [ Node "Array" 
     383                        [ Node "Array::Const" [] 
     384                        , Node "Array::Slice" [] 
     385                        ] 
     386                    , Node "Hash" 
     387                        [ Node "Hash::Const" [] 
     388                        , Node "Hash::Env" [] 
     389                        ] 
     390                    ] 
     391                , Node "Eager" [] 
     392                ] 
     393            , Node "Scalar" 
     394                [ Node "Complex" 
     395                    [ Node "Num" 
     396                        [ Node "Rat" 
     397                            [ Node "Int" 
     398                                [ Node "Bit" [] ] ] ] ] 
     399                , Node "Bool" [] 
     400                , Node "Str" [] 
     401                , Node "Ref" [] 
     402                , Node "IO" 
     403                    [ Node "IO::Dir" [] 
     404                    ] 
     405                , Node "Socket" [] 
     406                , Node "Thread" [] 
     407                , Node "Code" 
     408                    [ Node "Routine" 
     409                        [ Node "Sub" 
     410                            [ Node "Method" [] 
     411                            , Node "Submethod" []  -- why isn't this a node off Method? - mugwump 
     412                            ] 
     413                        , Node "Macro" [] ] 
     414                    , Node "Block" [] 
     415                    ] 
     416                , Node "Rul" [] 
     417                , Node "Pugs::Internals::VRule" [] 
     418                , Node "Match" [] 
     419                , Node "Scalar::Const" [] 
     420                , Node "Scalar::Proxy" [] 
     421                , Node "Scalar::Lazy" [] 
     422                , Node "Scalar::Perl5" [] 
     423                , Node "Proxy" [] 
     424                , Node "Control::Caller" [] 
     425                , Node "Time::Local" [] 
     426                , Node "Type" 
     427                    [ Node "Package" 
     428                        [ Node "Module" 
     429                            [ Node "Class" 
     430                                [ Node "Role" [] 
     431                                , Node "Grammar" [] 
     432                                ] ] ] ] 
     433                ] 
     434            ] 
     435        , Node "Pair" [] 
     436        ] 
     437    , Node "Junction" [] ] 
     438