| 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 |
| | 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]) |
| | 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) |
| 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 |