diff --git a/lamagraph-compiler/lamagraph-compiler.cabal b/lamagraph-compiler/lamagraph-compiler.cabal index 948f268..4fb6788 100644 --- a/lamagraph-compiler/lamagraph-compiler.cabal +++ b/lamagraph-compiler/lamagraph-compiler.cabal @@ -31,6 +31,7 @@ library Lamagraph.Compiler.Parser.LexerUtils Lamagraph.Compiler.Parser.SrcLoc Lamagraph.Compiler.PrettyAST + Lamagraph.Compiler.PrettyLML Lamagraph.Compiler.Syntax Lamagraph.Compiler.Syntax.Decl Lamagraph.Compiler.Syntax.Expr @@ -89,8 +90,11 @@ test-suite lamagraph-compiler-test type: exitcode-stdio-1.0 main-is: Spec.hs other-modules: + Lamagraph.Compiler.Parser.GoldenCommon Lamagraph.Compiler.Parser.LexerTest - Lamagraph.Compiler.ParserGoldenTest + Lamagraph.Compiler.Parser.ParserRoundtrip + Lamagraph.Compiler.Parser.PrettyASTGolden + Lamagraph.Compiler.Parser.PrettyLmlGolden Paths_lamagraph_compiler hs-source-dirs: test @@ -106,12 +110,13 @@ test-suite lamagraph-compiler-test , base >=4.7 && <5 , extra , filepath + , hedgehog , lamagraph-compiler , lens - , pretty-simple , prettyprinter , relude , tasty , tasty-golden + , tasty-hedgehog , tasty-hunit default-language: GHC2021 diff --git a/lamagraph-compiler/package.yaml b/lamagraph-compiler/package.yaml index fe4743d..16486f8 100644 --- a/lamagraph-compiler/package.yaml +++ b/lamagraph-compiler/package.yaml @@ -78,4 +78,5 @@ tests: - tasty - tasty-hunit - tasty-golden - - pretty-simple + - tasty-hedgehog + - hedgehog diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Extension.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Extension.hs index 44d93a6..018e5ba 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Extension.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Extension.hs @@ -3,8 +3,6 @@ module Lamagraph.Compiler.Extension (Pass (..), LmlcPass (..), LmlcPs) where --- import Relude - import Lamagraph.Compiler.Parser.SrcLoc import Lamagraph.Compiler.Syntax diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Parser.y b/lamagraph-compiler/src/Lamagraph/Compiler/Parser.y index 3ced243..164090c 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Parser.y +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Parser.y @@ -168,23 +168,52 @@ typeconstr_name :: { XLocated LmlcPs Text } -- Qualified names -- --------------------- module_pathT :: { NonEmpty LToken } - : mkIdent(module_pathT, capitalized_ident) { $1 } + : mkIdentRev(module_pathT, capitalized_ident) { $1 } + +value_nameT :: { LToken } + : lowercase_ident { $1 } + | '(' operator_nameT ')' { sLL $1 $3 $ unLoc $2 } + +operator_nameT :: { LToken } + : prefix_symbol { $1 } + | infix_opT { $1 } + +infix_opT :: { LToken } + : infix_symbol0 { $1 } + | infix_symbol1 { $1 } + | infix_symbol2 { $1 } + | infix_symbol3 { $1 } + | infix_symbol4 { $1 } + | '*' { $1 } + | '+' { $1 } + | '-' { $1 } + | '=' { $1 } + | '||' { $1 } + | '&&' { $1 } + | 'mod' { $1 } + | 'land' { $1 } + | 'lor' { $1 } + | 'lxor' { $1 } + | 'lsl' { $1 } + | 'lsr' { $1 } + | 'asr' { $1 } value_path :: { LLongident LmlcPs } - : mkIdent(module_pathT, lowercase_ident) { sLNE $1 $ getLongident $1 } + : mkIdentRev(module_pathT, value_nameT) { sLNE $1 $ getLongident (NE.reverse $1) } + -- | mkIdentRev(module_pathT, ) { sLNE $1 $ getLongident (NE.reverse $1) } constr :: { LLongident LmlcPs } - : mkIdent(module_pathT, capitalized_ident) { sLNE $1 $ getLongident $1 } + : mkIdentRev(module_pathT, capitalized_ident) { sLNE $1 $ getLongident (NE.reverse $1) } | '[' ']' { sLL $1 $2 nilConstruct } | '(' ')' { sLL $1 $2 unitConstruct } | 'true' { sL1 $1 $ (mkLongident . pure) "true" } | 'false' { sL1 $1 $ (mkLongident . pure) "false" } typeconstr :: { LLongident LmlcPs } - : mkIdent(module_pathT, lowercase_ident) { sLNE $1 $ getLongident $1 } + : mkIdentRev(module_pathT, lowercase_ident) { sLNE $1 $ getLongident (NE.reverse $1) } module_path :: { LLongident LmlcPs } - : module_pathT { sLNE $1 $ getLongident $1 } + : module_pathT { sLNE $1 $ getLongident (NE.reverse $1) } ---------------------- -- Type expressions -- diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Parser/Lexer.x b/lamagraph-compiler/src/Lamagraph/Compiler/Parser/Lexer.x index cf371d8..44186d0 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Parser/Lexer.x +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Parser/Lexer.x @@ -49,7 +49,11 @@ $operator_char = [\! \$ \% & \* \+ \. \/ \: \< \= \> \? \@ \^ \| \~] -- Identifiers @ident_tail = ( $letter | $digit | \_ | \' )* @capitalized_ident = $capital_letter @ident_tail -@lowercase_ident = ( $lowercase_letter | \_ ) @ident_tail +-- @lowercase_ident = ( $lowercase_letter | \_ ) @ident_tail +@lowercase_ident = ( + ( $lowercase_letter @ident_tail) + | ( \_ ( $letter | $digit ) @ident_tail ) +) -- Integer literals @integer_literal = \-? $digit ( $digit | \_ )* diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Parser/SrcLoc.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Parser/SrcLoc.hs index 4ee126b..892c15d 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Parser/SrcLoc.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Parser/SrcLoc.hs @@ -119,9 +119,9 @@ makeLenses ''RealSrcSpan A 'SrcSpan' represents either "good" portion of a file or a description of a "bad" span. -} -data SrcSpan = RealSrcSpan RealSrcSpan | UnhelpfulSpan UnhelpfulSpanReason deriving (Show) +data SrcSpan = RealSrcSpan RealSrcSpan | UnhelpfulSpan UnhelpfulSpanReason deriving (Show, Eq) -data UnhelpfulSpanReason = UnhelpfulGenerated | UnhelpfulOther Text deriving (Show) +data UnhelpfulSpanReason = UnhelpfulGenerated | UnhelpfulOther Text deriving (Show, Eq) generatedSrcSpan :: SrcSpan generatedSrcSpan = UnhelpfulSpan UnhelpfulGenerated @@ -173,6 +173,13 @@ combineSrcSpans (RealSrcSpan span1) (RealSrcSpan span2) -- | 'SrcSpan's will be attached to nearly everything, let's create a type for attaching. data GenLocated l e = L l e deriving (Show) +{- | This is very specific instance for 'Eq'. +It doesn't compare locations, only contents. +-} +instance (Eq e) => Eq (GenLocated l e) where + (==) :: GenLocated l e -> GenLocated l e -> Bool + (L _ a) == (L _ b) = a == b + makePrisms ''GenLocated type Located = GenLocated SrcSpan diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/PrettyAST.hs b/lamagraph-compiler/src/Lamagraph/Compiler/PrettyAST.hs index fcbbbb4..082e0ea 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/PrettyAST.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/PrettyAST.hs @@ -119,7 +119,7 @@ instance Pretty (LmlLit (LmlcPass pass)) where instance Pretty Longident where pretty :: Longident -> Doc ann - pretty (Longident indents) = dquotes $ hsep $ punctuate comma (map pretty (toList indents)) + pretty (Longident idents) = dquotes $ hsep $ punctuate comma (map pretty (toList idents)) instance Pretty (LmlPat (LmlcPass pass)) where pretty :: LmlPat (LmlcPass pass) -> Doc ann diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/PrettyLML.hs b/lamagraph-compiler/src/Lamagraph/Compiler/PrettyLML.hs new file mode 100644 index 0000000..5c09f85 --- /dev/null +++ b/lamagraph-compiler/src/Lamagraph/Compiler/PrettyLML.hs @@ -0,0 +1,149 @@ +{-# OPTIONS_GHC -Wno-orphans #-} + +-- | Orphan instances for pretty-printing LamagraphML +module Lamagraph.Compiler.PrettyLML () where + +import Relude + +import Data.Text qualified as T +import Prettyprinter + +import Lamagraph.Compiler.Extension +import Lamagraph.Compiler.Parser.SrcLoc +import Lamagraph.Compiler.Syntax + +prettyADTVar :: LLmlType (LmlcPass pass) -> Doc ann +prettyADTVar (L _ (LmlTyVar _ varName)) = "'" <> pretty varName +prettyADTVar _ = error "Internal pretty-printer error: cannot have complex types in type parameters" + +prettyADTVars :: [LLmlType (LmlcPass pass)] -> Doc ann +prettyADTVars [] = emptyDoc +prettyADTVars [var] = prettyADTVar var <> space +prettyADTVars vars = parens (fillSep $ punctuate comma (map prettyADTVar vars)) <> space + +prettyChar :: Char -> Doc ann +prettyChar '\\' = "\\\\" +prettyChar '\"' = "\\\"" +prettyChar '\'' = "\\\'" +prettyChar '\n' = "\\\n" +prettyChar c + | c `elem` ['\32' .. '\127'] = pretty c + | otherwise = error "Internal pretty-printer error: trying to print unsupported character" + +prettyString :: Text -> Doc ann +prettyString str = mconcat $ map prettyChar (toString str) + +instance (Pretty a) => Pretty (Located a) where + pretty :: Located a -> Doc ann + pretty (L _ a) = pretty a + +instance Pretty RecFlag where + pretty :: RecFlag -> Doc ann + pretty Recursive = "rec" <> space + pretty NonRecursive = emptyDoc + +instance Pretty (LmlDecl (LmlcPass pass)) where + pretty :: LmlDecl (LmlcPass pass) -> Doc ann + pretty (OpenD _ decl) = "open" <+> pretty decl + pretty (ValD _ recFlag binds) = "let" <+> pretty recFlag <> concatWith (surround (hardline <> "and" <> hardline)) (map pretty (toList binds)) + pretty (TyD _ decls) = "type" <+> concatWith (surround (hardline <> "and" <> hardline)) (map pretty (toList decls)) + +instance Pretty (OpenDecl (LmlcPass pass)) where + pretty :: OpenDecl (LmlcPass pass) -> Doc ann + pretty (OpenDecl _ ident) = pretty ident + +instance Pretty (TyDecl (LmlcPass pass)) where + pretty :: TyDecl (LmlcPass pass) -> Doc ann + pretty (AliasDecl _ name vars ty) = prettyADTVars vars <> pretty name <+> "=" <> softline <> pretty ty + pretty (DataDecl _ name vars []) = prettyADTVars vars <> pretty name + pretty (DataDecl _ name vars constrs) = + prettyADTVars vars + <> pretty name <+> align ("=" <+> encloseSep emptyDoc emptyDoc (flatAlt "| " " | ") (map pretty constrs)) + +instance Pretty (ConDecl (LmlcPass pass)) where + pretty :: ConDecl (LmlcPass pass) -> Doc ann + pretty (ConDecl _ (L _ "::") args) = "(::)" <+> "of" <+> concatWith (surround " * ") (map pretty args) + pretty (ConDecl _ name args) = + pretty name <> case args of + [] -> emptyDoc + _ -> space <> "of" <+> concatWith (surround " * ") (map pretty args) + +instance Pretty (LmlExpr (LmlcPass pass)) where + pretty :: LmlExpr (LmlcPass pass) -> Doc ann + pretty (LmlExprIdent _ ident) = pretty ident + pretty (LmlExprConstant _ constant) = pretty constant + pretty (LmlExprLet _ recFlag binds expr) = + "let" <+> pretty recFlag + <> concatWith (surround (hardline <> "and" <> hardline)) (map pretty (toList binds)) <+> "in" <+> pretty expr + pretty (LmlExprFunction _ pat expr) = "fun" <+> pretty pat <+> "->" <+> pretty expr + pretty (LmlExprApply _ expr exprs) = pretty expr <+> hsep (map (parens . pretty) (toList exprs)) + pretty (LmlExprMatch _ expr cases) = + parens $ + align + ("match" <+> pretty expr <+> "with" <+> encloseSep emptyDoc emptyDoc (flatAlt "| " " | ") (map pretty (toList cases))) + pretty (LmlExprTuple _ expr exprs) = parens (fillSep $ punctuate comma (map (parens . pretty) (expr : toList exprs))) + pretty (LmlExprConstruct _ (L _ (Longident ("::" :| []))) (Just (L _ (LmlExprTuple _ hd tl)))) = parens (pretty hd <+> "::" <+> pretty (head tl)) + pretty (LmlExprConstruct _ constr Nothing) = pretty constr + pretty (LmlExprConstruct _ constr (Just expr)) = parens (pretty constr <+> parens (pretty expr)) + pretty (LmlExprIfThenElse _ cond t f) = "if" <+> pretty cond <+> "then" <+> pretty t <+> "else" <+> pretty f + pretty (LmlExprConstraint _ expr ty) = parens (pretty expr <+> ":" <+> pretty ty) + +instance Pretty (LmlBind (LmlcPass pass)) where + pretty :: LmlBind (LmlcPass pass) -> Doc ann + pretty (LmlBind _ pat expr) = pretty pat <+> "=" <> softline <> pretty expr + +instance Pretty (LmlCase (LmlcPass pass)) where + pretty :: LmlCase (LmlcPass pass) -> Doc ann + pretty (LmlCase _ pat Nothing expr) = pretty pat <+> "->" <+> pretty expr + pretty (LmlCase _ pat (Just constraint) expr) = pretty pat <+> "when" <+> pretty constraint <+> "->" <+> pretty expr + +instance Pretty (LmlLit (LmlcPass pass)) where + pretty :: LmlLit (LmlcPass pass) -> Doc ann + pretty (LmlInt _ int) = pretty int + pretty (LmlInt32 _ int32) = pretty int32 <> "l" + pretty (LmlUInt32 _ uint32) = pretty uint32 <> "ul" + pretty (LmlInt64 _ int64) = pretty int64 <> "L" + pretty (LmlUInt64 _ uint64) = pretty uint64 <> "UL" + pretty (LmlChar _ char) = squotes $ prettyChar char + pretty (LmlString _ str) = dquotes $ prettyString str + +instance Pretty Longident where + pretty :: Longident -> Doc ann + pretty (Longident ident) = if res then prettyInit <> parens (space <> pretty func <> space) else prettyInit <> pretty func + where + func = last ident + initList = init ident + prettyInit = if null initList then emptyDoc else concatWith (surround dot) (map pretty initList) <> dot + prefixes = ["*", "/", "%", "+", "-", "@", "^", "=", "<", ">", "|", "&", "$", "!", "?", "~"] + equal = ["lor", "lxor", "mod", "land", "lsl", "lsr", "asr"] + startsWithB = map (`T.isPrefixOf` func) prefixes + equalsB = map (func ==) equal + res = or startsWithB || or equalsB + +instance Pretty (LmlPat (LmlcPass pass)) where + pretty :: LmlPat (LmlcPass pass) -> Doc ann + pretty (LmlPatAny _) = "_" + pretty (LmlPatVar _ (L _ var)) = pretty $ mkLongident (pure var) + pretty (LmlPatConstant _ constant) = pretty constant + pretty (LmlPatTuple _ pat pats) = parens $ fillSep (punctuate comma (map pretty (pat : toList pats))) + pretty (LmlPatConstruct _ (L _ (Longident ("::" :| []))) (Just (L _ (LmlPatTuple _ hd tl)))) = parens (pretty hd <+> "::" <+> pretty (head tl)) + pretty (LmlPatConstruct _ constr Nothing) = pretty constr + pretty (LmlPatConstruct _ constr (Just pat)) = parens (pretty constr <+> parens (pretty pat)) + pretty (LmlPatOr _ pat1 pat2) = parens (pretty pat1 <+> "|" <+> pretty pat2) + pretty (LmlPatConstraint _ pat ty) = parens (pretty pat <+> ":" <+> pretty ty) + +instance Pretty (LmlType (LmlcPass pass)) where + pretty :: LmlType (LmlcPass pass) -> Doc ann + pretty (LmlTyVar _ var) = "'" <> pretty var + pretty (LmlTyArrow _ ty1 ty2) = parens (pretty ty1 <+> "->" <> softline <> pretty ty2) + pretty (LmlTyTuple _ ty tys) = parens $ concatWith (surround " * ") (map pretty (ty : toList tys)) + pretty (LmlTyConstr _ constr []) = pretty constr + pretty (LmlTyConstr _ constr [ty@(L _ (LmlTyArrow{}))]) = parens (pretty ty) <+> pretty constr + pretty (LmlTyConstr _ constr [ty]) = pretty ty <+> pretty constr + pretty (LmlTyConstr _ constr tys) = parens (fillSep $ punctuate comma (map pretty tys)) <+> pretty constr + +instance Pretty (LmlModule (LmlcPass pass)) where + pretty :: LmlModule (LmlcPass pass) -> Doc ann + pretty (LmlModule _ name decls) = concatWith (surround (hardline <> hardline)) $ case name of + Nothing -> map pretty decls + Just moduleName -> ("module" <+> pretty moduleName) : map pretty decls diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax.hs index 9dd9d1e..a943662 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax.hs @@ -362,3 +362,4 @@ type ForallLmlModule (tc :: Type -> Constraint) pass = (tc (XCModule pass), tc (LLongident pass), tc (LLmlDecl pass), tc (XXModule pass)) deriving instance (ForallLmlModule Show pass) => Show (LmlModule pass) +deriving instance (ForallLmlModule Eq pass) => Eq (LmlModule pass) diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Decl.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Decl.hs index c5cc246..8715eec 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Decl.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Decl.hs @@ -44,6 +44,7 @@ type ForallLmlDecl (tc :: Type -> Constraint) pass = ) deriving instance (ForallLmlDecl Show pass) => Show (LmlDecl pass) +deriving instance (ForallLmlDecl Eq pass) => Eq (LmlDecl pass) -- | Located open declaration type LOpenDecl pass = XLocated pass (OpenDecl pass) @@ -60,6 +61,7 @@ type ForallOpenDecl (tc :: Type -> Constraint) pass = (tc (XOpenDecl pass), tc (XXOpenDecl pass), tc (LLongident pass)) deriving instance (ForallOpenDecl Show pass) => Show (OpenDecl pass) +deriving instance (ForallOpenDecl Eq pass) => Eq (OpenDecl pass) -- | Located type declaration type LTyDecl pass = XLocated pass (TyDecl pass) @@ -82,6 +84,7 @@ type ForallTyDecl (tc :: Type -> Constraint) pass = ) deriving instance (ForallTyDecl Show pass) => Show (TyDecl pass) +deriving instance (ForallTyDecl Eq pass) => Eq (TyDecl pass) -- | Located ADT constructor declaration type LConDecl pass = XLocated pass (ConDecl pass) @@ -102,3 +105,4 @@ type ForallConDecl (tc :: Type -> Constraint) pass = (tc (XConDecl pass), tc (XLocated pass Text), tc (LLmlType pass), tc (XXConDecl pass)) deriving instance (ForallConDecl Show pass) => Show (ConDecl pass) +deriving instance (ForallConDecl Eq pass) => Eq (ConDecl pass) diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Expr.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Expr.hs index 18f5297..5d30cac 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Expr.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Expr.hs @@ -23,7 +23,7 @@ import Lamagraph.Compiler.Syntax.Pat import Lamagraph.Compiler.Syntax.Type -- | Flag for recursive let-bindings -data RecFlag = Recursive | NonRecursive deriving (Show) +data RecFlag = Recursive | NonRecursive deriving (Show, Eq) -- | Located 'LmlExpr' type LLmlExpr pass = XLocated pass (LmlExpr pass) @@ -81,6 +81,7 @@ type ForallLmlExpr (tc :: Type -> Constraint) pass = ) deriving instance (ForallLmlExpr Show pass) => Show (LmlExpr pass) +deriving instance (ForallLmlExpr Eq pass) => Eq (LmlExpr pass) -- | Located let binder type LLmlBind pass = XLocated pass (LmlBind pass) @@ -97,6 +98,7 @@ type ForallLmlBind (tc :: Type -> Constraint) pass = (tc (XLmlBind pass), tc (LLmlPat pass), tc (LLmlExpr pass), tc (XXBind pass)) deriving instance (ForallLmlBind Show pass) => Show (LmlBind pass) +deriving instance (ForallLmlBind Eq pass) => Eq (LmlBind pass) -- | Located case binder type type LLmlCase pass = XLocated pass (LmlCase pass) @@ -110,3 +112,4 @@ type ForallLmlCase (tc :: Type -> Constraint) pass = (tc (XLmlCase pass), tc (LLmlPat pass), tc (LLmlExpr pass), tc (XXCase pass)) deriving instance (ForallLmlCase Show pass) => Show (LmlCase pass) +deriving instance (ForallLmlCase Eq pass) => Eq (LmlCase pass) diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Extension.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Extension.hs index 2915937..a2ae042 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Extension.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Extension.hs @@ -10,14 +10,14 @@ import Relude {- | Type to serve as a placeholder for TTG extension points, which can be constructed, but aren't used to hold something more useful. -} -data NoExtField = NoExtField deriving (Show) +data NoExtField = NoExtField deriving (Show, Eq) -- | Is used to construct a term. noExtField :: NoExtField noExtField = NoExtField -- | Isomorphic to 'Void'. -data DataConCantHappen deriving (Show) +data DataConCantHappen deriving (Show, Eq) dataConCanHappen :: DataConCantHappen -> a dataConCanHappen x = case x of {} diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Lit.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Lit.hs index a3d4f4d..710b7b8 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Lit.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Lit.hs @@ -30,3 +30,4 @@ type ForallLmlLit (tc :: Type -> Constraint) pass = ) deriving instance (ForallLmlLit Show pass) => Show (LmlLit pass) +deriving instance (ForallLmlLit Eq pass) => Eq (LmlLit pass) diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Longident.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Longident.hs index d9fafb0..c4fbadd 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Longident.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Longident.hs @@ -9,7 +9,7 @@ import Lamagraph.Compiler.Syntax.Extension 'Text' fragments are dot separated in the source code. -} newtype Longident = Longident (NonEmpty Text) - deriving (Show) + deriving (Show, Eq) mkLongident :: NonEmpty Text -> Longident mkLongident = Longident diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Pat.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Pat.hs index 6ddb1e1..fcc8674 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Pat.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Pat.hs @@ -50,3 +50,4 @@ type ForallLmlPat (tc :: Type -> Constraint) pass = ) deriving instance (ForallLmlPat Show pass) => Show (LmlPat pass) +deriving instance (ForallLmlPat Eq pass) => Eq (LmlPat pass) diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Type.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Type.hs index ad854d6..1f768f7 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Type.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Syntax/Type.hs @@ -44,3 +44,4 @@ type ForallLmlType (tc :: Type -> Constraint) pass = ) deriving instance (ForallLmlType Show pass) => Show (LmlType pass) +deriving instance (ForallLmlType Eq pass) => Eq (LmlType pass) diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/Parser/GoldenCommon.hs b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/GoldenCommon.hs new file mode 100644 index 0000000..5f9ffc3 --- /dev/null +++ b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/GoldenCommon.hs @@ -0,0 +1,28 @@ +module Lamagraph.Compiler.Parser.GoldenCommon ( + renderPretty, + parserGoldenTestsDir, + lmlExt, + changeFileDir, +) where + +import Relude + +import Prettyprinter +import Prettyprinter.Render.Text +import System.FilePath + +renderPretty :: Doc ann -> LText +renderPretty = renderLazy . layoutPretty (defaultLayoutOptions{layoutPageWidth = AvailablePerLine 80 1.0}) + +parserGoldenTestsDir :: FilePath +parserGoldenTestsDir = "test" "parserGolden" "source" + +lmlExt :: FilePath +lmlExt = ".lml" + +changeFileDir :: FilePath -> FilePath -> FilePath +changeFileDir filePath relativePath = newDir fileName + where + dir = takeDirectory filePath + newDir = normalise (dir relativePath) + fileName = takeFileName filePath diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/Parser/ParserRoundtrip.hs b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/ParserRoundtrip.hs new file mode 100644 index 0000000..62e9514 --- /dev/null +++ b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/ParserRoundtrip.hs @@ -0,0 +1,264 @@ +{-# LANGUAGE RecordWildCards #-} + +module Lamagraph.Compiler.Parser.ParserRoundtrip (prop_ParserRoundtrip) where + +import Relude + +import Data.List.NonEmpty.Extra qualified as NE +import Data.Text qualified as T +import Hedgehog +import Hedgehog.Gen qualified as Gen +import Hedgehog.Range qualified as Range +import Prettyprinter +import Prettyprinter.Render.Text + +import Lamagraph.Compiler.Extension +import Lamagraph.Compiler.Parser +import Lamagraph.Compiler.Parser.SrcLoc +import Lamagraph.Compiler.PrettyLML () +import Lamagraph.Compiler.Syntax + +{- | '<>' lifted to 'Applicative' +Very useful in this module because of 'Text' concatenation under 'Gen' monad +-} +(.<>.) :: (Applicative f, Semigroup c) => f c -> f c -> f c +a .<>. b = liftA2 (<>) a b + +keywords :: [Text] +keywords = + [ "and" + , "asr" + , "else" + , "false" + , "fun" + , "if" + , "in" + , "land" + , "let" + , "lor" + , "lsl" + , "lsr" + , "lxor" + , "match" + , "mod" + , "module" + , "of" + , "open" + , "rec" + , "then" + , "true" + , "type" + , "when" + , "with" + ] + +isKeyword :: Text -> Bool +isKeyword word = word `elem` keywords + +notKeyword :: Text -> Bool +notKeyword = not . isKeyword + +-- | Mostly 'Gen.alphaNum', but with @_@ +identChar :: Gen Char +identChar = Gen.element "abcdefghiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" + +identRange :: Range Int +identRange = Range.linear 0 11 + +nonEmptyRange :: Range Int +nonEmptyRange = Range.linear 1 6 + +listRange :: Range Int +listRange = Range.linear 0 6 + +declRange :: Range Int +declRange = Range.linear 0 200 + +{-# INLINE mkGenLoc #-} +mkGenLoc :: a -> Located a +mkGenLoc = L generatedSrcSpan + +genCapitalizedIdent :: Gen Text +genCapitalizedIdent = (T.singleton <$> Gen.upper) .<>. Gen.text identRange identChar + +genLCapitalizedIdent :: Gen (Located Text) +genLCapitalizedIdent = mkGenLoc <$> genCapitalizedIdent + +genLowercaseIdent :: Gen Text +genLowercaseIdent = + Gen.choice + [ Gen.filter notKeyword identStartingLetter + , Gen.constant "_" .<>. Gen.text (Range.linear 1 1) Gen.alphaNum .<>. Gen.text identRange identChar + ] + where + identStartingLetter = (T.singleton <$> Gen.lower) .<>. Gen.text identRange identChar + +genLLowercaseIdent :: Gen (Located Text) +genLLowercaseIdent = mkGenLoc <$> genLowercaseIdent + +genLongident :: Gen Text -> Gen Longident +genLongident genLastIdent = do + modulePath <- Gen.nonEmpty nonEmptyRange genCapitalizedIdent + mkLongident . NE.snoc modulePath <$> genLastIdent + +genLLongident :: Gen Text -> Gen (LLongident LmlcPs) +genLLongident genLastIdent = mkGenLoc <$> genLongident genLastIdent + +genValueName :: Gen Text +genValueName = Gen.choice [genLowercaseIdent, genPrefixSymbol, genInfixSymbolFiltered] + where + opTailRange = Range.linear 0 5 + genOpChar = Gen.element "!$%&*+./:<=>?@^|~" + genPrefixSymbol = + Gen.choice + [ pure "!" .<>. Gen.text opTailRange genOpChar + , Gen.choice [pure "?", pure "~"] .<>. Gen.text (Range.linear 1 5) genOpChar + ] + genInfixSymbol = (T.singleton <$> Gen.element "=<>@^|&+-*/$%") .<>. Gen.text opTailRange genOpChar + genInfixSymbolFiltered = Gen.filter (\x -> not (T.isPrefixOf "|" x || T.isPrefixOf "->" x)) genInfixSymbol + +genLValueName :: Gen (Located Text) +genLValueName = mkGenLoc <$> genValueName + +genIdent :: Gen Text +genIdent = + Gen.choice + [ genLowercaseIdent + , genCapitalizedIdent + ] + +genLIdent :: Gen (Located Text) +genLIdent = mkGenLoc <$> genIdent + +genChar :: Gen Char +genChar = Gen.enum '\32' '\126' + +genLmlDecl :: Gen (LmlDecl LmlcPs) +genLmlDecl = do + Gen.choice + [ OpenD noExtField <$> genOpenDecl + , genValD + , TyD noExtField <$> Gen.nonEmpty nonEmptyRange genLTyDecl + ] + +genValD :: Gen (LmlDecl LmlcPs) +genValD = do + binds <- Gen.nonEmpty nonEmptyRange genLLmlBind + flag <- Gen.element [NonRecursive, Recursive] + pure $ ValD noExtField flag binds + +genLLmlDecl :: Gen (LLmlDecl LmlcPs) +genLLmlDecl = mkGenLoc <$> genLmlDecl + +genOpenDecl :: Gen (OpenDecl LmlcPs) +genOpenDecl = do + OpenDecl noExtField <$> genLLongident genCapitalizedIdent + +genTyVars :: Gen [LLmlType LmlcPs] +genTyVars = Gen.list listRange (mkGenLoc . LmlTyVar noExtField <$> genLIdent) + +genTyDecl :: Gen (TyDecl LmlcPs) +genTyDecl = + Gen.choice + [ AliasDecl noExtField <$> genLLowercaseIdent <*> genTyVars <*> genLLmlType + , DataDecl noExtField <$> genLLowercaseIdent <*> genTyVars <*> Gen.list listRange genLConDecl + ] + +genLTyDecl :: Gen (LTyDecl LmlcPs) +genLTyDecl = mkGenLoc <$> genTyDecl + +genConDecl :: Gen (ConDecl LmlcPs) +genConDecl = ConDecl noExtField <$> genLCapitalizedIdent <*> Gen.list listRange genLLmlType + +genLConDecl :: Gen (LConDecl LmlcPs) +genLConDecl = mkGenLoc <$> genConDecl + +genLmlExpr :: Gen (LmlExpr LmlcPs) +genLmlExpr = + Gen.recursive + Gen.choice + [ LmlExprIdent noExtField <$> genLongident genValueName + , LmlExprConstant noExtField <$> genLmlLit + ] + [ LmlExprLet noExtField + <$> Gen.element [NonRecursive, Recursive] + <*> Gen.nonEmpty nonEmptyRange genLLmlBind + <*> genLLmlExpr + , LmlExprFunction noExtField <$> genLLmlPat <*> genLLmlExpr + , let func = (mkGenLoc . LmlExprIdent noExtField <$> genLongident genValueName) + in LmlExprApply noExtField <$> func <*> Gen.nonEmpty nonEmptyRange genLLmlExpr + , LmlExprMatch noExtField <$> genLLmlExpr <*> Gen.nonEmpty nonEmptyRange genLLmlCase + , LmlExprTuple noExtField <$> genLLmlExpr <*> Gen.nonEmpty nonEmptyRange genLLmlExpr + , LmlExprConstruct noExtField <$> genLLongident genCapitalizedIdent <*> Gen.maybe genLLmlExpr + , LmlExprIfThenElse noExtField <$> genLLmlExpr <*> genLLmlExpr <*> genLLmlExpr + , LmlExprConstraint noExtField <$> genLLmlExpr <*> genLLmlType + ] + +genLLmlExpr :: Gen (LLmlExpr LmlcPs) +genLLmlExpr = mkGenLoc <$> genLmlExpr + +genLmlBind :: Gen (LmlBind LmlcPs) +genLmlBind = LmlBind noExtField <$> genLLmlPat <*> genLLmlExpr + +genLLmlBind :: Gen (LLmlBind LmlcPs) +genLLmlBind = mkGenLoc <$> genLmlBind + +genLmlCase :: Gen (LmlCase LmlcPs) +genLmlCase = LmlCase noExtField <$> genLLmlPat <*> Gen.maybe genLLmlExpr <*> genLLmlExpr + +genLLmlCase :: Gen (LLmlCase LmlcPs) +genLLmlCase = mkGenLoc <$> genLmlCase + +genLmlLit :: Gen (LmlLit LmlcPs) +genLmlLit = + Gen.choice + [ LmlInt noExtField <$> Gen.int (Range.linear minBound maxBound) + , LmlInt32 noExtField <$> Gen.int32 (Range.linear minBound maxBound) + , LmlUInt32 noExtField <$> Gen.word32 (Range.linear minBound maxBound) + , LmlInt64 noExtField <$> Gen.int64 (Range.linear minBound maxBound) + , LmlUInt64 noExtField <$> Gen.word64 (Range.linear minBound maxBound) + , LmlChar noExtField <$> genChar + , LmlString noExtField <$> Gen.text (Range.linear 0 25) genChar + ] + +genLmlPat :: Gen (LmlPat LmlcPs) +genLmlPat = + Gen.recursive + Gen.choice + [ pure $ LmlPatAny noExtField + , LmlPatVar noExtField <$> genLValueName + , LmlPatConstant noExtField <$> genLmlLit + ] + [ LmlPatTuple noExtField <$> genLLmlPat <*> Gen.nonEmpty nonEmptyRange genLLmlPat + , LmlPatConstruct noExtField <$> genLLongident genCapitalizedIdent <*> Gen.maybe genLLmlPat + , LmlPatOr noExtField <$> genLLmlPat <*> genLLmlPat + , LmlPatConstraint noExtField <$> genLLmlPat <*> genLLmlType + ] + +genLLmlPat :: Gen (LLmlPat LmlcPs) +genLLmlPat = mkGenLoc <$> genLmlPat + +genLmlType :: Gen (LmlType LmlcPs) +genLmlType = + Gen.recursive + Gen.choice + [LmlTyVar noExtField <$> genLIdent] + [ LmlTyArrow noExtField <$> genLLmlType <*> genLLmlType + , LmlTyTuple noExtField <$> genLLmlType <*> Gen.nonEmpty nonEmptyRange genLLmlType + , LmlTyConstr noExtField <$> genLLongident genLowercaseIdent <*> Gen.list listRange genLLmlType + ] + +genLLmlType :: Gen (LLmlType LmlcPs) +genLLmlType = mkGenLoc <$> genLmlType + +genModule :: Gen (LmlModule LmlcPs) +genModule = do + let _lmlModExt = noExtField + _lmlModName <- Gen.maybe $ genLLongident genCapitalizedIdent + _lmlModDecls <- Gen.list declRange genLLmlDecl + pure LmlModule{..} + +prop_ParserRoundtrip :: Property +prop_ParserRoundtrip = withTests 100 . property $ do + asts <- forAll genModule + tripping asts (renderStrict . layoutPretty defaultLayoutOptions . pretty) parseLamagraphML diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/Parser/PrettyASTGolden.hs b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/PrettyASTGolden.hs new file mode 100644 index 0000000..f565ec4 --- /dev/null +++ b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/PrettyASTGolden.hs @@ -0,0 +1,32 @@ +module Lamagraph.Compiler.Parser.PrettyASTGolden (parserGoldenTestsAST) where + +import Relude + +import Prettyprinter +import System.FilePath +import Test.Tasty +import Test.Tasty.Golden + +import Lamagraph.Compiler.Parser +import Lamagraph.Compiler.Parser.GoldenCommon +import Lamagraph.Compiler.PrettyAST () + +parserGoldenTestsAST :: IO TestTree +parserGoldenTestsAST = do + lmlFiles <- findByExtension [lmlExt] parserGoldenTestsDir + return $ + testGroup + "Pretty AST Golden tests" + [ goldenVsString (takeBaseName lmlFile) resLmlFile (helper lmlFile) + | lmlFile <- lmlFiles + , let resLmlFile = addExtension (changeFileDir lmlFile "../ast") "ast" + ] + where + helper :: FilePath -> IO LByteString + helper lmlFile = do + fileBS <- readFileBS lmlFile + let fileT = decodeUtf8 fileBS + parseResult = parseLamagraphML fileT + pure $ case parseResult of + Left err -> encodeUtf8 err + Right tree -> encodeUtf8 $ (renderPretty . pretty) tree diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/Parser/PrettyLmlGolden.hs b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/PrettyLmlGolden.hs new file mode 100644 index 0000000..593b266 --- /dev/null +++ b/lamagraph-compiler/test/Lamagraph/Compiler/Parser/PrettyLmlGolden.hs @@ -0,0 +1,30 @@ +module Lamagraph.Compiler.Parser.PrettyLmlGolden (parserPrettyLmlGolden) where + +import Relude + +import Prettyprinter +import System.FilePath +import Test.Tasty +import Test.Tasty.Golden + +import Lamagraph.Compiler.Parser +import Lamagraph.Compiler.Parser.GoldenCommon +import Lamagraph.Compiler.PrettyLML () + +parserPrettyLmlGolden :: IO TestTree +parserPrettyLmlGolden = do + lmlFiles <- findByExtension [lmlExt] parserGoldenTestsDir + return $ + testGroup + "Pretty LML Golden tests" + [ goldenVsString (takeBaseName lmlFile) resLmlFile (helper lmlFile) | lmlFile <- lmlFiles, let resLmlFile = changeFileDir lmlFile "../ppr" + ] + where + helper :: FilePath -> IO LByteString + helper lmlFile = do + fileBS <- readFileBS lmlFile + let fileT = decodeUtf8 fileBS + parseResult = parseLamagraphML fileT + pure $ case parseResult of + Left err -> encodeUtf8 err + Right tree -> encodeUtf8 $ (renderPretty . pretty) tree diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/ParserGoldenTest.hs b/lamagraph-compiler/test/Lamagraph/Compiler/ParserGoldenTest.hs deleted file mode 100644 index 04bf1c5..0000000 --- a/lamagraph-compiler/test/Lamagraph/Compiler/ParserGoldenTest.hs +++ /dev/null @@ -1,41 +0,0 @@ -module Lamagraph.Compiler.ParserGoldenTest (parserGoldenTestsAST) where - -import Relude - -import Prettyprinter -import Prettyprinter.Render.Text -import System.FilePath -import Test.Tasty -import Test.Tasty.Golden - -import Lamagraph.Compiler.Parser -import Lamagraph.Compiler.PrettyAST () - -render :: Doc ann -> LText -render = renderLazy . layoutPretty defaultLayoutOptions - -parserGoldenTestsAST :: IO TestTree -parserGoldenTestsAST = do - lmlFiles <- findByExtension [".lml"] "test/parserGolden/source" - return $ - testGroup - "Golden tests AST" - [ goldenVsString (takeBaseName lmlFile) resLmlFile (helper lmlFile) - | lmlFile <- lmlFiles - , let resLmlFile = addExtension (changePath lmlFile) "ast" - ] - where - helper :: FilePath -> IO LByteString - helper lmlFile = do - fileBS <- readFileBS lmlFile - let fileT = decodeUtf8 fileBS - parseResult = parseLamagraphML fileT - pure $ case parseResult of - Left err -> encodeUtf8 err - Right tree -> encodeUtf8 $ (render . pretty) tree - changePath :: FilePath -> FilePath - changePath filePath = astDir fileName - where - parserGoldenDir = takeDirectory $ takeDirectory filePath - astDir = parserGoldenDir "ast" - fileName = takeFileName filePath diff --git a/lamagraph-compiler/test/Spec.hs b/lamagraph-compiler/test/Spec.hs index 540432b..ae9671e 100644 --- a/lamagraph-compiler/test/Spec.hs +++ b/lamagraph-compiler/test/Spec.hs @@ -1,14 +1,17 @@ import Relude import Test.Tasty +import Test.Tasty.Hedgehog import Lamagraph.Compiler.Parser.LexerTest -import Lamagraph.Compiler.ParserGoldenTest +import Lamagraph.Compiler.Parser.ParserRoundtrip +import Lamagraph.Compiler.Parser.PrettyASTGolden +import Lamagraph.Compiler.Parser.PrettyLmlGolden main :: IO () main = do parserTests' <- parserTests - let tests = testGroup "" [lexerTests, parserTests'] + let tests = testGroup "Lamagraph Compiler" [lexerTests, parserTests'] defaultMain tests lexerTests :: TestTree @@ -16,5 +19,7 @@ lexerTests = testGroup "Lexer" [lexerUnitTests] parserTests :: IO TestTree parserTests = do - parserGolden <- parserGoldenTestsAST - return $ testGroup "Parser" [parserGolden] + parserASTGolden <- parserGoldenTestsAST + parserLmlGolden <- parserPrettyLmlGolden + let roundtrip = testPropertyNamed "Parser roundtrip (AST -> LML -> AST)" "prop_ParserRoundtrip" prop_ParserRoundtrip + return $ testGroup "Parser" [parserASTGolden, parserLmlGolden, roundtrip] diff --git a/lamagraph-compiler/test/parserGolden/ast/ConstrPatterns.lml.ast b/lamagraph-compiler/test/parserGolden/ast/ConstrPatterns.lml.ast index a6397f2..571c2e1 100644 --- a/lamagraph-compiler/test/parserGolden/ast/ConstrPatterns.lml.ast +++ b/lamagraph-compiler/test/parserGolden/ast/ConstrPatterns.lml.ast @@ -4,25 +4,31 @@ { :1:8-22 } ("ConstrPatterns"))) [ (L - { :3:1-28 } + { :3:1-36 } (ValD NonRec [ (L - { :3:5-28 } + { :3:5-36 } (Bind (L - { :3:5-15 } + { :3:5-19 } (PatConstruct (L - { :3:5-15 } + { :3:6-16 } ("SomeConstr")) - (Nothing))) + (Just + (L + { :3:17-18 } + (PatAny))))) (L - { :3:18-28 } + { :3:22-36 } (ExprConstruct (L - { :3:18-28 } + { :3:23-33 } ("SomeConstr")) - (Nothing))))) ])) + (Just + (L + { :3:34-35 } + (ExprConstant 1))))))) ])) , (L { :4:1-16 } (ValD NonRec @@ -102,4 +108,84 @@ (L { :7:10-12 } ("[]")) - (Nothing))))) ])) ]) \ No newline at end of file + (Nothing))))) ])) + , (L + { :8:1-22 } + (ValD NonRec + [ (L + { :8:5-22 } + (Bind + (L + { :8:5-13 } + (PatConstruct + (L + { :8:6-8 } + ("::")) + (Just + (L + { :8:5-13 } + (PatTuple + [ (L + { :8:5-6 } + (PatVar + (L + { :8:5-6 } + "a"))) + , (L + { :8:8-13 } + (PatConstruct + (L + { :8:9-11 } + ("::")) + (Just + (L + { :8:8-13 } + (PatTuple + [ (L + { :8:8-9 } + (PatVar + (L + { :8:8-9 } + "b"))) + , (L + { :8:11-13 } + (PatConstruct + (L + { :8:11-13 } + ("[]")) + (Nothing))) ]))))) ]))))) + (L + { :8:17-22 } + (ExprConstruct + (L + { } + ("::")) + (Just + (L + { :8:17-22 } + (ExprTuple + [ (L + { :8:17-18 } + (ExprIdent + "a")) + , (L + { :8:20-22 } + (ExprConstruct + (L + { } + ("::")) + (Just + (L + { :8:20-22 } + (ExprTuple + [ (L + { :8:20-21 } + (ExprIdent + "b")) + , (L + { :8:21-22 } + (ExprConstruct + (L + { } + ("[]")) + (Nothing))) ]))))) ]))))))) ])) ]) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ast/Opens.lml.ast b/lamagraph-compiler/test/parserGolden/ast/Opens.lml.ast new file mode 100644 index 0000000..9e7905c --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ast/Opens.lml.ast @@ -0,0 +1,19 @@ +(Module + (Just + (L + { :1:8-13 } + ("Opens"))) + [ (L + { :3:1-8 } + (OpenD + OpenDecl + (L + { :3:6-8 } + ("M1")))) + , (L + { :5:1-20 } + (OpenD + OpenDecl + (L + { :5:6-20 } + ("Stdlib, Fun, Abs")))) ]) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ast/Types.lml.ast b/lamagraph-compiler/test/parserGolden/ast/Types.lml.ast index be82a8b..2a4cb5a 100644 --- a/lamagraph-compiler/test/parserGolden/ast/Types.lml.ast +++ b/lamagraph-compiler/test/parserGolden/ast/Types.lml.ast @@ -170,4 +170,226 @@ (L { :13:30-33 } ("int")) - [])) ])) ])) ])) ])) ]) \ No newline at end of file + [])) ])) ])) ])) ])) + , (L + { :15:1-108 } + (TyD + [ (L + { :15:7-108 } + (AliasDecl + (L + { :15:19-34 } + "weirdTupleAlias") + [ (L + { :15:7-9 } + (TyVar + (L + { :15:8-9 } + "a"))) + , (L + { :15:11-13 } + (TyVar + (L + { :15:12-13 } + "b"))) + , (L + { :15:15-17 } + (TyVar + (L + { :15:16-17 } + "c"))) ] + (L + { :15:37-108 } + (TyArrow + (L + { :15:37-77 } + (TyArrow + (L + { :15:38-52 } + (TyConstr + (L + { :15:48-52 } + ("list")) + [ (L + { :15:38-47 } + (TyTuple + [ (L + { :15:39-41 } + (TyVar + (L + { :15:40-41 } + "a"))) + , (L + { :15:44-46 } + (TyVar + (L + { :15:45-46 } + "b"))) ])) ])) + (L + { :15:56-76 } + (TyConstr + (L + { :15:72-76 } + ("list")) + [ (L + { :15:56-71 } + (TyConstr + (L + { :15:65-71 } + ("either")) + [ (L + { :15:57-59 } + (TyVar + (L + { :15:58-59 } + "c"))) + , (L + { :15:61-63 } + (TyVar + (L + { :15:62-63 } + "b"))) ])) ])))) + (L + { :15:81-108 } + (TyArrow + (L + { :15:81-102 } + (TyConstr + (L + { :15:96-102 } + ("either")) + [ (L + { :15:82-90 } + (TyArrow + (L + { :15:82-84 } + (TyVar + (L + { :15:83-84 } + "a"))) + (L + { :15:88-90 } + (TyVar + (L + { :15:89-90 } + "b"))))) + , (L + { :15:92-94 } + (TyVar + (L + { :15:93-94 } + "c"))) ])) + (L + { :15:106-108 } + (TyVar + (L + { :15:107-108 } + "c"))))))))) ])) + , (L + { :(17,1)-(19,33) } + (TyD + [ (L + { :(17,6)-(19,33) } + (DataDecl + (L + { :17:6-20 } + "tooMuchConstrs") + [] + [ (L + { :17:23-60 } + (ConDecl + (L + { :17:23-25 } + "C1") + [ (L + { :17:29-60 } + (TyArrow + (L + { :17:30-33 } + (TyConstr + (L + { :17:30-33 } + ("int")) + [])) + (L + { :17:37-59 } + (TyArrow + (L + { :17:37-45 } + (TyConstr + (L + { :17:41-45 } + ("list")) + [ (L + { :17:37-40 } + (TyConstr + (L + { :17:37-40 } + ("int")) + [])) ])) + (L + { :17:49-59 } + (TyConstr + (L + { :17:53-59 } + ("either")) + [ (L + { :17:49-52 } + (TyConstr + (L + { :17:49-52 } + ("int")) + [])) ])))))) ])) + , (L + { :18:23-54 } + (ConDecl + (L + { :18:23-25 } + "C2") + [ (L + { :18:29-54 } + (TyArrow + (L + { :18:30-44 } + (TyConstr + (L + { :18:30-44 } + ("tooMuchConstrs")) + [])) + (L + { :18:48-53 } + (TyConstr + (L + { :18:48-53 } + ("int32")) + [])))) ])) + , (L + { :19:23-33 } + (ConDecl + (L + { :19:23-25 } + "C3") + [ (L + { :19:29-33 } + (TyConstr + (L + { :19:29-33 } + ("bool")) + [])) ])) ])) ])) + , (L + { :21:1-17 } + (TyD + [ (L + { :21:6-17 } + (AliasDecl + (L + { :21:9-11 } + "_t") + [(L { :21:6-8 } (TyVar (L { :21:7-8 } "a")))] + (L + { :21:14-17 } + (TyConstr + (L + { :21:14-17 } + ("int")) + [])))) ])) ]) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/Arif.lml b/lamagraph-compiler/test/parserGolden/ppr/Arif.lml new file mode 100644 index 0000000..4253d4d --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/Arif.lml @@ -0,0 +1 @@ +let x = ( + ) (1) (( * ) (2) (3)) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/Const.lml b/lamagraph-compiler/test/parserGolden/ppr/Const.lml new file mode 100644 index 0000000..2477558 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/Const.lml @@ -0,0 +1,15 @@ +module Const + +let x1 = 1 + +let x2 = 1l + +let x3 = 1ul + +let x4 = 1L + +let x5 = 1UL + +let x6 = 'a' + +let x7 = "ab" \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/ConstrPatterns.lml b/lamagraph-compiler/test/parserGolden/ppr/ConstrPatterns.lml new file mode 100644 index 0000000..ecc7002 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/ConstrPatterns.lml @@ -0,0 +1,13 @@ +module ConstrPatterns + +let (SomeConstr (_)) = (SomeConstr (1)) + +let true = true + +let false = false + +let () = () + +let [] = [] + +let (a :: (b :: [])) = (a :: (b :: [])) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/EmptyModule.lml b/lamagraph-compiler/test/parserGolden/ppr/EmptyModule.lml new file mode 100644 index 0000000..d79e8de --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/EmptyModule.lml @@ -0,0 +1 @@ +module EmptyModule \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/Fac.lml b/lamagraph-compiler/test/parserGolden/ppr/Fac.lml new file mode 100644 index 0000000..1465787 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/Fac.lml @@ -0,0 +1,6 @@ +module Fac + +open Stdlib + +let fac = fun n -> let rec helper = +fun m -> fun acc -> if ( > ) (m) (n) then acc else helper (( + ) (m) (1)) (( * ) (acc) (m)) in helper (1) (1) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/FuncApp.lml b/lamagraph-compiler/test/parserGolden/ppr/FuncApp.lml new file mode 100644 index 0000000..b2ce741 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/FuncApp.lml @@ -0,0 +1 @@ +let x = f (y) (z) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/KakaduExample.lml b/lamagraph-compiler/test/parserGolden/ppr/KakaduExample.lml new file mode 100644 index 0000000..9bcf094 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/KakaduExample.lml @@ -0,0 +1,3 @@ +module KakaduExample + +let x = ( + ) (1) (let y = 5 in ( + ) (5) (y)) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/ListPatterns.lml b/lamagraph-compiler/test/parserGolden/ppr/ListPatterns.lml new file mode 100644 index 0000000..899f856 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/ListPatterns.lml @@ -0,0 +1,9 @@ +module ListPatterns + +let [] = x + +let (a :: []) = x + +let (a :: (b :: [])) = x + +let (a :: (b :: (c :: []))) = x \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/MatchPatAssoc.lml b/lamagraph-compiler/test/parserGolden/ppr/MatchPatAssoc.lml new file mode 100644 index 0000000..7143e6c --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/MatchPatAssoc.lml @@ -0,0 +1,3 @@ +let f = (match x with ((1 | 2) | 3) -> true + | x when ( == ) (x) (4) -> true + | _ -> false) \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/Opens.lml b/lamagraph-compiler/test/parserGolden/ppr/Opens.lml new file mode 100644 index 0000000..66de068 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/Opens.lml @@ -0,0 +1,5 @@ +module Opens + +open M1 + +open Stdlib.Fun.Abs \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/Types.lml b/lamagraph-compiler/test/parserGolden/ppr/Types.lml new file mode 100644 index 0000000..56176af --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/Types.lml @@ -0,0 +1,22 @@ +module Types + +type unit + +type 'a alias = (int -> ('a list -> 'a)) + +type data = C1 of int | C2 + +type 'a list = [] of 'a | (::) of 'a * 'a list + +type ('a, 'b) either = Left of 'a | Right of 'b + +type someTuple = T of (int * int) + +type ('a, 'b, 'c) weirdTupleAlias = ((('a * 'b) list -> ('c, 'b) either list) -> +((('a -> 'b), 'c) either -> 'c)) + +type tooMuchConstrs = C1 of (int -> (int list -> int either)) + | C2 of (tooMuchConstrs -> int32) + | C3 of bool + +type 'a _t = int \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/ppr/ValuePath.lml b/lamagraph-compiler/test/parserGolden/ppr/ValuePath.lml new file mode 100644 index 0000000..402d17e --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/ppr/ValuePath.lml @@ -0,0 +1,3 @@ +let x = M.y +and +y = M.x \ No newline at end of file diff --git a/lamagraph-compiler/test/parserGolden/source/ConstrPatterns.lml b/lamagraph-compiler/test/parserGolden/source/ConstrPatterns.lml index 70f637b..a46d69c 100644 --- a/lamagraph-compiler/test/parserGolden/source/ConstrPatterns.lml +++ b/lamagraph-compiler/test/parserGolden/source/ConstrPatterns.lml @@ -1,7 +1,8 @@ module ConstrPatterns -let SomeConstr = SomeConstr +let (SomeConstr _) = (SomeConstr 1) let true = true let false = false let () = () let [] = [] +let a::b::[] = [a; b] diff --git a/lamagraph-compiler/test/parserGolden/source/Opens.lml b/lamagraph-compiler/test/parserGolden/source/Opens.lml new file mode 100644 index 0000000..a1a1171 --- /dev/null +++ b/lamagraph-compiler/test/parserGolden/source/Opens.lml @@ -0,0 +1,5 @@ +module Opens + +open M1 + +open Stdlib.Fun.Abs diff --git a/lamagraph-compiler/test/parserGolden/source/Types.lml b/lamagraph-compiler/test/parserGolden/source/Types.lml index 250fe61..991b7f9 100644 --- a/lamagraph-compiler/test/parserGolden/source/Types.lml +++ b/lamagraph-compiler/test/parserGolden/source/Types.lml @@ -11,3 +11,11 @@ type 'a list = [] of 'a | (::) of 'a * 'a list type ('a, 'b) either = Left of 'a | Right of 'b type someTuple = T of (int * int) + +type ('a, 'b, 'c) weirdTupleAlias = (('a * 'b) list -> ('c, 'b) either list) -> ('a -> 'b, 'c) either -> 'c + +type tooMuchConstrs = C1 of (int -> int list -> int either) + | C2 of (tooMuchConstrs -> int32) + | C3 of bool + +type 'a _t = int