Skip to content

Commit 0974c35

Browse files
committed
Merge branch 'master' into 32-ES-to-master
2 parents 093f2e6 + bc14718 commit 0974c35

File tree

3 files changed

+44
-27
lines changed

3 files changed

+44
-27
lines changed

grin/src/Grin/Lint.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,7 @@ lint warningKinds mTypeEnv exp@(Program exts _) =
317317
expectedPatType <- normalizeType <$> mTypeOfValTE typeEnv lpat
318318
lhsType <- normalizeType <$> extract leftExp
319319
pure $ do -- Lint
320-
-- NOTE: This can still give false positive errors, because bottom-up typing can only approximate the result of HPT.
321-
when (sameType expectedPatType lhsType == Just False) $ do
320+
when (subType expectedPatType lhsType == Just False) $ do
322321
warning Semantics $ [beforeMsg $ unwords
323322
["Invalid pattern match for", plainShow lpat ++ "." , "Expected pattern of type:", plainShow expectedPatType ++ ",", "but got:", plainShow lhsType]]
324323

grin/src/Grin/TypeEnv.hs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import Data.Map (Map)
1111
import Data.Set (Set)
1212
import Data.Vector (Vector)
1313
import qualified Data.Map as Map
14-
import qualified Data.Set as Set (fromList, toList)
15-
import qualified Data.Vector as Vector (fromList, toList, map)
14+
import qualified Data.Set as Set
15+
import qualified Data.Vector as Vector
1616
import Data.Bifunctor (bimap)
1717
import Data.Monoid
1818
import Data.Maybe (fromMaybe)
@@ -181,6 +181,29 @@ sameType (T_SimpleType T_UnspecifiedLocation) _ = Nothing
181181
sameType _ (T_SimpleType T_UnspecifiedLocation) = Nothing
182182
sameType t1 t2 = Just $ t1 == t2
183183

184+
subType :: Type -> Type -> Maybe Bool
185+
subType (T_SimpleType T_Dead) _ = Nothing
186+
subType _ (T_SimpleType T_Dead) = Nothing
187+
subType (T_SimpleType T_UnspecifiedLocation) _ = Nothing
188+
subType _ (T_SimpleType T_UnspecifiedLocation) = Nothing
189+
subType (T_SimpleType st1) (T_SimpleType st2) = Just $ simpleSubType st1 st2
190+
subType (T_NodeSet t1) (T_NodeSet t2) = do -- t1 <: t2
191+
let ks1 = Map.keysSet t1
192+
let ks2 = Map.keysSet t2
193+
let subset = ks1 `Set.isSubsetOf` ks2
194+
pure $ subset && and [ Vector.length v1 == Vector.length v2
195+
&& (Vector.all id (Vector.zipWith simpleSubType v1 v2))
196+
| (t,v1) <- Map.toList t1
197+
, Just v2 <- pure $ Map.lookup t t2
198+
]
199+
subType _ _ = Nothing
200+
201+
simpleSubType :: SimpleType -> SimpleType -> Bool
202+
simpleSubType T_UnspecifiedLocation (T_Location l) = True
203+
simpleSubType (T_Location ls1) (T_Location ls2) =
204+
(Set.fromList ls1) `Set.isSubsetOf` (Set.fromList ls2)
205+
simpleSubType t1 t2 = t1 == t2
206+
184207
ptrLocations :: TypeEnv -> Name -> [Loc]
185208
ptrLocations te p = case variableType te p of
186209
T_SimpleType (T_Location locs) -> locs

grin/test/LintSpec.hs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -224,45 +224,40 @@ spec = do
224224
let (_, errors) = lint allWarnings (Just typeEnv) program
225225
lintErrors errors `shouldBe` ["Invalid pattern match for (CInt x). Expected pattern of type: {CInt[T_Dead]}, but got: {CFloat[T_Float]}"]
226226

227-
it "disregards variable patterns" $ do
227+
it "doesn't alert over-approximated binds" $ do
228228
let program = [prog|
229229
main =
230-
n0 <- pure (CInt 0)
231-
n1 <- case n0 of
232-
(CInt c0) -> pure n0
233-
(CFloat c1) ->
234-
a0 <- pure (CFloat 2.0)
235-
pure a0
230+
i <- pure (CInt 1)
231+
f <- pure (CFloat 1.0)
232+
l <- store i
233+
update l f
234+
v <- fetch l
235+
(CFloat f2) <- pure v
236236
pure ()
237237
|]
238238
let typeEnv = inferTypeEnv program
239239
let (_, errors) = lint allWarnings (Just typeEnv) program
240240
lintErrors errors `shouldBe` []
241241

242-
-- NOTE: Bottom-up typing can only approximate the result of HPT.
243-
it "can give false positive errors" $ do
242+
it "disregards variable patterns" $ do
244243
let program = [prog|
245244
main =
246-
n0 <- case 0 of
247-
0 ->
248-
n1 <- pure (CInt 0)
249-
pure n1
250-
1 ->
251-
n2 <- pure (CFloat 0.0)
252-
pure n2
253-
(CInt x) <- case n0 of
245+
k0 <- pure 0
246+
n0 <- pure (CInt k0)
247+
n1 <- case n0 of
254248
(CInt c0) -> pure n0
255249
(CFloat c1) ->
256-
a0 <- pure (CInt 0)
250+
k1 <- pure 2.0
251+
a0 <- pure (CFloat k1)
257252
pure a0
258253
pure ()
259254
|]
260255
let typeEnv = inferTypeEnv program
261256
let (_, errors) = lint allWarnings (Just typeEnv) program
262-
lintErrors errors `shouldBe` ["Invalid pattern match for (CInt x). Expected pattern of type: {CInt[T_Int64]}, but got: {CFloat[T_Float],CInt[T_Int64]}"]
257+
lintErrors errors `shouldBe` []
263258

264259
describe "Producer lint" $ do
265-
it "finds nodes in single return statment" $ do
260+
it "finds nodes in single return statement" $ do
266261
let program = [prog|
267262
grinMain =
268263
pure (CInt 5)
@@ -271,7 +266,7 @@ spec = do
271266
let (_, errors) = lint allWarnings (Just typeEnv) program
272267
lintErrors errors `shouldBe` ["Last return expressions can only return non-node values: pure (CInt 5)"]
273268

274-
it "finds nodes in last return statment" $ do
269+
it "finds nodes in last return statement" $ do
275270
let program = [prog|
276271
grinMain =
277272
n <- pure (CInt 0)
@@ -281,7 +276,7 @@ spec = do
281276
let (_, errors) = lint allWarnings (Just typeEnv) program
282277
lintErrors errors `shouldBe` ["Last return expressions can only return non-node values: pure (CInt 5)"]
283278

284-
it "finds nodes in single return statment in case alternative" $ do
279+
it "finds nodes in single return statement in case alternative" $ do
285280
let program = [prog|
286281
grinMain =
287282
case 0 of
@@ -291,7 +286,7 @@ spec = do
291286
let (_, errors) = lint allWarnings (Just typeEnv) program
292287
lintErrors errors `shouldBe` ["Last return expressions can only return non-node values: pure (CInt 5)"]
293288

294-
it "finds nodes in last return statment in case alternative" $ do
289+
it "finds nodes in last return statement in case alternative" $ do
295290
let program = [prog|
296291
grinMain =
297292
case 0 of

0 commit comments

Comments
 (0)