Skip to content

Commit 6c7c18c

Browse files
committed
interpreter: Now that the Cryptol is scoped, it needs to be in Environ.
That causes it to get closed in along with the SAWScript environments in lambdas and do-blocks. Otherwise, the Cryptol-level values for SAWScript function arguments mysteriously disappear except (due to implementation quirks) when they're associated with the last argument of a function. Note that the SAWCore environment really properly speaking needs a similar treatment, but we can't currently. The result is that in obscure cases (e.g. test03.saw in test2304) uses of the same variable name in what should be distinct places cause a duplicate definition error. For the moment, we're going to hope that these cases are all sufficiently obscure that nobody trips on them, and track the issue in
1 parent 71756da commit 6c7c18c

File tree

17 files changed

+162
-132
lines changed

17 files changed

+162
-132
lines changed

intTests/test2304/test04.log.good

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,5 @@
33
\(_P : PLiteral u1218) -> ecNumber (TCNum 3) u1218 _P)
44
("b",\(u1218 : isort 0) ->
55
\(_P : PLiteral u1218) -> ecNumber (TCNum 4) u1218 _P)
6-
Stack trace:
7-
(builtin) in h
8-
test04.saw:11:6-11:9 (at top level)
9-
Cryptol error:
10-
[error] at test04.saw:3:38--3:39
11-
Type not in scope: x
12-
13-
FAILED
6+
("c",\(u1218 : isort 0) ->
7+
\(_P : PLiteral u1218) -> ecNumber (TCNum 5) u1218 _P)

intTests/test2304/test05.log.good

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
Loading file "test05.saw"
2-
Stack trace:
3-
(builtin) in f
4-
test05.saw:5:9-5:14 (at top level)
5-
Cryptol error:
6-
[error] at test05.saw:1:39--1:40
7-
Type not in scope: x
8-
9-
FAILED
2+
("a",\(u1218 : isort 0) ->
3+
\(_P : PLiteral u1218) -> ecNumber (TCNum 3) u1218 _P)
4+
("b",\(u1218 : isort 0) ->
5+
\(_P : PLiteral u1218) -> ecNumber (TCNum 4) u1218 _P)
6+
("c",\(u1218 : isort 0) ->
7+
\(_P : PLiteral u1218) -> ecNumber (TCNum 5) u1218 _P)

saw-central/src/SAWCentral/Builtins.hs

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,7 @@ envCmd :: TopLevel ()
17061706
envCmd = do
17071707
opts <- getOptions
17081708
avail <- gets rwPrimsAvail
1709-
SV.Environ varenv _tyenv <- gets rwEnviron
1709+
SV.Environ varenv _tyenv _cryenv <- gets rwEnviron
17101710
rbenv <- gets rwRebindables
17111711

