diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index cca021e..5b55c8c 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -15,6 +15,7 @@ jobs: with: enable-stack: true stack-version: "latest" + ghc-version: "9.4.8" - name: Cache dependencies uses: actions/cache@v4 @@ -53,6 +54,7 @@ jobs: with: enable-stack: true stack-version: "latest" + ghc-version: "9.4.8" - name: Cache dependencies uses: actions/cache@v4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1c9c025..c8605ff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: trailing-whitespace - id: end-of-file-fixer - exclude: "ast/.*|ppr/.*" + exclude: "ast/.*|ppr/.*|core/.*" - id: check-yaml - id: fix-byte-order-marker - id: mixed-line-ending diff --git a/lamagraph-compiler/lamagraph-compiler.cabal b/lamagraph-compiler/lamagraph-compiler.cabal index 178f566..c1e1a53 100644 --- a/lamagraph-compiler/lamagraph-compiler.cabal +++ b/lamagraph-compiler/lamagraph-compiler.cabal @@ -24,6 +24,10 @@ source-repository head library exposed-modules: + Lamagraph.Compiler.Core + Lamagraph.Compiler.Core.LmlToCore + Lamagraph.Compiler.Core.MonadDesugar + Lamagraph.Compiler.Core.Pretty Lamagraph.Compiler.Extension Lamagraph.Compiler.Parser Lamagraph.Compiler.Parser.Lexer @@ -109,6 +113,7 @@ test-suite lamagraph-compiler-test type: exitcode-stdio-1.0 main-is: Spec.hs other-modules: + Lamagraph.Compiler.Core.PrettyCoreGolden Lamagraph.Compiler.GoldenCommon Lamagraph.Compiler.Parser.LexerTest Lamagraph.Compiler.Parser.ParserRoundtrip diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Core.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Core.hs new file mode 100644 index 0000000..00667b3 --- /dev/null +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Core.hs @@ -0,0 +1,49 @@ +module Lamagraph.Compiler.Core ( + Literal (..), + DataCon, + Var (..), + Expr (..), + MatchAlt, + AltCon (..), + Bind (..), + CoreExpr, + CoreMatchAlt, + CoreBind, +) where + +import Relude + +import Lamagraph.Compiler.Typechecker.TcTypes + +data Literal = LitInt Int | LitChar Char | LitString Text deriving (Show) + +-- FIXME: Must change after addition of ADTs +type DataCon = Name + +-- TODO: Is this wrapper really required? +newtype Var + = Id Name -- Term variable + deriving (Eq, Show) + +data Expr b + = Var b + | Lit Literal + | App (Expr b) (Expr b) + | Lam b (Expr b) + | Let (Bind b) (Expr b) + | -- | For a reason behind this signature see https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/core-syn-type#case-expressions + Match (Expr b) b (NonEmpty (MatchAlt b)) + | -- In Haskell, tuples are just syntactic sugar for @data TupleN a1...aN = TupleN a1...aN@, + -- but in Caml they are separate construction + Tuple (Expr b) (NonEmpty (Expr b)) + deriving (Show) + +type MatchAlt b = (AltCon, [b], Expr b) + +data AltCon = DataAlt DataCon | LitAlt Literal | TupleAlt | DEFAULT deriving (Show) + +data Bind b = NonRec b (Expr b) | Rec (NonEmpty (b, Expr b)) deriving (Show) + +type CoreExpr = Expr Var +type CoreMatchAlt = MatchAlt Var +type CoreBind = Bind Var diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Core/LmlToCore.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Core/LmlToCore.hs new file mode 100644 index 0000000..1d861cf --- /dev/null +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Core/LmlToCore.hs @@ -0,0 +1,162 @@ +module Lamagraph.Compiler.Core.LmlToCore (desugarLmlModule) where + +import Relude + +import Control.Monad.Extra +import Data.Foldable.Extra hiding (elem) + +import Lamagraph.Compiler.Core +import Lamagraph.Compiler.Core.MonadDesugar +import Lamagraph.Compiler.Extension +import Lamagraph.Compiler.Parser.SrcLoc +import Lamagraph.Compiler.Syntax +import Lamagraph.Compiler.Typechecker.DefaultEnv +import Lamagraph.Compiler.Typechecker.TcTypes + +desugarLmlLit :: LmlLit LmlcTc -> Literal +desugarLmlLit = \case + LmlInt _ int -> LitInt int + LmlChar _ char -> LitChar char + LmlString _ string -> LitString string + +desugarLLmlExpr :: LLmlExpr LmlcTc -> MonadDesugar CoreExpr +desugarLLmlExpr (L _ expr) = desugarLmlExpr expr + +desugarLmlExpr :: LmlExpr LmlcTc -> MonadDesugar CoreExpr +desugarLmlExpr = \case + LmlExprIdent _ longident -> pure $ Var $ Id $ Name longident + LmlExprConstant _ lit -> pure $ Lit $ desugarLmlLit lit + LmlExprLet _ lBindGroup lExpr -> foldr Let <$> desugarLLmlExpr lExpr <*> desugarLLmlBindGroup lBindGroup + LmlExprFunction _ lPat lExpr -> Lam <$> desugarLLmlPat lPat <*> desugarLLmlExpr lExpr + LmlExprApply _ lExpr lExprs -> foldl App <$> desugarLLmlExpr lExpr <*> mapM desugarLLmlExpr lExprs + LmlExprMatch _ lExpr lCases -> do + scrutineeVar <- freshVar + expr <- desugarLLmlExpr lExpr + cases <- mapM (desugarLLmlCase scrutineeVar) lCases + pure $ Match expr scrutineeVar cases + LmlExprTuple _ lExpr lExprs -> Tuple <$> desugarLLmlExpr lExpr <*> mapM desugarLLmlExpr lExprs + LmlExprConstruct _ (L _ longident) maybeArgs -> + let constructorVar = Var $ Id $ Name longident + in case maybeArgs of + Nothing -> pure constructorVar + Just lArgs -> App constructorVar <$> desugarLLmlExpr lArgs + LmlExprIfThenElse _ lCond lTrue lFalse -> do + trueExpr <- desugarLLmlExpr lTrue + falseExpr <- desugarLLmlExpr lFalse + let trueAlt = (DataAlt trueConstrName, [], trueExpr) + falseAlt = (DataAlt falseConstrName, [], falseExpr) + condExpr <- desugarLLmlExpr lCond + var <- freshVar + pure $ Match condExpr var (trueAlt :| [falseAlt]) + LmlExprConstraint _ lExpr _ -> desugarLLmlExpr lExpr + +desugarLLmlCase :: Var -> LLmlCase LmlcTc -> MonadDesugar CoreMatchAlt +desugarLLmlCase scrutineeVar (L _ case') = desugarLmlCase scrutineeVar case' + +desugarLmlCase :: Var -> LmlCase LmlcTc -> MonadDesugar CoreMatchAlt +desugarLmlCase scrutineeVar (LmlCase _ (L _ pat) Nothing lExpr) = do + expr <- desugarLLmlExpr lExpr + case pat of + LmlPatAny _ -> pure (DEFAULT, [], expr) + LmlPatVar _ (L _ ident) -> + pure + ( DEFAULT + , [] + , replaceVar (Id $ Name $ mkLongident $ pure ident) scrutineeVar expr + ) + LmlPatConstant _ lit -> pure (LitAlt $ desugarLmlLit lit, [], expr) + LmlPatTuple _ lPat lPats -> + let vars = map helper (lPat : toList lPats) + in pure (TupleAlt, vars, expr) + LmlPatConstruct _ (L _ longident) maybeLPat -> + let constuctorName = Name longident + in case maybeLPat of + Nothing -> pure (DataAlt constuctorName, [], expr) + Just (L _ args) -> + case args of + LmlPatVar _ (L _ ident) -> pure (DataAlt constuctorName, [Id $ Name $ mkLongident $ pure ident], expr) + LmlPatTuple _ lPat lPats -> + let vars = map helper (lPat : toList lPats) + in pure (DataAlt constuctorName, vars, expr) + _ -> error "Internal error: Constructors can only be applied to Var or Tuple." + LmlPatOr{} -> error "FIXME: Or patterns in match expressions aren't supported." + LmlPatConstraint{} -> error "FIXME: Constraints in pattern-matching are currently unsupported." + where + helper lPat = case unLoc lPat of + LmlPatVar _ (L _ ident) -> Id $ Name $ mkLongident $ pure ident + _ -> error "FIXME: Nested patterns are currently unsupported." +desugarLmlCase _ (LmlCase _ _ (Just _) _) = error "FIXME: Guards in pattern-matching are currently unsupported." + +desugarLLmlPat :: LLmlPat LmlcTc -> MonadDesugar Var +desugarLLmlPat (L _ pat) = desugarLmlPat pat + +desugarLmlPat :: LmlPat LmlcTc -> MonadDesugar Var +desugarLmlPat = \case + LmlPatVar _ (L _ ident) -> pure $ Id $ Name $ mkLongident $ pure ident + LmlPatConstraint _ lPat _ -> desugarLLmlPat lPat + _ -> error "FIXME: Only Var and Constraint patterns are currently supported." + +desugarLLmlBindGroup :: LLmlBindGroup LmlcTc -> MonadDesugar (NonEmpty CoreBind) +desugarLLmlBindGroup (L _ bindGroup) = desugarLmlBindGroup bindGroup + +{- | Invariant of this function: +If we have 'Recursive' bind group then we have only one element in the list, +otherwise we have as many elements in the list as let exprs. +-} +desugarLmlBindGroup :: LmlBindGroup LmlcTc -> MonadDesugar (NonEmpty CoreBind) +desugarLmlBindGroup (LmlBindGroup _ NonRecursive lBinds) = do + binds <- mapM desugarLLmlBind lBinds + pure $ fmap (uncurry NonRec) binds +desugarLmlBindGroup (LmlBindGroup _ Recursive lBinds) = do + binds <- mapM desugarLLmlBind lBinds + pure $ pure $ Rec binds + +desugarLLmlBind :: LLmlBind LmlcTc -> MonadDesugar (Var, CoreExpr) +desugarLLmlBind (L _ bind) = desugarLmlBind bind + +desugarLmlBind :: LmlBind LmlcTc -> MonadDesugar (Var, CoreExpr) +desugarLmlBind (LmlBind _ lPat lExpr) = liftA2 (,) (desugarLLmlPat lPat) (desugarLLmlExpr lExpr) + +replaceVar :: Var -> Var -> CoreExpr -> CoreExpr +replaceVar oldVar newVar = \case + var@(Var id') -> if id' == oldVar then Var newVar else var + lit@(Lit _) -> lit + App leftExpr rightExpr -> App (replaceVar oldVar newVar leftExpr) (replaceVar oldVar newVar rightExpr) + lam@(Lam var expr) -> if var == oldVar then lam else Lam var (replaceVar oldVar newVar expr) + Let bind expr -> + let (newBind, control) = replaceVarBind oldVar newVar bind + in if control then Let newBind (replaceVar oldVar newVar expr) else Let newBind expr + Match scrutinee scrutineeVar alts -> + if scrutineeVar == oldVar + then Match (replaceVar oldVar newVar scrutinee) scrutineeVar alts + else Match (replaceVar oldVar newVar scrutinee) scrutineeVar (fmap (replaceVarMatchAlt oldVar newVar) alts) + Tuple expr exprs -> Tuple (replaceVar oldVar newVar expr) $ fmap (replaceVar oldVar newVar) exprs + +{- | Replaces variable in 'Bind'. +If this binding binds variable then we emit 'False' to stop replacing further, otherwise return 'True'. +-} +replaceVarBind :: Var -> Var -> CoreBind -> (CoreBind, Bool) +replaceVarBind oldVar newVar = \case + nr@(NonRec var expr) -> if var == oldVar then (nr, False) else (NonRec newVar (replaceVar oldVar newVar expr), True) + r@(Rec binds) -> + if elem oldVar $ fmap fst binds + then (r, False) + else (Rec $ fmap (second (replaceVar oldVar newVar)) binds, True) + +replaceVarMatchAlt :: Var -> Var -> CoreMatchAlt -> CoreMatchAlt +replaceVarMatchAlt oldVar newVar alt@(altCon, boundVars, expr) = + if oldVar `elem` boundVars + then alt + else + (altCon, boundVars, replaceVar oldVar newVar expr) + +desugarLLmlDecl :: LLmlDecl LmlcTc -> MonadDesugar [CoreBind] +desugarLLmlDecl (L _ decl) = desugarLmlDecl decl + +desugarLmlDecl :: LmlDecl LmlcTc -> MonadDesugar [CoreBind] +desugarLmlDecl = \case + ValD _ lBindGroup -> toList <$> desugarLLmlBindGroup lBindGroup + _ -> pure [] + +desugarLmlModule :: LmlModule LmlcTc -> MonadDesugar [CoreBind] +desugarLmlModule (LmlModule _ _ lDecls) = concatMapM desugarLLmlDecl lDecls diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Core/MonadDesugar.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Core/MonadDesugar.hs new file mode 100644 index 0000000..2e9aaab --- /dev/null +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Core/MonadDesugar.hs @@ -0,0 +1,42 @@ +{-# LANGUAGE TemplateHaskell #-} + +module Lamagraph.Compiler.Core.MonadDesugar (MonadDesugar, runMonadDesugar, freshVar) where + +import Relude +import Relude.Unsafe ((!!)) + +import Control.Lens +import Data.Sequences qualified + +import Lamagraph.Compiler.Core +import Lamagraph.Compiler.Syntax +import Lamagraph.Compiler.Typechecker.TcTypes + +newtype MonadDesugarState = MonadDesugarState {_freshDsCounter :: Int} + +makeLenses 'MonadDesugarState + +defaultMonadDesugarState :: MonadDesugarState +defaultMonadDesugarState = + MonadDesugarState + { _freshDsCounter = 0 + } + +data DesugarError + +type MonadDesugar a = ExceptT DesugarError (State MonadDesugarState) a + +runMonadDesugar :: MonadDesugar a -> Either DesugarError a +runMonadDesugar f = evalState (runExceptT f) defaultMonadDesugarState + +-- FIXME: Copied from Typechecker + +-- | This function generates words @a@, ..., @z@, @aa@, ..., @az@ and so on. +letters :: [Text] +letters = [1 ..] >>= flip Data.Sequences.replicateM ['a' .. 'z'] + +freshVar :: MonadDesugar Var +freshVar = do + count <- use freshDsCounter + freshDsCounter += 1 + pure $ Id $ Name $ mkLongident $ pure $ "t#" <> letters !! count diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Core/Pretty.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Core/Pretty.hs new file mode 100644 index 0000000..c3e5508 --- /dev/null +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Core/Pretty.hs @@ -0,0 +1,76 @@ +{-# OPTIONS_GHC -Wno-orphans #-} + +module Lamagraph.Compiler.Core.Pretty () where + +import Relude + +import Lamagraph.Compiler.Core + +import Lamagraph.Compiler.Syntax.Longident +import Lamagraph.Compiler.Typechecker.TcTypes +import Prettyprinter + +-- TODO: These instances will conflict with "PrettyAST"! + +instance Pretty Longident where + pretty :: Longident -> Doc ann + pretty (Longident idents) = hsep $ punctuate comma (map pretty (toList idents)) + +instance Pretty Name where + pretty :: Name -> Doc ann + pretty (Name longident) = pretty longident + +instance Pretty Var where + pretty :: Var -> Doc ann + pretty (Id name) = pretty name + +instance Pretty CoreBind where + pretty :: CoreBind -> Doc ann + pretty = \case + NonRec var expr -> "let" <+> helper var expr + Rec binds -> "let rec" <+> concatWith (surround (hardline <> "and" <> hardline)) (map inner (toList binds)) + where + inner (var, expr) = helper var expr + where + helper var expr = pretty var <+> "=" <+> align (pretty expr) + prettyList :: [CoreBind] -> Doc ann + prettyList binds = vsep $ map pretty binds + +instance Pretty CoreExpr where + pretty :: CoreExpr -> Doc ann + pretty = \case + Var var -> pretty var + Lit lit -> pretty lit + App expr1 expr2 -> helper expr1 <+> helper expr2 + where + helper expr = case expr of + var@(Var{}) -> pretty var + lit@(Lit{}) -> pretty lit + tuple@(Tuple{}) -> pretty tuple + other -> parens $ pretty other + Lam var expr -> "fun" <+> pretty var <+> "->" <> softline <> pretty expr + Let bind expr -> pretty bind <> softline <> "in" <+> pretty expr + Match scrutinee scrutineeVar alts -> + align $ + "match" + <+> pretty scrutinee + <+> "as" + <+> pretty scrutineeVar + <+> "with" + <+> encloseSep emptyDoc emptyDoc (flatAlt "| " " | ") (map pretty (toList alts)) + Tuple expr exprs -> parens (fillSep $ punctuate comma (map (parens . pretty) (expr : toList exprs))) + +instance Pretty Literal where + pretty :: Literal -> Doc ann + pretty = \case + LitInt int -> pretty int + LitChar char -> squotes $ pretty char + LitString string -> dquotes $ pretty string + +instance Pretty AltCon where + pretty :: AltCon -> Doc ann + pretty = \case + DataAlt dataCon -> pretty dataCon + LitAlt lit -> pretty lit + TupleAlt -> "TUPLE" + DEFAULT -> "DEFAULT" diff --git a/lamagraph-compiler/src/Lamagraph/Compiler/Typechecker/DefaultEnv.hs b/lamagraph-compiler/src/Lamagraph/Compiler/Typechecker/DefaultEnv.hs index 2c05f96..0f3bdaa 100644 --- a/lamagraph-compiler/src/Lamagraph/Compiler/Typechecker/DefaultEnv.hs +++ b/lamagraph-compiler/src/Lamagraph/Compiler/Typechecker/DefaultEnv.hs @@ -1,4 +1,12 @@ -module Lamagraph.Compiler.Typechecker.DefaultEnv (tyInt, tyChar, tyString, tyBool, defaultEnv) where +module Lamagraph.Compiler.Typechecker.DefaultEnv ( + tyInt, + tyChar, + tyString, + tyBool, + trueConstrName, + falseConstrName, + defaultEnv, +) where import Relude @@ -30,6 +38,12 @@ tyString = mkTConstr "string" [] tyBool :: Ty tyBool = mkTConstr "bool" [] +trueConstrName :: Name +trueConstrName = Name $ mkLongident $ pure "true" + +falseConstrName :: Name +falseConstrName = Name $ mkLongident $ pure "false" + tyList :: Ty tyList = mkTConstr "list" [TVar $ Name $ mkLongident $ pure "a"] @@ -63,6 +77,6 @@ defaultEnv = TyEnv env ( Name $ mkLongident $ pure "Some" , Forall [Name $ mkLongident $ pure "a"] (TVar (Name $ mkLongident $ pure "a") `TArrow` tyOption) ) - , (Name $ mkLongident $ pure "true", Forall [] tyBool) - , (Name $ mkLongident $ pure "false", Forall [] tyBool) + , (trueConstrName, Forall [] tyBool) + , (falseConstrName, Forall [] tyBool) ] diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/Core/PrettyCoreGolden.hs b/lamagraph-compiler/test/Lamagraph/Compiler/Core/PrettyCoreGolden.hs new file mode 100644 index 0000000..fab4ace --- /dev/null +++ b/lamagraph-compiler/test/Lamagraph/Compiler/Core/PrettyCoreGolden.hs @@ -0,0 +1,45 @@ +module Lamagraph.Compiler.Core.PrettyCoreGolden (corePrettyGolden) where + +import Relude + +import Prettyprinter +import System.FilePath +import Test.Tasty +import Test.Tasty.Golden + +import Lamagraph.Compiler.Core.LmlToCore +import Lamagraph.Compiler.Core.MonadDesugar +import Lamagraph.Compiler.Core.Pretty () +import Lamagraph.Compiler.GoldenCommon +import Lamagraph.Compiler.Parser +import Lamagraph.Compiler.Typechecker.Infer + +newExt :: String +newExt = "core" + +newDir :: FilePath +newDir = ".." "core" + +corePrettyGolden :: IO TestTree +corePrettyGolden = do + lmlFiles <- findByExtension [lmlExt] coreSourceGoldenTestsDir + return $ + testGroup + "Core Golden tests" + [ goldenVsString (takeBaseName lmlFile) resLmlFile (helper lmlFile) + | lmlFile <- lmlFiles + , let resLmlFile = addExtension (changeFileDir lmlFile newDir) newExt + ] + 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 -> case inferDef tree of + Left err -> show err + Right core -> case (runMonadDesugar . desugarLmlModule) core of + Left _ -> "FIXME: Either add constructors to DesugarError, or get rid of ExceptT" + Right t -> encodeUtf8 $ (renderPretty . pretty) t diff --git a/lamagraph-compiler/test/Lamagraph/Compiler/GoldenCommon.hs b/lamagraph-compiler/test/Lamagraph/Compiler/GoldenCommon.hs index ca36ad2..586cffb 100644 --- a/lamagraph-compiler/test/Lamagraph/Compiler/GoldenCommon.hs +++ b/lamagraph-compiler/test/Lamagraph/Compiler/GoldenCommon.hs @@ -2,6 +2,7 @@ module Lamagraph.Compiler.GoldenCommon ( renderPretty, parserSourceGoldenTestsDir, typecheckerSourceGoldenTestsDir, + coreSourceGoldenTestsDir, lmlExt, changeFileDir, ) where @@ -24,6 +25,9 @@ parserSourceGoldenTestsDir = baseGoldenTestsDir "parser" "source" typecheckerSourceGoldenTestsDir :: FilePath typecheckerSourceGoldenTestsDir = baseGoldenTestsDir "typechecker" "source" +coreSourceGoldenTestsDir :: FilePath +coreSourceGoldenTestsDir = baseGoldenTestsDir "core" "source" + lmlExt :: FilePath lmlExt = ".lml" diff --git a/lamagraph-compiler/test/Spec.hs b/lamagraph-compiler/test/Spec.hs index 9e1efed..28e0118 100644 --- a/lamagraph-compiler/test/Spec.hs +++ b/lamagraph-compiler/test/Spec.hs @@ -3,6 +3,7 @@ import Relude import Test.Tasty import Test.Tasty.Hedgehog +import Lamagraph.Compiler.Core.PrettyCoreGolden import Lamagraph.Compiler.Parser.LexerTest import Lamagraph.Compiler.Parser.ParserRoundtrip import Lamagraph.Compiler.Parser.PrettyAstGolden @@ -13,7 +14,8 @@ main :: IO () main = do parserTests' <- parserTests typecheckerTests' <- typeCheckerTests - let tests = testGroup "Lamagraph Compiler" [lexerTests, parserTests', typecheckerTests'] + coreTests' <- coreTests + let tests = testGroup "Lamagraph Compiler" [lexerTests, parserTests', typecheckerTests', coreTests'] defaultMain tests lexerTests :: TestTree @@ -30,3 +32,8 @@ typeCheckerTests :: IO TestTree typeCheckerTests = do tc <- typecheckerPrettyAstGolden pure $ testGroup "Typechecker" [tc] + +coreTests :: IO TestTree +coreTests = do + core <- corePrettyGolden + pure $ testGroup "Core" [core] diff --git a/lamagraph-compiler/test/golden/core/core/Fac.lml.core b/lamagraph-compiler/test/golden/core/core/Fac.lml.core new file mode 100644 index 0000000..44bda54 --- /dev/null +++ b/lamagraph-compiler/test/golden/core/core/Fac.lml.core @@ -0,0 +1,13 @@ +let fac = fun n -> let rec helper = fun m -> fun acc -> + match (> m) n as t#a with (true, [], acc) + | ( false + , [] + , (helper ((+ m) 1)) ((* acc) m) ) + in (helper 1) 1 +let rec fac' = fun n -> match (< n) 2 as t#b with (true, [], 1) + | (false, [], (* n) (fac' ((- n) 1))) +let rec fix = fun f -> fun x -> (f (fix f)) x +let rec fixCBV = fun f -> fun x -> (f (fixCBV f)) x +let rec fixCBN = fun f -> f (fixCBN f) +let fac'' = fun self -> fun n -> match (<= n) 1 as t#c with (true, [], 1) + | (false, [], (* n) (self ((- n) 1))) \ No newline at end of file diff --git a/lamagraph-compiler/test/golden/core/core/T.lml.core b/lamagraph-compiler/test/golden/core/core/T.lml.core new file mode 100644 index 0000000..cdb1dc1 --- /dev/null +++ b/lamagraph-compiler/test/golden/core/core/T.lml.core @@ -0,0 +1,3 @@ +let f = fun x -> match x as t#a with (1, [], 2) + | (2, [], 1) + | (DEFAULT, [], (* t#a) 7) \ No newline at end of file diff --git a/lamagraph-compiler/test/golden/core/source/Fac.lml b/lamagraph-compiler/test/golden/core/source/Fac.lml new file mode 120000 index 0000000..7857dbd --- /dev/null +++ b/lamagraph-compiler/test/golden/core/source/Fac.lml @@ -0,0 +1 @@ +../../typechecker/source/Fac.lml \ No newline at end of file diff --git a/lamagraph-compiler/test/golden/core/source/T.lml b/lamagraph-compiler/test/golden/core/source/T.lml new file mode 100644 index 0000000..1c7e89d --- /dev/null +++ b/lamagraph-compiler/test/golden/core/source/T.lml @@ -0,0 +1,4 @@ +let f x = match x with + | 1 -> 2 + | 2 -> 1 + | y -> y * 7