various inference fixes; cond compiles now

cvs
Slava Pestov 2005-08-30 22:12:21 +00:00
parent d41b3d0c71
commit ea830a4f14
12 changed files with 111 additions and 93 deletions

View File

@ -1,6 +1,7 @@
- reader syntax for arrays, byte arrays, displaced aliens - reader syntax for arrays, byte arrays, displaced aliens
- out of memory error when printing global namespace - out of memory error when printing global namespace
- removing unneeded #label - removing unneeded #label
- pprint trailing space regression
+ ui: + ui:

View File

@ -1,7 +1,7 @@
! Copyright (C) 2005 Slava Pestov. ! Copyright (C) 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license. ! See http://factor.sf.net/license.txt for BSD license.
IN: sequences IN: sequences
USING: generic kernel kernel-internals lists math strings USING: errors generic kernel kernel-internals lists math strings
vectors words ; vectors words ;
! Combinators ! Combinators
@ -234,12 +234,14 @@ IN: kernel
#! Push the number of elements on the datastack. #! Push the number of elements on the datastack.
datastack length ; datastack length ;
: no-cond "cond fall-through" throw ; inline
: cond ( conditions -- ) : cond ( conditions -- )
#! Conditions is a sequence of quotation pairs. #! Conditions is a sequence of quotation pairs.
#! { { [ X ] [ Y ] } { [ Z ] [ T ] } } #! { { [ X ] [ Y ] } { [ Z ] [ T ] } }
#! => X [ Y ] [ Z [ T ] [ ] ifte ] ifte #! => X [ Y ] [ Z [ T ] [ ] ifte ] ifte
#! The last condition should be a catch-all 't'. #! The last condition should be a catch-all 't'.
[ first call ] find nip second call ; [ first call ] find nip [ second call ] [ no-cond ] ifte ;
: with-datastack ( stack word -- stack ) : with-datastack ( stack word -- stack )
datastack >r >r set-datastack r> execute datastack >r >r set-datastack r> execute

View File

@ -9,7 +9,7 @@ IN: errors
TUPLE: no-method object generic ; TUPLE: no-method object generic ;
: no-method ( object generic -- ) <no-method> throw ; : no-method ( object generic -- ) <no-method> throw ; inline
: catchstack ( -- cs ) 6 getenv ; : catchstack ( -- cs ) 6 getenv ;
: set-catchstack ( cs -- ) 6 setenv ; : set-catchstack ( cs -- ) 6 setenv ;

View File

