Skip to content

Commit e1da98a

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 b4ea484 commit e1da98a

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
@@ -2096,28 +2096,30 @@ cryptol_prims =
20962096
parsePrim :: (Text, Ident, Text) -> TopLevel (C.Name, TypedTerm)
20972097
parsePrim (n, i, s) = do
20982098
sc <- getSharedContext
2099-
rw <- getTopLevelRW
2100-
let SV.CryptolScopeStack (cenv :| cenvs) = rwCryptol rw
2099+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2100+
let SV.CryptolScopeStack (cenv :| cenvs) = cryenv
21012101
unless (null cenvs) $ do
21022102
fail "cryptol_prims is an import operation and may not be done in a nested block"
21032103
let mname = C.packModName ["Prims"]
21042104
let ?fileReader = StrictBS.readFile
21052105
(n', cenv') <- io $ CEnv.declareName cenv mname n
21062106
s' <- io $ CEnv.parseSchema cenv' (noLoc s)
21072107
t' <- io $ scGlobalDef sc i
2108-
putTopLevelRW $ rw { rwCryptol = SV.CryptolScopeStack (cenv' :| cenvs) }
2108+
let cryenv' = SV.CryptolScopeStack (cenv' :| cenvs)
2109+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21092110
return (n', TypedTerm (TypedTermSchema s') t')
21102111

21112112
cryptol_load :: (FilePath -> IO StrictBS.ByteString) -> FilePath -> TopLevel CEnv.ExtCryptolModule
21122113
cryptol_load fileReader path = do
21132114
sc <- getSharedContext
2114-
rw <- getTopLevelRW
2115-
let SV.CryptolScopeStack (ce :| ces) = rwCryptol rw
2115+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2116+
let SV.CryptolScopeStack (ce :| ces) = cryenv
21162117
unless (null ces) $ do
21172118
fail "cryptol_load is an import operation and is not permitted in nested blocks"
21182119
let ?fileReader = fileReader
21192120
(m, ce') <- io $ CEnv.loadExtCryptolModule sc ce path
2120-
putTopLevelRW $ rw { rwCryptol = SV.CryptolScopeStack (ce' :| ces) }
2121+
let cryenv' = SV.CryptolScopeStack (ce' :| ces)
2122+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21212123
return m
21222124

21232125
cryptol_extract :: CEnv.ExtCryptolModule -> Text -> TopLevel TypedTerm
@@ -2134,35 +2136,37 @@ cryptol_extract ecm var = do
21342136
-- of the environment closed in with lambdas and do-blocks, so that's
21352137
-- probably a bad idea.)
21362138
cryptol_add_path :: FilePath -> TopLevel ()
2137-
cryptol_add_path path =
2138-
do rw <- getTopLevelRW
2139-
let SV.CryptolScopeStack (ce :| ces) = rwCryptol rw
2139+
cryptol_add_path path = do
2140+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2141+
let SV.CryptolScopeStack (ce :| ces) = cryenv
21402142
let me = CEnv.eModuleEnv ce
21412143
let me' = me { C.meSearchPath = path : C.meSearchPath me }
21422144
let ce' = ce { CEnv.eModuleEnv = me' }
2143-
let rw' = rw { rwCryptol = SV.CryptolScopeStack (ce' :| ces) }
2144-
putTopLevelRW rw'
2145+
let cryenv' = SV.CryptolScopeStack (ce' :| ces)
2146+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21452147

