wip: reader
build / build (push) Successful in 1m19s

This commit is contained in:
2026-08-21 01:07:26 -06:00
parent f9ed1274d9
commit 5200932944
59 changed files with 284 additions and 16 deletions
+9
View File
@@ -0,0 +1,9 @@
[ Fix
( SimpleF ( Boolean True ) )
, Fix
( SimpleF ( Boolean True ) )
, Fix
( SimpleF ( Boolean False ) )
, Fix
( SimpleF ( Boolean False ) )
]
+1
View File
@@ -0,0 +1 @@
#t #true #f #false
+15
View File
@@ -0,0 +1,15 @@
[ Fix
( SimpleF
( Number 45.0 )
)
, Fix
( SimpleF
( Number 5667.0 )
)
, Fix
( SimpleF
( Number
( -123.0 )
)
)
]
+1
View File
@@ -0,0 +1 @@
45 +5667 -123
+5
View File
@@ -0,0 +1,5 @@
[ Fix
( SimpleF
( Symbol "aaaa bc" )
)
]
@@ -0,0 +1 @@
|aaaa bc|
+1
View File
@@ -0,0 +1 @@
[]
View File
+9
View File
@@ -0,0 +1,9 @@
[ Fix
( SimpleF
( Symbol "+" )
)
, Fix
( SimpleF
( Symbol "-" )
)
]
@@ -0,0 +1 @@
+ -
@@ -0,0 +1,5 @@
[ Fix
( SimpleF
( String "가나다라마바" )
)
]
@@ -0,0 +1,2 @@
"가나다\
라마바"
+5
View File
@@ -0,0 +1,5 @@
[ Fix
( SimpleF
( String "가나다라" )
)
]
+1
View File
@@ -0,0 +1 @@
"가나다라"
+29
View File
@@ -0,0 +1,29 @@
[ Fix
( SimpleF
( Symbol "abc" )
)
, Fix
( SimpleF
( Symbol "balahwa$" )
)
, Fix
( SimpleF
( Symbol "x!!!" )
)
, Fix
( SimpleF
( Symbol "z" )
)
, Fix
( SimpleF
( Symbol "z123" )
)
, Fix
( SimpleF
( Symbol "나는너무졸리다" )
)
, Fix
( SimpleF
( Symbol "學" )
)
]
@@ -0,0 +1 @@
abc balahwa$ x!!! z z123 나는너무졸리다 學
+7
View File
@@ -77,12 +77,16 @@ library
, base ^>=4.21.2.0 , base ^>=4.21.2.0
, binary , binary
, bytestring , bytestring
, comonad
, containers , containers
, data-fix
, deepseq , deepseq
, deriving-compat
, effectful , effectful
, effectful-core , effectful-core
, effectful-plugin , effectful-plugin
, filepath , filepath
, free
, generic-lens , generic-lens
, hashable , hashable
, invertible-grammar , invertible-grammar
@@ -114,6 +118,8 @@ test-suite test
hs-source-dirs: test hs-source-dirs: test
main-is: Main.hs main-is: Main.hs
build-tool-depends: tasty-discover:tasty-discover build-tool-depends: tasty-discover:tasty-discover
-- cabal-fmt: expand test -Main
other-modules: other-modules:
Gyehoek.Test.CPS.Eval Gyehoek.Test.CPS.Eval
Gyehoek.Test.CPS.Stackify Gyehoek.Test.CPS.Stackify
@@ -133,6 +139,7 @@ test-suite test
, generic-lens , generic-lens
, gyehoek , gyehoek
, lens , lens
, pretty-simple
, process-extras , process-extras
, sexp-grammar , sexp-grammar
, tasty , tasty
+1 -1
View File
@@ -21,7 +21,7 @@ module Gyehoek.Prelude
import Control.Lens import Control.Lens
import Data.List (List) import Data.List (List)
import Data.Text (Text) import Data.Text (Text)
import Effectful (Eff, runEff, runPureEff, (:>)) import Effectful
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Data.Data (Data) import Data.Data (Data)
import Control.DeepSeq (NFData) import Control.DeepSeq (NFData)
+130 -1
View File
@@ -1,4 +1,133 @@
module Gyehoek.Sexp.Read module Gyehoek.Sexp.Read
( ( readFile
) where ) where
import Text.Megaparsec
import Text.Megaparsec.Char hiding (string)
import qualified Text.Megaparsec.Char.Lexer as L
import Data.Void (Void)
import Gyehoek.Sexp.Syntax
import Gyehoek.Prelude hiding (Simple, (:<))
import qualified Data.Text.IO as T
import System.IO (stderr, hPutStrLn)
import Prelude hiding (readFile)
import Data.Functor (($>))
import qualified Data.Text as T
import Data.Char (GeneralCategory(..), generalCategory)
import Control.Exception hiding (try)
import Data.Scientific (Scientific)
-- i'm lazy
newtype ReaderError = MkReaderError String
deriving (Show)
instance Exception ReaderError where
displayException (MkReaderError x) = x
readFile :: IOE :> es => FilePath -> Eff es (List Datum)
readFile f = do
s <- liftIO . T.readFile $ f
case runParser file f s of
Right x -> pure x
Left e -> do
-- liftIO . hPutStrLn stderr . errorBundlePretty $ e
liftIO . throw . MkReaderError . errorBundlePretty $ e
type P = Parsec Void Text
--- lexer helpers
-- TODO: check R⁷RS
sc :: P ()
sc = L.space space1
(L.skipLineComment ";")
(L.skipBlockCommentNested "#|" "|#")
lexeme :: P a -> P a
lexeme = L.lexeme sc
verb :: Text -> P Text
verb = L.symbol sc
--- tokens
identifier :: P Text
identifier = label "identifier" . lexeme . choice $
[ typical-- , delimited, peculiar
]
where
typical = T.cons <$> initial <*> subsequent
where
subsequent = takeWhileP Nothing identChar
initial = satisfy \c ->
identChar c && not (c `hasCategory`
[DecimalNumber,SpacingCombiningMark,EnclosingMark])
delimited = _
peculiar = _
hasCategory c xs = generalCategory c `elem` xs
identChar c = c `hasCategory`
[ UppercaseLetter, LowercaseLetter, TitlecaseLetter, ModifierLetter
, OtherLetter, SpacingCombiningMark, EnclosingMark, DecimalNumber
, LetterNumber, OtherNumber, DashPunctuation, ConnectorPunctuation
, OpenPunctuation, CurrencySymbol, OtherPunctuation, MathSymbol
, ModifierSymbol, OtherSymbol, PrivateUse ]
|| c == '\x200c' || c == '\x200d'
boolean :: P Bool
boolean = label "boolean" . lexeme $ choice
[ ("#true" <|> "#t") $> True
, ("#false" <|> "#f") $> False
]
symbol = identifier
number :: P Scientific
number = label "number" . lexeme $ num
where
num = L.signed (pure ()) L.decimal
-- prefix r = _
-- radix = \case
-- 2 -> "#b"
-- 8 -> "#o"
-- 10 -> "" <|> "#d"
-- 16 -> "#x"
lparen = lexeme $ char '('
rparen = lexeme $ char ')'
string :: P Text
string = label "string" . lexeme $
char '"' *> (T.pack <$> many element) <* char '"'
where
element = choice
[ satisfy (\c -> c /= '"' && c /= '\\')
, "\\\"" $> '"'
, "\\\\" $> '\\'
]
file :: P (List Datum)
file = many datum <* eof
datum :: P Datum
datum = choice
[ Fix . SimpleF <$> simpleDatum
-- , Fix . CompoundF <$> compoundDatum
-- , labeled
-- , labelRef
]
simpleDatum :: P Simple
simpleDatum = choice
[ Boolean <$> boolean
, Number <$> try number
-- , Character <$> character
, String <$> string
, Symbol <$> symbol
-- , Bytevector <$> bytevector
]
+27 -9
View File
@@ -1,4 +1,5 @@
{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TemplateHaskell #-}
module Gyehoek.Sexp.Syntax module Gyehoek.Sexp.Syntax
( DatumF(..) ( DatumF(..)
, Simple(..) , Simple(..)
@@ -6,12 +7,22 @@ module Gyehoek.Sexp.Syntax
, Prefix(..) , Prefix(..)
, Delimiter(..) , Delimiter(..)
, Label(..) , Label(..)
, SourcePos(..)
, Datum
, Cofree((:<))
, Fix(..)
) where ) where
import Language.Haskell.TH.Syntax (Lift) import Language.Haskell.TH.Syntax (Lift)
import Data.Scientific (Scientific) import Data.Scientific (Scientific)
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Gyehoek.Prelude hiding (Simple) import Gyehoek.Prelude hiding ((:<), Simple)
import Text.Megaparsec.Pos (SourcePos(..))
import Control.Comonad.Cofree (Cofree((:<)))
import Data.Fix (Fix (..))
import Data.Functor.Foldable
import Text.Show.Deriving (deriveShow1)
import qualified Control.Comonad.Trans.Cofree as F
data DatumF a data DatumF a
@@ -19,16 +30,16 @@ data DatumF a
| CompoundF (CompoundF a) | CompoundF (CompoundF a)
| LabeledF Label a | LabeledF Label a
| LabelRefF Label | LabelRefF Label
deriving stock (Show, Eq, Data, Generic, Lift) deriving stock (Show, Eq, Data, Generic, Lift, Functor, Foldable, Traversable)
deriving anyclass (NFData) deriving anyclass (NFData)
data Simple data Simple
= SimpleBool Bool = Boolean Bool
| SimpleNumber Scientific | Number Scientific
| SimpleChar Char | Character Char
| SimpleString Text | String Text
| SimpleSymbol Text | Symbol Text
| SimpleBytevector ByteString | Bytevector ByteString
deriving stock (Show, Eq, Data, Generic, Lift) deriving stock (Show, Eq, Data, Generic, Lift)
deriving anyclass (NFData) deriving anyclass (NFData)
@@ -37,7 +48,7 @@ data CompoundF a
| DotListF (NonEmpty a) a | DotListF (NonEmpty a) a
| VectorF (List a) | VectorF (List a)
| AbbrevF Prefix a | AbbrevF Prefix a
deriving stock (Show, Eq, Data, Generic, Lift) deriving stock (Show, Eq, Data, Generic, Lift, Functor, Foldable, Traversable)
deriving anyclass (NFData) deriving anyclass (NFData)
data Prefix data Prefix
@@ -56,3 +67,10 @@ newtype Label = MkLabel Natural
deriving stock (Data, Generic, Lift) deriving stock (Data, Generic, Lift)
deriving newtype (Eq, Ord, Show) deriving newtype (Eq, Ord, Show)
deriving anyclass (NFData) deriving anyclass (NFData)
deriveShow1 ''CompoundF
deriveShow1 ''DatumF
type Datum = Fix DatumF
+33 -5
View File
@@ -16,6 +16,10 @@ import Data.Text qualified as T
import System.Exit (ExitCode(..)) import System.Exit (ExitCode(..))
import Test.Tasty.ExpectedFailure (expectFail, ignoreTestBecause) import Test.Tasty.ExpectedFailure (expectFail, ignoreTestBecause)
import Control.DeepSeq (($!!)) import Control.DeepSeq (($!!))
import Text.Pretty.Simple (pShow, pShowNoColor)
import Control.Lens (strict, view)
import Gyehoek.Sexp.Read qualified as Read
import Effectful
brokenWasmTests :: List String brokenWasmTests :: List String
@@ -31,12 +35,17 @@ brokenStackifyTests =
-- , "callcc-nested1" -- requires closure-conversion -- , "callcc-nested1" -- requires closure-conversion
-- ] -- ]
brokenReaderTests =
[ "delimited-identifier"
, "string-line-continuation"
]
test_root :: IO TestTree test_root :: IO TestTree
test_root = do test_root = do
all_cases <- listDirectory "golden" all_cases <- listDirectory "golden/exec"
let tests = all_cases let tests = all_cases
& fmap ("golden"</>) & fmap ("golden/exec"</>)
testGroup "golden" <$> sequenceA testGroup "execution" <$> sequenceA
[ ignoreTestBecause "wasm codegen is on the backburner" [ ignoreTestBecause "wasm codegen is on the backburner"
<$> wasmTests tests <$> wasmTests tests
, stackifyTests tests , stackifyTests tests
@@ -48,7 +57,7 @@ wasmTests :: List FilePath -> IO TestTree
wasmTests files = do wasmTests files = do
cmd <- getEnvDefault "GYEHOEK_RUNTIME" cmd <- getEnvDefault "GYEHOEK_RUNTIME"
"runtime/target/debug/gyehoek-runtime" "runtime/target/debug/gyehoek-runtime"
pure $ testGroup "wasm execution" $ files <&> \test -> pure $ testGroup "wasm" $ files <&> \test ->
let testname = takeFileName test let testname = takeFileName test
scmfile = test </> "source.scm" scmfile = test </> "source.scm"
resultfile = test </> "exec" resultfile = test </> "exec"
@@ -64,7 +73,7 @@ wasmTests files = do
stackifyTests :: List FilePath -> IO TestTree stackifyTests :: List FilePath -> IO TestTree
stackifyTests files = do stackifyTests files = do
pure $ testGroup "stackified execution" $ files <&> \test -> pure $ testGroup "stackified" $ files <&> \test ->
let testname = takeFileName test let testname = takeFileName test
scmfile = test </> "source.scm" scmfile = test </> "source.scm"
resultfile = test </> "exec" resultfile = test </> "exec"
@@ -81,3 +90,22 @@ stackifyTests files = do
resultfile resultfile
action action
printProcResult printProcResult
test_reader :: IO TestTree
test_reader = do
all_cases <- listDirectory "golden/reader"
let tests = all_cases
& fmap ("golden/reader"</>)
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