| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  | ! Copyright (C) 2004, 2008 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: arrays generic assocs hashtables inference kernel | 
					
						
							|  |  |  | math namespaces sequences words parser math.intervals | 
					
						
							| 
									
										
										
										
											2008-03-24 20:52:21 -04:00
										 |  |  | effects classes classes.algebra inference.dataflow | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  | inference.backend combinators accessors ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: inference.class | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Class inference | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! A constraint is a statement about a value. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! We need a notion of equality which doesn't recurse so cannot | 
					
						
							|  |  |  | ! infinite loop on circular data | 
					
						
							|  |  |  | GENERIC: eql? ( obj1 obj2 -- ? )
 | 
					
						
							|  |  |  | M: object eql? eq? ;
 | 
					
						
							|  |  |  | M: number eql? number= ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Maps constraints to constraints | 
					
						
							|  |  |  | SYMBOL: constraints | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: literal-constraint literal value ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | C: <literal-constraint> literal-constraint | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: literal-constraint equal? | 
					
						
							|  |  |  |     over literal-constraint? [ | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         [ [ literal>> ] bi@ eql? ] | 
					
						
							|  |  |  |         [ [ value>>   ] bi@ =    ] | 
					
						
							|  |  |  |         2bi and
 | 
					
						
							|  |  |  |     ] [ 2drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | TUPLE: class-constraint class value ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | C: <class-constraint> class-constraint | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: interval-constraint interval value ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | C: <interval-constraint> interval-constraint | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: apply-constraint ( constraint -- )
 | 
					
						
							|  |  |  | GENERIC: constraint-satisfied? ( constraint -- ? )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-08 16:32:55 -04:00
										 |  |  | : `input ( n -- value ) node get in-d>> nth ;
 | 
					
						
							|  |  |  | : `output ( n -- value ) node get out-d>> nth ;
 | 
					
						
							|  |  |  | : class, ( class value -- ) <class-constraint> , ;
 | 
					
						
							|  |  |  | : literal, ( literal value -- ) <literal-constraint> , ;
 | 
					
						
							|  |  |  | : interval, ( interval value -- ) <interval-constraint> , ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: f apply-constraint drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : make-constraints ( node quot -- constraint )
 | 
					
						
							|  |  |  |     [ swap node set call ] { } make ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : set-constraints ( node quot -- )
 | 
					
						
							|  |  |  |     make-constraints | 
					
						
							|  |  |  |     unclip [ 2array ] reduce
 | 
					
						
							|  |  |  |     apply-constraint ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : assume ( constraint -- )
 | 
					
						
							|  |  |  |     constraints get at [ apply-constraint ] when* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Variables used by the class inferencer | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Current value --> literal mapping | 
					
						
							|  |  |  | SYMBOL: value-literals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Current value --> interval mapping | 
					
						
							|  |  |  | SYMBOL: value-intervals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Current value --> class mapping | 
					
						
							|  |  |  | SYMBOL: value-classes | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  | : value-interval* ( value -- interval/f )
 | 
					
						
							|  |  |  |     value-intervals get at ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | : set-value-interval* ( interval value -- )
 | 
					
						
							|  |  |  |     value-intervals get set-at ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  | : intersect-value-interval ( interval value -- )
 | 
					
						
							|  |  |  |     [ value-interval* interval-intersect ] keep
 | 
					
						
							|  |  |  |     set-value-interval* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | M: interval-constraint apply-constraint | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ interval>> ] [ value>> ] bi intersect-value-interval ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : set-class-interval ( class value -- )
 | 
					
						
							| 
									
										
										
										
											2008-03-24 20:52:21 -04:00
										 |  |  |     over class? [ | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         >r "interval" word-prop r> over
 | 
					
						
							|  |  |  |         [ set-value-interval* ] [ 2drop ] if
 | 
					
						
							| 
									
										
										
										
											2008-03-24 20:52:21 -04:00
										 |  |  |     ] [ 2drop ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  | : value-class* ( value -- class )
 | 
					
						
							|  |  |  |     value-classes get at object or ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | : set-value-class* ( class value -- )
 | 
					
						
							|  |  |  |     over [ | 
					
						
							|  |  |  |         dup value-intervals get at [ | 
					
						
							|  |  |  |             2dup set-class-interval | 
					
						
							|  |  |  |         ] unless
 | 
					
						
							|  |  |  |         2dup <class-constraint> assume | 
					
						
							|  |  |  |     ] when
 | 
					
						
							|  |  |  |     value-classes get set-at ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  | : intersect-value-class ( class value -- )
 | 
					
						
							|  |  |  |     [ value-class* class-and ] keep set-value-class* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | M: class-constraint apply-constraint | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ class>> ] [ value>> ] bi intersect-value-class ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : literal-interval ( value -- interval/f )
 | 
					
						
							|  |  |  |     dup real? [ [a,a] ] [ drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : set-value-literal* ( literal value -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |         [ >r class r> set-value-class* ] | 
					
						
							|  |  |  |         [ >r literal-interval r> set-value-interval* ] | 
					
						
							|  |  |  |         [ <literal-constraint> assume ] | 
					
						
							|  |  |  |         [ value-literals get set-at ] | 
					
						
							|  |  |  |     } 2cleave ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: literal-constraint apply-constraint | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ literal>> ] [ value>> ] bi set-value-literal* ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! For conditionals, an assoc of child node # --> constraint | 
					
						
							|  |  |  | GENERIC: child-constraints ( node -- seq )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: infer-classes-before ( node -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: infer-classes-around ( node -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: node infer-classes-before drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: node child-constraints | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     children>> length
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     dup zero? [ drop f ] [ f <repetition> ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : value-literal* ( value -- obj ? )
 | 
					
						
							|  |  |  |     value-literals get at* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: literal-constraint constraint-satisfied? | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     dup value>> value-literal* | 
					
						
							|  |  |  |     [ swap literal>> eql? ] [ 2drop f ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: class-constraint constraint-satisfied? | 
					
						
							| 
									
										
										
										
											2008-05-02 03:51:38 -04:00
										 |  |  |     [ value>> value-class* ] [ class>> ] bi class<= ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: pair apply-constraint | 
					
						
							|  |  |  |     first2 2dup constraints get set-at
 | 
					
						
							|  |  |  |     constraint-satisfied? [ apply-constraint ] [ drop ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: pair constraint-satisfied? | 
					
						
							|  |  |  |     first constraint-satisfied? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-22 23:41:48 -04:00
										 |  |  | : valid-keys ( seq assoc -- newassoc )
 | 
					
						
							|  |  |  |     extract-keys [ nip ] assoc-filter f assoc-like ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : annotate-node ( node -- )
 | 
					
						
							|  |  |  |     #! Annotate the node with the currently-inferred set of | 
					
						
							|  |  |  |     #! value classes. | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     dup node-values { | 
					
						
							| 
									
										
										
										
											2008-05-22 23:41:48 -04:00
										 |  |  |         [ value-intervals get valid-keys >>intervals ] | 
					
						
							|  |  |  |         [ value-classes   get valid-keys >>classes   ] | 
					
						
							|  |  |  |         [ value-literals  get valid-keys >>literals  ] | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         [ 2drop ] | 
					
						
							|  |  |  |     } cleave ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : intersect-classes ( classes values -- )
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  |     [ intersect-value-class ] 2each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : intersect-intervals ( intervals values -- )
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  |     [ intersect-value-interval ] 2each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : predicate-constraints ( class #call -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-04-02 22:27:49 -04:00
										 |  |  |         ! If word outputs true, input is an instance of class | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             0 `input class, | 
					
						
							|  |  |  |             \ f class-not 0 `output class, | 
					
						
							|  |  |  |         ] set-constraints | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         ! If word outputs false, input is not an instance of class | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             class-not 0 `input class, | 
					
						
							|  |  |  |             \ f 0 `output class, | 
					
						
							|  |  |  |         ] set-constraints | 
					
						
							|  |  |  |     ] 2bi ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : compute-constraints ( #call -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     dup param>> "constraints" word-prop [ | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         call
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         dup param>> "predicating" word-prop dup
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         [ swap predicate-constraints ] [ 2drop ] if
 | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compute-output-classes ( node word -- classes intervals )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     dup param>> "output-classes" word-prop | 
					
						
							| 
									
										
										
										
											2008-02-11 15:51:20 -05:00
										 |  |  |     dup [ call ] [ 2drop f f ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : output-classes ( node -- classes intervals )
 | 
					
						
							| 
									
										
										
										
											2008-02-11 15:51:20 -05:00
										 |  |  |     dup compute-output-classes >r | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ ] [ param>> "default-output-classes" word-prop ] ?if
 | 
					
						
							| 
									
										
										
										
											2008-02-11 15:51:20 -05:00
										 |  |  |     r> ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #call infer-classes-before | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ compute-constraints ] keep
 | 
					
						
							|  |  |  |     [ output-classes ] [ out-d>> ] bi
 | 
					
						
							|  |  |  |     tuck [ intersect-classes ] [ intersect-intervals ] 2bi* ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #push infer-classes-before | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     out-d>> [ [ value-literal ] keep set-value-literal* ] each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #if child-constraints | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-04-02 22:27:49 -04:00
										 |  |  |         \ f class-not 0 `input class, | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         f 0 `input literal, | 
					
						
							|  |  |  |     ] make-constraints ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #dispatch child-constraints | 
					
						
							|  |  |  |     dup [ | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         children>> length [ 0 `input literal, ] each
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     ] make-constraints ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #declare infer-classes-before | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ param>> ] [ in-d>> ] bi
 | 
					
						
							| 
									
										
										
										
											2008-02-10 21:32:48 -05:00
										 |  |  |     [ intersect-value-class ] 2each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | DEFER: (infer-classes) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : infer-children ( node -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ children>> ] [ child-constraints ] bi [ | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         [ | 
					
						
							|  |  |  |             value-classes [ clone ] change
 | 
					
						
							|  |  |  |             value-literals [ clone ] change
 | 
					
						
							|  |  |  |             value-intervals [ clone ] change
 | 
					
						
							|  |  |  |             constraints [ clone ] change
 | 
					
						
							|  |  |  |             apply-constraint | 
					
						
							|  |  |  |             (infer-classes) | 
					
						
							|  |  |  |         ] with-scope
 | 
					
						
							|  |  |  |     ] 2each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : pad-all ( seqs elt -- seq )
 | 
					
						
							|  |  |  |     >r dup [ length ] map supremum r> [ pad-left ] 2curry map ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (merge-classes) ( nodes -- seq )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     dup length 1 = [ | 
					
						
							|  |  |  |         first node-input-classes | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         [ node-input-classes ] map null pad-all flip
 | 
					
						
							|  |  |  |         [ null [ class-or ] reduce ] map
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : set-classes ( seq node -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     out-d>> [ set-value-class* ] 2reverse-each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : merge-classes ( nodes node -- )
 | 
					
						
							|  |  |  |     >r (merge-classes) r> set-classes ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : set-intervals ( seq node -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     out-d>> [ set-value-interval* ] 2reverse-each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : merge-intervals ( nodes node -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-17 13:54:47 -04:00
										 |  |  |     >r | 
					
						
							|  |  |  |     [ node-input-intervals ] map f pad-all flip
 | 
					
						
							|  |  |  |     [ dup first [ interval-union ] reduce ] map
 | 
					
						
							|  |  |  |     r> set-intervals ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : annotate-merge ( nodes #merge/#entry -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-03 05:58:37 -04:00
										 |  |  |     [ merge-classes ] [ merge-intervals ] 2bi ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : merge-children ( node -- )
 | 
					
						
							|  |  |  |     dup node-successor dup #merge? [ | 
					
						
							|  |  |  |         swap active-children dup empty?
 | 
					
						
							|  |  |  |         [ 2drop ] [ swap annotate-merge ] if
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     ] [ 2drop ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : classes= ( inferred current -- ? )
 | 
					
						
							|  |  |  |     2dup min-length [ tail* ] curry bi@ sequence= ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: fixed-point? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: nested-labels | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : annotate-entry ( nodes #label -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     >r (merge-classes) r> node-child | 
					
						
							|  |  |  |     2dup node-output-classes classes= | 
					
						
							|  |  |  |     [ 2drop ] [ set-classes fixed-point? off ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : init-recursive-calls ( #label -- )
 | 
					
						
							|  |  |  |     #! We set recursive calls to output the empty type, then | 
					
						
							|  |  |  |     #! repeat inference until a fixed point is reached. | 
					
						
							|  |  |  |     #! Hopefully, our type functions are monotonic so this | 
					
						
							|  |  |  |     #! will always converge. | 
					
						
							|  |  |  |     returns>> [ dup in-d>> [ null ] { } map>assoc >>classes drop ] each ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #label infer-classes-before ( #label -- )
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ init-recursive-calls ] | 
					
						
							|  |  |  |     [ [ 1array ] keep annotate-entry ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : infer-label-loop ( #label -- )
 | 
					
						
							|  |  |  |     fixed-point? on
 | 
					
						
							|  |  |  |     dup node-child (infer-classes) | 
					
						
							|  |  |  |     dup [ calls>> ] [ suffix ] [ annotate-entry ] tri
 | 
					
						
							|  |  |  |     fixed-point? get [ drop ] [ infer-label-loop ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #label infer-classes-around ( #label -- )
 | 
					
						
							|  |  |  |     #! Now merge the types at every recursion point with the | 
					
						
							|  |  |  |     #! entry types. | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             [ nested-labels get push ] | 
					
						
							|  |  |  |             [ annotate-node ] | 
					
						
							|  |  |  |             [ infer-classes-before ] | 
					
						
							|  |  |  |             [ infer-label-loop ] | 
					
						
							|  |  |  |             [ drop nested-labels get pop* ] | 
					
						
							|  |  |  |         } cleave
 | 
					
						
							|  |  |  |     ] with-scope ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : find-label ( param -- #label )
 | 
					
						
							|  |  |  |     param>> nested-labels get [ param>> eq? ] with find nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #call-label infer-classes-before ( #call-label -- )
 | 
					
						
							|  |  |  |     [ find-label returns>> (merge-classes) ] [ out-d>> ] bi
 | 
					
						
							|  |  |  |     [ set-value-class* ] 2each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #return infer-classes-around | 
					
						
							|  |  |  |     nested-labels get length 0 > [ | 
					
						
							|  |  |  |         dup param>> nested-labels get peek param>> eq? [ | 
					
						
							|  |  |  |             [ ] [ node-input-classes ] [ in-d>> [ value-class* ] map ] tri
 | 
					
						
							| 
									
										
										
										
											2008-04-19 21:39:58 -04:00
										 |  |  |             classes= not [ | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |                 fixed-point? off
 | 
					
						
							| 
									
										
										
										
											2008-05-22 23:41:48 -04:00
										 |  |  |                 [ in-d>> value-classes get valid-keys ] keep
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |                 set-node-classes | 
					
						
							| 
									
										
										
										
											2008-04-19 21:39:58 -04:00
										 |  |  |             ] [ drop ] if
 | 
					
						
							| 
									
										
										
										
											2008-04-19 22:43:45 -04:00
										 |  |  |         ] [ call-next-method ] if
 | 
					
						
							|  |  |  |     ] [ call-next-method ] if ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: object infer-classes-around | 
					
						
							| 
									
										
										
										
											2008-04-03 05:58:37 -04:00
										 |  |  |     { | 
					
						
							|  |  |  |         [ infer-classes-before ] | 
					
						
							|  |  |  |         [ annotate-node ] | 
					
						
							|  |  |  |         [ infer-children ] | 
					
						
							|  |  |  |         [ merge-children ] | 
					
						
							|  |  |  |     } cleave ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (infer-classes) ( node -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-04-03 05:58:37 -04:00
										 |  |  |         [ infer-classes-around ] | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         [ node-successor ] bi
 | 
					
						
							|  |  |  |         (infer-classes) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     ] when* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : infer-classes-with ( node classes literals intervals -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  |         V{ } clone nested-labels set
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |         H{ } assoc-like value-intervals set
 | 
					
						
							|  |  |  |         H{ } assoc-like value-literals set
 | 
					
						
							|  |  |  |         H{ } assoc-like value-classes set
 | 
					
						
							|  |  |  |         H{ } clone constraints set
 | 
					
						
							|  |  |  |         (infer-classes) | 
					
						
							|  |  |  |     ] with-scope ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-19 03:11:55 -04:00
										 |  |  | : infer-classes ( node -- node )
 | 
					
						
							|  |  |  |     dup f f f infer-classes-with ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : infer-classes/node ( node existing -- )
 | 
					
						
							|  |  |  |     #! Infer classes, using the existing node's class info as a | 
					
						
							|  |  |  |     #! starting point. | 
					
						
							| 
									
										
										
										
											2008-04-19 21:39:58 -04:00
										 |  |  |     [ classes>> ] [ literals>> ] [ intervals>> ] tri
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     infer-classes-with ;
 |