Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespaces #337

Merged
merged 67 commits into from Jan 5, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
17a4208
initial
emilypi Nov 21, 2018
87981c6
Merge branch 'master' into feat/56-namespaces
emilypi Nov 30, 2018
e9ee5d5
make some headway for Monday on namespaces
emilypi Dec 2, 2018
e3c2382
TODO: finish the native def - see about env comparisons during eval p…
emilypi Dec 2, 2018
b43ea58
implementation time
emilypi Dec 3, 2018
6a3821d
finished - moving on to namespace toplevel call
emilypi Dec 3, 2018
fb5710b
defineNamespaceDef now uses Guards as opposed to Keysets
emilypi Dec 3, 2018
fb4fa6b
move up and redefine defineNamespace
emilypi Dec 3, 2018
6f7086e
remove stale commentary
emilypi Dec 3, 2018
82ac2e5
use foldM, lensing in constraint solver
emilypi Dec 3, 2018
e8734d7
fix native define-namespace
emilypi Dec 4, 2018
c1d421c
updates to evalNamespace
emilypi Dec 4, 2018
672f3b3
updates to evalNamespace
emilypi Dec 4, 2018
1b3868a
move eeNamespace to EvalState, fix accordingly
emilypi Dec 4, 2018
b65ef9e
cleaner defineNamespace functionality
emilypi Dec 4, 2018
5ef53aa
keep track of namespaces declared in compile phase in Modules
emilypi Dec 4, 2018
d425e46
small formatting fixes
emilypi Dec 4, 2018
4feec92
add additional check for defined namespace while parsing
emilypi Dec 4, 2018
debec59
amend ModuleName to include NamespaceName
emilypi Dec 4, 2018
f32aa2b
small fixes - need to discuss strategy with Stuart
emilypi Dec 5, 2018
9399289
updates to useForm
emilypi Dec 5, 2018
0d01cf7
remove unnecessary comment, newline
emilypi Dec 6, 2018
9571355
remove wrong namespacing
emilypi Dec 6, 2018
f973318
add namespacing to RefState, define native def
emilypi Dec 11, 2018
a5ea88d
add namespace policy - revert modulename changes
emilypi Dec 12, 2018
2744609
add namespace policy - revert modulename changes
emilypi Dec 12, 2018
36f873a
fix some stale stuff
emilypi Dec 12, 2018
98e8cac
amend namespace native fun to overwrite current namespace)
emilypi Dec 13, 2018
f1aab98
get back to where we were
emilypi Dec 18, 2018
d683a7d
PLATED M'FERS
emilypi Dec 21, 2018
0d70559
todo: fix tables
emilypi Dec 22, 2018
f1d099a
remove namespace.hs, small cleanups here and there
emilypi Dec 23, 2018
d3bd369
clean up
emilypi Dec 24, 2018
3a27c5f
namespaces work
emilypi Dec 24, 2018
daff719
add tests for namespaces
emilypi Dec 24, 2018
ac22bb4
swap out m's for mangled versions
emilypi Dec 24, 2018
9b64d04
Fix tests, native defs, reference lookups
emilypi Dec 27, 2018
135a9eb
add qualified atom form to ExpParser, break Use so that it only
emilypi Dec 28, 2018
f443a9e
Remove `qualifiedAtom`, inline the modulename qualifier atom parsing,
emilypi Dec 28, 2018
b9038c7
change shadowed name
emilypi Dec 28, 2018
5c65c3c
Start working on tests, commit fixes to plating defs, tables, and schema
emilypi Dec 28, 2018
d8e103f
Fix up repl tests to make sure `use` takes atoms instead of strings
emilypi Dec 28, 2018
85c222a
make the examples a little more expressive
emilypi Dec 28, 2018
b8140ed
fixed tests
emilypi Dec 28, 2018
20ed609
tick examples
emilypi Dec 28, 2018
5569e6c
fix pact-functions.md
emilypi Dec 28, 2018
f47f1d1
regen pact-functions.md
emilypi Dec 28, 2018
5ca5d9e
fix up the regression formatting
emilypi Dec 28, 2018
af55fe2
fix up on final pass
emilypi Dec 28, 2018
305b7a9
doc fixes
emilypi Dec 28, 2018
40ce9a2
docs fixes 2
emilypi Dec 28, 2018
73d2695
remove unnecessary space
emilypi Dec 29, 2018
0cf6bb2
fix stu's comments
emilypi Jan 3, 2019
e5f7247
remove some unnecessary cruft for NativeDFun, change default policy t…
emilypi Jan 3, 2019
961f290
permissive policy
emilypi Jan 3, 2019
aeda2dd
doc fixes
emilypi Jan 3, 2019
f90ec3d
default -> permissive
emilypi Jan 3, 2019
9b17780
sanity prevails
emilypi Jan 3, 2019
4dbdad8
purge the data typeable
emilypi Jan 4, 2019
604c254
purge data/typable 2
emilypi Jan 4, 2019
0a121b1
fix some test code
emilypi Jan 4, 2019
6d6cefb
fix some test code
emilypi Jan 4, 2019
7f858c1
fix whitespace problems
emilypi Jan 4, 2019
7098c61
pair down some stuff
emilypi Jan 4, 2019
676359b
revert whitespaces
emilypi Jan 4, 2019
09bde8d
fix docs, remove from error string
emilypi Jan 4, 2019
f4ab22e
Fix name parser for modulenames in Remote/Server.hs
emilypi Jan 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1,443 changes: 4 additions & 1,439 deletions docs/en/pact-functions.md

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions src-ghc/Pact/Interpreter.hs
Expand Up @@ -23,6 +23,7 @@ import Control.Monad.Catch
import Data.Maybe
import qualified Data.HashMap.Strict as HM

