factor/extra/mongodb/tuple/persistent/persistent.factor

116 lines
3.4 KiB
Factor

USING: accessors assocs bson.constants combinators.short-circuit
constructors continuations fry kernel mirrors mongodb.tuple.collection
mongodb.tuple.state namespaces sequences words bson.writer combinators
hashtables linked-assocs ;
IN: mongodb.tuple.persistent
SYMBOLS: object-map ;
GENERIC: tuple>assoc ( tuple -- assoc )
GENERIC: tuple>selector ( tuple -- selector )
DEFER: assoc>tuple
<PRIVATE
: mdbinfo>tuple-class ( tuple-info -- class )
[ first ] keep second lookup ; inline
: tuple-instance ( tuple-info -- instance )
mdbinfo>tuple-class new ; inline
: prepare-assoc>tuple ( assoc -- tuple keylist mirror assoc )
[ tuple-info tuple-instance dup
<mirror> [ keys ] keep ] keep swap ; inline
: make-tuple ( assoc -- tuple )
prepare-assoc>tuple
'[ dup _ at assoc>tuple swap _ set-at ] each
[ mark-persistent ] keep ; inline recursive
: at+ ( value key assoc -- value )
2dup key?
[ at nip ] [ [ dup ] 2dip set-at ] if ; inline
: data-tuple? ( tuple -- ? )
dup tuple?
[ assoc? not ] [ drop f ] if ; inline
: add-storable ( assoc ns -- )
[ H{ } clone ] dip object-map get at+
[ dup [ MDB_OID_FIELD ] dip at ] dip set-at ; inline
: write-field? ( tuple key value -- ? )
pick mdb-persistent? [
{ [ [ 2drop ] dip not ]
[ drop transient-slot? ] } 3|| not ] [ 3drop t ] if ; inline
TUPLE: cond-value value quot ;
CONSTRUCTOR: cond-value ( value quot -- cond-value ) ;
: write-mdb-persistent ( value quot: ( tuple -- assoc ) -- value' )
over [ (( tuple -- assoc )) call-effect ] dip
[ tuple-collection name>> ] keep
[ add-storable ] dip
[ tuple-collection name>> ] [ _id>> ] bi <objref> ; inline
: write-field ( value quot: ( tuple -- assoc ) -- value' )
<cond-value> {
{ [ dup value>> mdb-special-value? ] [ value>> ] }
{ [ dup value>> mdb-persistent? ]
[ [ value>> ] [ quot>> ] bi write-mdb-persistent ] }
{ [ dup value>> data-tuple? ]
[ [ value>> ] [ quot>> ] bi (( tuple -- assoc )) call-effect ] }
{ [ dup value>> [ hashtable? ] [ linked-assoc? ] bi or ]
[ [ value>> ] [ quot>> ] bi '[ _ write-field ] assoc-map ] }
[ value>> ]
} cond ; inline recursive
: write-tuple-fields ( mirror tuple assoc quot: ( tuple -- assoc ) -- )
swap ! m t q q a
'[ _ 2over write-field?
[ _ write-field swap _ set-at ]
[ 2drop ] if
] assoc-each ;
: prepare-assoc ( tuple -- assoc mirror tuple assoc )
H{ } clone swap [ <mirror> ] keep pick ; inline
: ensure-mdb-info ( tuple -- tuple )
dup _id>> [ <objid> >>_id ] unless
[ mark-persistent ] keep ; inline
: with-object-map ( quot: ( -- ) -- store-assoc )
[ H{ } clone dup object-map ] dip with-variable ; inline
: (tuple>assoc) ( tuple -- assoc )
[ prepare-assoc [ tuple>assoc ] write-tuple-fields ] keep
over set-tuple-info ; inline
PRIVATE>
GENERIC: tuple>storable ( tuple -- storable )
M: mdb-persistent tuple>storable ( mdb-persistent -- object-map )
'[ _ [ tuple>assoc ] write-mdb-persistent drop ] with-object-map ; inline
M: mdb-persistent tuple>assoc ( tuple -- assoc )
ensure-mdb-info (tuple>assoc) ;
M: tuple tuple>assoc ( tuple -- assoc )
(tuple>assoc) ;
M: tuple tuple>selector ( tuple -- assoc )
prepare-assoc [ tuple>selector ] write-tuple-fields ;
: assoc>tuple ( assoc -- tuple )
dup assoc?
[ [ dup tuple-info?
[ make-tuple ]
[ ] if ] [ drop ] recover
] [ ] if ; inline recursive