21462148
cryptol_add_prim :: Text -> Text -> TypedTerm -> TopLevel ()
2147-
cryptol_add_prim mnm nm trm =
2148-
do rw <- getTopLevelRW
2149-
let SV.CryptolScopeStack (env :| envs) = rwCryptol rw
2149+
cryptol_add_prim mnm nm trm = do
2150+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2151+
let SV.CryptolScopeStack (env :| envs) = cryenv
21502152
let prim_name =
21512153
C.PrimIdent (C.textToModName mnm) nm
21522154
let env' =
21532155
env { CEnv.ePrims =
21542156
Map.insert prim_name (ttTerm trm) (CEnv.ePrims env) }
2155-
putTopLevelRW (rw { rwCryptol = SV.CryptolScopeStack (env' :| envs) })
2157+
let cryenv' = SV.CryptolScopeStack (env' :| envs)
2158+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21562159

21572160
cryptol_add_prim_type :: Text -> Text -> TypedTerm -> TopLevel ()
2158-
cryptol_add_prim_type mnm nm tp =
2159-
do rw <- getTopLevelRW
2160-
let SV.CryptolScopeStack (env :| envs) = rwCryptol rw
2161+
cryptol_add_prim_type mnm nm tp = do
2162+
SV.Environ varenv tyenv cryenv <- gets rwEnviron
2163+
let SV.CryptolScopeStack (env :| envs) = cryenv
21612164
let prim_name =
21622165
C.PrimIdent (C.textToModName mnm) nm
21632166
let env' = env { CEnv.ePrimTypes =
21642167
Map.insert prim_name (ttTerm tp) (CEnv.ePrimTypes env) }
2165-
putTopLevelRW (rw { rwCryptol = SV.CryptolScopeStack (env' :| envs) })
2168+
let cryenv' = SV.CryptolScopeStack (env' :| envs)
2169+
modify (\rw -> rw { rwEnviron = SV.Environ varenv tyenv cryenv' })
21662170

21672171
-- | Call 'Cryptol.importSchema' using a 'CEnv.CryptolEnv'
21682172
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
@@ -755,26 +755,28 @@ type VarEnv = ScopedMap SS.Name (SS.Pos, SS.PrimitiveLifecycle,
755755
-- builtin types that aren't special cases in the AST appear)
756756
type TyEnv = ScopedMap SS.Name (SS.PrimitiveLifecycle, SS.NamedType)
757757

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

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

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

806806

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

812813
cryptolPush :: CryptolScopeStack -> CryptolScopeStack
@@ -858,9 +859,6 @@ data TopLevelRW =
858859
rwEnviron :: Environ
859860
, rwRebindables :: RebindableEnv
860861

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

11791177
-- Update the SAWScript environment.
1180-
Environ varenv tyenv <- gets rwEnviron
1178+
Environ varenv tyenv cryenv <- gets rwEnviron
11811179
rbenv <- gets rwRebindables
11821180
let (varenv', rbenv') = case rb of
11831181
SS.ReadOnlyVar ->
@@ -1196,7 +1194,7 @@ extendEnv pos name rb ty doc v = do
11961194
(varenv, re')
11971195

11981196
-- Mirror the value into the Cryptol environment if appropriate.
1199-
CryptolScopeStack (ce :| ces) <- gets rwCryptol
1197+
let CryptolScopeStack (ce :| ces) = cryenv
12001198
ce' <-
12011199
case v of
12021200
VTerm t ->
@@ -1215,19 +1213,19 @@ extendEnv pos name rb ty doc v = do
12151213
pure $ CEnv.bindTypedTerm (ident, tt) ce
12161214
_ ->
12171215
pure ce
1216+
let cryenv' = CryptolScopeStack (ce' :| ces)
12181217

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

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

12291227
-- Update the SAWScript environment.
1230-
Environ varenv tyenv <- gets rwEnviron
1228+
Environ varenv tyenv cryenv <- gets rwEnviron
12311229

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

12651263
-- Drop the new bits into place.
12661264
modify (\rw -> rw { rwEnviron = environ' })
@@ -1270,10 +1268,10 @@ extendEnvMulti bindings = do
12701268
addTypedef :: SS.Name -> SS.Type -> TopLevel ()
12711269
addTypedef name ty = do
12721270
avail <- gets rwPrimsAvail
1273-
Environ varenv tyenv <- gets rwEnviron
1271+
Environ varenv tyenv cryenv <- gets rwEnviron
12741272
let ty' = SS.substituteTyVars avail tyenv ty
12751273
tyenv' = ScopedMap.insert name (SS.Current, SS.ConcreteType ty') tyenv
1276-
modify (\rw -> rw { rwEnviron = Environ varenv tyenv' })
1274+
modify (\rw -> rw { rwEnviron = Environ varenv tyenv' cryenv })
12771275

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

0 commit comments

Comments
 (0)