import Pact.Types.Term
import Pact.Types.Runtime
import Pact.Compile
import Pact.Eval
Expand Down Expand Up @@ -68,8 +69,14 @@ evalContinuation :: EvalEnv e -> Term Name -> IO EvalResult
evalContinuation ee pact = interpret ee [pact]


setupEvalEnv :: PactDbEnv e -> Maybe EntityName -> ExecutionMode ->
MsgData -> RefStore -> GasEnv -> EvalEnv e
setupEvalEnv
:: PactDbEnv e
-> Maybe EntityName
-> ExecutionMode
-> MsgData
-> RefStore
-> GasEnv
-> EvalEnv e
setupEvalEnv dbEnv ent mode msgData refStore gasEnv =
EvalEnv {
_eeRefStore = refStore
Expand Down
2 changes: 1 addition & 1 deletion src-ghc/Pact/PersistPactDb/Regression.hs
Expand Up @@ -45,7 +45,7 @@ runRegression p = do
let ks = KeySet [PublicKey "skdjhfskj"] (Name "predfun" def)
_writeRow pactdb Write KeySets "ks1" ks v
assertEquals' "keyset write" (Just ks) $ _readRow pactdb KeySets "ks1" v
let mod' = Module "mod1" "mod-admin-keyset" (Meta Nothing []) "code" (H.hash "code") mempty mempty mempty
let mod' = Module "mod1" "mod-admin-keyset" (Meta Nothing []) "code" (H.hash "code") mempty mempty mempty Nothing
_writeRow pactdb Write Modules "mod1" mod' v
assertEquals' "module write" (Just mod') $ _readRow pactdb Modules "mod1" v
assertEquals' "result of commit 3"
Expand Down
8 changes: 4 additions & 4 deletions src-ghc/Pact/Server/PactService.hs
Expand Up @@ -153,7 +153,7 @@ applyContinuation rk msg@ContMsg{..} Command{..} = do
Left (SomeException ex) -> throwM ex
Right EvalResult{..} -> do
exec@PactExec{..} <- maybe (throwCmdEx "No pact execution in continuation exec!")
return erExec
return erExec
if _cmRollback
then rollbackUpdate env msg state
else continuationUpdate env msg state pact exec
Expand All @@ -162,7 +162,7 @@ applyContinuation rk msg@ContMsg{..} Command{..} = do
rollbackUpdate :: CommandEnv p -> ContMsg -> CommandState -> CommandM p ()
rollbackUpdate CommandEnv{..} ContMsg{..} CommandState{..} = do
-- if step doesn't have a rollback function, no error thrown. Therefore, pact will be deleted
-- from state.
-- from state.
let newState = CommandState _csRefStore $ M.delete _cmTxId _csPacts
liftIO $ logLog _ceLogger "DEBUG" $ "applyContinuation: rollbackUpdate: reaping pact "
++ show _cmTxId
Expand All @@ -172,7 +172,7 @@ continuationUpdate :: CommandEnv p -> ContMsg -> CommandState -> CommandPact ->
continuationUpdate CommandEnv{..} ContMsg{..} CommandState{..} CommandPact{..} PactExec{..} = do
let nextStep = _cmStep + 1
isLast = nextStep >= _cpStepCount
updateState pacts = CommandState _csRefStore pacts -- never loading modules during continuations
updateState pacts = CommandState _csRefStore pacts -- never loading modules during continuations

