Changeset 12374 for src/Pugs/Eval

Show
Ignore:
Timestamp:
08/17/06 17:31:05 (2 years ago)
Author:
audreyt
Message:

* Fix infinite loop in SUPER::new dispatch.
* Also refactoed Eval.Var with implicit parameters, so we can

more easily get a stack trace when something goes wrong, with
"make fastprof" and then "./pugs-prof t.pl +RTS -xs".

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Eval/Var.hs

    r12366 r12374  
    150150    | NoSuchSub 
    151151    | NoSuchMethod !Type 
     152    deriving (Show) 
    152153 
    153154_SUPER :: ByteString 
     
    158159        -> [Exp]      -- ^ Other arguments 
    159160        -> Eval (Either FindSubFailure VCode) 
    160 findSub var invs args 
    161     | Nothing <- invs = findBuiltinSub NoMatchingMulti var 
    162     | not (isQualifiedVar var) = case unwrap inv of 
    163         Val inv@VV{}     -> withExternalCall callMethodVV inv  
    164         Val inv@PerlSV{} -> withExternalCall callMethodPerl5 inv  
    165         inv' -> do 
    166             typ <- evalInvType inv' 
    167             findTypedSub (cast typ) var 
    168     | Just var' <- dropVarPkg _SUPER var = do 
    169         pkg <- asks envPackage 
    170         findSuperSub pkg var' 
    171     | otherwise = do 
    172         findBuiltinSub NoMatchingMulti var 
     161findSub var invs args = 
     162    let ?var  = var 
     163        ?invs = invs 
     164        ?args = args 
     165    in case invs of 
     166        Nothing -> findBuiltinSub NoMatchingMulti var 
     167        _ | not (isQualifiedVar var) -> case unwrap inv of 
     168            Val vv@VV{}     -> withExternalCall callMethodVV vv 
     169            Val sv@PerlSV{} -> withExternalCall callMethodPerl5 sv 
     170            inv' -> do 
     171                typ <- evalInvType inv' 
     172                findTypedSub (cast typ) var 
     173          | Just var' <- dropVarPkg _SUPER var -> do 
     174            pkg <- asks envPackage 
     175            findSuperSub pkg var' 
     176          | otherwise -> do 
     177            findBuiltinSub NoMatchingMulti var 
    173178    where 
    174179    inv = fromJust invs 
    175180 
    176     findSuperSub :: Pkg -> Var -> Eval (Either FindSubFailure VCode) 
    177     findSuperSub pkg var = do 
    178 --          qualified = Str.concat [Str.take 1 name, pkg, __"::", Str.tail name] 
    179         subs    <- findWithSuper pkg var 
    180         subs'   <- either (flip findBuiltinSub var) (return . Right) subs 
    181         case subs' of 
    182 --          Right sub | subName sub == qualified -> return (Left $ NoSuchMethod typ) 
    183             _   -> return subs' 
    184     findTypedSub :: Pkg -> Var -> Eval (Either FindSubFailure VCode) 
    185     findTypedSub pkg var = do 
    186         subs    <- findWithPkg pkg var 
    187         either (flip findBuiltinSub var) (return . Right) subs 
    188     findBuiltinSub :: FindSubFailure -> Var -> Eval (Either FindSubFailure VCode) 
    189     findBuiltinSub failure var = do 
    190         sub <- findSub' var 
    191         maybe (fmap (err failure) $ possiblyBuildMetaopVCode var) (return . Right) sub 
    192     evalInvType :: Exp -> Eval Type 
    193     evalInvType x = inferExpType $ unwrap x 
    194  
    195     withExternalCall callMeth inv = do 
    196         fmap (err . NoSuchMethod $ valType inv) $ do 
    197             metaSub <- possiblyBuildMetaopVCode var 
    198             if isJust metaSub then return metaSub else callMeth 
    199  
    200     callMethodVV :: Eval (Maybe VCode) 
    201     callMethodVV = do 
    202         let methName = cast (v_name var) 
    203         -- Look up the proto for the method in VV land right here 
    204         -- Whether it matched or not, it's the proto's signature 
    205         -- that's available to the inferencer, not any of its children's 
    206         -- (this is because MMD in newland is performed _after_ everything 
    207         -- has been reduced.) 
    208         return . Just $ mkPrim 
    209             { subName     = methName 
    210             , subParams   = makeParams ["Object", "List", "Named"] 
    211             , subReturns  = mkType "Any" 
    212             , subBody     = Prim $ \(inv:named:pos:_) -> do 
    213                 invVV   <- fromVal inv      :: Eval Val.Val 
    214                 posVVs  <- fromVals pos     :: Eval [Val.Val] 
    215                 namVVs  <- do 
    216                     list <- fromVal named 
    217                     fmap Map.fromList $ forM list $ \(k, v) -> do 
    218                         key <- fromVal k 
    219                         val <- fromVal v 
    220                         return (key, [val])   :: Eval (ID, [Val.Val]) 
    221  
    222                 -- This is the Capture object we are going to work with 
    223                 let capt = CaptMeth invVV [MkFeed posVVs namVVs] 
    224  
    225                 return . castV $ "CCall " ++ show methName ++ " " ++ show capt 
     181findSuperSub :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     182    => Pkg -> Var -> Eval (Either FindSubFailure VCode) 
     183findSuperSub pkg var = do 
     184    subs    <- findWithSuper pkg var 
     185    subs'   <- either (flip findBuiltinSub var) (return . Right) subs 
     186    case subs' of 
     187        -- Recursion prevention -- SUPER::foo should not go back to ThisClas::foo 
     188        Right sub | cast (Str.cons '&' $ subName sub) == var{ v_package = pkg } -> do 
     189            return (Left . NoSuchMethod $ cast pkg) 
     190        _   -> do 
     191            return subs' 
     192 
     193findTypedSub :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     194    => Pkg -> Var -> Eval (Either FindSubFailure VCode) 
     195findTypedSub pkg var = do 
     196    subs    <- findWithPkg pkg var 
     197    either (flip findBuiltinSub var) (return . Right) subs 
     198 
     199evalInvType :: Exp -> Eval Type 
     200evalInvType x = inferExpType $ unwrap x 
     201 
     202withExternalCall callMeth inv = do 
     203    fmap (err . NoSuchMethod $ valType inv) $ do 
     204        metaSub <- possiblyBuildMetaopVCode ?var 
     205        if isJust metaSub then return metaSub else callMeth 
     206 
     207callMethodVV :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     208    => Eval (Maybe VCode) 
     209callMethodVV = do 
     210    let methName = cast (v_name ?var) 
     211    -- Look up the proto for the method in VV land right here 
     212    -- Whether it matched or not, it's the proto's signature 
     213    -- that's available to the inferencer, not any of its children's 
     214    -- (this is because MMD in newland is performed _after_ everything 
     215    -- has been reduced.) 
     216    return . Just $ mkPrim 
     217        { subName     = methName 
     218        , subParams   = makeParams ["Object", "List", "Named"] 
     219        , subReturns  = mkType "Any" 
     220        , subBody     = Prim $ \(inv:named:pos:_) -> do 
     221            invVV   <- fromVal inv      :: Eval Val.Val 
     222            posVVs  <- fromVals pos     :: Eval [Val.Val] 
     223            namVVs  <- do 
     224                list <- fromVal named 
     225                fmap Map.fromList $ forM list $ \(k, v) -> do 
     226                    key <- fromVal k 
     227                    val <- fromVal v 
     228                    return (key, [val])   :: Eval (ID, [Val.Val]) 
     229 
     230            -- This is the Capture object we are going to work with 
     231            let capt = CaptMeth invVV [MkFeed posVVs namVVs] 
     232 
     233            return . castV $ "CCall " ++ show methName ++ " " ++ show capt 
     234        } 
     235 
     236callMethodPerl5 :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     237    => Eval (Maybe VCode) 
     238callMethodPerl5 = do 
     239    let name = cast (v_name ?var) 
     240    return . Just $ mkPrim 
     241        { subName     = name 
     242        , subParams   = makeParams ["Object", "List", "Named"] 
     243        , subReturns  = mkType "Scalar::Perl5" 
     244        , subBody     = Prim $ \(inv:named:pos:_) -> do 
     245            sv      <- fromVal inv 
     246            posSVs  <- fromVals pos 
     247            namSVs  <- fmap concat (fromVals named) 
     248            let svs = posSVs ++ namSVs 
     249            found   <- liftIO $ canPerl5 sv name 
     250            found'  <- liftIO $ if found 
     251                then return found 
     252                else canPerl5 sv (__"AUTOLOAD") 
     253            if not found' 
     254                then do 
     255                    -- XXX - when svs is empty, this could call back here infinitely 
     256                    --       add an extra '&' to force no-reinterpretation. 
     257                    evalExp $ 
     258                        App (Var ?var{ v_sigil = SCodeMulti }) Nothing 
     259                            (map (Val . PerlSV) (sv:svs)) 
     260                else do 
     261                    subSV   <- liftIO . bufToSV $ name 
     262                    runInvokePerl5 subSV sv svs 
     263        } 
     264 
     265findWithPkg :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     266    => Pkg -> Var -> Eval (Either FindSubFailure VCode) 
     267findWithPkg pkg var = do 
     268    subs <- findSub' var{ v_package = pkg } 
     269    maybe (findWithSuper pkg var) (return . Right) subs 
     270 
     271findWithSuper :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     272    => Pkg -> Var -> Eval (Either FindSubFailure VCode) 
     273findWithSuper pkg var = do 
     274    -- get superclasses 
     275    attrs <- fmap (fmap (filter (/= pkg) . nub)) $ findAttrs pkg 
     276    if isNothing attrs || null (fromJust attrs) then fmap (err NoMatchingMulti) (findSub' var) else do 
     277    (`fix` (fromJust attrs)) $ \run pkgs -> do 
     278        if null pkgs then return (Left $ NoSuchMethod (cast pkg)) else do 
     279        subs <- findWithPkg (head pkgs) var 
     280        either (const $ run (tail pkgs)) (return . Right) subs 
     281 
     282findSub' :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) => Var -> Eval (Maybe VCode) 
     283findSub' var = do 
     284    subSyms     <- findSyms var 
     285    lens        <- mapM argSlurpLen (unwrap $ maybeToList ?invs ++ ?args) 
     286    doFindSub (sum lens) subSyms 
     287 
     288argSlurpLen :: Exp -> Eval Int 
     289argSlurpLen (Val val) = valSlurpLen val 
     290argSlurpLen (Var name) = do 
     291    val <- evalExp (Var name) 
     292    valSlurpLen val 
     293argSlurpLen (Syn "," list) =  return $ length list 
     294argSlurpLen _ = return 1 -- XXX 
     295 
     296valSlurpLen :: Val -> Eval Int 
     297valSlurpLen (VList list) = return $ length list 
     298valSlurpLen (VRef (MkRef (IArray av))) = array_fetchSize av 
     299valSlurpLen (VRef (MkRef (IHash hv))) = hash_fetchSize hv 
     300valSlurpLen _  = return 1 -- XXX 
     301 
     302doFindSub :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     303    => Int -> [(Var, Val)] -> Eval (Maybe VCode) 
     304doFindSub slurpLen subSyms = do 
     305    subs' <- subs slurpLen subSyms 
     306    -- let foo (x, sub) = show x ++ show (map paramContext $ subParams sub) 
     307    -- trace (unlines $ map foo $ sort subs') return () 
     308    return $ case sort subs' of 
     309        ((_, sub):_)    -> Just sub 
     310        _               -> Nothing 
     311 
     312subs :: (?invs :: Maybe Exp, ?args :: [Exp]) 
     313    => Int -> [(Var, Val)] -> Eval [((Bool, Bool, Int, Int), VCode)] 
     314subs slurpLen subSyms = fmap catMaybes . forM subSyms $ \(_, val) -> do 
     315    sub@(MkCode{ subReturns = ret, subParams = prms }) <- fromVal val 
     316    let rv = return $ arityMatch sub (length (maybeToList ?invs ++ ?args)) slurpLen 
     317    maybeM rv $ \fun -> do 
     318        -- if deltaFromCxt ret == 0 then return Nothing else do 
     319        let pairs = map (typeOfCxt . paramContext) prms 
     320                        `zip` (map unwrap $ maybeToList ?invs ++ ?args) 
     321        deltaCxt    <- deltaFromCxt ret 
     322        deltaArgs   <- mapM deltaFromPair pairs 
     323        let bound = either (const False) (const True) $ bindParams sub ?invs ?args 
     324        return ((isMulti sub, bound, sum deltaArgs, deltaCxt), fun) 
     325 
     326findBuiltinSub :: (?var :: Var, ?invs :: Maybe Exp, ?args :: [Exp]) 
     327    => FindSubFailure -> Var -> Eval (Either FindSubFailure VCode) 
     328findBuiltinSub failure var = do 
     329    sub <- findSub' var 
     330    maybe (fmap (err failure) $ possiblyBuildMetaopVCode var) (return . Right) sub 
     331 
     332firstArg :: (?args :: [Exp]) => [Exp] 
     333firstArg = [maybe (Val undef) id (listToMaybe ?args)] 
     334 
     335buildPrefixHyper name var = do 
     336    let rv = fmap (either (const Nothing) Just) $ 
     337            findSub var Nothing firstArg 
     338    maybeM rv $ \code -> return $ mkPrim 
     339        { subName     = name 
     340        , subType     = SubPrim 
     341        , subAssoc    = subAssoc code 
     342        , subParams   = subParams code 
     343        , subReturns  = mkType "List" 
     344        , subBody     = Prim 
     345            (\x -> op1HyperPrefix code (listArg x)) 
     346        } 
     347 
     348buildPostfixHyper name var = do 
     349    let rv = fmap (either (const Nothing) Just) $ 
     350            findSub var Nothing firstArg 
     351    maybeM rv $ \code -> return $ mkPrim 
     352        { subName     = name 
     353        , subType     = SubPrim 
     354        , subAssoc    = subAssoc code 
     355        , subParams   = subParams code 
     356        , subReturns  = mkType "List" 
     357        , subBody     = Prim 
     358            (\x -> op1HyperPostfix code (listArg x)) 
     359        } 
     360 
     361buildInfixHyper name var = do 
     362    let rv = fmap (either (const Nothing) Just) $ 
     363            findSub var Nothing (take 2 (?args ++ [Val undef, Val undef])) 
     364    maybeM rv $ \code -> return $ mkPrim 
     365        { subName     = name 
     366        , subType     = SubPrim 
     367        , subAssoc    = subAssoc code 
     368        , subParams   = makeParams ["Any", "Any"] 
     369        , subReturns  = mkType "List" 
     370        , subBody     = Prim (\[x, y] -> op2Hyper code x y) 
     371        } 
     372 
     373possiblyBuildMetaopVCode :: (?args :: [Exp]) => Var -> Eval (Maybe VCode) 
     374possiblyBuildMetaopVCode var@MkVar{ v_categ = cat, v_name = name } 
     375    | C_prefix <- cat, '\171' <- Str.last buf = do 
     376        buildPrefixHyper buf var{ v_name = cast $ Str.init buf } 
     377    | C_prefix <- cat, __"<<" `Str.isSuffixOf` buf = do 
     378        buildPrefixHyper buf var{ v_name = cast $ dropEnd 2 buf } 
     379    | C_postfix <- cat, '\187' <- Str.head buf = do 
     380        buildPostfixHyper buf var{ v_name = cast $ Str.tail buf } 
     381    | C_postfix <- cat, __">>" `Str.isPrefixOf` buf = do 
     382        buildPostfixHyper buf var{ v_name = cast $ Str.drop 2 buf } 
     383    | C_infix <- cat, '\187' <- Str.head buf, '\171' <- Str.last buf = do 
     384        buildInfixHyper buf var{ v_name = cast $ Str.init (Str.tail buf) } 
     385    | C_infix <- cat, __">>" `Str.isPrefixOf` buf, __"<<" `Str.isSuffixOf` buf = do 
     386        buildInfixHyper buf var{ v_name = cast $ Str.take 2 (dropEnd 2 buf) } 
     387    | C_prefix <- cat, '[' <- Str.head buf, ']' <- Str.last buf = do 
     388        -- Strip the trailing "]" from op 
     389        let (op, keep) 
     390                | Str.index buf 1 == '\\'   = (Str.drop 2 (Str.init buf), True) 
     391                | otherwise                 = (Str.tail (Str.init buf), False) 
     392 
     393        -- We try to find the userdefined sub. 
     394        -- We use the first two elements of invs as invocants, as these are the 
     395        -- types of the op. 
     396            rv = fmap (either (const Nothing) Just) $ 
     397                findSub (var{ v_categ = C_infix, v_name = cast op }) Nothing 
     398                    (take 2 $ ?args ++ [Val undef, Val undef]) 
     399        maybeM rv $ \code -> return $ mkPrim 
     400            { subName     = buf 
     401            , subType     = SubPrim 
     402            , subAssoc    = "spre" 
     403            , subParams   = makeParams $ 
     404                if any isLValue (subParams code) 
     405                    then ["rw!List"] -- XXX - does not yet work for the [=] case 
     406                    else ["List"] 
     407            , subReturns  = anyType 
     408            , subBody     = Prim $ \[vs] -> do 
     409                list_of_args <- fromVal vs 
     410                op2Reduce keep list_of_args (VCode code) 
    226411            } 
    227  
    228     callMethodPerl5 :: Eval (Maybe VCode) 
    229     callMethodPerl5 = do 
    230         return . Just $ mkPrim 
    231             { subName     = cast (v_name var) 
    232             , subParams   = makeParams ["Object", "List", "Named"] 
    233             , subReturns  = mkType "Scalar::Perl5" 
    234             , subBody     = Prim $ \(inv:named:pos:_) -> do 
    235                 sv      <- fromVal inv 
    236                 posSVs  <- fromVals pos 
    237                 namSVs  <- fmap concat (fromVals named) 
    238                 let svs = posSVs ++ namSVs 
    239                 found   <- liftIO $ canPerl5 sv (cast $ v_name var) 
    240                 found'  <- liftIO $ if found 
    241                     then return found 
    242                     else canPerl5 sv (__"AUTOLOAD") 
    243                 if not found' 
    244                     then do 
    245                         -- XXX - when svs is empty, this could call back here infinitely 
    246                         --       add an extra '&' to force no-reinterpretation. 
    247                         evalExp $ 
    248                             App (Var var{ v_sigil = SCodeMulti }) Nothing 
    249                                 (map (Val . PerlSV) (sv:svs)) 
    250                     else do 
    251                         subSV   <- liftIO . bufToSV . cast $ v_name var 
    252                         runInvokePerl5 subSV sv svs 
    253             } 
    254  
    255     findWithPkg :: Pkg -> Var -> Eval (Either FindSubFailure VCode) 
    256     findWithPkg pkg var = do 
    257         subs <- findSub' var{ v_package = pkg } 
    258         maybe (findWithSuper pkg var) (return . Right) subs 
    259  
    260     findWithSuper :: Pkg -> Var -> Eval (Either FindSubFailure VCode) 
    261     findWithSuper pkg var = do 
    262         -- get superclasses 
    263         attrs <- fmap (fmap (filter (/= pkg) . nub)) $ findAttrs pkg 
    264         if isNothing attrs || null (fromJust attrs) then fmap (err NoMatchingMulti) (findSub' var) else do 
    265         (`fix` (fromJust attrs)) $ \run pkgs -> do 
    266             if null pkgs then return (Left $ NoSuchMethod (cast pkg)) else do 
    267             subs <- findWithPkg (head pkgs) var 
    268             either (const $ run (tail pkgs)) (return . Right) subs 
    269     findSub' :: Var -> Eval (Maybe VCode) 
    270     findSub' var = do 
    271         subSyms     <- findSyms var 
    272         lens        <- mapM argSlurpLen (unwrap $ maybeToList invs ++ args) 
    273         doFindSub (sum lens) subSyms 
    274     argSlurpLen :: Exp -> Eval Int 
    275     argSlurpLen (Val val) = valSlurpLen val 
    276     argSlurpLen (Var name) = do 
    277         val <- evalExp (Var name) 
    278         valSlurpLen val 
    279     argSlurpLen (Syn "," list) =  return $ length list 
    280     argSlurpLen _ = return 1 -- XXX 
    281  
    282     valSlurpLen :: Val -> Eval Int 
    283     valSlurpLen (VList list) = return $ length list 
    284     valSlurpLen (VRef (MkRef (IArray av))) = array_fetchSize av 
    285     valSlurpLen (VRef (MkRef (IHash hv))) = hash_fetchSize hv 
    286     valSlurpLen _  = return 1 -- XXX 
    287  
    288     doFindSub :: Int -> [(Var, Val)] -> Eval (Maybe VCode) 
    289     doFindSub slurpLen subSyms = do 
    290         subs' <- subs slurpLen subSyms 
    291         -- let foo (x, sub) = show x ++ show (map paramContext $ subParams sub) 
    292         -- trace (unlines $ map foo $ sort subs') return () 
    293         return $ case sort subs' of 
    294             ((_, sub):_)    -> Just sub 
    295             _               -> Nothing 
    296     subs :: Int -> [(Var, Val)] -> Eval [((Bool, Bool, Int, Int), VCode)] 
    297     subs slurpLen subSyms = fmap catMaybes . forM subSyms $ \(_, val) -> do 
    298         sub@(MkCode{ subReturns = ret, subParams = prms }) <- fromVal val 
    299         let rv = return $ arityMatch sub (length (maybeToList invs ++ args)) slurpLen 
    300         maybeM rv $ \fun -> do 
    301             -- if deltaFromCxt ret == 0 then return Nothing else do 
    302             let pairs = map (typeOfCxt . paramContext) prms 
    303                             `zip` (map unwrap $ maybeToList invs ++ args) 
    304             deltaCxt    <- deltaFromCxt ret 
    305             deltaArgs   <- mapM deltaFromPair pairs 
    306             let bound = either (const False) (const True) $ bindParams sub invs args 
    307             return ((isMulti sub, bound, sum deltaArgs, deltaCxt), fun) 
    308  
    309     firstArg = [maybe (Val undef) id (listToMaybe args)] 
    310  
    311     buildPrefixHyper name var = do 
    312         let rv = fmap (either (const Nothing) Just) $ 
    313                 findSub var Nothing firstArg 
    314         maybeM rv $ \code -> return $ mkPrim 
    315             { subName     = name 
    316             , subType     = SubPrim 
    317             , subAssoc    = subAssoc code 
    318             , subParams   = subParams code 
    319             , subReturns  = mkType "List" 
    320             , subBody     = Prim 
    321                 (\x -> op1HyperPrefix code (listArg x)) 
    322             } 
    323  
    324     buildPostfixHyper name var = do 
    325         let rv = fmap (either (const Nothing) Just) $ 
    326                 findSub var Nothing firstArg 
    327         maybeM rv $ \code -> return $ mkPrim 
    328             { subName     = name 
    329             , subType     = SubPrim 
    330             , subAssoc    = subAssoc code 
    331             , subParams   = subParams code 
    332             , subReturns  = mkType "List" 
    333             , subBody     = Prim 
    334                 (\x -> op1HyperPostfix code (listArg x)) 
    335             } 
    336  
    337     buildInfixHyper name var = do 
    338         let rv = fmap (either (const Nothing) Just) $ 
    339                 findSub var Nothing (take 2 (args ++ [Val undef, Val undef])) 
    340         maybeM rv $ \code -> return $ mkPrim 
    341             { subName     = name 
    342             , subType     = SubPrim 
    343             , subAssoc    = subAssoc code 
    344             , subParams   = makeParams ["Any", "Any"] 
    345             , subReturns  = mkType "List" 
    346             , subBody     = Prim (\[x, y] -> op2Hyper code x y) 
    347             } 
    348  
    349     possiblyBuildMetaopVCode :: Var -> Eval (Maybe VCode) 
    350     possiblyBuildMetaopVCode var@MkVar{ v_categ = cat, v_name = name } 
    351         | C_prefix <- cat, '\171' <- Str.last buf = do 
    352             buildPrefixHyper buf var{ v_name = cast $ Str.init buf } 
    353         | C_prefix <- cat, __"<<" `Str.isSuffixOf` buf = do 
    354             buildPrefixHyper buf var{ v_name = cast $ dropEnd 2 buf } 
    355         | C_postfix <- cat, '\187' <- Str.head buf = do 
    356             buildPostfixHyper buf var{ v_name = cast $ Str.tail buf } 
    357         | C_postfix <- cat, __">>" `Str.isPrefixOf` buf = do 
    358             buildPostfixHyper buf var{ v_name = cast $ Str.drop 2 buf } 
    359         | C_infix <- cat, '\187' <- Str.head buf, '\171' <- Str.last buf = do 
    360             buildInfixHyper buf var{ v_name = cast $ Str.init (Str.tail buf) } 
    361         | C_infix <- cat, __">>" `Str.isPrefixOf` buf, __"<<" `Str.isSuffixOf` buf = do 
    362             buildInfixHyper buf var{ v_name = cast $ Str.take 2 (dropEnd 2 buf) } 
    363         | C_prefix <- cat, '[' <- Str.head buf, ']' <- Str.last buf = do 
    364             -- Strip the trailing "]" from op 
    365             let (op, keep) 
    366                     | Str.index buf 1 == '\\'   = (Str.drop 2 (Str.init buf), True) 
    367                     | otherwise                 = (Str.tail (Str.init buf), False) 
    368  
    369             -- We try to find the userdefined sub. 
    370             -- We use the first two elements of invs as invocants, as these are the 
    371             -- types of the op. 
    372                 rv = fmap (either (const Nothing) Just) $ 
    373                     findSub (var{ v_categ = C_infix, v_name = cast op }) Nothing 
    374                         (take 2 $ args ++ [Val undef, Val undef]) 
    375             maybeM rv $ \code -> return $ mkPrim 
    376                 { subName     = buf 
    377                 , subType     = SubPrim 
    378                 , subAssoc    = "spre" 
    379                 , subParams   = makeParams $ 
    380                     if any isLValue (subParams code) 
    381                         then ["rw!List"] -- XXX - does not yet work for the [=] case 
    382                         else ["List"] 
    383                 , subReturns  = anyType 
    384                 , subBody     = Prim $ \[vs] -> do 
    385                     list_of_args <- fromVal vs 
    386                     op2Reduce keep list_of_args (VCode code) 
    387                 } 
    388             -- Now we construct the sub. Is there a more simple way to do it? 
    389         | otherwise = return Nothing 
    390         where 
    391         buf = cast name 
     412        -- Now we construct the sub. Is there a more simple way to do it? 
     413    | otherwise = return Nothing 
     414    where 
     415    buf = cast name 
    392416 
    393417metaVar :: Pkg -> Var 
     
    567591findSyms :: Var -> Eval [(Var, Val)] 
    568592findSyms var = do 
    569     runMaybeT (findLexical `mplus` findPackage `mplus` findGlobal) 
    570         >>= maybe (return []) return 
     593    runMaybeT findAll >>= maybe (return []) return 
    571594    where 
     595    findAll 
     596        | isGlobalVar var       = findGlobal 
     597        | isQualifiedVar var    = findQualified 
     598        | otherwise             = findLexical `mplus` findPackage 
     599 
     600    -- $x should look up $x in the current pad first. 
    572601    findLexical :: MaybeT Eval [(Var, Val)] 
    573602    findLexical = do 
    574603        lex <- lift $ asks envLexical 
    575         padSym lex var{ v_package = emptyPkg } 
     604        padSym lex var 
    576605         
     606    -- $x then fallbacks to $This::Package::x, or maybe $*x. 
    577607    findPackage :: MaybeT Eval [(Var, Val)] 
    578608    findPackage = do 
    579609        glob <- lift $ askGlobal 
    580610        pkg  <- lift $ asks envPackage 
    581         padSym glob var `mplus` padSym glob (toPackage pkg var) 
    582  
     611        padSym glob var 
     612            `mplus` padSym glob (toPackage pkg var) 
     613            `mplus` padSym glob (toGlobalVar var) 
     614 
     615    -- $Foo::x is just $Foo::x, or maybe $*Foo::x. 
     616    findQualified :: MaybeT Eval [(Var, Val)] 
     617    findQualified = do 
     618        glob <- lift $ askGlobal 
     619        padSym glob var 
     620            `mplus` padSym glob (toGlobalVar var) 
     621 
     622    -- $*Foo::x is just that. 
    583623    findGlobal :: MaybeT Eval [(Var, Val)] 
    584624    findGlobal = do