Changeset 10648

Show
Ignore:
Timestamp:
06/12/06 14:32:44 (2 years ago)
Author:
audreyt
Message:

* Unify named and unamed subroutines.

(note - for releng, I'll rollback this thread of changes

and hold until 6.2.12 is released, to investigate more
into the serious perf hit caused by it.)

Location:
src/Pugs
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Eval.hs

    r10645 r10648  
    350350    enterLex [sym] $ evalExp exp 
    351351 
    352 reduceSym scope name exp | scope <= SMy = do 
     352reduceSym scope name exp | scope < SGlobal = do 
    353353    ref <- newObject (typeOfSigil $ head name) 
    354354    let (gen, name') = case name of 
     
    356356            _               -> (genSym, name) 
    357357    sym <- gen name' ref 
     358    when (scope == SOur) $ do 
     359        qn  <- toQualified name' 
     360        addGlobalSym =<< gen qn ref 
    358361    enterLex [ sym ] $ evalExp exp 
    359362 
  • src/Pugs/Lexer.hs

    r10504 r10648  
    386386 
    387387ruleBareTrait :: String -> RuleParser String 
    388 ruleBareTrait trait = rule "bare trait" $ do 
     388ruleBareTrait trait = tryRule "bare trait" $ do 
    389389    choice [ ruleTraitName trait 
    390390           , do symbol trait 
  • src/Pugs/Parser.hs

    r10646 r10648  
    159159    ] 
    160160 
    161 ruleSubHead :: RuleParser (Bool, SubType, String) 
    162 ruleSubHead = rule "subroutine head" $ do 
    163     isMulti <- option False $ do { symbol "multi" ; return True } 
    164     -- You're allowed to omit the "sub": 
    165     --   multi sub foo (...) {...}      # legal 
    166     --         sub foo (...) {...}      # legal, too 
    167     let implicitSub | isMulti == True = return SubRoutine 
    168                     | otherwise       = pzero 
    169     styp    <- choice 
    170         [ do symbol "sub" 
    171              return SubRoutine 
    172         , do symbol "coro" 
    173              return SubCoroutine 
    174         , do (symbol "submethod" <|> symbol "method") 
    175              return SubMethod 
    176         , do symbol "macro" 
    177              return SubMacro 
    178         ] <|> implicitSub 
    179     name    <- ruleSubName 
    180     return (isMulti, styp, name) 
    181  
    182 -- | Scope, context, isMulti, styp, name 
    183 type SubDescription = (Scope, String, Bool, SubType, String) 
    184  
    185 ruleSubScopedWithContext :: RuleParser SubDescription 
    186 ruleSubScopedWithContext = tryRule "scoped subroutine with context" $ do 
    187     scope   <- ruleScope 
    188     cxt     <- identifier 
    189     (isMulti, styp, name) <- ruleSubHead 
    190     return (scope, cxt, isMulti, styp, name) 
    191  
    192 ruleSubScoped :: RuleParser SubDescription 
    193 ruleSubScoped = tryRule "scoped subroutine" $ do 
    194     scope <- ruleScope 
    195     (isMulti, styp, name) <- ruleSubHead 
    196     return (scope, "Any", isMulti, styp, name) 
    197  
    198 ruleSubGlobal :: RuleParser SubDescription 
    199 ruleSubGlobal = tryRule "global subroutine" $ do 
    200     (isMulti, styp, name) <- ruleSubHead 
    201     return (SGlobal, "Any", isMulti, styp, name) 
    202  
    203161ruleRuleDeclaration :: RuleParser Exp 
    204162ruleRuleDeclaration = rule "rule declaration" $ do 
     
    251209        Nothing   -> return name 
    252210        _         -> fail "I only know about package- and global-scoped classes. Sorry." 
    253     traits  <- many $ ruleTrait 
     211    traits  <- many ruleTrait 
    254212    let pkgClass = case sym of 
    255213                       "package" -> "Package" 
     
    274232                kind   = Val . VStr $ sym 
    275233            return $ Right (newName, kind, pkgVal, env) 
    276  
    277 ruleSubDeclaration :: RuleParser Exp 
    278 ruleSubDeclaration = rule "subroutine declaration" $ do 
    279     namePos <- getPosition 
    280     (scope, typ, isMulti, styp, name) <- choice 
    281         [ ruleSubScopedWithContext 
    282         , ruleSubScoped 
    283         , ruleSubGlobal 
    284         ] 
    285     optional $ do { symbol "handles"; ruleExpression } 
    286     typ'    <- option typ $ try $ ruleBareTrait "returns" 
    287     formal  <- option Nothing $ ruleSubParameters ParensMandatory 
    288     typ''   <- option typ' $ try $ ruleBareTrait "returns" 
    289     traits  <- many $ ruleTrait 
    290  
    291     -- XXX - We have the prototype now; install it immediately? 
    292  
    293     -- bodyPos <- getPosition 
    294     body    <- ruleBlockWithParams (maybe [] id formal) 
    295     let (fun, names, params) = doExtract styp formal body 
    296     -- Check for placeholder vs formal parameters 
    297     when (isJust formal && (not.null) names) $ 
    298         fail "Cannot mix placeholder variables with formal parameters" 
    299     env <- ask 
    300     let sub = VCode $ MkCode 
    301             { isMulti       = isMulti 
    302             , subName       = nameQualified 
    303             , subEnv        = Just env 
    304             , subType       = if "primitive" `elem` traits 
    305                 then SubPrim else styp 
    306             , subAssoc      = "pre" 
    307             , subReturns    = mkType typ'' 
    308             , subLValue     = "rw" `elem` traits 
    309             , subParams     = self ++ paramsFor styp formal params 
    310             , subBindings   = [] 
    311             , subSlurpLimit = [] 
    312             , subBody       = fun 
    313             , subCont       = Nothing 
    314             } 
    315         pkg = envPackage env 
    316         nameQualified | ':' `elem` name     = name 
    317                       | scope <= SMy        = name 
    318                       | isGlobal            = name 
    319                       | isBuiltin           = (head name:'*':tail name) 
    320                       | otherwise           = (head name:pkg) ++ "::" ++ tail name 
    321         self :: [Param] 
    322         self | styp > SubMethod = [] 
    323              | (prm:_) <- params, isInvocant prm = [] 
    324              | otherwise = [selfParam $ envPackage env] 
    325         mkExp n = Syn ":=" [Var n, Syn "sub" [Val sub]] 
    326         mkSym n = Sym scope (mkMulti n) (mkExp n) 
    327         mkSymGlobal globalName lexicalName = Stmts 
    328             (Sym SMy (mkMulti lexicalName) (mkExp lexicalName)) 
    329             (Sym SGlobal (mkMulti globalName) (Syn ":=" [Var globalName, Var lexicalName])) 
    330         -- Horrible hack! Sym "&&" is the multi form. 
    331         mkMulti | isMulti   = ('&':) 
    332                 | otherwise = id 
    333         isGlobal = '*' `elem` name 
    334         isBuiltin = ("builtin" `elem` traits) 
    335         isExported = ("export" `elem` traits) 
    336         isScopeGlobal = case scope of 
    337             SGlobal -> True 
    338             SOur    -> True 
    339             _       -> False 
    340         expMakeSym 
    341             | isScopeGlobal = mkSymGlobal nameQualified name 
    342             | otherwise     = mkSym nameQualified 
    343         expImmediate 
    344             | isExported    = Stmts expMakeSym $  
    345                 (App (Var "&push") 
    346                     (Just (Syn "{}" [Var ("%" ++ pkg ++ "::EXPORTS"), Val $ VStr name])) 
    347                     [Var name]) 
    348             | otherwise     = expMakeSym 
    349          
    350     -- XXX this belongs in semantic analysis, not in the parser 
    351     -- also, maybe we should only warn when you try to export an 
    352     -- operator that is "standard" 
    353     -- XXX I can't figure out how to do this without trace 
    354     when (isExported && isOperatorName name) $ 
    355         trace  
    356             ("You probably don't want to export an operator name; instead\n\ 
    357   define a new variant on the new operator (eg. multi sub *infix:<+>): " 
    358                 ++ show name ++ " at " ++ show namePos) 
    359             (return ()) 
    360              
    361     -- Don't add the sub if it's unsafe and we're in safemode. 
    362     if "unsafe" `elem` traits && safeMode then return emptyExp else do 
    363     lexDiff <- unsafeEvalLexDiff expImmediate 
    364     addBlockPad SMy lexDiff 
    365     clearDynParsers 
    366     return (Var name) 
    367234 
    368235ruleSubNamePossiblyWithTwigil :: RuleParser String 
     
    482349                    -> return (x:'!':xs) 
    483350        _           -> fail $ "Invalid member variable name '" ++ attr ++ "'" 
    484     traits  <- many $ ruleTrait 
     351    traits  <- many ruleTrait 
    485352    optional $ do { symbol "handles"; ruleExpression } 
    486353    env     <- ask 
     
    11671034    exp <- ruleExpression 
    11681035    return $ \body -> do 
    1169         block <- retBlock SubBlock Nothing False body 
     1036        block <- retBlock SubBlock Nothing Nothing [] body 
    11701037        return $ Syn cond [exp, block] 
    11711038 
     
    11761043ruleBlockLiteral :: RuleParser Exp 
    11771044ruleBlockLiteral = rule "block construct" $ 
    1178     ruleBlockVariants [ ruleBlockFormalPointy, ruleBlockFormalStandard ] 
    1179  
    1180 ruleBlockVariants :: [RuleParser (SubType, Maybe [Param], Bool)] -> RuleParser Exp 
     1045    ruleBlockVariants [ ruleBlockFormalPointy, ruleSubHead ] 
     1046 
     1047ruleBlockVariants :: [RuleParser SubDescription] -> RuleParser Exp 
    11811048ruleBlockVariants variants = do 
    1182     (typ, formal, lvalue) <- option (SubBlock, Nothing, False) 
     1049    (isMulti, typ, maybeName, formal, traits) <- option (False, SubBlock, Nothing, Nothing, []) 
    11831050        $ choice variants 
    11841051    body    <- ruleBlockWithParams (maybe [] id formal) 
    1185     retBlock typ formal lvalue body 
    1186  
    1187 retBlock :: SubType -> Maybe [Param] -> Bool -> Exp -> RuleParser Exp 
    1188 retBlock SubBlock Nothing _ exp | Just hashExp <- extractHash (unwrap exp) = return $ Syn "\\{}" [hashExp] 
    1189 retBlock typ formal lvalue body = retVerbatimBlock typ formal lvalue body 
    1190  
    1191 retVerbatimBlock :: SubType -> Maybe [Param] -> Bool -> Exp -> RuleParser Exp 
    1192 retVerbatimBlock styp formal lvalue body = expRule $ do 
     1052    rv      <- retBlock typ maybeName formal traits body 
     1053    case maybeName of 
     1054        Just name   -> registerSubName isMulti SOur name traits rv 
     1055        _           -> return rv 
     1056 
     1057registerSubName :: Bool -> Scope -> Var -> Traits -> Exp -> RuleParser Exp 
     1058registerSubName isMulti scope name traits exp = do 
     1059    -- Don't add the sub if it's unsafe and we're in safemode. 
     1060    if "unsafe" `elem` traits && safeMode then return emptyExp else do 
     1061    lexDiff <- unsafeEvalLexDiff $ 
     1062        Sym scope ((if isMulti then ('&':) else id) name) emptyExp 
     1063    addBlockPad scope lexDiff 
     1064    rv  <- unsafeEvalExp $! Syn ":=" [Var name, exp] 
     1065    pkg <- asks envPackage 
     1066    when (scope == SOur || scope == SGlobal) $ do 
     1067        let qualifiedName = (head name:pkg) ++ (':':':':tail name) 
     1068        unsafeEvalExp $! Syn ":=" [Var qualifiedName, rv] 
     1069        return () 
     1070    when ("export" `elem` traits) $ do 
     1071        when (isOperatorName name) $ do 
     1072            namePos <- getPosition 
     1073            trace ("You probably don't want to export an operator name; instead\n\ 
     1074    define a new variant on the new operator (eg. multi sub *infix:<+>): " 
     1075                    ++ show name ++ " at " ++ show namePos) 
     1076                (return ()) 
     1077        unsafeEvalExp $! 
     1078            App (Var "&push") 
     1079                (Just (Syn "{}" [Var ("%" ++ pkg ++ "::EXPORTS"), Val $ VStr name])) 
     1080                [rv] 
     1081        return () 
     1082    -- Now handle exports and push the sub into namedness 
     1083    return rv 
     1084 
     1085retBlock :: SubType -> Maybe Var -> Maybe [Param] -> Traits -> Exp -> RuleParser Exp 
     1086retBlock SubBlock _ Nothing _ exp | Just hashExp <- extractHash (unwrap exp) = return $ Syn "\\{}" [hashExp] 
     1087retBlock typ maybeName formal traits body = retVerbatimBlock typ maybeName formal traits body 
     1088 
     1089retVerbatimBlock :: SubType -> Maybe Var -> Maybe [Param] -> Traits -> Exp -> RuleParser Exp 
     1090retVerbatimBlock styp maybeName formal traits body = expRule $ do 
    11931091    let (fun, names, params) = doExtract styp formal body 
    11941092    -- Check for placeholder vs formal parameters 
     
    11981096    let sub = MkCode 
    11991097            { isMulti       = False 
    1200             , subName       = "<anon>" 
     1098            , subName       = maybe "<anon>" qualify maybeName 
    12011099            , subEnv        = Just env 
    1202             , subType       = styp 
     1100            , subType       = if "primitive" `elem` traits 
     1101                then SubPrim else styp 
    12031102            , subAssoc      = "pre" 
    12041103            , subReturns    = anyType 
    1205             , subLValue     = lvalue 
    1206             , subParams     = paramsFor styp formal params 
     1104            , subLValue     = "rw" `elem` traits 
     1105            , subParams     = self ++ paramsFor styp formal params 
    12071106            , subBindings   = [] 
    12081107            , subSlurpLimit = [] 
     
    12101109            , subCont       = Nothing 
    12111110            } 
     1111        pkg = envPackage env 
     1112        qualify name | ':' `elem` name     = name 
     1113                     | '*' `elem` name     = name 
     1114                     | isBuiltin           = (head name:'*':tail name) 
     1115                     | otherwise           = (head name:pkg) ++ "::" ++ tail name 
     1116        self :: [Param] 
     1117        self | styp > SubMethod = [] 
     1118             | (prm:_) <- params, isInvocant prm = [] 
     1119             | otherwise = [selfParam $ envPackage env] 
     1120        isBuiltin = "builtin" `elem` traits 
    12121121    return (Syn "sub" [Val $ VCode sub]) 
    12131122 
    1214 ruleBlockFormalStandard :: RuleParser (SubType, Maybe [Param], Bool) 
    1215 ruleBlockFormalStandard = rule "standard block parameters" $ do 
    1216     styp <- choice 
    1217         [ do { symbol "sub";   return SubRoutine } 
    1218         , do { symbol "coro";  return SubCoroutine } 
    1219         , do { symbol "macro"; return SubMacro } 
    1220         ] 
     1123type Traits = [String] 
     1124 
     1125type IsMulti = Bool 
     1126type MaybeName = Maybe Var 
     1127type SubDescription = (IsMulti, SubType, MaybeName, Maybe [Param], Traits) 
     1128 
     1129ruleSubHead :: RuleParser SubDescription 
     1130ruleSubHead = rule "subroutine head" $ do 
     1131    isMulti <- option False $ do { symbol "multi" ; return True } 
     1132    -- You're allowed to omit the "sub": 
     1133    --   multi sub foo (...) {...}      # legal 
     1134    --         sub foo (...) {...}      # legal, too 
     1135    let implicitSub | isMulti == True = return SubRoutine 
     1136                    | otherwise       = pzero 
     1137    styp    <- choice 
     1138        [ do symbol "sub" 
     1139             return SubRoutine 
     1140        , do symbol "coro" 
     1141             return SubCoroutine 
     1142        , do (symbol "submethod" <|> symbol "method") 
     1143             return SubMethod 
     1144        , do symbol "macro" 
     1145             return SubMacro 
     1146        ] <|> implicitSub 
     1147    name   <- option Nothing $ fmap Just (lexeme ruleSubName) 
    12211148    params <- option Nothing $ ruleSubParameters ParensMandatory 
    1222     traits <- many $ ruleTrait 
    1223     return $ (styp, params, "rw" `elem` traits) 
    1224  
    1225 ruleBlockFormalPointy :: RuleParser (SubType, Maybe [Param], Bool) 
     1149    optional $ ruleBareTrait "returns" 
     1150    traits <- many ruleTrait 
     1151    optional $ ruleBareTrait "returns" 
     1152    return (isMulti, styp, name, params, traits) 
     1153 
     1154ruleBlockFormalPointy :: RuleParser SubDescription 
    12261155ruleBlockFormalPointy = rule "pointy block parameters" $ do 
    12271156    symbol "->" 
    12281157    params <- ruleSubParameters ParensOptional 
    1229     traits <- many $ ruleTrait 
    1230     return $ (SubPointy, params, "rw" `elem` traits) 
     1158    optional $ ruleBareTrait "returns" 
     1159    traits <- many ruleTrait 
     1160    optional $ ruleBareTrait "returns" 
     1161    return $ (False, SubPointy, Nothing, params, traits) 
    12311162 
    12321163 
     
    12691200parseExpWithItemOps = parseExpWithCachedParser dynParseLitOp 
    12701201 
    1271 ruleVarDecl :: RuleParser Exp 
    1272 ruleVarDecl = rule "variable declaration" $ do 
     1202ruleScopedRoutine :: Scope -> SubDescription -> RuleParser Exp 
     1203ruleScopedRoutine scope (isMulti, styp, maybeName, params, traits) = do 
     1204    body    <- ruleBlockWithParams $ maybe [] id params 
     1205    rv      <- retBlock styp maybeName params traits body 
     1206    case maybeName of 
     1207        Just name   -> registerSubName isMulti scope name traits rv 
     1208        _           -> return rv 
     1209 
     1210ruleScopedDeclaration :: RuleParser Exp 
     1211ruleScopedDeclaration = rule "variable declaration" $ do 
    12731212    scope           <- ruleScope 
    1274     (cxtNames, exp) <- oneDecl <|> manyDecl 
    1275     let makeBinding (nam, cxt) 
    1276             | typ == anyType    = mkSym 
    1277             | otherwise         = mkSym . bindSym 
    1278             where 
    1279             mkSym   = Sym scope nam 
    1280             bindSym = Stmts (Syn "=" [Var nam, Val (VType typ)]) 
    1281             typ     = typeOfCxt cxt 
    1282     lexDiff <- unsafeEvalLexDiff $ combine (map makeBinding cxtNames) emptyExp 
    1283     -- Now hoist the lexDiff to the current block 
    1284     addBlockPad scope lexDiff 
    1285     return exp 
     1213    (ruleSubHead >>= ruleScopedRoutine scope) <|> do 
     1214        (cxtNames, exp) <- oneDecl <|> manyDecl 
     1215        let makeBinding (name, cxt) 
     1216                | ('$':_) <- name, typ /= anyType   = mkSym . bindSym 
     1217                | otherwise                         = mkSym 
     1218                where 
     1219                mkSym   = Sym scope name 
     1220                bindSym = Stmts (Syn "=" [Var name, Val (VType typ)]) 
     1221                typ     = typeOfCxt cxt 
     1222        lexDiff <- unsafeEvalLexDiff $ combine (map makeBinding cxtNames) emptyExp 
     1223        -- Now hoist the lexDiff to the current block 
     1224        addBlockPad scope lexDiff 
     1225        return exp 
    12861226    where 
    12871227    deSigil (sig:'!':rest@(_:_)) = (sig:rest) 
     
    13021242parseTerm = rule "term" $ do 
    13031243    term <- choice 
    1304         [ ruleSubDeclaration 
    1305         , ruleDereference 
    1306         , ruleVarDecl 
     1244        [ ruleDereference 
     1245        , ruleScopedDeclaration 
    13071246        , ruleVar 
    13081247        , ruleApply True    -- Folded metaoperators 
    13091248        , ruleLit 
    1310 --      , ruleBarewordMethod 
    13111249        , ruleClosureTrait True 
    13121250        , ruleCodeQuotation 
    13131251        , ruleTypeVar 
    1314 --      , ruleTypeLiteral 
    13151252        , ruleApply False   -- Normal application 
    13161253        , verbatimParens ruleBracketedExpression 
     
    13231260            fs <- many rulePostTerm 
    13241261            return (combine (reverse fs) term) 
    1325  
    1326 {- 
    1327 ruleBarewordMethod :: RuleParser Exp 
    1328 ruleBarewordMethod = try $ do 
    1329     name <- identifier 
    1330     lookAhead (char '.' >> ruleSubName) 
    1331     return $ Var (':':name) 
    1332 -} 
    13331262 
    13341263ruleTypeVar :: RuleParser Exp 
     
    14711400        then ruleFoldOp 
    14721401        else ruleSubNameWithoutPostfixModifier 
    1473  
    14741402    (paramListInv, args) <- choice $ 
    14751403        [ (ruleDot `tryLookAhead` char '(') >> parseHasParenParamList 
     
    14791407        ] 
    14801408    possiblyApplyMacro $ App (Var name) paramListInv args 
    1481 {- 
    1482     -- True for `foo. .($bar)`-style applications 
    1483     let takeArguments = do 
    1484             (paramListInv, args) <- choice $ 
    1485                 [ (ruleDot `tryLookAhead` char '(') >> parseHasParenParamList 
    1486                 , parseParenParamList 
    1487                 , mandatoryWhiteSpace >> parseNoParenParamList 
    1488                 ] ++ (if isFolded then [return (Nothing, [])] else []) 
    1489             possiblyApplyMacro $ App (Var name) paramListInv args 
    1490     takeArguments 
    1491         <|> possiblyTypeLiteral name 
    1492         <|> possiblyApplyMacro (App (Var name) Nothing []) 
    1493 -} 
    14941409 
    14951410ruleFoldOp :: RuleParser String 
     
    16941609ruleSigiledVar = (<|> ruleSymbolicDeref) $ do 
    16951610    name <- ruleVarNameString 
    1696     let (sigil, rest) = span (`elem` "$@%&:^") name 
     1611    let (sigil, rest) = span (`elem` "$@%&:") name 
    16971612    case rest of 
    16981613        []                              -> return (makeVar name)