jacinda 3.3.0.5 → 3.3.0.6
raw patch · 10 files changed
+147/−177 lines, 10 files
Files
- CHANGELOG.md +5/−0
- README.md +0/−1
- jacinda.cabal +1/−1
- src/A.hs +1/−2
- src/File.hs +2/−2
- src/L.x +62/−51
- src/Parser.y +14/−15
- src/R.hs +55/−95
- src/Ty.hs +0/−3
- x/Opt.hs +7/−7
CHANGELOG.md view
@@ -1,3 +1,8 @@+# 3.3.0.6++ * Fix to allow nested dfns+ * Allow `-Dval=VAR` on command-line+ # 3.3.0.5 * Add `Ord` instance for tuples, etc.
README.md view
@@ -63,7 +63,6 @@ ## Missing Features & Bugs - * No nested dfns * No list literal syntax * Postfix `:f` and `:i` are handled poorly * Streams of functions don't work
jacinda.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: jacinda-version: 3.3.0.5+version: 3.3.0.6 license: AGPL-3.0-only license-file: COPYING maintainer: vamchale@gmail.com
src/A.hs view
@@ -128,7 +128,7 @@ | Substr | Sub1 | Subs | Option | Captures | AllCaptures | Ixes- | Bookend | BookendG+ | Bookend instance Pretty BTer where pretty ZipW = ","@@ -291,7 +291,6 @@ ps _ (EApp _ (UB _ FParse) e') = pretty e' <> ":f" ps _ (EApp _ (UB _ Parse) e') = pretty e' <> ":" ps d (EApp _ (EApp _ (EApp _ (TB _ Bookend) e) e') e'') = parensp (d>3) (ps 4 e <> ",," <> ps 4 e' <+> ps 5 e'')- ps d (EApp _ (EApp _ (EApp _ (TB _ BookendG) e) e') e'') = parensp (d>3) (ps 4 e <> "|," <> ps 4 e' <+> ps 5 e'') ps d (EApp _ (EApp _ (EApp _ (TB _ Fold) e) e') e'') = parensp (d>5) (ps 6 e <> "|" <> ps 6 e' <+> ps 7 e'') ps d (EApp _ (EApp _ (EApp _ (TB _ Scan) e) e') e'') = parensp (d>5) (ps 6 e <> "^" <> ps 6 e' <+> ps 7 e'') ps d (EApp _ (EApp _ (EApp _ (TB _ ScanList) e) e') e'') = parensp (d>5) (ps 6 e <> "^" <> ps 6 e' <+> ps 7 e'')
src/File.hs view
@@ -71,8 +71,8 @@ -- | Parse + rename parsePWithMax :: [FilePath] -> Maybe FilePath -> T.Text -> [(T.Text, T.Text)] -> IO (Program AlexPosn, Int)-parsePWithMax incls fn src vars = uncurry rP.swap.second fst3 <$> runStateT (parseP incls fn src vars) alexInitUserState- where fst3 (x,_,_) = x+parsePWithMax incls fn src vars = uncurry rP.swap.second fst4 <$> runStateT (parseP incls fn src vars) alexInitUserState+ where fst4 (x,_,_,_) = x parseWithMax' :: T.Text -> Either (ParseError AlexPosn) (Program AlexPosn, Int) parseWithMax' = fmap (uncurry rP . second (rwP.snd)) . parseWithMax
src/L.x view
@@ -15,7 +15,6 @@ , AlexUserState ) where -import Control.Arrow ((&&&)) import Data.Bifunctor (first) import qualified Data.ByteString.Lazy as BSL import Data.Functor (($>))@@ -58,14 +57,27 @@ y { res VarY } } - <0> "[" { sym LSqBracket `andBegin` dfn } -- FIXME: this doesn't allow nested+ <0> {+ "#!".* ; -- shebang + asv { mkKw KwAsv }+ usv { mkKw KwUsv }+ csv { mkKw KwCsv }+ header { mkKw KwHeader }+ fs { mkKw KwFs }+ rs { mkKw KwRs }+ :set { mkKw KwSet }+ :flush { mkKw KwFlush }+ "@include" { mkKw KwInclude }+ fn { mkKw KwFn }++ }+ <0,dfn> { $white+ ; "{.".* ;- "#!".* ; -- shebang ":=" { sym DefEq } "≔" { sym DefEq }@@ -103,7 +115,7 @@ "{%" { sym LBracePercent } "#{" { sym LBraceOctothorpe } "{|" { sym LBraceBar }- "]" { sym RSqBracket `andBegin` 0 }+ "]" { tok (\p _ -> rsq (TokSym p RSqBracket)) } ".=" { sym DotEq } "~" { sym Tilde } "!~" { sym NotMatchTok }@@ -136,32 +148,23 @@ "`$" { sym FieldListTok } \? { sym QuestionMark } "@@" { sym AmpAmp }+ ¨ { sym Quot } - in { mkKw KwIn }+ "[" { tok (\p _ -> lsq (TokSym p LSqBracket)) }+ let { mkKw KwLet } val { mkKw KwVal }+ in { mkKw KwIn } end { mkKw KwEnd }- :set { mkKw KwSet }- :flush { mkKw KwFlush }- fn { mkKw KwFn }- "@include" { mkKw KwInclude } if { mkKw KwIf } then { mkKw KwThen } else { mkKw KwElse }- asv { mkKw KwAsv }- usv { mkKw KwUsv }- csv { mkKw KwCsv }- header { mkKw KwHeader } - fs { res VarFs }- rs { res VarRs }- ix { res VarIx }- ⍳ { res VarIx }- nf { res VarNf }- ¨ { sym Quot }- min { res VarMin }- max { res VarMax }-+ ix { mkBuiltin BIx }+ ⍳ { mkBuiltin BIx }+ nf { mkBuiltin BNf }+ min { mkBuiltin BMin }+ max { mkBuiltin BMax } substr { mkBuiltin BSubstr } split { mkBuiltin BSplit } splitc { mkBuiltin BSplitc }@@ -211,7 +214,6 @@ @string { tok (\p s -> alex $ TokStr p (escReplace $ T.init $ T.tail s)) } - -- TODO: allow chars to be escaped @rr { tok (\p s -> alex $ TokRR p (escRr $ T.init $ T.tail s)) } @name { tok (\p s -> TokName p <$> newIdentAlex p s) }@@ -228,8 +230,10 @@ constructor c t = tok (\p _ -> alex $ c p t) -res = constructor TokResVar; mkKw = constructor TokKeyword-sym = constructor TokSym; mkBuiltin = constructor TokBuiltin+res = constructor TokVar+mkKw = constructor TokKeyword+sym = constructor TokSym+mkBuiltin = constructor TokBuiltin data R = Z | B | EE | ES @@ -252,16 +256,23 @@ instance Pretty AlexPosn where pretty (AlexPn _ line col) = pretty line <> colon <> pretty col -type AlexUserState = (Int, M.Map T.Text Int, IM.IntMap (Nm AlexPosn))+type AlexUserState = (Int, M.Map T.Text Int, IM.IntMap (Nm AlexPosn), Int) alexInitUserState :: AlexUserState-alexInitUserState = (0, mempty, mempty)+alexInitUserState = (0, mempty, mempty, 0) -gets_alex :: (AlexState -> a) -> Alex a-gets_alex f = Alex (Right . (id &&& f))+lsq, rsq :: a -> Alex a+lsq ret = Alex $ \st ->+ let (max', names, uniqs, db) = alex_ust st+ db' = db+1+ in Right (st { alex_ust = (max', names, uniqs, db'), alex_scd = dfn }, ret)+rsq ret = Alex $ \st ->+ let (max', names, uniqs, db) = alex_ust st+ db' = db-1+ in Right (st { alex_ust = (max', names, uniqs, db'), alex_scd = if db'==0 then 0 else dfn }, ret) get_pos :: Alex AlexPosn-get_pos = gets_alex alex_pos+get_pos = Alex $ \st -> Right (st, alex_pos st) alexEOF = EOF <$> get_pos @@ -275,10 +286,9 @@ | DefEq | Colon | LBrace | RBrace- | LParen+ | LParen | RParen | LAnchor | DotEq- | RParen | LSqBracket | RSqBracket | Semicolon | Underscore@@ -381,20 +391,13 @@ | KwInclude | KwIf | KwThen | KwElse | KwAsv | KwUsv | KwCsv+ | KwFs | KwRs+ | KwOfs | KwOrs --- | Reserved/special variables data Var = VarX | VarY- | VarFs | VarRs- | VarOfs | VarOrs- | VarIx | VarNf- | VarMin | VarMax instance Pretty Var where pretty VarX = "x"; pretty VarY = "y"- pretty VarFs = "fs"; pretty VarRs = "rs"- pretty VarOrs = "ors"; pretty VarOfs = "ofs"- pretty VarMin = "min"; pretty VarMax = "max"- pretty VarIx = "⍳"; pretty VarNf = "nf" instance Pretty Keyword where pretty KwLet = "let"@@ -411,7 +414,11 @@ pretty KwUsv = "usv" pretty KwAsv = "asv" pretty KwCsv = "csv"- pretty KwHeader = "header"+ pretty KwHeader = "header"+ pretty KwFs = "fs"+ pretty KwRs = "rs"+ pretty KwOrs = "ors"+ pretty KwOfs = "ofs" data Builtin = BIParse | BFParse | BSubstr@@ -433,6 +440,8 @@ | BInit | BLast | BDrop | BTake | BRein+ | BMin | BMax+ | BIx | BNf instance Pretty Builtin where pretty BIParse = ":i"@@ -465,6 +474,10 @@ pretty BTake = "take#" pretty BDrop = "drop#" pretty BRein = "reintercalate"+ pretty BMin = "min"+ pretty BMax = "max"+ pretty BIx = "⍳"+ pretty BNf = "nf" data Token a = EOF { loc :: a } | TokSym { loc :: a, _sym :: Sym }@@ -472,7 +485,7 @@ | TokTyName { loc :: a, _tyName :: TyName a } | TokBuiltin { loc :: a, _builtin :: Builtin } | TokKeyword { loc :: a, _kw :: Keyword }- | TokResVar { loc :: a, _var :: Var }+ | TokVar { loc :: a, _var :: Var } | TokInt { loc :: a, int :: Integer } | TokFloat { loc :: a, float :: Double } | TokBool { loc :: a, boolTok :: Bool }@@ -497,7 +510,7 @@ pretty (TokStreamLit _ i) = "$" <> pretty i pretty (TokFieldLit _ i) = "`" <> pretty i pretty (TokRR _ rr') = "/" <> pretty rr' <> "/"- pretty (TokResVar _ v) = "reserved variable" <+> squotes (pretty v)+ pretty (TokVar _ v) = "implicit variable" <+> squotes (pretty v) pretty (TokBool _ True) = "#t" pretty (TokBool _ False) = "#f" pretty (TokAccess _ i) = "." <> pretty i@@ -508,9 +521,9 @@ freshName :: T.Text -> Alex (Nm AlexPosn) freshName t = do pos <- get_pos- (i, ns, us) <- alexGetUserState+ (i, ns, us, db) <- alexGetUserState let (j, n) = freshIdent pos t i- alexSetUserState (j, ns, us) $> n+ alexSetUserState (j, ns, us, db) $> n newVarAlex :: T.Text -> Alex (Nm AlexPosn) newVarAlex t = do {pos <- get_pos; newIdentAlex pos t}@@ -522,17 +535,15 @@ alexSetUserState st' $> n freshIdent :: AlexPosn -> T.Text -> Int -> (Int, Nm AlexPosn)-freshIdent pos t max' =- let i=max'+1; nm=Nm t (U i) pos- in (i, nm)+freshIdent pos t max' = let i=max'+1 in (i, Nm t (U i) pos) newIdent :: AlexPosn -> T.Text -> AlexUserState -> (AlexUserState, Nm AlexPosn)-newIdent pos t pre@(max', names, uniqs) =+newIdent pos t pre@(max', names, uniqs, depth') = case M.lookup t names of Just i -> (pre, Nm t (U i) pos) Nothing -> let i = max' + 1 in let newName = Nm t (U i) pos- in ((i, M.insert t i names, IM.insert i newName uniqs), newName)+ in ((i, M.insert t i names, IM.insert i newName uniqs, depth'), newName) runAlexSt :: T.Text -> Alex a -> Either String (AlexUserState, a) runAlexSt inp = withAlexSt inp alexInitUserState
src/Parser.y view
@@ -10,7 +10,7 @@ ) where import Control.Exception (Exception, throw)-import Control.Monad.Except (ExceptT, runExceptT, throwError)+import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE) import Control.Monad.Trans.Class (lift) import Data.Bifunctor (first, second) import Data.Functor (void)@@ -130,19 +130,18 @@ usv { TokKeyword $$ KwUsv } asv { TokKeyword $$ KwAsv } csv { TokKeyword $$ KwCsv }-- x { TokResVar $$ VarX }- y { TokResVar $$ VarY }+ fs { TokKeyword $$ KwFs }+ rs { TokKeyword $$ KwRs }+ ofs { TokKeyword $$ KwOfs }+ ors { TokKeyword $$ KwOrs } - min { TokResVar $$ VarMin }- max { TokResVar $$ VarMax }- ix { TokResVar $$ VarIx }- nf { TokResVar $$ VarNf }- fs { TokResVar $$ VarFs }- rs { TokResVar $$ VarRs }- ofs { TokResVar $$ VarOfs }- ors { TokResVar $$ VarOrs }+ x { TokVar $$ VarX }+ y { TokVar $$ VarY } + min { TokBuiltin $$ BMin }+ max { TokBuiltin $$ BMax }+ ix { TokBuiltin $$ BIx }+ nf { TokBuiltin $$ BNf } split { TokBuiltin $$ BSplit } splitc { TokBuiltin $$ BSplitc } substr { TokBuiltin $$ BSubstr }@@ -386,7 +385,7 @@ type Value = T.Text parseError :: Token AlexPosn -> [String] -> Parse a-parseError tok = throwError . Unexpected tok+parseError tok = throwE.Unexpected tok mkLet :: a -> [(Nm a, E a)] -> E a -> E a mkLet _ [] e = e@@ -416,8 +415,8 @@ df t x = do {nm <- newVarAlex t; let l=Nm.loc nm in pure (Let l (nm, guess l x))} parseWithMax :: T.Text -> Either (ParseError AlexPosn) (Int, File)-parseWithMax = fmap (first fst3) . runParse parseF- where fst3 (x, _, _) = x+parseWithMax = fmap (first fst4) . runParse parseF+ where fst4 (x, _, _, _) = x binds :: [(T.Text, Value)] -> Alex (E AlexPosn -> E AlexPosn) binds = fmap thread.traverse (uncurry df) where thread = foldr (.) id
src/R.hs view
@@ -6,9 +6,10 @@ import A import C import Control.Monad.State.Strict (MonadState, State, runState)-import Data.Bifunctor (second)+import Data.Bifunctor (bimap, first, second) import qualified Data.IntMap as IM import qualified Data.Text as T+import qualified Data.Vector as V import Lens.Micro (Lens', over) import Lens.Micro.Mtl (use, (%=), (.=)) import Nm@@ -81,76 +82,6 @@ mkLam :: [Nm a] -> E a -> E a mkLam ns e = foldr (\n -> Lam (loc n) n) e ns -hasY :: E a -> Bool-hasY = g where- g (ResVar _ Y) = True- g (Tup _ es) = g!|es- g (Rec _ es) = (g.snd)!|es- g (OptionVal _ (Just e)) = g e- g (EApp _ e0 e1) = g e0 || g e1- g Dfn{} = error "nested dfns not yet implemented"- g (Let _ (_, be) e) = g e || g be- g (Lam _ _ e) = g e- g (Paren _ e) = g e- g (Guarded _ p e) = g p || g e- g (Implicit _ e) = g e- g (Arr _ es) = g!|es- g (Anchor _ es) = g!|es- g (Cond _ p e0 e1) = g e0 || g e1 || g p- g _ = False-- infixr 6 !|-- (!|) :: Foldable t => (a -> Bool) -> t a -> Bool- (!|) = any--replaceXY :: (a -> Nm a) -- ^ @x@- -> (a -> Nm a) -- ^ @y@- -> E a- -> E a-replaceXY nX nY = r where- r (ResVar l Y) = Var l (nY l)- r (ResVar l X) = Var l (nX l)- r e@Lit{} = e- r e@RegexLit{} = e- r e@RC{} = e- r e@Var{} = e- r e@NB{} = e- r e@UB{} = e- r e@BB{} = e- r e@RwB{} = e- r e@RwT{} = e- r e@TB{} = e- r (EApp l e0 e1) = EApp l (r e0) (r e1)- r (Implicit l e) = Implicit l (r e)- r (Guarded l p e) = Guarded l (r p) (r e)- r (Let l (n, be) e) = Let l (n, r be) (r e)- r (Lam l n e) = Lam l n (r e)- r (Cond l p e0 e1) = Cond l (r p) (r e0) (r e1)- r (OptionVal l e) = OptionVal l (r<$>e)- r (Tup l es) = Tup l (r<$>es)- r (Rec l es) = Rec l (second r<$>es)- r (Arr l es) = Arr l (r<$>es)- r (Anchor l es) = Anchor l (r<$>es)- r e@Column{} = e- r e@AllColumn{} = e- r e@Field{} = e- r e@AllField{} = e- r e@LastField{} = e- r e@FieldList{} = e- r e@FParseAllCol{} = e- r e@IParseAllCol{} = e- r e@ParseAllCol{} = e- r e@FParseCol{} = e- r e@IParseCol{} = e- r e@ParseCol{} = e- r (Paren l e) = Paren l (r e)- r Dfn{} = error "nested dfns not yet implemented"- r F{} = error "Internal error."--replaceX :: (a -> Nm a) -> E a -> E a-replaceX n = replaceXY n (error "Internal error: 'y' not expected.")- renameD :: D a -> RenameM (D a) renameD (FunDecl n ns e) = FunDecl n [] <$> rE (mkLam ns e) renameD d = pure d@@ -160,30 +91,59 @@ {-# INLINABLE rE #-} rE :: (HasRenames s, MonadState s m) => E a -> m (E a)-rE (EApp l e e') = EApp l <$> rE e <*> rE e'-rE (Tup l es) = Tup l <$> traverse rE es-rE (Rec l es) = Rec l <$> traverse (secondM rE) es-rE (Var l n) = Var l <$> replaceVar n-rE (Lam l n e) = doLocal $ do+rE = fmap fst.r undefined undefined++{-# INLINABLE r #-}+r :: (HasRenames s, MonadState s m) => (a -> Nm a) -> (a -> Nm a) -> E a -> m (E a, Bool)+r _ _ (Var l n) = (\n' -> (Var l n', False)) <$> replaceVar n+r x y (EApp l e0 e1) = do+ (e0',b0) <- r x y e0+ (e1',b1) <- r x y e1+ pure (EApp l e0' e1', b0||b1)+r x y (Cond l p e0 e1) = do+ (p',b0) <- r x y p+ (e0',b1) <- r x y e0+ (e1',b2) <- r x y e1+ pure (Cond l p' e0' e1', b0||b1||b2)+r x y (Lam l n e) = doLocal $ do n' <- freshen n- Lam l n' <$> rE e-rE (Dfn l e) | {-# SCC "hasY" #-} hasY e = do+ first (Lam l n') <$> r x y e+r x y (Let l (n, eb) e) = doLocal $ do+ (eb', b) <- r x y eb+ n' <- freshen n+ bimap (Let l (n', eb')) (b||) <$> r x y e+r _ _ (Dfn l e) = do x@(Nm nX uX _) <- dummyName l "x" y@(Nm nY uY _) <- dummyName l "y"- Lam l x . Lam l y <$> rE ({-# SCC "replaceXY" #-} replaceXY (Nm nX uX) (Nm nY uY) e)- | otherwise = do- x@(Nm n u _) <- dummyName l "x"- Lam l x <$> rE ({-# SCC "replaceX" #-} replaceX (Nm n u) e)-rE (Guarded l p e) = Guarded l <$> rE p <*> rE e-rE (Implicit l e) = Implicit l <$> rE e-rE ResVar{} = error "Bare reserved variable."-rE (Let l (n, eϵ) e') = doLocal $ do- eϵ' <- rE eϵ- n' <- freshen n- Let l (n', eϵ') <$> rE e'-rE (Paren _ e) = rE e-rE (Arr l es) = Arr l <$> traverse rE es-rE (Anchor l es) = Anchor l <$> traverse rE es-rE (OptionVal l e) = OptionVal l <$> traverse rE e-rE (Cond l p e e') = Cond l <$> rE p <*> rE e <*> rE e'-rE e = pure e+ (e',hasY) <- r (Nm nX uX) (Nm nY uY) e+ pure $ if hasY+ then (Lam l x (Lam l y e'), False)+ else (Lam l x e', False)+r x y (Implicit l e) = do+ (e',b) <- r x y e+ pure (Implicit l e', b)+r x y (Guarded l p e) = do+ (p',b0) <- r x y p+ (e',b1) <- r x y e+ pure (Guarded l p' e', b0||b1)+r x _ (ResVar l X) = pure (Var l (x l), False)+r _ y (ResVar l Y) = pure (Var l (y l), True)+r x y (Tup l es) = do+ (es',b) <- unzip <$> traverse (r x y) es+ pure (Tup l es', or b)+r x y (OptionVal l e) = do+ v <- traverse (r x y) e+ case v of+ Nothing -> pure (OptionVal l Nothing, False)+ Just (e',b) -> pure (OptionVal l (Just e'), b)+r x y (Rec l es) = do+ (es',b) <- unzip . map (\(n,(eϵ,b)) -> ((n,eϵ),b)) <$> traverse (secondM (r x y)) es+ pure (Rec l es', or b)+r x y (Anchor l es) = do+ (es',b) <- unzip <$> traverse (r x y) es+ pure (Anchor l es', or b)+r x y (Arr l es) = do+ (es',b) <- V.unzip <$> traverse (r x y) es+ pure (Arr l es', or b)+r x y (Paren _ e') = r x y e'+r _ _ e' = pure (e', False)
src/Ty.hs view
@@ -467,9 +467,6 @@ addCM f (Foldable, l) pure (BB ((a ~> a ~> a) ~> ((f':$a) ~> a)) Fold1, s) tyES s (TB _ Bookend) = pure (TB (tyR ~> tyR ~> tyStream tyStr ~> tyStream tyStr) Bookend, s)-tyES s (TB _ BookendG) = do- a <- freshTV "a"- pure (TB ((a~>tyB) ~> (a~>tyB) ~> tyStream a ~> tyStream a) BookendG, s) tyES s (TB _ Captures) = pure (TB (tyStr ~> tyI ~> tyR ~> tyOpt tyStr) Captures, s) tyES s (BB _ Prior) = do a <- freshTV "a"; b <- freshTV "b"
x/Opt.hs view
@@ -17,7 +17,7 @@ data Cmd = TC !FilePath ![FilePath] | Run !FilePath !(Maybe T.Text) !(Maybe T.Text) !(Maybe FilePath) ![FilePath] ![(T.Text, Value)] Bool- | Expr !T.Text !(Maybe FilePath) !(Maybe T.Text) !Bool !Bool !Bool !(Maybe T.Text) ![FilePath] Bool+ | Expr !T.Text !(Maybe FilePath) !(Maybe T.Text) !Bool !Bool !Bool !(Maybe T.Text) ![FilePath] ![(T.Text, Value)] Bool | Eval !T.Text | Install @@ -93,7 +93,7 @@ where tcP = TC <$> j'File <*> incls; eP = Eval <$> jacExpr runP = Run <$> j'File <*> jacFs <*> jacRs <*> inpFile <*> incls <*> defVar <*> begin- exprP = Expr <$> jacExpr <*> inpFile <*> jacFs <*> asv <*> usv <*> csv <*> jacRs <*> incls <*> begin+ exprP = Expr <$> jacExpr <*> inpFile <*> jacFs <*> asv <*> usv <*> csv <*> jacRs <*> incls <*> defVar <*> begin incls :: Parser [FilePath] incls = many $ strOption@@ -130,12 +130,12 @@ run :: Cmd -> IO () run (TC fp is) = tcIO is fp =<< TIO.readFile fp-run (Run fp fs rs Nothing is vs h) = do { contents <- TIO.readFile fp ; runStdin is (Just fp) contents vs (AWK fs rs h) }-run (Run fp fs rs (Just dat) is vs h) = do { contents <- TIO.readFile fp ; runOnFile is (Just fp) contents vs (AWK fs rs h) dat stdout }-run (Expr eb f fs a u c rs is h) =+run (Run fp fs rs Nothing is vs h) = do {contents <- TIO.readFile fp ; runStdin is (Just fp) contents vs (AWK fs rs h)}+run (Run fp fs rs (Just dat) is vs h) = do {contents <- TIO.readFile fp ; runOnFile is (Just fp) contents vs (AWK fs rs h) dat stdout}+run (Expr eb f fs a u c rs is vs h) = case f of- Nothing -> runStdin is Nothing eb [] (m h)- Just fp -> runOnFile is Nothing eb [] (m h) fp stdout+ Nothing -> runStdin is Nothing eb vs (m h)+ Just fp -> runOnFile is Nothing eb vs (m h) fp stdout where m = ap a u c fs rs run (Eval e) = print (exprEval e)