Fix locals with smart combinator macros, document that locals work with macros now

db4
Slava Pestov 2008-08-26 20:40:34 -05:00
parent 47cb866891
commit 19c5317d97
3 changed files with 71 additions and 11 deletions

View File

@ -101,15 +101,27 @@ $nl
ARTICLE: "locals-limitations" "Limitations of locals" ARTICLE: "locals-limitations" "Limitations of locals"
"The first limitation is that the " { $link >r } " and " { $link r> } " words may not be used together with locals. Instead, use the " { $link dip } " combinator." "The first limitation is that the " { $link >r } " and " { $link r> } " words may not be used together with locals. Instead, use the " { $link dip } " combinator."
$nl $nl
"Another limitation is that closure conversion does not descend into arrays, hashtables or other types of literals. For example, the following does not work:" "Another limitation concerns combinators implemented as macros. Locals can only be used with such combinators if the input array immediately precedes the combinator call. For example, the following will work:"
{ $code { $code
":: bad-cond-usage ( a -- ... )" ":: good-cond-usage ( a -- ... )"
" {" " {"
" { [ a 0 < ] [ ... ] }" " { [ a 0 < ] [ ... ] }"
" { [ a 0 > ] [ ... ] }" " { [ a 0 > ] [ ... ] }"
" { [ a 0 = ] [ ... ] }" " { [ a 0 = ] [ ... ] }"
" } cond ;" " } cond ;"
} ; }
"But not the following:"
{ $code
": my-cond ( alist -- ) cond ; inline"
""
":: bad-cond-usage ( a -- ... )"
" {"
" { [ a 0 < ] [ ... ] }"
" { [ a 0 > ] [ ... ] }"
" { [ a 0 = ] [ ... ] }"
" } my-cond ;"
}
"The reason is that locals are rewritten into stack code at parse time, whereas macro expansion is performed later during compile time. To circumvent this problem, the " { $vocab-link "macros.expander" } " vocabulary is used to rewrite simple macro usages prior to local transformation, however "{ $vocab-link "macros.expander" } " does not deal with more complicated cases where the literal inputs to the macro do not immediately precede the macro call in the source." ;
ARTICLE: "locals" "Local variables and lexical closures" ARTICLE: "locals" "Local variables and lexical closures"
"The " { $vocab-link "locals" } " vocabulary implements lexical scope with full closures, both downward and upward. Mutable bindings are supported, including assignment to bindings in outer scope." "The " { $vocab-link "locals" } " vocabulary implements lexical scope with full closures, both downward and upward. Mutable bindings are supported, including assignment to bindings in outer scope."

View File

@ -1,6 +1,7 @@
USING: locals math sequences tools.test hashtables words kernel USING: locals math sequences tools.test hashtables words kernel
namespaces arrays strings prettyprint io.streams.string parser namespaces arrays strings prettyprint io.streams.string parser
accessors generic eval ; accessors generic eval combinators combinators.short-circuit
combinators.short-circuit.smart ;
IN: locals.tests IN: locals.tests
:: foo ( a b -- a a ) a a ; :: foo ( a b -- a a ) a a ;
@ -276,3 +277,42 @@ M:: sequence method-with-locals ( a -- y ) a reverse ;
[ \ sequence \ method-with-locals method see ] with-string-writer [ \ sequence \ method-with-locals method see ] with-string-writer
method-definition = method-definition =
] unit-test ] unit-test
:: cond-test ( a b -- c )
{
{ [ a b < ] [ 3 ] }
{ [ a b = ] [ 4 ] }
{ [ a b > ] [ 5 ] }
} cond ;
[ 3 ] [ 1 2 cond-test ] unit-test
[ 4 ] [ 2 2 cond-test ] unit-test
[ 5 ] [ 3 2 cond-test ] unit-test
:: 0&&-test ( a -- ? )
{ [ a integer? ] [ a even? ] [ a 10 > ] } 0&& ;
[ f ] [ 1.5 0&&-test ] unit-test
[ f ] [ 3 0&&-test ] unit-test
[ f ] [ 8 0&&-test ] unit-test
[ t ] [ 12 0&&-test ] unit-test
:: &&-test ( a -- ? )
{ [ a integer? ] [ a even? ] [ a 10 > ] } && ;
[ f ] [ 1.5 &&-test ] unit-test
[ f ] [ 3 &&-test ] unit-test
[ f ] [ 8 &&-test ] unit-test
[ t ] [ 12 &&-test ] unit-test
:: wlet-&&-test ( a -- ? )
[wlet | is-integer? [ a integer? ]
is-even? [ a even? ]
>10? [ a 10 > ] |
{ [ is-integer? ] [ is-even? ] [ >10? ] } &&
] ;
! [ f ] [ 1.5 wlet-&&-test ] unit-test
! [ f ] [ 3 wlet-&&-test ] unit-test
! [ f ] [ 8 wlet-&&-test ] unit-test
! [ t ] [ 12 wlet-&&-test ] unit-test

View File

@ -5,7 +5,8 @@ parser words quotations debugger macros arrays macros splitting
combinators prettyprint.backend definitions prettyprint combinators prettyprint.backend definitions prettyprint
hashtables prettyprint.sections sets sequences.private effects hashtables prettyprint.sections sets sequences.private effects
effects.parser generic generic.parser compiler.units accessors effects.parser generic generic.parser compiler.units accessors
locals.backend memoize macros.expander lexer ; locals.backend memoize macros.expander lexer
stack-checker.known-words ;
IN: locals IN: locals
! Inspired by ! Inspired by
@ -42,7 +43,9 @@ PREDICATE: local < word "local?" word-prop ;
: <local> ( name -- word ) : <local> ( name -- word )
#! Create a local variable identifier #! Create a local variable identifier
f <word> dup t "local?" set-word-prop ; f <word>
dup t "local?" set-word-prop
dup { } { object } define-primitive ;
PREDICATE: local-word < word "local-word?" word-prop ; PREDICATE: local-word < word "local-word?" word-prop ;
@ -52,15 +55,20 @@ PREDICATE: local-word < word "local-word?" word-prop ;
PREDICATE: local-reader < word "local-reader?" word-prop ; PREDICATE: local-reader < word "local-reader?" word-prop ;
: <local-reader> ( name -- word ) : <local-reader> ( name -- word )
f <word> dup t "local-reader?" set-word-prop ; f <word>
dup t "local-reader?" set-word-prop
dup { } { object } define-primitive ;
PREDICATE: local-writer < word "local-writer?" word-prop ; PREDICATE: local-writer < word "local-writer?" word-prop ;
: <local-writer> ( reader -- word ) : <local-writer> ( reader -- word )
dup name>> "!" append f <word> dup name>> "!" append f <word> {
[ t "local-writer?" set-word-prop ] keep [ nip { object } { } define-primitive ]
[ "local-writer" set-word-prop ] 2keep [ nip t "local-writer?" set-word-prop ]
[ swap "local-reader" set-word-prop ] keep ; [ swap "local-reader" set-word-prop ]
[ "local-writer" set-word-prop ]
[ nip ]
} 2cleave ;
TUPLE: quote local ; TUPLE: quote local ;