if isLast
then do
Expand All @@ -183,4 +183,4 @@ continuationUpdate CommandEnv{..} ContMsg{..} CommandState{..} CommandPact{..} P
let newPact = CommandPact _cpTxId _cpContinuation _cpStepCount _cmStep _peYield
liftIO $ logLog _ceLogger "DEBUG" $ "applyContinuation: updated state of pact "
++ show _cmTxId ++ ": " ++ show newPact
void $ liftIO $ swapMVar _ceState $ updateState $ M.insert _cmTxId newPact _csPacts
void $ liftIO $ swapMVar _ceState $ updateState $ M.insert _cmTxId newPact _csPacts
sirlensalot marked this conversation as resolved.
Show resolved Hide resolved
37 changes: 25 additions & 12 deletions src/Pact/Compile.hs
Expand Up @@ -21,13 +21,10 @@
--

module Pact.Compile
(
compile,compileExps
,MkInfo,mkEmptyInfo,mkStringInfo,mkTextInfo
,Reserved(..)
)

where
( compile,compileExps
, MkInfo,mkEmptyInfo,mkStringInfo,mkTextInfo
, Reserved(..)
) where

import qualified Text.Trifecta as TF hiding (expected)
import Control.Applicative hiding (some,many)
Expand Down Expand Up @@ -75,13 +72,14 @@ initModuleState n h = ModuleState n h def def def
data CompileState = CompileState
{ _csFresh :: Int
, _csModule :: Maybe ModuleState
, _csNamespace :: Maybe NamespaceName
}
makeLenses ''CompileState

type Compile a = ExpParse CompileState a

initParseState :: Exp Info -> ParseState CompileState
initParseState e = ParseState e $ CompileState 0 Nothing
initParseState e = ParseState e $ CompileState 0 Nothing Nothing

data Reserved =
RBless
Expand All @@ -97,6 +95,7 @@ data Reserved =
| RLet
| RLetStar
| RModule
| RNamespace
| RStep
| RStepWithRollback
| RTrue
Expand All @@ -119,6 +118,7 @@ instance AsString Reserved where
RLet -> "let"
RLetStar -> "let*"
RModule -> "module"
RNamespace -> "namespace"
RStep -> "step"
RStepWithRollback -> "step-with-rollback"
RTrue -> "true"
Expand Down Expand Up @@ -198,7 +198,8 @@ topLevel = specialFormOrApp topLevelForm <|> literals <|> varAtom where
RLetStar -> return letsForm
RModule -> return moduleForm
RInterface -> return interface
_ -> expected "top-level form (use, let[*], module, interface)"
RNamespace -> return namespace
_ -> expected "top-level form (use, let[*], module, interface, namespace)"


valueLevel :: Compile (Term Name)
Expand Down Expand Up @@ -239,7 +240,6 @@ userAtom = do
pure a



