Skip to content

Commit

Permalink
feature: Allow any names as record keys
Browse files Browse the repository at this point in the history
  • Loading branch information
supki committed Oct 8, 2024
1 parent 8990799 commit e9ce83f
Show file tree
Hide file tree
Showing 10 changed files with 28 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/T/Embed.hs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ instance Eject Pcre.Regex where
value ->
Left (TypeError (varE name) Type.Regexp (typeOf value) (sexp value))

instance (k ~ Text, v ~ Value) => Eject (HashMap k v) where
instance (k ~ Name, v ~ Value) => Eject (HashMap k v) where
eject name = \case
Record o ->
pure o
Expand Down
4 changes: 2 additions & 2 deletions src/T/Exp.hs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ array :: Vector Exp -> Exp
array =
litE_ . Array

record :: HashMap Text Exp -> Exp
record :: HashMap Name Exp -> Exp
record =
litE_ . Record

Expand Down Expand Up @@ -164,7 +164,7 @@ data Literal
| String Text
| Regexp Pcre.Regex
| Array (Vector Exp)
| Record (HashMap Text Exp)
| Record (HashMap Name Exp)
deriving (Show, Eq)

instance SExp.To Literal where
Expand Down
5 changes: 5 additions & 0 deletions src/T/Name.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module T.Name
( Name(..)
, toString
, toText
) where


Expand Down Expand Up @@ -32,3 +33,7 @@ instance Pretty Name where
toString :: Name -> String
toString name =
Text.unpack name.unName

toText :: Name -> Text
toText name =
name.unName
2 changes: 1 addition & 1 deletion src/T/Parse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ litP = do
(braces (spaces *> Unspaced (sepBy kv (symbol ","))))
where
kv = do
k <- map fromString (some letter)
_ :+ k <- nameP
_ <- symbol ":"
v <- expP
pure (k, v)
Expand Down
8 changes: 4 additions & 4 deletions src/T/Render.hs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ evalExp = \case
throwError (OutOfBounds expIdx (sexp xs) (sexp idx))
Just x ->
pure x
_ :< Key exp (_ :+ Name key) -> do
_ :< Key exp (_ :+ key) -> do
r <- enforceRecord exp
case HashMap.lookup key r of
Nothing ->
Expand All @@ -245,7 +245,7 @@ enforceArray exp = do
_ ->
throwError (TypeError exp Type.Array (Value.typeOf v) (sexp v))

enforceRecord :: (Ctx m, MonadError Error m) => Exp -> m (HashMap Text Value)
enforceRecord :: (Ctx m, MonadError Error m) => Exp -> m (HashMap Name Value)
enforceRecord exp = do
v <- evalExp exp
case v of
Expand Down Expand Up @@ -429,12 +429,12 @@ build :: MonadState Rendering m => Builder -> m ()
build chunk =
modify (\env -> env {Rendering.result = env.result <> chunk})

loopRecord :: Maybe Text -> Int -> Int -> Value
loopRecord :: Maybe Name -> Int -> Int -> Value
loopRecord key len idx =
Value.Record $ HashMap.fromList
[ ("length", Value.Int len)
, ("index", Value.Int idx)
, ("first", Value.Bool (idx == 0))
, ("last", Value.Bool (idx == len - 1))
, ("key", maybe Value.Null Value.String key)
, ("key", maybe Value.Null (Value.String . Name.toText) key)
]
9 changes: 6 additions & 3 deletions src/T/Value.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ module T.Value
import Data.Aeson qualified as Aeson
import Data.Aeson.KeyMap qualified as Aeson (fromHashMapText, toHashMapText)
import Data.ByteString.Lazy qualified as Lazy (ByteString)
import Data.HashMap.Strict qualified as HashMap
import Data.Scientific qualified as Scientific
import Data.Text.Lazy qualified as Text.Lazy
import Data.Text.Lazy.Encoding qualified as Text.Lazy
import Text.Regex.PCRE.Light qualified as Pcre

import T.Error (Error)
import T.Exp ((:+)(..), Ann)
import T.Name (Name(..))
import T.Name qualified as Name
import T.Prelude
import T.SExp (sexp)
import T.SExp qualified as SExp
Expand All @@ -32,7 +35,7 @@ data Value
| String Text
| Regexp Pcre.Regex
| Array (Vector Value)
| Record (HashMap Text Value)
| Record (HashMap Name Value)
| Lam (Ann :+ Value -> Either Error Value)

