2006-08-09 01:57:56 -04:00
|
|
|
#! A lambda expression manipulator, by Matthew Willis
|
|
|
|
USING: lazy-lists strings arrays hashtables
|
2006-08-21 00:35:06 -04:00
|
|
|
sequences namespaces words parser kernel ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
|
|
|
IN: lambda
|
|
|
|
|
2006-08-23 19:05:25 -04:00
|
|
|
: dip swap slip ; inline
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
TUPLE: lambda-node expr original canonical ;
|
2006-08-09 01:57:56 -04:00
|
|
|
TUPLE: apply-node func arg ;
|
|
|
|
TUPLE: variable-node var ;
|
2006-08-21 00:35:06 -04:00
|
|
|
TUPLE: alien-node word ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
|
|
|
DEFER: substitute
|
|
|
|
C: lambda-node ( var expr implicit-empty-lambda-node -- lambda-node )
|
|
|
|
#! store the expr, replacing every occurence of var with
|
|
|
|
#! a pointer to this lambda-node
|
2006-08-19 21:18:14 -04:00
|
|
|
[ <variable-node> -rot substitute ] 3keep nip swapd
|
|
|
|
[ set-lambda-node-expr ] keep
|
|
|
|
[ set-lambda-node-original ] keep ;
|
|
|
|
|
|
|
|
GENERIC: (traverse)
|
|
|
|
: (pre) ( data-array pre-post node -- data-array pre-post new-node )
|
|
|
|
[ swap first execute ] 3keep drop rot ;
|
|
|
|
|
|
|
|
: (post) ( data-array pre-post node -- new-node )
|
|
|
|
swap second execute ;
|
|
|
|
|
|
|
|
#! Traverses the tree while executing pre and post order words
|
2006-08-23 19:05:25 -04:00
|
|
|
M: lambda-node (traverse) ( data-array words lambda-node -- node )
|
2006-08-19 21:18:14 -04:00
|
|
|
(pre)
|
|
|
|
[ [ lambda-node-expr (traverse) ] keep set-lambda-node-expr ] 3keep
|
|
|
|
(post) ;
|
|
|
|
|
2006-08-23 19:05:25 -04:00
|
|
|
M: apply-node (traverse) ( data-array words apply-node -- node )
|
2006-08-19 21:18:14 -04:00
|
|
|
(pre)
|
|
|
|
[ [ apply-node-func (traverse) ] keep set-apply-node-func ] 3keep
|
|
|
|
[ [ apply-node-arg (traverse) ] keep set-apply-node-arg ] 3keep
|
|
|
|
(post) ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-23 19:05:25 -04:00
|
|
|
M: variable-node (traverse) ( data-array words variable-node -- node )
|
2006-08-19 21:18:14 -04:00
|
|
|
(pre) (post) ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-21 00:35:06 -04:00
|
|
|
M: alien-node (traverse) ( data-array word alien-node -- node ) nip nip ;
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
: traverse ( node data-array {pre,post} -- node )
|
|
|
|
rot (traverse) ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
: pre-order ( node data-array word -- node )
|
2006-08-23 19:05:25 -04:00
|
|
|
{ nip } curry traverse ;
|
2006-08-19 21:18:14 -04:00
|
|
|
|
2006-08-09 01:57:56 -04:00
|
|
|
: post-order ( node data-array word -- node )
|
2006-08-23 19:05:25 -04:00
|
|
|
{ nip } swap add traverse ;
|
2006-08-19 21:18:14 -04:00
|
|
|
|
|
|
|
GENERIC: (clone-pre)
|
|
|
|
M: lambda-node (clone-pre) ( data lambda-node -- node )
|
|
|
|
#! leave a copy of the original lambda node on the stack
|
|
|
|
#! for later substitution
|
|
|
|
nip dup clone ;
|
|
|
|
|
|
|
|
M: apply-node (clone-pre) ( data apply-node -- node ) nip clone ;
|
|
|
|
|
|
|
|
M: variable-node (clone-pre) ( data variable-node -- node ) nip clone ;
|
|
|
|
|
|
|
|
GENERIC: (clone-post)
|
|
|
|
M: lambda-node (clone-post) ( data lambda-node -- node )
|
|
|
|
nip [ dup <variable-node> -rot lambda-node-expr substitute ] keep
|
2006-08-09 01:57:56 -04:00
|
|
|
[ set-lambda-node-expr ] keep ;
|
2006-08-19 21:18:14 -04:00
|
|
|
|
2006-08-23 19:05:25 -04:00
|
|
|
M: apply-node (clone-post) ( data apply-node -- node ) nip ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-23 19:05:25 -04:00
|
|
|
M: variable-node (clone-post) ( data variable-node -- node ) nip ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
: clone-node ( node -- clone )
|
|
|
|
f { (clone-pre) (clone-post) } traverse ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
|
|
|
GENERIC: variable-eq?
|
|
|
|
M: string variable-eq? ( var string -- bool ) = ;
|
|
|
|
|
|
|
|
M: lambda-node variable-eq? ( var lambda-node-pointer -- bool ) eq? ;
|
|
|
|
|
|
|
|
GENERIC: (substitute)
|
2006-08-19 21:18:14 -04:00
|
|
|
M: lambda-node (substitute) ( data-array lambda-node -- node ) nip ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
M: apply-node (substitute) ( data-array apply-node -- node ) nip ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
M: variable-node (substitute) ( data-array variable-node -- node )
|
2006-08-09 01:57:56 -04:00
|
|
|
#! ( variable-node == var ) ? expr | variable-node
|
|
|
|
#! this could use multiple dispatch!
|
2006-08-19 21:18:14 -04:00
|
|
|
[ first2 ] dip ( expr var variable-node -- )
|
2006-08-09 01:57:56 -04:00
|
|
|
[ variable-node-var variable-eq? ] keep swap ( expr variable-node cond )
|
|
|
|
[ swap ] unless drop ;
|
|
|
|
|
|
|
|
: substitute ( expr var node -- node )
|
|
|
|
-rot 2array \ (substitute) post-order ;
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
: beta-reduce ( apply-node -- expr )
|
2006-08-09 01:57:56 -04:00
|
|
|
#! "pass" expr to the lambda-node, returning a reduced expression
|
2006-08-19 21:18:14 -04:00
|
|
|
dup apply-node-arg swap apply-node-func
|
|
|
|
clone-node dup lambda-node-expr substitute ;
|
|
|
|
|
|
|
|
: eta-reduce ( lambda-node -- expr )
|
|
|
|
lambda-node-expr apply-node-func ;
|
|
|
|
|
2006-08-21 00:35:06 -04:00
|
|
|
DEFER: evaluate
|
|
|
|
: alien-reduce ( apply-node -- expr )
|
|
|
|
#! execute the factor word in the alien-node
|
|
|
|
dup apply-node-arg evaluate
|
|
|
|
swap apply-node-func alien-node-word "lambda" lookup execute ;
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
GENERIC: evaluate
|
|
|
|
M: lambda-node evaluate ( lambda-node -- node )
|
|
|
|
#! eta-reduction
|
|
|
|
dup lambda-node-expr apply-node? [
|
|
|
|
dup lambda-node-expr apply-node-arg
|
|
|
|
variable-node? [
|
|
|
|
dup dup lambda-node-expr apply-node-arg variable-node-var
|
|
|
|
eq? [
|
|
|
|
eta-reduce evaluate
|
|
|
|
] when
|
|
|
|
] when
|
|
|
|
] when ;
|
|
|
|
|
|
|
|
M: apply-node evaluate ( apply-node -- node )
|
2006-08-09 01:57:56 -04:00
|
|
|
#! beta-reduction
|
2006-08-19 21:18:14 -04:00
|
|
|
#! TODO: fix the weird recursion here
|
2006-08-21 00:35:06 -04:00
|
|
|
dup apply-node-func alien-node?
|
|
|
|
[ alien-reduce evaluate ]
|
2006-08-19 21:18:14 -04:00
|
|
|
[
|
2006-08-21 00:35:06 -04:00
|
|
|
dup apply-node-func lambda-node?
|
|
|
|
[ beta-reduce evaluate ]
|
|
|
|
[
|
|
|
|
dup apply-node-func evaluate swap [ set-apply-node-func ] keep
|
|
|
|
dup apply-node-func lambda-node? [ evaluate ] when
|
|
|
|
] if
|
2006-08-19 21:18:14 -04:00
|
|
|
] if ;
|
|
|
|
|
|
|
|
M: variable-node evaluate ( variable-node -- node ) ;
|
|
|
|
|
2006-08-21 00:35:06 -04:00
|
|
|
M: alien-node evaluate ( alien-node -- node ) ;
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
GENERIC: (replace-names)
|
|
|
|
DEFER: replace-names
|
2006-08-09 01:57:56 -04:00
|
|
|
M: lambda-node (replace-names) ( names-hash l-node -- node ) nip ;
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
M: apply-node (replace-names) ( names-hash a-node -- node ) nip ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
M: variable-node (replace-names) ( names-hash v-node -- node )
|
|
|
|
[ variable-node-var swap hash ] 2keep pick not
|
|
|
|
[ 2nip ] [ drop swap clone-node replace-names ] if ;
|
2006-08-09 01:57:56 -04:00
|
|
|
|
|
|
|
: replace-names ( names-hash node -- node )
|
|
|
|
swap \ (replace-names) post-order ;
|
|
|
|
|
2006-08-19 21:18:14 -04:00
|
|
|
: set-temp-label ( available-vars lambda-node -- available-vars label lambda-node )
|
|
|
|
over nil?
|
|
|
|
[ [ lambda-node-original ] keep [ set-lambda-node-canonical ] 2keep ]
|
|
|
|
[ [ uncons swap ] dip [ set-lambda-node-canonical ] 2keep ] if ;
|
|
|
|
|
2006-08-09 01:57:56 -04:00
|
|
|
GENERIC: expr>string
|
|
|
|
M: lambda-node expr>string ( available-vars lambda-node -- string )
|
2006-08-19 21:18:14 -04:00
|
|
|
set-temp-label swapd lambda-node-expr expr>string swap
|
2006-08-09 01:57:56 -04:00
|
|
|
[ "(" , , ". " , , ")" , ] { } make concat ;
|
|
|
|
|
|
|
|
M: apply-node expr>string ( available-vars apply-node -- string )
|
|
|
|
[ apply-node-arg expr>string ] 2keep apply-node-func expr>string
|
|
|
|
[ "(" , , " " , , ")" , ] { } make concat ;
|
|
|
|
|
|
|
|
M: variable-node expr>string ( available-vars variable-node -- string )
|
2006-08-21 00:35:06 -04:00
|
|
|
nip variable-node-var dup string? [ lambda-node-canonical ] unless ;
|
|
|
|
|
|
|
|
M: alien-node expr>string ( available-vars alien-node -- string )
|
|
|
|
nip [ "[" , alien-node-word , "]" , ] { } make concat ;
|