app :: Compile (Term Name)
app = do
v <- varAtom
Expand Down Expand Up @@ -411,14 +411,15 @@ moduleForm = do
Just {} -> syntaxError "Invalid nested module or interface"
Nothing -> return ()
i <- contextInfo
namespaceName <- use (psUser . csNamespace)
let code = case i of
Info Nothing -> "<code unavailable>"
Info (Just (c,_)) -> c
modName = ModuleName modName'
modHash = hash $ encodeUtf8 $ _unCode code
((bd,bi),ModuleState{..}) <- withModuleState (initModuleState modName modHash) $ bodyForm' moduleLevel
return $ TModule
(Module modName (KeySetName keyset) m code modHash (HS.fromList _msBlessed) _msImplements _msImports)
(Module modName (KeySetName keyset) m code modHash (HS.fromList _msBlessed) _msImplements _msImports namespaceName)
(abstract (const Nothing) (TList (concat bd) TyAny bi)) i

implements :: Compile ()
Expand All @@ -434,6 +435,7 @@ interface = do
use (psUser . csModule) >>= \ci -> case ci of
Just {} -> syntaxError "invalid nested interface or module"
Nothing -> return ()
namespaceName <- use (psUser . csNamespace)
info <- contextInfo
let code = case info of
Info Nothing -> "<code unavailable>"
Expand All @@ -447,9 +449,20 @@ interface = do
RUse -> return useForm
t -> syntaxError $ "Invalid interface declaration: " ++ show (asString t)
return $ TModule
(Interface iname code m _msImports)
(Interface iname code m _msImports namespaceName)
(abstract (const Nothing) bd) info

namespace :: Compile (Term Name)
namespace = do
bareName <- _atomAtom <$> bareAtom
info <- contextInfo
let _nsName = NamespaceName bareName
use (psUser . csNamespace) >>= \case
Just ns -> syntaxError $ "A namespace has already been declared: " ++ asString' ns
Nothing -> pure ()
psUser . csNamespace .= (Just _nsName)
pure $ TNamespace _nsName info

