Merge branch 'emacs' of http://git.hacks-galore.org/jao/factor
[factor/jcg.git] / unmaintained / bitfields / bitfields.factor
blob90e588be48661f39a37cffc574fd8f9a80fee422
1 USING: parser lexer kernel math sequences namespaces make assocs
2 summary words splitting math.parser arrays sequences.next
3 mirrors generalizations compiler.units ;
4 IN: bitfields
6 ! Example:
7 ! BITFIELD: blah short:16 char:8 nothing:5 ;
8 ! defines <blah> blah-short blah-char blah-nothing.
10 ! An efficient bitfield has a sum of 29 bits or less
11 ! so it can fit in a fixnum.
12 ! No class is defined and there is no overflow checking.
13 ! The first field is the most significant.
15 : >ranges ( slots/sizes -- slots/ranges )
16     ! range is { start length }
17     reverse 0 swap [
18         swap >r tuck >r [ + ] keep r> 2array r> swap
19     ] assoc-map nip reverse ;
21 SYMBOL: safe-bitfields? ! default f; set at parsetime
23 TUPLE: check< number bound ;
24 M: check< summary drop "Number exceeds upper bound" ;
26 : check< ( num cmp -- num )
27     2dup < [ drop ] [ \ check< boa throw ] if ;
29 : ?check ( length -- )
30     safe-bitfields? get [ 2^ , \ check< , ] [ drop ] if ;
32 : put-together ( lengths -- )
33     ! messy because of bounds checking
34     dup length 1- [ \ >r , ] times [ 0 swap ] % [
35         ?check [ \ bitor , , [ shift r> ] % ] when*
36     ] each-next \ bitor , ;
38 : padding-name? ( string -- ? )
39     [ "10" member? ] all? ;
41 : pad ( i name -- )
42     bin> , , \ -nrot , ;
44 : add-padding ( names -- ) 
45     <enum>
46     [ dup padding-name? [ pad ] [ 2drop ] if ] assoc-each ;
48 : [constructor] ( names lengths -- quot )
49     [ swap add-padding put-together ] [ ] make ;
51 : define-constructor ( classname slots -- )
52     [ keys ] keep values [constructor]
53     >r in get constructor-word dup save-location r>
54     define ;
56 : range>accessor ( range -- quot )
57     [
58         dup first neg , \ shift ,
59         second 2^ 1- , \ bitand ,
60     ] [ ] make ;
62 : [accessors] ( lengths -- accessors )
63     [ range>accessor ] map ;
65 : clear-range ( range -- num )
66     first2 dupd + [ 2^ 1- ] bi@ bitnot bitor ;
68 : range>setter ( range -- quot )
69     [
70         \ >r , dup second ?check \ r> ,
71         dup clear-range ,
72         [ bitand >r ] %
73         first , [ shift r> bitor ] %
74     ] [ ] make ;
76 : [setters] ( lengths -- setters )
77     [ range>setter ] map ;
79 : parse-slots ( slotspecs -- slots )
80     [ ":" split1 string>number [ dup length ] unless* ] { } map>assoc ;
82 : define-slots ( prefix names quots -- )
83     >r [ "-" glue create-in ] with map r>
84     [ define ] 2each ;
86 : define-accessors ( classname slots -- )
87     dup values [accessors]
88     >r keys r> define-slots ;
90 : define-setters ( classname slots -- )
91     >r "with-" prepend r>
92     dup values [setters]
93     >r keys r> define-slots ;
95 : filter-pad ( slots -- slots )
96     [ drop padding-name? not ] assoc-filter ;
98 : define-bitfield ( classname slots -- ) 
99     [
100         [ define-constructor ] 2keep
101         >ranges filter-pad [ define-setters ] 2keep define-accessors
102     ] with-compilation-unit ;
104 : parse-bitfield ( -- )
105     scan ";" parse-tokens parse-slots define-bitfield ;
107 : BITFIELD:
108     parse-bitfield ; parsing
110 : SAFE-BITFIELD:
111     [ safe-bitfields? on parse-bitfield ] with-scope ; parsing