]> hydra-www.ietfng.org Git - dyna2/commitdiff
More parser work
authorNathaniel Wesley Filardo <nwf@cs.jhu.edu>
Wed, 5 Jun 2013 18:55:16 +0000 (14:55 -0400)
committerNathaniel Wesley Filardo <nwf@cs.jhu.edu>
Wed, 5 Jun 2013 18:59:35 +0000 (14:59 -0400)
Allow backends to restrict the set of acceptable aggregators.
Feed through rendered parser state.

src/Dyna/Backend/BackendDefn.hs
src/Dyna/Backend/NoBackend.hs
src/Dyna/Backend/Python/Backend.hs
src/Dyna/Main/Driver.hs
src/Dyna/ParserHS/OneshotDriver.hs
src/Dyna/ParserHS/Parser.hs
src/Dyna/ParserHS/Selftest.hs

index bec013ec0a117531adf925e1eda090dcd3e87a22..ff3c11d40571383f80851cd6299031bb945d58fe 100644 (file)
@@ -7,7 +7,7 @@
 
 module Dyna.Backend.BackendDefn where
 
-import qualified Data.Set as S
+import qualified Data.Set                         as S
 import           Dyna.Analysis.Aggregation (AggMap)
 import           Dyna.Analysis.ANF (Rule)
 import           Dyna.Analysis.DOpAMine (BackendRenderDopIter)
@@ -32,8 +32,18 @@ type BackendDriver bs = AggMap                    -- ^ Aggregation
                       -> IO ()
 
 data Backend = forall bs . Backend
