@@ -140,10 +140,11 @@ lookupVars = foldMap $ \case
140140 addSlot l = zipWith (\ (name, typ) slot -> (name, (typ, slot))) l [0 .. ]
141141
142142
143- lookupConstructors :: [U. Contract ] -> Map Id [AbiType ]
143+ lookupConstructors :: [U. Contract ] -> Map Id [( AbiType , Maybe Id ) ]
144144lookupConstructors = foldMap $ \ case
145- U. Contract (U. Definition _ contract (Interface _ decls) _ _ _ _ _) _ ->
146- Map. singleton contract (map (\ (Decl t _) -> t) decls)
145+ U. Contract (U. Definition _ contract (Interface _ decls) pointers _ _ _ _) _ ->
146+ let ptrs = Map. fromList $ map (\ (PointsTo _ x c) -> (x, c)) pointers in
147+ Map. singleton contract (map (\ (Decl t x) -> (t, Map. lookup x ptrs)) decls)
147148
148149-- | Extracts what we need to build a 'Store' and to verify that its names are unique.
149150-- Kind of stupid return type but it makes it easier to use the same function
@@ -155,12 +156,12 @@ fromAssign (U.AssignStruct _ _) = error "TODO: assignstruct"
155156
156157-- | The type checking environment.
157158data Env = Env
158- { contract :: Id -- ^ The name of the current contract.
159- , store :: Map Id SlotType -- ^ This contract's storage entry names and their types.
160- , theirs :: Store -- ^ Mapping from contract names to a map of their entry names and their types.
161- , calldata :: Map Id AbiType -- ^ The calldata var names and their types.
162- , pointers :: Map Id Id -- ^ Maps address calldata variables to their contract type.
163- , constructors :: Map Id [AbiType ] -- ^ Interfaces of contract contructors (we only allow constructor calls ATM)
159+ { contract :: Id -- ^ The name of the current contract.
160+ , store :: Map Id SlotType -- ^ This contract's storage entry names and their types.
161+ , theirs :: Store -- ^ Mapping from contract names to a map of their entry names and their types.
162+ , calldata :: Map Id AbiType -- ^ The calldata var names and their types.
163+ , pointers :: Map Id Id -- ^ Maps address calldata variables to their contract type.
164+ , constructors :: Map Id [( AbiType , Maybe Id ) ] -- ^ Interfaces of contract contructors together with points to contraints
164165 }
165166
166167-- typing of eth env variables
@@ -182,7 +183,7 @@ defaultStore =
182183 ]
183184
184185
185- mkEnv :: Id -> Store -> Map Id [AbiType ] -> Env
186+ mkEnv :: Id -> Store -> Map Id [( AbiType , Maybe Id ) ] -> Env
186187mkEnv contract store constructors = Env
187188 { contract = contract
188189 , store = Map. map fst $ fromMaybe mempty (Map. lookup contract store)
@@ -204,7 +205,7 @@ addPointers decls env = env{ pointers = ptrs }
204205 where
205206 ptrs = Map. fromList $ map (\ (PointsTo _ x c) -> (x, c)) decls
206207
207- checkContract :: Store -> Map Id [AbiType ] -> U. Contract -> Err Contract
208+ checkContract :: Store -> Map Id [( AbiType , Maybe Id ) ] -> U. Contract -> Err Contract
208209checkContract store constructors (U. Contract constr@ (U. Definition _ cid _ _ _ _ _ _) trans) =
209210 Contract <$> checkDefinition env constr <*> (concat <$> traverse (checkTransition env) trans) <* namesConsistent
210211 where
@@ -314,7 +315,7 @@ noStorageRead store expr = for_ (keys store) $ \name ->
314315checkAssign :: Env -> U. Assign -> Err [StorageUpdate ]
315316checkAssign env@ Env {contract,store} (U. AssignVal (U. StorageVar pn (StorageValue vt@ (FromVType typ)) name) expr)
316317 = sequenceA [checkExpr env typ expr `bindValidation` \ te ->
317- checkContractType env typ te `bindValidation` \ ctyp ->
318+ findContractType env te `bindValidation` \ ctyp ->
318319 _Update (_Item vt (SVar pn contract name)) te <$ validContractType pn vt ctyp]
319320 <* noStorageRead store expr
320321
@@ -426,7 +427,7 @@ checkStorageExpr :: Env -> U.Entry -> U.Expr -> Err StorageUpdate
426427checkStorageExpr env entry expr =
427428 validateEntry env entry `bindValidation` \ (vt@ (FromVType typ), ref) ->
428429 checkExpr env typ expr `bindValidation` \ te ->
429- checkContractType env typ te `bindValidation` \ ctyp ->
430+ findContractType env te `bindValidation` \ ctyp ->
430431 _Update (_Item vt ref) te <$ validContractType (getPosn expr) vt ctyp
431432
432433
@@ -437,6 +438,13 @@ validContractType pn (ContractType c1) Nothing =
437438 throw (pn, " Assignment to storage variable was expected to have contract type " <> c1)
438439validContractType _ _ _ = pure ()
439440
441+ -- findContractTypes :: Pn -> -> Maybe Id -> Err ()
442+ -- findContractTypes pn (Just c1) (Just c2) =
443+ -- assert (pn, "Assignment to storage variable was expected to have contract type " <> c1 <> " but has contract type " <> c2) (c1 == c2)
444+ -- validContractType pn (Just c1) Nothing =
445+ -- throw (pn, "Assignment to storage variable was expected to have contract type " <> c1)
446+ -- validContractType _ _ _ = pure ()
447+
440448
441449checkIffs :: Env -> [U. IffH ] -> Err [Exp ABoolean Untimed ]
442450checkIffs env = foldr check (pure [] )
@@ -506,14 +514,18 @@ checkExpr env@Env{constructors} typ e = case (typ, e) of
506514 (SInteger , U. IntLit p v1) -> pure $ LitInt p v1
507515 -- Constructor calls
508516 (SInteger , U. ECreate p c args) -> case Map. lookup c constructors of
509- -- TODO check contract types
510- Just typs -> Create p c <$> checkIxs env p args (fmap PrimitiveType typs)
517+ Just ctrs ->
518+ let (typs, ptrs) = unzip ctrs in
519+ checkIxs env p args (fmap PrimitiveType typs) `bindValidation` (\ args ->
520+ pure (Create p c args) <* traverse_ (\ (e, t) -> checkContractType env e t) (zip args ptrs))
511521 Nothing -> throw (p, " Unknown constructor " <> show c)
512- -- Control
522+
523+ -- Control
513524 (_, U. EITE p v1 v2 v3) ->
514525 ((,) <$> checkExpr env typ v2 <*> checkExpr env typ v3) `bindValidation` (\ (e1, e2) -> do
515526 b <- checkExpr env SBoolean v1
516527 pure $ ITE p b e1 e2)
528+
517529 -- Environment variables
518530 (SInteger , U. EnvExp p v1) -> case lookup v1 defaultStore of
519531 Just AInteger -> pure $ IntEnv p v1
@@ -523,8 +535,8 @@ checkExpr env@Env{constructors} typ e = case (typ, e) of
523535 Just AInteger -> throw (p, " Environment variable " <> show v1 <> " has type integer but an expression of type bytestring is expected." )
524536 Just AByteStr -> pure $ ByEnv p v1
525537 _ -> throw (p, " Unknown environment variable " <> show v1)
526- -- Variable references
527538
539+ -- Variable references
528540 (_, U. EUTEntry entry) | isCalldataEntry env entry -> validateVar env entry `bindValidation` \ (vt@ (FromVType typ'), ref) ->
529541 checkTime (getPosEntry entry) <*> (Var (getPosEntry entry) Neither typ vt ref <$ checkEq (getPosEntry entry) typ typ')
530542 (_, U. EPreEntry entry) | isCalldataEntry env entry -> error " Not supported"
@@ -566,19 +578,26 @@ checkExpr env@Env{constructors} typ e = case (typ, e) of
566578
567579
568580-- | Find the contract id of an expression with contract type
569- checkContractType :: Env -> SType a -> Exp a t -> Err (Maybe Id )
570- checkContractType env SInteger (ITE p _ a b) =
571- checkContractType env SInteger a `bindValidation` \ oc1 ->
572- checkContractType env SInteger b `bindValidation` \ oc2 ->
581+ findContractType :: Env -> Exp a t -> Err (Maybe Id )
582+ findContractType env (ITE p _ a b) =
583+ findContractType env a `bindValidation` \ oc1 ->
584+ findContractType env b `bindValidation` \ oc2 ->
573585 case (oc1, oc2) of
574586 (Just c1, Just c2) -> Just c1 <$ assert (p, " Type of if-then-else branches does not match" ) (c1 == c2)
575587 (_, _ )-> pure Nothing
576- checkContractType _ SInteger (Create _ c _) = pure $ Just c
577- checkContractType _ _ (Var _ _ _ (ContractType c) _) = pure $ Just c
578- checkContractType _ _ (TEntry _ _ (Item _ (ContractType c) _)) = pure $ Just c
579- checkContractType _ SInteger _ = pure Nothing
580- checkContractType _ SBoolean _ = pure Nothing
581- checkContractType _ SByteStr _ = pure Nothing
588+ findContractType _ (Create _ c _) = pure $ Just c
589+ findContractType _ (Var _ _ _ (ContractType c) _) = pure $ Just c
590+ findContractType _ (TEntry _ _ (Item _ (ContractType c) _)) = pure $ Just c
591+ findContractType _ _ = pure Nothing
592+
593+ -- | Check if an expression has the expected contract id, if any
594+ checkContractType :: Env -> TypedExp t -> Maybe Id -> Err ()
595+ checkContractType _ _ Nothing = pure ()
596+ checkContractType env (TExp _ e) (Just c) =
597+ findContractType env e `bindValidation` \ oc ->
598+ case oc of -- TODO fix position
599+ Just c' -> assert (nowhere, " Expression was expected to have contract type " <> c <> " but has contract type " <> c') (c == c')
600+ Nothing -> throw (nowhere, " Expression was expected to have contract type " <> c)
582601
583602checkEq :: forall a b . Pn -> SType a -> SType b -> Err ()
584603checkEq p t1 t2 = maybe err (\ Refl -> pure () ) $ testEquality t1 t2
0 commit comments