Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions src/Solcore/Backend/Specialise.hs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ specialiseTopDecl (TContr (Contract name args decls)) = withLocalState do
-- Deployer code
modify (\st -> st {specTable = emptyTable})
-- let deployerName = Name (pretty name <> "$Deployer")
mStart <- specEntry "start"
mStart <- specEntryOpt "start"
deployDecls <- case mStart of
Just {} -> do
depDecls <- getSpecialisedDecls
Expand All @@ -252,16 +252,23 @@ specialiseTopDecl d@TDataDef {} = pure [d]
specialiseTopDecl _ = pure []

specEntry :: Name -> SM (Maybe Name)
specEntry name = withLocalState do
specEntry name = do
mres <- specEntryOpt name
when (null mres) $ warns ["!! Warning: no resolution found for ", show name]
pure mres

-- | Like 'specEntry' but silently returns Nothing when the name is absent.
-- Use for optional entry points (e.g. "start") that may not exist when
-- contract dispatch generation is disabled.
specEntryOpt :: Name -> SM (Maybe Name)
specEntryOpt name = withLocalState do
let anytype = TyVar (TVar (Name "any"))
mres <- lookupResolution name anytype
case mres of
Just (fd, ty, subst) -> do
debug ["< resolution: ", show name, " : ", pretty ty, "@", pretty subst]
Just <$> specFunDef fd
Nothing -> do
warns ["!! Warning: no resolution found for ", show name]
pure Nothing
Nothing -> pure Nothing

addContractResolutions :: Contract Id -> SM ()
addContractResolutions (Contract _name _args cdecls) = do
Expand Down
56 changes: 33 additions & 23 deletions src/Solcore/Desugarer/ContractDispatch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ contractDispatchDesugarer (CompUnit ims topdecls) = CompUnit ims (Set.toList ext
| otherwise = (acc, TContr (genMainFn False c))
go acc v = (acc, v)

hasConstructor :: [ContractDecl Name] -> Bool
hasConstructor = any isConstr
where
isConstr (CConstrDecl _) = True
isConstr _ = False

functionNames :: Contract a -> [Name]
functionNames = foldr go [] . decls
where
Expand All @@ -48,7 +54,9 @@ genMainFn addMain (Contract cname tys cdecls)
| addMain = Contract cname tys (CFunDecl mainfn : Set.toList cdecls')
| otherwise = Contract cname tys (Set.toList cdecls')
where
cdecls' = Set.unions (map (transformCDecl cname) cdecls)
cdecls'' = if hasConstructor cdecls then cdecls else cdecls ++ [defaultConstructor]
cdecls' = Set.unions (map (transformCDecl cname) cdecls'')
defaultConstructor = CConstrDecl (Constructor {constrParams = [], constrBody = []})
mainfn = FunDef (Signature [] [] "main" [] Nothing) body
body = [StmtExp (Call Nothing (QualName "RunContract" "exec") [cdata])]
cdata = Con "Contract" [methods, fallback]
Expand Down Expand Up @@ -115,28 +123,30 @@ transformConstructor contractName cons
contractString = show contractName
yulContractName = YLit $ YulString contractString
deployer = YLit $ YulString $ contractString <> "Deploy"
copyBody =
[ Let "res" (Just argsTuple) Nothing,
Let "memoryDataOffset" (Just word) Nothing,
Asm
[yulBlock|{
let programSize := datasize(`deployer`)
let argSize := sub(codesize(), programSize)
memoryDataOffset := mload(64)
mstore(64, add(memoryDataOffset, argSize))
codecopy(memoryDataOffset, programSize, argSize)
}|],
Let "source" (Just (memoryT bytesT)) (Just (memoryE (Var "memoryDataOffset"))),
Var "res"
:= Call
Nothing
"abi_decode"
[ Var "source",
proxyExp argsTuple,
proxyExp (TyCon "MemoryWordReader" [])
],
Return (Var "res")
]
copyBody
| null params = [Return (Con "()" [])]
| otherwise =
[ Let "res" (Just argsTuple) Nothing,
Let "memoryDataOffset" (Just word) Nothing,
Asm
[yulBlock|{
let programSize := datasize(`deployer`)
let argSize := sub(codesize(), programSize)
memoryDataOffset := mload(64)
mstore(64, add(memoryDataOffset, argSize))
codecopy(memoryDataOffset, programSize, argSize)
}|],
Let "source" (Just (memoryT bytesT)) (Just (memoryE (Var "memoryDataOffset"))),
Var "res"
:= Call
Nothing
"abi_decode"
[ Var "source",
proxyExp argsTuple,
proxyExp (TyCon "MemoryWordReader" [])
],
Return (Var "res")
]
memoryT t = TyCon "memory" [t]
memoryE e = Con "memory" [e]
bytesT = TyCon "bytes" []
Expand Down
Loading