[project @ 2003-09-04 11:08:46 by simonmar]
authorsimonmar <unknown>
Thu, 4 Sep 2003 11:08:48 +0000 (11:08 +0000)
committersimonmar <unknown>
Thu, 4 Sep 2003 11:08:48 +0000 (11:08 +0000)
Add a new command-line flag -e EXPR, which runs ghc in interactive
mode and evaluates EXPR only before exiting.

Also, the lexer now ignores lines beginning with "#!".  This is so
that we can use ghc as a scripting language with Unix-style scripts
beginning with

#! /usr/local/bin/ghc -e main

(well, it's not quite that simple, but I'll leave the details for the
more enterprising hackers).

ghc/compiler/ghci/InteractiveUI.hs
ghc/compiler/main/DriverFlags.hs
ghc/compiler/main/DriverState.hs
ghc/compiler/main/Main.hs
ghc/compiler/parser/Lex.lhs

index 257c219..fceb192 100644 (file)
@@ -1,6 +1,6 @@
 {-# OPTIONS -#include "Linker.h" #-}
 -----------------------------------------------------------------------------
--- $Id: InteractiveUI.hs,v 1.158 2003/08/27 12:29:21 simonmar Exp $
+-- $Id: InteractiveUI.hs,v 1.159 2003/09/04 11:08:46 simonmar Exp $
 --
 -- GHC Interactive User Interface
 --
@@ -155,8 +155,8 @@ helpText = "\
 \                         (eg. -v2, -fglasgow-exts, etc.)\n\ 
 \"
 
-interactiveUI :: [FilePath] -> IO ()
-interactiveUI srcs = do
+interactiveUI :: [FilePath] -> Maybe String -> IO ()
+interactiveUI srcs maybe_expr = do
    dflags <- getDynFlags
 
    cmstate <- cmInit Interactive;
@@ -178,7 +178,7 @@ interactiveUI srcs = do
    Readline.initialize
 #endif
 
-   startGHCi (runGHCi srcs dflags) 
+   startGHCi (runGHCi srcs dflags maybe_expr)
        GHCiState{ progname = "<interactive>",
                   args = [],
                   targets = srcs,
@@ -191,8 +191,8 @@ interactiveUI srcs = do
 
    return ()
 
-runGHCi :: [FilePath] -> DynFlags -> GHCi ()
-runGHCi paths dflags = do
+runGHCi :: [FilePath] -> DynFlags -> Maybe String -> GHCi ()
+runGHCi paths dflags maybe_expr = do
   read_dot_files <- io (readIORef v_Read_DotGHCi)
 
   when (read_dot_files) $ do
@@ -234,8 +234,14 @@ runGHCi paths dflags = do
   is_tty <- io (hIsTerminalDevice stdin)
   let show_prompt = verbosity dflags > 0 || is_tty
 
-  -- enter the interactive loop
-  interactiveLoop is_tty show_prompt
+  case maybe_expr of
+       Nothing -> 
+           -- enter the interactive loop
+           interactiveLoop is_tty show_prompt
+       Just expr -> do
+           -- just evaluate the expression we were given
+           runCommand expr
+           return ()
 
   -- and finally, exit
   io $ do when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
index 38210a7..1189f10 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
--- $Id: DriverFlags.hs,v 1.122 2003/08/29 16:00:25 simonmar Exp $
+-- $Id: DriverFlags.hs,v 1.123 2003/09/04 11:08:47 simonmar Exp $
 --
 -- Driver flags
 --
@@ -178,6 +178,7 @@ static_flags =
   ,  ( "-make"         , PassFlag (setMode DoMake))
   ,  ( "-interactive"  , PassFlag (setMode DoInteractive))
   ,  ( "-mk-dll"       , PassFlag (setMode DoMkDLL))
+  ,  ( "e"              , HasArg   (\s -> setMode (DoEval s) "-e"))
 
        -- -fno-code says to stop after Hsc but don't generate any code.
   ,  ( "fno-code"      , PassFlag (\f -> do setMode (StopBefore HCc) f
index 7c01e32..e8f83a2 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
--- $Id: DriverState.hs,v 1.95 2003/08/20 18:48:20 sof Exp $
+-- $Id: DriverState.hs,v 1.96 2003/09/04 11:08:47 simonmar Exp $
 --
 -- Settings for the driver
 --
@@ -47,6 +47,7 @@ data GhcMode
   | DoMake                             -- ghc --make
   | DoInteractive                      -- ghc --interactive
   | DoLink                             -- [ the default ]
+  | DoEval String                      -- ghc -e
   deriving (Eq,Show)
 
 GLOBAL_VAR(v_GhcMode,     DoLink, GhcMode)
index 7da0074..5c66a92 100644 (file)
@@ -1,7 +1,7 @@
 {-# OPTIONS -fno-warn-incomplete-patterns -optc-DNON_POSIX_SOURCE #-}
 
 -----------------------------------------------------------------------------
--- $Id: Main.hs,v 1.131 2003/07/21 15:14:18 ross Exp $
+-- $Id: Main.hs,v 1.132 2003/09/04 11:08:47 simonmar Exp $
 --
 -- GHC Driver program
 --
@@ -142,11 +142,11 @@ main =
        -- -O and --interactive are not a good combination
        -- ditto with any kind of way selection
    orig_opt_level <- readIORef v_OptLevel
-   when (orig_opt_level > 0 && mode == DoInteractive) $
+   when (orig_opt_level > 0 && isInteractive mode) $
       do putStr "warning: -O conflicts with --interactive; -O turned off.\n"
          writeIORef v_OptLevel 0
    orig_ways <- readIORef v_Ways
-   when (notNull orig_ways && mode == DoInteractive) $
+   when (notNull orig_ways && isInteractive mode) $
       do throwDyn (UsageError 
                    "--interactive can't be used with -prof, -ticky, -unreg or -smp.")
 
@@ -177,6 +177,7 @@ main =
    build_tag <- readIORef v_Build_tag
    let lang = case mode of 
                 DoInteractive  -> HscInterpreted
+                DoEval _       -> HscInterpreted
                 _other | build_tag /= "" -> HscC
                        | otherwise       -> hscLang dyn_flags
                -- for ways other that the normal way, we must 
@@ -187,7 +188,9 @@ main =
                           hscLang  = lang,
                           -- leave out hscOutName for now
                           hscOutName = panic "Main.main:hscOutName not set",
-                          verbosity = 1
+                          verbosity = case mode of
+                                        DoEval _ -> 0
+                                        _other   -> 1
                        })
 
        -- The rest of the arguments are "dynamic"
@@ -255,9 +258,13 @@ main =
                                    (staticLink o_files def_hs_pkgs) }
 
 #ifndef GHCI
-       DoInteractive -> throwDyn (CmdLineError "not built for interactive use")
+       DoInteractive -> noInteractiveError
+       DoEval _      -> noInteractiveError
+     where
+       noInteractiveError = throwDyn (CmdLineError "not built for interactive use")
 #else
-       DoInteractive -> interactiveUI srcs
+       DoInteractive -> interactiveUI srcs Nothing
+       DoEval expr   -> interactiveUI srcs (Just expr)
 #endif
 
 -- -----------------------------------------------------------------------------
@@ -273,7 +280,7 @@ checkOptions mode srcs objs = do
        -- -ohi sanity check
    ohi <- readIORef v_Output_hi
    if (isJust ohi && 
-      (mode == DoMake || mode == DoInteractive || srcs `lengthExceeds` 1))
+      (mode == DoMake || isInteractive mode || srcs `lengthExceeds` 1))
        then throwDyn (UsageError "-ohi can only be used when compiling a single source file")
        else do
 
@@ -285,13 +292,16 @@ checkOptions mode srcs objs = do
 
        -- Check that there are some input files (except in the interactive 
        -- case)
-   if null srcs && null objs && mode /= DoInteractive
+   if null srcs && null objs && not (isInteractive mode)
        then throwDyn (UsageError "no input files")
        else do
 
      -- Verify that output files point somewhere sensible.
    verifyOutputFiles
 
+isInteractive DoInteractive = True
+isInteractive (DoEval _)    = True
+isInteractive _             = False
 
 -- -----------------------------------------------------------------------------
 -- Compile files in one-shot mode.
index d559150..5be189c 100644 (file)
@@ -441,6 +441,13 @@ lexer cont buf s@(PState{
 
                -- special GHC extension: we grok cpp-style #line pragmas
            '#'# | lexemeIndex buf ==# bol ->   -- the '#' must be in column 0
+               -- SPECIAL CASE: if we see "#!" at the beginning of the line,
+               -- we ignore the rest of the line.  This is for script-files
+               -- on Unix which begin with the special syntax "#! /bin/sh", 
+               -- for example.
+               if lookAhead# buf 1# `eqChar#` '!'#
+                  then next_line (stepOnBy# buf 2#) s'
+                  else
                let buf1 | lookAhead# buf 1# `eqChar#` 'l'# &&
                           lookAhead# buf 2# `eqChar#` 'i'# &&
                           lookAhead# buf 3# `eqChar#` 'n'# &&