17121712
-- print rebindables first if there are any
@@ -2093,28 +2093,30 @@ cryptol_prims = CryptolModule Map.empty <$> Map.fromList <$> traverse parsePrim
20932093
parsePrim :: (Text, Ident, Text) -> TopLevel (C.Name, TypedTerm)
20942094
parsePrim (n, i, s) = do
20952095
sc <- getSharedContext
2096-
rw <- getTopLevelRW
2097-
let SV.CryptolScopeStack (cenv :| cenvs) = rwCryptol rw
2096+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2097+
let SV.CryptolScopeStack (cenv :| cenvs) = cryenv
20982098
unless (null cenvs) $ do
20992099
fail "cryptol_prims is an import operation and may not be done in a nested block"
21002100
let mname = C.packModName ["Prims"]
21012101
let ?fileReader = StrictBS.readFile
21022102
(n', cenv') <- io $ CEnv.declareName cenv mname n
21032103
s' <- io $ CEnv.parseSchema cenv' (noLoc s)
21042104
t' <- io $ scGlobalDef sc i
2105-
putTopLevelRW $ rw { rwCryptol = SV.CryptolScopeStack (cenv' :| cenvs) }
2105+
let cryenv' = SV.CryptolScopeStack (cenv' :| cenvs)
2106+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21062107
return (n', TypedTerm (TypedTermSchema s') t')
21072108

21082109
cryptol_load :: (FilePath -> IO StrictBS.ByteString) -> FilePath -> TopLevel CryptolModule
21092110
cryptol_load fileReader path = do
21102111
sc <- getSharedContext
2111-
rw <- getTopLevelRW
2112-
let SV.CryptolScopeStack (ce :| ces) = rwCryptol rw
2112+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2113+
let SV.CryptolScopeStack (ce :| ces) = cryenv
21132114
unless (null ces) $ do
21142115
fail "cryptol_load is an import operation and is not permitted in nested blocks"
21152116
let ?fileReader = fileReader
21162117
(m, ce') <- io $ CEnv.loadCryptolModule sc ce path
2117-
putTopLevelRW $ rw { rwCryptol = SV.CryptolScopeStack (ce' :| ces) }
2118+
let cryenv' = SV.CryptolScopeStack (ce' :| ces)
2119+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21182120
return m
21192121

21202122
-- XXX: This is kind of a top-level style operation; should it be
@@ -2124,35 +2126,37 @@ cryptol_load fileReader path = do
21242126
-- of the environment closed in with lambdas and do-blocks, so that's
21252127
-- probably a bad idea.)
21262128
cryptol_add_path :: FilePath -> TopLevel ()
2127-
cryptol_add_path path =
2128-
do rw <- getTopLevelRW
2129-
let SV.CryptolScopeStack (ce :| ces) = rwCryptol rw
2129+
cryptol_add_path path = do
2130+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2131+
let SV.CryptolScopeStack (ce :| ces) = cryenv
21302132
let me = CEnv.eModuleEnv ce
21312133
let me' = me { C.meSearchPath = path : C.meSearchPath me }
21322134
let ce' = ce { CEnv.eModuleEnv = me' }
2133-
let rw' = rw { rwCryptol = SV.CryptolScopeStack (ce' :| ces) }
2134-
putTopLevelRW rw'
2135+
let cryenv' = SV.CryptolScopeStack (ce' :| ces)
2136+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21352137

