Changeset 12375 for src/Pugs/Eval

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

* So much for contextual variables and dynamic binding --

GHC 6.4's mutual recursion limitation forced us to put
Eval.Var.findSub into a deeply nested recursive group again.

/me pines for GHC 6.6...

Files:
1 modified

Legend:

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

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