Fix locals with smart combinator macros, document that locals work with macros now
parent
47cb866891
commit
19c5317d97
|
@ -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."
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue