2004-11-26 22:23:57 -05:00
|
|
|
! :folding=indent:collapseFolds=1:
|
|
|
|
|
|
|
|
! $Id$
|
|
|
|
!
|
|
|
|
! Copyright (C) 2004 Slava Pestov.
|
|
|
|
!
|
|
|
|
! Redistribution and use in source and binary forms, with or without
|
|
|
|
! modification, are permitted provided that the following conditions are met:
|
|
|
|
!
|
|
|
|
! 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
! this list of conditions and the following disclaimer.
|
|
|
|
!
|
|
|
|
! 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
! this list of conditions and the following disclaimer in the documentation
|
|
|
|
! and/or other materials provided with the distribution.
|
|
|
|
!
|
|
|
|
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
|
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
IN: inference
|
|
|
|
USE: errors
|
2004-12-10 18:38:40 -05:00
|
|
|
USE: generic
|
2004-11-26 22:23:57 -05:00
|
|
|
USE: interpreter
|
|
|
|
USE: kernel
|
|
|
|
USE: lists
|
|
|
|
USE: math
|
|
|
|
USE: namespaces
|
|
|
|
USE: strings
|
|
|
|
USE: vectors
|
|
|
|
USE: words
|
|
|
|
USE: hashtables
|
2004-12-24 17:29:16 -05:00
|
|
|
USE: prettyprint
|
2004-11-26 22:23:57 -05:00
|
|
|
|
2004-12-27 15:27:18 -05:00
|
|
|
! If this symbol is on, partial evalution of conditionals is
|
|
|
|
! disabled.
|
|
|
|
SYMBOL: inferring-base-case
|
|
|
|
|
2004-12-26 01:42:09 -05:00
|
|
|
: vector-length< ( vec1 vec2 -- ? )
|
|
|
|
swap vector-length swap vector-length < ;
|
|
|
|
|
|
|
|
: unify-length ( vec1 vec2 -- vec1 )
|
|
|
|
2dup vector-length< [ swap ] unless [
|
|
|
|
vector-length over vector-length -
|
|
|
|
empty-vector [ swap vector-append ] keep
|
|
|
|
] keep ;
|
|
|
|
|
|
|
|
: unify-classes ( value value -- class )
|
|
|
|
#! If one of the values is f, it was added as a result of
|
|
|
|
#! length unification so we just replace it with a computed
|
|
|
|
#! object value.
|
|
|
|
2dup and [
|
|
|
|
value-class swap value-class class-or
|
|
|
|
] [
|
|
|
|
2drop object
|
|
|
|
] ifte ;
|
2004-12-23 16:37:16 -05:00
|
|
|
|
|
|
|
: unify-results ( value value -- value )
|
2004-11-26 22:23:57 -05:00
|
|
|
#! Replace values with unknown result if they differ,
|
|
|
|
#! otherwise retain them.
|
2004-12-26 01:42:09 -05:00
|
|
|
2dup = [ drop ] [ unify-classes <computed> ] ifte ;
|
2004-11-26 22:23:57 -05:00
|
|
|
|
|
|
|
: unify-stacks ( list -- stack )
|
|
|
|
#! Replace differing literals in stacks with unknown
|
|
|
|
#! results.
|
2004-12-26 01:42:09 -05:00
|
|
|
uncons [
|
|
|
|
unify-length vector-zip [
|
|
|
|
uncons unify-results
|
|
|
|
] vector-map
|
|
|
|
] each ;
|
2004-12-22 22:16:46 -05:00
|
|
|
|
|
|
|
: balanced? ( list -- ? )
|
2004-12-26 01:42:09 -05:00
|
|
|
#! Check if a list of [ instack | outstack ] pairs is
|
|
|
|
#! balanced.
|
|
|
|
[ uncons vector-length swap vector-length - ] map all=? ;
|
2004-12-07 23:21:32 -05:00
|
|
|
|
2004-12-26 01:42:09 -05:00
|
|
|
: unify-effect ( list -- in out )
|
|
|
|
#! Unify a list of [ instack | outstack ] pairs.
|
|
|
|
dup balanced? [
|
|
|
|
unzip unify-stacks >r unify-stacks r>
|
2004-12-25 21:28:47 -05:00
|
|
|
] [
|
2004-12-26 01:42:09 -05:00
|
|
|
"Unbalanced branches" throw
|
2004-12-25 21:28:47 -05:00
|
|
|
] ifte ;
|
2004-12-07 23:21:32 -05:00
|
|
|
|
2004-12-26 01:42:09 -05:00
|
|
|
: datastack-effect ( list -- )
|
|
|
|
[ [ d-in get meta-d get ] bind cons ] map
|
|
|
|
unify-effect
|
|
|
|
meta-d set d-in set ;
|
|
|
|
|
|
|
|
: callstack-effect ( list -- )
|
|
|
|
[ [ { } meta-r get ] bind cons ] map
|
|
|
|
unify-effect
|
|
|
|
meta-r set drop ;
|
|
|
|
|
|
|
|
: filter-terminators ( list -- list )
|
|
|
|
[ [ d-in get meta-d get and ] bind ] subset [
|
|
|
|
"No branch has a stack effect" throw
|
|
|
|
] unless* ;
|
2004-12-07 23:21:32 -05:00
|
|
|
|
2004-12-24 17:29:16 -05:00
|
|
|
: unify-effects ( list -- )
|
2004-12-26 01:42:09 -05:00
|
|
|
filter-terminators dup datastack-effect callstack-effect ;
|
2004-11-26 22:23:57 -05:00
|
|
|
|
2004-12-26 17:04:08 -05:00
|
|
|
SYMBOL: cloned
|
|
|
|
|
2004-12-23 18:26:04 -05:00
|
|
|
: deep-clone ( vector -- vector )
|
2004-12-26 17:04:08 -05:00
|
|
|
#! Clone a vector if it hasn't already been cloned in this
|
|
|
|
#! with-deep-clone scope.
|
|
|
|
dup cloned get assoc dup [
|
|
|
|
nip
|
|
|
|
] [
|
|
|
|
drop vector-clone [ dup cloned [ acons ] change ] keep
|
|
|
|
] ifte ;
|
|
|
|
|
|
|
|
: deep-clone-vector ( vector -- vector )
|
2004-12-23 18:26:04 -05:00
|
|
|
#! Clone a vector of vectors.
|
2004-12-26 17:04:08 -05:00
|
|
|
[ ( deep-clone ) vector-clone ] vector-map ;
|
|
|
|
|
|
|
|
: copy-inference ( -- )
|
|
|
|
#! We avoid cloning the same object more than once in order
|
|
|
|
#! to preserve identity structure.
|
|
|
|
cloned off
|
|
|
|
meta-r [ deep-clone-vector ] change
|
|
|
|
meta-d [ deep-clone-vector ] change
|
|
|
|
d-in [ deep-clone-vector ] change
|
|
|
|
dataflow-graph off ;
|
2004-12-23 18:26:04 -05:00
|
|
|
|
2004-12-27 15:27:18 -05:00
|
|
|
: infer-branch ( value -- namespace )
|
2004-12-07 23:21:32 -05:00
|
|
|
<namespace> [
|
2004-12-26 02:52:39 -05:00
|
|
|
uncons [ unswons [ \ value-class set ] bind ] when*
|
2004-12-19 22:53:41 -05:00
|
|
|
dup value-recursion recursive-state set
|
2004-12-26 17:04:08 -05:00
|
|
|
copy-inference
|
2004-12-22 22:16:46 -05:00
|
|
|
literal-value infer-quot
|
2004-12-08 18:39:36 -05:00
|
|
|
#values values-node
|
2004-12-07 23:21:32 -05:00
|
|
|
] extend ;
|
|
|
|
|
2004-12-23 23:55:22 -05:00
|
|
|
: terminator? ( obj -- ? )
|
|
|
|
dup word? [ "terminator" word-property ] [ drop f ] ifte ;
|
2004-11-30 23:56:01 -05:00
|
|
|
|
2004-12-26 02:52:39 -05:00
|
|
|
: terminator-quot? ( [ quot | type-prop ] -- ? )
|
|
|
|
car literal-value [ terminator? ] some? ;
|
2004-12-23 23:55:22 -05:00
|
|
|
|
2004-12-27 22:58:43 -05:00
|
|
|
: dual-branch ( branch branchlist -- rstate )
|
2004-12-24 17:29:16 -05:00
|
|
|
#! Return a recursive state for a branch other than the
|
|
|
|
#! given one in the list.
|
2004-12-27 22:58:43 -05:00
|
|
|
[ over eq? not ] subset nip car car value-recursion ;
|
2004-12-24 17:29:16 -05:00
|
|
|
|
2004-12-27 22:58:43 -05:00
|
|
|
: recursive-branch ( branch branchlist -- )
|
2004-11-26 22:23:57 -05:00
|
|
|
[
|
2004-12-27 22:58:43 -05:00
|
|
|
dupd dual-branch >r infer-branch r> set-base
|
2004-11-26 22:23:57 -05:00
|
|
|
] [
|
2004-12-27 22:58:43 -05:00
|
|
|
[ 2drop ] when
|
2004-11-26 22:23:57 -05:00
|
|
|
] catch ;
|
|
|
|
|
2004-12-08 18:39:36 -05:00
|
|
|
: infer-base-case ( branchlist -- )
|
2004-12-24 17:29:16 -05:00
|
|
|
[
|
2004-12-27 15:27:18 -05:00
|
|
|
inferring-base-case on
|
|
|
|
|
2004-12-27 22:58:43 -05:00
|
|
|
dup [
|
|
|
|
2dup terminator-quot? [
|
|
|
|
2drop
|
|
|
|
] [
|
|
|
|
recursive-branch
|
|
|
|
] ifte
|
|
|
|
] each drop
|
2004-12-24 17:29:16 -05:00
|
|
|
] with-scope ;
|
2004-12-08 18:39:36 -05:00
|
|
|
|
|
|
|
: (infer-branches) ( branchlist -- list )
|
2004-12-26 02:52:39 -05:00
|
|
|
#! The branchlist is a list of pairs:
|
|
|
|
#! [ value | typeprop ]
|
|
|
|
#! value is either a literal or computed instance; typeprop
|
|
|
|
#! is a pair [ value | class ] indicating a type propagation
|
|
|
|
#! for the given branch.
|
|
|
|
dup infer-base-case [
|
2004-12-27 15:27:18 -05:00
|
|
|
dup infer-branch swap terminator-quot? [
|
2004-12-24 17:29:16 -05:00
|
|
|
[ meta-d off meta-r off d-in off ] extend
|
|
|
|
] when
|
2004-12-07 23:21:32 -05:00
|
|
|
] map ;
|
2004-11-29 23:14:12 -05:00
|
|
|
|
2004-12-24 17:29:16 -05:00
|
|
|
: unify-dataflow ( inputs instruction effectlist -- )
|
|
|
|
[ [ get-dataflow ] bind ] map
|
|
|
|
swap dataflow, [ node-consume-d set ] bind ;
|
|
|
|
|
2004-11-29 23:14:12 -05:00
|
|
|
: infer-branches ( inputs instruction branchlist -- )
|
2004-11-26 22:23:57 -05:00
|
|
|
#! Recursive stack effect inference is done here. If one of
|
|
|
|
#! the branches has an undecidable stack effect, we set the
|
2004-11-29 23:14:12 -05:00
|
|
|
#! base case to this stack effect and try again. The inputs
|
|
|
|
#! parameter is a vector.
|
2004-12-24 17:29:16 -05:00
|
|
|
(infer-branches) dup unify-effects unify-dataflow ;
|
2004-11-26 22:23:57 -05:00
|
|
|
|
2004-12-27 15:27:18 -05:00
|
|
|
: static-branch? ( value -- )
|
|
|
|
literal? inferring-base-case get not and ;
|
|
|
|
|
2004-12-26 02:52:39 -05:00
|
|
|
: static-ifte ( true false -- )
|
|
|
|
#! If the branch taken is statically known, just infer
|
|
|
|
#! along that branch.
|
2004-12-27 15:27:18 -05:00
|
|
|
dataflow-drop, pop-d literal-value [ drop ] [ nip ] ifte
|
|
|
|
gensym [
|
|
|
|
dup value-recursion recursive-state set
|
|
|
|
literal-value infer-quot
|
|
|
|
] (with-block) ;
|
2004-12-26 02:52:39 -05:00
|
|
|
|
|
|
|
: dynamic-ifte ( true false -- )
|
|
|
|
#! If branch taken is computed, infer along both paths and
|
|
|
|
#! unify.
|
|
|
|
2list >r 1 meta-d get vector-tail* #ifte r>
|
2004-12-26 02:16:38 -05:00
|
|
|
pop-d [
|
2004-12-26 02:52:39 -05:00
|
|
|
dup \ object cons ,
|
2004-12-26 02:16:38 -05:00
|
|
|
\ f cons ,
|
|
|
|
] make-list zip ( condition )
|
2004-11-26 22:23:57 -05:00
|
|
|
infer-branches ;
|
|
|
|
|
2004-12-26 02:52:39 -05:00
|
|
|
: infer-ifte ( -- )
|
|
|
|
#! Infer effects for both branches, unify.
|
|
|
|
[ object general-list general-list ] ensure-d
|
|
|
|
dataflow-drop, pop-d
|
|
|
|
dataflow-drop, pop-d swap
|
2004-12-27 15:27:18 -05:00
|
|
|
peek-d static-branch? [
|
|
|
|
static-ifte
|
|
|
|
] [
|
|
|
|
dynamic-ifte
|
|
|
|
] ifte ;
|
2004-12-26 02:52:39 -05:00
|
|
|
|
2004-12-13 16:28:28 -05:00
|
|
|
\ ifte [ infer-ifte ] "infer" set-word-property
|
|
|
|
|
2004-12-19 22:53:41 -05:00
|
|
|
: vtable>list ( value -- list )
|
2004-12-22 22:16:46 -05:00
|
|
|
dup value-recursion swap literal-value vector>list
|
|
|
|
[ over <literal> ] map nip ;
|
2004-11-26 22:23:57 -05:00
|
|
|
|
2004-12-13 16:28:28 -05:00
|
|
|
: infer-dispatch ( -- )
|
2004-11-26 22:23:57 -05:00
|
|
|
#! Infer effects for all branches, unify.
|
2004-12-23 01:14:07 -05:00
|
|
|
[ object vector ] ensure-d
|
2004-11-28 21:56:58 -05:00
|
|
|
dataflow-drop, pop-d vtable>list
|
2004-12-26 02:16:38 -05:00
|
|
|
[ f cons ] map
|
2004-12-13 16:28:28 -05:00
|
|
|
>r 1 meta-d get vector-tail* #dispatch r>
|
|
|
|
pop-d drop ( n )
|
2004-11-26 22:23:57 -05:00
|
|
|
infer-branches ;
|
|
|
|
|
2004-12-24 02:52:02 -05:00
|
|
|
USE: kernel-internals
|
2004-12-13 16:28:28 -05:00
|
|
|
\ dispatch [ infer-dispatch ] "infer" set-word-property
|
2004-12-24 17:29:16 -05:00
|
|
|
\ dispatch [ [ fixnum vector ] [ ] ]
|
|
|
|
"infer-effect" set-word-property
|