| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | ! Copyright (C) 2009 Slava Pestov. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: accessors arrays assocs combinators.short-circuit | 
					
						
							|  |  |  | continuations fry kernel namespaces quotations sequences sets | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  | generalizations slots locals.types generalizations splitting math | 
					
						
							|  |  |  | locals.rewrite.closures generic words smalltalk.ast | 
					
						
							|  |  |  | smalltalk.compiler.lexenv smalltalk.selectors | 
					
						
							|  |  |  | smalltalk.classes ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | IN: smalltalk.compiler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: return-continuation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: need-return-continuation? ( ast -- ? )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-return need-return-continuation? drop t ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  | M: ast-block need-return-continuation? body>> need-return-continuation? ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ast-message-send need-return-continuation? | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         [ receiver>> need-return-continuation? ] | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  |         [ arguments>> need-return-continuation? ] | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  |     } 1&& ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-assignment need-return-continuation? | 
					
						
							|  |  |  |     value>> need-return-continuation? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  | M: array need-return-continuation? [ need-return-continuation? ] any? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | M: object need-return-continuation? drop f ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: assigned-locals ( ast -- seq )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-return assigned-locals value>> assigned-locals ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-block assigned-locals | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  |     [ body>> assigned-locals ] [ arguments>> ] bi diff ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ast-message-send assigned-locals | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  |     [ arguments>> assigned-locals ] | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  |     [ receiver>> assigned-locals ] | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  |     bi append ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ast-assignment assigned-locals | 
					
						
							|  |  |  |     [ name>> dup ast-name? [ name>> 1array ] [ drop { } ] if ] | 
					
						
							|  |  |  |     [ value>> assigned-locals ] bi append ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  | M: array assigned-locals | 
					
						
							|  |  |  |     [ assigned-locals ] map concat ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | M: object assigned-locals drop f ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: compile-ast ( lexenv ast -- quot )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: object compile-ast nip 1quotation ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  | M: self compile-ast drop self>> 1quotation ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | ERROR: unbound-local name ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  | M: ast-name compile-ast name>> swap lookup-reader ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ast-message-send compile-ast | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  |     [ arguments>> [ compile-ast ] with map [ ] join ] | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  |     [ receiver>> compile-ast ] | 
					
						
							|  |  |  |     [ nip selector>> selector>generic ] | 
					
						
							|  |  |  |     2tri [ append ] dip suffix ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-return compile-ast | 
					
						
							|  |  |  |     value>> compile-ast | 
					
						
							|  |  |  |     [ return-continuation get continue-with ] append ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  | GENERIC: contains-blocks? ( obj -- ? )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-block contains-blocks? drop t ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: object contains-blocks? drop f ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: array contains-blocks? [ contains-blocks? ] any? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: array compile-ast | 
					
						
							|  |  |  |     dup contains-blocks? [ | 
					
						
							|  |  |  |         [ [ compile-ast ] with map [ ] join ] [ length ] bi
 | 
					
						
							|  |  |  |         '[ @ _ narray ] | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  |     ] [ call-next-method ] if ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 21:45:01 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | GENERIC: compile-assignment ( lexenv name -- quot )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  | M: ast-name compile-assignment name>> swap lookup-writer ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: ast-assignment compile-ast | 
					
						
							|  |  |  |     [ value>> compile-ast [ dup ] ] [ name>> compile-assignment ] 2bi 3append ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : block-lexenv ( block -- lexenv )
 | 
					
						
							|  |  |  |     [ arguments>> ] [ body>> [ assigned-locals ] map concat unique ] bi
 | 
					
						
							|  |  |  |     '[ | 
					
						
							|  |  |  |         dup dup _ key?
 | 
					
						
							|  |  |  |         [ <local-reader> ] | 
					
						
							|  |  |  |         [ <local> ] | 
					
						
							|  |  |  |         if
 | 
					
						
							|  |  |  |     ] { } map>assoc
 | 
					
						
							|  |  |  |     dup
 | 
					
						
							|  |  |  |     [ nip local-reader? ] assoc-filter
 | 
					
						
							|  |  |  |     [ <local-writer> ] assoc-map
 | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  |     <lexenv> swap >>local-writers swap >>local-readers ;
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  | : compile-block ( lexenv block -- vars body )
 | 
					
						
							| 
									
										
										
										
											2009-03-30 06:31:50 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         block-lexenv | 
					
						
							|  |  |  |         [ nip local-readers>> values ] | 
					
						
							|  |  |  |         [ lexenv-union ] 2bi
 | 
					
						
							|  |  |  |     ] [ body>> ] bi
 | 
					
						
							| 
									
										
										
										
											2009-03-31 02:24:38 -04:00
										 |  |  |     [ drop [ nil ] ] [ [ compile-ast ] with map [ drop ] join ] if-empty ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-block compile-ast | 
					
						
							|  |  |  |     compile-block <lambda> '[ _ ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : make-return ( quot n block -- quot )
 | 
					
						
							|  |  |  |     need-return-continuation? [ | 
					
						
							|  |  |  |         '[ | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 _ _ ncurry | 
					
						
							|  |  |  |                 [ return-continuation set ] prepose callcc1
 | 
					
						
							|  |  |  |             ] with-scope
 | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ] [ drop ] if
 | 
					
						
							|  |  |  |     rewrite-closures first ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: compile-smalltalk ( ast -- quot )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: object compile-smalltalk ( statement -- quot )
 | 
					
						
							|  |  |  |     [ [ empty-lexenv ] dip compile-ast 0 ] keep make-return ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (compile-method-body) ( lexenv block -- lambda )
 | 
					
						
							|  |  |  |     [ drop self>> ] [ compile-block ] 2bi [ swap suffix ] dip <lambda> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compile-method-body ( lexenv block -- quot )
 | 
					
						
							|  |  |  |     [ [ (compile-method-body) ] [ arguments>> length 1+ ] bi ] keep
 | 
					
						
							|  |  |  |     make-return ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compile-method ( lexenv ast-method -- )
 | 
					
						
							|  |  |  |     [ [ class>> ] [ name>> selector>generic ] bi* create-method ] | 
					
						
							|  |  |  |     [ body>> compile-method-body ] | 
					
						
							|  |  |  |     2bi define ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <class-lexenv> ( class -- lexenv )
 | 
					
						
							|  |  |  |     <lexenv> swap >>class "self" <local-reader> >>self ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-class compile-smalltalk ( ast-class -- quot )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ name>> ] [ superclass>> ] [ ivars>> ] tri
 | 
					
						
							|  |  |  |         define-class <class-lexenv>  | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     [ methods>> ] bi
 | 
					
						
							|  |  |  |     [ compile-method ] with each
 | 
					
						
							|  |  |  |     [ nil ] ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ERROR: no-word name ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: ast-foreign compile-smalltalk | 
					
						
							|  |  |  |     [ class>> dup ":" split1 lookup [ ] [ no-word ] ?if ] | 
					
						
							|  |  |  |     [ name>> ] bi define-foreign | 
					
						
							|  |  |  |     [ nil ] ;
 |