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 generalizations 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? ;
17 M: ast-message-send need-return-continuation?
19 [ receiver>> need-return-continuation? ]
20 [ arguments>> need-return-continuation? ]
23 M: ast-assignment need-return-continuation?
24 value>> need-return-continuation? ;
26 M: array need-return-continuation? [ need-return-continuation? ] any? ;
28 M: object need-return-continuation? drop f ;
30 GENERIC: assigned-locals ( ast -- seq )
32 M: ast-return assigned-locals value>> assigned-locals ;
34 M: ast-block assigned-locals
35 [ body>> assigned-locals ] [ arguments>> ] bi diff ;
37 M: ast-message-send assigned-locals
38 [ arguments>> assigned-locals ]
39 [ receiver>> assigned-locals ]
42 M: ast-assignment assigned-locals
43 [ name>> dup ast-name? [ name>> 1array ] [ drop { } ] if ]
44 [ value>> assigned-locals ] bi append ;
46 M: array assigned-locals
47 [ assigned-locals ] map concat ;
49 M: object assigned-locals drop f ;
51 GENERIC: compile-ast ( lexenv ast -- quot )
53 M: object compile-ast nip 1quotation ;
55 ERROR: unbound-local name ;
57 M: ast-name compile-ast
58 name>> swap local-readers>> at 1quotation ;
60 M: ast-message-send compile-ast
61 [ arguments>> [ compile-ast ] with map [ ] join ]
62 [ receiver>> compile-ast ]
63 [ nip selector>> selector>generic ]
64 2tri [ append ] dip suffix ;
66 M: ast-return compile-ast
68 [ return-continuation get continue-with ] append ;
70 GENERIC: contains-blocks? ( obj -- ? )
72 M: ast-block contains-blocks? drop t ;
74 M: object contains-blocks? drop f ;
76 M: array contains-blocks? [ contains-blocks? ] any? ;
79 dup contains-blocks? [
80 [ [ compile-ast ] with map [ ] join ] [ length ] bi
86 GENERIC: compile-assignment ( lexenv name -- quot )
88 M: ast-name compile-assignment
89 name>> swap local-writers>> at 1quotation ;
91 M: ast-assignment compile-ast
92 [ value>> compile-ast [ dup ] ] [ name>> compile-assignment ] 2bi 3append ;
94 : block-lexenv ( block -- lexenv )
95 [ arguments>> ] [ body>> [ assigned-locals ] map concat unique ] bi
103 [ nip local-reader? ] assoc-filter
104 [ <local-writer> ] assoc-map
107 M: ast-block compile-ast
110 [ nip local-readers>> values ]
115 [ [ compile-ast [ drop ] append ] with map [ ] join ]
122 : compile-method ( block -- quot )
123 [ [ empty-lexenv ] dip compile-ast [ call ] compose ]
124 [ arguments>> length ]
125 [ need-return-continuation? ]
127 [ '[ [ _ _ ncurry [ return-continuation set ] prepose callcc1 ] with-scope ] ] [ drop ] if ;
129 : compile-statement ( statement -- quot )
130 [ [ empty-lexenv ] dip compile-ast ] [ need-return-continuation? ] bi
131 [ '[ [ [ return-continuation set @ ] callcc1 ] with-scope ] ] when ;