189 lines
5.1 KiB
Factor
189 lines
5.1 KiB
Factor
! Copyright (C) 2004, 2009 Slava Pestov.
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
USING: fry arrays generic io io.streams.string kernel math namespaces
|
|
parser sequences strings vectors words quotations effects classes
|
|
continuations assocs combinators compiler.errors accessors math.order
|
|
definitions locals sets hints macros stack-checker.state
|
|
stack-checker.visitor stack-checker.errors stack-checker.values
|
|
stack-checker.recursive-state stack-checker.dependencies summary ;
|
|
FROM: sequences.private => from-end ;
|
|
FROM: namespaces => set ;
|
|
IN: stack-checker.backend
|
|
|
|
: push-d ( obj -- ) meta-d push ;
|
|
|
|
: introduce-values ( values -- )
|
|
[ [ [ input-parameter ] dip set-known ] each ]
|
|
[ length input-count +@ ]
|
|
[ #introduce, ]
|
|
tri ;
|
|
|
|
: update-inner-d ( new -- )
|
|
inner-d-index get min inner-d-index set ;
|
|
|
|
: pop-d ( -- obj )
|
|
meta-d
|
|
[ <value> dup 1array introduce-values ]
|
|
[ pop meta-d length update-inner-d ] if-empty ;
|
|
|
|
: peek-d ( -- obj ) pop-d dup push-d ;
|
|
|
|
: make-values ( n -- values )
|
|
[ <value> ] replicate ;
|
|
|
|
: ensure-d ( n -- values )
|
|
meta-d 2dup length > [
|
|
2dup
|
|
[ nip >array ] [ length - make-values ] [ nip delete-all ] 2tri
|
|
[ introduce-values ] [ meta-d push-all ] bi
|
|
meta-d push-all
|
|
] when
|
|
swap from-end [ tail ] [ update-inner-d ] bi ;
|
|
|
|
: shorten-by ( n seq -- )
|
|
[ length swap - ] keep shorten ; inline
|
|
|
|
: shorten-d ( n -- )
|
|
meta-d shorten-by meta-d length update-inner-d ;
|
|
|
|
: consume-d ( n -- seq )
|
|
[ ensure-d ] [ shorten-d ] bi ;
|
|
|
|
: output-d ( values -- ) meta-d push-all ;
|
|
|
|
: produce-d ( n -- values )
|
|
make-values dup meta-d push-all ;
|
|
|
|
: push-r ( obj -- ) meta-r push ;
|
|
|
|
: pop-r ( -- obj )
|
|
meta-r dup empty?
|
|
[ too-many-r> ] [ pop ] if ;
|
|
|
|
: consume-r ( n -- seq )
|
|
meta-r 2dup length >
|
|
[ too-many-r> ] when
|
|
[ swap tail* ] [ shorten-by ] 2bi ;
|
|
|
|
: output-r ( seq -- ) meta-r push-all ;
|
|
|
|
: push-literal ( obj -- )
|
|
literals get push ;
|
|
|
|
: pop-literal ( -- rstate obj )
|
|
literals get [
|
|
pop-d
|
|
[ 1array #drop, ]
|
|
[ literal [ recursion>> ] [ value>> ] bi ] bi
|
|
] [ pop recursive-state get swap ] if-empty ;
|
|
|
|
: literals-available? ( n -- literals ? )
|
|
literals get 2dup length <=
|
|
[ [ swap tail* ] [ shorten-by ] 2bi t ] [ 2drop f f ] if ;
|
|
|
|
GENERIC: apply-object ( obj -- )
|
|
|
|
M: wrapper apply-object
|
|
wrapped>>
|
|
[ dup word? [ depends-on-effect ] [ drop ] if ]
|
|
[ push-literal ]
|
|
bi ;
|
|
|
|
M: object apply-object push-literal ;
|
|
|
|
: terminate ( -- )
|
|
terminated? on meta-d clone meta-r clone #terminate, ;
|
|
|
|
: check->r ( -- )
|
|
meta-r empty? [ too-many->r ] unless ;
|
|
|
|
: infer-quot-here ( quot -- )
|
|
meta-r [
|
|
V{ } clone \ meta-r set
|
|
[ apply-object terminated? get not ] all?
|
|
[ commit-literals check->r ] [ literals get delete-all ] if
|
|
] dip \ meta-r set ;
|
|
|
|
: infer-quot ( quot rstate -- )
|
|
recursive-state get [
|
|
recursive-state set
|
|
infer-quot-here
|
|
] dip recursive-state set ;
|
|
|
|
: time-bomb-quot ( obj generic -- quot )
|
|
[ literalize ] [ "default-method" word-prop ] bi* [ ] 2sequence ;
|
|
|
|
: time-bomb ( obj generic -- )
|
|
time-bomb-quot infer-quot-here ;
|
|
|
|
: infer-literal-quot ( literal -- )
|
|
dup recursive-quotation? [
|
|
value>> recursive-quotation-error
|
|
] [
|
|
dup value>> callable? [
|
|
[ value>> ]
|
|
[ [ recursion>> ] keep add-local-quotation ]
|
|
bi infer-quot
|
|
] [
|
|
value>> \ call time-bomb
|
|
] if
|
|
] if ;
|
|
|
|
: infer->r ( n -- )
|
|
consume-d dup copy-values [ nip output-r ] [ #>r, ] 2bi ;
|
|
|
|
: infer-r> ( n -- )
|
|
consume-r dup copy-values [ nip output-d ] [ #r>, ] 2bi ;
|
|
|
|
: consume/produce ( ..a effect quot: ( ..a inputs outputs -- ..b ) -- ..b )
|
|
'[ [ in>> length consume-d ] [ out>> length produce-d ] bi @ ]
|
|
[ terminated?>> [ terminate ] when ]
|
|
bi ; inline
|
|
|
|
: apply-word/effect ( word effect -- )
|
|
swap '[ _ #call, ] consume/produce ;
|
|
|
|
: end-infer ( -- )
|
|
meta-d clone #return, ;
|
|
|
|
: required-stack-effect ( word -- effect )
|
|
dup stack-effect [ ] [ missing-effect ] ?if ;
|
|
|
|
: with-infer ( quot -- effect visitor )
|
|
[
|
|
init-inference
|
|
init-known-values
|
|
stack-visitor off
|
|
call
|
|
end-infer
|
|
current-effect
|
|
stack-visitor get
|
|
] with-scope ; inline
|
|
|
|
: (infer) ( quot -- effect )
|
|
[ infer-quot-here ] with-infer drop ;
|
|
|
|
: ?quotation-effect ( in -- effect/f )
|
|
dup pair? [ second dup effect? [ drop f ] unless ] [ drop f ] if ;
|
|
|
|
:: declare-effect-d ( word effect variables branches n -- )
|
|
meta-d length :> d-length
|
|
n d-length < [
|
|
d-length 1 - n - :> n'
|
|
n' meta-d nth :> value
|
|
value known :> known
|
|
known word effect variables branches <declared-effect> :> known'
|
|
known' value set-known
|
|
known' branches push
|
|
] [ word unknown-macro-input ] if ;
|
|
|
|
:: declare-input-effects ( word -- )
|
|
H{ } clone :> variables
|
|
V{ } clone :> branches
|
|
word stack-effect in>> <reversed> [| in n |
|
|
in ?quotation-effect [| effect |
|
|
word effect variables branches n declare-effect-d
|
|
] when*
|
|
] each-index ;
|
|
|