packages feed

hpaco-lib 0.16.2.0 → 0.18.0.0

raw patch · 16 files changed

+577/−228 lines, 16 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Text.HPaco.Readers.Paco.Basics: anyQuotedString :: ParsecT String PacoState IO [Char]
- Text.HPaco.Readers.Paco.Basics: assertStartOfInput :: Parser ()
- Text.HPaco.Readers.Paco.Basics: assertStartOfLine :: Parser ()
- Text.HPaco.Readers.Paco.Basics: braces :: Parser a -> Parser a
- Text.HPaco.Readers.Paco.Basics: discard :: Parser a -> Parser ()
- Text.HPaco.Readers.Paco.Basics: doubleQuotedString :: ParsecT String PacoState IO [Char]
- Text.HPaco.Readers.Paco.Basics: identifier :: Parser String
- Text.HPaco.Readers.Paco.Basics: manySepBy :: Parser a -> Parser b -> Parser [a]
- Text.HPaco.Readers.Paco.Basics: singleQuotedString :: ParsecT String PacoState IO [Char]
- Text.HPaco.Readers.Paco.Basics: ss :: a -> Parser a
- Text.HPaco.Readers.Paco.Basics: ss_ :: Parser ()
+ Text.HPaco.AST.AST: mapStatement :: (Statement -> Maybe Statement) -> Statement -> Statement
+ Text.HPaco.AST.AST: type Def = (Identifier, Statement)
+ Text.HPaco.AST.AST: walkStatement :: (Statement -> Maybe a) -> Statement -> [a]
+ Text.HPaco.Optimizer: evaluateConstExpression :: Expression -> Expression
+ Text.HPaco.Optimizer: expandDefs :: AST -> AST
+ Text.HPaco.Optimizer: fromVariant :: Variant -> Expression
+ Text.HPaco.Optimizer: fusePrints :: [Statement] -> [Statement]
+ Text.HPaco.Optimizer: isConst :: Expression -> Bool
+ Text.HPaco.Optimizer: optimizeASTDefs :: AST -> AST
+ Text.HPaco.Optimizer: optimizeASTStatements :: AST -> AST
+ Text.HPaco.Optimizer: optimizeExpression :: Expression -> Expression
+ Text.HPaco.Optimizer: optimizeStatement :: Statement -> Statement
+ Text.HPaco.Readers.Capo.Statements: statement :: ParsecT String PacoState IO Statement
+ Text.HPaco.Readers.Capo.Statements: statements :: Parser [Statement]
+ Text.HPaco.Readers.Common: anyQuotedString :: ParsecT String u IO [Char]
+ Text.HPaco.Readers.Common: assertStartOfInput :: Parser s ()
+ Text.HPaco.Readers.Common: assertStartOfLine :: Parser s ()
+ Text.HPaco.Readers.Common: braces :: Parser s a -> Parser s a
+ Text.HPaco.Readers.Common: discard :: Parser s a -> Parser s ()
+ Text.HPaco.Readers.Common: doubleQuotedString :: ParsecT String u IO [Char]
+ Text.HPaco.Readers.Common: identifier :: Parser s String
+ Text.HPaco.Readers.Common: manySepBy :: Parser s a -> Parser s b -> Parser s [a]
+ Text.HPaco.Readers.Common: path :: Parser s String
+ Text.HPaco.Readers.Common: singleQuotedString :: ParsecT String u IO [Char]
+ Text.HPaco.Readers.Common: ss :: a -> Parser s a
+ Text.HPaco.Readers.Common: ss_ :: Parser s ()
+ Text.HPaco.Readers.Common: type Parser s a = ParsecT String s IO a
+ Text.HPaco.Readers.Paco: readCapo :: Reader
+ Text.HPaco.Readers.Paco.Include: performInclude :: String -> Maybe (Identifier, Expression) -> Parser Statement
+ Text.HPaco.Writer: woSourcePositionComments :: WriterOptions -> Bool
- Text.HPaco.AST.AST: AST :: Statement -> [(Identifier, Statement)] -> [String] -> AST
+ Text.HPaco.AST.AST: AST :: Statement -> [Def] -> [String] -> AST
- Text.HPaco.AST.AST: astDefs :: AST -> [(Identifier, Statement)]
+ Text.HPaco.AST.AST: astDefs :: AST -> [Def]
- Text.HPaco.Readers.Paco.Expressions: expression :: Parser Expression
+ Text.HPaco.Readers.Paco.Expressions: expression :: Parser s Expression
- Text.HPaco.Writer: WriterOptions :: Bool -> String -> String -> Bool -> WrapMode -> Bool -> String -> WriterOptions
+ Text.HPaco.Writer: WriterOptions :: Bool -> String -> String -> Bool -> WrapMode -> Bool -> String -> Bool -> WriterOptions

Files

