@@ -697,7 +697,7 @@ evalPrimOp env = case _ of
697697 | NeutLit (LitInt 0) <- x ->
698698 evalPrimOp env (Op1 OpIntNegate y)
699699 OpIntNum op
700− | Just result <- evalPrimOpNum OpIntNum liftInt caseInt op x y ->
700+ | Just result <- evalPrimOpNumInt op x y ->
701701 result
702702 OpIntOrd op
703703 | NeutLit (LitInt a) <- x
@@ -707,18 +707,18 @@ evalPrimOp env = case _ of
707707 | NeutLit (LitNumber 0.0) <- x ->
708708 evalPrimOp env (Op1 OpNumberNegate y)
709709 OpNumberNum op
710− | Just result <- evalPrimOpNum OpNumberNum liftNumber caseNumber op x y ->
710+ | Just result <- evalPrimOpNumNumber op x y ->
711711 result
712712 OpNumberOrd op
713713 | NeutLit (LitNumber a) <- x
714714 , NeutLit (LitNumber b) <- y ->
715− liftBoolean (evalPrimOpOrd op a b)
715+ liftBoolean (evalPrimOpOrdNumber op a b)
716716 OpStringOrd op
717717 | NeutLit (LitString a) <- x
718718 , NeutLit (LitString b) <- y ->
719719 liftBoolean (evalPrimOpOrd op a b)
720720 OpStringAppend
721− | Just result <- evalPrimOpAssocL OpStringAppend caseString (\a b -> liftString (a <> b)) x y ->
721+ | Just result <- evalPrimOpAssocL OpStringAppend caseString (\a b -> Just $ liftString (a <> b)) x y ->
722722 result
723723 OpArrayIndex
724724 | NeutLit (LitInt n) <- y ->
@@ -743,19 +743,19 @@ evalPrimOp env = case _ of
743743 evalAssocLet2 env x y \_ x' y' ->
744744 NeutPrimOp (Op2 op2 x' y')
745745
746−evalPrimOpAssocL :: forall a. BackendOperator2 -> (BackendSemantics -> Maybe a) -> (a -> a -> BackendSemantics) -> BackendSemantics -> BackendSemantics -> Maybe BackendSemantics
746+evalPrimOpAssocL :: forall a. BackendOperator2 -> (BackendSemantics -> Maybe a) -> (a -> a -> Maybe BackendSemantics) -> BackendSemantics -> BackendSemantics -> Maybe BackendSemantics
747747evalPrimOpAssocL op match combine a b = case match a of
748748 Just lhs
749749 | Just rhs <- match b ->
750− Just $ combine lhs rhs
750+ combine lhs rhs
751751 | Just (Tuple x y) <- decompose b ->
752752 case match x of
753753 Just rhs ->
754− Just $ liftOp2 op (combine lhs rhs) y
754+ (\x' -> liftOp2 op x' y) <$> combine lhs rhs
755755 Nothing
756756 | Just (Tuple v w) <- decompose x
757757 , Just rhs <- match v ->
758− Just $ liftOp2 op (liftOp2 op (combine lhs rhs) w) y
758+ (\v' -> liftOp2 op (liftOp2 op v' w) y) <$> combine lhs rhs
759759 _ ->
760760 Nothing
761761 Nothing
@@ -763,11 +763,11 @@ evalPrimOpAssocL op match combine a b = case match a of
763763 , Just (Tuple v w) <- decompose a ->
764764 case match w of
765765 Just lhs ->
766− Just $ liftOp2 op v (combine lhs rhs)
766+ liftOp2 op v <$> combine lhs rhs
767767 Nothing
768768 | Just (Tuple x y) <- decompose w
769769 , Just lhs <- match y ->
770− Just $ liftOp2 op (liftOp2 op v x) (combine lhs rhs)
770+ liftOp2 op (liftOp2 op v x) <$> combine lhs rhs
771771 _ ->
772772 Nothing
773773 _ ->
@@ -788,29 +788,66 @@ evalPrimOpOrd op x y = case op of
788788 OpLt -> x < y
789789 OpLte -> x <= y
790790
791−evalPrimOpNum
792− :: forall a
793− . EuclideanRing a
794− => (BackendOperatorNum -> BackendOperator2)
795− -> (a -> BackendSemantics)
796− -> (BackendSemantics -> Maybe a)
797− -> BackendOperatorNum
798− -> BackendSemantics
799− -> BackendSemantics
800− -> Maybe BackendSemantics
801−evalPrimOpNum injOp inj prj op x y = case op of
791+-- Duplicate because inlined operators behave differently with NaN.
792+-- This just ensures we get the same behavior for const eval.
793+evalPrimOpOrdNumber :: BackendOperatorOrd -> Number -> Number -> Boolean
794+evalPrimOpOrdNumber op x y = case op of
795+ OpEq -> x == y
796+ OpNotEq -> x /= y
797+ OpGt -> x > y
798+ OpGte -> x >= y
799+ OpLt -> x < y
800+ OpLte -> x <= y
801+
802+evalPrimOpNumNumber :: BackendOperatorNum -> BackendSemantics -> BackendSemantics -> Maybe BackendSemantics
803+evalPrimOpNumNumber op x y = case op of
804+ OpAdd ->
805+ evalPrimOpAssocL (OpNumberNum OpAdd) caseNumber (\a b -> Just $ liftNumber (a + b)) x y
806+ OpMultiply ->
807+ evalPrimOpAssocL (OpNumberNum OpMultiply) caseNumber (\a b -> Just $ liftNumber (a * b)) x y
808+ OpSubtract
809+ | NeutLit (LitNumber a) <- x
810+ , NeutLit (LitNumber b) <- y ->
811+ Just $ liftNumber (a - b)
812+ OpDivide
813+ | NeutLit (LitNumber a) <- x
814+ , NeutLit (LitNumber b) <- y ->
815+ Just $ liftNumber (a / b)
816+ _ ->
817+ Nothing
818+
819+evalPrimOpNumInt :: BackendOperatorNum -> BackendSemantics -> BackendSemantics -> Maybe BackendSemantics
820+evalPrimOpNumInt op x y = case op of
802821 OpAdd ->
803− evalPrimOpAssocL (injOp op) prj (\a b -> inj (a + b)) x y
822+ evalPrimOpAssocL (OpIntNum OpAdd) caseInt addOverflow x y
823+ where
824+ addOverflow a b = do
825+ let res = a + b
826+ if b > 0 && res < a || b < 0 && res > a then
827+ Nothing
828+ else
829+ Just $ liftInt res
804830 OpMultiply ->
805− evalPrimOpAssocL (injOp op) prj (\a b -> inj (a * b)) x y
831+ evalPrimOpAssocL (OpIntNum OpMultiply) caseInt mulOverflow x y
832+ where
833+ mulOverflow a b = do
834+ let res = a * b
835+ if a /= (res / b) then
836+ Nothing
837+ else
838+ Just $ liftInt res
806839 OpSubtract
807− | Just a <- prj x
808− , Just b <- prj y ->
809− Just $ inj (a - b)
840+ | NeutLit (LitInt a) <- x
841+ , NeutLit (LitInt b) <- y -> do
842+ let res = a - b
843+ if b > 0 && res > a || b < 0 && res < a then
844+ Nothing
845+ else
846+ Just $ liftInt res
810847 OpDivide
811− | Just a <- prj x
812− , Just b <- prj y ->
813− Just $ inj (a / b)
848+ | NeutLit (LitInt a) <- x
849+ , NeutLit (LitInt b) <- y ->
850+ Just $ liftInt (a / b)
814851 _ ->
815852 Nothing
816853