-             { -- | Hook for planner to get builtin information
-               be_builtin :: BackendPossible bs
+             { -- | Aggregators exported by this backend, if specified.
+               --
+               -- If not given, the parser will use a generic set of
+               -- aggregators.
+               --
+               -- XXX This is not really right, as the set of aggregators is
+               -- a property of Dyna, not of the backend, but for the
+               -- moment...
+               be_aggregators :: Maybe (S.Set String)
+
+               -- | Hook for planner to get builtin information
+             , be_builtin :: BackendPossible bs
 
                -- | Any constants made available by this backend.
                -- 
index cf28817beff610f48e59b8ecd49c548711156359..7f3149f0163a50e4202b75ecbaac6135c9c5ce94 100644 (file)
@@ -35,7 +35,8 @@ import qualified Debug.Trace                as XT
 
 noBackend :: Backend
 noBackend = Backend
-          { be_builtin        = primPossible
+          { be_aggregators    = Nothing
+          , be_builtin        = primPossible
           , be_constants      = MA.isJust . primOps -- XXX
           , be_debug_dop_iter = \_ _ _ _ _ -> empty
           , be_driver         = driver
index 493bb8b07f42326570ef14a52ae94a3c29c59f83..26a4eb0257420c9276b4643ba13a88b5416d43e3 100644 (file)
@@ -25,7 +25,7 @@ import           Control.Monad.State
 import qualified Data.Map                   as M
 import qualified Data.Maybe                 as MA
 -- import qualified Data.Ord                   as O
--- import qualified Data.Set                   as S
+import qualified Data.Set                   as S
 -- import qualified Debug.Trace                as XT
 import           Dyna.Analysis.ANF
 -- import           Dyna.Analysis.Aggregation
@@ -43,6 +43,20 @@ import           System.IO
 import           Text.PrettyPrint.Free
 -- import qualified Text.Trifecta              as T
 
+------------------------------------------------------------------------}}}
+-- Supported aggregations                                               {{{
+
+aggrs = S.fromList
+  [ "max=" , "min="
+  , "+=" , "*="
+  , "and=" , "or=" , "&=" , "|="
+  , ":-"
+  , "majority=" , "set=" , "bag="
+  , ":="
+  , "dict="
+  ]
+
+
 ------------------------------------------------------------------------}}}
 -- DOpAMine Backend Information                                         {{{
 
@@ -274,7 +288,13 @@ printUpdate fh rule@(Rule _ h _ r _ _ _ _) cost evalix (Just (f,a)) (hv,v) dope
 -- Driver                                                               {{{
 
 driver :: BackendDriver PyDopeBS
-driver am um {-qm-} is pp fh = do
+driver am um {-qm-} is pr fh = do
+  -- Parser resume state
+  hPutStrLn fh "parser_state = \"\"\""
+  hPutStrLn fh $ show pr
+  hPutStrLn fh "\"\"\""
+  hPutStrLn fh ""
+
   -- Aggregation mapping
   forM_ (M.toList am) $ \((f,a),v) -> do
      hPutStrLn fh $ show $    "agg_decl"
@@ -313,7 +333,8 @@ driver am um {-qm-} is pp fh = do
 -- Export                                                               {{{
 
 pythonBackend :: Backend
-pythonBackend = Backend builtins
+pythonBackend = Backend (Just aggrs)
+                        builtins
                         (MA.isJust . constants)
                         (\o is _ _ (PDBS e) -> e o is)
                         driver
index 2bc3ad3ee0180210d8f2dd4b797d2fb97c6beb1b..c5ea94d2280fd09632fc2f785b32d77f6ba59da7 100644 (file)
@@ -298,7 +298,7 @@ processFile fileName = bracket openOut hClose go
   maybeWarnANF xs = Just $ vcat $ map (uncurry renderSpannedWarn) xs
 
   go out = do
-    P.PDP rs pp <- parse
+    P.PDP rs pp <- parse (be_aggregators $ dcfg_backend ?dcfg)
 
     dump DumpParsed $
          (vcat $ map (\(i,_,r) -> text $ show (i,r)) rs)
@@ -317,7 +317,7 @@ processFile fileName = bracket openOut hClose go
                                  empty aggm)
 
     case dcfg_backend ?dcfg of
-      Backend be_b be_c be_ddi be_d ->
+      Backend be_b be_c be_ddi be_d ->
         let initializers = MA.mapMaybe
                              (\(f,mca) -> (\(c,a) -> (f,c,a)) `fmap` mca)
                            $ map (\x -> (x, planInitializer be_b x)) frs
@@ -345,8 +345,8 @@ processFile fileName = bracket openOut hClose go
             -- Invoke the backend code generator
             be_d aggm uPlans' {- qPlans -} initializers' pp out
 
-  parse = do
-    pr <- T.parseFromFileEx (P.oneshotDynaParser <* T.eof) fileName
+  parse aggs = do
+    pr <- T.parseFromFileEx (P.oneshotDynaParser aggs <* T.eof) fileName
     case pr of
       TR.Failure td -> dynacUserANSIErr $ PPA.align ("Parser error" PPA.<$> td)
       TR.Success rs -> return rs
index e3dd4fe36bb83df567876bdf83dfbd1b5f3aa7ef..d8f7b31b742e59904091cf0a5f465f040ac34da4 100644 (file)
@@ -21,7 +21,9 @@ import           Control.Applicative
 import           Control.Lens
 import           Control.Monad.State
 import qualified Data.ByteString                  as B
+import qualified Data.ByteString.UTF8             as BU
 import qualified Data.Map                         as M
+import qualified Data.Set                         as S
 import           Data.Monoid (mempty)
 import           Dyna.Main.Defns
 import           Dyna.Main.Exception
@@ -74,7 +76,10 @@ data PCS = PCS
   }
 $(makeLenses ''PCS)
 
-_pcs_dlc pcs = DLC (_pcs_ot_cache pcs)
+mkdlc aggs pcs = DLC (_pcs_ot_cache pcs)
+                     (maybe genericAggregators ct aggs)
+ where
+  ct = fmap BU.fromString . choice . map (try . string) . S.toList
 
 update_pcs_dt = pcs_dt_cache <<~
                 liftA2 ($) (uses pcs_dt_mk dtmk) (use pcs_dt_over)
@@ -162,23 +167,27 @@ pragmasFromPCS (PCS dt_mk dt_over _
     ++ [PRuleIx rix]
 
 nextRule :: (DeltaParsing m, LookAheadParsing m, MonadState PCS m)
-         => m (Spanned Rule)
-nextRule = do
-  (l :~ s) <- gets _pcs_dlc >>= parse
-  case l of
-    LPragma  p -> pcsProcPragma (p :~ s) >> nextRule
-    LRule r -> return r
+         => Maybe (S.Set String)
+         -> m (Spanned Rule)
+nextRule aggs = go
+ where
+  go = do
+    (l :~ s) <- gets (mkdlc aggs) >>= parse
+    case l of
+      LPragma  p -> pcsProcPragma (p :~ s) >> go
+      LRule r -> return r
 
 oneshotDynaParser :: (DeltaParsing m, LookAheadParsing m)
-                  => m ParsedDynaProgram
-oneshotDynaParser = (postProcess =<<)
-                  $ flip runStateT defPCS
-                  $ many (try $ do
-                            r <- nextRule
-                            rix <- pcs_ruleix <<%= (+1)
-                            dt  <- use pcs_dt_cache
-                            return $ (rix, dt, r))
-                    <* optional (dynaWhiteSpace (someSpace))
+                  => Maybe (S.Set String)
+                  -> m ParsedDynaProgram
+oneshotDynaParser aggs = (postProcess =<<)
+   $ flip runStateT defPCS
+   $ many (try $ do
+             r <- nextRule aggs
+             rix <- pcs_ruleix <<%= (+1)
+             dt  <- use pcs_dt_cache
+             return $ (rix, dt, r))
+     <* optional (dynaWhiteSpace (someSpace))
  where
   postProcess (rs,pcs) = return $ PDP rs (pragmasFromPCS pcs)
 
index 1a12beb3d2ea522035b521dffabb5b10be247072..5a8c46d527b81d26da74e6b49a9a6a92510c12ab 100644 (file)
@@ -43,7 +43,7 @@ module Dyna.ParserHS.Parser (
     -- * Parser output types
     NameWithArgs(..),
     -- ** Surface langauge
-    Term(..), Rule(..), dynaWhiteSpace,
+    Term(..), Rule(..), dynaWhiteSpace, genericAggregators,
     -- ** Pragmas
     ParsedInst(..), ParsedModeInst, Pragma(..), renderPragma,
     -- ** Line
@@ -51,7 +51,7 @@ module Dyna.ParserHS.Parser (
     -- * Action
     parse,
     -- * Test harness hooks
-    testTerm, testAggr, testRule, testPragma,
+    testTerm, testGenericAggr, testRule, testPragma,
 ) where
 
 import           Control.Applicative
@@ -217,7 +217,12 @@ parseNameWithArgs n = PNWA <$> n
 ------------------------------------------------------------------------}}}
 -- Parser Monad                                                         {{{
 
-data DLCfg = DLC { dlc_opertab :: EOT }
+data DLCfg = DLC { dlc_opertab :: EOT
+                 , dlc_aggrs   :: forall m .
+                                  (CharParsing m, DeltaParsing m,
+                                   LookAheadParsing m)
+                               => m B.ByteString
+                 }
 
 newtype DynaLanguage m a = DL { unDL :: ReaderT DLCfg m a }
   deriving (Functor,Applicative,Alternative,Monad,MonadPlus,
@@ -485,8 +490,8 @@ tfexpr = buildExpressionParser moreETable tlexpr <?> "Expression"
 -- Rules                                                                {{{
 
 -- XXX There must be a better way.
-parseAggr :: (DeltaParsing m, LookAheadParsing m) => m B.ByteString
-parseAggr = token
+genericAggregators :: (DeltaParsing m, LookAheadParsing m) => m B.ByteString
+genericAggregators = token
  (do
    an <- optional (identNL dynaAggNameStyle)
    as <- manyTill (oneOfSet usualpunct)
@@ -505,7 +510,8 @@ rule = do
             _    <- try (char '.' <* lookAhead whiteSpace)
             return (Rule h "|=" (TFunctor "true" [] :~ hs))
          , do
-            aggr <- parseAggr
+            aggr <- join $ asks dlc_aggrs
+            _    <- whiteSpace
             body <- tfexpr
             _    <- char '.'
             return (Rule h aggr body)
@@ -751,9 +757,9 @@ testTerm   :: (DeltaParsing m, LookAheadParsing m)
            => DLCfg -> m (Spanned Term)
 testTerm   = configureParser term
 
-testAggr   :: (DeltaParsing m, LookAheadParsing m)
-           => m B.ByteString
-testAggr   = parseAggr
+testGenericAggr :: (DeltaParsing m, LookAheadParsing m)
+                => m B.ByteString
+testGenericAggr = genericAggregators
 
 testRule   :: (DeltaParsing m, LookAheadParsing m)
            => DLCfg -> m Rule
index d9e2c1bc4ea99d7ace997c414d2fe72f879e49b1..96f01576e5785da1029cb6e7df0114c959f5ba4f 100644 (file)
@@ -48,7 +48,7 @@ _tNumeric :: Either Integer Double -> Term
 _tNumeric = TBase . TNumeric
 
 defDLC :: DLCfg
-defDLC = DLC (mkEOT defOperSpec True)
+defDLC = DLC (mkEOT defOperSpec True) genericAggregators
 
 term :: ByteString -> Spanned Term
 term = unsafeParse (testTerm defDLC <* eof)
@@ -185,13 +185,27 @@ case_tyAnnot = e @=? (term fintx)
 
 test_aggregators :: [TF.Test]
 test_aggregators = hUnitTestToTests $ TestList
-  [ TestLabel "valid" $ TestList $
-      map (\x -> (BU.toString x) ~: x ~=? unsafeParse testAggr x)
+  [ TestLabel "generic valid" $ TestList $
+      map (\x -> (BU.toString x) ~: x ~=? unsafeParse testGenericAggr x)
         ["+=", "*=", ".=", "min=", "max=", "?=", ":-", "max+=" ]
-  , TestLabel "invalid" $ TestList $
-      map (\x -> TestLabel (BU.toString x) $ TestCase $ checkParseFail_ testAggr x)
+  , TestLabel "generic invalid" $ TestList $
+      map (\x -> TestLabel (BU.toString x) $ TestCase
+                                           $ checkParseFail_ testGenericAggr x)
         [".", ". ", "+=3", "+3=", "+=a", "+a=" ]
+  , TestLabel "custom accept" $
+      let r = unsafeParse (testRule cdlc) r1
+      in r ~=? Rule (TFunctor "a" [] :~ Span (Columns 0 0) (Columns 2 2) r1)
+                    "+="
+                    (TFunctor "b" [] :~ Span (Columns 5 5) (Columns 6 6) r1)
+  , TestLabel "custom reject" $ TestCase
+                              $ checkParseFail_ (testRule cdlc) "a *= b."
   ]
+ where
+  r1 = "a += b."
+
+  cdlc = DLC { dlc_opertab = dlc_opertab defDLC
+             , dlc_aggrs   = fmap BU.fromString (string "+=")
+             }
 
 ------------------------------------------------------------------------}}}
 -- Rules                                                                {{{
@@ -203,7 +217,7 @@ progrules :: ByteString -> [Spanned Rule]
 progrules = unsafeParse (many (spanned (testRule defDLC)) <* eof)
 
 oneshotRules :: ByteString -> [(RuleIx, Spanned Rule)]
-oneshotRules = xlate . unsafeParse (oneshotDynaParser)
+oneshotRules = xlate . unsafeParse (oneshotDynaParser Nothing)
  where
   xlate (PDP rs _) = map (\(i,_,sr) -> (i,sr)) rs