on master help sign in
Add record modification syntax:

{ book | title <- "Harry Potter" } Allows you to change the type of a field.

commitde6cb460cd9de99e4de9740227878c25f96a8fe4 authorevancz <info@elm-lang.org> dateTue 25 Dec 2012, 03:45 (14 years ago) parentec94f4e
6 files changed+43−19
elm/src/Ast.hs+3−1 elm/src/Gen/CompileToJS.hs+7 elm/src/Parse/Expr.hs+13−18 elm/src/Rename.hs+8 elm/src/Substitute.hs+2 elm/src/Types/Constrain.hs+10
elm/src/Ast.hs+3−1
@@ -27,6 +27,7 @@ data Expr = IntNum Int
2727 | Boolean Bool
2828 | Range CExpr CExpr
2929 | Access CExpr String
30+ | Modify CExpr String CExpr
3031 | Record [(String,[String],CExpr)]
3132 | Binop String CExpr CExpr
3233 | Lambda String CExpr
@@ -88,7 +89,8 @@ instance Show Expr where
8889 Boolean b -> show b
8990 Range e1 e2 -> "[" ++ show e1 ++ ".." ++ show e2 ++ "]"
9091 Access e x -> show' e ++ "." ++ x
91− Record r -> "{" ++ intercalate ", " (map fields r) ++ "}"
92+ Modify e x e' -> "{ " ++ show e ++ " | " ++ x ++ " <- " ++ show e' ++ " }"
93+ Record r -> "{ " ++ intercalate ", " (map fields r) ++ " }"
9294 where fields (f,args,e) = f ++ concatMap (' ':) args ++ " = " ++ show e
9395 Binop op e1 e2 -> show' e1 ++ " " ++ op ++ " " ++ show' e2
9496 Lambda x e -> let (xs,e') = getLambdas (noContext $ Lambda x e) in
elm/src/Gen/CompileToJS.hs+7
@@ -186,6 +186,13 @@ instance ToJS Expr where
186186 Boolean b -> return $ if b then "true" else "false"
187187 Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
188188 Access e lbl -> (\s -> s ++ "." ++ lbl) `liftM` toJS' e
189+
190+ Modify e lbl v -> do e' <- toJS' e
191+ v' <- toJS' v
192+ let body = concat [ assign "r" e'
193+ , globalAssign ("r." ++ lbl) v'
194+ , ret "r" ]
195+ return $ jsFunc "" body ++ "()"
189196
190197 Record fs -> (braces . intercalate ",\n") `liftM` mapM toField fs
191198 where toField (f, as, ce@(C t s e)) =
elm/src/Parse/Expr.hs+13−18
@@ -93,27 +93,22 @@ parensTerm = parens $ choice
9393 ]
9494
9595recordTerm :: IParser Expr
96−recordTerm = brackets $ do
97− Record <$> (mapM extract =<< commaSep field)
96+recordTerm = brackets $ choice [ modify, record ]
9897 where field = do
99− fDefs <- (:) <$> (PVar <$> lowVar) <*> spacePrefix patternTerm
100− whitespace
101− e <- string "=" >> whitespace >> expr
102− flattenPatterns fDefs e
98+ fDefs <- (:) <$> (PVar <$> lowVar) <*> spacePrefix patternTerm
99+ whitespace
100+ e <- string "=" >> whitespace >> expr
101+ flattenPatterns fDefs e
103102 extract [ FnDef f args exp ] = return (f,args,exp)
104103 extract _ = fail "Improperly formed record field."
105−{--
106− record <- expr
107− whitespace >> string "|" >> whitespace
108− label <- lowVar
109− whitespace
110− op <- (string "<-" <|> string "=")
111− whitespace
112− e <- expr
113− case op of
114− "<-" ->
115− "=" ->
116−--}
104+ record = Record <$> (mapM extract =<< commaSep field)
105+ modify = do
106+ record <- try $ do record <- addContext (Var <$> lowVar)
107+ whitespace >> string "|" >> whitespace
108+ return record
109+ label <- lowVar
110+ whitespace >> string "<-" >> whitespace
111+ Modify record label <$> expr
117112
118113term :: IParser CExpr
119114term = addContext (choice [ numTerm, strTerm, chrTerm, listTerm, accessor ])
elm/src/Rename.hs+8
@@ -63,6 +63,14 @@ instance Rename Expr where
6363 Access e x -> Access `liftM` rnm e
6464 `ap` return x
6565
66+ Modify e f v -> flip Modify f `liftM` rnm e
67+ `ap` rnm v
68+
69+ Record fs -> Record `liftM` mapM frnm fs
70+ where frnm (f,as,e) = do env' <- extends env as
71+ e' <- rename env' e
72+ return (f, map env' as, e')
73+
6674 Binop op@(h:_) e1 e2 ->
6775 let rop = if isLower h || '_' == h
6876 then env op
elm/src/Substitute.hs+2
@@ -10,6 +10,8 @@ subst old new expr =
1010 case expr of
1111 Range e1 e2 -> Range (f e1) (f e2)
1212 Access e x -> Access (f e) x
13+ Modify r lbl v -> Modify (f r) lbl (f v)
14+ Record fs -> Record (map (\(lbl,as,e) -> (lbl,as,f e)) fs)
1315 Binop op e1 e2 -> Binop op (f e1) (f e2)
1416 Lambda x e -> if x == old then expr else Lambda x (f e)
1517 App e1 e2 -> App (f e1) (f e2)
elm/src/Types/Constrain.hs+10
@@ -138,6 +138,16 @@ gen (C _ span expr) =
138138 c = (ctx' (RecordT fs rtype' :=: rtype))
139139 return (as, Set.insert c cs, t)
140140
141+ Modify record label value ->
142+ do (ras,rcs,rtype) <- gen record
143+ (vas,vcs,vtype) <- gen value
144+ t <- beta
145+ rtype' <- beta
146+ let c = rtype :=: RecordT (Map.singleton label [t]) rtype'
147+ return ( unionA ras vas
148+ , Set.unions [Set.singleton (ctx' c), rcs, vcs]
149+ , RecordT (Map.singleton label [vtype]) rtype' )
150+
141151 Record fields ->
142152 let insert label tipe = Map.insertWith (++) label [tipe]
143153 getScheme (f,args,e) = do