Skip to content

Commit

Permalink
Get static HTML pages working with the hover-info goodness
Browse files Browse the repository at this point in the history
  • Loading branch information
dougalm committed Jan 5, 2024
1 parent a7d5c6f commit 6dc735f
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 223 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ To learn more, check out our
our [tutorial](https://google-research.github.io/dex-lang/examples/tutorial.html)
or these example programs:

* [Dex prelude](https://google-research.github.io/dex-lang/prelude.html)
* [Dex prelude](https://google-research.github.io/dex-lang/lib/prelude.html)
* [Mandelbrot set](https://google-research.github.io/dex-lang/examples/mandelbrot.html)
* [Ray tracer](https://google-research.github.io/dex-lang/examples/raytrace.html)
* [Estimating pi](https://google-research.github.io/dex-lang/examples/pi.html)
Expand Down
21 changes: 6 additions & 15 deletions dex.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ license-file: LICENSE
build-type: Simple

data-files: lib/*.dx
, static/*.css
, static/*.html
, static/*.js
, static/dynamic.html
, static/index.js
, static/style.css
, src/lib/dexrt.bc

flag cuda
Expand All @@ -27,10 +27,6 @@ flag optimized
description: Enables GHC optimizations
default: False

flag live
description: Enables live-editing environments (web notebook and terminal)
default: True

flag llvm-head
description: Use the bleeding-edge version of LLVM
default: False
Expand Down Expand Up @@ -99,8 +95,7 @@ library
, QueryTypePure
, Util
, Vectorize
if flag(live)
exposed-modules: Actor
, Actor
, Live.Eval
, Live.Web
, RenderHtml
Expand Down Expand Up @@ -136,16 +131,13 @@ library
, time
-- Floating-point pedanticness (correcting for GHC < 9.2.2)
, floating-bits
if flag(live)
build-depends: binary
, binary
, blaze-html
, blaze-markup
, cmark
, http-types
, wai
, warp
cpp-options: -DDEX_LIVE
cxx-options: -DDEX_LIVE
if flag(debug)
cpp-options: -DDEX_DEBUG
default-language: Haskell2010
Expand Down Expand Up @@ -252,6 +244,7 @@ executable dex
ghc-options: -threaded
-optP-Wno-nonportable-include-path
-rtsopts
-Wall
"-with-rtsopts=-I0 -A16m"
default-extensions: CPP
, DeriveGeneric
Expand All @@ -260,8 +253,6 @@ executable dex
, BlockArguments
if flag(cuda)
cpp-options: -DDEX_CUDA
if flag(live)
cpp-options: -DDEX_LIVE
if flag(optimized)
ghc-options: -O3
else
Expand Down
18 changes: 12 additions & 6 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ bench-summary:
# --- building docs ---

slow-pages = pages/examples/mnist-nearest-neighbors.html
static-names = dynamic.html index.js style.css

doc-files = $(doc-names:%=doc/%.dx)
pages-doc-files = $(doc-names:%=pages/%.html)
Expand All @@ -420,30 +421,35 @@ pages-example-files = $(example-names:%=pages/examples/%.html)

lib-files = $(filter-out lib/prelude.dx,$(wildcard lib/*.dx))
pages-lib-files = $(patsubst %.dx,pages/%.html,$(lib-files))
static-files = $(static-names:%=pages/static/%)

docs: pages-prelude $(pages-doc-files) $(pages-example-files) $(pages-lib-files) $(slow-pages) pages/index.md
docs: $(static-files) pages-prelude $(pages-doc-files) $(pages-example-files) $(pages-lib-files) $(slow-pages) pages/index.md

pages/static/%: static/%
mkdir -p pages/static
cp $^ $@

pages-prelude: lib/prelude.dx
mkdir -p pages
$(dex) --prelude /dev/null script lib/prelude.dx --outfmt html > pages/prelude.html
mkdir -p pages/lib
$(dex) --prelude /dev/null generate-html lib/prelude.dx lib/prelude

pages/examples/tutorial.html: tutorial-data
pages/examples/dither.html: dither-data

pages/examples/%.html: examples/%.dx
mkdir -p pages/examples
$(dex) script $< --outfmt html > $@
$(dex) generate-html $< examples/$*

pages/lib/%.html: lib/%.dx
mkdir -p pages/lib
$(dex) script $^ --outfmt html > $@
$(dex) generate-html $^ lib/$*

pages/index.md: $(doc-files) $(example-files) $(lib-files)
python3 misc/build-web-index "$(doc-files)" "$(example-files)" "$(lib-files)" > $@

${pages-doc-files}:pages/%.html: doc/%.dx
mkdir -p pages
$(dex) script $^ --outfmt html > $@
$(dex) generate-html $^ $*

clean:
$(STACK) clean
Expand Down
2 changes: 1 addition & 1 deletion misc/build-web-index
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def main():

print(""); print("## Libraries"); print("")

print("- [lib/prelude.dx](prelude.html): The Dex Prelude (automatically imported)")
print("- [lib/prelude.dx](lib/prelude.html): The Dex Prelude (automatically imported)")

file_block(libraries.split())

Expand Down
129 changes: 45 additions & 84 deletions src/dex.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
-- license that can be found in the LICENSE file or at
-- https://developers.google.com/open-source/licenses/bsd

{-# LANGUAGE RecordWildCards #-}

import System.Console.Haskeline
import System.Exit
import Control.Monad
Expand All @@ -14,88 +12,76 @@ import Options.Applicative hiding (Success, Failure)
import Text.PrettyPrint.ANSI.Leijen (text, hardline)
import System.Posix.Terminal (queryTerminal)
import System.Posix.IO (stdOutput)
import System.IO (openFile, IOMode (..))

import qualified Data.ByteString as BS
import Data.List
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Map.Strict as M
import qualified System.Console.ANSI as ANSI
import System.Console.ANSI hiding (Color)

import TopLevel
import Err
import Name
import AbstractSyntax (parseTopDeclRepl)
import ConcreteSyntax (keyWordStrs, preludeImportBlock)
import RenderHtml
-- import Live.Terminal (runTerminal)
import Live.Web (runWeb)
import Live.Web
import PPrint hiding (hardline)
import Core
import Types.Core
import Types.Imp
import Types.Source
import Types.Top
import MonadUtil
import Util (readFileText)

data DocFmt = ResultOnly
| TextDoc
| JSONDoc
#ifdef DEX_LIVE
| HTMLDoc
#endif
data EvalMode = ReplMode String
| ScriptMode FilePath DocFmt ErrorHandling
| ExportMode FilePath FilePath -- Dex path, .o path
| ClearCache
#ifdef DEX_LIVE

data EvalMode = ReplMode
| ScriptMode FilePath DocFmt
| WebMode FilePath
| WatchMode FilePath
#endif
| GenerateHTML FilePath FilePath
| ClearCache

data CmdOpts = CmdOpts EvalMode EvalConfig

runMode :: EvalMode -> EvalConfig -> IO ()
runMode evalMode cfg = case evalMode of
ScriptMode fname fmt onErr -> do
runMode :: CmdOpts -> IO ()
runMode (CmdOpts evalMode cfg) = case evalMode of
ScriptMode fname fmt -> do
env <- loadCache
((), finalEnv) <- runTopperM cfg env do
source <- liftIO $ T.decodeUtf8 <$> BS.readFile fname
evalSourceText source $ printIncrementalSource fmt
((), finalEnv) <- runTopperM cfg stdOutLogger env do
blocks <- parseSourceBlocks <$> readFileText fname
forM_ blocks \block -> do
case fmt of
ResultOnly -> return ()
TextDoc -> liftIO $ putStr $ pprint block
evalSourceBlockRepl block
storeCache finalEnv
ReplMode prompt -> do
ReplMode -> do
env <- loadCache
void $ runTopperM cfg env do
void $ runTopperM cfg stdOutLogger env do
void $ evalSourceBlockRepl preludeImportBlock
forever do
block <- readSourceBlock prompt
block <- readSourceBlock
void $ evalSourceBlockRepl block
ClearCache -> clearCache
#ifdef DEX_LIVE
WebMode fname -> do
env <- loadCache
runWeb fname cfg env
WatchMode _ -> error "not implemented"
#endif

printIncrementalSource :: DocFmt -> SourceBlock -> IO ()
printIncrementalSource fmt sb = case fmt of
ResultOnly -> return ()
JSONDoc -> return ()
TextDoc -> putStr $ pprint sb
#ifdef DEX_LIVE
HTMLDoc -> return ()
#endif

readSourceBlock :: (MonadIO (m n), EnvReader m) => String -> m n SourceBlock
readSourceBlock prompt = do
GenerateHTML fname dest -> do
env <- loadCache
generateHTML fname dest cfg env
ClearCache -> clearCache

stdOutLogger :: Outputs -> IO ()
stdOutLogger (Outputs outs) = do
isatty <- queryTerminal stdOutput
forM_ outs \out -> putStr $ printOutput isatty out

readSourceBlock :: (MonadIO (m n), EnvReader m) => m n SourceBlock
readSourceBlock = do
sourceMap <- withEnv $ envSourceMap . moduleEnv
let filenameAndDexCompletions =
completeQuotedWord (Just '\\') "\"'" listFiles (dexCompletions sourceMap)
let hasklineSettings = setComplete filenameAndDexCompletions defaultSettings
liftIO $ runInputT hasklineSettings $ readMultiline prompt (parseTopDeclRepl . T.pack)
where prompt = ">=> "

dexCompletions :: Monad m => SourceMap n -> CompletionFunc m
dexCompletions sourceMap (line, _) = do
Expand Down Expand Up @@ -133,31 +119,18 @@ helpOption optionName options =

parseMode :: Parser EvalMode
parseMode = subparser $
command "repl" (simpleInfo
(ReplMode <$> strOption (long "prompt" <> value ">=> "
<> metavar "STRING" <> help "REPL prompt")))
#ifdef DEX_LIVE
command "repl" (simpleInfo (pure ReplMode))
<> command "web" (simpleInfo (WebMode <$> sourceFileInfo))
<> command "watch" (simpleInfo (WatchMode <$> sourceFileInfo))
#endif
<> command "generate-html" (simpleInfo (GenerateHTML <$> sourceFileInfo <*> destFileInfo))
<> command "clean" (simpleInfo (pure ClearCache))
<> command "export" (simpleInfo (ExportMode <$> sourceFileInfo <*> objectFileInfo))
<> command "script" (simpleInfo (ScriptMode <$> sourceFileInfo
<*> option
<> command "script" (simpleInfo (ScriptMode <$> sourceFileInfo <*> option
(optionList [ ("literate" , TextDoc)
, ("result-only", ResultOnly)
#ifdef DEX_LIVE
, ("html" , HTMLDoc)
#endif
, ("json" , JSONDoc)])
, ("result-only", ResultOnly)])
(long "outfmt" <> value TextDoc <>
helpOption "Output format" "literate (default) | result-only | html | json")
<*> flag ContinueOnErr HaltOnErr (
long "stop-on-error"
<> help "Stop program evaluation when an error occurs (type or runtime)")))
helpOption "Output format" "literate (default) | result-only | html | json")))
where
sourceFileInfo = argument str (metavar "FILE" <> help "Source program")
objectFileInfo = argument str (metavar "OBJFILE" <> help "Output path (.o file)")
sourceFileInfo = argument str (metavar "FILE" <> help "Source program")
destFileInfo = argument str (metavar "OUTFILE" <> help "Output path")

optionList :: [(String, a)] -> ReadM a
optionList opts = eitherReader \s -> case lookup s opts of
Expand All @@ -178,11 +151,7 @@ parseEvalOpts = EvalConfig
<*> optional (strOption $ long "prelude" <> metavar "FILE" <> help "Prelude file")
<*> flag NoOptimize Optimize (short 'O' <> help "Optimize generated code")
<*> enumOption "print" "Print backend" PrintCodegen printBackends
<*> flag ContinueOnErr HaltOnErr (
long "stop-on-error"
<> help "Stop program evaluation when an error occurs (type or runtime)")
<*> enumOption "loglevel" "Log level" NormalLogLevel logLevels
<*> pure stdOutLogger
where
printBackends = [ ("haskell", PrintHaskell)
, ("dex" , PrintCodegen) ]
Expand All @@ -191,43 +160,35 @@ parseEvalOpts = EvalConfig
logLevels = [ ("normal", NormalLogLevel)
, ("debug" , DebugLogLevel ) ]

stdOutLogger :: Outputs -> IO ()
stdOutLogger (Outputs outs) = do
isatty <- queryTerminal stdOutput
forM_ outs \out -> putStr $ printOutput isatty out

printOutput :: Bool -> Output -> String
printOutput isatty out = case out of
Error _ -> addColor isatty Red $ addPrefix ">" $ pprint out
_ -> addPrefix (addColor isatty Cyan ">") $ pprint $ out

addPrefix :: String -> String -> String
addPrefix prefix str = unlines $ map prefixLine $ lines str
addPrefix prefix s = unlines $ map prefixLine $ lines s
where prefixLine :: String -> String
prefixLine s = case s of "" -> prefix
_ -> prefix ++ " " ++ s
prefixLine l = case l of "" -> prefix
_ -> prefix ++ " " ++ l

addColor :: Bool -> ANSI.Color -> String -> String
addColor False _ s = s
addColor True c s =
setSGRCode [SetConsoleIntensity BoldIntensity, SetColor Foreground Vivid c]
++ s ++ setSGRCode [Reset]


pathOption :: ReadM [LibPath]
pathOption = splitPaths [] <$> str
where
splitPaths :: [LibPath] -> String -> [LibPath]
splitPaths revAcc = \case
[] -> reverse revAcc
str -> let (p,t) = break (==':') str in
s -> let (p,t) = break (==':') s in
splitPaths (parseLibPath p:revAcc) (dropWhile (==':') t)

parseLibPath = \case
"BUILTIN_LIBRARIES" -> LibBuiltinPath
path -> LibDirectory path

main :: IO ()
main = do
CmdOpts evalMode opts <- execParser parseOpts
runMode evalMode opts
main = execParser parseOpts >>= runMode
Loading

0 comments on commit 6dc735f

Please sign in to comment.