21362138
cryptol_add_prim :: Text -> Text -> TypedTerm -> TopLevel ()
2137-
cryptol_add_prim mnm nm trm =
2138-
do rw <- getTopLevelRW
2139-
let SV.CryptolScopeStack (env :| envs) = rwCryptol rw
2139+
cryptol_add_prim mnm nm trm = do
2140+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2141+
let SV.CryptolScopeStack (env :| envs) = cryenv
21402142
let prim_name =
21412143
C.PrimIdent (C.textToModName mnm) nm
21422144
let env' =
21432145
env { CEnv.ePrims =
21442146
Map.insert prim_name (ttTerm trm) (CEnv.ePrims env) }
2145-
putTopLevelRW (rw { rwCryptol = SV.CryptolScopeStack (env' :| envs) })
2147+
let cryenv' = SV.CryptolScopeStack (env' :| envs)
2148+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21462149

21472150
cryptol_add_prim_type :: Text -> Text -> TypedTerm -> TopLevel ()
2148-
cryptol_add_prim_type mnm nm tp =
2149-
do rw <- getTopLevelRW
2150-
let SV.CryptolScopeStack (env :| envs) = rwCryptol rw
2151+
cryptol_add_prim_type mnm nm tp = do
2152+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2153+
let SV.CryptolScopeStack (env :| envs) = cryenv
21512154
let prim_name =
21522155
C.PrimIdent (C.textToModName mnm) nm
21532156
let env' = env { CEnv.ePrimTypes =
21542157
Map.insert prim_name (ttTerm tp) (CEnv.ePrimTypes env) }
2155-
putTopLevelRW (rw { rwCryptol = SV.CryptolScopeStack (env' :| envs) })
2158+
let cryenv' = SV.CryptolScopeStack (env' :| envs)
2159+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21562160

21572161
-- | Call 'Cryptol.importSchema' using a 'CEnv.CryptolEnv'
21582162
importSchemaCEnv :: SharedContext -> CEnv.CryptolEnv -> Cryptol.Schema ->

saw-central/src/SAWCentral/Value.hs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -754,26 +754,28 @@ type VarEnv = ScopedMap SS.Name (SS.Pos, SS.PrimitiveLifecycle,
754754
-- builtin types that aren't special cases in the AST appear)
755755
type TyEnv = ScopedMap SS.Name (SS.PrimitiveLifecycle, SS.NamedType)
756756

757+
-- | The Cryptol environment. We maintain a stack of Cryptol
758+
-- environments and push/pop them as we enter and leave scopes;
759+
-- otherwise the Cryptol environment doesn't track SAWScript scopes
760+
-- and horribly confusing wrong things happen.
761+
newtype CryptolScopeStack = CryptolScopeStack (NonEmpty CEnv.CryptolEnv)
762+
757763
-- | Type for the ordinary interpreter environment.
758764
--
759765
-- There's one environment that maps variable names to values, and
760-
-- one that maps type names to types. Both get closed in with
761-
-- lambdas and do-blocks at the appropriate times.
766+
-- one that maps type names to types. A third handles the Cryptol
767+
-- domain. All three get closed in with lambdas and do-blocks at the
768+
-- appropriate times.
762769
--
763770
-- Note that rebindable variables are sold separately. This is so
764771
-- they don't get closed in; references to rebindable variables
765772
-- always retrieve the most recent version.
766773
data Environ = Environ {
767774
eVarEnv :: VarEnv,
768-
eTyEnv :: TyEnv
775+
eTyEnv :: TyEnv,
776+
eCryptol :: CryptolScopeStack
769777
}
770778

771-
-- | The Cryptol environment. We maintain a stack of Cryptol
772-
-- environments and push/pop them as we enter and leave scopes;
773-
-- otherwise the Cryptol environment doesn't track SAWScript scopes
774-
-- and horribly confusing wrong things happen.
775-
newtype CryptolScopeStack = CryptolScopeStack (NonEmpty CEnv.CryptolEnv)
776-
777779
-- | The extra environment for rebindable globals.
778780
--
779781
-- Note: because no builtins are rebindable, there are no lifecycle
@@ -784,28 +786,27 @@ type RebindableEnv = Map SS.Name (SS.Pos, SS.Schema, Value)
784786
-- | Enter a scope.
785787
pushScope :: TopLevel ()
786788
pushScope = do
787-
Environ varenv tyenv <- gets rwEnviron
788-
cryenv <- gets rwCryptol
789+
Environ varenv tyenv cryenv <- gets rwEnviron
789790
let varenv' = ScopedMap.push varenv
790791
tyenv' = ScopedMap.push tyenv
791792
cryenv' = cryptolPush cryenv
792-
modifyTopLevelRW (\rw -> rw { rwEnviron = Environ varenv' tyenv', rwCryptol = cryenv' })
793+
modifyTopLevelRW (\rw -> rw { rwEnviron = Environ varenv' tyenv' cryenv' })
793794

794795
-- | Leave a scope. This will panic if you try to leave the last scope;
795796
-- pushes and pops should be matched.
796797
popScope :: TopLevel ()
797798
popScope = do
798-
Environ varenv tyenv <- gets rwEnviron
799-
cryenv <- gets rwCryptol
799+
Environ varenv tyenv cryenv <- gets rwEnviron
800800
let varenv' = ScopedMap.pop varenv
801801
tyenv' = ScopedMap.pop tyenv
802802
cryenv' = cryptolPop cryenv
803-
modifyTopLevelRW (\rw -> rw { rwEnviron = Environ varenv' tyenv', rwCryptol = cryenv' })
803+
modifyTopLevelRW (\rw -> rw { rwEnviron = Environ varenv' tyenv' cryenv' })
804804

805805

806806
getCryptolEnv :: TopLevel CEnv.CryptolEnv
807807
getCryptolEnv = do
808-
CryptolScopeStack (e :| _) <- gets rwCryptol
808+
Environ _varenv _tyenv cryenv <- gets rwEnviron
809+
let CryptolScopeStack (e :| _) = cryenv
809810
return e
810811

811812
cryptolPush :: CryptolScopeStack -> CryptolScopeStack
@@ -857,9 +858,6 @@ data TopLevelRW =
857858
rwEnviron :: Environ
858859
, rwRebindables :: RebindableEnv
859860

860-
-- | The Cryptol naming environment.
861-
, rwCryptol :: CryptolScopeStack
862-
863861
-- | The current execution position. This is only valid when the
864862
-- interpreter is calling out into saw-central to execute a
865863
-- builtin. Within the interpreter, the current position is
@@ -1176,7 +1174,7 @@ extendEnv pos name rb ty doc v = do
11761174
modname = T.packModName [name]
11771175

11781176
-- Update the SAWScript environment.
1179-
Environ varenv tyenv <- gets rwEnviron
1177+
Environ varenv tyenv cryenv <- gets rwEnviron
11801178
rbenv <- gets rwRebindables
11811179
let (varenv', rbenv') = case rb of
11821180
SS.ReadOnlyVar ->
@@ -1195,7 +1193,7 @@ extendEnv pos name rb ty doc v = do
11951193
(varenv, re')
11961194

11971195
-- Mirror the value into the Cryptol environment if appropriate.
1198-
CryptolScopeStack (ce :| ces) <- gets rwCryptol
1196+
let CryptolScopeStack (ce :| ces) = cryenv
11991197
ce' <-
12001198
case v of
12011199
VTerm t ->
@@ -1214,19 +1212,19 @@ extendEnv pos name rb ty doc v = do
12141212
pure $ CEnv.bindTypedTerm (ident, tt) ce
12151213
_ ->
12161214
pure ce
1215+
let cryenv' = CryptolScopeStack (ce' :| ces)
12171216

12181217
-- Drop the new bits into place.
12191218
modify (\rw -> rw {
1220-
rwCryptol = CryptolScopeStack (ce' :| ces),
1221-
rwEnviron = Environ varenv' tyenv,
1219+
rwEnviron = Environ varenv' tyenv cryenv',
12221220
rwRebindables = rbenv'
12231221
})
12241222

12251223
extendEnvMulti :: [(SS.Pos, SS.Name, SS.Rebindable, SS.Schema, Maybe [Text], Environ -> Value)] -> TopLevel ()
12261224
extendEnvMulti bindings = do
12271225

12281226
-- Update the SAWScript environment.
1229-
Environ varenv tyenv <- gets rwEnviron
1227+
Environ varenv tyenv cryenv <- gets rwEnviron
12301228

12311229
-- Insert all the bindings at once, and feed the final resulting
12321230
-- interpreter environment into each value. This circular
@@ -1259,7 +1257,7 @@ extendEnvMulti bindings = do
12591257
in
12601258
ScopedMap.insert name (pos, SS.Current, ty, v'', doc) tmpenv
12611259
varenv' = foldr insert varenv bindings
1262-
environ' = Environ varenv' tyenv
1260+
environ' = Environ varenv' tyenv cryenv
12631261

12641262
-- Drop the new bits into place.
12651263
modify (\rw -> rw { rwEnviron = environ' })
@@ -1269,10 +1267,10 @@ extendEnvMulti bindings = do
12691267
addTypedef :: SS.Name -> SS.Type -> TopLevel ()
12701268
addTypedef name ty = do
12711269
avail <- gets rwPrimsAvail
1272-
Environ varenv tyenv <- gets rwEnviron
1270+
Environ varenv tyenv cryenv <- gets rwEnviron
12731271
let ty' = SS.substituteTyVars avail tyenv ty
12741272
tyenv' = ScopedMap.insert name (SS.Current, SS.ConcreteType ty') tyenv
1275-
modify (\rw -> rw { rwEnviron = Environ varenv tyenv' })
1273+
modify (\rw -> rw { rwEnviron = Environ varenv tyenv' cryenv })
12761274

12771275
typedTermOfString :: SharedContext -> String -> IO TypedTerm
12781276
typedTermOfString sc str =

0 commit comments

Comments
 (0)