1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs combinators.short-circuit
4 continuations fry kernel namespaces quotations sequences sets
5 slots locals.types generalizations smalltalk.ast
6 smalltalk.compiler.lexenv smalltalk.selectors ;
9 SYMBOL: return-continuation
11 GENERIC: need-return-continuation? ( ast -- ? )
13 M: ast-return need-return-continuation? drop t ;
15 M: ast-block need-return-continuation? body>> [ need-return-continuation? ] any? ;
17 M: ast-message-send need-return-continuation?
19 [ receiver>> need-return-continuation? ]
20 [ arguments>> [ need-return-continuation? ] any? ]
23 M: ast-assignment need-return-continuation?
24 value>> need-return-continuation? ;
26 M: object need-return-continuation? drop f ;
28 GENERIC: assigned-locals ( ast -- seq )
30 M: ast-return assigned-locals value>> assigned-locals ;
32 M: ast-block assigned-locals
33 [ body>> [ assigned-locals ] map concat ] [ arguments>> ] bi diff ;
35 M: ast-message-send assigned-locals
36 [ receiver>> assigned-locals ]
37 [ arguments>> [ assigned-locals ] map ] bi append ;
39 M: ast-assignment assigned-locals
40 [ name>> dup ast-name? [ name>> 1array ] [ drop { } ] if ]
41 [ value>> assigned-locals ] bi append ;
43 M: object assigned-locals drop f ;
45 GENERIC: compile-ast ( lexenv ast -- quot )
47 M: object compile-ast nip 1quotation ;
49 ERROR: unbound-local name ;
51 M: ast-name compile-ast
52 name>> swap local-readers>> at 1quotation ;
54 M: ast-message-send compile-ast
55 [ receiver>> compile-ast ]
56 [ arguments>> [ compile-ast ] with map concat ]
57 [ nip selector>> selector>generic ]
58 2tri [ append ] dip suffix ;
60 M: ast-return compile-ast
62 [ return-continuation get continue-with ] append ;
64 GENERIC: compile-assignment ( lexenv name -- quot )
66 M: ast-name compile-assignment
67 name>> swap local-writers>> at 1quotation ;
69 M: ast-assignment compile-ast
70 [ value>> compile-ast [ dup ] ] [ name>> compile-assignment ] 2bi 3append ;
72 : block-lexenv ( block -- lexenv )
73 [ arguments>> ] [ body>> [ assigned-locals ] map concat unique ] bi
81 [ nip local-reader? ] assoc-filter
82 [ <local-writer> ] assoc-map
85 M: ast-block compile-ast
88 [ nip local-readers>> values ]
93 [ [ compile-ast [ drop ] append ] with map [ ] join ]
100 : compile-method ( block -- quot )
101 [ [ empty-lexenv ] dip compile-ast ] [ arguments>> length ] [ need-return-continuation? ] tri
102 [ '[ [ _ _ ncurry [ return-continuation set ] prepose callcc1 ] with-scope ] ] [ drop ] if ;