120 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Factor
		
	
	
| ! Copyright (C) 2008, 2009 Slava Pestov.
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| USING: accessors arrays assocs classes.algebra combinators
 | |
| combinators.short-circuit compiler.tree compiler.tree.builder
 | |
| compiler.tree.normalization compiler.tree.propagation.info
 | |
| compiler.tree.propagation.nodes compiler.tree.recursive generic
 | |
| generic.math generic.single generic.standard kernel locals math
 | |
| math.partial-dispatch namespaces quotations sequences words ;
 | |
| IN: compiler.tree.propagation.inlining
 | |
| 
 | |
| : splicing-call ( #call word -- nodes )
 | |
|     [ [ in-d>> ] [ out-d>> ] bi ] dip <#call> 1array ;
 | |
| 
 | |
| : open-code-#call ( #call word/quot -- nodes/f )
 | |
|     [ [ in-d>> ] [ out-d>> ] bi ] dip build-sub-tree ;
 | |
| 
 | |
| : splicing-body ( #call quot/word -- nodes/f )
 | |
|     open-code-#call dup [ analyze-recursive normalize ] when ;
 | |
| 
 | |
| ! Dispatch elimination
 | |
| : undo-inlining ( #call -- ? )
 | |
|     f >>method f >>body f >>class drop f ;
 | |
| 
 | |
| : propagate-body ( #call -- ? )
 | |
|     body>> (propagate) t ;
 | |
| 
 | |
| GENERIC: splicing-nodes ( #call word/quot -- nodes/f )
 | |
| 
 | |
| M: word splicing-nodes splicing-call ;
 | |
| 
 | |
| M: callable splicing-nodes splicing-body ;
 | |
| 
 | |
| : eliminate-dispatch ( #call class/f word/quot/f -- ? )
 | |
|     dup [
 | |
|         [ >>class ] dip
 | |
|         over method>> over = [ drop propagate-body ] [
 | |
|             2dup splicing-nodes dup [
 | |
|                 [ >>method ] [ >>body ] bi* propagate-body
 | |
|             ] [ 2drop undo-inlining ] if
 | |
|         ] if
 | |
|     ] [ 2drop undo-inlining ] if ;
 | |
| 
 | |
| : inlining-standard-method ( #call word -- class/f method/f )
 | |
|     dup "methods" word-prop assoc-empty? [ 2drop f f ] [
 | |
|         2dup [ in-d>> length ] [ dispatch# ] bi* <= [ 2drop f f ] [
 | |
|             [ in-d>> <reversed> ] [ [ dispatch# ] keep ] bi*
 | |
|             [ swap nth value-info class>> dup ] dip
 | |
|             method-for-class
 | |
|         ] if
 | |
|     ] if ;
 | |
| 
 | |
| : inline-standard-method ( #call word -- ? )
 | |
|     dupd inlining-standard-method eliminate-dispatch ;
 | |
| 
 | |
| : normalize-math-class ( class -- class' )
 | |
|     {
 | |
|         null
 | |
|         fixnum bignum integer
 | |
|         ratio rational
 | |
|         float real
 | |
|         complex number
 | |
|         object
 | |
|     } [ class<= ] with find nip ;
 | |
| 
 | |
| : inlining-math-method ( #call word -- class/f quot/f )
 | |
|     swap in-d>>
 | |
|     first2 [ value-info class>> normalize-math-class ] bi@
 | |
|     3dup math-both-known?
 | |
|     [ math-method* ] [ 3drop f ] if
 | |
|     number swap ;
 | |
| 
 | |
| : inline-math-method ( #call word -- ? )
 | |
|     dupd inlining-math-method eliminate-dispatch ;
 | |
| 
 | |
| ! Method body inlining
 | |
| SYMBOL: history
 | |
| 
 | |
| : already-inlined? ( obj -- ? ) history get member-eq? ;
 | |
| 
 | |
| : add-to-history ( obj -- ) history [ swap suffix ] change ;
 | |
| 
 | |
| :: inline-word ( #call word -- ? )
 | |
|     word already-inlined? [ f ] [
 | |
|         #call word splicing-body [
 | |
|             word add-to-history
 | |
|             #call body<<
 | |
|             #call propagate-body
 | |
|         ] [ f ] if*
 | |
|     ] if ;
 | |
| 
 | |
| : always-inline-word? ( word -- ? )
 | |
|     { curry compose } member-eq? ;
 | |
| 
 | |
| : never-inline-word? ( word -- ? )
 | |
|     { [ deferred? ] [ "default" word-prop ] [ \ call eq? ] } 1|| ;
 | |
| 
 | |
| : custom-inlining? ( word -- quot/f )
 | |
|     "custom-inlining" word-prop ;
 | |
| 
 | |
| : inline-custom ( #call word -- ? )
 | |
|     [ dup ] [ custom-inlining? ] bi*
 | |
|     call( #call -- word/quot/f )
 | |
|     object swap eliminate-dispatch ;
 | |
| 
 | |
| : (do-inlining) ( #call word -- ? )
 | |
|     {
 | |
|         { [ dup never-inline-word? ] [ 2drop f ] }
 | |
|         { [ dup always-inline-word? ] [ inline-word ] }
 | |
|         { [ dup standard-generic? ] [ inline-standard-method ] }
 | |
|         { [ dup math-generic? ] [ inline-math-method ] }
 | |
|         { [ dup inline? ] [ inline-word ] }
 | |
|         [ 2drop f ]
 | |
|     } cond ;
 | |
| 
 | |
| : do-inlining ( #call word -- ? )
 | |
|     [
 | |
|         dup custom-inlining? [ 2dup inline-custom ] [ f ] if
 | |
|         [ 2drop t ] [ (do-inlining) ] if
 | |
|     ] with-scope ;
 |