Fixing some problems with the locals implementation:
- Smart combinators now work with wlet words - Expansion no longer usees >r/r> - Hook into fry so that fry and locals can work as expected - Document limitations of locals with macros in more detail, remove mention of >r/r> limitation since those two words are going away anywaydb4
parent
a3231c5a4e
commit
a729e72b7e
|
@ -1,5 +1,5 @@
|
||||||
USING: help.syntax help.markup kernel macros prettyprint
|
USING: help.syntax help.markup kernel macros prettyprint
|
||||||
memoize combinators arrays ;
|
memoize combinators arrays generalizations ;
|
||||||
IN: locals
|
IN: locals
|
||||||
|
|
||||||
HELP: [|
|
HELP: [|
|
||||||
|
@ -131,10 +131,40 @@ $nl
|
||||||
$nl
|
$nl
|
||||||
"Unlike some languages such as Python and Java, writing to mutable locals in outer scopes is fully supported and has the expected semantics." ;
|
"Unlike some languages such as Python and Java, writing to mutable locals in outer scopes is fully supported and has the expected semantics." ;
|
||||||
|
|
||||||
|
ARTICLE: "locals-fry" "Locals and fry"
|
||||||
|
"Locals integrate with " { $link "fry" } " so that mixing locals with fried quotations gives intuitive results."
|
||||||
|
$nl
|
||||||
|
"Recall that the following two code snippets are equivalent:"
|
||||||
|
{ $code "'[ sq _ + ]" }
|
||||||
|
{ $code "[ [ sq ] dip + ] curry" }
|
||||||
|
"The semantics of " { $link dip } " and " { $link curry } " are such that the first example behaves as if the top of the stack as ``inserted'' in the ``hole'' in the quotation's second element."
|
||||||
|
$nl
|
||||||
|
"Conceptually, " { $link curry } " is defined so that the following two code snippets are equivalent:"
|
||||||
|
{ $code "3 [ - ] curry" }
|
||||||
|
{ $code "[ 3 - ]" }
|
||||||
|
"With lambdas, " { $link curry } " behaves differently. Rather than prepending an element, it fills in named parameters from right to left. The following two snippets are equivalent:"
|
||||||
|
{ $code "3 [| a b | a b - ] curry" }
|
||||||
|
{ $code "[| a | a 3 - ]" }
|
||||||
|
"Because of this, the behavior of fry changes when applied to a lambda, to ensure that conceptually, fry behaves as with quotations. So the following snippets are no longer equivalent:"
|
||||||
|
{ $code "'[ [| a | _ a - ] ]" }
|
||||||
|
{ $code "'[ [| a | a - ] curry ] call" }
|
||||||
|
"Instead, the first line above expands into something like the following:"
|
||||||
|
{ $code "[ [ swap [| a | a - ] ] curry call ]" }
|
||||||
|
"This ensures that the fried value appears ``underneath'' the local variable " { $snippet "a" } " when the quotation calls."
|
||||||
|
$nl
|
||||||
|
"The precise behavior is the following. When frying a lambda, a stack shuffle (" { $link mnswap } ") is prepended to the lambda so that the " { $snippet "m" } " curried values, which start off at the top of the stack, are transposed with the " { $snippet "n" } " inputs to the lambda." ;
|
||||||
|
|
||||||
ARTICLE: "locals-limitations" "Limitations of locals"
|
ARTICLE: "locals-limitations" "Limitations of locals"
|
||||||
"The first limitation is also shared by " { $vocab-link "fry" } ": the " { $link >r } " and " { $link r> } " words may not be used together with locals. Instead, use the " { $link dip } " combinator. An error is thrown at parse time if an attempt is made to use " { $link >r } " and " { $link r> } " inside a lambda body:"
|
"There are two main limitations of the current locals implementation, and both concern macros."
|
||||||
{ $subsection >r/r>-in-lambda-error }
|
{ $heading "Macro expansions with free variables" }
|
||||||
"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:"
|
"The expansion of a macro cannot reference local variables bound in the outer scope. For example, the following macro is invalid:"
|
||||||
|
{ $code "MACRO:: twice ( quot -- ) [ quot call quot call ] ;" }
|
||||||
|
"The following is fine, though:"
|
||||||
|
{ $code "MACRO:: twice ( quot -- ) quot quot '[ @ @ ] ;" }
|
||||||
|
{ $heading "Static stack effect inference and macros" }
|
||||||
|
"Recall that a macro will only expand at compile-time, and the word containing it will only get a static stack effect, if all inputs to the macro are literal. When locals are used, there is an additional restriction; the literals must immediately precede the macro call, lexically."
|
||||||
|
$nl
|
||||||
|
"For example, all of the following three examples are equivalent semantically, but only the first will have a static stack effect and compile with the optimizing compiler:"
|
||||||
{ $code
|
{ $code
|
||||||
":: good-cond-usage ( a -- ... )"
|
":: good-cond-usage ( a -- ... )"
|
||||||
" {"
|
" {"
|
||||||
|
@ -143,7 +173,7 @@ ARTICLE: "locals-limitations" "Limitations of locals"
|
||||||
" { [ a 0 = ] [ ... ] }"
|
" { [ a 0 = ] [ ... ] }"
|
||||||
" } cond ;"
|
" } cond ;"
|
||||||
}
|
}
|
||||||
"But not the following:"
|
"The following two will not, and will run slower as a result:"
|
||||||
{ $code
|
{ $code
|
||||||
": my-cond ( alist -- ) cond ; inline"
|
": my-cond ( alist -- ) cond ; inline"
|
||||||
""
|
""
|
||||||
|
@ -154,6 +184,14 @@ ARTICLE: "locals-limitations" "Limitations of locals"
|
||||||
" { [ a 0 = ] [ ... ] }"
|
" { [ a 0 = ] [ ... ] }"
|
||||||
" } my-cond ;"
|
" } my-cond ;"
|
||||||
}
|
}
|
||||||
|
{ $code
|
||||||
|
":: bad-cond-usage ( a -- ... )"
|
||||||
|
" {"
|
||||||
|
" { [ a 0 < ] [ ... ] }"
|
||||||
|
" { [ a 0 > ] [ ... ] }"
|
||||||
|
" { [ a 0 = ] [ ... ] }"
|
||||||
|
" } swap swap 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." ;
|
"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"
|
||||||
|
@ -174,6 +212,7 @@ $nl
|
||||||
"Additional topics:"
|
"Additional topics:"
|
||||||
{ $subsection "locals-literals" }
|
{ $subsection "locals-literals" }
|
||||||
{ $subsection "locals-mutable" }
|
{ $subsection "locals-mutable" }
|
||||||
|
{ $subsection "locals-fry" }
|
||||||
{ $subsection "locals-limitations" }
|
{ $subsection "locals-limitations" }
|
||||||
"Locals complement dynamically scoped variables implemented in the " { $vocab-link "namespaces" } " vocabulary." ;
|
"Locals complement dynamically scoped variables implemented in the " { $vocab-link "namespaces" } " vocabulary." ;
|
||||||
|
|
||||||
|
|
|
@ -398,7 +398,7 @@ M:: integer lambda-method-forget-test ( a -- b ) ;
|
||||||
|
|
||||||
[ ] [ [ { integer lambda-method-forget-test } forget ] with-compilation-unit ] unit-test
|
[ ] [ [ { integer lambda-method-forget-test } forget ] with-compilation-unit ] unit-test
|
||||||
|
|
||||||
[ { [ 10 ] } ] [ 10 [| A | { [ A ] } ] call ] unit-test
|
[ 10 ] [ 10 [| A | { [ A ] } ] call first call ] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
"USING: locals fry math ; [ 0 '[ [let | A [ 10 ] | A _ + ] ] ]" eval
|
"USING: locals fry math ; [ 0 '[ [let | A [ 10 ] | A _ + ] ] ]" eval
|
||||||
|
@ -431,14 +431,53 @@ M:: integer lambda-method-forget-test ( a -- b ) ;
|
||||||
|
|
||||||
[ 3 ] [ 3 [| a | \ a ] call ] unit-test
|
[ 3 ] [ 3 [| a | \ a ] call ] unit-test
|
||||||
|
|
||||||
! :: wlet-&&-test ( a -- ? )
|
[ "USE: locals [| | { [let | a [ 0 ] | a ] } ]" eval ] must-fail
|
||||||
! [wlet | is-integer? [ a integer? ]
|
|
||||||
! is-even? [ a even? ]
|
|
||||||
! >10? [ a 10 > ] |
|
|
||||||
! { [ is-integer? ] [ is-even? ] [ >10? ] } &&
|
|
||||||
! ] ;
|
|
||||||
|
|
||||||
! [ f ] [ 1.5 wlet-&&-test ] unit-test
|
[ "USE: locals [| | { [wlet | a [ 0 ] | a ] } ]" eval ] must-fail
|
||||||
! [ f ] [ 3 wlet-&&-test ] unit-test
|
|
||||||
! [ f ] [ 8 wlet-&&-test ] unit-test
|
[ "USE: locals [| | { [let* | a [ 0 ] | a ] } ]" eval ] must-fail
|
||||||
! [ t ] [ 12 wlet-&&-test ] unit-test
|
|
||||||
|
[ "USE: locals [| | [let | a! [ 0 ] | { a! } ] ]" eval ] must-fail
|
||||||
|
|
||||||
|
[ "USE: locals [| | [wlet | a [ 0 ] | { a } ] ]" eval ] must-fail
|
||||||
|
|
||||||
|
:: wlet-&&-test ( a -- ? )
|
||||||
|
[wlet | is-integer? [ a integer? ]
|
||||||
|
is-even? [ a even? ]
|
||||||
|
>10? [ a 10 > ] |
|
||||||
|
{ [ is-integer? ] [ is-even? ] [ >10? ] } &&
|
||||||
|
] ;
|
||||||
|
|
||||||
|
\ wlet-&&-test must-infer
|
||||||
|
[ 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
|
||||||
|
|
||||||
|
: fry-locals-test-1 ( -- n )
|
||||||
|
[let | | 6 '[ [let | A [ 4 ] | A _ + ] ] call ] ;
|
||||||
|
|
||||||
|
\ fry-locals-test-1 must-infer
|
||||||
|
[ 10 ] [ fry-locals-test-1 ] unit-test
|
||||||
|
|
||||||
|
:: fry-locals-test-2 ( -- n )
|
||||||
|
[let | | 6 '[ [let | A [ 4 ] | A _ + ] ] call ] ;
|
||||||
|
|
||||||
|
\ fry-locals-test-2 must-infer
|
||||||
|
[ 10 ] [ fry-locals-test-2 ] unit-test
|
||||||
|
|
||||||
|
[ 1 ] [ 3 4 [| | '[ [ _ swap - ] call ] call ] call ] unit-test
|
||||||
|
[ -1 ] [ 3 4 [| | [| a | a - ] call ] call ] unit-test
|
||||||
|
[ -1 ] [ 3 4 [| | [| a | a - ] curry call ] call ] unit-test
|
||||||
|
[ -1 ] [ 3 4 [| a | a - ] curry call ] unit-test
|
||||||
|
[ 1 ] [ 3 4 [| | '[ [| a | _ a - ] call ] call ] call ] unit-test
|
||||||
|
[ -1 ] [ 3 4 [| | '[ [| a | a _ - ] call ] call ] call ] unit-test
|
||||||
|
|
||||||
|
[ { 1 2 3 4 } ] [
|
||||||
|
1 3 2 4
|
||||||
|
[| | '[ [| a b | a _ b _ 4array ] call ] call ] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ 10 ] [
|
||||||
|
[| | 0 '[ [let | A [ 10 ] | A _ + ] ] call ] call
|
||||||
|
] unit-test
|
|
@ -6,18 +6,36 @@ quotations debugger macros arrays macros splitting combinators
|
||||||
prettyprint.backend definitions prettyprint hashtables
|
prettyprint.backend definitions prettyprint hashtables
|
||||||
prettyprint.sections sets sequences.private effects
|
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 classes summary ;
|
locals.backend memoize macros.expander lexer classes summary fry
|
||||||
|
fry.private ;
|
||||||
IN: locals
|
IN: locals
|
||||||
|
|
||||||
! Inspired by
|
|
||||||
! http://cat-language.googlecode.com/svn/trunk/CatPointFreeForm.cs
|
|
||||||
|
|
||||||
ERROR: >r/r>-in-lambda-error ;
|
ERROR: >r/r>-in-lambda-error ;
|
||||||
|
|
||||||
M: >r/r>-in-lambda-error summary
|
M: >r/r>-in-lambda-error summary
|
||||||
drop
|
drop
|
||||||
"Explicit retain stack manipulation is not permitted in lambda bodies" ;
|
"Explicit retain stack manipulation is not permitted in lambda bodies" ;
|
||||||
|
|
||||||
|
ERROR: binding-form-in-literal-error ;
|
||||||
|
|
||||||
|
M: binding-form-in-literal-error summary
|
||||||
|
drop "[let, [let* and [wlet not permitted inside literals" ;
|
||||||
|
|
||||||
|
ERROR: local-writer-in-literal-error ;
|
||||||
|
|
||||||
|
M: local-writer-in-literal-error summary
|
||||||
|
drop "Local writer words not permitted inside literals" ;
|
||||||
|
|
||||||
|
ERROR: local-word-in-literal-error ;
|
||||||
|
|
||||||
|
M: local-word-in-literal-error summary
|
||||||
|
drop "Local words not permitted inside literals" ;
|
||||||
|
|
||||||
|
ERROR: bad-lambda-rewrite output ;
|
||||||
|
|
||||||
|
M: bad-lambda-rewrite summary
|
||||||
|
drop "You have found a bug in locals. Please report." ;
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
TUPLE: lambda vars body ;
|
TUPLE: lambda vars body ;
|
||||||
|
@ -87,45 +105,40 @@ C: <quote> quote
|
||||||
: read-local-quot ( obj args -- quot )
|
: read-local-quot ( obj args -- quot )
|
||||||
local-index 1+ [ get-local ] curry ;
|
local-index 1+ [ get-local ] curry ;
|
||||||
|
|
||||||
: localize-writer ( obj args -- quot )
|
GENERIC# localize 1 ( obj args -- quot )
|
||||||
>r "local-reader" word-prop r>
|
|
||||||
|
M: local localize read-local-quot ;
|
||||||
|
|
||||||
|
M: quote localize [ local>> ] dip read-local-quot ;
|
||||||
|
|
||||||
|
M: local-word localize read-local-quot [ call ] append ;
|
||||||
|
|
||||||
|
M: local-reader localize read-local-quot [ local-value ] append ;
|
||||||
|
|
||||||
|
M: local-writer localize
|
||||||
|
[ "local-reader" word-prop ] dip
|
||||||
read-local-quot [ set-local-value ] append ;
|
read-local-quot [ set-local-value ] append ;
|
||||||
|
|
||||||
: localize ( obj args -- quot )
|
M: object localize drop 1quotation ;
|
||||||
{
|
|
||||||
{ [ over local? ] [ read-local-quot ] }
|
|
||||||
{ [ over quote? ] [ >r local>> r> read-local-quot ] }
|
|
||||||
{ [ over local-word? ] [ read-local-quot [ call ] append ] }
|
|
||||||
{ [ over local-reader? ] [ read-local-quot [ local-value ] append ] }
|
|
||||||
{ [ over local-writer? ] [ localize-writer ] }
|
|
||||||
{ [ over \ lambda eq? ] [ 2drop [ ] ] }
|
|
||||||
{ [ t ] [ drop 1quotation ] }
|
|
||||||
} cond ;
|
|
||||||
|
|
||||||
UNION: special local quote local-word local-reader local-writer ;
|
UNION: special local quote local-word local-reader local-writer ;
|
||||||
|
|
||||||
: load-locals-quot ( args -- quot )
|
: load-locals-quot ( args -- quot )
|
||||||
[
|
[ [ ] ] [
|
||||||
[ ]
|
|
||||||
] [
|
|
||||||
dup [ local-reader? ] contains? [
|
dup [ local-reader? ] contains? [
|
||||||
<reversed> [
|
dup [ local-reader? [ 1array ] [ ] ? ] map spread>quot
|
||||||
local-reader? [ 1array >r ] [ >r ] ?
|
] [ [ ] ] if swap length [ load-locals ] curry append
|
||||||
] map concat
|
|
||||||
] [
|
|
||||||
length [ load-locals ] curry >quotation
|
|
||||||
] if
|
|
||||||
] if-empty ;
|
] if-empty ;
|
||||||
|
|
||||||
: drop-locals-quot ( args -- quot )
|
: drop-locals-quot ( args -- quot )
|
||||||
[ [ ] ] [ length [ drop-locals ] curry ] if-empty ;
|
[ [ ] ] [ length [ drop-locals ] curry ] if-empty ;
|
||||||
|
|
||||||
: point-free-body ( quot args -- newquot )
|
: point-free-body ( quot args -- newquot )
|
||||||
>r but-last-slice r> [ localize ] curry map concat ;
|
[ but-last-slice ] dip '[ _ localize ] map concat ;
|
||||||
|
|
||||||
: point-free-end ( quot args -- newquot )
|
: point-free-end ( quot args -- newquot )
|
||||||
over peek special?
|
over peek special?
|
||||||
[ dup drop-locals-quot >r >r peek r> localize r> append ]
|
[ dup drop-locals-quot [ [ peek ] dip localize ] dip append ]
|
||||||
[ dup drop-locals-quot nip swap peek suffix ]
|
[ dup drop-locals-quot nip swap peek suffix ]
|
||||||
if ;
|
if ;
|
||||||
|
|
||||||
|
@ -227,9 +240,6 @@ GENERIC: rewrite-element ( obj -- )
|
||||||
M: array rewrite-element
|
M: array rewrite-element
|
||||||
dup rewrite-literal? [ rewrite-sequence ] [ , ] if ;
|
dup rewrite-literal? [ rewrite-sequence ] [ , ] if ;
|
||||||
|
|
||||||
M: quotation rewrite-element
|
|
||||||
dup rewrite-literal? [ rewrite-sequence ] [ , ] if ;
|
|
||||||
|
|
||||||
M: vector rewrite-element rewrite-sequence ;
|
M: vector rewrite-element rewrite-sequence ;
|
||||||
|
|
||||||
M: hashtable rewrite-element >alist rewrite-sequence \ >hashtable , ;
|
M: hashtable rewrite-element >alist rewrite-sequence \ >hashtable , ;
|
||||||
|
@ -237,12 +247,22 @@ M: hashtable rewrite-element >alist rewrite-sequence \ >hashtable , ;
|
||||||
M: tuple rewrite-element
|
M: tuple rewrite-element
|
||||||
[ tuple-slots rewrite-elements ] [ class literalize , ] bi \ boa , ;
|
[ tuple-slots rewrite-elements ] [ class literalize , ] bi \ boa , ;
|
||||||
|
|
||||||
|
M: quotation rewrite-element local-rewrite* ;
|
||||||
|
|
||||||
M: lambda rewrite-element local-rewrite* ;
|
M: lambda rewrite-element local-rewrite* ;
|
||||||
|
|
||||||
|
M: binding-form rewrite-element binding-form-in-literal-error ;
|
||||||
|
|
||||||
M: local rewrite-element , ;
|
M: local rewrite-element , ;
|
||||||
|
|
||||||
M: local-reader rewrite-element , ;
|
M: local-reader rewrite-element , ;
|
||||||
|
|
||||||
|
M: local-writer rewrite-element
|
||||||
|
local-writer-in-literal-error ;
|
||||||
|
|
||||||
|
M: local-word rewrite-element
|
||||||
|
local-word-in-literal-error ;
|
||||||
|
|
||||||
M: word rewrite-element literalize , ;
|
M: word rewrite-element literalize , ;
|
||||||
|
|
||||||
M: wrapper rewrite-element
|
M: wrapper rewrite-element
|
||||||
|
@ -278,8 +298,9 @@ M: object local-rewrite* , ;
|
||||||
: make-locals ( seq -- words assoc )
|
: make-locals ( seq -- words assoc )
|
||||||
[ [ make-local ] map ] H{ } make-assoc ;
|
[ [ make-local ] map ] H{ } make-assoc ;
|
||||||
|
|
||||||
: make-local-word ( name -- word )
|
: make-local-word ( name def -- word )
|
||||||
<local-word> dup dup name>> set ;
|
[ <local-word> [ dup name>> set ] [ ] [ ] tri ] dip
|
||||||
|
"local-word-def" set-word-prop ;
|
||||||
|
|
||||||
: push-locals ( assoc -- )
|
: push-locals ( assoc -- )
|
||||||
use get push ;
|
use get push ;
|
||||||
|
@ -328,7 +349,7 @@ SYMBOL: in-lambda?
|
||||||
|
|
||||||
: (parse-wbindings) ( -- )
|
: (parse-wbindings) ( -- )
|
||||||
parse-binding [
|
parse-binding [
|
||||||
first2 >r make-local-word r> 2array ,
|
first2 [ make-local-word ] keep 2array ,
|
||||||
(parse-wbindings)
|
(parse-wbindings)
|
||||||
] when* ;
|
] when* ;
|
||||||
|
|
||||||
|
@ -340,7 +361,7 @@ SYMBOL: in-lambda?
|
||||||
|
|
||||||
: let-rewrite ( body bindings -- )
|
: let-rewrite ( body bindings -- )
|
||||||
<reversed> [
|
<reversed> [
|
||||||
>r 1array r> spin <lambda> [ call ] curry compose
|
[ 1array ] dip spin <lambda> '[ @ @ ]
|
||||||
] assoc-each local-rewrite* \ call , ;
|
] assoc-each local-rewrite* \ call , ;
|
||||||
|
|
||||||
M: let local-rewrite*
|
M: let local-rewrite*
|
||||||
|
@ -351,7 +372,7 @@ M: let* local-rewrite*
|
||||||
|
|
||||||
M: wlet local-rewrite*
|
M: wlet local-rewrite*
|
||||||
[ body>> ] [ bindings>> ] bi
|
[ body>> ] [ bindings>> ] bi
|
||||||
[ [ ] curry ] assoc-map
|
[ '[ _ ] ] assoc-map
|
||||||
let-rewrite ;
|
let-rewrite ;
|
||||||
|
|
||||||
: parse-locals ( -- vars assoc )
|
: parse-locals ( -- vars assoc )
|
||||||
|
@ -359,11 +380,6 @@ M: wlet local-rewrite*
|
||||||
word [ over "declared-effect" set-word-prop ] when*
|
word [ over "declared-effect" set-word-prop ] when*
|
||||||
in>> [ dup pair? [ first ] when ] map make-locals dup push-locals ;
|
in>> [ dup pair? [ first ] when ] map make-locals dup push-locals ;
|
||||||
|
|
||||||
ERROR: bad-lambda-rewrite output ;
|
|
||||||
|
|
||||||
M: bad-lambda-rewrite summary
|
|
||||||
drop "You have found a bug in locals. Please report." ;
|
|
||||||
|
|
||||||
: parse-locals-definition ( word -- word quot )
|
: parse-locals-definition ( word -- word quot )
|
||||||
"(" expect parse-locals \ ; (parse-lambda) <lambda>
|
"(" expect parse-locals \ ; (parse-lambda) <lambda>
|
||||||
2dup "lambda" set-word-prop
|
2dup "lambda" set-word-prop
|
||||||
|
@ -431,7 +447,7 @@ M: lambda pprint*
|
||||||
\ | pprint-word
|
\ | pprint-word
|
||||||
t <inset
|
t <inset
|
||||||
<block
|
<block
|
||||||
[ <block >r pprint-var r> pprint* block> ] assoc-each
|
[ <block [ pprint-var ] dip pprint* block> ] assoc-each
|
||||||
block>
|
block>
|
||||||
\ | pprint-word
|
\ | pprint-word
|
||||||
<block pprint-elements block>
|
<block pprint-elements block>
|
||||||
|
@ -497,3 +513,15 @@ M: lambda-method synopsis*
|
||||||
method-stack-effect effect>string comment. ;
|
method-stack-effect effect>string comment. ;
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
|
! Locals and fry
|
||||||
|
M: binding-form count-inputs body>> count-inputs ;
|
||||||
|
|
||||||
|
M: lambda count-inputs body>> count-inputs ;
|
||||||
|
|
||||||
|
M: lambda deep-fry
|
||||||
|
clone [ shallow-fry swap ] change-body
|
||||||
|
[ [ vars>> length ] keep '[ _ _ mnswap @ ] , ] [ drop [ncurry] % ] 2bi ;
|
||||||
|
|
||||||
|
M: binding-form deep-fry
|
||||||
|
clone [ fry '[ @ call ] ] change-body , ;
|
||||||
|
|
Loading…
Reference in New Issue