namespaces make parser sequences strings words assocs splitting
math.parser cpu.architecture alien alien.accessors quotations
layouts system compiler.units io.files io.encodings.binary
-accessors combinators effects continuations fry call classes ;
+accessors combinators effects continuations fry classes ;
IN: alien.c-types
DEFER: <int>
quotation type-number object tag-number [
emit ! array
f ' emit ! compiled
+ f ' emit ! cached-effect
+ f ' emit ! cache-counter
0 emit ! xt
0 emit ! code
] emit-object
[ "bootstrap." prepend require ] each ;
: count-words ( pred -- )
- all-words swap count number>string write ;
+ all-words swap count number>string write ; inline
: print-time ( ms -- )
1000 /i
+++ /dev/null
-Daniel Ehrenberg
-Slava Pestov
+++ /dev/null
-! Copyright (C) 2009 Daniel Ehrenberg.
-! See http://factorcode.org/license.txt for BSD license.
-USING: help.markup help.syntax quotations effects words call.private ;
-IN: call
-
-ABOUT: "call"
-
-ARTICLE: "call" "Calling code with known stack effects"
-"The " { $vocab-link "call" } " vocabulary allows for arbitrary quotations to be called from code accepted by the optimizing compiler. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate."
-$nl
-"Quotations:"
-{ $subsection POSTPONE: call( }
-{ $subsection call-effect }
-"Words:"
-{ $subsection POSTPONE: execute( }
-{ $subsection execute-effect }
-"Unsafe calls:"
-{ $subsection POSTPONE: execute-unsafe( }
-{ $subsection execute-effect-unsafe } ;
-
-HELP: call(
-{ $syntax "call( stack -- effect )" }
-{ $description "Calls the quotation on the top of the stack, asserting that it has the given stack effect. The quotation does not need to be known at compile time." } ;
-
-HELP: call-effect
-{ $values { "quot" quotation } { "effect" effect } }
-{ $description "Given a quotation and a stack effect, calls the quotation, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary quotation which is not required at compile time." } ;
-
-HELP: execute(
-{ $syntax "execute( stack -- effect )" }
-{ $description "Calls the word on the top of the stack, asserting that it has the given stack effect. The word does not need to be known at compile time." } ;
-
-HELP: execute-effect
-{ $values { "word" word } { "effect" effect } }
-{ $description "Given a word and a stack effect, executes the word, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." } ;
-
-HELP: execute-unsafe(
-{ $syntax "execute-unsafe( stack -- effect )" }
-{ $description "Calls the word on the top of the stack, blindly declaring that it has the given stack effect. The word does not need to be known at compile time." }
-{ $warning "If the word being executed has an incorrect stack effect, undefined behavior will result. User code should use " { $link POSTPONE: execute( } " instead." } ;
-HELP: execute-effect-unsafe
-{ $values { "word" word } { "effect" effect } }
-{ $description "Given a word and a stack effect, executes the word, blindly declaring at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." }
-{ $warning "If the word being executed has an incorrect stack effect, undefined behavior will result. User code should use " { $link execute-effect-unsafe } " instead." } ;
-
-{ call-effect execute-effect execute-effect-unsafe } related-words
-{ POSTPONE: call( POSTPONE: execute( POSTPONE: execute-unsafe( } related-words
\ No newline at end of file
+++ /dev/null
-! Copyright (C) 2009 Daniel Ehrenberg.
-! See http://factorcode.org/license.txt for BSD license.
-USING: math tools.test call call.private kernel accessors ;
-IN: call.tests
-
-[ 3 ] [ 1 2 [ + ] call( x y -- z ) ] unit-test
-[ 1 2 [ + ] call( -- z ) ] must-fail
-[ 1 2 [ + ] call( x y -- z a ) ] must-fail
-[ 1 2 3 { 4 } ] [ 1 2 3 4 [ datastack nip ] call( x -- y ) ] unit-test
-[ [ + ] call( x y -- z ) ] must-infer
-
-[ 3 ] [ 1 2 \ + execute( x y -- z ) ] unit-test
-[ 1 2 \ + execute( -- z ) ] must-fail
-[ 1 2 \ + execute( x y -- z a ) ] must-fail
-[ \ + execute( x y -- z ) ] must-infer
-
-: compile-execute(-test-1 ( a b -- c ) \ + execute( a b -- c ) ;
-
-[ t ] [ \ compile-execute(-test-1 optimized>> ] unit-test
-[ 4 ] [ 1 3 compile-execute(-test-1 ] unit-test
-
-: compile-execute(-test-2 ( a b w -- c ) execute( a b -- c ) ;
-
-[ t ] [ \ compile-execute(-test-2 optimized>> ] unit-test
-[ 4 ] [ 1 3 \ + compile-execute(-test-2 ] unit-test
-[ 5 ] [ 1 4 \ + compile-execute(-test-2 ] unit-test
-[ -3 ] [ 1 4 \ - compile-execute(-test-2 ] unit-test
-[ 5 ] [ 1 4 \ + compile-execute(-test-2 ] unit-test
-
-[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
-[ t ] [ \ + (( a b c -- d e )) execute-effect-unsafe? ] unit-test
-[ f ] [ \ + (( a b c -- d )) execute-effect-unsafe? ] unit-test
-[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
+++ /dev/null
-! Copyright (C) 2009 Daniel Ehrenberg, Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel macros fry summary sequences sequences.private
-generalizations accessors continuations effects effects.parser
-parser words ;
-IN: call
-
-ERROR: wrong-values values quot length-required ;
-
-M: wrong-values summary
- drop "Wrong number of values returned from quotation" ;
-
-<PRIVATE
-
-: firstn-safe ( array quot n -- ... )
- 3dup nip swap length = [ nip firstn ] [ wrong-values ] if ; inline
-
-: parse-call( ( accum word -- accum )
- [ ")" parse-effect parsed ] dip parsed ;
-
-PRIVATE>
-
-MACRO: call-effect ( effect -- quot )
- [ in>> length ] [ out>> length ] bi
- '[ [ _ narray ] dip [ with-datastack ] keep _ firstn-safe ] ;
-
-: call( \ call-effect parse-call( ; parsing
-
-<PRIVATE
-
-: execute-effect-unsafe ( word effect -- )
- drop execute ;
-
-: execute-unsafe( \ execute-effect-unsafe parse-call( ; parsing
-
-: execute-effect-slow ( word effect -- )
- [ [ execute ] curry ] dip call-effect ; inline
-
-: cache-hit? ( word ic -- ? ) first-unsafe eq? ; inline
-
-: cache-hit ( word effect ic -- ) drop execute-effect-unsafe ; inline
-
-: execute-effect-unsafe? ( word effect -- ? )
- over optimized>> [ [ stack-effect ] dip effect<= ] [ 2drop f ] if ; inline
-
-: cache-miss ( word effect ic -- )
- [ 2dup execute-effect-unsafe? ] dip
- '[ [ drop _ set-first ] [ execute-effect-unsafe ] 2bi ]
- [ execute-effect-slow ] if ; inline
-
-: execute-effect-ic ( word effect ic -- )
- #! ic is a mutable cell { effect }
- 3dup nip cache-hit? [ cache-hit ] [ cache-miss ] if ; inline
-
-PRIVATE>
-
-MACRO: execute-effect ( effect -- )
- { f } clone '[ _ _ execute-effect-ic ] ;
-
-: execute( \ execute-effect parse-call( ; parsing
+++ /dev/null
-Calling arbitrary quotations and executing arbitrary words with a static stack effect
+++ /dev/null
-extensions
math namespaces make parser quotations sequences strings words
cocoa.runtime io macros memoize io.encodings.utf8 effects libc
libc.private parser lexer init core-foundation fry generalizations
-specialized-arrays.direct.alien call ;
+specialized-arrays.direct.alien ;
IN: cocoa.messages
: make-sender ( method function -- quot )
: init-method ( method -- sel imp types )
first3 swap
- [ sel_registerName ] [ execute ] [ utf8 string>alien ]
+ [ sel_registerName ] [ execute( -- xt ) ] [ utf8 string>alien ]
tri* ;
: throw-if-false ( obj what -- )
embedded? [
"alien.remote-control"
] [
- main-vocab-hook get [ call ] [ "listener" ] if*
+ main-vocab-hook get [ call( -- vocab ) ] [ "listener" ] if*
] if ;
: default-cli-args ( -- )
dup current-callback eq? [
drop
] [
- yield-hook get call wait-to-return
+ yield-hook get call( -- ) wait-to-return
] if ;
: do-callback ( quot token -- )
] with-return ;
: compile-loop ( deque -- )
- [ (compile) yield-hook get assert-depth ] slurp-deque ;
+ [ (compile) yield-hook get call( -- ) ] slurp-deque ;
: decompile ( word -- )
f 2array 1array modify-code-heap ;
: tuple-class-offset ( -- n ) bootstrap-cell tuple tag-number - ; inline
: class-hash-offset ( -- n ) bootstrap-cell object tag-number - ; inline
: word-xt-offset ( -- n ) 9 bootstrap-cells object tag-number - ; inline
-: quot-xt-offset ( -- n ) 3 bootstrap-cells object tag-number - ; inline
+: quot-xt-offset ( -- n ) 5 bootstrap-cells object tag-number - ; inline
: word-code-offset ( -- n ) 10 bootstrap-cells object tag-number - ; inline
: array-start-offset ( -- n ) 2 bootstrap-cells object tag-number - ; inline
: compiled-header-size ( -- n ) 4 bootstrap-cells ; inline
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel arrays sequences math math.order call
+USING: accessors kernel arrays sequences math math.order
math.partial-dispatch generic generic.standard generic.math
classes.algebra classes.union sets quotations assocs combinators
words namespaces continuations classes fry combinators.smart
eventFlags numEvents <direct-int-array>
eventIds numEvents <direct-longlong-array>
3array flip
- info event-stream-callbacks get at [ drop ] or call ;
+ info event-stream-callbacks get at [ drop ] or call( changes -- ) ;
: master-event-source-callback ( -- alien )
"void"
M: check-mixin-class summary drop "Not a mixin class" ;
M: not-found-in-roots summary drop "Cannot resolve vocab: path" ;
+
+M: wrong-values summary drop "Quotation called with wrong stack effect" ;
\ No newline at end of file
: edit-location ( file line -- )
[ (normalize-path) ] dip edit-hook get-global
- [ call ] [ no-edit-hook edit-location ] if* ;
+ [ call( file line -- ) ] [ no-edit-hook edit-location ] if* ;
ERROR: cannot-find-source definition ;
debugger io.streams.string fry ;
IN: eval
-: parse-string ( str -- )
+: parse-string ( str -- quot )
[ string-lines parse-lines ] with-compilation-unit ;
: (eval) ( str -- )
M: object fake-quotations> ;
-: parse-definition* ( -- )
+: parse-definition* ( accum -- accum )
parse-definition >fake-quotations parsed \ fake-quotations> parsed ;
: DEFINE* ( accum -- accum ) effect get parsed \ define* parsed ;
! See http://factorcode.org/license.txt for BSD license.\r
USING: accessors sequences kernel assocs combinators\r
validators http hashtables namespaces fry continuations locals\r
-io arrays math boxes splitting urls call\r
+io arrays math boxes splitting urls\r
xml.entities\r
http.server\r
http.server.responses\r
! Copyright (c) 2008, 2009 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel math.order namespaces combinators.short-circuit call
+USING: accessors kernel math.order namespaces combinators.short-circuit
html.forms
html.templates
html.templates.chloe
! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel http.server http.server.filters
-http.server.responses furnace.utilities call ;
+http.server.responses furnace.utilities ;
IN: furnace.referrer
TUPLE: referrer-check < filter-responder quot ;
definitions generic quotations effects slots continuations
classes.tuple debugger combinators vocabs help.stylesheet
help.topics help.crossref help.markup sorting classes
-vocabs.loader call ;
+vocabs.loader ;
IN: help
GENERIC: word-help* ( word -- content )
sort-articles [ \ $subsection swap 2array ] map print-element ;
: $index ( element -- )
- first call [ ($index) ] unless-empty ;
+ first call( -- seq ) [ ($index) ] unless-empty ;
: $about ( element -- )
first vocab-help [ 1array $subsection ] when* ;
hashtables sorting effects vocabs vocabs.loader assocs editors
continuations classes.predicate macros math sets eval
vocabs.parser words.symbol values grouping unicode.categories
-sequences.deep call ;
+sequences.deep ;
IN: help.lint
SYMBOL: vocabs-quot
: check-example ( element -- )
- [
- rest [
+ '[
+ _ rest [
but-last "\n" join
[ (eval>string) ] call( code -- output )
"\n" ?tail drop
] keep
peek assert=
- ] vocabs-quot get call ;
+ ] vocabs-quot get call( quot -- ) ;
: check-examples ( element -- )
\ $example swap elements [ check-example ] each ;
hashtables namespaces make parser prettyprint sequences strings
io.styles vectors words math sorting splitting classes slots fry
sets vocabs help.stylesheet help.topics vocabs.loader quotations
-combinators call see ;
+combinators see ;
IN: help.markup
PREDICATE: simple-element < array
! Copyright (C) 2008, 2009 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors strings namespaces assocs hashtables io call
+USING: kernel accessors strings namespaces assocs hashtables io
mirrors math fry sequences words continuations
xml.entities xml.writer xml.syntax ;
IN: html.forms
namespaces make classes.tuple assocs splitting words arrays io
io.files io.files.info io.encodings.utf8 io.streams.string
unicode.case mirrors math urls present multiline quotations xml
-logging call
+logging
xml.data xml.writer xml.syntax strings
html.forms
html
! See http://factorcode.org/license.txt for BSD license.
USING: assocs namespaces make kernel sequences accessors
combinators strings splitting io io.streams.string present
-xml.writer xml.data xml.entities html.forms call
+xml.writer xml.data xml.entities html.forms
html.templates html.templates.chloe.syntax ;
IN: html.templates.chloe.compiler
! See http://factorcode.org/license.txt for BSD license.
USING: continuations sequences kernel namespaces debugger
combinators math quotations generic strings splitting accessors
-assocs fry vocabs.parser parser lexer io io.files call
+assocs fry vocabs.parser parser lexer io io.files
io.streams.string io.encodings.utf8 html.templates ;
IN: html.templates.fhtml
] with-file-vocabs ;
: eval-template ( string -- )
- parse-template call ;
+ parse-template call( -- ) ;
TUPLE: fhtml path ;
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel fry io io.encodings.utf8 io.files
debugger prettyprint continuations namespaces boxes sequences
-arrays strings html io.streams.string assocs call
+arrays strings html io.streams.string assocs
quotations xml.data xml.writer xml.syntax ;
IN: html.templates
io.files.info io.directories io.pathnames io.encodings.binary\r
fry xml.entities destructors urls html xml.syntax\r
html.templates.fhtml http http.server http.server.responses\r
-http.server.redirection xml.writer call ;\r
+http.server.redirection xml.writer ;\r
IN: http.server.static\r
\r
TUPLE: file-responder root hook special allow-listings ;\r
continuations debugger classes.tuple namespaces make vectors
bit-arrays byte-arrays strings sbufs math.functions macros
sequences.private combinators mirrors splitting
-combinators.short-circuit fry words.symbol generalizations call ;
+combinators.short-circuit fry words.symbol generalizations ;
RENAME: _ fry => __
IN: inverse
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: io.encodings io.backend io.ports io.streams.duplex
io splitting grouping sequences namespaces kernel
-destructors math concurrency.combinators accessors
+destructors math concurrency.combinators accessors fry
arrays continuations quotations system vocabs.loader combinators ;
IN: io.pipes
: ?writer ( handle/f -- stream )
[ <output-port> &dispose ] [ output-stream get ] if* ;
-GENERIC: run-pipeline-element ( input-fd output-fd obj -- quot )
+GENERIC: run-pipeline-element ( input-fd output-fd obj -- result )
M: callable run-pipeline-element
[
- [ [ ?reader ] [ ?writer ] bi* ] dip with-streams*
+ [ [ ?reader ] [ ?writer ] bi* ] dip
+ '[ _ call( -- result ) ] with-streams*
] with-destructors ;
: <pipes> ( n -- pipes )
io.sockets.secure io.files io.streams.duplex io.timeouts
io.encodings threads make concurrency.combinators
concurrency.semaphores concurrency.flags
-combinators.short-circuit call ;
+combinators.short-circuit ;
IN: io.servers.connection
TUPLE: threaded-server
namespaces parser lexer sequences strings io.styles
vectors words generic system combinators continuations debugger
definitions compiler.units accessors colors prettyprint fry
-sets vocabs.parser call ;
+sets vocabs.parser ;
IN: listener
GENERIC: stream-read-quot ( stream -- quot/f )
! Copyright (C) 2004, 2008 Chris Double, Matthew Willis, James Cash.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences math vectors arrays namespaces make
-quotations promises combinators io lists accessors call ;
+quotations promises combinators io lists accessors ;
IN: lists.lazy
M: promise car ( promise -- car )
! Copyright (C) 2008, 2009 Slava Pestov.\r
! See http://factorcode.org/license.txt for BSD license.\r
-USING: accessors models kernel call ;\r
+USING: accessors models kernel ;\r
IN: models.arrow\r
\r
TUPLE: arrow < model model quot ;\r
continuations peg peg.parsers unicode.categories multiline\r
splitting accessors effects sequences.deep peg.search\r
combinators.short-circuit lexer io.streams.string stack-checker\r
-io combinators parser call ;\r
+io combinators parser ;\r
IN: peg.ebnf\r
\r
: rule ( name word -- parser )\r
io vectors arrays math.parser math.order vectors combinators
classes sets unicode.categories compiler.units parser words
quotations effects memoize accessors locals effects splitting
-combinators.short-circuit generalizations call ;
+combinators.short-circuit generalizations ;
IN: peg
TUPLE: parse-result remaining ast ;
sequences.private strings sets assocs prettyprint.backend
prettyprint.custom make lexer namespaces parser arrays fry locals
regexp.parser splitting sorting regexp.ast regexp.negation
-regexp.compiler compiler.units words call call.private math.ranges ;
+regexp.compiler compiler.units words math.ranges ;
IN: regexp
TUPLE: regexp
: match-index-from ( i string regexp -- index/f )
! This word is unsafe. It assumes that i is a fixnum
! and that string is a string.
- dup dfa>> execute-unsafe( index string regexp -- i/f ) ; inline
+ dup dfa>> execute( index string regexp -- i/f ) ; inline
GENERIC: end/start ( string regexp -- end start )
M: regexp end/start drop length 0 ;
: do-next-match ( i string regexp -- i start end ? )
dup next-match>>
- execute-unsafe( i string regexp -- i start end ? ) ; inline
+ execute( i string regexp -- i start end ? ) ; inline
:: (each-match) ( i string regexp quot: ( start end string -- ) -- )
i string regexp do-next-match [| i' start end |
--- /dev/null
+Slava Pestov
\ No newline at end of file
--- /dev/null
+USING: stack-checker.call-effect tools.test math kernel ;
+IN: stack-checker.call-effect.tests
+
+[ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
+[ t ] [ \ + (( a b c -- d e )) execute-effect-unsafe? ] unit-test
+[ f ] [ \ + (( a b c -- d )) execute-effect-unsafe? ] unit-test
+[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
\ No newline at end of file
--- /dev/null
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators combinators.private effects fry
+kernel kernel.private make sequences continuations quotations
+stack-checker stack-checker.transforms ;
+IN: stack-checker.call-effect
+
+! call( and execute( have complex expansions.
+
+! call( uses the following strategy:
+! - Inline caching. If the quotation is the same as last time, just call it unsafely
+! - Effect inference. Infer quotation's effect, caching it in the cached-effect slot,
+! and compare it with declaration. If matches, call it unsafely.
+! - Fallback. If the above doesn't work, call it and compare the datastack before
+! and after to make sure it didn't mess anything up.
+
+! execute( uses a similar strategy.
+
+TUPLE: inline-cache value ;
+
+: cache-hit? ( word/quot ic -- ? ) value>> eq? ; inline
+
+SYMBOL: +unknown+
+
+GENERIC: cached-effect ( quot -- effect )
+
+M: object cached-effect drop +unknown+ ;
+
+M: quotation cached-effect
+ dup cached-effect>>
+ [ ] [
+ [ [ infer ] [ 2drop +unknown+ ] recover dup ] keep
+ (>>cached-effect)
+ ] ?if ;
+
+: call-effect-unsafe? ( quot effect -- ? )
+ [ cached-effect ] dip
+ over +unknown+ eq?
+ [ 2drop f ] [ effect<= ] if ; inline
+
+: (call-effect-slow>quot) ( in out effect -- quot )
+ [
+ [ [ datastack ] dip dip ] %
+ [ [ , ] bi@ \ check-datastack , ] dip
+ '[ _ wrong-values ] , \ unless ,
+ ] [ ] make ;
+
+: call-effect-slow>quot ( effect -- quot )
+ [ in>> length ] [ out>> length ] [ ] tri
+ [ (call-effect-slow>quot) ] keep add-effect-input
+ [ call-effect-unsafe ] 2curry ;
+
+: call-effect-slow ( quot effect -- ) drop call ;
+
+\ call-effect-slow [ call-effect-slow>quot ] 1 define-transform
+
+: call-effect-fast ( quot effect inline-cache -- )
+ 2over call-effect-unsafe?
+ [ [ nip (>>value) ] [ drop call-effect-unsafe ] 3bi ]
+ [ drop call-effect-slow ]
+ if ; inline
+
+\ call-effect [
+ inline-cache new '[
+ _
+ 3dup nip cache-hit? [
+ drop call-effect-unsafe
+ ] [
+ call-effect-fast
+ ] if
+ ]
+] 0 define-transform
+
+: execute-effect-slow ( word effect -- )
+ [ '[ _ execute ] ] dip call-effect-slow ; inline
+
+: execute-effect-unsafe? ( word effect -- ? )
+ over optimized>> [ [ stack-effect ] dip effect<= ] [ 2drop f ] if ; inline
+
+: execute-effect-fast ( word effect inline-cache -- )
+ 2over execute-effect-unsafe?
+ [ [ nip (>>value) ] [ drop execute-effect-unsafe ] 3bi ]
+ [ drop execute-effect-slow ]
+ if ; inline
+
+: execute-effect-ic ( word effect inline-cache -- )
+ 3dup nip cache-hit?
+ [ drop execute-effect-unsafe ]
+ [ execute-effect-fast ]
+ if ; inline
+
+: execute-effect>quot ( effect -- quot )
+ inline-cache new '[ _ _ execute-effect-ic ] ;
+
+\ execute-effect [ execute-effect>quot ] 1 define-transform
classes.tuple.private vectors vectors.private words definitions
words.private assocs summary compiler.units system.private
combinators locals locals.backend locals.types words.private
-quotations.private call call.private stack-checker.values
+quotations.private combinators.private stack-checker.values
stack-checker.alien
stack-checker.state
stack-checker.errors
peek-d literal value>> second 1+ { tuple } <effect>
apply-word/effect ;
-: infer-(throw) ( -- )
- \ (throw)
- peek-d literal value>> 2 + { "*" } <effect>
+: infer-effect-unsafe ( word -- )
+ pop-literal nip
+ add-effect-input
apply-word/effect ;
: infer-execute-effect-unsafe ( -- )
- \ execute
- pop-literal nip
- [ in>> "word" suffix ] [ out>> ] [ terminated?>> ] tri
- effect boa
- apply-word/effect ;
+ \ execute infer-effect-unsafe ;
+
+: infer-call-effect-unsafe ( -- )
+ \ call infer-effect-unsafe ;
: infer-exit ( -- )
\ exit (( n -- * )) apply-word/effect ;
{ \ execute [ infer-execute ] }
{ \ (execute) [ infer-execute ] }
{ \ execute-effect-unsafe [ infer-execute-effect-unsafe ] }
+ { \ call-effect-unsafe [ infer-call-effect-unsafe ] }
{ \ if [ infer-if ] }
{ \ dispatch [ infer-dispatch ] }
{ \ <tuple-boa> [ infer-<tuple-boa> ] }
- { \ (throw) [ infer-(throw) ] }
{ \ exit [ infer-exit ] }
{ \ load-local [ 1 infer->r ] }
{ \ load-locals [ infer-load-locals ] }
{
declare call (call) slip 2slip 3slip dip 2dip 3dip curry compose
- execute (execute) execute-effect-unsafe if dispatch <tuple-boa>
- (throw) exit load-local load-locals get-local drop-locals
- do-primitive alien-invoke alien-indirect alien-callback
+ execute (execute) call-effect-unsafe execute-effect-unsafe if
+ dispatch <tuple-boa> exit load-local load-locals get-local
+ drop-locals do-primitive alien-invoke alien-indirect
+ alien-callback
} [ t "special" set-word-prop ] each
{ call execute dispatch load-locals get-local drop-locals }
\ datastack { } { array } define-primitive
\ datastack make-flushable
+\ check-datastack { array integer integer } { object } define-primitive
+\ check-datastack make-flushable
+
\ retainstack { } { array } define-primitive
\ retainstack make-flushable
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel io effects namespaces sequences quotations vocabs
-generic words stack-checker.backend stack-checker.state
+vocabs.loader generic words stack-checker.backend stack-checker.state
stack-checker.known-words stack-checker.transforms
stack-checker.errors stack-checker.inlining
stack-checker.visitor.dummy ;
dup subwords [ f "inferred-effect" set-word-prop ] each
f "inferred-effect" set-word-prop
] each ;
+
+"stack-checker.call-effect" require
\ No newline at end of file
Slava Pestov
+Daniel Ehrenberg
quotations stack-checker accessors combinators words arrays
classes classes.tuple ;
-: compose-n-quot ( word -- quot' ) <repetition> >quotation ;
-: compose-n ( quot -- ) compose-n-quot call ;
+: compose-n-quot ( word n -- quot' ) <repetition> >quotation ;
+: compose-n ( quot n -- ) compose-n-quot call ;
\ compose-n [ compose-n-quot ] 2 define-transform
: compose-n-test ( a b c -- x ) 2 \ + compose-n ;
-! Copyright (C) 2007, 2009 Slava Pestov.
+! Copyright (C) 2007, 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
-USING: fry accessors arrays kernel words sequences generic math
-namespaces make quotations assocs combinators classes.tuple
-classes.tuple.private effects summary hashtables classes generic
-sets definitions generic.standard slots.private continuations locals
-generalizations stack-checker.backend stack-checker.state
-stack-checker.visitor stack-checker.errors stack-checker.values
+USING: fry accessors arrays kernel kernel.private combinators.private
+words sequences generic math namespaces make quotations assocs
+combinators classes.tuple classes.tuple.private effects summary
+hashtables classes generic sets definitions generic.standard
+slots.private continuations locals generalizations
+stack-checker.backend stack-checker.state stack-checker.visitor
+stack-checker.errors stack-checker.values
stack-checker.recursive-state ;
IN: stack-checker.transforms
dup bit-member? [
bit-member-quot
] [
- [ literalize [ t ] ] { } map>assoc
- [ drop f ] suffix [ case ] curry
+ dup length 4 <= [
+ [ drop f ] swap
+ [ literalize [ t ] ] { } map>assoc linear-case-quot
+ ] [
+ unique [ key? ] curry
+ ] if
] if ;
\ member? [
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
! Copyright (C) 2005 Mackenzie Straight.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays hashtables heaps kernel kernel.private math
namespaces sequences vectors continuations continuations.private
-dlists assocs system combinators init boxes accessors
-math.order deques strings quotations fry ;
+dlists assocs system combinators combinators.private init boxes
+accessors math.order deques strings quotations fry ;
IN: threads
SYMBOL: initial-thread
{ } set-retainstack
{ } set-datastack
self quot>> [ call stop ] call-clear
- ] 2 (throw) ;
+ ] (( namestack thread -- * )) call-effect-unsafe ;
DEFER: next
PRIVATE>
: stop ( -- )
- self [ exit-handler>> call ] [ unregister-thread ] bi next ;
+ self [ exit-handler>> call( -- ) ] [ unregister-thread ] bi next ;
: suspend ( quot state -- obj )
[
dup def>> "unannotated-def" set-word-prop ;
: (annotate) ( word quot -- )
- [ dup def>> ] dip call define ; inline
+ [ dup def>> ] dip call( old -- new ) define ;
PRIVATE>
: annotate ( word quot -- )
[ method-spec>word check-annotate-twice ] dip
- [ over save-unannotated-def (annotate) ] with-compilation-unit ; inline
+ [ over save-unannotated-def (annotate) ] with-compilation-unit ;
<PRIVATE
USING: help.markup help.syntax words alien.c-types assocs
-kernel call call.private tools.deploy.config ;
+kernel combinators combinators.private tools.deploy.config ;
IN: tools.deploy
ARTICLE: "prepare-deploy" "Preparing to deploy an application"
{ $heading "Behavior of " { $link boa } }
"In deployed applications, the " { $link boa } " word does not verify that the parameters on the stack satisfy the tuple's slot declarations, if any. This reduces deploy image size but can make bugs harder to track down. Make sure your program is fully debugged before deployment."
{ $heading "Behavior of " { $link POSTPONE: execute( } }
-"Similarly, the " { $link POSTPONE: execute( } " word does not check word stack effects in deployed applications, since stack effects are stripped out, and so it behaves exactly like " { $link POSTPONE: execute-unsafe( } "."
+"Similarly, the " { $link POSTPONE: execute( } " word does not check word stack effects in deployed applications, since stack effects are stripped out, and so it behaves exactly like " { $link POSTPONE: execute-effect-unsafe } "."
{ $heading "Error reporting" }
"If the " { $link deploy-reflection } " level in the configuration is low enough, the debugger is stripped out, and error messages can be rather cryptic. Increase the reflection level to get readable error messages."
{ $heading "Choosing the right deploy flags" }
IN: tools.deploy.tests\r
USING: tools.test system io.pathnames io.files io.files.info\r
-io.files.temp kernel tools.deploy.config\r
-tools.deploy.config.editor tools.deploy.backend math sequences\r
-io.launcher arrays namespaces continuations layouts accessors\r
-io.encodings.ascii urls math.parser io.directories\r
-tools.deploy.test ;\r
+io.files.temp kernel tools.deploy.config tools.deploy.config.editor\r
+tools.deploy.backend math sequences io.launcher arrays namespaces\r
+continuations layouts accessors io.encodings.ascii urls math.parser\r
+io.directories tools.deploy.test ;\r
\r
[ t ] [ "hello-world" shake-and-bake 500000 small-enough? ] unit-test\r
\r
"inline"
"inlined-block"
"input-classes"
+ "instances"
"interval"
"intrinsics"
"lambda"
] 2each ;
: compress-quotations ( -- )
- [ quotation? ] [ remain-compiled ] "quotations" compress ;
+ [ quotation? ] [ remain-compiled ] "quotations" compress
+ [ quotation? ] instances [ f >>cached-effect f >>cache-counter drop ] each ;
: compress-strings ( -- )
[ string? ] [ ] "strings" compress ;
IN: call
USE: call.private
+: call-effect ( word effect -- ) call-effect-unsafe ; inline
+
: execute-effect ( word effect -- ) execute-effect-unsafe ; inline
\ No newline at end of file
! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: call math.parser io math ;
+USING: math.parser io math ;
IN: tools.deploy.test.12
: execute-test ( a b w -- c ) execute( a b -- c ) ;
-: foo ( -- ) 1 2 \ + execute-test number>string print ;
+: call-test ( a b q -- c ) call( a b -- c ) ;
+
+: foo ( -- ) 1 2 \ + execute-test 4 [ * ] call-test number>string print ;
MAIN: foo
\ No newline at end of file
[ this-test get failure ] recover
] [
call
- ] if ;
+ ] if ; inline
: unit-test ( output input -- )
[ 2array ] 2keep '[
} cleave ;
: keyed-vocabs ( str quot -- seq )
- all-vocabs [
- swap [
- [ [ 2dup ] dip swap call member? ] filter
- ] dip swap
- ] assoc-map 2nip ; inline
+ [ all-vocabs ] 2dip '[ [ _ swap @ member? ] filter ] assoc-map ; inline
: tagged ( tag -- assoc )
[ vocab-tags ] keyed-vocabs ;
{ dip [ (step-into-dip) ] }
{ 2dip [ (step-into-2dip) ] }
{ 3dip [ (step-into-3dip) ] }
- { (throw) [ drop (step-into-quot) ] }
{ execute [ (step-into-execute) ] }
{ if [ (step-into-if) ] }
{ dispatch [ (step-into-dispatch) ] }
[ [ ascii? ] all? ] both? [ bad-tr ] unless ;
: compute-tr ( quot from to -- mapping )
- zip [ 128 ] 2dip '[ [ @ _ at ] keep or ] B{ } map-as ; inline
+ [ 128 ] 3dip zip
+ '[ [ _ call( x -- y ) _ at ] keep or ] B{ } map-as ; inline
: tr-hints ( word -- )
{ { byte-array } { string } } "specializer" set-word-prop ;
ui.backend.cocoa.views core-foundation core-foundation.run-loop
core-graphics.types threads math.rectangles fry libc
generalizations alien.c-types cocoa.views
-combinators io.thread locals call ;
+combinators io.thread locals ;
IN: ui.backend.cocoa
TUPLE: handle ;
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays definitions kernel sequences strings
math assocs words generic namespaces make assocs quotations
-splitting ui.gestures unicode.case unicode.categories tr fry
-call ;
+splitting ui.gestures unicode.case unicode.categories tr fry ;
IN: ui.commands
SYMBOL: +nullary+
ui.gadgets.borders ui.gadgets.labels ui.gadgets.tracks
ui.gadgets.packs ui.gadgets.worlds ui.gestures ui.pens ui.pens.solid
ui.pens.image ui.pens.tile math.rectangles locals fry
-combinators.smart call ;
+combinators.smart ;
IN: ui.gadgets.buttons
TUPLE: button < border pressed? selected? quot ;
} define-command-map
: clear-editor ( editor -- )
- #! The with-datastack is a kludge to make it infer. Stupid.
- model>> 1array [ clear-doc ] with-datastack drop ;
+ model>> clear-doc ;
: select-all ( editor -- ) doc-elt select-elt ;
[ editor>> editor-string ]
[ editor>> clear-editor ]
[ quot>> ]
- tri call ;
+ tri call( string -- ) ;
action-field H{
{ T{ key-down f f "RET" } [ invoke-action-field ] }
ui.gadgets.menus ui.clipboards ui.gestures ui.traverse ui.render
ui.text ui.gadgets.presentations ui.gadgets.grids ui.gadgets.tracks
ui.gadgets.icons ui.gadgets.grid-lines ui.baseline-alignment
-colors call io.styles ;
+colors io.styles ;
IN: ui.gadgets.panes
TUPLE: pane < track
! Copyright (C) 2005, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs continuations kernel math models
-call namespaces opengl sequences io combinators
-combinators.short-circuit fry math.vectors math.rectangles cache
-ui.gadgets ui.gestures ui.render ui.text ui.text.private
-ui.backend ui.gadgets.tracks ui.commands ;
+namespaces opengl sequences io combinators combinators.short-circuit
+fry math.vectors math.rectangles cache ui.gadgets ui.gestures
+ui.render ui.text ui.text.private ui.backend ui.gadgets.tracks
+ui.commands ;
IN: ui.gadgets.worlds
TUPLE: world < track
namespaces make sequences words strings system hashtables math.parser
math.vectors classes.tuple classes boxes calendar alarms combinators
sets columns fry deques ui.gadgets ui.gadgets.private unicode.case
-unicode.categories combinators.short-circuit call ;
+unicode.categories combinators.short-circuit ;
IN: ui.gestures
GENERIC: handle-gesture ( gesture gadget -- ? )
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays definitions kernel ui.commands
ui.gestures sequences strings math words generic namespaces
-hashtables help.markup quotations assocs fry call linked-assocs ;
+hashtables help.markup quotations assocs fry linked-assocs ;
IN: ui.operations
SYMBOL: +keyboard+
[
dup find-walker-window dup
- [ raise-window 3drop ] [ drop [ walker-window ] with-ui ] if
+ [ raise-window 3drop ] [ drop '[ _ _ _ walker-window ] with-ui ] if
] show-walker-hook set-global
! Copyright (C) 2006, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays assocs io kernel math models namespaces make dlists
-deques sequences threads sequences words continuations init call
+deques sequences threads sequences words continuations init
combinators hashtables concurrency.flags sets accessors calendar fry
destructors ui.gadgets ui.gadgets.private ui.gadgets.worlds
ui.gadgets.tracks ui.gestures ui.backend ui.render ui.text
! Copyright (C) 2009 Daniel Ehrenberg
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences math arrays locals fry accessors
-lists splitting call make combinators.short-circuit namespaces
+lists splitting make combinators.short-circuit namespaces
grouping splitting.monotonic ;
IN: wrap
: RULE:
scan scan-word scan-word [
- parse-definition { } make
+ [ parse-definition call( -- ) ] { } make
swap [ (parse-rule-tag) ] 2curry
] dip swap define-tag ; parsing
"word" "words" create register-builtin
"byte-array" "byte-arrays" create register-builtin
-! For predicate classes
-"predicate-instance?" "classes.predicate" create drop
-
! We need this before defining c-ptr below
"f" "syntax" lookup { } define-builtin
"quotation" "quotations" create {
{ "array" { "array" "arrays" } read-only }
{ "compiled" read-only }
+ "cached-effect"
+ "cache-counter"
} define-builtin
"dll" "alien" create {
{ "set-alien-double" "alien.accessors" }
{ "alien-cell" "alien.accessors" }
{ "set-alien-cell" "alien.accessors" }
- { "(throw)" "kernel.private" }
{ "alien-address" "alien" }
{ "set-slot" "slots.private" }
{ "string-nth" "strings.private" }
{ "gc-reset" "memory" }
{ "jit-compile" "quotations" }
{ "load-locals" "locals.backend" }
+ { "check-datastack" "kernel.private" }
}
[ [ first2 ] dip make-primitive ] each-index
"call-next-method"
"initial:"
"read-only"
+ "call("
+ "execute("
} [ "syntax" create drop ] each
"t" "syntax" lookup define-symbol
[ 10 ] [ -10 abs ] unit-test
[ 10 ] [ 10 abs ] unit-test
-[ 0 ] [ 0 abs ] unit-test
-
-PREDICATE: blah < word blah eq? ;
-
-[ f ] [ \ predicate-instance? "compiled-uses" word-prop keys \ blah swap memq? ] unit-test
-
-FORGET: blah
\ No newline at end of file
+[ 0 ] [ 0 abs ] unit-test
\ No newline at end of file
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: classes classes.algebra kernel namespaces make words
sequences quotations arrays kernel.private assocs combinators ;
PREDICATE: predicate-class < class
"metaclass" word-prop predicate-class eq? ;
-DEFER: predicate-instance? ( object class -- ? )
-
-: update-predicate-instance ( -- )
- \ predicate-instance? bootstrap-word
- classes [ predicate-class? ] filter [
- [ literalize ]
- [
- [ superclass 1array [ declare ] curry ]
- [ "predicate-definition" word-prop ]
- bi compose
- ]
- bi
- ] { } map>assoc [ case ] curry
- define ;
-
: predicate-quot ( class -- quot )
[
\ dup ,
[ dup predicate-quot define-predicate ]
[ update-classes ]
bi
- ]
- 3tri
- update-predicate-instance ;
+ ] 3tri ;
M: predicate-class reset-class
- [ call-next-method ] [ { "predicate-definition" } reset-props ] bi
- update-predicate-instance ;
+ [ call-next-method ] [ { "predicate-definition" } reset-props ] bi ;
M: predicate-class rank-class drop 1 ;
M: predicate-class instance?
- 2dup superclass instance?
- [ predicate-instance? ] [ 2drop f ] if ;
+ 2dup superclass instance? [
+ "predicate-definition" word-prop call( object -- ? )
+ ] [ 2drop f ] if ;
M: predicate-class (flatten-class)
superclass (flatten-class) ;
ERROR: invalid-slot-name name ;
-: parse-long-slot-name ( -- )
+: parse-long-slot-name ( -- spec )
[ scan , \ } parse-until % ] { } make ;
: parse-slot-name ( string/f -- ? )
: parse-slot-value ( -- )
scan scan-object 2array , scan {
- { f [ unexpected-eof ] }
+ { f [ \ } unexpected-eof ] }
{ "}" [ ] }
[ bad-literal-tuple ]
} case ;
: (parse-slot-values) ( -- )
parse-slot-value
scan {
- { f [ unexpected-eof ] }
+ { f [ \ } unexpected-eof ] }
{ "{" [ (parse-slot-values) ] }
{ "}" [ ] }
[ bad-literal-tuple ]
} case ;
-: parse-slot-values ( -- )
+: parse-slot-values ( -- values )
[ (parse-slot-values) ] { } make ;
: boa>tuple ( class slots -- tuple )
Slava Pestov
+Daniel Ehrenberg
USING: arrays help.markup help.syntax strings sbufs vectors
kernel quotations generic generic.standard classes
-math assocs sequences sequences.private ;
+math assocs sequences sequences.private combinators.private
+effects words ;
IN: combinators
ARTICLE: "combinators-quot" "Quotation construction utilities"
{ $subsection case>quot }
{ $subsection alist>quot } ;
+ARTICLE: "call" "Calling code with known stack effects"
+"Arbitrary quotations and words can be called from code accepted by the optimizing compiler. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate."
+$nl
+"Quotations:"
+{ $subsection POSTPONE: call( }
+{ $subsection call-effect }
+"Words:"
+{ $subsection POSTPONE: execute( }
+{ $subsection execute-effect }
+"Unsafe calls:"
+{ $subsection call-effect-unsafe }
+{ $subsection execute-effect-unsafe } ;
+
ARTICLE: "combinators" "Additional combinators"
"The " { $vocab-link "combinators" } " vocabulary provides a few useful combinators."
$nl
$nl
"A combinator which can help with implementing methods on " { $link hashcode* } ":"
{ $subsection recursive-hashcode }
+{ $subsection "call" }
{ $subsection "combinators-quot" }
{ $see-also "quotations" "dataflow" } ;
ABOUT: "combinators"
+HELP: call-effect
+{ $values { "quot" quotation } { "effect" effect } }
+{ $description "Given a quotation and a stack effect, calls the quotation, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary quotation which is not required at compile time." } ;
+
+HELP: execute-effect
+{ $values { "word" word } { "effect" effect } }
+{ $description "Given a word and a stack effect, executes the word, asserting at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." } ;
+
+HELP: execute-effect-unsafe
+{ $values { "word" word } { "effect" effect } }
+{ $description "Given a word and a stack effect, executes the word, blindly declaring at runtime that it has the given stack effect. This is a macro which expands given a literal effect parameter, and an arbitrary word which is not required at compile time." }
+{ $warning "If the word being executed has an incorrect stack effect, undefined behavior will result. User code should use " { $link POSTPONE: execute( } " instead." } ;
+
+{ call-effect call-effect-unsafe execute-effect execute-effect-unsafe } related-words
+
HELP: cleave
{ $values { "x" object } { "seq" "a sequence of quotations with stack effect " { $snippet "( x -- ... )" } } }
{ $description "Applies each quotation to the object in turn." }
math.functions arrays ;
IN: combinators.tests
+[ 3 ] [ 1 2 [ + ] call( x y -- z ) ] unit-test
+[ 1 2 [ + ] call( -- z ) ] must-fail
+[ 1 2 [ + ] call( x y -- z a ) ] must-fail
+[ 1 2 3 { 1 2 3 4 } ] [ 1 2 3 4 [ datastack nip ] call( x -- y ) ] unit-test
+[ [ + ] call( x y -- z ) ] must-infer
+
+[ 3 ] [ 1 2 \ + execute( x y -- z ) ] unit-test
+[ 1 2 \ + execute( -- z ) ] must-fail
+[ 1 2 \ + execute( x y -- z a ) ] must-fail
+[ \ + execute( x y -- z ) ] must-infer
+
+: compile-execute(-test-1 ( a b -- c ) \ + execute( a b -- c ) ;
+
+[ t ] [ \ compile-execute(-test-1 optimized>> ] unit-test
+[ 4 ] [ 1 3 compile-execute(-test-1 ] unit-test
+
+: compile-execute(-test-2 ( a b w -- c ) execute( a b -- c ) ;
+
+[ t ] [ \ compile-execute(-test-2 optimized>> ] unit-test
+[ 4 ] [ 1 3 \ + compile-execute(-test-2 ] unit-test
+[ 5 ] [ 1 4 \ + compile-execute(-test-2 ] unit-test
+[ -3 ] [ 1 4 \ - compile-execute(-test-2 ] unit-test
+[ 5 ] [ 1 4 \ + compile-execute(-test-2 ] unit-test
+
+: compile-call(-test-1 ( a b q -- c ) call( a b -- c ) ;
+
+[ t ] [ \ compile-call(-test-1 optimized>> ] unit-test
+[ 4 ] [ 1 3 [ + ] compile-call(-test-1 ] unit-test
+[ 7 ] [ 1 3 2 [ * + ] curry compile-call(-test-1 ] unit-test
+[ 7 ] [ 1 3 [ 2 * ] [ + ] compose compile-call(-test-1 ] unit-test
+[ 4 ] [ 1 3 [ { + } [ ] like call ] compile-call(-test-1 ] unit-test
+
! Compiled
: cond-test-1 ( obj -- str )
{
-! Copyright (C) 2006, 2008 Slava Pestov.
+! Copyright (C) 2006, 2009 Slava Pestov, Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays sequences sequences.private math.private
kernel kernel.private math assocs quotations vectors
hashtables sorting words sets math.order make ;
IN: combinators
+<PRIVATE
+
+: call-effect-unsafe ( quot effect -- ) drop call ;
+
+: execute-effect-unsafe ( word effect -- ) drop execute ;
+
+M: object throw 5 getenv [ die ] or (( error -- * )) call-effect-unsafe ;
+
+PRIVATE>
+
+ERROR: wrong-values effect ;
+
+! We can't USE: effects here so we forward reference slots instead
+SLOT: in
+SLOT: out
+
+: call-effect ( quot effect -- )
+ [ [ datastack ] dip dip ] dip
+ [ in>> length ] [ out>> length ] [ ] tri [ check-datastack ] dip
+ [ wrong-values ] curry unless ;
+
+: execute-effect ( word effect -- )
+ [ [ execute ] curry ] dip call-effect ;
+
! cleave
: cleave ( x seq -- )
[ call ] with each ;
{ $subsection with-return }
"Reflecting the datastack:"
{ $subsection with-datastack }
-{ $subsection assert-depth }
"Continuations serve as the building block for a number of higher-level abstractions, such as " { $link "errors" } " and " { $link "threads" } "."
{ $subsection "continuations.private" } ;
{ $example "USING: continuations math prettyprint ;" "{ 3 7 } [ + ] with-datastack ." "{ 10 }" }
} ;
-HELP: assert-depth
-{ $values { "quot" "a quotation" } }
-{ $description "Runs a quotation. Throws an error if the quotation attempts to take input values from the stack, or leave outputs on the stack." } ;
-
HELP: attempt-all
{ $values
{ "seq" sequence } { "quot" quotation }
-! Copyright (C) 2003, 2008 Slava Pestov.
+! Copyright (C) 2003, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays vectors kernel kernel.private sequences
namespaces make math splitting sorting quotations assocs
-combinators accessors ;
+combinators combinators.private accessors ;
IN: continuations
SYMBOL: error
<PRIVATE
-: (continue) ( continuation -- )
+: (continue) ( continuation -- * )
>continuation<
set-catchstack
set-namestack
[ set-datastack ] dip
set-callstack ;
-: (continue-with) ( obj continuation -- )
- swap 4 setenv
- >continuation<
- set-catchstack
- set-namestack
- set-retainstack
- [ set-datastack drop 4 getenv f 4 setenv f ] dip
- set-callstack ;
-
PRIVATE>
: continue-with ( obj continuation -- * )
- [ (continue-with) ] 2 (throw) ;
+ [
+ swap 4 setenv
+ >continuation<
+ set-catchstack
+ set-namestack
+ set-retainstack
+ [ set-datastack drop 4 getenv f 4 setenv f ] dip
+ set-callstack
+ ] (( obj continuation -- * )) call-effect-unsafe ;
: continue ( continuation -- * )
f swap continue-with ;
[
[ [ { } like set-datastack ] dip call datastack ] dip
continue-with
- ] 3 (throw)
+ ] (( stack quot continuation -- * )) call-effect-unsafe
] callcc1 2nip ;
-: assert-depth ( quot -- )
- { } swap with-datastack { } assert= ; inline
-
GENERIC: compute-restarts ( error -- seq )
<PRIVATE
dup save-error
catchstack* empty? [
thread-error-hook get-global
- [ 1 (throw) ] [ die ] if*
+ [ (( error -- * )) call-effect-unsafe ] [ die ] if*
] when
c> continue-with ;
: shuffle ( stack shuffle -- newstack )
shuffle-mapping swap nths ;
+
+: add-effect-input ( effect -- effect' )
+ [ in>> "obj" suffix ] [ out>> ] [ terminated?>> ] tri effect boa ;
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: lexer sets sequences kernel splitting effects
combinators arrays parser ;
: parse-effect ( end -- effect )
parse-effect-tokens { "--" } split1 dup
[ <effect> ] [ "Stack effect declaration must contain --" throw ] if ;
+
+: parse-call( ( accum word -- accum )
+ [ ")" parse-effect parsed ] dip parsed ;
\ No newline at end of file
: with-method-definition ( method quot -- )
over current-method set call current-method off ; inline
-: (M:) ( method def -- )
+: (M:) ( -- method def )
CREATE-METHOD [ parse-definition ] with-method-definition ;
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: continuations continuations.private kernel
kernel.private sequences assocs namespaces namespaces.private ;
init-hooks global [ drop V{ } clone ] cache drop
: do-init-hooks ( -- )
- init-hooks get [ nip call ] assoc-each ;
+ init-hooks get [ nip call( -- ) ] assoc-each ;
: add-init-hook ( quot name -- )
- dup init-hooks get at [ over call ] unless
+ dup init-hooks get at [ over call( -- ) ] unless
init-hooks get set-at ;
: boot ( -- ) init-namespaces init-catchstack init-error-handler ;
: set-io-backend ( io-backend -- )
io-backend set-global init-io init-stdio
- "io.files" init-hooks get at call ;
+ "io.files" init-hooks get at call( -- ) ;
! Note that we have 'alien' in our using list so that the alien
! init hook runs before this one.
! Combinators
GENERIC: call ( callable -- )
+GENERIC: execute ( word -- )
+
DEFER: if
: ? ( ? true false -- true/false )
! Error handling -- defined early so that other files can
! throw errors before continuations are loaded
-: throw ( error -- * ) 5 getenv [ die ] or 1 (throw) ;
+GENERIC: throw ( error -- * )
ERROR: assert got expect ;
[ t ] [ "foo" "parser.tests" lookup symbol? ] unit-test
] times
-[ "vocab:parser/test/assert-depth.factor" run-file ]
-[ got>> { 1 2 3 } sequence= ]
-must-fail-with
+[ "vocab:parser/test/assert-depth.factor" run-file ] must-fail
2 [
[ ] [
-! Copyright (C) 2005, 2008 Slava Pestov.
+! Copyright (C) 2005, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays definitions generic assocs kernel math namespaces
-sequences strings vectors words words.symbol quotations io
-combinators sorting splitting math.parser effects continuations
-io.files vocabs io.encodings.utf8 source-files
-classes hashtables compiler.errors compiler.units accessors sets
-lexer vocabs.parser slots ;
+sequences strings vectors words words.symbol quotations io combinators
+sorting splitting math.parser effects continuations io.files vocabs
+io.encodings.utf8 source-files classes hashtables compiler.errors
+compiler.units accessors sets lexer vocabs.parser slots ;
IN: parser
: location ( -- loc )
ERROR: staging-violation word ;
-: execute-parsing ( word -- )
+: execute-parsing ( accum word -- accum )
dup changed-definitions get key? [ staging-violation ] when
- execute ;
+ execute( accum -- accum ) ;
: scan-object ( -- object )
scan-word dup parsing-word?
[ f parse-until >quotation ] with-lexer ;
: parse-lines ( lines -- quot )
- lexer-factory get call (parse-lines) ;
+ lexer-factory get call( lines -- lexer ) (parse-lines) ;
: parse-literal ( accum end quot -- accum )
[ parse-until ] dip call parsed ; inline
[
V{ } clone amended-use set
parse-lines
- amended-use get empty? [ print-use-hook get call ] unless
+ amended-use get empty? [ print-use-hook get call( -- ) ] unless
] with-file-vocabs ;
: parsing-file ( file -- )
] recover ;
: run-file ( file -- )
- [ parse-file call ] curry assert-depth ;
+ parse-file call( -- ) ;
: ?run-file ( path -- )
dup exists? [ run-file ] [ drop ] if ;
: unicode-escape ( str -- ch str' )
"{" ?head-slice [
CHAR: } over index cut-slice
- [ >string name>char-hook get call ] dip
+ [ >string name>char-hook get call( name -- char ) ] dip
rest-slice
] [
6 cut-slice [ hex> ] dip
: (parse-string) ( str -- m )
dup [ "\"\\" member? ] find dup [
[ cut-slice [ % ] dip rest-slice ] dip
- dup CHAR: " = [
- drop from>>
+ CHAR: " = [
+ from>>
] [
- drop next-escape [ , ] dip (parse-string)
+ next-escape [ , ] dip (parse-string)
] if
] [
"Unterminated string" throw
[ swap tail-slice (parse-string) ] "" make swap
] change-lexer-column ;
-: (unescape-string) ( str -- str' )
- dup [ CHAR: \\ = ] find [
+: (unescape-string) ( str -- )
+ CHAR: \\ over index dup [
cut-slice [ % ] dip rest-slice
next-escape [ , ] dip
(unescape-string)
{ POSTPONE: call-next-method (call-next-method) next-method } related-words
{ POSTPONE: << POSTPONE: >> } related-words
+
+HELP: call(
+{ $syntax "call( stack -- effect )" }
+{ $description "Calls the quotation on the top of the stack, asserting that it has the given stack effect. The quotation does not need to be known at compile time." } ;
+
+HELP: execute(
+{ $syntax "execute( stack -- effect )" }
+{ $description "Calls the word on the top of the stack, asserting that it has the given stack effect. The word does not need to be known at compile time." } ;
+
+{ POSTPONE: call( POSTPONE: execute( } related-words
\ No newline at end of file
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien arrays byte-arrays definitions generic
hashtables kernel math namespaces parser lexer sequences strings
scan {
{ [ dup length 1 = ] [ first ] }
{ [ "\\" ?head ] [ next-escape >string "" assert= ] }
- [ name>char-hook get call ]
+ [ name>char-hook get call( name -- char ) ]
} cond parsed
] define-syntax
"<<" [
[
\ >> parse-until >quotation
- ] with-nested-compilation-unit call
+ ] with-nested-compilation-unit call( -- )
] define-syntax
"call-next-method" [
"initial:" "syntax" lookup define-symbol
"read-only" "syntax" lookup define-symbol
+
+ "call(" [ \ call-effect parse-call( ] define-syntax
+
+ "execute(" [ \ execute-effect parse-call( ] define-syntax
] with-compilation-unit
+parsing+ >>source-loaded?
dup vocab-source-path [ parse-file ] [ [ ] ] if*
[ +parsing+ >>source-loaded? ] dip
- [ % ] [ assert-depth ] if-bootstrapping
+ [ % ] [ call( -- ) ] if-bootstrapping
+done+ >>source-loaded? drop
] [ ] [ f >>source-loaded? ] cleanup ;
: run ( vocab -- )
dup load-vocab vocab-main [
- execute
+ execute( -- )
] [
"The " write vocab-name write
" vocabulary does not define an entry point." print
SYMBOL: load-vocab-hook ! ( name -- vocab )
-: load-vocab ( name -- vocab ) load-vocab-hook get call ;
\ No newline at end of file
+: load-vocab ( name -- vocab ) load-vocab-hook get call( name -- vocab ) ;
\ No newline at end of file
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays definitions graphs assocs kernel
kernel.private slots.private math namespaces sequences strings
: set-word ( word -- ) \ word set-global ;
-GENERIC: execute ( word -- )
-
M: word execute (execute) ;
M: word <=>
colors.constants\r
prettyprint\r
vars\r
-call\r
quotations\r
io\r
io.directories\r
LAZY: nats-from ( n -- list )
dup 1+ nats-from cons ;
-: nats 0 nats-from ;
+: nats ( -- list ) 0 nats-from ;
[ 3 ] [
{
IN: monads
! Functors
-GENERIC# fmap 1 ( functor quot -- functor' ) inline
+GENERIC# fmap 1 ( functor quot -- functor' )
! Monads
M: monad return monad-of return ;
M: monad fail monad-of fail ;
-: bind ( mvalue quot -- mvalue' ) swap >>= call ;
+: bind ( mvalue quot -- mvalue' ) swap >>= call( quot -- mvalue ) ;
: >> ( mvalue k -- mvalue' ) '[ drop _ ] bind ;
:: lift-m2 ( m1 m2 f monad -- m3 )
:: apply ( mvalue mquot monad -- result )
mvalue [| value |
mquot [| quot |
- value quot call monad return
+ value quot call( value -- mvalue ) monad return
] bind
] bind ;
M: monad fmap over '[ @ _ return ] bind ;
! 'do' notation
-: do ( quots -- result ) unclip dip [ bind ] each ;
+: do ( quots -- result ) unclip [ call( -- mvalue ) ] curry dip [ bind ] each ;
! Identity
SINGLETON: identity-monad
M: identity-monad return drop identity boa ;
M: identity-monad fail "Fail" throw ;
-M: identity >>= value>> '[ _ swap call ] ;
+M: identity >>= value>> '[ _ swap call( x -- y ) ] ;
: run-identity ( identity -- value ) value>> ;
M: maybe-monad fail 2drop nothing ;
M: nothing >>= '[ drop _ ] ;
-M: just >>= value>> '[ _ swap call ] ;
+M: just >>= value>> '[ _ swap call( x -- y ) ] ;
: if-maybe ( maybe just-quot nothing-quot -- )
pick nothing? [ 2nip call ] [ drop [ value>> ] dip call ] if ; inline
M: either-monad fail drop left ;
M: left >>= '[ drop _ ] ;
-M: right >>= value>> '[ _ swap call ] ;
+M: right >>= value>> '[ _ swap call( x -- y ) ] ;
: if-either ( value left-quot right-quot -- )
[ [ value>> ] [ left? ] bi ] 2dip if ; inline
M: state-monad return drop '[ _ 2array ] state ;
M: state-monad fail "Fail" throw ;
-: mcall ( state -- ) quot>> call ;
+: mcall ( x state -- y ) quot>> call( x -- y ) ;
M: state >>= '[ _ swap '[ _ mcall first2 @ mcall ] state ] ;
: get-st ( -- state ) [ dup 2array ] state ;
: put-st ( value -- state ) '[ drop _ f 2array ] state ;
-: run-st ( state initial -- ) swap mcall second ;
+: run-st ( state initial -- value ) swap mcall second ;
: return-st ( value -- mvalue ) state-monad return ;
M: reader >>= '[ _ swap '[ dup _ mcall @ mcall ] reader ] ;
-: run-reader ( reader env -- ) swap mcall ;
+: run-reader ( reader env -- value ) swap quot>> call( env -- value ) ;
: ask ( -- reader ) [ ] reader ;
: local ( reader quot -- reader' ) swap '[ @ _ mcall ] reader ;
M: writer >>= '[ [ _ run-writer ] dip '[ @ run-writer ] dip append writer ] ;
-: pass ( writer -- writer' ) run-writer [ first2 ] dip swap call writer ;
+: pass ( writer -- writer' ) run-writer [ first2 ] dip swap call( x -- y ) writer ;
: listen ( writer -- writer' ) run-writer [ 2array ] keep writer ;
: tell ( seq -- writer ) f swap writer ;
! Copyright (C) 2004, 2006 Chris Double, Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
-USING: arrays kernel sequences math vectors arrays namespaces call
+USING: arrays kernel sequences math vectors arrays namespaces
make quotations parser effects stack-checker words accessors ;
IN: promises
! Copyright (C) 2006, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors math.vectors classes.tuple math.rectangles colors
-kernel sequences models opengl math math.order namespaces call
+kernel sequences models opengl math math.order namespaces
ui.commands ui.gestures ui.render ui.gadgets ui.gadgets.labels
ui.gadgets.scrollers ui.gadgets.presentations ui.gadgets.viewports
ui.gadgets.packs ;
CELL frame_type(F_STACK_FRAME *frame);
void primitive_callstack(void);
-void primitive_set_datastack(void);
-void primitive_set_retainstack(void);
void primitive_set_callstack(void);
void primitive_callstack_to_array(void);
void primitive_innermost_stack_frame_quot(void);
pop %ebp ; \
pop %ebx
-#define QUOT_XT_OFFSET 9
+#define QUOT_XT_OFFSET 17
/* We pass a function pointer to memcpy to work around a Mac OS X
ABI limitation which would otherwise require us to do a bizzaro PC-relative
#endif
-#define QUOT_XT_OFFSET 21
+#define QUOT_XT_OFFSET 37
/* We pass a function pointer to memcpy to work around a Mac OS X
ABI limitation which would otherwise require us to do a bizzaro PC-relative
signal_error(signal_number,signal_callstack_top);
}
-void primitive_throw(void)
-{
- dpop();
- throw_impl(dpop(),stack_chain->callstack_top);
-}
-
void primitive_call_clear(void)
{
throw_impl(dpop(),stack_chain->callstack_bottom);
void type_error(CELL type, CELL tagged);
void not_implemented_error(void);
-void primitive_throw(void);
void primitive_call_clear(void);
INLINE void type_check(CELL type, CELL tagged)
CELL array;
/* tagged */
CELL compiledp;
+ /* tagged */
+ CELL cached_effect;
+ /* tagged */
+ CELL cache_counter;
/* UNTAGGED */
XT xt;
/* UNTAGGED compiled code block */
primitive_set_alien_double,
primitive_alien_cell,
primitive_set_alien_cell,
- primitive_throw,
primitive_alien_address,
primitive_set_slot,
primitive_string_nth,
primitive_clear_gc_stats,
primitive_jit_compile,
primitive_load_locals,
+ primitive_check_datastack
};
quot->array = dpeek();
quot->xt = lazy_jit_compile;
quot->compiledp = F;
+ quot->cached_effect = F;
+ quot->cache_counter = F;
drepl(tag_object(quot));
}
rs = array_to_stack(untag_array(dpop()),rs_bot);
}
+/* Used to implement call( */
+void primitive_check_datastack(void)
+{
+ F_FIXNUM out = to_fixnum(dpop());
+ F_FIXNUM in = to_fixnum(dpop());
+ F_FIXNUM height = out - in;
+ F_ARRAY *array = untag_array(dpop());
+ F_FIXNUM length = array_capacity(array);
+ F_FIXNUM depth = (ds - ds_bot + CELLS) / CELLS;
+ if(depth - height != length)
+ dpush(F);
+ else
+ {
+ F_FIXNUM i;
+ for(i = 0; i < length - in; i++)
+ {
+ if(get(ds_bot + i * CELLS) != array_nth(array,i))
+ {
+ dpush(F);
+ return;
+ }
+ }
+ dpush(T);
+ }
+}
+
void primitive_getenv(void)
{
F_FIXNUM e = untag_fixnum_fast(dpeek());
void primitive_datastack(void);
void primitive_retainstack(void);
+void primitive_set_datastack(void);
+void primitive_set_retainstack(void);
+void primitive_check_datastack(void);
void primitive_getenv(void);
void primitive_setenv(void);
void primitive_exit(void);