-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Towards #116. This PR introduces a new built-in command `read`, which can (attempt to) convert text into values, *i.e.* a partial inverse to `format`. It has type `read : Text -> a` and is a little bit magical, since its behavior depends on the inferred output type. In particular, if reading at the expected output type succeeds, it will return the value read; otherwise it throws an exception. In other words, in order to use `read` successfully you must already know what type you expect to get. At first I gave it the type `Text -> (Unit + a)` and had it return `inl ()` whenever it failed, but then I realized that (1) you can make either version from the other (to convert `Text -> (Unit + a)` to `Text -> a`, `case` on the result and call `fail` if you get `inl`; to convert the other way, use `try`), but (2) it is simpler/easier to have the version that crashes to start and then use a `net` to turn it into the pure functional version if you wish, rather than the other way around (which requires a much harder-to-obtain `ADT calculator`). From a technical point of view, the way this is achieved is by inserting the type inferred for `read` as an extra parameter during elaboration. (Having types-as-special-values in the language might be useful for other things down the road as well.) Note that this makes `read` strictly weaker than the `read` function in Haskell, which works via dictionary-passing. For `read` in Swarm to work, its concrete type must be statically known at compile time. For example here is a function that works in Haskell but not Swarm: ``` def testRead : a -> Bool = \x. read (format x) == x end ``` I think it should still be sufficiently usable, however, and the current implementation is much simpler than going to full-fledged type classes. Currently `read` does not work on functions or delay types (even though such things are supported by `format`). We may add them in the future, but it would be much more complex since it would require parsing arbitrary Swarm code and dealing properly with environments and closures etc. `read` also does not currently work with user-defined types; see #2223 .
- Loading branch information
Showing
23 changed files
with
268 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -161,6 +161,7 @@ | |
"fail" | ||
"not" | ||
"format" | ||
"read" | ||
"chars" | ||
"split" | ||
"charat" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
-- | | ||
-- SPDX-License-Identifier: BSD-3-Clause | ||
-- | ||
-- Parse values of the Swarm language, indexed by type, by running the | ||
-- full swarm-lang parser and then checking that the result is a value | ||
-- of the proper type. | ||
module Swarm.Language.Parser.Value (readValue) where | ||
|
||
import Control.Lens ((^.)) | ||
import Data.Either.Extra (eitherToMaybe) | ||
import Data.Text (Text) | ||
import Swarm.Language.Context qualified as Ctx | ||
import Swarm.Language.Key (parseKeyComboFull) | ||
import Swarm.Language.Parser (readNonemptyTerm) | ||
import Swarm.Language.Syntax | ||
import Swarm.Language.Typecheck (checkTop) | ||
import Swarm.Language.Types (Type) | ||
import Swarm.Language.Value | ||
import Text.Megaparsec qualified as MP | ||
|
||
readValue :: Type -> Text -> Maybe Value | ||
readValue ty txt = do | ||
s <- eitherToMaybe $ readNonemptyTerm txt | ||
_ <- eitherToMaybe $ checkTop Ctx.empty Ctx.empty Ctx.empty s ty | ||
toValue $ s ^. sTerm | ||
|
||
toValue :: Term -> Maybe Value | ||
toValue = \case | ||
TUnit -> Just VUnit | ||
TDir d -> Just $ VDir d | ||
TInt n -> Just $ VInt n | ||
TText t -> Just $ VText t | ||
TBool b -> Just $ VBool b | ||
TApp (TConst c) t2 -> case c of | ||
Neg -> toValue t2 >>= negateInt | ||
Inl -> VInj False <$> toValue t2 | ||
Inr -> VInj True <$> toValue t2 | ||
Key -> do | ||
VText k <- toValue t2 | ||
VKey <$> eitherToMaybe (MP.runParser parseKeyComboFull "" k) | ||
_ -> Nothing | ||
TPair t1 t2 -> VPair <$> toValue t1 <*> toValue t2 | ||
TRcd m -> VRcd <$> traverse (>>= toValue) m | ||
-- List the other cases explicitly, instead of a catch-all, so that | ||
-- we will get a warning if we ever add new constructors in the | ||
-- future | ||
TConst {} -> Nothing | ||
TAntiInt {} -> Nothing | ||
TAntiText {} -> Nothing | ||
TRequireDevice {} -> Nothing | ||
TRequire {} -> Nothing | ||
TRequirements {} -> Nothing | ||
TVar {} -> Nothing | ||
TLam {} -> Nothing | ||
TApp {} -> Nothing | ||
TLet {} -> Nothing | ||
TTydef {} -> Nothing | ||
TBind {} -> Nothing | ||
TDelay {} -> Nothing | ||
TProj {} -> Nothing | ||
TAnnotate {} -> Nothing | ||
TSuspend {} -> Nothing | ||
|
||
-- TODO(#2232): in order to get `read` to work for delay, function, | ||
-- and/or command types, we will need to handle a few more of the | ||
-- above cases, e.g. TConst, TLam, TApp, TLet, TBind, TDelay. | ||
|
||
negateInt :: Value -> Maybe Value | ||
negateInt = \case | ||
VInt n -> Just (VInt (-n)) | ||
_ -> Nothing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.