factor/extra/locals/locals.factor

406 lines
10 KiB
Factor
Raw Normal View History

2008-01-06 11:17:38 -05:00
! Copyright (C) 2007, 2008 Slava Pestov, Eduardo Cavazos.
! See http://factorcode.org/license.txt for BSD license.
2008-02-12 16:54:13 -05:00
USING: kernel namespaces sequences sequences.private assocs math
inference.transforms parser words quotations debugger macros
arrays macros splitting combinators prettyprint.backend
2008-04-14 03:40:32 -04:00
definitions prettyprint hashtables prettyprint.sections sets
2008-04-05 08:00:59 -04:00
sequences.private effects generic compiler.units accessors ;
2007-09-20 18:09:08 -04:00
IN: locals
2008-01-06 11:17:38 -05:00
! Inspired by
! http://cat-language.googlecode.com/svn/trunk/CatPointFreeForm.cs
2007-09-20 18:09:08 -04:00
<PRIVATE
TUPLE: lambda vars body ;
C: <lambda> lambda
2008-03-19 22:16:09 -04:00
TUPLE: let bindings body ;
2007-09-20 18:09:08 -04:00
C: <let> let
2008-03-19 22:16:09 -04:00
TUPLE: let* bindings body ;
C: <let*> let*
TUPLE: wlet bindings body ;
2007-09-20 18:09:08 -04:00
C: <wlet> wlet
2008-03-26 19:23:19 -04:00
PREDICATE: local < word "local?" word-prop ;
2007-09-20 18:09:08 -04:00
: <local> ( name -- word )
#! Create a local variable identifier
2007-12-26 20:41:02 -05:00
f <word> dup t "local?" set-word-prop ;
2007-09-20 18:09:08 -04:00
2008-03-26 19:23:19 -04:00
PREDICATE: local-word < word "local-word?" word-prop ;
2007-09-20 18:09:08 -04:00
: <local-word> ( name -- word )
2007-12-26 20:41:02 -05:00
f <word> dup t "local-word?" set-word-prop ;
2007-09-20 18:09:08 -04:00
2008-03-26 19:23:19 -04:00
PREDICATE: local-reader < word "local-reader?" word-prop ;
2007-09-20 18:09:08 -04:00
: <local-reader> ( name -- word )
2007-12-26 20:41:02 -05:00
f <word> dup t "local-reader?" set-word-prop ;
2007-09-20 18:09:08 -04:00
2008-03-26 19:23:19 -04:00
PREDICATE: local-writer < word "local-writer?" word-prop ;
2007-09-20 18:09:08 -04:00
: <local-writer> ( reader -- word )
2007-12-26 20:41:02 -05:00
dup word-name "!" append f <word>
2007-09-20 18:09:08 -04:00
[ t "local-writer?" set-word-prop ] keep
[ "local-writer" set-word-prop ] 2keep
[ swap "local-reader" set-word-prop ] keep ;
TUPLE: quote local ;
C: <quote> quote
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! read-local
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: local-index ( obj args -- n )
2008-01-09 17:36:30 -05:00
[ dup quote? [ quote-local ] when eq? ] with find drop ;
2007-09-20 18:09:08 -04:00
: read-local ( obj args -- quot )
local-index 1+
dup [ r> ] <repetition> concat [ dup ] append
swap [ swap >r ] <repetition> concat append ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! localize
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: localize-writer ( obj args -- quot )
2008-02-12 16:48:30 -05:00
>r "local-reader" word-prop r> read-local [ 0 swap set-array-nth ] append ;
2007-09-20 18:09:08 -04:00
: localize ( obj args -- quot )
{
{ [ over local? ] [ read-local ] }
{ [ over quote? ] [ >r quote-local r> read-local ] }
{ [ over local-word? ] [ read-local [ call ] append ] }
2008-02-12 16:48:30 -05:00
{ [ over local-reader? ] [ read-local [ 0 swap array-nth ] append ] }
2007-09-20 18:09:08 -04:00
{ [ over local-writer? ] [ localize-writer ] }
{ [ over \ lambda eq? ] [ 2drop [ ] ] }
{ [ t ] [ drop 1quotation ] }
} cond ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! point-free
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
UNION: special local quote local-word local-reader local-writer ;
: load-local ( arg -- quot )
local-reader? [ 1array >r ] [ >r ] ? ;
: load-locals ( quot args -- quot )
nip <reversed> [ load-local ] map concat ;
: drop-locals ( args -- args quot )
dup length [ r> drop ] <repetition> concat ;
: point-free-body ( quot args -- newquot )
>r 1 head-slice* r> [ localize ] curry map concat ;
: point-free-end ( quot args -- newquot )
over peek special?
[ drop-locals >r >r peek r> localize r> append ]
[ drop-locals nip swap peek suffix ]
2007-09-20 18:09:08 -04:00
if ;
: (point-free) ( quot args -- newquot )
[ load-locals ] [ point-free-body ] [ point-free-end ]
2tri 3append >quotation ;
2007-09-20 18:09:08 -04:00
: point-free ( quot args -- newquot )
over empty? [ drop ] [ (point-free) ] if ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! free-vars
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
UNION: lexical local local-reader local-writer local-word ;
GENERIC: free-vars ( form -- vars )
: add-if-free ( vars object -- vars )
{
{ [ dup local-writer? ] [ "local-reader" word-prop suffix ] }
{ [ dup lexical? ] [ suffix ] }
{ [ dup quote? ] [ quote-local suffix ] }
2007-09-20 18:09:08 -04:00
{ [ t ] [ free-vars append ] }
} cond ;
M: object free-vars drop { } ;
M: quotation free-vars { } [ add-if-free ] reduce ;
M: lambda free-vars
dup vars>> swap body>> free-vars diff ;
2007-09-20 18:09:08 -04:00
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! lambda-rewrite
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
GENERIC: lambda-rewrite* ( obj -- )
2008-02-12 16:48:30 -05:00
GENERIC: local-rewrite* ( obj -- )
2007-09-20 18:09:08 -04:00
2008-02-12 16:48:30 -05:00
: lambda-rewrite
[ local-rewrite* ] [ ] make
[ [ lambda-rewrite* ] each ] [ ] make ;
UNION: block callable lambda ;
2007-09-20 18:09:08 -04:00
GENERIC: block-vars ( block -- seq )
GENERIC: block-body ( block -- quot )
2008-02-12 16:48:30 -05:00
M: callable block-vars drop { } ;
M: callable block-body ;
2007-09-20 18:09:08 -04:00
2008-02-12 16:48:30 -05:00
M: callable local-rewrite*
[ [ local-rewrite* ] each ] [ ] make , ;
2007-09-20 18:09:08 -04:00
2008-03-19 22:16:09 -04:00
M: lambda block-vars vars>> ;
2007-09-20 18:09:08 -04:00
2008-03-19 22:16:09 -04:00
M: lambda block-body body>> ;
2007-09-20 18:09:08 -04:00
2008-02-12 16:48:30 -05:00
M: lambda local-rewrite*
2008-03-19 22:16:09 -04:00
dup vars>> swap body>>
2008-02-12 16:48:30 -05:00
[ local-rewrite* \ call , ] [ ] make <lambda> , ;
2007-09-20 18:09:08 -04:00
M: block lambda-rewrite*
#! Turn free variables into bound variables, curry them
#! onto the body
dup free-vars [ <quote> ] map dup % [
over block-vars prepend
2007-09-20 18:09:08 -04:00
swap block-body [ [ lambda-rewrite* ] each ] [ ] make
swap point-free ,
] keep length \ curry <repetition> % ;
M: object lambda-rewrite* , ;
2008-02-12 16:48:30 -05:00
M: object local-rewrite* , ;
2007-09-20 18:09:08 -04:00
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2008-03-19 22:16:09 -04:00
: make-local ( name -- word )
"!" ?tail [
<local-reader>
dup <local-writer> dup word-name set
] [ <local> ] if
dup dup word-name set ;
2007-09-20 18:09:08 -04:00
: make-locals ( seq -- words assoc )
2008-03-19 22:16:09 -04:00
[ [ make-local ] map ] H{ } make-assoc ;
: make-local-word ( name -- word )
<local-word> dup dup word-name set ;
2007-09-20 18:09:08 -04:00
: push-locals ( assoc -- )
use get push ;
: pop-locals ( assoc -- )
use get delete ;
: (parse-lambda) ( assoc end -- quot )
2008-03-19 22:16:09 -04:00
parse-until >quotation swap pop-locals ;
2007-09-20 18:09:08 -04:00
: parse-lambda ( -- lambda )
2008-03-19 22:16:09 -04:00
"|" parse-tokens make-locals dup push-locals
\ ] (parse-lambda) <lambda> ;
2007-09-20 18:09:08 -04:00
2008-03-19 22:16:09 -04:00
: parse-binding ( -- pair/f )
2007-09-20 18:09:08 -04:00
scan dup "|" = [
2008-03-19 22:16:09 -04:00
drop f
2007-09-20 18:09:08 -04:00
] [
scan {
{ "[" [ \ ] parse-until >quotation ] }
{ "[|" [ parse-lambda ] }
2008-03-19 22:16:09 -04:00
} case 2array
2007-09-20 18:09:08 -04:00
] if ;
2008-03-19 22:16:09 -04:00
: (parse-bindings) ( -- )
parse-binding [
first2 >r make-local r> 2array ,
(parse-bindings)
] when* ;
2007-09-20 18:09:08 -04:00
2008-03-19 22:16:09 -04:00
: parse-bindings ( -- bindings vars )
2008-02-12 16:48:30 -05:00
[
2008-03-19 22:16:09 -04:00
[ (parse-bindings) ] H{ } make-assoc
dup push-locals
] { } make swap ;
: parse-bindings* ( -- words assoc )
[
[
namespace push-locals
(parse-bindings)
] { } make-assoc
] { } make swap ;
: (parse-wbindings) ( -- )
parse-binding [
first2 >r make-local-word r> 2array ,
(parse-wbindings)
] when* ;
: parse-wbindings ( -- bindings vars )
[
[ (parse-wbindings) ] H{ } make-assoc
dup push-locals
] { } make swap ;
: let-rewrite ( body bindings -- )
<reversed> [
>r 1array r> spin <lambda> [ call ] curry compose
] assoc-each local-rewrite* \ call , ;
M: let local-rewrite*
[ body>> ] [ bindings>> ] bi let-rewrite ;
2008-03-19 22:16:09 -04:00
M: let* local-rewrite*
[ body>> ] [ bindings>> ] bi let-rewrite ;
2007-09-20 18:09:08 -04:00
2008-02-12 16:48:30 -05:00
M: wlet local-rewrite*
[ body>> ] [ bindings>> ] bi
2008-03-19 22:16:09 -04:00
[ [ ] curry ] assoc-map
let-rewrite ;
2007-09-20 18:09:08 -04:00
2008-03-19 22:16:09 -04:00
: parse-locals ( -- vars assoc )
2008-02-26 19:40:32 -05:00
parse-effect
word [ over "declared-effect" set-word-prop ] when*
2008-03-19 22:16:09 -04:00
effect-in make-locals dup push-locals ;
2008-02-26 19:40:32 -05:00
2008-03-16 03:43:00 -04:00
: parse-locals-definition ( word -- word quot )
2008-02-26 19:40:32 -05:00
scan "(" assert= parse-locals \ ; (parse-lambda) <lambda>
2dup "lambda" set-word-prop
lambda-rewrite first ;
2008-03-16 03:43:00 -04:00
: (::) CREATE-WORD parse-locals-definition ;
: (M::) CREATE-METHOD parse-locals-definition ;
2007-09-20 18:09:08 -04:00
PRIVATE>
: [| parse-lambda parsed ; parsing
: [let
2008-03-19 22:16:09 -04:00
scan "|" assert= parse-bindings
\ ] (parse-lambda) <let> parsed ; parsing
: [let*
scan "|" assert= parse-bindings*
>r \ ] parse-until >quotation <let*> parsed r> pop-locals ;
parsing
2007-09-20 18:09:08 -04:00
: [wlet
2008-03-19 22:16:09 -04:00
scan "|" assert= parse-wbindings
\ ] (parse-lambda) <wlet> parsed ; parsing
2007-09-20 18:09:08 -04:00
MACRO: with-locals ( form -- quot ) lambda-rewrite ;
2008-02-26 19:40:32 -05:00
: :: (::) define ; parsing
2008-03-16 03:43:00 -04:00
: M:: (M::) define ; parsing
2008-02-26 19:40:32 -05:00
: MACRO:: (::) define-macro ; parsing
2007-09-20 18:09:08 -04:00
<PRIVATE
! Pretty-printing locals
SYMBOL: |
: pprint-var ( var -- )
#! Prettyprint a read/write local as its writer, just like
#! in the input syntax: [| x! | ... x 3 + x! ]
dup local-reader? [
"local-writer" word-prop
] when pprint-word ;
: pprint-vars ( vars -- ) [ pprint-var ] each ;
M: lambda pprint*
<flow
\ [| pprint-word
2008-03-19 22:16:09 -04:00
dup vars>> pprint-vars
2007-09-20 18:09:08 -04:00
\ | pprint-word
2008-03-19 22:16:09 -04:00
f <inset body>> pprint-elements block>
2007-09-20 18:09:08 -04:00
\ ] pprint-word
block> ;
2008-03-19 22:16:09 -04:00
: pprint-let ( let word -- )
pprint-word
[ body>> ] [ bindings>> ] bi
2007-09-20 18:09:08 -04:00
\ | pprint-word
t <inset
<block
2008-03-19 22:16:09 -04:00
[ <block >r pprint-var r> pprint* block> ] assoc-each
2007-09-20 18:09:08 -04:00
block>
\ | pprint-word
<block pprint-elements block>
2008-03-19 22:16:09 -04:00
block>
2007-09-20 18:09:08 -04:00
\ ] pprint-word ;
2008-03-19 22:16:09 -04:00
M: let pprint* \ [let pprint-let ;
M: wlet pprint* \ [wlet pprint-let ;
M: let* pprint* \ [let* pprint-let ;
2007-09-20 18:09:08 -04:00
2008-03-26 19:23:19 -04:00
PREDICATE: lambda-word < word
2007-09-20 18:09:08 -04:00
"lambda" word-prop >boolean ;
M: lambda-word definer drop \ :: \ ; ;
M: lambda-word definition
2008-03-19 22:16:09 -04:00
"lambda" word-prop body>> ;
2007-09-20 18:09:08 -04:00
2008-02-26 19:40:32 -05:00
: lambda-word-synopsis ( word -- )
dup definer.
dup seeing-word
dup pprint-word
stack-effect. ;
2007-09-20 18:09:08 -04:00
2008-02-26 19:40:32 -05:00
M: lambda-word synopsis* lambda-word-synopsis ;
2007-09-20 18:09:08 -04:00
2008-03-26 19:23:19 -04:00
PREDICATE: lambda-macro < macro
2008-02-26 19:40:32 -05:00
"lambda" word-prop >boolean ;
2007-09-20 18:09:08 -04:00
M: lambda-macro definer drop \ MACRO:: \ ; ;
M: lambda-macro definition
2008-03-19 22:16:09 -04:00
"lambda" word-prop body>> ;
2008-02-26 19:40:32 -05:00
M: lambda-macro synopsis* lambda-word-synopsis ;
2008-03-26 19:23:19 -04:00
PREDICATE: lambda-method < method-body
2008-02-26 19:40:32 -05:00
"lambda" word-prop >boolean ;
M: lambda-method definer drop \ M:: \ ; ;
M: lambda-method definition
2008-03-19 22:16:09 -04:00
"lambda" word-prop body>> ;
2007-09-20 18:09:08 -04:00
2008-03-05 17:00:34 -05:00
: method-stack-effect ( method -- effect )
2008-03-19 22:16:09 -04:00
dup "lambda" word-prop vars>>
2008-03-04 23:44:46 -05:00
swap "method-generic" word-prop stack-effect
dup [ effect-out ] when
2008-02-26 19:40:32 -05:00
<effect> ;
M: lambda-method synopsis*
2008-03-05 17:00:34 -05:00
dup dup dup definer.
2008-03-04 23:44:46 -05:00
"method-specializer" word-prop pprint*
"method-generic" word-prop pprint*
2008-02-26 19:40:32 -05:00
method-stack-effect effect>string comment. ;
2007-09-20 18:09:08 -04:00
PRIVATE>