{-# LANGUAGE OverloadedStrings #-} module Jikka.RestrictedPython.Convert.ToCoreSpec (spec) where import Jikka.Common.Alpha import Jikka.Common.Error import qualified Jikka.Core.Format as Y (formatProgram) import qualified Jikka.Core.Language.BuiltinPatterns as Y import qualified Jikka.Core.Language.Expr as Y import qualified Jikka.Core.Parse as Y (parseProgram) import Jikka.RestrictedPython.Convert.ToCore (run) import qualified Jikka.RestrictedPython.Language.Expr as X import qualified Jikka.RestrictedPython.Language.WithoutLoc as X import Test.Hspec run' :: X.Program -> Either Error Y.Program run' = flip evalAlphaT 0 . run parseProgram :: [String] -> Y.Program parseProgram = fromSuccess . flip evalAlphaT 100 . Y.parseProgram . unlines spec :: Spec spec = describe "run" $ do it "works" $ do let prog = [ X.ToplevelFunctionDef "solve" [("n", X.IntTy)] X.IntTy [ X.If (X.eqExp X.IntTy (X.name "n") (X.constIntExp 0)) [ X.Return (X.constIntExp 1) ] [ X.Return (X.binOp (X.name "n") X.Mult (X.call (X.name "solve") [X.binOp (X.name "n") X.Sub (X.constIntExp 1)])) ] ] ] let expected = Y.ToplevelLetRec "solve" [("n", Y.IntTy)] Y.IntTy ( Y.If' (Y.VarTy "$0") (Y.Equal' Y.IntTy (Y.Var "n") Y.Lit0) Y.Lit1 ( Y.Mult' (Y.Var "n") (Y.App (Y.Var "solve") (Y.Minus' (Y.Var "n") Y.Lit1)) ) ) (Y.ResultExpr (Y.Var "solve")) run' prog `shouldBe` Right expected it "converts for-loops to foldl" $ do let prog = [ X.ToplevelFunctionDef "solve" [("n", X.IntTy)] X.IntTy [ X.AnnAssign (X.nameTrg "a") X.IntTy (X.constIntExp 0), X.AnnAssign (X.nameTrg "b") X.IntTy (X.constIntExp 1), X.For (X.nameTrg "i") (X.call (X.constBuiltinExp X.BuiltinRange1) [X.name "n"]) [ X.AnnAssign (X.nameTrg "c") X.IntTy (X.binOp (X.name "a") X.Add (X.name "b")), X.AnnAssign (X.nameTrg "a") X.IntTy (X.name "b"), X.AnnAssign (X.nameTrg "b") X.IntTy (X.name "c") ], X.Return (X.name "a") ] ] let expected = parseProgram [ "let rec solve (n: int): int =", " let a: $0 = 0", " in let b: $1 = 1", " in let $4: $5 * $6 =", " foldl (fun ($4: $5 * $6) ($3: $2) ->", " let b: $5 = $4.0", " in let a: $6 = $4.1", " in let i: $7 = $3", " in let c: $8 = a + b", " in let a: $9 = b", " in let b: $10 = c", " in (b, a)", " ) (b, a) (range n)", " in let b: $5 = $4.0", " in let a: $6 = $4.1", " in a", "in", "solve" ] (Y.formatProgram <$> run' prog) `shouldBe` Right (Y.formatProgram expected) it "converts if-statements correctly" $ do let prog = [ X.ToplevelFunctionDef "solve" [] X.IntTy [ X.If (X.constBoolExp True) [ X.AnnAssign (X.nameTrg "x") X.IntTy (X.constIntExp 1) ] [ X.AnnAssign (X.nameTrg "x") X.IntTy (X.constIntExp 0) ], X.Return (X.name "x") ] ] let expected = parseProgram [ "let rec solve : int =", " let $2: $1 one_tuple = if true", " then let x: $3 = 1 in (x,)", " else let x: $5 = 0 in (x,)", " in let x: $1 = $2.0", " in x", "in", "solve" ] (Y.formatProgram <$> run' prog) `shouldBe` Right (Y.formatProgram expected)