macros: macro body is now defined in its own subword, for compile-time stack effect checking
parent
e32d5fd0ac
commit
b7fde7af27
|
@ -1,9 +1,10 @@
|
||||||
! Copyright (C) 2006, 2009 Slava Pestov
|
! Copyright (C) 2006, 2010 Slava Pestov
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: compiler io kernel cocoa.runtime cocoa.subclassing
|
USING: compiler io kernel cocoa.runtime cocoa.subclassing
|
||||||
cocoa.messages cocoa.types sequences words vocabs parser
|
cocoa.messages cocoa.types sequences words vocabs parser
|
||||||
core-foundation.bundles namespaces assocs hashtables
|
core-foundation.bundles namespaces assocs hashtables
|
||||||
compiler.units lexer init ;
|
compiler.units lexer init macros quotations fry alien.c-types
|
||||||
|
arrays combinators ;
|
||||||
IN: cocoa
|
IN: cocoa
|
||||||
|
|
||||||
: (remember-send) ( selector variable -- )
|
: (remember-send) ( selector variable -- )
|
||||||
|
@ -14,7 +15,7 @@ SYMBOL: sent-messages
|
||||||
: remember-send ( selector -- )
|
: remember-send ( selector -- )
|
||||||
sent-messages (remember-send) ;
|
sent-messages (remember-send) ;
|
||||||
|
|
||||||
SYNTAX: -> scan dup remember-send suffix! \ send suffix! ;
|
SYNTAX: -> scan [ remember-send ] [ suffix! ] bi \ send suffix! ;
|
||||||
|
|
||||||
SYMBOL: super-sent-messages
|
SYMBOL: super-sent-messages
|
||||||
|
|
||||||
|
@ -33,6 +34,14 @@ SYNTAX: FRAMEWORK: scan [ load-framework ] [ frameworks get push ] bi ;
|
||||||
|
|
||||||
SYNTAX: IMPORT: scan [ ] import-objc-class ;
|
SYNTAX: IMPORT: scan [ ] import-objc-class ;
|
||||||
|
|
||||||
|
MACRO: objc-class-case ( alist -- quot )
|
||||||
|
"isKindOfClass:" remember-send
|
||||||
|
[
|
||||||
|
dup callable?
|
||||||
|
[ first2 [ '[ dup _ execute "isKindOfClass:" send c-bool> ] ] dip 2array ]
|
||||||
|
unless
|
||||||
|
] map '[ _ cond ] ;
|
||||||
|
|
||||||
"Importing Cocoa classes..." print
|
"Importing Cocoa classes..." print
|
||||||
|
|
||||||
"cocoa.classes" create-vocab drop
|
"cocoa.classes" create-vocab drop
|
||||||
|
|
|
@ -40,13 +40,6 @@ DEFER: plist>
|
||||||
[ -> propertyListFromData:mutabilityOption:format:errorDescription: ] keep
|
[ -> propertyListFromData:mutabilityOption:format:errorDescription: ] keep
|
||||||
*void* [ -> release "read-plist failed" throw ] when* ;
|
*void* [ -> release "read-plist failed" throw ] when* ;
|
||||||
|
|
||||||
MACRO: objc-class-case ( alist -- quot )
|
|
||||||
[
|
|
||||||
dup callable?
|
|
||||||
[ first2 [ '[ dup _ execute -> isKindOfClass: c-bool> ] ] dip 2array ]
|
|
||||||
unless
|
|
||||||
] map '[ _ cond ] ;
|
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
ERROR: invalid-plist-object object ;
|
ERROR: invalid-plist-object object ;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
! Copyright (C) 2006, 2010 Slava Pestov.
|
! Copyright (C) 2006, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel assocs match fry accessors namespaces make effects
|
USING: kernel assocs match fry accessors namespaces make effects
|
||||||
sequences sequences.private quotations generic macros arrays
|
sequences sequences.private quotations generic arrays
|
||||||
prettyprint prettyprint.backend prettyprint.custom
|
prettyprint prettyprint.backend prettyprint.custom
|
||||||
prettyprint.sections math words combinators
|
prettyprint.sections math words combinators
|
||||||
combinators.short-circuit io sorting hints
|
combinators.short-circuit io sorting hints
|
||||||
|
@ -30,34 +30,31 @@ IN: compiler.tree.debugger
|
||||||
|
|
||||||
GENERIC: node>quot ( node -- )
|
GENERIC: node>quot ( node -- )
|
||||||
|
|
||||||
MACRO: match-choose ( alist -- )
|
|
||||||
[ '[ _ ] ] assoc-map '[ _ match-cond ] ;
|
|
||||||
|
|
||||||
MATCH-VARS: ?a ?b ?c ;
|
MATCH-VARS: ?a ?b ?c ;
|
||||||
|
|
||||||
: pretty-shuffle ( effect -- word/f )
|
: pretty-shuffle ( effect -- word/f )
|
||||||
[ in>> ] [ out>> ] bi 2array {
|
[ in>> ] [ out>> ] bi 2array {
|
||||||
{ { { } { } } [ ] }
|
{ { { } { } } [ [ ] ] }
|
||||||
{ { { ?a } { ?a } } [ ] }
|
{ { { ?a } { ?a } } [ [ ] ] }
|
||||||
{ { { ?a ?b } { ?a ?b } } [ ] }
|
{ { { ?a ?b } { ?a ?b } } [ [ ] ] }
|
||||||
{ { { ?a ?b ?c } { ?a ?b ?c } } [ ] }
|
{ { { ?a ?b ?c } { ?a ?b ?c } } [ [ ] ] }
|
||||||
{ { { ?a } { } } [ drop ] }
|
{ { { ?a } { } } [ [ drop ] ] }
|
||||||
{ { { ?a ?b } { } } [ 2drop ] }
|
{ { { ?a ?b } { } } [ [ 2drop ] ] }
|
||||||
{ { { ?a ?b ?c } { } } [ 3drop ] }
|
{ { { ?a ?b ?c } { } } [ [ 3drop ] ] }
|
||||||
{ { { ?a } { ?a ?a } } [ dup ] }
|
{ { { ?a } { ?a ?a } } [ [ dup ] ] }
|
||||||
{ { { ?a ?b } { ?a ?b ?a ?b } } [ 2dup ] }
|
{ { { ?a ?b } { ?a ?b ?a ?b } } [ [ 2dup ] ] }
|
||||||
{ { { ?a ?b ?c } { ?a ?b ?c ?a ?b ?c } } [ 3dup ] }
|
{ { { ?a ?b ?c } { ?a ?b ?c ?a ?b ?c } } [ [ 3dup ] ] }
|
||||||
{ { { ?a ?b } { ?a ?b ?a } } [ over ] }
|
{ { { ?a ?b } { ?a ?b ?a } } [ [ over ] ] }
|
||||||
{ { { ?b ?a } { ?a ?b } } [ swap ] }
|
{ { { ?b ?a } { ?a ?b } } [ [ swap ] ] }
|
||||||
{ { { ?b ?a ?c } { ?a ?b ?c } } [ swapd ] }
|
{ { { ?b ?a ?c } { ?a ?b ?c } } [ [ swapd ] ] }
|
||||||
{ { { ?a ?b } { ?a ?a ?b } } [ dupd ] }
|
{ { { ?a ?b } { ?a ?a ?b } } [ [ dupd ] ] }
|
||||||
{ { { ?a ?b ?c } { ?a ?b ?c ?a } } [ pick ] }
|
{ { { ?a ?b ?c } { ?a ?b ?c ?a } } [ [ pick ] ] }
|
||||||
{ { { ?a ?b ?c } { ?c ?a ?b } } [ -rot ] }
|
{ { { ?a ?b ?c } { ?c ?a ?b } } [ [ -rot ] ] }
|
||||||
{ { { ?a ?b ?c } { ?b ?c ?a } } [ rot ] }
|
{ { { ?a ?b ?c } { ?b ?c ?a } } [ [ rot ] ] }
|
||||||
{ { { ?a ?b } { ?b } } [ nip ] }
|
{ { { ?a ?b } { ?b } } [ [ nip ] ] }
|
||||||
{ { { ?a ?b ?c } { ?c } } [ 2nip ] }
|
{ { { ?a ?b ?c } { ?c } } [ [ 2nip ] ] }
|
||||||
{ __ f }
|
{ __ [ f ] }
|
||||||
} match-choose ;
|
} match-cond ;
|
||||||
|
|
||||||
TUPLE: shuffle-node { effect effect } ;
|
TUPLE: shuffle-node { effect effect } ;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
! Copyright (C) 2008, 2009 Slava Pestov.
|
! Copyright (C) 2008, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel sequences sequences.private namespaces make
|
USING: kernel sequences sequences.private namespaces make
|
||||||
quotations accessors words continuations vectors effects math
|
quotations accessors words continuations vectors effects math
|
||||||
generalizations fry arrays ;
|
generalizations fry arrays combinators ;
|
||||||
IN: macros.expander
|
IN: macros.expander
|
||||||
|
|
||||||
GENERIC: expand-macros ( quot -- quot' )
|
GENERIC: expand-macros ( quot -- quot' )
|
||||||
|
@ -55,7 +55,7 @@ M: wrapper expand-macros* wrapped>> literal ;
|
||||||
|
|
||||||
: word, ( word -- ) end , ;
|
: word, ( word -- ) end , ;
|
||||||
|
|
||||||
: expand-macro ( word quot -- )
|
: expand-transform ( word quot -- )
|
||||||
'[
|
'[
|
||||||
drop
|
drop
|
||||||
stack [ _ with-datastack >vector ] change
|
stack [ _ with-datastack >vector ] change
|
||||||
|
@ -65,18 +65,25 @@ M: wrapper expand-macros* wrapped>> literal ;
|
||||||
word,
|
word,
|
||||||
] recover ;
|
] recover ;
|
||||||
|
|
||||||
: expand-macro? ( word -- quot ? )
|
: expand-transform? ( word -- ? )
|
||||||
dup [ "transform-quot" word-prop ] [ "macro" word-prop ] bi or dup [
|
dup "transform-quot" word-prop [
|
||||||
swap [ "transform-n" word-prop ] [ stack-effect in>> length ] bi or
|
"transform-n" word-prop
|
||||||
stack get length <=
|
stack get length <=
|
||||||
] [ 2drop f f ] if ;
|
] [ drop f ] if ;
|
||||||
|
|
||||||
|
: expand-macro? ( word -- ? )
|
||||||
|
dup "macro" word-prop [
|
||||||
|
stack-effect in>> length
|
||||||
|
stack get length <=
|
||||||
|
] [ drop f ] if ;
|
||||||
|
|
||||||
M: word expand-macros*
|
M: word expand-macros*
|
||||||
dup expand-dispatch? [ drop expand-dispatch ] [
|
{
|
||||||
dup expand-macro? [ expand-macro ] [
|
{ [ dup expand-dispatch? ] [ drop expand-dispatch ] }
|
||||||
drop word,
|
{ [ dup expand-macro? ] [ dup "macro" word-prop '[ _ execute ] expand-transform ] }
|
||||||
] if
|
{ [ dup expand-transform? ] [ dup "transform-quot" word-prop expand-transform ] }
|
||||||
] if ;
|
[ word, ]
|
||||||
|
} cond ;
|
||||||
|
|
||||||
M: object expand-macros* literal ;
|
M: object expand-macros* literal ;
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,7 @@ $nl
|
||||||
$nl
|
$nl
|
||||||
"Defining new macros:"
|
"Defining new macros:"
|
||||||
{ $subsections POSTPONE: MACRO: }
|
{ $subsections POSTPONE: MACRO: }
|
||||||
"A slightly lower-level facility, " { $emphasis "compiler transforms" } ", allows an ordinary word definition to co-exist with a version that performs compile-time expansion."
|
"As with parsing words, macros cannot be used from the same source file that they are defined in."
|
||||||
{ $subsections define-transform }
|
|
||||||
"An example is the " { $link member? } " word. If the input sequence is a literal, the compile transform kicks in and converts the " { $link member? } " call into a series of conditionals. Otherwise, if the input sequence is not literal, a call to the definition of " { $link member? } " is generated."
|
|
||||||
{ $see-also "generalizations" "fry" } ;
|
{ $see-also "generalizations" "fry" } ;
|
||||||
|
|
||||||
ABOUT: "macros"
|
ABOUT: "macros"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
IN: macros.tests
|
|
||||||
USING: tools.test macros math kernel arrays
|
USING: tools.test macros math kernel arrays
|
||||||
vectors io.streams.string prettyprint parser eval see ;
|
vectors io.streams.string prettyprint parser eval see
|
||||||
|
stack-checker compiler.units definitions vocabs ;
|
||||||
|
IN: macros.tests
|
||||||
|
|
||||||
MACRO: see-test ( a b -- quot ) + ;
|
MACRO: see-test ( a b -- quot ) + ;
|
||||||
|
|
||||||
|
@ -19,7 +20,18 @@ unit-test
|
||||||
|
|
||||||
[ f ] [ \ see-test macro? ] unit-test
|
[ f ] [ \ see-test macro? ] unit-test
|
||||||
|
|
||||||
[ ] [ "USING: macros stack-checker kernel ; IN: hanging-macro MACRO: c ( quot -- ) infer drop [ ] ; : a ( -- ) [ a ] c ;" eval( -- ) ] unit-test
|
[ ] [ "USING: macros stack-checker kernel ; IN: hanging-macro MACRO: c ( quot -- ) infer drop [ ] ;" eval( -- ) ] unit-test
|
||||||
|
[ ] [ "USING: macros kernel ; IN: hanging-macro : a ( -- ) [ a ] c ;" eval( -- ) ] unit-test
|
||||||
|
|
||||||
|
[ ] [ [ "hanging-macro" forget-vocab ] with-compilation-unit ] unit-test
|
||||||
|
|
||||||
[ ] [ "IN: macros.tests USE: macros MACRO: foo ( -- x ) [ ] ;" eval( -- ) ] unit-test
|
[ ] [ "IN: macros.tests USE: macros MACRO: foo ( -- x ) [ ] ;" eval( -- ) ] unit-test
|
||||||
[ "IN: macros.tests USE: macros MACRO: foo ( -- x ) [ ] ; inline" eval( -- ) ] must-fail
|
[ "IN: macros.tests USE: macros MACRO: foo ( -- x ) [ ] ; inline" eval( -- ) ] must-fail
|
||||||
|
|
||||||
|
! The macro expander code should infer
|
||||||
|
MACRO: bad-macro ( a -- b ) 1 2 3 [ ] ;
|
||||||
|
|
||||||
|
[ [ 0 bad-macro ] call ] must-fail
|
||||||
|
[ [ 0 bad-macro ] infer ] must-fail
|
||||||
|
|
||||||
|
[ ] [ [ \ bad-macro forget ] with-compilation-unit ] unit-test
|
||||||
|
|
|
@ -1,23 +1,47 @@
|
||||||
! Copyright (C) 2007, 2010 Slava Pestov.
|
! Copyright (C) 2007, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: parser kernel sequences words effects combinators assocs
|
USING: parser kernel sequences words effects combinators assocs
|
||||||
definitions quotations namespaces memoize accessors
|
definitions quotations namespaces memoize accessors arrays
|
||||||
compiler.units ;
|
compiler.units ;
|
||||||
IN: macros
|
IN: macros
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
|
! The macro expander is split off into its own word. This allows
|
||||||
|
! the optimizing compiler to optimize and check the stack effect
|
||||||
|
! of the expander, even though the actual macro word does not
|
||||||
|
! infer.
|
||||||
|
|
||||||
: real-macro-effect ( effect -- effect' )
|
: real-macro-effect ( effect -- effect' )
|
||||||
in>> { "quot" } <effect> ;
|
in>> { "quot" } <effect> ;
|
||||||
|
|
||||||
|
PREDICATE: macro-body < memoized "macro-owner" word-prop >boolean ;
|
||||||
|
|
||||||
|
: <macro-body> ( word quot effect -- macro-body )
|
||||||
|
real-macro-effect
|
||||||
|
[ name>> "( macro body: " " )" surround <uninterned-word> dup ] 2dip
|
||||||
|
define-memoized ;
|
||||||
|
|
||||||
|
M: macro-body crossref? "forgotten" word-prop not ;
|
||||||
|
|
||||||
|
M: macro-body reset-word
|
||||||
|
[ call-next-method ] [ "macro-body" remove-word-prop ] bi ;
|
||||||
|
|
||||||
|
M: macro-body where "macro-owner" word-prop where ;
|
||||||
|
|
||||||
|
: reset-macro ( word -- )
|
||||||
|
[ "macro" word-prop forget ] [ f "macro" set-word-prop ] bi ;
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
: define-macro ( word definition effect -- )
|
: define-macro ( word quot effect -- )
|
||||||
real-macro-effect {
|
[ 2drop ] [ <macro-body> ] 3bi
|
||||||
[ [ memoize-quot [ call ] append ] keep define-declared ]
|
{
|
||||||
[ drop "macro" set-word-prop ]
|
[ "macro" set-word-prop ]
|
||||||
[ 2drop changed-effect ]
|
[ swap "macro-owner" set-word-prop ]
|
||||||
} 3cleave ;
|
[ [ \ call [ ] 2sequence ] [ stack-effect ] bi define-declared ]
|
||||||
|
[ drop changed-effect ]
|
||||||
|
} 2cleave ;
|
||||||
|
|
||||||
SYNTAX: MACRO: (:) define-macro ;
|
SYNTAX: MACRO: (:) define-macro ;
|
||||||
|
|
||||||
|
@ -27,9 +51,12 @@ M: macro make-inline cannot-be-inline ;
|
||||||
|
|
||||||
M: macro definer drop \ MACRO: \ ; ;
|
M: macro definer drop \ MACRO: \ ; ;
|
||||||
|
|
||||||
M: macro definition "macro" word-prop ;
|
M: macro definition "macro" word-prop definition ;
|
||||||
|
|
||||||
M: macro reset-word
|
M: macro subwords "macro" word-prop 1array ;
|
||||||
[ call-next-method ] [ f "macro" set-word-prop ] bi ;
|
|
||||||
|
M: macro reset-word [ call-next-method ] [ reset-macro ] bi ;
|
||||||
|
|
||||||
|
M: macro forget* [ call-next-method ] [ reset-macro ] bi ;
|
||||||
|
|
||||||
M: macro always-bump-effect-counter? drop t ;
|
M: macro always-bump-effect-counter? drop t ;
|
||||||
|
|
|
@ -48,7 +48,7 @@ IN: stack-checker.transforms
|
||||||
|
|
||||||
: apply-macro ( word -- )
|
: apply-macro ( word -- )
|
||||||
[ current-word set ]
|
[ current-word set ]
|
||||||
[ "macro" word-prop ]
|
[ "macro" word-prop '[ _ execute ] ]
|
||||||
[ "declared-effect" word-prop in>> length ] tri
|
[ "declared-effect" word-prop in>> length ] tri
|
||||||
(apply-transform) ;
|
(apply-transform) ;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ sequences stack-checker strings system unix.time unix.types
|
||||||
vocabs vocabs.loader unix.ffi ;
|
vocabs vocabs.loader unix.ffi ;
|
||||||
IN: unix
|
IN: unix
|
||||||
|
|
||||||
|
<<
|
||||||
|
|
||||||
ERROR: unix-error errno message ;
|
ERROR: unix-error errno message ;
|
||||||
|
|
||||||
: (io-error) ( -- * ) errno dup strerror unix-error ;
|
: (io-error) ( -- * ) errno dup strerror unix-error ;
|
||||||
|
@ -46,6 +48,8 @@ MACRO:: unix-system-call ( quot -- )
|
||||||
] if
|
] if
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
|
>>
|
||||||
|
|
||||||
HOOK: open-file os ( path flags mode -- fd )
|
HOOK: open-file os ( path flags mode -- fd )
|
||||||
|
|
||||||
: close-file ( fd -- ) [ close ] unix-system-call drop ;
|
: close-file ( fd -- ) [ close ] unix-system-call drop ;
|
||||||
|
@ -72,10 +76,6 @@ M: unix open-file [ open ] unix-system-call ;
|
||||||
|
|
||||||
: unlink-file ( path -- ) [ unlink ] unix-system-call drop ;
|
: unlink-file ( path -- ) [ unlink ] unix-system-call drop ;
|
||||||
|
|
||||||
<<
|
|
||||||
|
|
||||||
"debugger" vocab [
|
"debugger" vocab [
|
||||||
"unix.debugger" require
|
"unix.debugger" require
|
||||||
] when
|
] when
|
||||||
|
|
||||||
>>
|
|
||||||
|
|
Loading…
Reference in New Issue