@ -31,7 +31,7 @@ math namespaces sequences words ;
TUPLE: no-math-method left right generic ; TUPLE: no-math-method left right generic ;
: no-math-method ( left right generic -- ) : no-math-method ( left right generic -- )
3dup <no-math-method> throw ; 3dup <no-math-method> throw ; inline
: applicable-method ( generic class -- quot ) : applicable-method ( generic class -- quot )
over "methods" word-prop hash [ ] [ over "methods" word-prop hash [ ] [

View File

@ -74,10 +74,14 @@ namespaces parser prettyprint sequences strings vectors words ;
#! meta-d, meta-r, d-in. They are set to f if #! meta-d, meta-r, d-in. They are set to f if
#! terminate was called. #! terminate was called.
[ [
[
base-case-continuation set
copy-inference copy-inference
dup value-recursion recursive-state set dup value-recursion recursive-state set
literal-value dup infer-quot handle-terminator dup literal-value infer-quot
active? [ #values node, ] when active? [ #values node, ] when
f
] callcc1 [ terminate ] when drop
] make-hash ; ] make-hash ;
: (infer-branches) ( branchlist -- list ) : (infer-branches) ( branchlist -- list )

View File

@ -7,11 +7,15 @@ namespaces parser prettyprint sequences strings vectors words ;
! This variable takes a boolean value. ! This variable takes a boolean value.
SYMBOL: inferring-base-case SYMBOL: inferring-base-case
! Called when a recursive call during base case inference is
! found. Either tries to infer another branch, or gives up.
SYMBOL: base-case-continuation
TUPLE: inference-error message rstate data-stack call-stack ; TUPLE: inference-error message rstate data-stack call-stack ;
: inference-error ( msg -- ) : inference-error ( msg -- )
recursive-state get meta-d get meta-r get recursive-state get meta-d get meta-r get
<inference-error> throw ; <inference-error> throw ; inline
M: inference-error error. ( error -- ) M: inference-error error. ( error -- )
"! Inference error:" print "! Inference error:" print
@ -22,10 +26,9 @@ M: inference-error error. ( error -- )
M: value literal-value ( value -- ) M: value literal-value ( value -- )
{ {
"A literal value was expected where a computed value was found.\n" "A literal value was expected where a computed value was found.\n"
"This means that an attempt was made to compile a word that\n" "This means the word you are inferring applies 'call' or 'execute'\n"
"applies 'call' or 'execute' to a value that is not known\n" "to a value that is not known at compile time.\n"
"at compile time. The value might become known if the word\n" "See the handbook for details."
"is marked 'inline'. See the handbook for details."
} concat inference-error ; } concat inference-error ;
! Word properties that affect inference: ! Word properties that affect inference:
@ -63,6 +66,13 @@ SYMBOL: d-in
d-in get length object <repeated> >list d-in get length object <repeated> >list
meta-d get length object <repeated> >list 2list ; meta-d get length object <repeated> >list 2list ;
: no-base-case ( word -- )
{
"The base case of a recursive word could not be inferred.\n"
"This means the word calls itself in every control flow path.\n"
"See the handbook for details."
} concat inference-error ;
: init-inference ( recursive-state -- ) : init-inference ( recursive-state -- )
init-interpreter init-interpreter
{ } clone d-in set { } clone d-in set
@ -89,25 +99,14 @@ M: wrapper apply-object wrapped apply-literal ;
#! Ignore this branch's stack effect. #! Ignore this branch's stack effect.
meta-d off meta-r off d-in off ; meta-d off meta-r off d-in off ;
: terminator? ( obj -- ? )
#! Does it throw an error?
dup word? [ "terminator" word-prop ] [ drop f ] ifte ;
: handle-terminator ( quot -- )
#! If the quotation throws an error, do not count its stack
#! effect.
[ terminator? ] contains? [ terminate ] when ;
: infer-quot ( quot -- ) : infer-quot ( quot -- )
#! Recursive calls to this word are made for nested #! Recursive calls to this word are made for nested
#! quotations. #! quotations.
[ active? [ apply-object t ] [ drop f ] ifte ] all? drop ; [ active? [ apply-object t ] [ drop f ] ifte ] all? drop ;
: infer-quot-value ( rstate quot -- ) : infer-quot-value ( rstate quot -- )
recursive-state get >r recursive-state get >r swap recursive-state set
swap recursive-state set infer-quot r> recursive-state set ;
dup infer-quot handle-terminator
r> recursive-state set ;
: check-return ( -- ) : check-return ( -- )
#! Raise an error if word leaves values on return stack. #! Raise an error if word leaves values on return stack.
@ -120,6 +119,7 @@ M: wrapper apply-object wrapped apply-literal ;
: with-infer ( quot -- ) : with-infer ( quot -- )
[ [
inferring-base-case off inferring-base-case off
[ no-base-case ] base-case-continuation set
f init-inference f init-inference
call call
check-return check-return

View File

@ -4,25 +4,42 @@ io-internals kernel kernel-internals lists math math-internals
memory parser sequences strings vectors words prettyprint ; memory parser sequences strings vectors words prettyprint ;
! Primitive combinators ! Primitive combinators
\ call [ [ general-list ] [ ] ] "infer-effect" set-word-prop
\ call [ \ call [
pop-literal infer-quot-value pop-literal infer-quot-value
] "infer" set-word-prop ] "infer" set-word-prop
\ execute [ [ word ] [ ] ] "infer-effect" set-word-prop
\ execute [ \ execute [
pop-literal unit infer-quot-value pop-literal unit infer-quot-value
] "infer" set-word-prop ] "infer" set-word-prop
\ ifte [ [ object general-list general-list ] [ ] ] "infer-effect" set-word-prop
\ ifte [ \ ifte [
2 #drop node, pop-d pop-d swap 2vector 2 #drop node, pop-d pop-d swap 2vector
#ifte pop-d drop infer-branches #ifte pop-d drop infer-branches
] "infer" set-word-prop ] "infer" set-word-prop
\ cond [ [ object ] [ ] ] "infer-effect" set-word-prop
\ cond [
pop-literal [ 2unseq cons ] map
[ no-cond ] swap alist>quot infer-quot-value
] "infer" set-word-prop
\ dispatch [ [ fixnum vector ] [ ] ] "infer-effect" set-word-prop
\ dispatch [ \ dispatch [
pop-literal nip [ <literal> ] map pop-literal nip [ <literal> ] map
#dispatch pop-d drop infer-branches #dispatch pop-d drop infer-branches
] "infer" set-word-prop ] "infer" set-word-prop
! Stack manipulation ! Stack manipulation
\ >r [ [ object ] [ ] ] "infer-effect" set-word-prop
\ >r [ \ >r [
\ >r #call \ >r #call
1 0 pick node-inputs 1 0 pick node-inputs
@ -31,6 +48,8 @@ memory parser sequences strings vectors words prettyprint ;
node, node,
] "infer" set-word-prop ] "infer" set-word-prop
\ r> [ [ ] [ object ] ] "infer-effect" set-word-prop
\ r> [ \ r> [
\ r> #call \ r> #call
0 1 pick node-inputs 0 1 pick node-inputs
@ -40,57 +59,25 @@ memory parser sequences strings vectors words prettyprint ;
] "infer" set-word-prop ] "infer" set-word-prop
\ drop [ 1 #drop node, pop-d drop ] "infer" set-word-prop \ drop [ 1 #drop node, pop-d drop ] "infer" set-word-prop
\ dup [ \ dup infer-shuffle ] "infer" set-word-prop \ drop [ [ object ] [ ] ] "infer-effect" set-word-prop
\ swap [ \ swap infer-shuffle ] "infer" set-word-prop
\ over [ \ over infer-shuffle ] "infer" set-word-prop
\ pick [ \ pick infer-shuffle ] "infer" set-word-prop
! These hacks will go away soon \ dup [ \ dup infer-shuffle ] "infer" set-word-prop
\ delegate [ [ object ] [ object ] ] "infer-effect" set-word-prop \ dup [ [ object ] [ object object ] ] "infer-effect" set-word-prop
\ no-method t "terminator" set-word-prop
\ no-method [ [ object word ] [ ] ] "infer-effect" set-word-prop \ swap [ \ swap infer-shuffle ] "infer" set-word-prop
\ <no-method> [ [ object object ] [ tuple ] ] "infer-effect" set-word-prop \ swap [ [ object object ] [ object object ] ] "infer-effect" set-word-prop
\ set-no-method-generic [ [ object tuple ] [ ] ] "infer-effect" set-word-prop
\ set-no-method-object [ [ object tuple ] [ ] ] "infer-effect" set-word-prop \ over [ \ over infer-shuffle ] "infer" set-word-prop
\ no-math-method t "terminator" set-word-prop \ over [ [ object object ] [ object object object ] ] "infer-effect" set-word-prop
\ not-a-number t "terminator" set-word-prop
\ inference-error t "terminator" set-word-prop \ pick [ \ pick infer-shuffle ] "infer" set-word-prop
\ throw t "terminator" set-word-prop \ pick [ [ object object object ] [ object object object object ] ] "infer-effect" set-word-prop
\ = [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop
\ hash-contained? [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop ! Non-standard control flow
\ gcd [ [ integer integer ] [ integer integer ] ] "infer-effect" set-word-prop \ throw [ [ object ] [ ] ] "infer-effect" set-word-prop
\ car [ [ general-list ] [ object ] ] "infer-effect" set-word-prop \ throw [ terminate ] "infer" set-word-prop
\ cdr [ [ general-list ] [ object ] ] "infer-effect" set-word-prop
\ < [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
\ <= [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
\ > [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
\ >= [ [ real real ] [ boolean ] ] "infer-effect" set-word-prop
\ number= [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop
\ + [ [ number number ] [ number ] ] "infer-effect" set-word-prop
\ - [ [ number number ] [ number ] ] "infer-effect" set-word-prop
\ * [ [ number number ] [ number ] ] "infer-effect" set-word-prop
\ / [ [ number number ] [ number ] ] "infer-effect" set-word-prop
\ /i [ [ number number ] [ number ] ] "infer-effect" set-word-prop
\ /f [ [ number number ] [ number ] ] "infer-effect" set-word-prop
\ mod [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
\ /mod [ [ integer integer ] [ integer integer ] ] "infer-effect" set-word-prop
\ bitand [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
\ bitor [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
\ bitxor [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
\ shift [ [ integer integer ] [ integer ] ] "infer-effect" set-word-prop
\ bitnot [ [ integer ] [ integer ] ] "infer-effect" set-word-prop
\ real [ [ number ] [ real ] ] "infer-effect" set-word-prop
\ imaginary [ [ number ] [ real ] ] "infer-effect" set-word-prop
! Stack effects for all primitives ! Stack effects for all primitives
\ execute [ [ word ] [ ] ] "infer-effect" set-word-prop
\ call [ [ general-list ] [ ] ] "infer-effect" set-word-prop
\ ifte [ [ object general-list general-list ] [ ] ] "infer-effect" set-word-prop
\ dispatch [ [ fixnum vector ] [ ] ] "infer-effect" set-word-prop
\ cons [ [ object object ] [ cons ] ] "infer-effect" set-word-prop \ cons [ [ object object ] [ cons ] ] "infer-effect" set-word-prop
\ cons t "foldable" set-word-prop \ cons t "foldable" set-word-prop
\ cons t "flushable" set-word-prop \ cons t "flushable" set-word-prop
@ -371,13 +358,6 @@ memory parser sequences strings vectors words prettyprint ;
\ update-xt [ [ word ] [ ] ] "infer-effect" set-word-prop \ update-xt [ [ word ] [ ] ] "infer-effect" set-word-prop
\ compiled? [ [ word ] [ boolean ] ] "infer-effect" set-word-prop \ compiled? [ [ word ] [ boolean ] ] "infer-effect" set-word-prop
\ drop [ [ object ] [ ] ] "infer-effect" set-word-prop
\ dup [ [ object ] [ object object ] ] "infer-effect" set-word-prop
\ swap [ [ object object ] [ object object ] ] "infer-effect" set-word-prop
\ over [ [ object object ] [ object object object ] ] "infer-effect" set-word-prop
\ pick [ [ object object object ] [ object object object object ] ] "infer-effect" set-word-prop
\ >r [ [ object ] [ ] ] "infer-effect" set-word-prop
\ r> [ [ ] [ object ] ] "infer-effect" set-word-prop
\ eq? [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop \ eq? [ [ object object ] [ boolean ] ] "infer-effect" set-word-prop
\ eq? t "flushable" set-word-prop \ eq? t "flushable" set-word-prop
@ -395,6 +375,7 @@ memory parser sequences strings vectors words prettyprint ;
\ os-env [ [ string ] [ object ] ] "infer-effect" set-word-prop \ os-env [ [ string ] [ object ] ] "infer-effect" set-word-prop
\ millis [ [ ] [ integer ] ] "infer-effect" set-word-prop \ millis [ [ ] [ integer ] ] "infer-effect" set-word-prop
\ (random-int) [ [ ] [ integer ] ] "infer-effect" set-word-prop \ (random-int) [ [ ] [ integer ] ] "infer-effect" set-word-prop
\ type [ [ object ] [ fixnum ] ] "infer-effect" set-word-prop \ type [ [ object ] [ fixnum ] ] "infer-effect" set-word-prop
\ type t "flushable" set-word-prop \ type t "flushable" set-word-prop
\ type t "foldable" set-word-prop \ type t "foldable" set-word-prop
@ -484,7 +465,6 @@ memory parser sequences strings vectors words prettyprint ;
\ alien-c-string t "flushable" set-word-prop \ alien-c-string t "flushable" set-word-prop
\ set-alien-c-string [ [ string c-ptr integer ] [ ] ] "infer-effect" set-word-prop \ set-alien-c-string [ [ string c-ptr integer ] [ ] ] "infer-effect" set-word-prop
\ throw [ [ object ] [ ] ] "infer-effect" set-word-prop
\ string>memory [ [ string integer ] [ ] ] "infer-effect" set-word-prop \ string>memory [ [ string integer ] [ ] ] "infer-effect" set-word-prop
\ memory>string [ [ integer integer ] [ string ] ] "infer-effect" set-word-prop \ memory>string [ [ integer integer ] [ string ] ] "infer-effect" set-word-prop
\ alien-address [ [ alien ] [ integer ] ] "infer-effect" set-word-prop \ alien-address [ [ alien ] [ integer ] ] "infer-effect" set-word-prop

View File

@ -112,7 +112,7 @@ M: symbol apply-object ( word -- )
nip consume/produce nip consume/produce
] [ ] [
inferring-base-case get [ inferring-base-case get [
2drop terminate t base-case-continuation get call
] [ ] [
car base-case car base-case
] ifte ] ifte

View File

@ -5,7 +5,7 @@ USING: errors generic kernel math namespaces sequences strings ;
! Number parsing ! Number parsing
: not-a-number "Not a number" throw ; : not-a-number "Not a number" throw ; inline
GENERIC: digit> ( ch -- n ) GENERIC: digit> ( ch -- n )
M: digit digit> CHAR: 0 - ; M: digit digit> CHAR: 0 - ;

View File

@ -1,4 +1,5 @@
IN: temporary IN: temporary
USING: alien strings ;
USE: compiler USE: compiler
USE: test USE: test
USE: math USE: math
@ -94,3 +95,32 @@ DEFER: countdown-b
[ 3 ] [ f dummy-unless-3 ] unit-test [ 3 ] [ f dummy-unless-3 ] unit-test
[ 4 ] [ 4 dummy-unless-3 ] unit-test [ 4 ] [ 4 dummy-unless-3 ] unit-test
[ "even" ] [
[
2 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] compile-1
] unit-test
[ "odd" ] [
[
3 {
{ [ dup 2 mod 0 = ] [ drop "even" ] }
{ [ dup 2 mod 1 = ] [ drop "odd" ] }
} cond
] compile-1
] unit-test
[ "neither" ] [
[
3 {
{ [ dup string? ] [ drop "string" ] }
{ [ dup float? ] [ drop "float" ] }
{ [ dup alien? ] [ drop "alien" ] }
{ [ t ] [ drop "neither" ] }
} cond
] compile-1
] unit-test

View File

@ -155,9 +155,11 @@ DEFER: agent
[ [ [ ] [ object object ] ] ] [ [ [ ] [ object object ] ] ]
[ [ [ drop ] 0 agent ] infer ] unit-test [ [ [ drop ] 0 agent ] infer ] unit-test
! : no-base-case dup [ no-base-case ] [ no-base-case ] ifte ; : no-base-case-1 dup [ no-base-case-1 ] [ no-base-case-1 ] ifte ;
! [ [ no-base-case-1 ] infer ] unit-test-fails
! [ [ no-base-case ] infer simple-effect ] unit-test-fails
: no-base-case-2 no-base-case-2 ;
[ [ no-base-case-2 ] infer ] unit-test-fails
[ { 2 1 } ] [ [ 2vector ] infer simple-effect ] unit-test [ { 2 1 } ] [ [ 2vector ] infer simple-effect ] unit-test
[ { 3 1 } ] [ [ 3vector ] infer simple-effect ] unit-test [ { 3 1 } ] [ [ 3vector ] infer simple-effect ] unit-test

View File

@ -76,12 +76,11 @@ sequences strings unparser vectors words ;
#! required word info. #! required word info.
dup [ dup [
[ [
"vocabulary" dup definer ,
"name" dup word-vocabulary ,
"stack-effect" dup word-name ,
] [ "stack-effect" word-prop ,
dupd word-prop ] [ ] make
] map >r definer r> cons
] when ; ] when ;
: completions ( str pred -- list | pred: str word -- ? ) : completions ( str pred -- list | pred: str word -- ? )