Mercurial > urweb
comparison src/sqlcache.sml @ 2289:78820fa8f5a7
Fix bugs for lock calculation and SQL parsing and add support for tasks.
author | Ziv Scully <ziv@mit.edu> |
---|---|
date | Sun, 15 Nov 2015 14:18:35 -0500 |
parents | 98f96a976ede |
children | 50ad02829abd |
comparison
equal
deleted
inserted
replaced
2288:98f96a976ede | 2289:78820fa8f5a7 |
---|---|
1 structure Sqlcache :> SQLCACHE = struct | 1 structure Sqlcache (* DEBUG :> SQLCACHE *) = struct |
2 | 2 |
3 | 3 |
4 (*********************) | 4 (*********************) |
5 (* General Utilities *) | 5 (* General Utilities *) |
6 (*********************) | 6 (*********************) |
310 in | 310 in |
311 removeRedundant' (zs, []) | 311 removeRedundant' (zs, []) |
312 end | 312 end |
313 | 313 |
314 datatype atomExp = | 314 datatype atomExp = |
315 QueryArg of int | 315 True |
316 | False | |
317 | QueryArg of int | |
316 | DmlRel of int | 318 | DmlRel of int |
317 | Prim of Prim.t | 319 | Prim of Prim.t |
318 | Field of string * string | 320 | Field of string * string |
319 | 321 |
320 structure AtomExpKey : ORD_KEY = struct | 322 structure AtomExpKey : ORD_KEY = struct |
321 | 323 |
322 type ord_key = atomExp | 324 type ord_key = atomExp |
323 | 325 |
324 val compare = | 326 val compare = |
325 fn (QueryArg n1, QueryArg n2) => Int.compare (n1, n2) | 327 fn (True, True) => EQUAL |
328 | (True, _) => LESS | |
329 | (_, True) => GREATER | |
330 | (False, False) => EQUAL | |
331 | (False, _) => LESS | |
332 | (_, False) => GREATER | |
333 | (QueryArg n1, QueryArg n2) => Int.compare (n1, n2) | |
326 | (QueryArg _, _) => LESS | 334 | (QueryArg _, _) => LESS |
327 | (_, QueryArg _) => GREATER | 335 | (_, QueryArg _) => GREATER |
328 | (DmlRel n1, DmlRel n2) => Int.compare (n1, n2) | 336 | (DmlRel n1, DmlRel n2) => Int.compare (n1, n2) |
329 | (DmlRel _, _) => LESS | 337 | (DmlRel _, _) => LESS |
330 | (_, DmlRel _) => GREATER | 338 | (_, DmlRel _) => GREATER |
529 | (_, NONE, _, sq as SOME _) => wrap sq | 537 | (_, NONE, _, sq as SOME _) => wrap sq |
530 (* Last case should suffice because we don't | 538 (* Last case should suffice because we don't |
531 project from a sqlified value (which is a | 539 project from a sqlified value (which is a |
532 string). *) | 540 string). *) |
533 | (_, sq as SOME _, [], NONE) => wrap sq | 541 | (_, sq as SOME _, [], NONE) => wrap sq |
534 | _ => raise Match | 542 | _ => raise Fail "Sqlcache: traverseSubst" |
535 end) | 543 end) |
536 (f n) | 544 (f n) |
537 in | 545 in |
538 traverseIM ops (fn (_, v) => mp v) | 546 traverseIM ops (fn (_, v) => mp v) |
539 end | 547 end |
618 <\obind\> | 626 <\obind\> |
619 (fn arg => | 627 (fn arg => |
620 AM.find (argsMap, arg) | 628 AM.find (argsMap, arg) |
621 <\obind\> | 629 <\obind\> |
622 (fn n' => SOME (ERel n'))) | 630 (fn n' => SOME (ERel n'))) |
623 | _ => raise Match | 631 | _ => raise Fail "Sqlcache: query (a)" |
624 in | 632 in |
625 case (map #1 qs) of | 633 case (map #1 qs) of |
626 (q :: qs) => | 634 (q :: qs) => |
627 let | 635 let |
628 val q = List.foldl Sql.Union q qs | 636 val q = List.foldl Sql.Union q qs |
629 val ns = IS.listItems (varsOfQuery q) | 637 val ns = IS.listItems (varsOfQuery q) |
630 val rename = | 638 val rename = |
631 fn ERel n => omap ERel (indexOf (fn n' => n' = n) ns) | 639 fn ERel n => omap ERel (indexOf (fn n' => n' = n) ns) |
632 | _ => raise Match | 640 | _ => raise Fail "Sqlcache: query (b)" |
633 in | 641 in |
634 case omapQuery rename q of | 642 case omapQuery rename q of |
635 SOME q => q | 643 SOME q => q |
636 (* We should never get NONE because indexOf should never fail. *) | 644 (* We should never get NONE because indexOf should never fail. *) |
637 | NONE => raise Match | 645 | NONE => raise Fail "Sqlcache: query (c)" |
638 end | 646 end |
639 (* We should never reach this case because [updateState] won't | 647 (* We should never reach this case because [updateState] won't |
640 put anything in the state if there are no queries. *) | 648 put anything in the state if there are no queries. *) |
641 | [] => raise Match | 649 | [] => raise Fail "Sqlcache: query (d)" |
642 end | 650 end |
643 | 651 |
644 val argOfExp = | 652 val argOfExp = |
645 let | 653 let |
646 fun doFields acc exp = | 654 fun doFields acc exp = |
698 | Sql.SqFalse => Combo (Disj, []) | 706 | Sql.SqFalse => Combo (Disj, []) |
699 | Sql.SqNot e => Negate (sqexpToFormula e) | 707 | Sql.SqNot e => Negate (sqexpToFormula e) |
700 | Sql.Binop (Sql.RCmp c, e1, e2) => Atom (c, e1, e2) | 708 | Sql.Binop (Sql.RCmp c, e1, e2) => Atom (c, e1, e2) |
701 | Sql.Binop (Sql.RLop l, p1, p2) => Combo (case l of Sql.And => Conj | Sql.Or => Disj, | 709 | Sql.Binop (Sql.RLop l, p1, p2) => Combo (case l of Sql.And => Conj | Sql.Or => Disj, |
702 [sqexpToFormula p1, sqexpToFormula p2]) | 710 [sqexpToFormula p1, sqexpToFormula p2]) |
711 | e as Sql.Field f => Atom (Sql.Eq, e, Sql.SqTrue) | |
703 (* ASK: any other sqexps that can be props? *) | 712 (* ASK: any other sqexps that can be props? *) |
704 | _ => raise Match | 713 | Sql.SqConst prim => |
714 (case prim of | |
715 (Prim.String (Prim.Normal, s)) => | |
716 if s = #trueString (Settings.currentDbms ()) | |
717 then Combo (Conj, []) | |
718 else if s = #falseString (Settings.currentDbms ()) | |
719 then Combo (Disj, []) | |
720 else raise Fail "Sqlcache: sqexpToFormula (SqConst a)" | |
721 | _ => raise Fail "Sqlcache: sqexpToFormula (SqConst b)") | |
722 | Sql.Computed _ => raise Fail "Sqlcache: sqexpToFormula (Computed)" | |
723 | Sql.SqKnown _ => raise Fail "Sqlcache: sqexpToFormula (SqKnown)" | |
724 | Sql.Inj _ => raise Fail "Sqlcache: sqexpToFormula (Inj)" | |
725 | Sql.SqFunc _ => raise Fail "Sqlcache: sqexpToFormula (SqFunc)" | |
726 | Sql.Unmodeled => raise Fail "Sqlcache: sqexpToFormula (Unmodeled)" | |
727 | Sql.Null => raise Fail "Sqlcache: sqexpToFormula (Null)" | |
705 | 728 |
706 fun mapSqexpFields f = | 729 fun mapSqexpFields f = |
707 fn Sql.Field (t, v) => f (t, v) | 730 fn Sql.Field (t, v) => f (t, v) |
708 | Sql.SqNot e => Sql.SqNot (mapSqexpFields f e) | 731 | Sql.SqNot e => Sql.SqNot (mapSqexpFields f e) |
709 | Sql.Binop (r, e1, e2) => Sql.Binop (r, mapSqexpFields f e1, mapSqexpFields f e2) | 732 | Sql.Binop (r, e1, e2) => Sql.Binop (r, mapSqexpFields f e1, mapSqexpFields f e2) |
797 | _ => NONE | 820 | _ => NONE |
798 | 821 |
799 fun equivClasses atoms : atomExp list list option = | 822 fun equivClasses atoms : atomExp list list option = |
800 let | 823 let |
801 val uf = List.foldl UF.union' UF.empty (List.mapPartial toKnownEquality atoms) | 824 val uf = List.foldl UF.union' UF.empty (List.mapPartial toKnownEquality atoms) |
802 val ineqs = List.filter (fn (cmp, _, _) => | |
803 cmp = Sql.Ne orelse cmp = Sql.Lt orelse cmp = Sql.Gt) | |
804 atoms | |
805 val contradiction = | 825 val contradiction = |
806 fn (cmp, SOME ae1, SOME ae2) => (cmp = Sql.Ne orelse cmp = Sql.Lt orelse cmp = Sql.Gt) | 826 fn (cmp, SOME ae1, SOME ae2) => (cmp = Sql.Ne orelse cmp = Sql.Lt orelse cmp = Sql.Gt) |
807 andalso UF.together (uf, ae1, ae2) | 827 andalso UF.together (uf, ae1, ae2) |
808 (* If we don't know one side of the comparision, not a contradiction. *) | 828 (* If we don't know one side of the comparision, not a contradiction. *) |
809 | _ => false | 829 | _ => false |
926 let | 946 let |
927 val loc = dummyLoc | 947 val loc = dummyLoc |
928 in | 948 in |
929 List.foldl (fn (e', seq) => ESeq ((seq, loc), (e', loc))) exp exps | 949 List.foldl (fn (e', seq) => ESeq ((seq, loc), (e', loc))) exp exps |
930 end | 950 end |
931 | _ => raise Match | 951 | _ => raise Fail "Sqlcache: sequence" |
932 | 952 |
933 (* Always increments negative indices as a hack we use later. *) | 953 (* Always increments negative indices as a hack we use later. *) |
934 fun incRels inc = | 954 fun incRels inc = |
935 MonoUtil.Exp.mapB | 955 MonoUtil.Exp.mapB |
936 {typ = fn t' => t', | 956 {typ = fn t' => t', |
981 exp = fn env => fn e' => fn s => Search.Continue (doExp env e' s), | 1001 exp = fn env => fn e' => fn s => Search.Continue (doExp env e' s), |
982 decl = fn _ => Search.return2, | 1002 decl = fn _ => Search.return2, |
983 bind = doBind} | 1003 bind = doBind} |
984 MonoEnv.empty file start of | 1004 MonoEnv.empty file start of |
985 Search.Continue x => x | 1005 Search.Continue x => x |
986 | Search.Return _ => raise Match | 1006 | Search.Return _ => raise Fail "Sqlcache: fileAllMapfoldB" |
987 | 1007 |
988 fun fileMap doExp file = #1 (fileAllMapfoldB (fn _ => fn e => fn _ => (doExp e, ())) file ()) | 1008 fun fileMap doExp file = #1 (fileAllMapfoldB (fn _ => fn e => fn _ => (doExp e, ())) file ()) |
989 | 1009 |
990 (* TODO: make this a bit prettier.... *) | 1010 (* TODO: make this a bit prettier.... *) |
991 val simplifySql = | 1011 val simplifySql = |
1027 fun doExp exp' = | 1047 fun doExp exp' = |
1028 let | 1048 let |
1029 val text = case exp' of | 1049 val text = case exp' of |
1030 EQuery {query = text, ...} => text | 1050 EQuery {query = text, ...} => text |
1031 | EDml (text, _) => text | 1051 | EDml (text, _) => text |
1032 | _ => raise Match | 1052 | _ => raise Fail "Sqlcache: simplifySql (a)" |
1033 val (newText, wrapLets, numArgs) = factorOutNontrivial text | 1053 val (newText, wrapLets, numArgs) = factorOutNontrivial text |
1034 val newExp' = case exp' of | 1054 val newExp' = case exp' of |
1035 EQuery q => EQuery {query = newText, | 1055 EQuery q => EQuery {query = newText, |
1036 exps = #exps q, | 1056 exps = #exps q, |
1037 tables = #tables q, | 1057 tables = #tables q, |
1038 state = #state q, | 1058 state = #state q, |
1039 body = #body q, | 1059 body = #body q, |
1040 initial = #initial q} | 1060 initial = #initial q} |
1041 | EDml (_, failureMode) => EDml (newText, failureMode) | 1061 | EDml (_, failureMode) => EDml (newText, failureMode) |
1042 | _ => raise Match | 1062 | _ => raise Fail "Sqlcache: simplifySql (b)" |
1043 in | 1063 in |
1044 (* Increment once for each new variable just made. This is | 1064 (* Increment once for each new variable just made. This is |
1045 where we use the negative De Bruijn indices hack. *) | 1065 where we use the negative De Bruijn indices hack. *) |
1046 (* TODO: please don't use that hack. As anyone could have | 1066 (* TODO: please don't use that hack. As anyone could have |
1047 predicted, it was incomprehensible a year later.... *) | 1067 predicted, it was incomprehensible a year later.... *) |
1126 fn (Cachable (_, f), state) => f state | 1146 fn (Cachable (_, f), state) => f state |
1127 | (Impure e, state) => (e, state) | 1147 | (Impure e, state) => (e, state) |
1128 | 1148 |
1129 val invalInfoOfSubexp = | 1149 val invalInfoOfSubexp = |
1130 fn Cachable (invalInfo, _) => invalInfo | 1150 fn Cachable (invalInfo, _) => invalInfo |
1131 | Impure _ => raise Match | 1151 | Impure _ => raise Fail "Sqlcache: invalInfoOfSubexp" |
1132 | 1152 |
1133 fun cacheWrap (env, exp, typ, args, index) = | 1153 fun cacheWrap (env, exp, typ, args, index) = |
1134 let | 1154 let |
1135 val loc = dummyLoc | 1155 val loc = dummyLoc |
1136 val rel0 = (ERel 0, loc) | 1156 val rel0 = (ERel 0, loc) |
1273 case attempt of | 1293 case attempt of |
1274 SOME (subexp, state) => (subexp, state) | 1294 SOME (subexp, state) => (subexp, state) |
1275 | NONE => mapFst Impure (mkExp state) | 1295 | NONE => mapFst Impure (mkExp state) |
1276 end | 1296 end |
1277 fun wrapBind1 f arg = | 1297 fun wrapBind1 f arg = |
1278 wrapBindN (fn [arg] => f arg | _ => raise Match) [arg] | 1298 wrapBindN (fn [arg] => f arg |
1299 | _ => raise Fail "Sqlcache: cacheTree (a)") [arg] | |
1279 fun wrapBind2 f (arg1, arg2) = | 1300 fun wrapBind2 f (arg1, arg2) = |
1280 wrapBindN (fn [arg1, arg2] => f (arg1, arg2) | _ => raise Match) [arg1, arg2] | 1301 wrapBindN (fn [arg1, arg2] => f (arg1, arg2) |
1302 | _ => raise Fail "Sqlcache: cacheTree (b)") [arg1, arg2] | |
1281 fun wrapN f es = wrapBindN f (map (fn e => ((env, e), Unknowns 0)) es) | 1303 fun wrapN f es = wrapBindN f (map (fn e => ((env, e), Unknowns 0)) es) |
1282 fun wrap1 f e = wrapBind1 f ((env, e), Unknowns 0) | 1304 fun wrap1 f e = wrapBind1 f ((env, e), Unknowns 0) |
1283 fun wrap2 f (e1, e2) = wrapBind2 f (((env, e1), Unknowns 0), ((env, e2), Unknowns 0)) | 1305 fun wrap2 f (e1, e2) = wrapBind2 f (((env, e1), Unknowns 0), ((env, e2), Unknowns 0)) |
1284 in | 1306 in |
1285 case exp' of | 1307 case exp' of |
1304 | ECase (e, cases, {disc, result}) => | 1326 | ECase (e, cases, {disc, result}) => |
1305 wrapBindN (fn (e::es) => | 1327 wrapBindN (fn (e::es) => |
1306 ECase (e, | 1328 ECase (e, |
1307 (ListPair.map (fn (e, (p, _)) => (p, e)) (es, cases)), | 1329 (ListPair.map (fn (e, (p, _)) => (p, e)) (es, cases)), |
1308 {disc = disc, result = result}) | 1330 {disc = disc, result = result}) |
1309 | _ => raise Match) | 1331 | _ => raise Fail "Sqlcache: cacheTree (c)") |
1310 (((env, e), Unknowns 0) | 1332 (((env, e), Unknowns 0) |
1311 :: map (fn (p, e) => | 1333 :: map (fn (p, e) => |
1312 ((MonoEnv.patBinds env p, e), Unknowns (MonoEnv.patBindsN p))) | 1334 ((MonoEnv.patBinds env p, e), Unknowns (MonoEnv.patBindsN p))) |
1313 cases) | 1335 cases) |
1314 | EStrcat (e1, e2) => wrap2 EStrcat (e1, e2) | 1336 | EStrcat (e1, e2) => wrap2 EStrcat (e1, e2) |
1360 | SOME e => (ESome (stringTyp, | 1382 | SOME e => (ESome (stringTyp, |
1361 (case e of | 1383 (case e of |
1362 DmlRel n => ERel n | 1384 DmlRel n => ERel n |
1363 | Prim p => EPrim p | 1385 | Prim p => EPrim p |
1364 (* TODO: make new type containing only these two. *) | 1386 (* TODO: make new type containing only these two. *) |
1365 | _ => raise Match, | 1387 | _ => raise Fail "Sqlcache: optionAtomExpToExp", |
1366 loc)), | 1388 loc)), |
1367 loc) | 1389 loc) |
1368 | 1390 |
1369 fun eqsToInvalidation numArgs eqs = | 1391 fun eqsToInvalidation numArgs eqs = |
1370 List.tabulate (numArgs, (fn n => IM.find (eqs, n))) | 1392 List.tabulate (numArgs, (fn n => IM.find (eqs, n))) |
1407 SOME (map (fn i => (case IM.find (indexToInvalInfo, i) of | 1429 SOME (map (fn i => (case IM.find (indexToInvalInfo, i) of |
1408 SOME invalInfo => | 1430 SOME invalInfo => |
1409 (i, invalidations (invalInfo, dmlParsed)) | 1431 (i, invalidations (invalInfo, dmlParsed)) |
1410 (* TODO: fail more gracefully. *) | 1432 (* TODO: fail more gracefully. *) |
1411 (* This probably means invalidating everything.... *) | 1433 (* This probably means invalidating everything.... *) |
1412 | NONE => raise Match)) | 1434 | NONE => raise Fail "Sqlcache: addFlushing (a)")) |
1413 (SIMM.findList (tableToIndices, tableOfDml dmlParsed))) | 1435 (SIMM.findList (tableToIndices, tableOfDml dmlParsed))) |
1414 | NONE => NONE | 1436 | NONE => NONE |
1415 in | 1437 in |
1416 case inval of | 1438 case inval of |
1417 (* TODO: fail more gracefully. *) | 1439 (* TODO: fail more gracefully. *) |
1418 NONE => raise Match | 1440 NONE => raise Fail "Sqlcache: addFlushing (b)" |
1419 | SOME invs => sequence (flushes invs @ [dmlExp]) | 1441 | SOME invs => sequence (flushes invs @ [dmlExp]) |
1420 end | 1442 end |
1421 | e' => e' | 1443 | e' => e' |
1422 val file = fileMap doExp file | 1444 val file = fileMap doExp file |
1423 | 1445 |
1430 (***********) | 1452 (***********) |
1431 (* Locking *) | 1453 (* Locking *) |
1432 (***********) | 1454 (***********) |
1433 | 1455 |
1434 (* TODO: do this less evilly by not relying on specific FFI names, please? *) | 1456 (* TODO: do this less evilly by not relying on specific FFI names, please? *) |
1435 fun locksNeeded file = | 1457 fun locksNeeded (lockMap : {store : IIMM.multimap, flush : IIMM.multimap}) = |
1458 MonoUtil.Exp.fold | |
1459 {typ = #2, | |
1460 exp = fn (EFfiApp ("Sqlcache", x, _), state as {store, flush}) => | |
1461 (case Int.fromString (String.extract (x, 5, NONE)) of | |
1462 NONE => state | |
1463 | SOME index => | |
1464 if String.isPrefix "flush" x | |
1465 then {store = store, flush = IS.add (flush, index)} | |
1466 else if String.isPrefix "store" x | |
1467 then {store = IS.add (store, index), flush = flush} | |
1468 else state) | |
1469 | (ENamed n, {store, flush}) => | |
1470 {store = IS.union (store, IIMM.findSet (#store lockMap, n)), | |
1471 flush = IS.union (flush, IIMM.findSet (#flush lockMap, n))} | |
1472 | (_, state) => state} | |
1473 {store = IS.empty, flush = IS.empty} | |
1474 | |
1475 fun lockMapOfFile file = | |
1436 transitiveAnalysis | 1476 transitiveAnalysis |
1437 (fn ((_, name, _, e, _), state) => | 1477 (fn ((_, name, _, e, _), state) => |
1438 MonoUtil.Exp.fold | 1478 let |
1439 {typ = #2, | 1479 val locks = locksNeeded state e |
1440 exp = fn (EFfiApp ("Sqlcache", x, _), state as {store, flush}) => | 1480 in |
1441 (case Int.fromString (String.extract (x, 5, NONE)) of | 1481 {store = IIMM.insertSet (#store state, name, #store locks), |
1442 NONE => state | 1482 flush = IIMM.insertSet (#flush state, name, #flush locks)} |
1443 | SOME index => | 1483 end) |
1444 if String.isPrefix "flush" x | |
1445 then {store = store, flush = IIMM.insert (flush, name, index)} | |
1446 else if String.isPrefix "store" x | |
1447 then {store = IIMM.insert (store, name, index), flush = flush} | |
1448 else state) | |
1449 | (_, state) => state} | |
1450 state | |
1451 e) | |
1452 {store = IIMM.empty, flush = IIMM.empty} | 1484 {store = IIMM.empty, flush = IIMM.empty} |
1453 file | 1485 file |
1454 | 1486 |
1455 fun exports (decls, _) = | 1487 fun exports (decls, _) = |
1456 List.foldl (fn ((DExport (_, _, n, _, _, _), _), ns) => IS.add (ns, n) | 1488 List.foldl (fn ((DExport (_, _, n, _, _, _), _), ns) => IS.add (ns, n) |
1457 | ((DTask _, _), _) => raise Fail "Sqlcache doesn't yet support tasks." | |
1458 | (_, ns) => ns) | 1489 | (_, ns) => ns) |
1459 IS.empty | 1490 IS.empty |
1460 decls | 1491 decls |
1461 | 1492 |
1462 fun wrapLocks (locks, (exp', loc)) = | 1493 fun wrapLocks (locks, (exp', loc)) = |
1464 EAbs (s, t1, t2, exp) => (EAbs (s, t1, t2, wrapLocks (locks, exp)), loc) | 1495 EAbs (s, t1, t2, exp) => (EAbs (s, t1, t2, wrapLocks (locks, exp)), loc) |
1465 | _ => (List.foldr (fn (l, e') => sequence [lock l, e']) exp' locks, loc) | 1496 | _ => (List.foldr (fn (l, e') => sequence [lock l, e']) exp' locks, loc) |
1466 | 1497 |
1467 fun addLocking file = | 1498 fun addLocking file = |
1468 let | 1499 let |
1469 val {store, flush} = locksNeeded file | 1500 val lockMap = lockMapOfFile file |
1470 fun locks n = | 1501 fun lockList {store, flush} = |
1471 let | 1502 let |
1472 val wlocks = IIMM.findSet (flush, n) | 1503 val ls = map (fn i => (i, true)) (IS.listItems flush) |
1473 val rlocks = IIMM.findSet (store, n) | 1504 @ map (fn i => (i, false)) (IS.listItems (IS.difference (store, flush))) |
1474 val ls = map (fn i => (i, true)) (IS.listItems wlocks) | |
1475 @ map (fn i => (i, false)) (IS.listItems (IS.difference (rlocks, wlocks))) | |
1476 in | 1505 in |
1477 ListMergeSort.sort (fn ((i, _), (j, _)) => i > j) ls | 1506 ListMergeSort.sort (fn ((i, _), (j, _)) => i > j) ls |
1478 end | 1507 end |
1508 fun locksOfName n = | |
1509 lockList {store = IIMM.findSet (#flush lockMap, n), | |
1510 flush =IIMM.findSet (#store lockMap, n)} | |
1511 val locksOfExp = lockList o locksNeeded lockMap | |
1479 val expts = exports file | 1512 val expts = exports file |
1480 fun doVal (v as (x, n, t, exp, s)) = | 1513 fun doVal (v as (x, n, t, exp, s)) = |
1481 if IS.member (expts, n) | 1514 if IS.member (expts, n) |
1482 then (x, n, t, wrapLocks ((locks n), exp), s) | 1515 then (x, n, t, wrapLocks ((locksOfName n), exp), s) |
1483 else v | 1516 else v |
1484 val doDecl = | 1517 val doDecl = |
1485 fn (DVal v, loc) => (DVal (doVal v), loc) | 1518 fn (DVal v, loc) => (DVal (doVal v), loc) |
1486 | (DValRec vs, loc) => (DValRec (map doVal vs), loc) | 1519 | (DValRec vs, loc) => (DValRec (map doVal vs), loc) |
1520 | (DTask (exp1, exp2), loc) => (DTask (exp1, wrapLocks (locksOfExp exp2, exp2)), loc) | |
1487 | decl => decl | 1521 | decl => decl |
1488 in | 1522 in |
1489 mapFst (map doDecl) file | 1523 mapFst (map doDecl) file |
1490 end | 1524 end |
1491 | 1525 |