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

Refactor CESK machine to track environments through new Suspended state #1928

Merged
merged 54 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
058c3fd
CESK suspend state
byorgey Jun 7, 2024
8ad3fe4
suspend primitive
byorgey Jun 7, 2024
db57d1a
remove RobotContext and turn it into Env
byorgey Jun 7, 2024
ba95254
remove VResult + F*Env
byorgey Jun 8, 2024
5a5a8ad
turn def into syntax sugar for let
byorgey Jun 8, 2024
49a595e
remove Module and ProcessedTerm
byorgey Jun 9, 2024
807a50b
fill in type annotations on binders
byorgey Jun 10, 2024
20b82bb
split up Requirements module
byorgey Jun 12, 2024
935e370
fix machine stepping for new Env
byorgey Jun 11, 2024
93e4fb3
automatically insert suspend calls
byorgey Jun 13, 2024
c5f5fb5
fix test + benchmark suites
byorgey Jun 13, 2024
bca7a23
fix FromJSON Syntax instance
byorgey Jun 14, 2024
845a824
replace undefined in Step.Const
byorgey Jun 14, 2024
03e19a9
fix unit test suite
byorgey Jun 14, 2024
94a7809
get unit tests building
byorgey Jun 14, 2024
01e0f44
fix unused var analysis
byorgey Jun 14, 2024
fa83471
reinstate CPower requirement; 21/333 failing
byorgey Jun 14, 2024
6abdc0c
fix code size scoring test; 16/333 failing
byorgey Jun 14, 2024
4ab7947
fix infinite type error message that changed slightly; 15/333 failing
byorgey Jun 14, 2024
1655828
reinstate typechecking context stack entries for def/let; 9/333 failing
byorgey Jun 14, 2024
08ad198
fix pretty-printing for consecutive defs; 8/333 failing
byorgey Jun 14, 2024
98948f2
cabal gild
byorgey Jun 14, 2024
bfb21f2
fourmolu
byorgey Jun 14, 2024
9b575ce
apply hlint suggestions
byorgey Jun 14, 2024
413b6d2
fix tydef
byorgey Jun 14, 2024
5615c29
refactor and fix CESK initialization code
byorgey Jun 14, 2024
09ba197
fix remaining XXX
byorgey Jun 14, 2024
8e5b587
recreate it variable
byorgey Jun 14, 2024
e34adb2
tests for #681 and #1032
byorgey Jun 14, 2024
2e3c4f8
special case for insertSuspend noop
byorgey Jun 14, 2024
0826fc1
fix type of it variable when using type alias
byorgey Jun 14, 2024
6646432
fix requirements checking for definitions
byorgey Jun 14, 2024
75fb8fe
fix requirements checking during type checking for let
byorgey Jun 14, 2024
0b30679
fix run command
byorgey Jun 15, 2024
ec35222
remove debugging code
byorgey Jun 15, 2024
8d579e0
restore base Env after an exception bubbles to top level
byorgey Jun 15, 2024
b289b61
properly handle suspend with more continuation remaining
byorgey Jun 15, 2024
e2b1b3b
Remove last XXX comment
byorgey Jun 15, 2024
17e5500
add tests with nested def/tydef
byorgey Jun 15, 2024
ee45a19
fourmolu
byorgey Jun 15, 2024
a9874b7
remove redundant import
byorgey Jun 15, 2024
5e1b6e4
fix benchmark suite
byorgey Jun 15, 2024
d99bf2e
bugfix: exceptions must terminate atomic blocks
byorgey Jun 15, 2024
ee570e0
fix docspec test
byorgey Jun 16, 2024
cd56578
properly add binding when Suspended meets FBind
byorgey Jun 16, 2024
0e065d5
delete stray files
byorgey Jun 16, 2024
2d34d4b
improve comments
byorgey Jun 16, 2024
5c8c979
report explicit type annotations after checking instead of expanded v…
byorgey Jun 16, 2024
92487b4
more comments, ensure def has command type, and properly make let loc…
byorgey Jun 16, 2024
e330c51
bug fix: free vars in scope of tydef were being ignored; add minimal …
byorgey Jun 16, 2024
e763af8
fix Ctrl-C so it doesn't lose all definitions in scope
byorgey Jun 17, 2024
6cab7ec
fix filterTCStack
byorgey Jun 18, 2024
a8e263a
remove unnecessary change
byorgey Jun 18, 2024
328afae
fix import
byorgey Jun 19, 2024
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
Prev Previous commit
Next Next commit
more comments, ensure def has command type, and properly make let loc…
…al vs def global
  • Loading branch information
