on master help sign in
Switch to a much more performant representation for records.
commit6b1285036e723c5be90ac1eb0ad8aa8d3c895d60 authorevancz <info@elm-lang.org> dateSun 10 Feb 2013, 13:48 (14 years ago) parentcb609ea
3 files changed+64−34
core-js/Prelude.js+33 core-js/Value.js+9−5 elm/src/Gen/CompileToJS.hs+22−29
core-js/Prelude.js+33
@@ -1,3 +1,36 @@
1+function elmRecordCopy(r) {
2+ var o = {};
3+ for (var i in r) { o[i] = r[i]; }
4+ return o;
5+}
6+
7+function elmRecordRemove(x,r) {
8+ var o = elmRecordCopy(r);
9+ if (x in o._) {
10+ o[x] = o._[x][0];
11+ o._[x] = o._[x].slice(1);
12+ if (o._[x].length === 0) { delete o._[x]; }
13+ } else {
14+ delete o[x];
15+ }
16+ return o;
17+}
18+
19+function elmRecordReplace(kvs,r) {
20+ var o = elmRecordCopy(r);
21+ for (var i = kvs.length; i--; ) {
22+ kvsi = kvs[i];
23+ o[kvsi[0]] = kvsi[1];
24+ }
25+ return o;
26+}
27+
28+function elmRecordInsert(x,v,r) {
29+ var o = elmRecordCopy(r);
30+ if (x in o) o._[x] = [o[x]].concat(x in o._ ? o._[x].slice(0) : []);
31+ o[x] = v;
32+ return o;
33+}
134
235Value.addListener(document, 'elm_log', function(e) { console.log(e.value); });
336Value.addListener(document, 'elm_title', function(e) {document.title = e.value;});
core-js/Value.js+9−5
@@ -173,13 +173,17 @@ var Value = function(){
173173 } else if (typeof v === "string" && v.length < 2) {
174174 return "'"+v+"'";
175175 } else if (typeof v === "object" && ('_' in v)) {
176− var output = []
177− for (var k in v) {
178− if (k == '_') continue;
179− for (var i = v[k].length; i--; ) {
180− output.push(k + " = " + toString(v[k][i]));
176+ var output = [];
177+ for (var k in v._) {
178+ console.log(k,v._[k]);
179+ for (var i = v._[k].length; i--; ) {
180+ output.push(k + " = " + toString(v._[k][i]));
181181 }
182182 }
183+ for (var k in v) {
184+ if (k === '_') continue;
185+ output.push(k + " = " + toString(v[k]));
186+ }
183187 if (output.length === 0) return "{}";
184188 return "{ " + output.join(", ") + " }";
185189 } else if (v[0]) {
elm/src/Gen/CompileToJS.hs+22−29
@@ -2,7 +2,7 @@ module CompileToJS (showErr, jsModule) where
22
33import Ast
44import Context
5−import Control.Arrow (first)
5+import Control.Arrow (first,second)
66import Control.Monad (liftM,(<=<),join,ap)
77import Data.Char (isAlpha,isDigit)
88import Data.List (intercalate,sortBy,inits,foldl')
@@ -181,31 +181,23 @@ toJS' (C txt span expr) =
181181 Case e cases -> caseToJS span e cases
182182 _ -> toJS expr
183183
184−recordToJS e loop cmds =
185− do e' <- toJS' e
186− return $ jsFunc "" (concat [ assign "r" "{}"
187− , assign "e" e'
188− , "\nfor(var i in e){", loop, "}"
189− , cmds
190− , ret "r" ]) ++ "()"
191−
192−remove x = concat [ "\n if (i!='", x, "') { r[i]=e[i]; }"
193− , "\n else if (e[i].length>1) { r[i]=e[i].slice(1); }" ]
194−addField (x,e) = ((++add) . assign "v") `liftM` toJS' e
195− where add = concat [ "\n r.", x, " = '", x, "' in r ? [v].concat(r.", x, ") : [v];" ]
196−setField (x,e) = let rx = "r." ++ x in
197− do set <- globalAssign (rx ++ "[0]") `liftM` toJS' e
198− return (globalAssign rx (rx ++ ".slice(0)") ++ set)
199−access x e = jsFunc "r" (ret body) ++ parens e
200− where body = "'_' in r ? r." ++ x ++ "[0] : r." ++ x
201−makeRecord kvs = do
202− kvs' <- (Map.toList . foldl' combine Map.empty) `liftM` mapM prep kvs
203− let fs = map (\(k,vs) -> k ++ " : " ++ jsList vs) kvs' ++ ["_ : true"]
204− return $ braces ("\n " ++ intercalate ",\n " fs)
205− where combine r (k,v) = Map.insertWith (++) k v r
206− prep (k, as, e@(C t s _)) =
207− do v <- toJS' (foldr (\x e -> C t s $ Lambda x e) e as)
208− return (k,[v])
184+remove x e = "elmRecordRemove('" ++ x ++ "', " ++ e ++ ")"
185+addField x v e = "elmRecordInsert('" ++ x ++ "', " ++ v ++ ", " ++ e ++ ")"
186+setField fs e = "elmRecordReplace(" ++ jsList (map f fs) ++ ", " ++ e ++ ")"
187+ where f (x,v) = "['" ++ x ++ "'," ++ v ++ "]"
188+access x e = parens e ++ "." ++ x
189+makeRecord kvs = record `liftM` collect kvs
190+ where
191+ combine r (k,v) = Map.insertWith (++) k v r
192+ collect = liftM (foldl' combine Map.empty) . mapM prep
193+ prep (k, as, e@(C t s _)) =
194+ do v <- toJS' (foldr (\x e -> C t s $ Lambda x e) e as)
195+ return (k,[v])
196+ fields fs =
197+ braces ("\n "++intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
198+ hidden = fields . map (second jsList) .
199+ filter (not . null . snd) . Map.toList . Map.map tail
200+ record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
209201
210202
211203instance ToJS Expr where
@@ -219,9 +211,10 @@ instance ToJS Expr where
219211 Boolean b -> return $ if b then "true" else "false"
220212 Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
221213 Access e x -> access x `liftM` toJS' e
222− Remove e x -> recordToJS e (remove x) ""
223− Insert e x v -> recordToJS e "r[i]=e[i];" =<< addField (x,v)
224− Modify e fs -> recordToJS e "r[i]=e[i];" . concat =<< mapM setField fs
214+ Remove e x -> remove x `liftM` toJS' e
215+ Insert e x v -> addField x `liftM` toJS' v `ap` toJS' e
216+ Modify e fs -> do fs' <- (mapM (\(x,v) -> (,) x `liftM` toJS' v) fs)
217+ setField fs' `liftM` toJS' e
225218 Record fs -> makeRecord fs
226219 Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
227220