instance SExp.To Value where
Expand Down Expand Up @@ -86,7 +89,7 @@ displayWith f =
Array xs ->
Aeson.Array (map ejectAeson xs)
Record r ->
Aeson.Object (Aeson.fromHashMapText (map ejectAeson r))
Aeson.Object (Aeson.fromHashMapText (HashMap.mapKeys Name.toText (map ejectAeson r)))
Lam _f ->
Aeson.String "<lambda>"

Expand Down Expand Up @@ -115,4 +118,4 @@ embedAeson = \case
Aeson.Array xs ->
Array (map embedAeson xs)
Aeson.Object xs ->
Record (Aeson.toHashMapText (map embedAeson xs))
Record (HashMap.mapKeys Name (Aeson.toHashMapText (map embedAeson xs)))
2 changes: 1 addition & 1 deletion test/T/Parse/AnnSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ spec =
errorOf "{{ {foo:4} + 1 }}" `shouldBe`
"(interactive):1:4: error: mismatched types in +: \n\
\ expected: Number\n\
\ but got: {\"foo\" 4} : Record\n\
\ but got: {foo 4} : Record\n\
\1 | {{ {foo:4} + 1 }}<EOF> \n\
\ | ~~~~~~~ "

Expand Down
3 changes: 2 additions & 1 deletion test/T/ParseSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ spec =
(int 7))
"{{ {} }}" `shouldParseTo` Tmpl.Exp (record [])
"{{ {x: 4} }}" `shouldParseTo` Tmpl.Exp (record [("x", int 4)])
"{{ {x->y: 4} }}" `shouldParseTo` Tmpl.Exp (record [("x->y", int 4)])
"{{ {x: 4, y: \"foo\"} }}" `shouldParseTo`
Tmpl.Exp
(record
Expand Down Expand Up @@ -258,7 +259,7 @@ array :: [Exp] -> Exp
array =
litE_ . Array . Vector.fromList

record :: [(Text, Exp)] -> Exp
record :: [(Name, Exp)] -> Exp
record =
litE_ . Record . HashMap.fromList

Expand Down
2 changes: 1 addition & 1 deletion test/T/RenderSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ spec =
r_ "{{ {foo: [1,{bar: 7},3]}.foo[1].bar }}" `shouldRender` "7"
r_ "{{ 4.foo }}" `shouldRaise`
TypeError (litE_ (Int 4)) Type.Record Type.Int "4"
r_ "{{ {}.foo }}" `shouldRaise` MissingProperty (record mempty) (sexp (record mempty)) "\"foo\""
r_ "{{ {}.foo }}" `shouldRaise` MissingProperty (record mempty) (sexp (record mempty)) "foo"

context "line blocks" $
it "examples" $ do
Expand Down
9 changes: 5 additions & 4 deletions test/T/SExpSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import T.Parse (parseText)
import T.Prelude
import T.Exp (Exp)
import T.SExp (render, sexp)
import T.Name (Name)
import T.Stdlib qualified as Stdlib
import T.Tmpl (Tmpl)
import T.Tmpl qualified as Tmpl
Expand Down Expand Up @@ -73,7 +74,7 @@ spec = do
rexp "{{ [false, 42] }}" `shouldBe` "[false 42]"

it "record" $
rexp "{{ {foo: 42, bar: 4.2} }}" `shouldBe` "{\"bar\" 4.2 \"foo\" 42}"
rexp "{{ {foo: 42, bar: 4.2} }}" `shouldBe` "{bar 4.2 foo 42}"

it "var" $
rexp "{{ foo }}" `shouldBe` "foo"
Expand Down Expand Up @@ -127,9 +128,9 @@ spec = do

it "record" $ do
render (sexp (Value.Record [("foo", Value.Int 4), ("bar", Value.Int 7)])) `shouldBe`
"{\"bar\" 7 \"foo\" 4}"
render (sexp ([("foo", 4), ("bar", 7)] :: HashMap Text Int)) `shouldBe`
"{\"bar\" 7 \"foo\" 4}"
"{bar 7 foo 4}"
render (sexp ([("foo", 4), ("bar", 7)] :: HashMap Name Int)) `shouldBe`
"{bar 7 foo 4}"

it "lam" $
render (sexp (Value.Lam (\_ -> pure Value.Null))) `shouldBe` "(lambda [_] ...)"
Expand Down

0 comments on commit e9ce83f

Please sign in to comment.