|
4513 | 4513 | [pb bvec b v] |
4514 | 4514 | (let [gmap (gensym "map__") |
4515 | 4515 | gmapseq (with-meta gmap {:tag 'clojure.lang.ISeq}) |
4516 | | - gignore (gensym "ignore__") |
| 4516 | + gtemp (gensym "temp__") |
4517 | 4517 | defaults (:or b) |
4518 | 4518 | defaults-as (:defaults b) |
4519 | 4519 | _ (when (and defaults-as (not defaults)) |
|
4523 | 4523 | select (:select b) |
4524 | 4524 | all (:all b) |
4525 | 4525 | excess (:excess b) |
| 4526 | + missing (:missing b) |
| 4527 | + gnotfound (when missing (gensym "notfound__")) |
| 4528 | + gnotfound? (when missing (gensym "notfound?__")) |
4526 | 4529 | xf (fn [mk] |
4527 | 4530 | (let [mkns (namespace mk) |
4528 | 4531 | mkn (name mk)] |
|
4546 | 4549 | (if (:as b) |
4547 | 4550 | (conj ret (:as b) gmap) |
4548 | 4551 | ret)))) |
4549 | | - bes (dissoc b :as :or :select :all :excess) |
| 4552 | + ret (if missing |
| 4553 | + (conj ret |
| 4554 | + missing nil |
| 4555 | + gnotfound (list 'new 'Object)) |
| 4556 | + ret) |
| 4557 | + bes (dissoc b :as :or :select :all :excess :missing) |
4550 | 4558 | localize (fn [bb] (if (instance? clojure.lang.Named bb) |
4551 | 4559 | (with-meta (symbol nil (name bb)) (meta bb)) bb)) |
4552 | 4560 | push1 (fn [ret bb bk req?] |
|
4562 | 4570 | (throw (new Exception |
4563 | 4571 | (str "Can't supply default value for required key: " bk))) |
4564 | 4572 | (list `get gmap bk (if local-default? (gdefaults local) (gdefaults bk))))) |
4565 | | - (list getter gmap bk))] |
| 4573 | + (if req? |
| 4574 | + (if missing |
| 4575 | + (list `get gmap bk gnotfound) |
| 4576 | + (list `req! gmap bk)) |
| 4577 | + (list `get gmap bk)))] |
4566 | 4578 | (if (ident? bb) |
4567 | | - (-> ret (conj local bv)) |
| 4579 | + (if (and req? missing) |
| 4580 | + (conj ret |
| 4581 | + gtemp bv |
| 4582 | + gnotfound? `(identical? ~gtemp ~gnotfound) |
| 4583 | + missing `(if ~gnotfound? (assoc ~missing ~bk nil) ~missing) |
| 4584 | + local `(when-not ~gnotfound? ~gtemp)) |
| 4585 | + (-> ret (conj local bv))) |
4568 | 4586 | (pb ret bb bv)))) |
4569 | 4587 | retsel |
4570 | | - (loop [ret ret, sel #{}, bes bes, b->k {}, subs nil, suba nil, subd nil] |
| 4588 | + (loop [ret ret, sel #{}, bes bes, b->k {}, subs nil, suba nil, subexcess nil, submissing nil] |
4571 | 4589 | (if (seq bes) |
4572 | 4590 | (let [be (first bes), bb (key be), bk (val be)] |
4573 | 4591 | (if (keyword? bb) |
|
4590 | 4608 | "' - binding symbols can only appear before '&', use keys after")))) |
4591 | 4609 | bk (if preamp? (tr bb) bb)] |
4592 | 4610 | (recur (if (or preamp? req?) |
4593 | | - (push1 ret (if preamp? bb gignore) bk req?) |
| 4611 | + (push1 ret (if preamp? bb gtemp) bk req?) |
4594 | 4612 | ret) |
4595 | 4613 | (conj sel bk) |
4596 | 4614 | (next bbs) preamp? |
4597 | 4615 | (if preamp? (assoc b->k (localize bb) bk) b->k))))) |
4598 | 4616 | {:ret ret, :sel sel, :b->k b->k}))] |
4599 | | - (recur (:ret retsel) (:sel retsel) (next bes) (:b->k retsel) subs suba subd)) |
| 4617 | + (recur (:ret retsel) (:sel retsel) (next bes) (:b->k retsel) subs suba subexcess submissing)) |
4600 | 4618 | (let [subsel? (and select (map? bb)) |
4601 | 4619 | bb (if (or (not subsel?) (:select bb)) |
4602 | 4620 | bb |
|
4613 | 4631 | bb (if (or (not subexcess?) (:excess bb)) |
4614 | 4632 | bb |
4615 | 4633 | (assoc bb :excess (gensym "excess__"))) |
4616 | | - subd (if subexcess? (assoc subd bk (:excess bb)) subd) |
| 4634 | + subexcess (if subexcess? (assoc subexcess bk (:excess bb)) subexcess) |
| 4635 | + |
| 4636 | + submissing? (and missing (map? bb)) |
| 4637 | + bb (if (or (not submissing?) (:missing bb)) |
| 4638 | + bb |
| 4639 | + (assoc bb :missing (gensym "missing__"))) |
| 4640 | + submissing (if submissing? (assoc submissing bk (:missing bb)) submissing) |
4617 | 4641 |
|
4618 | 4642 | b->k (if (symbol? bb) (assoc b->k bb bk) b->k)] |
4619 | | - (recur (push1 ret bb bk false) (conj sel bk) (next bes) b->k subs suba subd)))) |
4620 | | - {:ret ret, :sel sel, :b->k b->k :subs subs :suba suba :subd subd})) |
| 4643 | + (recur (push1 ret bb bk false) (conj sel bk) (next bes) b->k subs suba subexcess submissing)))) |
| 4644 | + {:ret ret, :sel sel, :b->k b->k :subs subs :suba suba :subexcess subexcess :submissing submissing})) |
4621 | 4645 | ret (:ret retsel), sel (:sel retsel), b->k (:b->k retsel) |
4622 | 4646 | new-or-code (and defaults (or defaults-as select all)) |
4623 | 4647 | bk #(if (symbol? %) |
|
4641 | 4665 | ret) |
4642 | 4666 |
|
4643 | 4667 | ret (if excess |
4644 | | - (conj ret excess `(merge (not-empty (apply dissoc ~gmap ~sel)) (some-vals ~(:subd retsel)))) |
| 4668 | + (conj ret excess `(merge (not-empty (apply dissoc ~gmap ~sel)) (some-vals ~(:subexcess retsel)))) |
4645 | 4669 | ret) |
4646 | 4670 |
|
| 4671 | + ret (if missing |
| 4672 | + (conj ret missing `(merge ~missing (some-vals ~(:submissing retsel)))) |
| 4673 | + ret) |
| 4674 | + |
4647 | 4675 | ret (if defaults-as (conj ret defaults-as dm) ret)] |
4648 | 4676 | ret)) |
4649 | 4677 |
|
|
0 commit comments