]> gitweb.factorcode.org Git - factor.git/blob - basis/typed/typed.factor
4a14e5d3b72e263ce92d5e7aebb424853d6f66aa
[factor.git] / basis / typed / typed.factor
1 ! (c)Joe Groff bsd license
2 USING: accessors arrays classes classes.tuple combinators
3 combinators.short-circuit definitions effects fry generalizations
4 hints math kernel kernel.private namespaces parser quotations
5 sequences slots words locals effects.parser
6 locals.parser macros stack-checker.dependencies
7 classes.maybe classes.algebra ;
8 FROM: classes.tuple.private => tuple-layout ;
9 IN: typed
10
11 ERROR: type-mismatch-error value expected-type word expected-types ;
12 ERROR: input-mismatch-error < type-mismatch-error ;
13 ERROR: output-mismatch-error < type-mismatch-error ;
14 ERROR: no-types-specified word effect ;
15
16 PREDICATE: typed-gensym < word "typed-gensym" word-prop >boolean ;
17 PREDICATE: typed-word < word "typed-word" word-prop >boolean ;
18
19 <PRIVATE
20
21 : unboxable-tuple-class? ( type -- ? )
22     {
23         [ only-classoid? not ]
24         [ all-slots empty? not ]
25         [ immutable-tuple-class? ]
26         [ final-class? ]
27     } 1&& ;
28
29 ! typed inputs
30
31 : typed-stack-effect? ( effect -- ? )
32     [ object = ] all? not ;
33
34 : add-depends-on-unboxing ( class -- )
35     [ dup tuple-layout add-depends-on-tuple-layout ]
36     [ add-depends-on-final ]
37     bi ;
38
39 : (unboxer) ( type -- quot )
40     dup unboxable-tuple-class? [
41         dup add-depends-on-unboxing
42         all-slots [
43             [ name>> reader-word 1quotation ]
44             [ class>> (unboxer) ] bi compose
45         ] map [ cleave ] curry
46     ] [ drop [ ] ] if ;
47
48 :: unboxer ( error-quot word types type -- quot )
49     type word? [ type "coercer" word-prop ] [ f ] if [ ] or
50     type type word types error-quot '[ dup _ instance? [ _ _ _ @ ] unless ]
51     type (unboxer)
52     compose compose ;
53
54 : make-unboxer ( error-quot word types -- quot )
55     dup [ unboxer ] 3 nwith
56     [ swap \ dip [ ] 2sequence prepend ] map-reduce ;
57
58 : (unboxed-types) ( type -- types )
59     dup unboxable-tuple-class?
60     [
61         dup add-depends-on-unboxing
62         all-slots [ class>> (unboxed-types) ] map concat
63     ]
64     [ 1array ] if ;
65
66 : unboxed-types ( types -- types' )
67     [ (unboxed-types) ] map concat ;
68
69 :: typed-inputs ( quot word types -- quot' )
70     types unboxed-types :> unboxed-types
71
72     [ input-mismatch-error ] word types make-unboxer
73     unboxed-types quot '[ _ declare @ ]
74     compose ;
75
76 ! typed outputs
77
78 :: typed-outputs ( quot word types -- quot' )
79     [ output-mismatch-error ] word types make-unboxer
80     quot prepose ;
81
82 DEFER: make-boxer
83
84 : boxer ( type -- quot )
85     dup unboxable-tuple-class?
86     [
87         dup add-depends-on-unboxing
88         [ all-slots [ class>> ] map make-boxer ]
89         [ [ boa ] curry ]
90         bi compose
91     ]
92     [ drop [ ] ] if ;
93
94 : make-boxer ( types -- quot )
95     [ [ ] ]
96     [ [ boxer ] [ swap '[ @ _ dip ] ] map-reduce ] if-empty ;
97
98 ! defining typed words
99
100 MACRO: (typed) ( word def effect -- quot )
101     swapd
102     [
103         nip effect-in-types swap
104         [ [ unboxed-types ] [ make-boxer ] bi ] dip
105         '[ _ declare @ @ ]
106     ]
107     [
108         effect-out-types
109         dup typed-stack-effect? [ typed-outputs ] [ 2drop ] if
110     ] 2bi ;
111
112 : <typed-gensym> ( parent-word -- word )
113     [ name>> "( typed " " )" surround f <word> dup ]
114     [ "typed-gensym" set-word-prop ] bi ;
115
116 : unboxed-effect ( effect -- effect' )
117     [ effect-in-types unboxed-types [ "in" swap 2array ] map ]
118     [ effect-out-types unboxed-types [ "out" swap 2array ] map ] bi <effect> ;
119
120 M: typed-gensym stack-effect call-next-method unboxed-effect ;
121 M: typed-gensym parent-word "typed-gensym" word-prop ;
122 M: typed-gensym crossref? parent-word crossref? ;
123 M: typed-gensym where parent-word where ;
124
125 : define-typed-gensym ( word def effect -- gensym )
126     [ 2drop <typed-gensym> dup ]
127     [ [ (typed) ] 3curry ]
128     [ 2nip ] 3tri define-declared ;
129
130 MACRO: typed ( quot word effect -- quot' )
131     [ effect-in-types dup typed-stack-effect? [ typed-inputs ] [ 2drop ] if ]
132     [
133         nip effect-out-types dup typed-stack-effect?
134         [ [ unboxed-types ] [ make-boxer ] bi '[ @ _ declare @ ] ] [ drop ] if
135     ] 2bi ;
136
137 : (typed-def) ( word def effect -- quot )
138     [ define-typed-gensym ] 3keep
139     [ drop [ swap "typed-word" set-word-prop ] [ [ 1quotation ] dip ] 2bi ] dip
140     [ typed ] 3curry ;
141
142 : typed-def ( word def effect -- quot )
143     dup {
144         [ effect-in-types typed-stack-effect? ]
145         [ effect-out-types typed-stack-effect? ]
146     } 1|| [ (typed-def) ] [ nip no-types-specified ] if ;
147
148 M: typed-word subwords
149     [ call-next-method ]
150     [ "typed-word" word-prop ] bi suffix ;
151
152 PRIVATE>
153
154 : define-typed ( word def effect -- )
155     [ [ 2drop ] [ typed-def ] [ 2nip ] 3tri define-inline ]
156     [ drop "typed-def" set-word-prop ]
157     [ 2drop "typed-word" word-prop set-last-word ] 3tri ;
158
159 SYNTAX: TYPED:
160     (:) define-typed ;
161 SYNTAX: TYPED::
162     (::) define-typed ;
163
164 USE: vocabs.loader
165
166 { "typed" "prettyprint" } "typed.prettyprint" require-when
167 { "typed" "compiler.cfg.debugger" } "typed.debugger" require-when