Commit fc260a46 authored by Andrew Gibiansky's avatar Andrew Gibiansky

fixing several issues that broke blaze-html integration

parent 8b0aa538
......@@ -24,8 +24,18 @@
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": "*"
"outputs": [
{
"metadata": {},
"output_type": "display_data",
"text": [
"X 20\n",
"Y \"Test\"\n",
"Z 0.5"
]
}
],
"prompt_number": 1
},
{
"cell_type": "code",
......@@ -38,27 +48,19 @@
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data",
"text": [
"1\n"
"1"
]
},
{
"metadata": {},
"output_type": "display_data",
"text": [
"Just 13\n"
"Just 13"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 2
......@@ -75,10 +77,6 @@
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data",
......@@ -87,12 +85,8 @@
"4\n",
"9\n",
"16\n",
"[-1,-2,-3,-4]\n"
"[-1,-2,-3,-4]"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 3
......@@ -109,10 +103,14 @@
"outputs": [
{
"html": [
"<span style='color: red; font-style: italic;'>Failed to load interface for `Lkjadflkjad'<br/></span>"
"<span style='color: red; font-style: italic;'>Failed to load interface for `Lkjadflkjad'</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"Failed to load interface for `Lkjadflkjad'\n",
"Use -v to see a list of the files searched for."
]
}
],
"prompt_number": 4
......@@ -129,10 +127,14 @@
"outputs": [
{
"html": [
"<span style='color: red; font-style: italic;'>Not in scope: `abc'<br/>Perhaps you meant `abs' (imported from Prelude)<br/></span>"
"<span style='color: red; font-style: italic;'>Not in scope: `abc'<br/>Perhaps you meant `abs' (imported from Prelude)</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"Not in scope: `abc'\n",
"Perhaps you meant `abs' (imported from Prelude)"
]
}
],
"prompt_number": 5
......@@ -146,16 +148,7 @@
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"prompt_number": 6
},
{
......@@ -167,16 +160,7 @@
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"prompt_number": 7
},
{
......@@ -192,12 +176,8 @@
"metadata": {},
"output_type": "display_data",
"text": [
"3\n"
"3"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 8
......@@ -206,17 +186,25 @@
"cell_type": "code",
"collapsed": false,
"input": [
"it11"
"data X = Y Int\n",
"return (Y 3)\n",
"Y 3"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<span style='color: red; font-style: italic;'>Not in scope: `it11'<br/>Perhaps you meant `it1' (line 1)<br/></span>"
"<span style='color: red; font-style: italic;'>No instance for (Show X)<br/> arising from a use of `print'<br/>Possible fix:<br/> add an instance declaration for (Show X)</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"No instance for (GHC.Show.Show :Interactive.X)\n",
" arising from a use of `System.IO.print'\n",
"Possible fix:\n",
" add an instance declaration for (GHC.Show.Show :Interactive.X)"
]
}
],
"prompt_number": 9
......@@ -234,12 +222,8 @@
"metadata": {},
"output_type": "display_data",
"text": [
"2\n"
"2"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 10
......@@ -252,16 +236,7 @@
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"prompt_number": 11
},
{
......@@ -277,12 +252,8 @@
"metadata": {},
"output_type": "display_data",
"text": [
"Y 3\n"
"Y 3"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 12
......@@ -295,16 +266,7 @@
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"prompt_number": 13
},
{
......@@ -318,10 +280,13 @@
"outputs": [
{
"html": [
"<span style='color: red; font-style: italic;'><interactive>:1:1-12: Non-exhaustive patterns in function test<br/></span>"
"<span style='color: red; font-style: italic;'><interactive>:1:1-12: Non-exhaustive patterns in function test</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"<interactive>:1:1-12: Non-exhaustive patterns in function test"
]
}
],
"prompt_number": 14
......@@ -340,11 +305,10 @@
"<span style='color: red; font-style: italic;'>Parse error (line 1, column 1): Unknown directive: 'tadaf'.</span>"
],
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"Parse error (line 1, column 1): Unknown directive: 'tadaf'."
]
}
],
"prompt_number": 15
......@@ -361,20 +325,12 @@
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data",
"text": [
"11\n"
"11"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 16
......@@ -387,16 +343,7 @@
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"prompt_number": 17
},
{
......@@ -414,12 +361,8 @@
"metadata": {},
"output_type": "display_data",
"text": [
"21\n"
"21"
]
},
{
"metadata": {},
"output_type": "display_data"
}
],
"prompt_number": 18
......@@ -431,85 +374,244 @@
"let x = 3\n",
"let y =10\n",
"let z = 100\n",
"print 3"
"print 3\n",
"import Control.Monad"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
},
"output_type": "display_data",
"text": [
"3"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import Text.Blaze.Html4.Strict hiding (map)\n",
"import Text.Blaze.Html4.Strict.Attributes\n",
"import Control.Monad\n",
"div ! Text.Blaze.Html4.Strict.Attributes.style \"color: red\" $ do\n",
" p \"This is an example of BlazeMarkup syntax.\"\n",
" p \"Hello\"\n",
" b \"Hello\"\n",
" img ! src \"/static/base/images/ipynblogo.png\" ! width \"200\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<div style=\"color: red\">\n",
" <p>\n",
" This is an example of BlazeMarkup syntax.\n",
" </p>\n",
" <p>\n",
" Hello\n",
" </p>\n",
" <b>\n",
" Hello\n",
" </b>\n",
" <img src=\"/static/base/images/ipynblogo.png\" width=\"200\">\n",
"</div>\n"
],
"metadata": {},
"output_type": "display_data"
},
"output_type": "display_data",
"text": [
"<div style=\"color: red\">\n",
" <p>\n",
" This is an example of BlazeMarkup syntax.\n",
" </p>\n",
" <p>\n",
" Hello\n",
" </p>\n",
" <b>\n",
" Hello\n",
" </b>\n",
" <img src=\"/static/base/images/ipynblogo.png\" width=\"200\">\n",
"</div>"
]
}
],
"prompt_number": 40
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"forM_ [100, 200, 300, 400, 500, 600, 700, 800] $ \\size -> do\n",
" let s = show size\n",
" img ! src \"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" ! width (toValue s)\n",
":t y\n",
"y"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"100\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"200\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"300\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"400\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"500\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"600\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"700\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"800\">\n"
],
"metadata": {},
"output_type": "display_data",
"text": [
"3\n"
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"100\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"200\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"300\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"400\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"500\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"600\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"700\">\n",
"<img src=\"http://127.0.0.1:8693/static/base/images/ipynblogo.png\" width=\"800\">"
]
},
{
"html": [
"<span style='color: red; font-style: italic;'>Not in scope: `y'</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"Not in scope: `y'"
]
}
],
"prompt_number": 19
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import Control.Monad\n",
"import Control.Monad\n",
"print 3"
"let y = forM (map (* 10) [1..40]) $ \\size -> do\n",
" let s = show size\n",
" Text.Blaze.Html4.Strict.div ! Text.Blaze.Html4.Strict.style \"bar\" $ \"Hello.\"\n",
" img ! src \"http://127.0.0.1:8800/static/base/images/ipynblogo.png\" ! width (toValue s)\n",
"y"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<span style='color: red; font-style: italic;'>Couldn't match type `Text.Blaze.Internal.MarkupM ()'<br/> with `Text.Blaze.Internal.Attribute'<br/>Expected type: Text.Blaze.Internal.Attribute<br/> Actual type: Text.Blaze.Html.Html</span>"
],
"metadata": {},
"output_type": "display_data"
},
{
"metadata": {},
"output_type": "display_data"
},
"output_type": "display_data",
"text": [
"Couldn't match type `Text.Blaze.Internal.MarkupM ()'\n",
" with `Text.Blaze.Internal.Attribute'\n",
"Expected type: Text.Blaze.Internal.Attribute\n",
" Actual type: Text.Blaze.Html.Html"
]
}
],
"prompt_number": 25
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import Prelude hiding (head, id, div)\n",
"import Text.Blaze.Html4.Strict hiding (map)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 34
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"data X = Y Int\n",
"Y 3"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<span style='color: red; font-style: italic;'>No instance for (Show X)<br/> arising from a use of `print'<br/>Possible fix:<br/> add an instance declaration for (Show X)</span>"
],
"metadata": {},
"output_type": "display_data",
"text": [
"3\n"
"No instance for (GHC.Show.Show :Interactive.X)\n",
" arising from a use of `System.IO.print'\n",
"Possible fix:\n",
" add an instance declaration for (GHC.Show.Show :Interactive.X)"
]
},
}
],
"prompt_number": 58
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"forM [1] $ \\x -> return (Y x)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 59
},
{
"cell_type": "code",
"collapsed": false,
"input": [
":t forM [1] $ \\x -> return (Y x)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<span style='font-weight: bold; color: green;'>forall (m :: * -> *). Monad m => m [X]</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"forall (m :: * -> *). Monad m => m [X]"
]
}
],
"prompt_number": 20
"prompt_number": 60
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\""
":t (Y 3)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"html": [
"<span style='font-weight: bold; color: green;'>X</span>"
],
"metadata": {},
"output_type": "display_data"
"output_type": "display_data",
"text": [
"X"
]
}
],
"prompt_number": 21
"prompt_number": 61
},
{
"cell_type": "code",
......
......@@ -53,7 +53,7 @@ becomes string expected = do
forM_ (zip results expected) $ \(result, expected) ->
case find isPlain result of
Just (Display PlainText str) -> expected `shouldBe` str
Just (Display PlainText str) -> str `shouldBe` expected
Nothing -> expectationFailure $ "No plain-text output in " ++ show result
......@@ -100,6 +100,14 @@ evalTests = do
print (Y 3 == Z "No")
|] `becomes` ["[Y 3,Z \"No\"]", "False"]
it "evaluates do blocks in expressions" $ do
[hereLit|
show (show (do
Just 10
Nothing
Just 100))
|] `becomes` ["\"\\\"Nothing\\\"\""]
it "is silent for imports" $ do
"import Control.Monad" `becomes` []
"import qualified Control.Monad" `becomes` []
......@@ -228,13 +236,13 @@ parseStringTests = describe "Parser" $ do
it "parses a <- stmt followed by let stmt" $
parses "y <- do print 'no'\nlet x = expr" `like` [
Statement "y <- do { print 'no' }",
Statement "y <- do print 'no'",
Statement "let x = expr"
]
it "parses <- followed by let followed by expr" $
parses "y <- do print 'no'\nlet x = expr\nexpression" `like` [
Statement "y <- do { print 'no' }",
Statement "y <- do print 'no'",
Statement "let x = expr",
Expression "expression"
]
......@@ -288,3 +296,15 @@ parseStringTests = describe "Parser" $ do
Import "import X",
Expression "print 3"
]
it "doesn't break on long strings" $ do
let longString = concat $ replicate 20 "hello "
("img ! src \"" ++ longString ++ "\" ! width \"500\"") `is` Expression
it "parses do blocks in expression" $ do
[hereLit|
show (show (do
Just 10
Nothing
Just 100))
|] `is` Expression
......@@ -50,7 +50,7 @@ import IHaskell.Display
data ErrorOccurred = Success | Failure deriving Show
debug :: Bool
debug = False
debug = True
ignoreTypePrefixes :: [String]
ignoreTypePrefixes = ["GHC.Types", "GHC.Base", "GHC.Show", "System.IO",
......@@ -394,35 +394,23 @@ evalCommand (Expression expr) = do
-- The output is bound to 'it', so we can then use it.
(success, out) <- evalCommand (Statement expr)
-- Try to use `display` to convert our type into the output
-- DisplayData. If typechecking fails and there is no appropriate
-- typeclass, this will throw an exception and thus `attempt` will
-- return False, and we just resort to plaintext.
let displayExpr = printf "(IHaskell.Display.display (%s))" expr
canRunDisplay <- attempt $ exprType displayExpr
write displayExpr
-- If evaluation failed, return the failure. If it was successful, we
-- may be able to use the IHaskellDisplay typeclass.
case success of
Failure -> return (success, out)
Success -> do
-- Try to use `display` to convert our type into the output
-- DisplayData. If typechecking fails and there is no appropriate
-- typeclass, this will throw an exception and thus `attempt` will
-- return False, and we just resort to plaintext.
canRunDisplay <- attempt $ exprType "IHaskell.Display.display it"
if canRunDisplay
then do
-- If there are instance matches, convert the object into
-- a [DisplayData]. We also serialize it into a bytestring. We get
-- the bytestring as a dynamic and then convert back to
-- a bytestring, which we promptly unserialize. Note that
-- attempting to do this without the serialization to binary and
-- back gives very strange errors - all the types match but it
-- refuses to decode back into a [DisplayData].
displayedBytestring <- dynCompileExpr "IHaskell.Display.serializeDisplay (IHaskell.Display.display it)"
case fromDynamic displayedBytestring of
Nothing -> error "Expecting lazy Bytestring"
Just bytestring ->
case Serialize.decode bytestring of
Left err -> error err
Right displayData -> do
write $ show displayData
return (success, displayData)
else return (success, out)
if not canRunDisplay
then return (success, out)
else case success of
Success -> useDisplay displayExpr
Failure -> if isShowError out
then useDisplay displayExpr
else return (success, out)
where
-- Try to evaluate an action. Return True if it succeeds and False if
......@@ -432,6 +420,35 @@ evalCommand (Expression expr) = do
where failure :: SomeException -> Interpreter Bool
failure _ = return False
-- Check if the error is due to trying to print something that doesn't
-- implement the Show typeclass.
isShowError errs = case find isPlain errs of
Just (Display PlainText msg) ->
startswith "No instance for (GHC.Show.Show " msg &&
isInfixOf " arising from a use of `System.IO.print'" msg
Nothing -> False
where isPlain (Display mime _) = (mime == PlainText)
useDisplay displayExpr = wrapExecution $ do
-- If there are instance matches, convert the object into
-- a [DisplayData]. We also serialize it into a bytestring. We get
-- the bytestring as a dynamic and then convert back to
-- a bytestring, which we promptly unserialize. Note that
-- attempting to do this without the serialization to binary and
-- back gives very strange errors - all the types match but it
-- refuses to decode back into a [DisplayData].
runStmt displayExpr RunToCompletion
displayedBytestring <- dynCompileExpr "IHaskell.Display.serializeDisplay it"
case fromDynamic displayedBytestring of
Nothing -> error "Expecting lazy Bytestring"
Just bytestring ->
case Serialize.decode bytestring of
Left err -> error err
Right displayData -> do
write $ show displayData
return displayData
evalCommand (Declaration decl) = wrapExecution $ runDecls decl >> return []
evalCommand (ParseError loc err) = wrapExecution $
......
......@@ -173,22 +173,16 @@ parseCodeChunk code startLine = do
parsers :: DynFlags -> [(String -> CodeBlock, String -> ParseOutput String)]
parsers flags =
[ (Import, unparser toCode partialImport)
, (TypeSignature, unparser toCode partialTypeSignature)
, (Declaration, unparser listCode partialDeclaration)
, (Statement, unparser toCode partialStatement)
[ (Import, unparser partialImport)
, (TypeSignature, unparser partialTypeSignature)
, (Declaration, unparser partialDeclaration)
, (Statement, unparser partialStatement)
]
where
toCode :: Outputable a => a -> String
toCode = strip . showSDoc flags . ppr
listCode :: Outputable a => OrdList a -> String
listCode = joinLines . map toCode . fromOL
unparser :: (a -> String) -> P a -> String -> ParseOutput String
unparser postprocess parser code =
unparser :: P a -> String -> ParseOutput String
unparser parser code =
case runParser flags parser code of
Success out strs -> Success (postprocess out) strs
Success out strs -> Success code strs
Failure err loc -> Failure err loc
-- | Find consecutive declarations of the same function and join them into
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment