mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-01 15:53:00 +03:00
536 lines
24 KiB
Elm
536 lines
24 KiB
Elm
module Simplify.InferTest exposing (all)
|
|
|
|
import AssocList
|
|
import Elm.Syntax.Expression exposing (Expression(..))
|
|
import Elm.Syntax.Infix as Infix exposing (InfixDirection(..))
|
|
import Elm.Syntax.Node exposing (Node(..))
|
|
import Elm.Syntax.Range as Range
|
|
import Expect exposing (Expectation)
|
|
import Simplify.Infer exposing (DeducedValue(..), Fact(..), Inferred(..), deduceNewFacts, empty, falseExpr, get, infer, trueExpr)
|
|
import Test exposing (Test, describe, test)
|
|
|
|
|
|
all : Test
|
|
all =
|
|
describe "Infer"
|
|
[ simpleTests
|
|
, detailedTests
|
|
, deduceNewFactsTests
|
|
]
|
|
|
|
|
|
simpleTests : Test
|
|
simpleTests =
|
|
describe "get"
|
|
[ test "should infer a is true when a is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer [ FunctionOrValue [] "a" ] True
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal (Just trueExpr)
|
|
, test "should infer a is true when a is False" <|
|
|
\() ->
|
|
empty
|
|
|> infer [ FunctionOrValue [] "a" ] False
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal (Just falseExpr)
|
|
, test "should infer a is 1 when a == 1 is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Floatable 1))
|
|
]
|
|
True
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal (Just (Floatable 1))
|
|
, test "should not infer a when a == 1 is False" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Floatable 1))
|
|
]
|
|
False
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal Nothing
|
|
, test "should infer a is true when a && b is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "&&"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal (Just trueExpr)
|
|
, test "should infer b is true when a && b is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "&&"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> get (FunctionOrValue [] "b")
|
|
|> Expect.equal (Just trueExpr)
|
|
, test "should not infer a when a || b is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal Nothing
|
|
, test "should not infer b when a || b is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> get (FunctionOrValue [] "b")
|
|
|> Expect.equal Nothing
|
|
, test "should infer a is false when a || b is False" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
False
|
|
|> get (FunctionOrValue [] "a")
|
|
|> Expect.equal (Just falseExpr)
|
|
, test "should infer b is false when a || b is False" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
False
|
|
|> get (FunctionOrValue [] "b")
|
|
|> Expect.equal (Just falseExpr)
|
|
, test "should infer b is true when a || b is True and a is False" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> infer [ FunctionOrValue [] "a" ]
|
|
False
|
|
|> get (FunctionOrValue [] "b")
|
|
|> Expect.equal (Just trueExpr)
|
|
, test "should infer b is true when b || a is True and a is False" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "b"))
|
|
(n (FunctionOrValue [] "a"))
|
|
]
|
|
True
|
|
|> infer [ FunctionOrValue [] "a" ]
|
|
False
|
|
|> get (FunctionOrValue [] "b")
|
|
|> Expect.equal (Just trueExpr)
|
|
, test "should not infer b when a || b is True and a is True" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> infer [ FunctionOrValue [] "a" ]
|
|
True
|
|
|> get (FunctionOrValue [] "b")
|
|
|> Expect.equal Nothing
|
|
]
|
|
|
|
|
|
detailedTests : Test
|
|
detailedTests =
|
|
describe "infer"
|
|
[ test "should infer a when True" <|
|
|
\() ->
|
|
infer
|
|
[ FunctionOrValue [] "a" ]
|
|
True
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "a") falseExpr
|
|
, Equals (FunctionOrValue [] "a") trueExpr
|
|
]
|
|
, deduced =
|
|
[ ( FunctionOrValue [] "a"
|
|
, DTrue
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a when False" <|
|
|
\() ->
|
|
infer
|
|
[ FunctionOrValue [] "a" ]
|
|
False
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "a") trueExpr
|
|
, Equals (FunctionOrValue [] "a") falseExpr
|
|
]
|
|
, deduced =
|
|
[ ( FunctionOrValue [] "a"
|
|
, DFalse
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a == True when True" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n trueExpr)
|
|
]
|
|
True
|
|
empty
|
|
|> expectEqual
|
|
{ deduced =
|
|
[ ( FunctionOrValue [] "a", DTrue )
|
|
, ( OperatorApplication "/=" Non (n (FunctionOrValue [] "a")) (n trueExpr), DFalse )
|
|
, ( OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n trueExpr), DTrue )
|
|
]
|
|
, facts =
|
|
[ Equals (FunctionOrValue [] "a") trueExpr
|
|
, NotEquals (OperatorApplication "/=" Non (n (FunctionOrValue [] "a")) (n trueExpr)) trueExpr
|
|
, NotEquals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n trueExpr)) falseExpr
|
|
, Equals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n trueExpr)) trueExpr
|
|
]
|
|
}
|
|
, test "should infer a == True when False" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n trueExpr)
|
|
]
|
|
False
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ Equals (FunctionOrValue [] "a") falseExpr
|
|
, NotEquals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n trueExpr)) trueExpr
|
|
, Equals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n trueExpr)) falseExpr
|
|
]
|
|
, deduced =
|
|
[ ( FunctionOrValue [] "a"
|
|
, DFalse
|
|
)
|
|
, ( OperatorApplication "=="
|
|
Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n trueExpr)
|
|
, DFalse
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a == 1 when True" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Floatable 1))
|
|
]
|
|
True
|
|
empty
|
|
|> expectEqual
|
|
{ deduced =
|
|
[ ( FunctionOrValue [] "a", DNumber 1 )
|
|
, ( OperatorApplication "/=" Non (n (FunctionOrValue [] "a")) (n (Floatable 1)), DFalse )
|
|
, ( OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Floatable 1)), DTrue )
|
|
]
|
|
, facts =
|
|
[ Equals (FunctionOrValue [] "a") (Floatable 1)
|
|
, NotEquals (OperatorApplication "/=" Non (n (FunctionOrValue [] "a")) (n (Floatable 1))) trueExpr
|
|
, NotEquals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Floatable 1))) falseExpr
|
|
, Equals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Floatable 1))) trueExpr
|
|
]
|
|
}
|
|
, test "should infer a == 1 when False" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Floatable 1))
|
|
]
|
|
False
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "a") (Floatable 1)
|
|
, NotEquals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Floatable 1))) trueExpr
|
|
, Equals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Floatable 1))) falseExpr
|
|
]
|
|
, deduced =
|
|
[ ( OperatorApplication "=="
|
|
Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Floatable 1))
|
|
, DFalse
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a == \"ok\" when True" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Literal "\"ok\""))
|
|
]
|
|
True
|
|
empty
|
|
|> expectEqual
|
|
{ deduced =
|
|
[ ( FunctionOrValue [] "a", DString "\"ok\"" )
|
|
, ( OperatorApplication "/=" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\"")), DFalse )
|
|
, ( OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\"")), DTrue )
|
|
]
|
|
, facts =
|
|
[ Equals (FunctionOrValue [] "a") (Literal "\"ok\"")
|
|
, NotEquals (OperatorApplication "/=" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\""))) trueExpr
|
|
, NotEquals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\""))) falseExpr
|
|
, Equals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\""))) trueExpr
|
|
]
|
|
}
|
|
, test "should infer a == \"ok\" when False" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "=="
|
|
Infix.Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Literal "\"ok\""))
|
|
]
|
|
False
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "a") (Literal "\"ok\"")
|
|
, NotEquals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\""))) trueExpr
|
|
, Equals (OperatorApplication "==" Non (n (FunctionOrValue [] "a")) (n (Literal "\"ok\""))) falseExpr
|
|
]
|
|
, deduced =
|
|
[ ( OperatorApplication "=="
|
|
Non
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (Literal "\"ok\""))
|
|
, DFalse
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a && b when True" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "&&"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "b") falseExpr
|
|
, Equals (FunctionOrValue [] "b") trueExpr
|
|
, NotEquals (FunctionOrValue [] "a") falseExpr
|
|
, Equals (FunctionOrValue [] "a") trueExpr
|
|
, NotEquals (OperatorApplication "&&" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) falseExpr
|
|
, Equals (OperatorApplication "&&" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) trueExpr
|
|
]
|
|
, deduced =
|
|
[ ( FunctionOrValue [] "b", DTrue )
|
|
, ( FunctionOrValue [] "a", DTrue )
|
|
, ( OperatorApplication "&&"
|
|
Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
, DTrue
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a && b when False" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "&&"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
False
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ Or [ Equals (FunctionOrValue [] "a") falseExpr, NotEquals (FunctionOrValue [] "a") trueExpr ] [ Equals (FunctionOrValue [] "b") falseExpr, NotEquals (FunctionOrValue [] "b") trueExpr ]
|
|
, NotEquals (OperatorApplication "&&" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) trueExpr
|
|
, Equals (OperatorApplication "&&" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) falseExpr
|
|
]
|
|
, deduced =
|
|
[ ( OperatorApplication "&&"
|
|
Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
, DFalse
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a || b when True" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ Or [ Equals (FunctionOrValue [] "a") trueExpr, NotEquals (FunctionOrValue [] "a") falseExpr ] [ Equals (FunctionOrValue [] "b") trueExpr, NotEquals (FunctionOrValue [] "b") falseExpr ]
|
|
, NotEquals (OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) falseExpr
|
|
, Equals (OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) trueExpr
|
|
]
|
|
, deduced =
|
|
[ ( OperatorApplication "||"
|
|
Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
, DTrue
|
|
)
|
|
]
|
|
}
|
|
, test "should infer a || b when False" <|
|
|
\() ->
|
|
infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
False
|
|
empty
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "b") trueExpr
|
|
, Equals (FunctionOrValue [] "b") falseExpr
|
|
, NotEquals (FunctionOrValue [] "a") trueExpr
|
|
, Equals (FunctionOrValue [] "a") falseExpr
|
|
, NotEquals (OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) trueExpr
|
|
, Equals (OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) falseExpr
|
|
]
|
|
, deduced =
|
|
[ ( FunctionOrValue [] "b", DFalse )
|
|
, ( FunctionOrValue [] "a", DFalse )
|
|
, ( OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b")), DFalse )
|
|
]
|
|
}
|
|
, test "should infer a || b when True and a when False" <|
|
|
\() ->
|
|
empty
|
|
|> infer
|
|
[ OperatorApplication "||"
|
|
Infix.Right
|
|
(n (FunctionOrValue [] "a"))
|
|
(n (FunctionOrValue [] "b"))
|
|
]
|
|
True
|
|
|> infer [ FunctionOrValue [] "a" ]
|
|
False
|
|
|> expectEqual
|
|
{ facts =
|
|
[ NotEquals (FunctionOrValue [] "a") trueExpr
|
|
, NotEquals (FunctionOrValue [] "b") falseExpr
|
|
, Equals (FunctionOrValue [] "b") trueExpr
|
|
, Equals (FunctionOrValue [] "a") falseExpr
|
|
, Or [ Equals (FunctionOrValue [] "a") trueExpr, NotEquals (FunctionOrValue [] "a") falseExpr ] [ Equals (FunctionOrValue [] "b") trueExpr, NotEquals (FunctionOrValue [] "b") falseExpr ]
|
|
, NotEquals (OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) falseExpr
|
|
, Equals (OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b"))) trueExpr
|
|
]
|
|
, deduced =
|
|
[ ( FunctionOrValue [] "a", DFalse )
|
|
, ( FunctionOrValue [] "b", DTrue )
|
|
, ( OperatorApplication "||" Right (n (FunctionOrValue [] "a")) (n (FunctionOrValue [] "b")), DTrue )
|
|
]
|
|
}
|
|
]
|
|
|
|
|
|
deduceNewFactsTests : Test
|
|
deduceNewFactsTests =
|
|
describe "deduceNewFacts"
|
|
[ test "should not deduce anything when facts don't share anything (a == True, b == True)" <|
|
|
\() ->
|
|
deduceNewFacts
|
|
(Equals (FunctionOrValue [] "b") trueExpr)
|
|
[ Equals (FunctionOrValue [] "a") trueExpr ]
|
|
|> Expect.equal []
|
|
, test "should deduce b is True when (a || b) and (a == False)" <|
|
|
\() ->
|
|
deduceNewFacts
|
|
(Equals (FunctionOrValue [] "a") falseExpr)
|
|
[ Or
|
|
[ Equals (FunctionOrValue [] "a") trueExpr ]
|
|
[ Equals (FunctionOrValue [] "b") trueExpr ]
|
|
]
|
|
|> Expect.equal
|
|
[ Equals (FunctionOrValue [] "b") trueExpr ]
|
|
]
|
|
|
|
|
|
expectEqual :
|
|
{ facts : List Fact
|
|
, deduced : List ( Expression, DeducedValue )
|
|
}
|
|
-> Inferred
|
|
-> Expectation
|
|
expectEqual record (Inferred inferred) =
|
|
{ facts = inferred.facts
|
|
, deduced = AssocList.toList inferred.deduced
|
|
}
|
|
|> Expect.equal record
|
|
|
|
|
|
n : Expression -> Node Expression
|
|
n =
|
|
Node Range.emptyRange
|