@@ -144,9 +144,11 @@ instance Free Pred where
144144 free = \case
145145 Update x y z -> free x <> free y <> free z
146146 HasField _ x (_, y) -> free x <> free y
147+ StringOrNumber x -> free x
147148 sub s = \case
148149 Update x y z -> Update (sub s x) (sub s y) (sub s z)
149150 HasField r t (f, v) -> HasField r (sub s t) (f, sub s v)
151+ StringOrNumber x -> StringOrNumber $ sub s x
150152
151153instance Free Scheme where
152154 free (x :=> y) = free x <> free y
@@ -275,6 +277,7 @@ data UnifyingError
275277data PredicateError
276278 = KeyNotPresent Text NType
277279 | NotAnAttributeSet NType
280+ | NotAddable NType
278281 deriving stock (Eq, Show)
279282
280283data InferError
@@ -378,13 +381,12 @@ infer (Fix (Compose (Ann src x))) = local (const src) $ case x of
378381 y : _ -> return $ List y
379382 NUnary NNeg y -> do
380383 t <- infer y
381− -- TODO: Infer either Float or Integer
382− -- tell $ t :~ (normalType . NAtomic $ )
383− return t
384+ t ~~ NAtomic Number
385+ return $ NAtomic Number
384386 NUnary NNot y -> do
385387 t <- infer y
386388 t ~~ NAtomic Bool
387− return t
389+ return $ NAtomic Bool
388390 NBinary NUpdate lhs rhs -> do
389391 lhsT <- infer lhs
390392 rhsT <- infer rhs
@@ -411,7 +413,12 @@ infer (Fix (Compose (Ann src x))) = local (const src) $ case x of
411413 NBinary NLte lhs rhs -> comparison lhs rhs
412414 NBinary NGt lhs rhs -> comparison lhs rhs
413415 NBinary NGte lhs rhs -> comparison lhs rhs
414− NBinary NPlus lhs rhs -> math lhs rhs
416+ NBinary NPlus lhs rhs -> do
417+ lhst <- infer lhs
418+ rhst <- infer rhs
419+ lhst ~~ rhst
420+ tell $ StringOrNumber lhst
421+ return lhst
415422 NBinary NMinus lhs rhs -> math lhs rhs
416423 NBinary NMult lhs rhs -> math lhs rhs
417424 NBinary NDiv lhs rhs -> math lhs rhs
@@ -514,21 +521,23 @@ infer (Fix (Compose (Ann src x))) = local (const src) $ case x of
514521 comparison lhs rhs = do
515522 lhst <- infer lhs
516523 rhst <- infer rhs
517− -- TODO: Infer lhst and rhst are either Integer or Double or String
524+ tell (StringOrNumber lhst)
518525 lhst ~~ rhst
519526 return $ NAtomic Bool
520527 math lhs rhs = do
521528 lhst <- infer lhs
522529 rhst <- infer rhs
523− -- TODO: Infer lhst and rhst are either Integer or Double
524− lhst ~~ rhst
525− return lhst
530+ let t = NAtomic Number
531+ lhst ~~ t
532+ rhst ~~ t
533+ return t
526534 logic lhs rhs = do
527535 lhst <- infer lhs
528536 rhst <- infer rhs
529− rhst ~~ NAtomic Bool
530− lhst ~~ NAtomic Bool
531− return $ NAtomic Bool
537+ let t = NAtomic Bool
538+ rhst ~~ t
539+ lhst ~~ t
540+ return t
532541
533542type NormalizedBinding' = F.Free (Map VarName)
534543
@@ -788,6 +797,7 @@ solveAndClose range (cs :=> t) = evalState @Substitution mempty $ do
788797 solveAndClose newRange $ sub s $ (collectedPreds <> solvedPreds) :=> t
789798
790799solveConstraints ::
800+ forall effs.
791801 Members
792802 '[ Fresh,
793803 Writer Pred,
@@ -802,6 +812,15 @@ solveConstraints ::
802812 Eff effs [Pred]
803813solveConstraints _ [] = pure []
804814solveConstraints range (p : ps) = case p of
815+ -- StringOrNumber
816+ StringOrNumber (NTypeVariable _) -> (p :) <$> solveConstraints range ps
817+ StringOrNumber t -> do
818+ case t of
819+ NAtomic String -> pure ()
820+ NAtomic Number -> pure ()
821+ other -> tell $ NotAddable other
822+ solveConstraints range ps
823+ -- HasField
805824 HasField r (NAttrSet ts) (f, t) -> case M.lookup f ts of
806825 Nothing -> do
807826 case r of
@@ -829,10 +848,19 @@ solveConstraints range (p : ps) = case p of
829848 HasField _ t _ -> do
830849 tell $ NotAnAttributeSet t
831850 solveConstraints range ps
851+ -- Update
832852 (Update (NAttrSet a) (NAttrSet b) t) -> do
833853 (NAttrSet $ b <> a) ~~ t
834854 solveConstraints range ps
835− _ -> (p :) <$> solveConstraints range ps
855+ (Update a b _) -> do
856+ allGood <- check `traverse` ([a, b] :: [NType])
857+ (if and allGood then (p :) else id) <$> solveConstraints range ps
858+ where
859+ check :: NType -> Eff effs Bool
860+ check = \case
861+ NTypeVariable _ -> pure True
862+ NAttrSet _ -> pure True
863+ other -> tell (NotAnAttributeSet other) >> pure False
836864
837865partitionWith :: (a -> Either b c) -> [a] -> ([b], [c])
838866partitionWith f = partitionEithers . map f