[ t ] [ [ 2 '[ _ ] 1 '[ _ + ] compose ] final-info first infer-value (( -- object )) effect= ] unit-test
[ t ] [ [ 2 '[ _ + ] ] final-info first infer-value (( object -- object )) effect= ] unit-test
[ f ] [ [ [ [ ] [ 1 ] if ] ] final-info first infer-value ] unit-test
-[ f ] [ [ [ 1 ] '[ @ ] ] final-info first infer-value ] unit-test
+[ t ] [ [ [ 1 ] '[ @ ] ] final-info first infer-value (( -- object )) effect= ] unit-test
[ f ] [ [ dup drop ] final-info first infer-value ] unit-test
! This should not hang
[ ] [ [ [ dup call( quot -- ) ] dup call( quot -- ) ] final-info drop ] unit-test
-[ ] [ [ [ dup curry call( quot -- ) ] dup curry call( quot -- ) ] final-info drop ] unit-test
\ No newline at end of file
+[ ] [ [ [ dup curry call( quot -- ) ] dup curry call( quot -- ) ] final-info drop ] unit-test
+
+! This should get inlined, because the parameter to the curry is literal even though
+! [ boa ] by itself doesn't infer
+TUPLE: a-tuple x ;
+
+[ V{ a-tuple } ] [ [ a-tuple '[ _ boa ] call( x -- tuple ) ] final-classes ] unit-test
\ No newline at end of file
M: compose cached-effect
[ first>> ] [ second>> ] bi [ cached-effect ] bi@ compose-effects* ;
+: safe-infer ( quot -- effect )
+ [ infer ] [ 2drop +unknown+ ] recover ;
+
M: quotation cached-effect
dup cached-effect>>
- [ ] [
- [ [ infer ] [ 2drop +unknown+ ] recover dup ] keep
- (>>cached-effect)
- ] ?if ;
+ [ ] [ [ safe-infer dup ] keep (>>cached-effect) ] ?if ;
: call-effect-unsafe? ( quot effect -- ? )
[ cached-effect ] dip
: execute-effect>quot ( effect -- quot )
inline-cache new '[ drop _ _ execute-effect-ic ] ;
+! Some bookkeeping to make sure that crap like
+! [ dup curry call( quot -- ) ] dup curry call( quot -- ) ]
+! doesn't hang the compiler.
+GENERIC: already-inlined-quot? ( quot -- ? )
+
+M: curry already-inlined-quot? quot>> already-inlined-quot? ;
+
+M: compose already-inlined-quot?
+ [ first>> already-inlined-quot? ]
+ [ second>> already-inlined-quot? ] bi or ;
+
+M: quotation already-inlined-quot? already-inlined? ;
+
+GENERIC: add-quot-to-history ( quot -- )
+
+M: curry add-quot-to-history quot>> add-quot-to-history ;
+
+M: compose add-quot-to-history
+ [ first>> add-quot-to-history ]
+ [ second>> add-quot-to-history ] bi ;
+
+M: quotation add-quot-to-history add-to-history ;
+
: last2 ( seq -- penultimate ultimate )
2 tail* first2 ;
(( -- object )) swap compose-effects ;
: (infer-value) ( value-info -- effect )
- dup class>> {
- { \ quotation [
- literal>> [ uninferable ] unless*
- dup already-inlined? [ uninferable ] when
- cached-effect dup +unknown+ = [ uninferable ] when
- ] }
- { \ curry [
- slots>> third (infer-value)
- remove-effect-input
- ] }
- { \ compose [
- slots>> last2 [ (infer-value) ] bi@
- compose-effects
- ] }
- [ uninferable ]
- } case ;
+ dup literal?>> [
+ literal>>
+ [ callable? [ uninferable ] unless ]
+ [ already-inlined-quot? [ uninferable ] when ]
+ [ safe-infer dup +unknown+ = [ uninferable ] when ] tri
+ ] [
+ dup class>> {
+ { \ curry [ slots>> third (infer-value) remove-effect-input ] }
+ { \ compose [ slots>> last2 [ (infer-value) ] bi@ compose-effects ] }
+ [ uninferable ]
+ } case
+ ] if ;
: infer-value ( value-info -- effect/f )
[ (infer-value) ]
recover ;
: (value>quot) ( value-info -- quot )
- dup class>> {
- { \ quotation [ literal>> dup add-to-history '[ drop @ ] ] }
- { \ curry [
- slots>> third (value>quot)
- '[ [ obj>> ] [ quot>> @ ] bi ]
- ] }
- { \ compose [
- slots>> last2 [ (value>quot) ] bi@
- '[ [ first>> @ ] [ second>> @ ] bi ]
- ] }
- } case ;
+ dup literal?>> [
+ literal>> [ add-quot-to-history ] [ '[ drop @ ] ] bi
+ ] [
+ dup class>> {
+ { \ curry [
+ slots>> third (value>quot)
+ '[ [ obj>> ] [ quot>> @ ] bi ]
+ ] }
+ { \ compose [
+ slots>> last2 [ (value>quot) ] bi@
+ '[ [ first>> @ ] [ second>> @ ] bi ]
+ ] }
+ } case
+ ] if ;
: value>quot ( value-info -- quot: ( code effect -- ) )
(value>quot) '[ drop @ ] ;
:: inline-word ( #call word -- ? )
word already-inlined? [ f ] [
#call word splicing-body [
- [
- word add-to-history
- dup (propagate)
- ] with-scope
- #call (>>body) t
+ word add-to-history
+ #call (>>body)
+ #call propagate-body
] [ f ] if*
] if ;
#! Note the logic here: if there's a custom inlining hook,
#! it is permitted to return f, which means that we try the
#! normal inlining heuristic.
- dup custom-inlining? [ 2dup inline-custom ] [ f ] if
- [ 2drop t ] [ (do-inlining) ] if ;
+ [
+ dup custom-inlining? [ 2dup inline-custom ] [ f ] if
+ [ 2drop t ] [ (do-inlining) ] if
+ ] with-scope ;
IN: struct-arrays.tests
USING: classes.struct struct-arrays tools.test kernel math sequences
-alien.syntax alien.c-types destructors libc accessors sequences.private ;
+alien.syntax alien.c-types destructors libc accessors sequences.private
+compiler.tree.debugger ;
STRUCT: test-struct-array
{ x int }
ALIEN: 123 4 fixed-string <direct-struct-array> [ (underlying)>> ] { } map-as
] unit-test
-[ 10 "int" <struct-array> ] must-fail
\ No newline at end of file
+[ 10 "int" <struct-array> ] must-fail
+
+STRUCT: wig { x int } ;
+: <bacon> ( -- wig ) 0 wig <struct-boa> ; inline
+: waterfall ( -- a b ) 1 wig <struct-array> <bacon> swap first x>> ; inline
+
+[ t ] [ [ waterfall ] { x>> } inlined? ] unit-test
\ No newline at end of file