Text/HPaco/AST/AST.hs view
@@ -2,10 +2,13 @@  import Text.HPaco.AST.Statement import Text.HPaco.AST.Identifier (Identifier)+import Data.Maybe (fromMaybe) +type Def = (Identifier, Statement)+ data AST =     AST { astRootStatement :: Statement-        , astDefs :: [(Identifier,Statement)]+        , astDefs :: [Def]         , astDeps :: [String]         }         deriving (Show)@@ -16,3 +19,31 @@         , astDefs = []         , astDeps = []         }++walkStatement :: (Statement -> Maybe a) -> Statement -> [a]+walkStatement f stmt =+    case f stmt of+        Just x -> [x]+        Nothing -> recurse+    where recurse =+            case stmt of+                StatementSequence stmts -> concatMap (walkStatement f) stmts+                IfStatement _ tb fb -> walkStatement f tb ++ walkStatement f fb+                LetStatement _ _ s -> walkStatement f s+                ForStatement _ _ _ s -> walkStatement f s+                SwitchStatement _ branches -> concat [ walkStatement f s | (e, s) <- branches ]+                otherwise -> []++mapStatement :: (Statement -> Maybe Statement) -> Statement -> Statement+mapStatement f stmt =+    fromMaybe recurse (f stmt)+    where+        g = mapStatement f+        recurse =+            case stmt of+                StatementSequence stmts -> StatementSequence $ map g stmts+                IfStatement e tb fb -> IfStatement e (g tb) (g fb)+                LetStatement a b s -> LetStatement a b (g s)+                ForStatement a b c s -> ForStatement a b c (g s)+                SwitchStatement e branches -> SwitchStatement e [ (c, g s) | (c, s) <- branches ]+                otherwise -> stmt
Text/HPaco/Optimizer.hs view
@@ -1,22 +1,63 @@+{-#LANGUAGE TupleSections #-} module Text.HPaco.Optimizer-            ( optimize-            )+--            ( optimize+--            ) where  import Text.HPaco.AST.AST import Text.HPaco.AST.Expression import Text.HPaco.AST.Statement import qualified Text.HPaco.Writers.Run as Run-import Data.Variant+import Data.Variant hiding (lookup, elem) import Control.Monad.State+import Control.Applicative import System.IO.Unsafe (unsafePerformIO)+import Text.HPaco.AST.Identifier (Identifier)+import Data.Maybe+import Control.Arrow ( (***) )+import qualified Control.Arrow as Arrow  optimize :: AST -> AST-optimize ast = ast -                { astRootStatement = optimizeStatement . astRootStatement $ ast -                , astDefs = map (\(i, s) -> (i, optimizeStatement s)) . astDefs $ ast-                }+optimize = expandDefs . optimizeASTStatements . optimizeASTDefs +-- Statically expand macros+--++expandDefs :: AST -> AST+expandDefs ast =+    ast { astRootStatement = goStatement [] $ astRootStatement ast+        , astDefs = [ (i, goStatement [i] s) | (i, s) <- astDefs ast ]+        }+    where+        goStatement :: [Identifier] -> Statement -> Statement+        goStatement identPath stmt = fromMaybe stmt $ goRaw identPath stmt++        goRaw :: [Identifier] -> Statement -> Maybe Statement+        goRaw identPath (CallStatement ident) | ident `elem` identPath =+            Just $ CallStatement ident+        goRaw identPath (CallStatement ident) =+            lookup ident (astDefs ast) >>= goRaw (ident:identPath)+        goRaw identPath stmt =+            case stmt of+                PrintStatement _ -> Just stmt+                NullStatement -> Just stmt+                SourcePositionStatement _ _ -> Just stmt+                otherwise -> Nothing++optimizeASTDefs :: AST -> AST+optimizeASTDefs (AST { astRootStatement = rs, astDeps = deps, astDefs = defs }) =+    AST {+        astRootStatement = rs,+        astDeps = deps,+        astDefs = [ (i, optimizeStatement s) | (i, s) <- defs ]+    }++optimizeASTStatements :: AST -> AST+optimizeASTStatements ast =+    ast { astRootStatement = optimizeStatement . astRootStatement $ ast +        , astDefs = map (Arrow.second optimizeStatement) . astDefs $ ast+        }+ optimizeStatement :: Statement -> Statement  -- Reduce constants@@ -36,7 +77,7 @@     let xs' = fusePrints $ filter (/= NullStatement) (map optimizeStatement xs)     in case xs' of         -- flatten nested statement sequences-        (StatementSequence ss):rem -> optimizeStatement . StatementSequence $ ss ++ rem+        StatementSequence ss:rem -> optimizeStatement . StatementSequence $ ss ++ rem         -- reduce statement sequences with only one statement in them down         -- to that single statement         s:[] -> s@@ -64,14 +105,14 @@  optimizeStatement (SwitchStatement e branches) =     let e' = optimizeExpression e-        branches' = map (\(k,v) -> (optimizeExpression k, optimizeStatement v)) branches+        branches' = map (optimizeExpression *** optimizeStatement) branches     in SwitchStatement e' branches'  optimizeStatement s = s   fusePrints :: [Statement] -> [Statement]-fusePrints ((PrintStatement (StringLiteral lhs)):(PrintStatement (StringLiteral rhs)):rem) =+fusePrints (PrintStatement (StringLiteral lhs):PrintStatement (StringLiteral rhs):rem) =     fusePrints $ PrintStatement (StringLiteral $ lhs ++ rhs):fusePrints rem fusePrints (s:rem) = s:fusePrints rem fusePrints [] = []@@ -106,4 +147,4 @@ fromVariant (Double d) = FloatLiteral d fromVariant (Bool b) = BooleanLiteral b fromVariant (List xs) = ListExpression $ map fromVariant xs-fromVariant (AList xs) = AListExpression $ map (\(k,v) -> (fromVariant k, fromVariant v)) xs+fromVariant (AList xs) = AListExpression $ map (fromVariant *** fromVariant) xs
+ Text/HPaco/Readers/Capo/Statements.hs view
@@ -0,0 +1,215 @@+{-#LANGUAGE TupleSections #-}+module Text.HPaco.Readers.Capo.Statements+( statements, statement )+where++import Control.Monad+import Control.Monad.IO.Class+import Control.Applicative ( (<$>), (<*>) )+import Text.HPaco.Reader+import Text.HPaco.Readers.Paco.Basics+import Text.HPaco.Readers.Paco.ParserInternals+import Text.HPaco.Readers.Common hiding (Parser)+import Text.HPaco.Readers.Paco.Expressions+import Text.HPaco.Readers.Paco.Include+import Text.HPaco.AST.AST+import Text.HPaco.AST.Statement+import Text.HPaco.AST.Expression+import Control.Exception (throw)+import System.IO (withFile, IOMode (ReadMode))+import System.IO.Strict+import System.FilePath++statements :: Parser [Statement]+statements = do+    ss_+    stmts <- manySepBy statement ss_+    ss_+    return stmts++statement =+    try defStatement+    <|> try callStatement+    <|> try letStatement+    <|> standaloneStatement++letStatement = do+    (ident, expr) <- withSemicolon assignment+    ss_+    body <- option [NullStatement] statements+    -- TODO: warn if null statement+    return $ LetStatement ident expr $ StatementSequence body++defStatement = do+    keyword "def"+    ss_+    defName <- identifier+    ss_+    char '='+    ss_+    body <- standaloneStatement+    addDef defName body+    return NullStatement++callStatement = do+    CallStatement <$> withSemicolon identifier++assignment :: Parser (String, Expression)+assignment =+    (,) <$> identifier <*> (betweenSpaces (char '=') >> expression)++betweenSpaces a = do+    ss_+    v <- a+    ss_+    return v++-- A standalone statement can appear at any level of the parse tree; it does+-- not need to be explicitly enclosed in a block.+standaloneStatement =+    try lineComment+    <|> try blockComment+    <|> try printStatement+    <|> try printHtmlStatement+    <|> try printUrlStatement+    <|> try ifStatement+    <|> try withStatement+    <|> try forStatement+    <|> try switchStatement+    <|> try includeStatement+    <|> try block+    <?> "Statement"++lineComment = do+    string "//"+    many (noneOf ['\n'])+    char '\n'+    return NullStatement++blockComment = do+    string "/*"+    manyTill (try (discard blockComment) <|> discard anyChar) (try $ string "*/")+    return NullStatement++printStatement = printStatementBase "print" id+printHtmlStatement = printStatementBase "printHtml" (EscapeExpression EscapeHTML)+printUrlStatement = printStatementBase "printUrl" (EscapeExpression EscapeURL)++printStatementBase kw enc =+    withSemicolon $+        StatementSequence . map (PrintStatement . enc) <$>+            (ss_ >> keyword kw >> ss_ >> (parenthesized  $ manySepBy expression (betweenSpaces $ char ',')))++includeStatement :: Parser Statement+includeStatement = do+    ss_+    keyword "include"+    ss_+    filename <- (parenthesized . betweenSpaces) anyQuotedString+    ss_+    char ';'+    ss_+    performInclude filename Nothing++ifStatement = do+    ss_+    keyword "if"+    cond <- parenthesized expression+    true <- standaloneStatement+    false <- option NullStatement $ try falseBranch+    return $ IfStatement cond true false+    where falseBranch = do+            ss_+            keyword "else"+            assertEndOfWord+            ss_+            standaloneStatement++switchStatement = do+    ss_+    keyword "switch"+    SwitchStatement <$> parenthesized expression <*> switchBody+    where+        switchBody = braced $ many switchCase+        switchCase = do+            ss_+            keyword "case"+            ss_+            expr <- expression+            ss_+            char ':'+            body <- StatementSequence <$> statements+            ss_+            optional $ withSemicolon $ keyword "break"+            ss_+            return (expr, body)+    +withStatement =+    withOrFor "with" letAssignment foldLetStatement+    where+        letAssignment = try assignment <|> try ( (".",) <$> expression)+        foldLetStatement :: [(String, Expression)] -> Statement -> Statement+        foldLetStatement assignments body =+            foldr combineAssignment body assignments+            where combineAssignment (ident, expr) stmt = LetStatement ident expr stmt++forStatement =+    withOrFor "for" forAssignment foldForStatement+    where+        forAssignment = try complexForAssignment <|> try ( (Nothing, ".",) <$> expression )+        complexForAssignment = do+            expr <- expression+            ss_+            discard (keyword "as") <|> discard (string ":")+            ss_+            ident1 <- identifier+            ident2 <- optionMaybe $ do+                            ss_+                            string "=>" <|> string "->"+                            ss_+                            identifier+            case ident2 of+                Nothing -> return (Nothing, ident1, expr)+                Just valIdent -> return (Just ident1, valIdent, expr)+        foldForStatement :: [(Maybe String, String, Expression)] -> Statement -> Statement+        foldForStatement assignments body =+            foldr combineAssignment body assignments+            where combineAssignment (keyIdent, valueIdent, expr) stmt = ForStatement keyIdent valueIdent expr stmt++withOrFor :: String -> Parser a -> ([a] -> Statement -> Statement) -> Parser Statement+withOrFor kw a combine = do+    keyword kw+    assignments <- parenthesized $ manySepBy a (ss_ >> char ',' >> ss_)+    body <- standaloneStatement+    return $ combine assignments body++block = StatementSequence <$> braced statements++keyword :: String -> Parser ()+keyword str = do+    string str+    assertEndOfWord++assertEndOfWord :: Parser ()+assertEndOfWord = notFollowedBy $ letter <|> digit <|> char '_'++withSemicolon :: Parser a -> Parser a+withSemicolon p = do+    v <- p +    ss_ +    char ';' +    return v++parenthesized = bracedWith '(' ')'+braced = bracedWith '{' '}'++bracedWith :: Char -> Char -> Parser a -> Parser a+bracedWith l r p = do+    ss_+    char l+    ss_+    val <- p+    ss_+    char r+    ss_+    return val
+ Text/HPaco/Readers/Common.hs view
@@ -0,0 +1,102 @@+module Text.HPaco.Readers.Common+    ( module Text.Parsec.Combinator+    , module Text.Parsec.Char+    , module Text.Parsec.Prim+    , module Text.Parsec.String+    , Parser+    , ss, ss_+    , discard+    , manySepBy+    , braces+    , identifier+    , path+    , anyQuotedString, singleQuotedString, doubleQuotedString+    , assertStartOfInput+    , assertStartOfLine+    )+where++import Text.Parsec.Char+import Text.Parsec.Combinator+import Text.Parsec.Pos (SourcePos, sourceLine, sourceColumn, sourceName)+import Text.Parsec.Prim+import Text.Parsec.String hiding (Parser)+import Control.Monad.IO.Class+import System.IO.Strict++type Parser s a = ParsecT String s IO a++-- Auxiliary parsers++ss :: a -> Parser s a+ss a = skipMany space >> return a++ss_ :: Parser s ()+ss_ = ss ()++braces :: Parser s a -> Parser s a+braces inner = do+    char '{'+    ss_+    v <- inner+    ss_+    char '}'+    return v++identifier :: Parser s String+identifier = do+    x <- letter <|> char '_'+    xs <- many $ letter <|> digit <|> char '_'+    return $ x:xs++anyQuotedString = singleQuotedString <|> doubleQuotedString++singleQuotedString = quotedString '\''+doubleQuotedString = quotedString '"'++quotedString qc = do+    char qc+    str <- many $ quotedStringChar qc+    char qc+    return str++quotedStringChar qc =+    try escapedChar+    <|> noneOf [qc]++escapedChar :: Parser s Char+escapedChar = do+    char '\\'+    c2 <- anyChar+    return $ case c2 of+                'n' -> '\n'+                'r' -> '\r'+                'b' -> '\b'+                't' -> '\t'+                otherwise -> c2++discard :: Parser s a -> Parser s ()+discard p = p >> return ()++manySepBy :: Parser s a -> Parser s b -> Parser s [a]+manySepBy elem sep = do+    h <- try elem+    t <- many (try $ sep >> elem)+    return $ h:t++assertStartOfInput :: Parser s ()+assertStartOfInput = do+    pos <- getPosition+    if sourceLine pos == 1 && sourceColumn pos == 1+        then return ()+        else unexpected "start of input"++assertStartOfLine :: Parser s ()+assertStartOfLine = do+    pos <- getPosition+    if sourceColumn pos == 1+        then return ()+        else unexpected "start of line"++path :: Parser s String+path = many1 $ try $ noneOf " \t\r\n%()"
Text/HPaco/Readers/Paco.hs view
@@ -1,5 +1,6 @@ module Text.HPaco.Readers.Paco     ( readPaco+    , readCapo     ) where @@ -8,7 +9,8 @@ import Text.HPaco.Reader import Text.HPaco.Readers.Paco.ParserInternals import Text.HPaco.Readers.Paco.Basics-import Text.HPaco.Readers.Paco.Statements+import Text.HPaco.Readers.Paco.Statements as PacoStatements+import Text.HPaco.Readers.Capo.Statements as CapoStatements import Text.HPaco.AST.AST import Text.HPaco.AST.Statement import Text.HPaco.AST.Expression@@ -17,28 +19,40 @@ import System.IO.Strict import System.FilePath -readPaco :: Reader-readPaco filename =+readPaco = readRaw pacoDocument+readCapo = readRaw capoDocument++readRawAuto parser filename =+    case (takeExtension filename) of+        ".capo" -> readCapo filename+        ".paco" -> readPaco filename+        otherwise -> readRaw parser filename++readRaw :: Parser AST -> Reader+readRaw parser filename =     let pstate = defaultPacoState                     { psBasePath = takeDirectory filename                     , psIncludeExtension = renull $ takeExtension filename-                    , psHandleInclude = readPaco+                    , psHandleInclude = readRawAuto parser                     }-    in readPacoWithState pstate filename+    in readRawWithState parser pstate filename     where renull "" = Nothing           renull x = Just x -readPacoWithState :: PacoState -> Reader-readPacoWithState pstate filename src = do-    result <- runParserT document pstate filename src+readRawWithState :: Parser AST -> PacoState -> Reader+readRawWithState parser pstate filename src = do+    result <- runParserT parser pstate filename src     either         throw         return         result -document :: Parser AST-document = do-    stmts <- statements+pacoDocument = document PacoStatements.statements+capoDocument = document CapoStatements.statements++document :: Parser [Statement] -> Parser AST+document pstatements = do+    stmts <- pstatements     eof     pstate <- getState     return $ AST 
Text/HPaco/Readers/Paco/Basics.hs view
@@ -3,17 +3,12 @@     , module Text.Parsec.Char     , module Text.Parsec.Prim     , module Text.Parsec.String-    , ss, ss_-    , braces-    , identifier-    , anyQuotedString, singleQuotedString, doubleQuotedString-    , discard-    , manySepBy-    , assertStartOfLine, assertStartOfInput+    , module Text.HPaco.Readers.Common     ) where  import Text.HPaco.Readers.Paco.ParserInternals+import Text.HPaco.Readers.Common hiding (Parser) import Text.Parsec.Char import Text.Parsec.Combinator import Text.Parsec.Pos (SourcePos, sourceLine, sourceColumn, sourceName)@@ -21,75 +16,3 @@ import Text.Parsec.String hiding (Parser) import Control.Monad.IO.Class import System.IO.Strict---- Auxiliary parsers--ss :: a -> Parser a-ss a = skipMany space >> return a--ss_ :: Parser ()-ss_ = ss ()--braces :: Parser a -> Parser a-braces inner = do-    char '{'-    ss_-    v <- inner-    ss_-    char '}'-    return v--identifier :: Parser String-identifier = do-    x <- letter <|> char '_'-    xs <- many $ letter <|> digit <|> char '_'-    return $ x:xs--anyQuotedString = singleQuotedString <|> doubleQuotedString--singleQuotedString = quotedString '\''-doubleQuotedString = quotedString '"'--quotedString qc = do-    char qc-    str <- many $ quotedStringChar qc-    char qc-    return str--quotedStringChar qc =-    try escapedChar-    <|> noneOf [qc]--escapedChar :: Parser Char-escapedChar = do-    char '\\'-    c2 <- anyChar-    return $ case c2 of-                'n' -> '\n'-                'r' -> '\r'-                'b' -> '\b'-                't' -> '\t'-                otherwise -> c2--discard :: Parser a -> Parser ()-discard p = p >> return ()--manySepBy :: Parser a -> Parser b -> Parser [a]-manySepBy elem sep = do-    h <- try elem-    t <- many (try $ sep >> elem)-    return $ h:t--assertStartOfInput :: Parser ()-assertStartOfInput = do-    pos <- getPosition-    if sourceLine pos == 1 && sourceColumn pos == 1-        then return ()-        else unexpected "start of input"--assertStartOfLine :: Parser ()-assertStartOfLine = do-    pos <- getPosition-    if sourceColumn pos == 1-        then return ()-        else unexpected "start of line"
Text/HPaco/Readers/Paco/Expressions.hs view
@@ -4,9 +4,7 @@ where  import Control.Monad-import Text.HPaco.Readers.Paco.Basics-import Text.HPaco.Readers.Paco.ParserInternals-import Text.HPaco.AST.Statement+import Text.HPaco.Readers.Common import Text.HPaco.AST.Expression  expression = booleanExpression@@ -46,10 +44,9 @@         [("*", OpMul), ("/", OpDiv), ("%", OpMod)]         (try traditionalFunctionCallExpression <|> postfixExpression) -binaryExpression :: [(String, BinaryOperator)] -> (Parser Expression) -> Parser Expression+binaryExpression :: [(String, BinaryOperator)] -> Parser s Expression -> Parser s Expression binaryExpression opMap innerParser = do-    let rem :: Parser (BinaryOperator, Expression)-        rem = do+    let rem = do             ss_             opStr <- foldl1 (<|>) $ map (try . string . fst) opMap             ss_@@ -93,13 +90,13 @@         <|> try indexPostfix         <|> try functionCallPostfix -memberAccessPostfix :: Parser (Expression -> Expression)+memberAccessPostfix :: Parser s (Expression -> Expression) memberAccessPostfix = do     char '.'     expr <- StringLiteral `liftM` identifier     return $ \l -> BinaryExpression OpMember l expr -indexPostfix :: Parser (Expression -> Expression)+indexPostfix :: Parser s (Expression -> Expression) indexPostfix = do     ss_     char '['@@ -108,7 +105,7 @@     ss_     return $ \l -> BinaryExpression OpMember l e -functionCallPostfix :: Parser (Expression -> Expression)+functionCallPostfix :: Parser s (Expression -> Expression) functionCallPostfix = do     char '('     args <- manySepBy (try expression) (try $ ss_ >> char ',' >> ss_)@@ -116,7 +113,7 @@     char ')'     return $ \l -> FunctionCallExpression l args -simpleExpression :: Parser Expression+simpleExpression :: Parser s Expression simpleExpression  =  floatLiteral                  <|> intLiteral                  <|> stringLiteral@@ -125,7 +122,7 @@                  <|> varRefExpr                  <|> bracedExpression -bracedExpression :: Parser Expression+bracedExpression :: Parser s Expression bracedExpression = do     char '('     ss_@@ -134,7 +131,7 @@     char ')'     return inner -listExpression :: Parser Expression+listExpression :: Parser s Expression listExpression = do     char '['     ss_@@ -144,7 +141,7 @@     char ']'     return $ ListExpression items -alistExpression :: Parser Expression+alistExpression :: Parser s Expression alistExpression = do     char '{'     ss_@@ -154,7 +151,7 @@     char '}'     return $ AListExpression items     where-        elem :: Parser (Expression, Expression)+        elem :: Parser s (Expression, Expression)         elem = do             ss_             key <- expression@@ -163,14 +160,14 @@             ss_             return (key, value) -intLiteral :: Parser Expression+intLiteral :: Parser s Expression intLiteral = do     sign <- option '+' $ oneOf "+-"     str <- many1 digit     let str' = if sign == '-' then sign:str else str     return . IntLiteral . read $ str' -floatLiteral :: Parser Expression+floatLiteral :: Parser s Expression floatLiteral = do     str <- (try dpd <|> try pd)     return . FloatLiteral . read $ str@@ -189,12 +186,12 @@             let str = "0." ++ fracpart             return $ if sign == '-' then sign:str else str -stringLiteral :: Parser Expression+stringLiteral :: Parser s Expression stringLiteral = do     str <- anyQuotedString     return . StringLiteral $ str -varRefExpr :: Parser Expression+varRefExpr :: Parser s Expression varRefExpr = do     id <- (string "." <|> identifier)     return $ VariableReference id
+ Text/HPaco/Readers/Paco/Include.hs view
@@ -0,0 +1,30 @@+module Text.HPaco.Readers.Paco.Include+where++import Control.Monad+import Control.Monad.IO.Class+import System.IO.Strict+import System.FilePath+import System.IO (withFile, IOMode (ReadMode))+import Text.HPaco.Readers.Paco.Basics+import Text.HPaco.Readers.Paco.ParserInternals+import Text.HPaco.Readers.Paco.Expressions+import Text.HPaco.AST.AST+import Text.HPaco.AST.Statement+import Text.HPaco.AST.Expression+import Text.HPaco.AST.Identifier++performInclude :: String -> Maybe (Identifier, Expression) -> Parser Statement+performInclude basename innerContext = do+    dirname <- psBasePath `liftM` getState+    extension <- psIncludeExtension `liftM` getState+    reader <- psHandleInclude `liftM` getState+    let fn0 = joinPath [ dirname, basename ]+    let fn = maybe fn0 (fillExtension fn0) extension+    src <- liftIO $ withFile fn ReadMode hGetContents+    subAst <- liftIO $ reader fn src+    let stmt = astRootStatement subAst+    modifyState (\s -> s { psDeps = fn:psDeps s ++ astDeps subAst })+    return $ maybe stmt (\(ident, expr) -> LetStatement ident expr stmt) innerContext+    where+
Text/HPaco/Readers/Paco/Statements.hs view
@@ -11,10 +11,13 @@ import Text.HPaco.Readers.Paco.Basics import Text.HPaco.Readers.Paco.ParserInternals import Text.HPaco.Readers.Paco.Expressions+import Text.HPaco.Readers.Paco.Include+import Text.HPaco.Readers.Common hiding (Parser) import Text.HPaco.AST.AST import Text.HPaco.AST.Statement import Text.HPaco.AST.Expression import Text.Parsec.Pos (SourcePos, sourceLine, sourceColumn, sourceName)+import qualified Text.HPaco.Readers.Capo.Statements as CapoStatements  statements :: Parser [Statement] statements =@@ -28,6 +31,7 @@ statement = try ifStatement            <|> try withStatement           <|> try switchStatement+          <|> try inlineCapoStatement           <|> try forStatement           <|> try defStatement           <|> try callStatement@@ -54,20 +58,8 @@ includeStatement :: Parser Statement includeStatement = do     (basename, innerContext) <- complexTag "include" inner-    dirname <- psBasePath `liftM` getState-    extension <- psIncludeExtension `liftM` getState-    reader <- psHandleInclude `liftM` getState-    let fn0 = joinPath [ dirname, basename ]-    let fn = maybe fn0 (fillExtension fn0) extension-    src <- liftIO $ withFile fn ReadMode hGetContents-    subAst <- liftIO $ reader fn src-    let stmt = astRootStatement subAst-    modifyState (\s -> s { psDeps = fn:psDeps s ++ astDeps subAst })-    return $ maybe stmt (\(ident, expr) -> LetStatement ident expr stmt) innerContext+    performInclude basename innerContext     where-        path :: Parser String-        path = many1 $ try $ noneOf " \t\r\n%"-         inner :: Parser (String, Maybe (String, Expression))         inner = do             basename <- path@@ -75,6 +67,7 @@             innerContext <- optionMaybe $ try (ss_ >> string "with" >> ss_ >> letPair)             return (basename, innerContext) + interpolateStatement :: Parser Statement interpolateStatement = do     char '{'@@ -122,6 +115,13 @@                     stmts <- statements                     return . StatementSequence $ stmts +inlineCapoStatement :: Parser Statement+inlineCapoStatement = do+    simpleTag "capo"+    stmts <- CapoStatements.statements+    simpleTag "endcapo"+    return $ StatementSequence stmts+ withStatement :: Parser Statement withStatement = withOrForStatement (\(n,v) -> LetStatement n v) "with" letPairs @@ -232,4 +232,3 @@ escapeMode :: Parser (Maybe EscapeMode) escapeMode = (char '!' >> return Nothing)           <|> (char '@' >> return (Just EscapeURL))-
Text/HPaco/Writer.hs view
@@ -21,6 +21,7 @@                   , woWrapMode :: WrapMode                   , woExposeAllFunctions :: Bool                   , woWriteFunc :: String+                  , woSourcePositionComments :: Bool                   }  defaultWriterOptions =@@ -31,8 +32,9 @@                   , woWrapMode = WrapNone                   , woExposeAllFunctions = False                   , woWriteFunc = ""+                  , woSourcePositionComments = False                   }  instance CodeWriterOptions WriterOptions where     cwoIndent = woIndentStr-    cwoNewline = \_ -> "\n"+    cwoNewline = const "\n"
Text/HPaco/Writers/Dependencies.hs view
@@ -5,4 +5,4 @@  writeDependencies :: String -> AST -> String writeDependencies fn ast =-    fn ++ ": " ++ (concat $ intersperse " " (astDeps ast)) ++ "\n"+    fn ++ ": " ++ unwords (astDeps ast) ++ "\n"
Text/HPaco/Writers/Internal/CodeWriter.hs view
@@ -89,7 +89,7 @@ writeIndent = do     indentLevel <- gets cwsGetIndent     indentStr <- asks cwoIndent-    write $ concat $ take indentLevel $ repeat indentStr+    write $ concat $ replicate indentLevel indentStr  endl :: (Monad m, CodeWriterOptions o, CodeWriterState s) => CodeWriterT o s m () endl = asks cwoNewline >>= write
Text/HPaco/Writers/Javascript.hs view
@@ -85,7 +85,8 @@         otherwise -> return ()     writeIndented "(function(){"     pushIndent-    writePreamble+    includePreamble <- asks woIncludePreamble+    when includePreamble writePreamble   writeFooter :: PWS ()@@ -118,19 +119,18 @@         ForStatement Nothing identifier expr stmt -> writeFor identifier expr stmt         ForStatement (Just iter) identifier expr stmt -> writeForExt iter identifier expr stmt         SwitchStatement masterExpr branches -> writeSwitch masterExpr branches-        CallStatement identifier -> do-            -- ast <- gets jwsAST-            -- let body = fromMaybe NullStatement $ lookup identifier $ astDefs ast-            -- writeStatement body+        CallStatement identifier ->             writeIndented $ "_macro_" ++ identifier ++ ".apply(this);"         SourcePositionStatement fn ln -> do-            writeIndent-            write "/* "-            write fn-            write ":"-            write $ show ln-            write " */"-            endl+            c <- asks woSourcePositionComments+            when c $ do+                writeIndent+                write "/* "+                write fn+                write ":"+                write $ show ln+                write " */"+                endl  writeIf :: Statement -> PWS () writeIf (IfStatement cond true false) = do@@ -141,12 +141,10 @@     endl     withIndent $ writeStatement true     writeIndented "}"-    if false == NullStatement-        then return ()-        else do-                writeIndented "else {"-                withIndent $ writeStatement false-                writeIndented "}"+    unless (false == NullStatement) $ do+        writeIndented "else {"+        withIndent $ writeStatement false+        writeIndented "}"  writeLet :: String -> Expression -> Statement -> PWS () writeLet identifier expr stmt =@@ -189,7 +187,7 @@         writeIndented "}"     writeIndented "}).apply(this);" -writeWithScope :: String -> (PWS ()) -> (PWS ()) -> PWS ()+writeWithScope :: String -> PWS () -> PWS () -> PWS () writeWithScope identifier rhs inner = do     if identifier == "."         then do@@ -264,7 +262,7 @@                 write " : "                 writeExpression value -        VariableReference vn -> do+        VariableReference vn ->             if vn == "."                 then write "this"                 else do@@ -375,4 +373,4 @@         escapeChar '\t' = "' + \"\\t\" + '"         escapeChar '\r' = "' + \"\\r\" + '"         escapeChar x = [x]-        escape = concat . map escapeChar+        escape = concatMap escapeChar
Text/HPaco/Writers/JsonLisp.hs view
@@ -53,28 +53,28 @@     return x  writeList :: [JWS ()] -> JWS ()-writeList ws = do+writeList ws =     wrapList $ sequence_ $ intersperse (write ", ") ws  writes :: JWSWrite a => [a] -> JWS () writes = writeList . map write  writeWithHead :: JWSWrite b => String -> [b] -> JWS ()-writeWithHead h xs = writeList ((writeExpression $ StringLiteral h):map write xs)+writeWithHead h xs = writeList (writeExpression (StringLiteral h):map write xs)  cullStatements stmts =-    catMaybes $ map toMay stmts+    mapMaybe toMay stmts     where         toMay NullStatement = Nothing         toMay (SourcePositionStatement {}) = Nothing         toMay x = Just x  writeAST :: AST -> JWS ()-writeAST ast = do+writeAST ast =     writeWithHead "progn" (map writeDef (astDefs ast) ++ [ write $ astRootStatement ast ])  writeDef :: (String, Statement) -> JWS ()-writeDef (defName, stmt) = do+writeDef (defName, stmt) =     writeWithHead "def" [ write $ StringLiteral defName, write stmt ]      writeStatement :: Statement -> JWS ()@@ -90,15 +90,12 @@             --     FloatLiteral _ -> writeWithHead "print" [expr]             --     otherwise -> wrapList $ write "flatten " >> writeWithHead "print" [expr]         NullStatement -> return ()-        IfStatement expr true false -> writeList [ (write $ StringLiteral "if"), write expr, write true, write false ]-        LetStatement identifier expr stmt -> writeList [ (write $ StringLiteral "let"), write $ StringLiteral identifier, write expr, write stmt ]-        ForStatement iter identifier expr stmt -> writeList [ (write $ StringLiteral "let"), write $ StringLiteral identifier, write expr, write stmt ]+        IfStatement expr true false -> writeList [ write $ StringLiteral "if", write expr, write true, write false ]+        LetStatement identifier expr stmt -> writeList [ write $ StringLiteral "let", write $ StringLiteral identifier, write expr, write stmt ]+        ForStatement iter identifier expr stmt -> writeList [ write $ StringLiteral "let", write $ StringLiteral identifier, write expr, write stmt ]         SwitchStatement masterExpr branches -> writeWithHead "switch" (map writeSwitchBranch branches)-        CallStatement identifier -> do+        CallStatement identifier ->             writeWithHead "calldef" [StringLiteral identifier]-            -- ast <- gets jwsAST-            -- let body = fromMaybe NullStatement $ lookup identifier $ astDefs ast-            -- writeStatement body         SourcePositionStatement fn ln -> return ()         where             writeSwitchBranch (expr, stmt) = writeWithHead "case" [ write expr, write stmt ]@@ -160,4 +157,4 @@         escapeChar '\t' = "\\t"         escapeChar '\r' = "\\r"         escapeChar x = [x]-        escape = concat . map escapeChar+        escape = concatMap escapeChar
Text/HPaco/Writers/PHP.hs view
@@ -60,8 +60,7 @@  writeAST :: AST -> PWS () writeAST ast = do-    writeHeader-    writeDefs $ astDefs ast+    writeHeader ast     writeStatement $ astRootStatement ast     writeFooter @@ -72,7 +71,7 @@ -- open/close tags for you. Should only be used when the PHP tags have been -- written using other means already. unsafeSetOutputMode :: OutputMode -> PWS ()-unsafeSetOutputMode m = do+unsafeSetOutputMode m =     modify (\s -> s { pwsOutputMode = m })  setOutputMode :: OutputMode -> PWS ()@@ -110,7 +109,7 @@     return $ resolve key scopeStack     where         resolve key scopes =-            let mr = catMaybes $ map (M.lookup key) scopes+            let mr = mapMaybe (M.lookup key) scopes             in if null mr then Nothing else (Just . head) mr  resolveVariable :: String -> PWS String@@ -157,8 +156,8 @@     unsafeSetOutputMode PHP     write src -writeHeader :: PWS ()-writeHeader = do+writeHeader :: AST -> PWS ()+writeHeader ast = do     templateName <- woTemplateName `liftM` ask     includePreamble <- woIncludePreamble `liftM` ask     wrapMode <- woWrapMode `liftM` ask@@ -174,6 +173,7 @@                         then "runTemplate"                         else "runTemplate_" ++ templateName             writeLn $ "function " ++ funcName ++ "($context) {"+            withIndent $ writeDefs $ astDefs ast             pushIndent         WrapClass -> do             let className =@@ -181,34 +181,46 @@                         then "Template"                         else "Template_" ++ templateName             writeLn $ "class " ++ className ++ " {"+            writeDefs $ astDefs ast             pushIndent             writeLn $ "public function __invoke($context) {"             pushIndent-        otherwise -> return ()+        otherwise -> writeDefs $ astDefs ast     pushScope     vid <- defineVariable "."     writeLn "if (isset($context)) {"-    withIndent $ do-        writeIndent-        write "$"-        write $ toVarname vid-        write " = $context;"-        endl+    withIndent $ writeVarAssignment vid $ write "$context"     writeLn "}"     writeLn "else {"-    withIndent $ do-        writeIndent-        write "$"-        write $ toVarname vid-        write " = array();"-        endl+    withIndent $ writeVarAssignment vid $ write "array()"     writeLn "}"     writeLn "$_scope = array();"     writePushScope +writeVar vid = do+    write "$"+    write $ toVarname vid++writeVarAssignment vid rhs = writeAssignment (writeVar vid) rhs++writeAssignment lhs rhs = do+    writeIndent+    lhs+    write " = "+    rhs+    write ";"+    endl+     writeDefs defs = do     mapM_ writeDef defs +writeUnsetVar id = do+    writeIndent+    write "unset($"+    write $ toVarname id+    write ");";+    endl+ withSealedScope inner = do     outerScope <- getScope     setScope []@@ -296,14 +308,16 @@             write identifier             write ");"             endl-        SourcePositionStatement fn ln -> return ()-            -- writeIndent-            -- write "/* "-            -- write fn-            -- write ":"-            -- write $ show ln-            -- write " */"-            -- endl+        SourcePositionStatement fn ln -> do+            c <- asks woSourcePositionComments+            when c $ do+                writeIndent+                write "/* "+                write fn+                write ":"+                write $ show ln+                write " */"+                endl  writeIf :: Statement -> PWS () writeIf (IfStatement cond true false) = do@@ -326,23 +340,13 @@     pushScope     id <- defineVariable identifier -    writeIndent-    write "$"-    write $ toVarname id-    write " = "-    writeExpression expr-    write ";"-    endl+    writeVarAssignment id $ writeExpression expr      writePushScopeVar identifier      writeStatement stmt -    writeIndent-    write "unset($"-    write $ toVarname id-    write ");";-    endl+    writeUnsetVar id      popScope     writePopScope@@ -351,16 +355,12 @@ writeFor :: Maybe String -> String -> Expression -> Statement -> PWS () writeFor iter identifier expr stmt = do     pushScope-    id <- defineVariable identifier -    writeIndent-    write "$_iteree = "-    writeExpression expr-    write ";"-    endl+    writeAssignment (write "$_iteree") (writeExpression expr)      writeLn "if (is_array($_iteree) || ($_iteree instanceof Traversable)) {" +    id <- defineVariable identifier     withIndent $ do         writeIndent         write "foreach ($_iteree as $"@@ -381,11 +381,7 @@          writeLn "}" -        writeIndent-        write "unset($"-        write $ toVarname id-        write ");";-        endl+        writeUnsetVar id      writeLn "}" @@ -464,16 +460,12 @@          BinaryExpression OpMember left right -> do             write "_r("-            writeExpression left-            write ", "-            writeExpression right+            writeExpressionPair left right             write ")"          BinaryExpression OpInList left right -> do             write "_in("-            writeExpression left-            write ", "-            writeExpression right+            writeExpressionPair left right             write ")"          BinaryExpression o left right -> do@@ -513,6 +505,11 @@             mapM_ (\e -> writeExpression e >> write ", ") args             write "))" +writeExpressionPair :: Expression -> Expression -> PWS ()+writeExpressionPair lhs rhs = do+    writeExpression lhs+    write ","+    writeExpression rhs  singleQuoteString :: String -> String singleQuoteString str =
hpaco-lib.cabal view
@@ -1,5 +1,5 @@ name:                hpaco-lib-version:             0.16.2.0+version:             0.18.0.0 synopsis:            Modular template compiler library description:         Template compiler library, compiles template code into                      PHP or Javascript, or interprets it directly.@@ -19,11 +19,14 @@  library   exposed-modules: Text.HPaco.Optimizer+                 , Text.HPaco.Readers.Common                  , Text.HPaco.Readers.Paco                  , Text.HPaco.Readers.Paco.ParserInternals                  , Text.HPaco.Readers.Paco.Basics                  , Text.HPaco.Readers.Paco.Expressions                  , Text.HPaco.Readers.Paco.Statements+                 , Text.HPaco.Readers.Paco.Include+                 , Text.HPaco.Readers.Capo.Statements                  , Text.HPaco.Writers.Javascript                  , Text.HPaco.Writers.JsonLisp                  , Text.HPaco.Writers.Dependencies