on master help sign in
Remove syntax for record insert and remove

These are pretty much never used in practice. They also can lead to problems if you extend a record with a field that already exists. You could potentially end up with weird behavior, but since this feature is rarely used, we have not actually observed this. Finally, this feature presents an optimization challenge. If the shape of a record can change as it flows through the program, it may become more difficult to optimize code to have constant time field lookups and straightforward field updates.

commit779f7aa10e10af944234f73dc911e96d66cb8374 authorEvan Czaplicki <info@elm-lang.org> dateThu 9 Jul 2015, 12:30 (11 years ago) parent8972f1e
9 files changed+42−155
src/AST/Expression/General.hs+2−27 src/Canonicalize.hs+2−8 src/Canonicalize/Declaration.hs+5−13 src/Canonicalize/Sort.hs+2−8 src/Generate/JavaScript.hs+1−10 src/Generate/Substitute.hs+2−8 src/Parse/Expression.hs+25−50 src/Type/Constrain/Expression.hs+1−18 src/Validate.hs+2−13
src/AST/Expression/General.hs+2−27
@@ -53,9 +53,7 @@ data Expr' ann def var typ
5353 | Case (Expr ann def var typ) [(Pattern.Pattern ann var, Expr ann def var typ)]
5454 | Data String [Expr ann def var typ]
5555 | Access (Expr ann def var typ) String
56− | Remove (Expr ann def var typ) String
57− | Insert (Expr ann def var typ) String (Expr ann def var typ)
58− | Modify (Expr ann def var typ) [(String, Expr ann def var typ)]
56+ | Update (Expr ann def var typ) [(String, Expr ann def var typ)]
5957 | Record [(String, Expr ann def var typ)]
6058 -- for type checking and code gen only
6159 | Port (PortImpl (Expr ann def var typ) typ)
@@ -215,30 +213,7 @@ instance (P.Pretty def, P.Pretty var, Var.ToString var) => P.Pretty (Expr' ann d
215213 Access record field ->
216214 P.pretty dealiaser True record <> P.text "." <> P.text field
217215
218− Remove record field ->
219− P.braces (P.pretty dealiaser False record <+> P.text "-" <+> P.text field)
220−
221− Insert (A.A _ (Remove record oldField)) newField expr ->
222− P.braces $
223− P.hsep
224− [ P.pretty dealiaser False record
225− , P.text "-"
226− , P.text oldField
227− , P.text "|"
228− , P.text newField
229− , P.equals
230− , P.pretty dealiaser False expr
231− ]
232−
233− Insert record field expr ->
234− P.braces $
235− P.pretty dealiaser False record
236− <+> P.text "|"
237− <+> P.text field
238− <+> P.equals
239− <+> P.pretty dealiaser False expr
240−
241− Modify record fields ->
216+ Update record fields ->
242217 P.braces $
243218 P.hang
244219 (P.pretty dealiaser False record <+> P.text "|")
src/Canonicalize.hs+2−8
@@ -337,14 +337,8 @@ expression env (A.A region validExpr) =
337337 Access record field ->
338338 Access <$> go record <*> Result.ok field
339339
340− Remove record field ->
341− flip Remove field <$> go record
342−
343− Insert record field expr ->
344− flip Insert field <$> go record <*> go expr
345−
346− Modify record fields ->
347− Modify
340+ Update record fields ->
341+ Update
348342 <$> go record
349343 <*> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
350344
src/Canonicalize/Declaration.hs+5−13
@@ -38,28 +38,20 @@ toDefs moduleName (A.A (region,_) decl) =
3838 in
3939 [ definition ctor (buildFunction body vars) region (foldr T.Lambda tbody tipes) ]
4040
41− D.TypeAlias name tvars tipe@(T.Record fields ext) ->
41+ D.TypeAlias name tvars tipe@(T.Record fields Nothing) ->
4242 [ definition name (buildFunction record vars) region (foldr T.Lambda result args) ]
4343 where
4444 result =
4545 T.Aliased (typeVar name) (zip tvars (map T.Var tvars)) (T.Holey tipe)
4646
4747 args =
48− map snd fields ++ maybe [] (:[]) ext
48+ map snd fields
4949
50− var = loc . E.localVar
51− vars = take (length args) infiniteArgs
52−
53− efields =
54− zip (map fst fields) (map var vars)
50+ vars =
51+ take (length args) infiniteArgs
5552
5653 record =
57− case ext of
58− Nothing ->
59− loc (E.Record efields)
60−
61− Just _ ->
62− foldl (\r (f,v) -> loc (E.Insert r f v)) (var (last vars)) efields
54+ loc (E.Record (zip (map fst fields) (map (loc . E.localVar) vars)))
6355
6456 -- Type aliases must be added to an extended equality dictionary,
6557 -- but they do not require any basic constraints.
src/Canonicalize/Sort.hs+2−8
@@ -79,14 +79,8 @@ reorder (A.A ann expression) =
7979 Access record field ->
8080 Access <$> reorder record <*> return field
8181
82− Remove record field ->
83− Remove <$> reorder record <*> return field
84−
85− Insert record field expr ->
86− Insert <$> reorder record <*> return field <*> reorder expr
87−
88− Modify record fields ->
89− Modify
82+ Update record fields ->
83+ Update
9084 <$> reorder record
9185 <*> mapM (\(field,expr) -> (,) field <$> reorder expr) fields
9286
src/Generate/JavaScript.hs+1−10
@@ -77,16 +77,7 @@ expression (A.A region expr) =
7777 do e' <- expression e
7878 return $ DotRef () e' (var (Var.varName field))
7979
80− Remove e field ->
81− do e' <- expression e
82− return $ _Utils "remove" `call` [ string (Var.varName field), e' ]
83−
84− Insert e field value ->
85− do value' <- expression value
86− e' <- expression e
87− return $ _Utils "insert" `call` [ string (Var.varName field), value', e' ]
88−
89− Modify e fields ->
80+ Update e fields ->
9081 do e' <- expression e
9182 fields' <-
9283 forM fields $ \(field, value) ->
src/Generate/Substitute.hs+2−8
@@ -72,14 +72,8 @@ subst old new expression =
7272 Access record field ->
7373 Access (f record) field
7474
75− Remove record field ->
76− Remove (f record) field
77−
78− Insert record field value ->
79− Insert (f record) field (f value)
80−
81− Modify record fields ->
82− Modify (f record) (map (second f) fields)
75+ Update record fields ->
76+ Update (f record) (map (second f) fields)
8377
8478 Record fields ->
8579 Record (map (second f) fields)
src/Parse/Expression.hs+25−50
@@ -134,65 +134,40 @@ parensTerm =
134134
135135recordTerm :: IParser Source.Expr
136136recordTerm =
137− addLocation $
138− brackets (choice [ misc, record ])
139− where
140− record =
141− E.Record <$> commaSep field
142−
143− field =
144− do label <- rLabel
145− patterns <- spacePrefix Pattern.term
146− padded equals
147− body <- expr
148− return (label, makeFunction patterns body)
149−
150− misc =
151− do nextParser <- try miscStarter
152− whitespace
153− nextParser
154−
155− miscStarter =
156− do start <- getMyPosition
157− record <- addLocation (E.rawVar <$> rLabel)
137+ addLocation $ brackets $ choice $
138+ [ do starter <- try (addLocation rLabel)
158139 whitespace
159140 choice
160− [ string "-" >> return (afterMinus start record)
161− , string "|" >> return (afterBar record)
141+ [ update starter
142+ , literal starter
162143 ]
144+ , return (E.Record [])
145+ ]
146+ where
147+ update (A.A ann starter) =
148+ do try (string "|")
149+ whitespace
150+ fields <- commaSep1 field
151+ return (E.Update (A.A ann (E.rawVar starter)) fields)
163152
164− afterMinus start record =
165− do field <- rLabel
166− end <- getMyPosition
167− let subRecord' = E.Remove record field
168− maybe <- optionMaybe (try (whitespace >> string "|"))
169− case maybe of
170− Nothing ->
171− return subRecord'
172− Just _ ->
173− do whitespace
174− field <- rLabel
175− padded equals
176− E.Insert (A.at start end subRecord') field <$> expr
177−
178− afterBar record =
179− do field <- rLabel
153+ literal (A.A _ starter) =
154+ do try (string "<-")
155+ whitespace
156+ value <- expr
180157 whitespace
181158 choice
182− [ do equals
183− whitespace
184− E.Insert record field <$> expr
185− , do leftArrow
159+ [ do try comma
186160 whitespace
187− value <- expr
188− updates <- spaceyPrefixBy comma update
189− return (E.Modify record ((field,value) : updates))
161+ fields <- commaSep field
162+ return (E.Record ((starter, value) : fields))
163+ , return (E.Record [(starter, value)])
190164 ]
191165
192− update =
193− do lbl <- rLabel
194− padded leftArrow
195− (,) lbl <$> expr
166+ field =
167+ do key <- rLabel
168+ padded (string "<-")
169+ value <- expr
170+ return (key, value)
196171
197172
198173term :: IParser Source.Expr
src/Type/Constrain/Expression.hs+1−18
@@ -117,24 +117,7 @@ constrain env annotatedExpr@(A.A region expression) tipe =
117117 exists $ \t ->
118118 constrain env expr (record (Map.singleton label [tipe]) t)
119119
120− E.Remove expr label ->
121− exists $ \t ->
122− constrain env expr (record (Map.singleton label [t]) tipe)
123−
124− E.Insert expr label value ->
125− exists $ \valueType ->
126− exists $ \recordType ->
127− do valueCon <- constrain env value valueType
128− recordCon <- constrain env expr recordType
129− let newRecordType =
130− record (Map.singleton label [valueType]) recordType
131− return $ CAnd
132− [ valueCon
133− , recordCon
134− , CEqual Error.Record region tipe newRecordType
135− ]
136−
137− E.Modify expr fields ->
120+ E.Update expr fields ->
138121 exists $ \t ->
139122 do oldVars <- Monad.forM fields $ \_ -> variable Flexible
140123 let oldFields = ST.fieldMap (zip (map fst fields) (map varN oldVars))
src/Validate.hs+2−13
@@ -221,19 +221,8 @@ expression (A.A ann sourceExpression) =
221221 <$> expression record
222222 <*> return field
223223
224− Remove record field ->
225− Remove
226− <$> expression record
227− <*> return field
228−
229− Insert record field expr ->
230− Insert
231− <$> expression record
232− <*> return field
233− <*> expression expr
234−
235− Modify record fields ->
236− Modify
224+ Update record fields ->
225+ Update
237226 <$> expression record
238227 <*> T.traverse second fields
239228