byorgey committed Jun 19, 2024
commit 92487b4da35e21f1b2ef163f7ddfb11290355f9e
25 changes: 15 additions & 10 deletions src/swarm-lang/Swarm/Language/Elaborate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@ elaborate =
-- (force x). When interpreting t1, we will put a binding (x |->
-- delay t1) in the context.
--
-- Here we also take inferred types for variables bound by let or
-- bind and stuff them into the term itself, so that we will still
-- have access to them at runtime, after type annotations on the
-- AST are erased. We need them at runtime so we can keep track
-- of the types of variables in scope, for use in typechecking
-- additional terms entered at the REPL.
-- Here we also take inferred types for variables bound by def or
-- bind (but NOT let) and stuff them into the term itself, so that
-- we will still have access to them at runtime, after type
-- annotations on the AST are erased. We need them at runtime so
-- we can keep track of the types of variables in scope, for use
-- in typechecking additional terms entered at the REPL. The
-- reason we do not do this for 'let' is so that 'let' introduces
-- truly local bindings which will not be available for use in
-- later REPL terms.
--
-- We assume requirements for these variables have already been
-- filled in during typechecking. The reason we need to wait
Expand All @@ -59,7 +62,10 @@ elaborate =
let wrap
| r = wrapForce (lvVar x) -- wrap in 'force' if recursive
| otherwise = id
in SLet ls r x (mty <|> Just (t1 ^. sType)) mreq (wrap t1) (wrap t2)
mty' = case ls of
LSDef -> mty <|> Just (t1 ^. sType)
LSLet -> Nothing
in SLet ls r x mty' mreq (wrap t1) (wrap t2)
SBind x (Just ty) _ mreq c1 c2 -> SBind x Nothing (Just ty) mreq c1 c2
-- Rewrite @f $ x@ to @f x@.
SApp (Syntax' _ (SApp (Syntax' _ (TConst AppF) _ _) l) _ _) r -> SApp l r
Expand All @@ -82,9 +88,8 @@ insertSuspend t = case t of
TRequireDevice {} -> thenSuspend
TRequire {} -> thenSuspend
TRequirements {} -> thenSuspend
-- Recurse through let, tydef, bind, and annotate (but NOT through
-- let).
TLet LSDef r x mty mreq t1 t2 -> TLet LSDef r x mty mreq t1 (insertSuspend t2)
-- Recurse through def, tydef, bind, and annotate.
TLet ls r x mty mreq t1 t2 -> TLet ls r x mty mreq t1 (insertSuspend t2)
TTydef x pty mtd t1 -> TTydef x pty mtd (insertSuspend t1)
TBind mx mty mreq c1 c2 -> TBind mx mty mreq c1 (insertSuspend c2)
TAnnotate t1 ty -> TAnnotate (insertSuspend t1) ty
Expand Down
38 changes: 36 additions & 2 deletions src/swarm-lang/Swarm/Language/Typecheck.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import Control.Effect.Reader
import Control.Effect.Throw
import Control.Lens ((^.))
import Control.Lens.Indexed (itraverse)
import Control.Monad (forM_, when, (<=<), (>=>))
import Control.Monad (forM_, void, when, (<=<), (>=>))
import Control.Monad.Free (Free (..))
import Data.Data (Data, gmapM)
import Data.Foldable (fold, traverse_)
Expand Down Expand Up @@ -975,6 +975,15 @@ check s@(CSyntax l t cs) expected = addLocToTypeErr l $ case t of
let Syntax' _ tt1 _ _ = t1
reqs = requirements tdCtx reqCtx tt1