emptyDef :: Compile (Term Name)
emptyDef = do
modName <- currentModuleName
Expand Down
33 changes: 23 additions & 10 deletions src/Pact/Eval.hs
Expand Up @@ -87,8 +87,7 @@ evalCommitTx i = do
Just {} -> commitTx i
{-# INLINE evalCommitTx #-}


enforceKeySetName :: Info -> KeySetName -> Eval e ()
enforceKeySetName :: Info -> KeySetName -> Eval e ()
enforceKeySetName mi mksn = do
ks <- maybe (evalError mi $ "No such keyset: " ++ show mksn) return =<< readRow mi KeySets mksn
runPure $ enforceKeySet mi (Just mksn) ks
Expand Down Expand Up @@ -174,6 +173,8 @@ revokeCapability c = evalCapabilities %= filter (/= c)
eval :: Term Name -> Eval e (Term Name)
eval (TUse u@Use{..} i) = topLevelCall i "use" (GUse _uModuleName _uModuleHash) $ \g ->
evalUse u >> return (g,tStr $ pack $ "Using " ++ show _uModuleName)
eval (TNamespace n info) = topLevelCall info "namespace" GNamespace $ \g ->
evalNamespace info n >> return (g, tStr . pack $ "Namespace " ++ asString' n)
eval (TModule m@Module{} bod i) =
topLevelCall i "module" (GModuleDecl m) $ \g0 -> do
-- enforce old module keysets
Expand Down Expand Up @@ -226,6 +227,19 @@ evalUse (Use mn h i) = do

installModule md

evalNamespace :: Info -> NamespaceName -> Eval e ()
evalNamespace info name = do
mOldNs <- use eeNamespace
case mOldNs of
Just (Namespace n _) ->
evalError info $ "Namespace already in use: " ++ asString' n
Nothing -> do
mNs <- readRow info Namespaces name
case mNs of
Nothing ->
evalError info $ "Namespace not defined: " ++ asString' name
ns -> eeNamespace .= ns

-- | Make table of module definitions for storage in namespace/RefStore.
loadModule :: Module -> Scope n Term Name -> Info -> Gas -> Eval e (Gas,HM.HashMap Text (Term Name))
loadModule m@Module{..} bod1 mi g0 = do
Expand Down Expand Up @@ -319,11 +333,10 @@ evaluateConstraints
evaluateConstraints info Interface{} _ =
evalError info "Unexpected: interface found in module position while solving constraints"
evaluateConstraints info m evalMap =
-- we would like the lazy semantics of foldr to shortcircuit the solver
foldr evaluateConstraint (pure (m, evalMap)) (_mInterfaces m)
-- we would like the lazy semantics of foldM to shortcircuit the solver
foldM evaluateConstraint (m, evalMap) $ _mInterfaces m
where
evaluateConstraint ifn em = do
(m',refMap) <- em
evaluateConstraint (m', refMap) ifn = do
refData <- preview $ eeRefStore . rsModules . ix ifn
case refData of
Nothing -> evalError info $
Expand Down Expand Up @@ -356,16 +369,15 @@ solveConstraint info refName (Ref t) evalMap = do
Just (Ref s) ->
case (t, s) of
(TDef (Def _n _mn dt (FunType args rty) _ m _) _,
TDef (Def _n' _mn' dt' (FunType args' rty') b m' i) _) -> do
TDef (Def _n' _mn' dt' (FunType args' rty') _ _ _) _) -> do
when (dt /= dt') $ evalError info $ "deftypes mismatching: " ++ show dt ++ "\n" ++ show dt'
when (rty /= rty') $ evalError info $ "return types mismatching: " ++ show rty ++ "\n" ++ show rty'
when (length args /= length args') $ evalError info $ "mismatching argument lists: " ++ show args ++ "\n" ++ show args'
forM_ (args `zip` args') $ \((Arg n ty _), (Arg n' ty' _)) -> do
when (n /= n') $ evalError info $ "mismatching argument names: " ++ show n ++ " and " ++ show n'
when (ty /= ty') $ evalError info $ "mismatching types: " ++ show ty ++ " and " ++ show ty'
-- the model concatenation step: we must reinsert the ref back into the map with new models
-- TODO yuck, should be lensing here
pure $ HM.insert refName (Ref $ TDef (Def _n' _mn' dt' (FunType args' rty') b (m <> m') i) i) em
-- the model concatenation step: we reinsert the ref back into the map with new models
pure $ HM.insert refName (Ref $ over (tDef . dMeta) (<> m) s) em
sirlensalot marked this conversation as resolved.
Show resolved Hide resolved
_ -> evalError info $ "found overlapping const refs - please resolve: " ++ show t

resolveRef :: Name -> Eval e (Maybe Ref)
Expand Down Expand Up @@ -430,6 +442,7 @@ reduce t@TUse {} = evalError (_tInfo t) "Use only allowed at top level"
reduce t@TStep {} = evalError (_tInfo t) "Step at invalid location"
reduce TSchema {..} = TSchema _tSchemaName _tModule _tMeta <$> traverse (traverse reduce) _tFields <*> pure _tInfo
reduce TTable {..} = TTable _tTableName _tModule _tHash <$> mapM reduce _tTableType <*> pure _tMeta <*> pure _tInfo
reduce t@TNamespace{} = unsafeReduce t

mkDirect :: Term Name -> Term Ref
mkDirect = (`TVar` def) . Direct
Expand Down
31 changes: 30 additions & 1 deletion src/Pact/Native.hs
Expand Up @@ -211,6 +211,35 @@ readDecimalDef = defRNative "read-decimal" readDecimal
return $ toTerm a'
readDecimal i as = argsError i as

defineNamespaceDef :: NativeDef
defineNamespaceDef = setTopLevelOnly $ defRNative "define-namespace" defineNamespace
(funType tTyString [("namespace", tTyString), ("guard", tTyGuard Nothing)])
"Create a namespace called NAMESPACE for a given GUARD. All expressions that occur \
\ in a given transaction will be tied to NAMESPACE, and may be accessed using the toplevel \
\ call (namespace NAMESPACE) when GUARD is in scope. If NAMESPACE is already defined, then \
\ the guard previously defined in NAMESPACE will be enforced, and GUARD will be rotated in \
\ its place. `(define-namespace 'my-namespace 'my-guard)`"
where
emilypi marked this conversation as resolved.
Show resolved Hide resolved
defineNamespace :: RNativeFun e
defineNamespace i as = case as of
[TLitString nsn, TGuard g _] -> go i nsn g
_ -> argsError i as

go fi nsn g = do
let name = NamespaceName nsn
info = _faInfo fi

mOldNs <- readRow info Namespaces name
case mOldNs of
Just (Namespace _ g') ->
-- if namespace is defined, enforce old guard and rotate
enforceGuard fi g' >> writeNamespace info name g
Nothing -> writeNamespace info name g

writeNamespace info n g =
writeRow info Write Namespaces n (Namespace n g)
& success "Namespace defined"


langDefs :: NativeModule
langDefs =
Expand Down Expand Up @@ -333,9 +362,9 @@ langDefs =
"Lazily ignore arguments IGNORE* and return VALUE. `(filter (constantly true) [1 2 3])`"
,defRNative "identity" identity (funType a [("value",a)])
"Return provided value. `(map (identity) [1 2 3])`"

,strToIntDef
,hashDef
,defineNamespaceDef
])
where b = mkTyVar "b" []
c = mkTyVar "c" []
Expand Down
40 changes: 20 additions & 20 deletions src/Pact/Native/Internal.hs
Expand Up @@ -18,6 +18,7 @@ module Pact.Native.Internal
(success
,parseMsgKey
,bindReduce
,enforceGuard
,defNative,defGasRNative,defRNative
,setTopLevelOnly
,foldDefs
Expand Down Expand Up @@ -150,27 +151,26 @@ enforceGuardDef dn =
where
enforceGuard' :: RNativeFun e
enforceGuard' i as = case as of
[TGuard g _] -> go g
[TLitString k] -> go (GKeySetRef (KeySetName k))
[TGuard g _] -> enforceGuard i g >> return (toTerm True)
[TLitString k] -> enforceGuard i (GKeySetRef (KeySetName k)) >> return (toTerm True)
_ -> argsError i as
where
go g = runGuard g >> return (toTerm True)
runGuard g = case g of
GKeySet k -> runPure $ enforceKeySet (_faInfo i) Nothing k
GKeySetRef n -> enforceKeySetName (_faInfo i) n
GPact PactGuard{..} -> do
pid <- getPactId i
unless (pid == _pgPactId) $
evalError' i $
"Pact guard failed, intended: " ++ show _pgPactId ++ ", active: " ++ show pid
GModule mg@ModuleGuard{..} -> do
m <- getModule (_faInfo i) _mgModuleName
case m of
Module{..} -> enforceKeySetName (_faInfo i) _mKeySet
Interface{} -> evalError' i $ "ModuleGuard not allowed on interface: " ++ show mg
GUser UserGuard{..} -> do
void $ runReadOnly (_faInfo i) $
enscopeApply $ App (TVar _ugPredFun def) [_ugData] (_faInfo i)

enforceGuard :: FunApp -> Guard -> Eval e ()
enforceGuard i g = case g of
GKeySet k -> runPure $ enforceKeySet (_faInfo i) Nothing k
GKeySetRef n -> enforceKeySetName (_faInfo i) n
GPact PactGuard{..} -> do
pid <- getPactId i
unless (pid == _pgPactId) $
evalError' i $ "Pact guard failed, intended: " ++ show _pgPactId ++ ", active: " ++ show pid
GModule mg@ModuleGuard{..} -> do
m <- getModule (_faInfo i) _mgModuleName
case m of
Module{..} -> enforceKeySetName (_faInfo i) _mKeySet
Interface{} -> evalError' i $ "ModuleGuard not allowed on interface: " ++ show mg
GUser UserGuard{..} -> do
void $ runReadOnly (_faInfo i) $
enscopeApply $ App (TVar _ugPredFun def) [_ugData] (_faInfo i)
sirlensalot marked this conversation as resolved.
Show resolved Hide resolved

findCallingModule :: Eval e (Maybe ModuleName)
findCallingModule = uses evalCallStack (firstOf (traverse . sfApp . _Just . _1 . faModule . _Just))
Expand Down
1 change: 1 addition & 0 deletions src/Pact/Persist.hs
Expand Up @@ -119,6 +119,7 @@ instance PactValue a => PactValue [a]
instance PactValue Module
instance PactValue KeySet
instance PactValue Value
instance PactValue Namespace

data Persister s = Persister {
createTable :: forall k . PactKey k => Table k -> Persist s ()
Expand Down