@@ -0,0 +1,12 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-expression/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleMeta "aHaskellVariable + abc * 2" )
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#{aHaskellVariable + abc * 2}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-splice-expression/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleMetaSplice "takeWhile (\x -> even x) aHaskellList" )
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
##{takeWhile (\x -> even x) aHaskellList}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-splice-variable/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleMetaSplice "aHaskellList" )
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
##{aHaskellList}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[ MkAnn
|
||||||
|
{ syntax = SynNone
|
||||||
|
, position = Just
|
||||||
|
( SourcePos
|
||||||
|
{ sourceName = "golden/read/meta-variable/source.scm"
|
||||||
|
, sourceLine = Pos 1
|
||||||
|
, sourceColumn = Pos 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} :< SimpleF
|
||||||
|
( SimpleMeta "aHaskellVariable" )
|
||||||
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#{aHaskellVariable}
|
||||||
@@ -131,7 +131,9 @@ test-suite test
|
|||||||
Gyehoek.Test.Scheme.Syntax
|
Gyehoek.Test.Scheme.Syntax
|
||||||
Gyehoek.Test.Sexp
|
Gyehoek.Test.Sexp
|
||||||
Gyehoek.Test.Sexp.Print
|
Gyehoek.Test.Sexp.Print
|
||||||
|
Gyehoek.Test.Sexp.Read
|
||||||
Gyehoek.Test.Stack.VM
|
Gyehoek.Test.Stack.VM
|
||||||
|
Gyehoek.TestUtil
|
||||||
Root
|
Root
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ module Gyehoek.CPS.Syntax
|
|||||||
, Imm(..)
|
, Imm(..)
|
||||||
, Obj(..)
|
, Obj(..)
|
||||||
, Hob(..)
|
, Hob(..)
|
||||||
, pattern Void
|
|
||||||
, pattern Halt
|
, pattern Halt
|
||||||
, pattern Halt1
|
, pattern Halt1
|
||||||
, _MkKappa
|
, _MkKappa
|
||||||
@@ -43,7 +42,7 @@ module Gyehoek.CPS.Syntax
|
|||||||
|
|
||||||
import Language.SexpGrammar qualified as S
|
import Language.SexpGrammar qualified as S
|
||||||
import Gyehoek.Sexp qualified
|
import Gyehoek.Sexp qualified
|
||||||
import Gyehoek.Scheme.Syntax (Name (..), Prim(..), primSexpIso, Lit(..), pattern Void)
|
import Gyehoek.Scheme.Syntax (Name (..), Prim(..), primDatumIso, Lit(..))
|
||||||
import Language.SexpGrammar.Generic
|
import Language.SexpGrammar.Generic
|
||||||
import Control.Category
|
import Control.Category
|
||||||
import Prelude hiding ((.), id)
|
import Prelude hiding ((.), id)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ module Gyehoek.Jalmot
|
|||||||
( Jalmot
|
( Jalmot
|
||||||
, Exception(..)
|
, Exception(..)
|
||||||
, AJalmot(..)
|
, AJalmot(..)
|
||||||
|
, AJalmotCS(..)
|
||||||
, module Effectful.Error.Static
|
, module Effectful.Error.Static
|
||||||
, runJalmot
|
, runJalmot
|
||||||
, runJalmotIO
|
, runJalmotIO
|
||||||
@@ -12,7 +13,7 @@ module Gyehoek.Jalmot
|
|||||||
import Gyehoek.Prelude
|
import Gyehoek.Prelude
|
||||||
import Text.Megaparsec.Error (ParseErrorBundle, errorBundlePretty)
|
import Text.Megaparsec.Error (ParseErrorBundle, errorBundlePretty)
|
||||||
import Data.Void (Void)
|
import Data.Void (Void)
|
||||||
import Control.Exception.Base (Exception(..), throwIO)
|
import Effectful.Exception
|
||||||
import Effectful.Error.Static
|
import Effectful.Error.Static
|
||||||
import qualified Data.InvertibleGrammar as Grammar
|
import qualified Data.InvertibleGrammar as Grammar
|
||||||
import Gyehoek.Sexp.Syntax (Ann)
|
import Gyehoek.Sexp.Syntax (Ann)
|
||||||
@@ -28,7 +29,7 @@ data AJalmot
|
|||||||
| GrammarError (Grammar.ErrorMessage Ann)
|
| GrammarError (Grammar.ErrorMessage Ann)
|
||||||
deriving (Show, Generic, Data)
|
deriving (Show, Generic, Data)
|
||||||
|
|
||||||
data AJalmotWithCallStack = MkAJalmotWithCallStack !CallStack !AJalmot
|
data AJalmotCS = MkAJalmotCS !CallStack !AJalmot
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
type Jalmot = Error AJalmot
|
type Jalmot = Error AJalmot
|
||||||
@@ -40,7 +41,7 @@ runJalmotIOE :: IOE :> es => Eff (Jalmot : es) a -> Eff es a
|
|||||||
runJalmotIOE eff =
|
runJalmotIOE eff =
|
||||||
runJalmot eff >>= \case
|
runJalmot eff >>= \case
|
||||||
Right a -> pure a
|
Right a -> pure a
|
||||||
Left (cs,jm) -> liftIO . throwIO $ MkAJalmotWithCallStack cs jm
|
Left (cs,jm) -> throwIO $ MkAJalmotCS cs jm
|
||||||
|
|
||||||
runJalmotIO :: Eff '[Jalmot, IOE] a -> IO a
|
runJalmotIO :: Eff '[Jalmot, IOE] a -> IO a
|
||||||
runJalmotIO = runEff . runJalmotIOE
|
runJalmotIO = runEff . runJalmotIOE
|
||||||
@@ -53,7 +54,7 @@ instance Exception AJalmot where
|
|||||||
& layoutPretty defaultLayoutOptions
|
& layoutPretty defaultLayoutOptions
|
||||||
& renderString
|
& renderString
|
||||||
|
|
||||||
instance Exception AJalmotWithCallStack where
|
instance Exception AJalmotCS where
|
||||||
backtraceDesired = const False
|
backtraceDesired = const False
|
||||||
displayException (MkAJalmotWithCallStack cs jm) =
|
displayException (MkAJalmotCS cs jm) =
|
||||||
"\n" <> displayException jm <> "\n\n" <> prettyCallStack cs
|
"\n" <> displayException jm <> "\n\n" <> prettyCallStack cs
|
||||||
|
|||||||
+16
-11
@@ -11,23 +11,14 @@ import Data.Void (Void)
|
|||||||
import Gyehoek.Sexp.Syntax
|
import Gyehoek.Sexp.Syntax
|
||||||
import Gyehoek.Prelude hiding (Simple, (:<))
|
import Gyehoek.Prelude hiding (Simple, (:<))
|
||||||
import qualified Data.Text.IO as T
|
import qualified Data.Text.IO as T
|
||||||
import System.IO (stderr, hPutStrLn)
|
|
||||||
import Prelude hiding (readFile)
|
import Prelude hiding (readFile)
|
||||||
import Data.Functor (($>), void)
|
import Data.Functor (($>))
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Char (GeneralCategory(..), generalCategory)
|
import Data.Char (GeneralCategory(..), generalCategory)
|
||||||
import Control.Exception hiding (try)
|
|
||||||
import Data.Scientific (Scientific)
|
import Data.Scientific (Scientific)
|
||||||
import Gyehoek.Jalmot
|
import Gyehoek.Jalmot
|
||||||
|
|
||||||
|
|
||||||
-- i'm lazy
|
|
||||||
newtype ReaderError = MkReaderError String
|
|
||||||
deriving (Show)
|
|
||||||
|
|
||||||
instance Exception ReaderError where
|
|
||||||
displayException (MkReaderError x) = x
|
|
||||||
|
|
||||||
readFile :: (Jalmot :> es, IOE :> es) => FilePath -> Eff es (List Datum)
|
readFile :: (Jalmot :> es, IOE :> es) => FilePath -> Eff es (List Datum)
|
||||||
readFile f = do
|
readFile f = do
|
||||||
s <- liftIO . T.readFile $ f
|
s <- liftIO . T.readFile $ f
|
||||||
@@ -52,7 +43,9 @@ type P = Parsec Void Text
|
|||||||
|
|
||||||
--- lexer helpers
|
--- lexer helpers
|
||||||
|
|
||||||
-- TODO: check R⁷RS
|
-- TODO: check R⁷RS's definition of ⟨atmosphere⟩.
|
||||||
|
-- TODO: datum comments.
|
||||||
|
-- | whitespace consumer.
|
||||||
sc :: P ()
|
sc :: P ()
|
||||||
sc = L.space space1
|
sc = L.space space1
|
||||||
(L.skipLineComment ";")
|
(L.skipLineComment ";")
|
||||||
@@ -61,6 +54,7 @@ sc = L.space space1
|
|||||||
lexeme :: P a -> P a
|
lexeme :: P a -> P a
|
||||||
lexeme = L.lexeme sc
|
lexeme = L.lexeme sc
|
||||||
|
|
||||||
|
-- | verbatim text.
|
||||||
verb :: Text -> P Text
|
verb :: Text -> P Text
|
||||||
verb = L.symbol sc
|
verb = L.symbol sc
|
||||||
|
|
||||||
@@ -92,6 +86,7 @@ identifier = label "identifier" . lexeme . choice $
|
|||||||
, ModifierSymbol, OtherSymbol, PrivateUse ]
|
, ModifierSymbol, OtherSymbol, PrivateUse ]
|
||||||
|| c == '\x200c' || c == '\x200d')
|
|| c == '\x200c' || c == '\x200d')
|
||||||
&& c /= ';' && c /= '|' && c /= '"' && c /= '.'
|
&& c /= ';' && c /= '|' && c /= '"' && c /= '.'
|
||||||
|
&& c /= ',' && c /= '#'
|
||||||
|
|
||||||
boolean :: P Bool
|
boolean :: P Bool
|
||||||
boolean = label "boolean" . lexeme $ choice
|
boolean = label "boolean" . lexeme $ choice
|
||||||
@@ -137,6 +132,14 @@ string = label "string" . lexeme $
|
|||||||
, "\\\\" $> '\\'
|
, "\\\\" $> '\\'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
metaSplice :: P Text
|
||||||
|
metaSplice = label "splicing meta" . lexeme . between "##{" "}" $
|
||||||
|
takeWhileP Nothing (/= '}')
|
||||||
|
|
||||||
|
meta :: P Text
|
||||||
|
meta = label "meta" . lexeme . between "#{" "}" $
|
||||||
|
takeWhileP Nothing (/= '}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
file :: P (List Datum)
|
file :: P (List Datum)
|
||||||
@@ -160,6 +163,8 @@ simpleDatum = choice
|
|||||||
, SimpleString <$> string
|
, SimpleString <$> string
|
||||||
, SimpleSymbol <$> symbol
|
, SimpleSymbol <$> symbol
|
||||||
-- , SimpleBytevector <$> bytevector
|
-- , SimpleBytevector <$> bytevector
|
||||||
|
, SimpleMetaSplice <$> metaSplice
|
||||||
|
, SimpleMeta <$> meta
|
||||||
]
|
]
|
||||||
|
|
||||||
compoundDatum :: P Compound
|
compoundDatum :: P Compound
|
||||||
|
|||||||
@@ -35,12 +35,6 @@ brokenStackifyTests =
|
|||||||
-- , "callcc-nested1" -- requires closure-conversion
|
-- , "callcc-nested1" -- requires closure-conversion
|
||||||
-- ]
|
-- ]
|
||||||
|
|
||||||
brokenReaderTests =
|
|
||||||
[ "delimited-identifier"
|
|
||||||
, "string-line-continuation"
|
|
||||||
, "peculiar-identifier-dot"
|
|
||||||
]
|
|
||||||
|
|
||||||
test_root :: IO TestTree
|
test_root :: IO TestTree
|
||||||
test_root = do
|
test_root = do
|
||||||
all_cases <- listDirectory "golden/exec"
|
all_cases <- listDirectory "golden/exec"
|
||||||
@@ -91,22 +85,3 @@ stackifyTests files = do
|
|||||||
resultfile
|
resultfile
|
||||||
action
|
action
|
||||||
printProcResult
|
printProcResult
|
||||||
|
|
||||||
test_reader :: IO TestTree
|
|
||||||
test_reader = do
|
|
||||||
all_cases <- listDirectory "golden/read"
|
|
||||||
let tests = all_cases
|
|
||||||
& fmap ("golden/read"</>)
|
|
||||||
pure . testGroup "reader" $ tests <&> \test ->
|
|
||||||
let testname = takeFileName test
|
|
||||||
scmfile = test </> "source.scm"
|
|
||||||
resultfile = test </> "read"
|
|
||||||
action = runEff $ Read.readFile scmfile
|
|
||||||
in maybeBroken testname brokenReaderTests $ goldenVsAction
|
|
||||||
testname
|
|
||||||
resultfile
|
|
||||||
action
|
|
||||||
(view strict . pShowNoColor)
|
|
||||||
|
|
||||||
-- readTests files = pure . testGroup "reader" $ files <&> \test ->
|
|
||||||
-- let
|
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
module Gyehoek.Test.Sexp.Read where
|
||||||
|
|
||||||
|
import Test.Tasty (TestTree, testGroup)
|
||||||
|
import Test.Tasty.Silver
|
||||||
|
import System.FilePath
|
||||||
|
import Data.List (List)
|
||||||
|
import System.Directory
|
||||||
|
import Gyehoek.Prelude
|
||||||
|
import qualified Gyehoek.Sexp.Read as Read
|
||||||
|
import Gyehoek.TestUtil
|
||||||
|
import Gyehoek.Jalmot (runJalmotIO)
|
||||||
|
import Text.Pretty.Simple (pShowNoColor)
|
||||||
|
import Gyehoek.Sexp.Syntax
|
||||||
|
import Test.Tasty.HUnit
|
||||||
|
import Control.Exception (tryWithContext, ExceptionWithContext (..), rethrowIO)
|
||||||
|
import Gyehoek.Jalmot
|
||||||
|
|
||||||
|
|
||||||
|
brokenReaderTests :: List String
|
||||||
|
brokenReaderTests =
|
||||||
|
[ "delimited-identifier"
|
||||||
|
, "string-line-continuation"
|
||||||
|
, "peculiar-identifier-dot"
|
||||||
|
]
|
||||||
|
|
||||||
|
test_golden :: IO TestTree
|
||||||
|
test_golden = do
|
||||||
|
all_cases <- listDirectory "golden/read"
|
||||||
|
let tests = all_cases
|
||||||
|
& fmap ("golden/read"</>)
|
||||||
|
pure . testGroup "reader" $ tests <&> \test ->
|
||||||
|
let testname = takeFileName test
|
||||||
|
scmfile = test </> "source.scm"
|
||||||
|
resultfile = test </> "read"
|
||||||
|
action = runJalmotIO $ Read.readFile scmfile
|
||||||
|
in markIfBroken testname brokenReaderTests $ goldenVsAction
|
||||||
|
testname
|
||||||
|
resultfile
|
||||||
|
action
|
||||||
|
(view strict . pShowNoColor)
|
||||||
|
|
||||||
|
readString1 = runJalmotIO . Read.readString1
|
||||||
|
|
||||||
|
test_invalidIdentifiers :: TestTree
|
||||||
|
test_invalidIdentifiers = testGroup "invalid identifiers"
|
||||||
|
[ testCase "dot" $ notIdentifier (readString1 ".")
|
||||||
|
, testCase "comma" $ notIdentifier (readString1 ",")
|
||||||
|
, testCase "pound" $ notIdentifier (readString1 "#")
|
||||||
|
, testCase "pound anything" $ notIdentifier (readString1 "#abc")
|
||||||
|
]
|
||||||
|
where
|
||||||
|
notIdentifier m = tryWithContext m >>= \case
|
||||||
|
-- the reader is allowed to fail; we're just don't want it to
|
||||||
|
-- return a symbol.
|
||||||
|
Left (ExceptionWithContext _ (MkAJalmotCS _ (ReaderError _))) -> pure ()
|
||||||
|
Left e -> rethrowIO e
|
||||||
|
Right (Symbol s) -> assertFailure [i|got symbol #{s}|]
|
||||||
|
Right _ -> pure ()
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module Gyehoek.TestUtil
|
||||||
|
( markIfBroken
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Test.Tasty.ExpectedFailure (expectFail)
|
||||||
|
import Data.Function
|
||||||
|
import Test.Tasty (TestTree)
|
||||||
|
|
||||||
|
|
||||||
|
markIfBroken :: Foldable f => String -> f String -> TestTree -> TestTree
|
||||||
|
markIfBroken name brokenTests = applyWhen (name `elem` brokenTests) expectFail
|
||||||
Reference in New Issue
Block a user