Skip to content

Commit cc89558

Browse files
joelburgetbts
authored andcommitted
Overhaul analysis error system to use Info.
1 parent a9c363d commit cc89558

File tree

4 files changed

+110
-104
lines changed

4 files changed

+110
-104
lines changed

‎src/Pact/Analyze/Analyze.hs‎

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{-# LANGUAGE FlexibleContexts #-}
22
{-# LANGUAGE FlexibleInstances #-}
3+
{-# LANGUAGE FunctionalDependencies #-}
34
{-# LANGUAGE GADTs #-}
45
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
56
{-# LANGUAGE LambdaCase #-}
@@ -58,7 +59,7 @@ import Data.Traversable (for)
5859
import System.Locale
5960

6061
import qualified Pact.Types.Hash as Pact
61-
import Pact.Types.Lang (Parsed)
62+
import Pact.Types.Lang (Info)
6263
import Pact.Types.Runtime (PrimType (TyBool, TyDecimal, TyInteger, TyKeySet, TyString, TyTime),
6364
Type (TyPrim), tShow)
6465
import qualified Pact.Types.Runtime as Pact
@@ -73,11 +74,12 @@ import Pact.Analyze.Util
7374

7475
data AnalyzeEnv
7576
= AnalyzeEnv
76-
{ _aeScope :: Map VarId AVal -- used as a stack
77-
, _aeKeySets :: SFunArray KeySetName KeySet -- read-only
78-
, _aeKsAuths :: SFunArray KeySet Bool -- read-only
79-
, _invariants :: TableMap [(Parsed, Invariant Bool)]
80-
, _aeModelTags :: ModelTags
77+
{ _aeScope :: !(Map VarId AVal) -- used as a stack
78+
, _aeKeySets :: !(SFunArray KeySetName KeySet) -- read-only
79+
, _aeKsAuths :: !(SFunArray KeySet Bool) -- read-only
80+
, _invariants :: !(TableMap [(Info, Invariant Bool)])
81+
, _aeModelTags :: !ModelTags
82+
, _aeInfo :: !Info
8183
}
8284
deriving Show
8385

@@ -122,7 +124,7 @@ data LatticeAnalyzeState
122124
-- finer-grained tracking, so that we can test whether a single
123125
-- invariant is being maintained
124126
--
125-
, _lasMaintainsInvariants :: TableMap (ZipList (Parsed, SBV Bool))
127+
, _lasMaintainsInvariants :: TableMap (ZipList (Info, SBV Bool))
126128
, _lasTablesRead :: SFunArray TableName Bool
127129
, _lasTablesWritten :: SFunArray TableName Bool
128130
, _lasIntCellDeltas :: TableMap (ColumnMap (SFunArray RowKey Integer))
@@ -221,7 +223,7 @@ data AnalyzeFailureNoLoc
221223
deriving (Eq, Show)
222224

223225
data AnalyzeFailure = AnalyzeFailure
224-
{ _analyzeFailureParsed :: !Parsed
226+
{ _analyzeFailureParsed :: !Info
225227
, _analyzeFailure :: !AnalyzeFailureNoLoc
226228
}
227229

@@ -336,9 +338,6 @@ mkSymbolicCells tables = TableMap $ Map.fromList cellsList
336338
mkSVal :: SBV a -> SBVI.SVal
337339
mkSVal (SBVI.SBV v) = v
338340

339-
throwErrorNoLoc :: MonadError AnalyzeFailure m => AnalyzeFailureNoLoc -> m a
340-
throwErrorNoLoc = throwError . AnalyzeFailure dummyParsed
341-
342341
describeAnalyzeFailureNoLoc :: AnalyzeFailureNoLoc -> Text
343342
describeAnalyzeFailureNoLoc = \case
344343
-- these are internal errors. not quite as much care is taken on the messaging
@@ -395,8 +394,8 @@ newtype Query a
395394
deriving (Functor, Applicative, Monad, MonadReader QueryEnv,
396395
MonadError AnalyzeFailure)
397396

398-
mkAnalyzeEnv :: [Table] -> ModelTags -> AnalyzeEnv
399-
mkAnalyzeEnv tables tags =
397+
mkAnalyzeEnv :: [Table] -> ModelTags -> Info -> AnalyzeEnv
398+
mkAnalyzeEnv tables tags info =
400399
let keySets' = mkFreeArray "keySets"
401400
keySetAuths = mkFreeArray "keySetAuths"
402401

@@ -407,7 +406,7 @@ mkAnalyzeEnv tables tags =
407406
argMap :: Map VarId AVal
408407
argMap = view (located._2._2) <$> _mtArgs tags
409408

410-
in AnalyzeEnv argMap keySets' keySetAuths invariants' tags
409+
in AnalyzeEnv argMap keySets' keySetAuths invariants' tags info
411410

412411
instance (Mergeable a) => Mergeable (Analyze a) where
413412
symbolicMerge force test left right = Analyze $ RWST $ \r s -> ExceptT $ Identity $
@@ -444,26 +443,36 @@ class HasAnalyzeEnv a where
444443
instance HasAnalyzeEnv AnalyzeEnv where analyzeEnv = id
445444
instance HasAnalyzeEnv QueryEnv where analyzeEnv = qeAnalyzeEnv
446445

447-
class (MonadError AnalyzeFailure m) => Analyzer m term where
448-
analyze :: (Show a, SymWord a) => term a -> m (S a)
446+
class (MonadError AnalyzeFailure m) => Analyzer m term | m -> term where
447+
analyze :: (Show a, SymWord a) => term a -> m (S a)
448+
throwErrorNoLoc :: AnalyzeFailureNoLoc -> m a
449449

450450
class Analyzer m term => ObjectAnalyzer m term where
451451
analyzeO :: term Object -> m Object
452452

453453
instance Analyzer Analyze Term where
454454
analyze = analyzeTerm
455+
throwErrorNoLoc err = do
456+
info <- view (analyzeEnv . aeInfo)
457+
throwError $ AnalyzeFailure info err
455458

456459
instance ObjectAnalyzer Analyze Term where
457460
analyzeO = analyzeTermO
458461

459462
instance Analyzer Query Prop where
460463
analyze = analyzeProp
464+
throwErrorNoLoc err = do
465+
info <- view (analyzeEnv . aeInfo)
466+
throwError $ AnalyzeFailure info err
461467

462468
instance ObjectAnalyzer Query Prop where
463469
analyzeO = analyzePropO
464470

465471
instance Analyzer InvariantCheck Invariant where
466472
analyze = checkInvariant
473+
throwErrorNoLoc err = do
474+
info <- view _1
475+
throwError $ AnalyzeFailure info err
467476

468477
class SymbolicTerm term where
469478
injectS :: S a -> term a
@@ -544,7 +553,7 @@ tagVarBinding vid av = do
544553
succeeds :: Lens' AnalyzeState (S Bool)
545554
succeeds = latticeState.lasSucceeds.sbv2S
546555

547-
maintainsInvariants :: Lens' AnalyzeState (TableMap (ZipList (Parsed, SBool)))
556+
maintainsInvariants :: Lens' AnalyzeState (TableMap (ZipList (Info, SBool)))
548557
maintainsInvariants = latticeState.lasMaintainsInvariants
549558

550559
tableRead :: TableName -> Lens' AnalyzeState (S Bool)
@@ -685,7 +694,7 @@ ksAuthorized sKs = do
685694
fmap sansProv $ readArray <$> view ksAuths <*> pure (_sSbv sKs)
686695

687696
aval
688-
:: MonadError AnalyzeFailure m
697+
:: Analyzer m term
689698
=> (Maybe Provenance -> SBVI.SVal -> m a)
690699
-> (Object -> m a)
691700
-> AVal
@@ -695,17 +704,17 @@ aval elimVal elimObj = \case
695704
AnObj obj -> elimObj obj
696705
OpaqueVal -> throwErrorNoLoc OpaqueValEncountered
697706

698-
expectVal :: MonadError AnalyzeFailure m => AVal -> m (S a)
707+
expectVal :: Analyzer m term => AVal -> m (S a)
699708
expectVal = aval (pure ... mkS) (throwErrorNoLoc . AValUnexpectedlyObj)
700709

701-
expectObj :: MonadError AnalyzeFailure m => AVal -> m Object
710+
expectObj :: Analyzer m term => AVal -> m Object
702711
expectObj = aval ((throwErrorNoLoc . AValUnexpectedlySVal) ... getSVal) pure
703712
where
704713
getSVal :: Maybe Provenance -> SBVI.SVal -> SBVI.SVal
705714
getSVal = flip const
706715

707716
lookupObj
708-
:: (MonadReader r m, HasAnalyzeEnv r, MonadError AnalyzeFailure m)
717+
:: (Analyzer m term, MonadReader r m, HasAnalyzeEnv r)
709718
=> Text
710719
-> VarId
711720
-> m Object
@@ -718,7 +727,7 @@ lookupObj name vid = do
718727
Just (OpaqueVal) -> throwErrorNoLoc OpaqueValEncountered
719728

720729
lookupVal
721-
:: (MonadReader r m, HasAnalyzeEnv r, MonadError AnalyzeFailure m)
730+
:: (Analyzer m term, MonadReader r m, HasAnalyzeEnv r)
722731
=> Text
723732
-> VarId
724733
-> m (S a)
@@ -745,10 +754,10 @@ applyInvariants tn sValFields addInvariants = do
745754
case mInvariants of
746755
Nothing -> pure ()
747756
Just invariants' -> do
748-
invariants'' <- for invariants' $ \(parsed, invariant) ->
749-
case runReaderT (checkInvariant invariant) sValFields of
757+
invariants'' <- for invariants' $ \(info, invariant) ->
758+
case runReaderT (checkInvariant invariant) (info, sValFields) of
750759
-- Use the location of the invariant
751-
Left (AnalyzeFailure _ err) -> throwError $ AnalyzeFailure parsed err
760+
Left (AnalyzeFailure _ err) -> throwError $ AnalyzeFailure info err
752761
Right inv -> pure inv
753762
addInvariants invariants''
754763

@@ -974,14 +983,14 @@ analyzeUnaryArithOp op term = do
974983
Signum -> pure $ signum x
975984

976985
analyzeModOp
977-
:: Analyzer m term
986+
:: (Analyzer m term)
978987
=> term Integer
979988
-> term Integer
980989
-> m (S Integer)
981990
analyzeModOp xT yT = sMod <$> analyze xT <*> analyze yT
982991

983992
analyzeRoundingLikeOp1
984-
:: Analyzer m term
993+
:: (Analyzer m term)
985994
=> RoundingLikeOp
986995
-> term Decimal
987996
-> m (S Integer)
@@ -1069,7 +1078,7 @@ analyzeIntAddTime timeT secsT = do
10691078
pure $ time + fromIntegralS (secs * 1000000)
10701079

10711080
analyzeDecAddTime
1072-
:: Analyzer m term
1081+
:: (Analyzer m term)
10731082
=> term Time
10741083
-> term Decimal
10751084
-> m (S Time)
@@ -1200,9 +1209,8 @@ analyzeTerm = \case
12001209
sValFields = Map.mapMaybe id mValFields
12011210

12021211
applyInvariants tn sValFields $ \invariants' ->
1203-
let fs :: ZipList ((Parsed, SBV Bool) -> (Parsed, SBV Bool))
1212+
let fs :: ZipList ((Info, SBV Bool) -> (Info, SBV Bool))
12041213
fs = ZipList $ (\s (p, s') -> (p, _sSbv s &&& s')) <$> invariants'
1205-
-- fs = ZipList $ (\s (p, s') -> (p, sSbv s &&& s')) <$> invariants'
12061214
in maintainsInvariants . at tn . _Just %= (fs <*>)
12071215

12081216
--
@@ -1289,7 +1297,7 @@ analyzeTerm = \case
12891297
Hash value -> do
12901298
let sHash = literalS . T.unpack . Pact.asString . Pact.hash
12911299
notStaticErr :: AnalyzeFailure
1292-
notStaticErr = AnalyzeFailure dummyParsed "We can only analyze calls to `hash` with statically determined contents"
1300+
notStaticErr = AnalyzeFailure dummyInfo "We can only analyze calls to `hash` with statically determined contents"
12931301
case value of
12941302
-- Note that strings are hashed in a different way from the other types
12951303
ETerm tm TStr -> analyze tm <&> unliteralS >>= \case
@@ -1340,13 +1348,13 @@ format s tms = do
13401348
if plen == 1
13411349
then Right (literalS s)
13421350
else if plen - length tms > 1
1343-
then Left (AnalyzeFailure dummyParsed "format: not enough arguments for template")
1351+
then Left (AnalyzeFailure dummyInfo "format: not enough arguments for template")
13441352
else Right $ foldl'
13451353
(\r (e, t) -> r .++ rep e .++ t)
13461354
(head parts)
13471355
(zip tms (tail parts))
13481356

1349-
type InvariantCheck = ReaderT (Map Text SBVI.SVal) (Either AnalyzeFailure)
1357+
type InvariantCheck = ReaderT (Info, Map Text SBVI.SVal) (Either AnalyzeFailure)
13501358

13511359
checkInvariant :: Invariant a -> InvariantCheck (S a)
13521360
checkInvariant = \case
@@ -1362,7 +1370,7 @@ checkInvariant = \case
13621370

13631371
-- variables
13641372
IVar name -> do
1365-
mVal <- view (at name)
1373+
mVal <- view (_2 . at name)
13661374
case mVal of
13671375
Just val -> pure (sansProv (SBVI.SBV val))
13681376
Nothing -> throwErrorNoLoc $ fromString $
@@ -1564,7 +1572,7 @@ analyzeCheck = fmap Identity . \case
15641572

15651573
-- | A convenience to treat a nested 'TableMap', '[]', and tuple as a single
15661574
-- functor instead of three.
1567-
newtype InvariantsF a = InvariantsF { unInvariantsF :: TableMap [(Parsed, a)] }
1575+
newtype InvariantsF a = InvariantsF { unInvariantsF :: TableMap [(Info, a)] }
15681576

15691577
instance Functor InvariantsF where
15701578
fmap f (InvariantsF a) = InvariantsF (f <$$$> a)
@@ -1577,7 +1585,7 @@ analyzeInvariants = assumingSuccess =<< invariantsHold'
15771585
success <- view (qeAnalyzeState.succeeds)
15781586
pure $ (success ==>) <$> ps
15791587

1580-
invariantsHold :: Query (TableMap (ZipList (Parsed, S Bool)))
1588+
invariantsHold :: Query (TableMap (ZipList (Info, S Bool)))
15811589
invariantsHold = sansProv <$$$$> view (qeAnalyzeState.maintainsInvariants)
15821590

15831591
invariantsHold' :: Query (InvariantsF (S Bool))
@@ -1590,10 +1598,11 @@ runAnalysis'
15901598
-> [Table]
15911599
-> ETerm
15921600
-> ModelTags
1601+
-> Info
15931602
-> ExceptT AnalyzeFailure Symbolic (f AnalysisResult)
1594-
runAnalysis' query tables tm tags = do
1603+
runAnalysis' query tables tm tags info = do
15951604
let act = analyzeETerm tm >>= \res -> tagResult res >> pure res
1596-
aEnv = mkAnalyzeEnv tables tags
1605+
aEnv = mkAnalyzeEnv tables tags info
15971606
state0 = mkInitialAnalyzeState tables
15981607

15991608
(funResult, state1, ()) <- hoist generalize $
@@ -1612,14 +1621,16 @@ runPropertyAnalysis
16121621
-> [Table]
16131622
-> ETerm
16141623
-> ModelTags
1624+
-> Info
16151625
-> ExceptT AnalyzeFailure Symbolic AnalysisResult
1616-
runPropertyAnalysis check tables tm tags =
1617-
runIdentity <$> runAnalysis' (analyzeCheck check) tables tm tags
1626+
runPropertyAnalysis check tables tm tags info =
1627+
runIdentity <$> runAnalysis' (analyzeCheck check) tables tm tags info
16181628

16191629
runInvariantAnalysis
16201630
:: [Table]
16211631
-> ETerm
16221632
-> ModelTags
1623-
-> ExceptT AnalyzeFailure Symbolic (TableMap [(Parsed, AnalysisResult)])
1624-
runInvariantAnalysis tables tm tags =
1625-
unInvariantsF <$> runAnalysis' analyzeInvariants tables tm tags
1633+
-> Info
1634+
-> ExceptT AnalyzeFailure Symbolic (TableMap [(Info, AnalysisResult)])
1635+
runInvariantAnalysis tables tm tags info =
1636+
unInvariantsF <$> runAnalysis' analyzeInvariants tables tm tags info

0 commit comments

Comments
 (0)