-- If we are checking a 'def', ensure t2 has a command type. This ensures that
-- something like 'def ... end; x + 3' is not allowed, since this
-- would result in the whole thing being wrapped in return, like
-- 'return (def ... end; x + 3)', which means the def would be local and
-- not persist to the next REPL input, which could be surprising.
--
-- On the other hand, 'let x = y in x + 3' is perfectly fine.
when (ls == LSDef) $ void $ decomposeCmdTy t2 (Expected, expected)

-- Now check the type of the body, under a context extended with
-- the type and requirements of the bound variable.
t2' <-
Expand All @@ -985,8 +994,33 @@ check s@(CSyntax l t cs) expected = addLocToTypeErr l $ case t of
-- Make sure no skolem variables have escaped.
ask @UCtx >>= mapM_ (noSkolems l)

-- Annotate a 'def' with requirements, but not 'let'. The reason
-- is so that let introduces truly "local" bindings which never
-- persist, but def introduces "global" bindings. Variables bound
-- in the environment can only be used to typecheck future REPL
-- terms if the environment holds not only a value but also a type
-- + requirements for them. For example:
--
-- > def x : Int = 3 end; return (x + 2)
-- 5
-- > x
-- 3
-- > let y : Int = 3 in y + 2
-- 5
-- > y
-- 1:1: Unbound variable y
-- > let y = 3 in def x = 5 end; return (x + y)
-- 8
-- > y
-- 1:1: Unbound variable y
-- > x
-- 5
let mreqs = case ls of
LSDef -> Just reqs
LSLet -> Nothing

-- Return the annotated let.
return $ Syntax' l (SLet ls r x mxTy (Just reqs) t1' t2') cs expected
return $ Syntax' l (SLet ls r x mxTy mreqs t1' t2') cs expected

-- Kind-check a type definition and then check the body under an
-- extended context.
Expand Down
6 changes: 3 additions & 3 deletions test/unit/TestEval.hs
Original file line number Diff line number Diff line change
Expand Up @@ -327,15 +327,15 @@ testEval g =
"nesting"
[ testCase
"def nested in def"
("def x : Int = def y : Int = 3 end; y + 2 end; x" `evaluatesTo` VInt 5)
("def x : Cmd Int = def y : Int = 3 end; return (y + 2) end; x" `evaluatesTo` VInt 5)
, testCase
"nested def does not escape"
( "def z = 1 end; def x = def z = 3 end; z + 2 end; x + z"
( "def z = 1 end; def x = def z = 3 end; return (z + 2) end; n <- x; return (n + z)"
`evaluatesTo` VInt 6
)
, testCase
"nested tydef"
( "def x = (tydef X = Int end; def z : X = 3 end; z + 2) end; x"
( "def x = (tydef X = Int end; def z : X = 3 end; return (z + 2)) end; x"
`evaluatesTo` VInt 5
)
]
Expand Down
18 changes: 18 additions & 0 deletions test/unit/TestLanguagePipeline.hs
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,24 @@ testLanguagePipeline =
"move; def x = move; say 3 end; move;"
"1:25: Type mismatch:\n From context, expected `3` to have type `Text`,\n but it actually has type `Int`\n\n - While checking the right-hand side of a semicolon\n - While checking the definition of x"
)
, testGroup
"let and def types"
[ testCase
"let at non-cmd type"
(valid "let x = 3 in x + 2")
, testCase
"let at cmd type"
(valid "let x = 3 in move; return (x+2)")
, testCase
"def at non-cmd type"
( process
"def x = 3 end; x + 2"
"1:16: Type mismatch:\n From context, expected `x + 2` to have a type like"
)
, testCase
"def at cmd type"
(valid "def x = 3 end; move; return (x+2)")
]
]
where
valid = flip process ""
Expand Down