Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
gargantext-ihaskell
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
gargantext-ihaskell
Commits
e97b7019
Commit
e97b7019
authored
Mar 05, 2017
by
Andrei Barbu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Apply #686
parent
00478f3b
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
165 additions
and
37 deletions
+165
-37
ghc-parser.cabal
ghc-parser/ghc-parser.cabal
+6
-3
HappyParser.hs
ghc-parser/src-8.0/Language/Haskell/GHC/HappyParser.hs
+42
-0
ihaskell-aeson.cabal
ihaskell-display/ihaskell-aeson/ihaskell-aeson.cabal
+1
-1
ihaskell-diagrams.cabal
ihaskell-display/ihaskell-diagrams/ihaskell-diagrams.cabal
+1
-1
ihaskell-gnuplot.cabal
ihaskell-display/ihaskell-gnuplot/ihaskell-gnuplot.cabal
+1
-1
ihaskell-hatex.cabal
ihaskell-display/ihaskell-hatex/ihaskell-hatex.cabal
+1
-1
ihaskell-magic.cabal
ihaskell-display/ihaskell-magic/ihaskell-magic.cabal
+1
-1
ihaskell.cabal
ihaskell.cabal
+5
-2
ipython-kernel.cabal
ipython-kernel/ipython-kernel.cabal
+3
-3
IHaskellPrelude.hs
main/IHaskellPrelude.hs
+3
-1
Main.hs
main/Main.hs
+2
-1
Completion.hs
src/IHaskell/Eval/Completion.hs
+9
-1
Evaluate.hs
src/IHaskell/Eval/Evaluate.hs
+62
-18
Util.hs
src/IHaskell/Eval/Util.hs
+25
-2
IHaskellPrelude.hs
src/IHaskellPrelude.hs
+3
-1
No files found.
ghc-parser/ghc-parser.cabal
View file @
e97b7019
...
...
@@ -33,8 +33,8 @@ library
Language.Haskell.GHC.HappyParser
-- other-modules:
-- other-extensions:
build-depends: base >=4.6 && <4.
9
,
ghc >=7.6 && <
7.1
1
build-depends: base >=4.6 && <4.
10
,
ghc >=7.6 && <
8.
1
if impl(ghc >= 7.6) && impl(ghc < 7.8)
hs-source-dirs: generic-src src-7.6
...
...
@@ -45,6 +45,9 @@ library
if impl(ghc < 7.10)
hs-source-dirs: generic-src src-7.8.3
else
hs-source-dirs: generic-src src-7.10
if impl(ghc < 8.0)
hs-source-dirs: generic-src src-7.10
else
hs-source-dirs: generic-src src-8.0
default-language: Haskell2010
ghc-parser/src-8.0/Language/Haskell/GHC/HappyParser.hs
0 → 100644
View file @
e97b7019
module
Language.Haskell.GHC.HappyParser
(
fullStatement
,
fullImport
,
fullDeclaration
,
fullExpression
,
fullTypeSignature
,
fullModule
)
where
import
Parser
import
SrcLoc
-- compiler/hsSyn
import
HsSyn
-- compiler/utils
import
OrdList
-- compiler/parser
import
RdrHsSyn
import
Lexer
-- compiler/basicTypes
import
RdrName
fullStatement
::
P
(
Maybe
(
LStmt
RdrName
(
LHsExpr
RdrName
)))
fullStatement
=
parseStmt
fullImport
::
P
(
LImportDecl
RdrName
)
fullImport
=
parseImport
fullDeclaration
::
P
(
OrdList
(
LHsDecl
RdrName
))
fullDeclaration
=
fmap
unitOL
parseDeclaration
fullExpression
::
P
(
LHsExpr
RdrName
)
fullExpression
=
parseExpression
fullTypeSignature
::
P
(
Located
(
OrdList
(
LHsDecl
RdrName
)))
fullTypeSignature
=
fmap
(
noLoc
.
unitOL
)
parseTypeSignature
fullModule
::
P
(
Located
(
HsModule
RdrName
))
fullModule
=
parseModule
ihaskell-display/ihaskell-aeson/ihaskell-aeson.cabal
View file @
e97b7019
...
...
@@ -57,7 +57,7 @@ library
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.6 && <4.
9
,
build-depends: base >=4.6 && <4.
10
,
here,
text,
bytestring,
...
...
ihaskell-display/ihaskell-diagrams/ihaskell-diagrams.cabal
View file @
e97b7019
...
...
@@ -58,7 +58,7 @@ library
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.6 && <4.
9
,
build-depends: base >=4.6 && <4.
10
,
text,
bytestring,
directory,
...
...
ihaskell-display/ihaskell-gnuplot/ihaskell-gnuplot.cabal
View file @
e97b7019
...
...
@@ -58,7 +58,7 @@ library
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.6 && <4.
9
,
build-depends: base >=4.6 && <4.
10
,
bytestring,
gnuplot >= 0.5.4,
ihaskell >= 0.6.2
...
...
ihaskell-display/ihaskell-hatex/ihaskell-hatex.cabal
View file @
e97b7019
...
...
@@ -14,7 +14,7 @@ cabal-version: >=1.16
library
exposed-modules: IHaskell.Display.Hatex
build-depends: base >=4.6 && <4.
9
,
build-depends: base >=4.6 && <4.
10
,
text,
HaTeX >= 3.9,
ihaskell >= 0.5
...
...
ihaskell-display/ihaskell-magic/ihaskell-magic.cabal
View file @
e97b7019
...
...
@@ -61,7 +61,7 @@ library
OverloadedStrings
-- Other library packages from which modules are imported.
build-depends: base >=4.6 && <4.
9
,
build-depends: base >=4.6 && <4.
10
,
magic >= 1.0.8,
text,
bytestring,
...
...
ihaskell.cabal
View file @
e97b7019
...
...
@@ -55,7 +55,7 @@ library
default-language: Haskell2010
build-depends:
aeson >=0.7 && < 0.12,
base >=4.6 && < 4.
9
,
base >=4.6 && < 4.
10
,
base64-bytestring >=1.0,
bytestring >=0.10,
cereal >=0.3,
...
...
@@ -91,6 +91,9 @@ library
if flag(binPkgDb)
build-depends: bin-package-db
if impl(ghc >= 8.0)
build-depends: ghc-boot >=8.0 && <8.1
exposed-modules: IHaskell.Display
IHaskell.Convert
IHaskell.Convert.Args
...
...
@@ -137,7 +140,7 @@ executable ihaskell
default-language: Haskell2010
build-depends:
ihaskell -any,
base >=4.6 && < 4.
9
,
base >=4.6 && < 4.
10
,
text >=0.11,
transformers -any,
ghc >=7.6 || < 7.11,
...
...
ipython-kernel/ipython-kernel.cabal
View file @
e97b7019
...
...
@@ -34,7 +34,7 @@ library
other-extensions: OverloadedStrings
hs-source-dirs: src
default-language: Haskell2010
build-depends: base >=4.6 && < 4.
9
,
build-depends: base >=4.6 && < 4.
10
,
aeson >=0.6 && < 0.12,
bytestring >=0.10,
cereal >=0.3,
...
...
@@ -56,7 +56,7 @@ executable simple-calc-example
hs-source-dirs: examples
main-is: Calc.hs
build-depends: ipython-kernel,
base >=4.6 && <4.
9
,
base >=4.6 && <4.
10
,
filepath >=1.2,
mtl >=2.1,
parsec >=3.1,
...
...
@@ -70,7 +70,7 @@ executable fun-calc-example
hs-source-dirs: examples
main-is: Simple.hs
build-depends: ipython-kernel,
base >=4.6 && <4.
9
,
base >=4.6 && <4.
10
,
filepath >=1.2,
mtl >=2.1,
parsec >=3.1,
...
...
main/IHaskellPrelude.hs
View file @
e97b7019
...
...
@@ -78,7 +78,9 @@ import GHC.Enum as X
import
GHC.Num
as
X
import
GHC.Real
as
X
import
GHC.Err
as
X
hiding
(
absentErr
)
#
if
MIN_VERSION_ghc
(
7
,
10
,
0
)
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
import
GHC.Base
as
X
hiding
(
Any
,
mapM
,
foldr
,
sequence
,
many
,
(
<|>
),
Module
(
..
))
#
elif
MIN_VERSION_ghc
(
7
,
10
,
0
)
import
GHC.Base
as
X
hiding
(
Any
,
mapM
,
foldr
,
sequence
,
many
,
(
<|>
))
#
else
import
GHC.Base
as
X
hiding
(
Any
)
...
...
main/Main.hs
View file @
e97b7019
...
...
@@ -128,7 +128,8 @@ runKernel kernelOpts profileSrc = do
useStack
=
kernelSpecUseStack
kernelOpts
-- Parse the profile file.
Just
profile
<-
liftM
decode
$
LBS
.
readFile
profileSrc
let
profileErr
=
error
$
"ihaskell: "
++
profileSrc
++
": Failed to parse profile file"
profile
<-
liftM
(
fromMaybe
profileErr
.
decode
)
$
LBS
.
readFile
profileSrc
-- Necessary for `getLine` and their ilk to work.
dir
<-
getIHaskellDir
...
...
src/IHaskell/Eval/Completion.hs
View file @
e97b7019
...
...
@@ -22,7 +22,7 @@ import qualified Data.ByteString.Char8 as CBS
import
Control.Applicative
((
<$>
))
import
Data.ByteString.UTF8
hiding
(
drop
,
take
,
lines
,
length
)
import
Data.Char
import
Data.List
(
nub
,
init
,
last
,
head
,
elemIndex
)
import
Data.List
(
nub
,
init
,
last
,
head
,
elemIndex
,
concatMap
)
import
qualified
Data.List.Split
as
Split
import
qualified
Data.List.Split.Internals
as
Split
import
Data.Maybe
(
fromJust
)
...
...
@@ -88,7 +88,11 @@ complete code posOffset = do
let
Just
db
=
pkgDatabase
flags
getNames
=
map
(
moduleNameString
.
exposedName
)
.
exposedModules
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
moduleNames
=
nub
$
concatMap
getNames
$
concatMap
snd
db
#
else
moduleNames
=
nub
$
concatMap
getNames
db
#
endif
let
target
=
completionTarget
line
pos
completion
=
completionType
line
pos
target
...
...
@@ -124,7 +128,11 @@ complete code posOffset = do
otherNames
=
[
"-package"
,
"-Wall"
,
"-w"
]
fNames
=
map
extName
fFlags
++
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
map
extName
wWarningFlags
++
#
else
map
extName
fWarningFlags
++
#
endif
map
extName
fLangFlags
fNoNames
=
map
(
"no"
++
)
fNames
fAllNames
=
map
(
"-f"
++
)
(
fNames
++
fNoNames
)
...
...
src/IHaskell/Eval/Evaluate.hs
View file @
e97b7019
...
...
@@ -26,6 +26,7 @@ import qualified Data.ByteString.Lazy as LBS
import
qualified
Data.ByteString.Char8
as
CBS
import
Control.Concurrent
(
forkIO
,
threadDelay
)
import
Data.Foldable
(
foldMap
)
import
Prelude
(
putChar
,
head
,
tail
,
last
,
init
,
(
!!
))
import
Data.List
(
findIndex
,
and
,
foldl1
,
nubBy
)
import
Text.Printf
...
...
@@ -77,7 +78,7 @@ import Module hiding (Module)
import
qualified
Pretty
import
FastString
import
Bag
import
ErrUtils
(
errMsgShortDoc
,
errMsgExtraInfo
)
import
qualified
ErrUtils
import
IHaskell.Types
import
IHaskell.IPython
...
...
@@ -184,13 +185,29 @@ interpret libdir allowedStdin action = runGhc (Just libdir) $ do
-- Run the rest of the interpreter
action
hasSupportLibraries
#
if
MIN_VERSION_ghc
(
7
,
10
,
2
)
packageIdString'
dflags
pkg_key
=
fromMaybe
"(unknown)"
(
packageKeyPackageIdString
dflags
pkg_key
)
packageIdString'
::
DynFlags
->
PackageConfig
->
String
packageIdString'
dflags
pkg_cfg
=
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
fromMaybe
"(unknown)"
(
unitIdPackageIdString
dflags
$
packageConfigId
pkg_cfg
)
#
elif
MIN_VERSION_ghc
(
7
,
10
,
2
)
fromMaybe
"(unknown)"
(
packageKeyPackageIdString
dflags
$
packageConfigId
pkg_cfg
)
#
elif
MIN_VERSION_ghc
(
7
,
10
,
0
)
packageIdString'
dflags
=
packageKeyPackageIdString
dflags
packageKeyPackageIdString
dflags
.
packageConfigId
#
else
packageIdString'
dflags
=
packageIdString
packageIdString
.
packageConfigId
#
endif
getPackageConfigs
::
DynFlags
->
[
PackageConfig
]
getPackageConfigs
dflags
=
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
foldMap
snd
pkgDb
#
else
pkgDb
#
endif
where
Just
pkgDb
=
pkgDatabase
dflags
-- | Initialize our GHC session with imports and a value for 'it'. Return whether the IHaskell
-- support libraries are available.
initializeImports
::
Interpreter
Bool
...
...
@@ -200,19 +217,23 @@ initializeImports = do
dflags
<-
getSessionDynFlags
broken
<-
liftIO
getBrokenPackages
(
dflags
,
_
)
<-
liftIO
$
initPackages
dflags
let
Just
db
=
pkgDatabase
dflags
packageNames
=
map
(
packageIdString'
dflags
.
packageConfigId
)
db
let
db
=
getPackageConfigs
dflags
packageNames
=
map
(
packageIdString'
dflags
)
db
initStr
=
"ihaskell-"
-- Name of the ihaskell package, e.g. "ihaskell-1.2.3.4"
iHaskellPkgName
=
initStr
++
intercalate
"."
(
map
show
(
versionBranch
version
))
#
if
!
MIN_VERSION_ghc
(
8
,
0
,
0
)
unitId
=
packageId
#
endif
dependsOnRight
pkg
=
not
$
null
$
do
pkg
<-
db
depId
<-
depends
pkg
dep
<-
filter
((
==
depId
)
.
installedPackage
Id
)
db
let
idString
=
packageIdString'
dflags
(
packageConfigId
dep
)
dep
<-
filter
((
==
depId
)
.
unit
Id
)
db
let
idString
=
packageIdString'
dflags
dep
guard
(
iHaskellPkgName
`
isPrefixOf
`
idString
)
displayPkgs
=
[
pkgName
...
...
@@ -411,6 +432,14 @@ flushWidgetMessages state evalMsgs widgetHandler = do
let
commMessages
=
evalMsgs
++
messages
widgetHandler
state
commMessages
getErrMsgDoc
::
ErrUtils
.
ErrMsg
->
SDoc
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
getErrMsgDoc
=
ErrUtils
.
pprLocErrMsg
#
else
getErrMsgDoc
msg
=
ErrUtils
.
errMsgShortString
msg
$$
ErrUtils
.
errMsgContext
msg
#
endif
safely
::
KernelState
->
Interpreter
EvalOut
->
Interpreter
EvalOut
safely
state
=
ghandle
handler
.
ghandle
sourceErrorHandler
where
...
...
@@ -428,10 +457,7 @@ safely state = ghandle handler . ghandle sourceErrorHandler
sourceErrorHandler
::
SourceError
->
Interpreter
EvalOut
sourceErrorHandler
srcerr
=
do
let
msgs
=
bagToList
$
srcErrorMessages
srcerr
errStrs
<-
forM
msgs
$
\
msg
->
do
shortStr
<-
doc
$
errMsgShortDoc
msg
contextStr
<-
doc
$
errMsgExtraInfo
msg
return
$
unlines
[
shortStr
,
contextStr
]
errStrs
<-
forM
msgs
$
doc
.
getErrMsgDoc
let
fullErr
=
unlines
errStrs
...
...
@@ -1027,7 +1053,11 @@ doLoadModule name modName = do
setSessionDynFlags
flags
{
hscTarget
=
objTarget
flags
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
,
log_action
=
\
dflags
sev
srcspan
ppr
_style
msg
->
modifyIORef'
errRef
(
showSDoc
flags
msg
:
)
#
else
,
log_action
=
\
dflags
sev
srcspan
ppr
msg
->
modifyIORef'
errRef
(
showSDoc
flags
msg
:
)
#
endif
}
-- Load the new target.
...
...
@@ -1142,7 +1172,6 @@ capturedEval output stmt = do
,
voidpf
"IHaskellIO.closeFd %s"
writeVariable
,
printf
"let it = %s"
itVariable
]
pipeExpr
=
printf
"let %s = %s"
(
var
"pipe_var_"
)
readVariable
goStmt
::
String
->
Ghc
RunResult
goStmt
s
=
runStmt
s
RunToCompletion
...
...
@@ -1156,22 +1185,37 @@ capturedEval output stmt = do
AnyException
e
->
RunException
e
-- Initialize evaluation context.
void
$
forM
initStmts
goStmt
results
<-
forM
initStmts
goStmt
#
if
__GLASGOW_HASKELL__
>=
800
-- This works fine on GHC 8.0 and newer
dyn
<-
dynCompileExpr
readVariable
pipe
<-
case
fromDynamic
dyn
of
Nothing
->
fail
"Evaluate: Bad pipe"
Just
fd
->
liftIO
$
do
handle
<-
fdToHandle
fd
hSetEncoding
handle
utf8
return
handle
#
else
-- Get the pipe to read printed output from. This is effectively the source code of dynCompileExpr
-- from GHC API's InteractiveEval. However, instead of using a `Dynamic` as an intermediary, it just
-- directly reads the value. This is incredibly unsafe! However, for some reason the `getContext`
-- and `setContext` required by dynCompileExpr (to import and clear Data.Dynamic) cause issues with
-- data declarations being updated (e.g. it drops newer versions of data declarations for older ones
-- for unknown reasons). First, compile down to an HValue.
let
pipeExpr
=
printf
"let %s = %s"
(
var
"pipe_var_"
)
readVariable
Just
(
_
,
hValues
,
_
)
<-
withSession
$
liftIO
.
flip
hscStmt
pipeExpr
-- Then convert the HValue into an executable bit, and read the value.
pipe
<-
liftIO
$
do
fd
<-
head
<$>
unsafeCoerce
hValues
fds
<-
unsafeCoerce
hValues
fd
<-
case
fds
of
fd
:
_
->
return
fd
[]
->
fail
"Failed to evaluate pipes"
_
->
fail
$
"Expected one fd, saw "
++
show
(
length
fds
)
handle
<-
fdToHandle
fd
hSetEncoding
handle
utf8
return
handle
#
endif
-- Keep track of whether execution has completed.
completed
<-
liftIO
$
newMVar
False
finishedReading
<-
liftIO
newEmptyMVar
...
...
src/IHaskell/Eval/Util.hs
View file @
e97b7019
...
...
@@ -59,6 +59,12 @@ import Data.List (nubBy)
import
StringUtils
(
replace
)
#
if
MIN_VERSION_ghc
(
8
,
0
,
1
)
import
GHC.LanguageExtensions
type
ExtensionFlag
=
Extension
#
endif
-- | A extension flag that can be set or unset.
data
ExtFlag
=
SetFlag
ExtensionFlag
|
UnsetFlag
ExtensionFlag
...
...
@@ -97,10 +103,16 @@ pprDynFlags show_all dflags =
,
O
.
text
"other dynamic, non-language, flag settings:"
O
.$$
O
.
nest
2
(
O
.
vcat
(
map
(
setting
opt
)
others
))
,
O
.
text
"warning settings:"
O
.$$
O
.
nest
2
(
O
.
vcat
(
map
(
setting
wopt
)
DynFlags
.
fW
arningFlags
))
O
.
nest
2
(
O
.
vcat
(
map
(
setting
wopt
)
w
arningFlags
))
]
where
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
warningFlags
=
DynFlags
.
wWarningFlags
#
else
warningFlags
=
DynFlags
.
fWarningFlags
#
endif
#
if
MIN_VERSION_ghc
(
7
,
8
,
0
)
opt
=
gopt
#
else
...
...
@@ -239,7 +251,11 @@ initGhci sandboxPackages = do
originalFlags
<-
getSessionDynFlags
let
flag
=
flip
xopt_set
unflag
=
flip
xopt_unset
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
dflags
=
flag
ExtendedDefaultRules
.
unflag
MonomorphismRestriction
$
originalFlags
#
else
dflags
=
flag
Opt_ExtendedDefaultRules
.
unflag
Opt_MonomorphismRestriction
$
originalFlags
#
endif
pkgConfs
=
case
sandboxPackages
of
Nothing
->
extraPkgConfs
originalFlags
...
...
@@ -323,8 +339,13 @@ cleanUpDuplicateInstances = modifySession $ \hscEnv ->
in
hscEnv
{
hsc_IC
=
ic
{
ic_instances
=
(
clsInsts'
,
famInsts
)
}
}
where
instEq
::
ClsInst
->
ClsInst
->
Bool
#
if
MIN_VERSION_ghc
(
7
,
8
,
0
)
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
-- Only support replacing instances on GHC 7.8 and up
instEq
c1
c2
|
ClsInst
{
is_tvs
=
tpl_tvs
,
is_tys
=
tpl_tys
,
is_cls
=
cls
}
<-
c1
,
ClsInst
{
is_tys
=
tpl_tys'
,
is_cls
=
cls'
}
<-
c2
=
cls
==
cls'
&&
isJust
(
tcMatchTys
tpl_tys
tpl_tys'
)
#
elif
MIN_VERSION_ghc
(
7
,
8
,
0
)
instEq
c1
c2
|
ClsInst
{
is_tvs
=
tpl_tvs
,
is_tys
=
tpl_tys
,
is_cls
=
cls
}
<-
c1
,
ClsInst
{
is_tys
=
tpl_tys'
,
is_cls
=
cls'
}
<-
c2
...
...
@@ -333,6 +354,8 @@ cleanUpDuplicateInstances = modifySession $ \hscEnv ->
#
else
instEq
_
_
=
False
#
endif
-- | Get the type of an expression and convert it to a string.
getType
::
GhcMonad
m
=>
String
->
m
String
getType
expr
=
do
...
...
src/IHaskellPrelude.hs
View file @
e97b7019
...
...
@@ -78,7 +78,9 @@ import GHC.Enum as X
import
GHC.Num
as
X
import
GHC.Real
as
X
import
GHC.Err
as
X
hiding
(
absentErr
)
#
if
MIN_VERSION_ghc
(
7
,
10
,
0
)
#
if
MIN_VERSION_ghc
(
8
,
0
,
0
)
import
GHC.Base
as
X
hiding
(
Any
,
mapM
,
foldr
,
sequence
,
many
,
(
<|>
),
Module
(
..
))
#
elif
MIN_VERSION_ghc
(
7
,
10
,
0
)
import
GHC.Base
as
X
hiding
(
Any
,
mapM
,
foldr
,
sequence
,
many
,
(
<|>
))
#
else
import
GHC.Base
as
X
hiding
(
Any
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment