110 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Factor
		
	
	
| USING: parser kernel math sequences namespaces assocs inspector
 | |
| words splitting math.parser arrays sequences.next mirrors
 | |
| shuffle ;
 | |
| IN: bitfields
 | |
| 
 | |
| ! Example:
 | |
| ! BITFIELD: blah short:16 char:8 nothing:5 ;
 | |
| ! defines <blah> blah-short blah-char blah-nothing.
 | |
| 
 | |
| ! An efficient bitfield has a sum of 29 bits or less
 | |
| ! so it can fit in a fixnum.
 | |
| ! No class is defined and there is no overflow checking.
 | |
| ! The first field is the most significant.
 | |
| 
 | |
| : >ranges ( slots/sizes -- slots/ranges )
 | |
|     ! range is { start length }
 | |
|     reverse 0 swap [
 | |
|         swap >r tuck >r [ + ] keep r> 2array r> swap
 | |
|     ] assoc-map nip reverse ;
 | |
| 
 | |
| SYMBOL: safe-bitfields? ! default f; set at parsetime
 | |
| 
 | |
| TUPLE: check< number bound ;
 | |
| M: check< summary drop "Number exceeds upper bound" ;
 | |
| 
 | |
| : check< ( num cmp -- num )
 | |
|     2dup < [ drop ] [ \ check< construct-boa throw ] if ;
 | |
| 
 | |
| : ?check ( length -- )
 | |
|     safe-bitfields? get [ 2^ , \ check< , ] [ drop ] if ;
 | |
| 
 | |
| : put-together ( lengths -- )
 | |
|     ! messy because of bounds checking
 | |
|     dup length 1- [ \ >r , ] times [ 0 swap ] % [
 | |
|         ?check [ \ bitor , , [ shift r> ] % ] when*
 | |
|     ] each-next \ bitor , ;
 | |
| 
 | |
| : padding-name? ( string -- ? )
 | |
|     [ "10" member? ] all? ;
 | |
| 
 | |
| : pad ( i name -- )
 | |
|     bin> , , \ -nrot , ;
 | |
| 
 | |
| : add-padding ( names -- ) 
 | |
|     <enum>
 | |
|     [ dup padding-name? [ pad ] [ 2drop ] if ] assoc-each ;
 | |
| 
 | |
| : [constructor] ( names lengths -- quot )
 | |
|     [ swap add-padding put-together ] [ ] make ;
 | |
| 
 | |
| : define-constructor ( classname slots -- )
 | |
|     [ keys ] keep values [constructor]
 | |
|     >r in get constructor-word dup save-location r>
 | |
|     define-compound ;
 | |
| 
 | |
| : range>accessor ( range -- quot )
 | |
|     [
 | |
|         dup first neg , \ shift ,
 | |
|         second 2^ 1- , \ bitand ,
 | |
|     ] [ ] make ;
 | |
| 
 | |
| : [accessors] ( lengths -- accessors )
 | |
|     [ range>accessor ] map ;
 | |
| 
 | |
| : clear-range ( range -- num )
 | |
|     first2 dupd + [ 2^ 1- ] 2apply bitnot bitor ;
 | |
| 
 | |
| : range>setter ( range -- quot )
 | |
|     [
 | |
|         \ >r , dup second ?check \ r> ,
 | |
|         dup clear-range ,
 | |
|         [ bitand >r ] %
 | |
|         first , [ shift r> bitor ] %
 | |
|     ] [ ] make ;
 | |
| 
 | |
| : [setters] ( lengths -- setters )
 | |
|     [ range>setter ] map ;
 | |
| 
 | |
| : parse-slots ( slotspecs -- slots )
 | |
|     [ ":" split1 string>number [ dup length ] unless* ] { } map>assoc ;
 | |
| 
 | |
| : define-slots ( prefix names quots -- )
 | |
|     >r [ "-" swap 3append create-in ] curry* map r>
 | |
|     [ define-compound ] 2each ;
 | |
| 
 | |
| : define-accessors ( classname slots -- )
 | |
|     dup values [accessors]
 | |
|     >r keys r> define-slots ;
 | |
| 
 | |
| : define-setters ( classname slots -- )
 | |
|     >r "with-" swap append r>
 | |
|     dup values [setters]
 | |
|     >r keys r> define-slots ;
 | |
| 
 | |
| : filter-pad ( slots -- slots )
 | |
|     [ drop padding-name? not ] assoc-subset ;
 | |
| 
 | |
| : define-bitfield ( classname slots -- ) 
 | |
|     [ define-constructor ] 2keep
 | |
|     >ranges filter-pad [ define-setters ] 2keep define-accessors ;
 | |
| 
 | |
| : parse-bitfield 
 | |
|     scan ";" parse-tokens parse-slots define-bitfield ;
 | |
| 
 | |
| : BITFIELD:
 | |
|     parse-bitfield ; parsing
 | |
| 
 | |
| : SAFE-BITFIELD:
 | |
|     [ safe-bitfields? on parse-bitfield ] with-scope ; parsing
 |