diff --git a/basis/compiler/tree/propagation/known-words/known-words.factor b/basis/compiler/tree/propagation/known-words/known-words.factor index 4d8d935477..d5aa5318a4 100644 --- a/basis/compiler/tree/propagation/known-words/known-words.factor +++ b/basis/compiler/tree/propagation/known-words/known-words.factor @@ -6,7 +6,7 @@ math.parser math.order layouts words sequences sequences.private arrays assocs classes classes.algebra combinators generic.math splitting fry locals classes.tuple alien.accessors classes.tuple.private slots.private definitions strings.private -vectors hashtables +vectors hashtables generic stack-checker.state compiler.tree.comparisons compiler.tree.propagation.info @@ -337,3 +337,12 @@ generic-comparison-ops [ bi ] [ 2drop object-info ] if ] "outputs" set-word-prop + +\ equal? [ + ! If first input has a known type and second input is an + ! object, we convert this to [ swap equal? ]. + in-d>> first2 value-info class>> object class= [ + value-info class>> \ equal? specific-method + [ swap equal? ] f ? + ] [ drop f ] if +] "custom-inlining" set-word-prop diff --git a/basis/compiler/tree/propagation/propagation-tests.factor b/basis/compiler/tree/propagation/propagation-tests.factor index d95245fe83..b324dc0fc2 100644 --- a/basis/compiler/tree/propagation/propagation-tests.factor +++ b/basis/compiler/tree/propagation/propagation-tests.factor @@ -640,6 +640,10 @@ MIXIN: empty-mixin [ { fixnum } declare log2 0 >= ] final-classes ] unit-test +[ V{ POSTPONE: f } ] [ + [ { word object } declare eq? ] final-classes +] unit-test + ! [ V{ string } ] [ ! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes ! ] unit-test diff --git a/basis/hints/hints.factor b/basis/hints/hints.factor index 240acf74b1..b6af773ce5 100644 --- a/basis/hints/hints.factor +++ b/basis/hints/hints.factor @@ -3,7 +3,8 @@ USING: parser words definitions kernel sequences assocs arrays kernel.private fry combinators accessors vectors strings sbufs byte-arrays byte-vectors io.binary io.streams.string splitting -math generic generic.standard generic.standard.engines classes ; +math generic generic.standard generic.standard.engines classes +hashtables ; IN: hints GENERIC: specializer-predicate ( spec -- quot ) @@ -50,14 +51,10 @@ M: object specializer-declaration class ; ] [ drop f ] if ; : specialized-def ( word -- quot ) - dup def>> swap { - { - [ dup "specializer" word-prop ] - [ "specializer" word-prop specialize-quot ] - } - { [ dup standard-method? ] [ specialize-method ] } - [ drop ] - } cond ; + [ def>> ] keep + [ dup standard-method? [ specialize-method ] [ drop ] if ] + [ "specializer" word-prop [ specialize-quot ] when* ] + bi ; : specialized-length ( specializer -- n ) dup [ array? ] all? [ first ] when length ; @@ -120,3 +117,7 @@ M: object specializer-declaration class ; \ >le { { fixnum fixnum } { bignum fixnum } } "specializer" set-word-prop \ >be { { bignum fixnum } { fixnum fixnum } } "specializer" set-word-prop + +\ hashtable \ at* method { { fixnum hashtable } { word hashtable } } "specializer" set-word-prop + +\ hashtable \ set-at method { { object fixnum object } { object word object } } "specializer" set-word-prop diff --git a/basis/io/files/windows/nt/nt.factor b/basis/io/files/windows/nt/nt.factor index d0d9d5174a..3241d19efa 100755 --- a/basis/io/files/windows/nt/nt.factor +++ b/basis/io/files/windows/nt/nt.factor @@ -4,7 +4,7 @@ io.backend.windows io.files.windows io.encodings.utf16n windows windows.kernel32 kernel libc math threads system environment alien.c-types alien.arrays alien.strings sequences combinators combinators.short-circuit ascii splitting alien strings assocs -namespaces make accessors tr ; +namespaces make accessors tr windows.time ; IN: io.files.windows.nt M: winnt cwd @@ -44,8 +44,18 @@ M: winnt normalize-path ( string -- string' ) M: winnt CreateFile-flags ( DWORD -- DWORD ) FILE_FLAG_OVERLAPPED bitor ; + + [ GetFileAttributesEx win32-error=0/f ] keep + [ WIN32_FILE_ATTRIBUTE_DATA-nFileSizeLow ] + [ WIN32_FILE_ATTRIBUTE_DATA-nFileSizeHigh ] bi >64bit ; + +PRIVATE> + M: winnt open-append - 0 ! [ dup file-info size>> ] [ drop 0 ] recover + [ dup windows-file-size ] [ drop 0 ] recover [ (open-append) ] dip >>ptr ; M: winnt home "USERPROFILE" os-env ; diff --git a/basis/io/launcher/windows/nt/nt-tests.factor b/basis/io/launcher/windows/nt/nt-tests.factor index 62fe45dc7f..93b1e8c2ff 100644 --- a/basis/io/launcher/windows/nt/nt-tests.factor +++ b/basis/io/launcher/windows/nt/nt-tests.factor @@ -41,8 +41,11 @@ IN: io.launcher.windows.nt.tests try-process ] unit-test +: launcher-test-path ( -- str ) + "resource:basis/io/launcher/windows/nt/test" ; + [ ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "stderr.factor" 3array >>command "out.txt" temp-file >>stdout @@ -60,7 +63,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "stderr.factor" 3array >>command "out.txt" temp-file >>stdout @@ -74,7 +77,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ "output" ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "stderr.factor" 3array >>command "err2.txt" temp-file >>stderr @@ -87,7 +90,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ t ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command ascii contents @@ -97,7 +100,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ t ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command +replace-environment+ >>environment-mode @@ -109,7 +112,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ "B" ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command { { "A" "B" } } >>environment @@ -120,7 +123,7 @@ IN: io.launcher.windows.nt.tests ] unit-test [ f ] [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "env.factor" 3array >>command { { "USERPROFILE" "XXX" } } >>environment @@ -146,7 +149,7 @@ IN: io.launcher.windows.nt.tests [ "Hello appender\r\nHello appender\r\n" ] [ 2 [ - "resource:basis/io/windows/nt/launcher/test" [ + launcher-test-path [ vm "-script" "append.factor" 3array >>command "append-test" temp-file >>stdout diff --git a/basis/windows/winsock/winsock.factor b/basis/windows/winsock/winsock.factor index 3ee333d05d..5c70e82ea9 100644 --- a/basis/windows/winsock/winsock.factor +++ b/basis/windows/winsock/winsock.factor @@ -15,74 +15,74 @@ TYPEDEF: void* SOCKET : ( -- byte-array ) HEX: 190 ; -: SOCK_STREAM 1 ; inline -: SOCK_DGRAM 2 ; inline -: SOCK_RAW 3 ; inline -: SOCK_RDM 4 ; inline -: SOCK_SEQPACKET 5 ; inline +CONSTANT: SOCK_STREAM 1 +CONSTANT: SOCK_DGRAM 2 +CONSTANT: SOCK_RAW 3 +CONSTANT: SOCK_RDM 4 +CONSTANT: SOCK_SEQPACKET 5 -: SO_DEBUG HEX: 1 ; inline -: SO_ACCEPTCONN HEX: 2 ; inline -: SO_REUSEADDR HEX: 4 ; inline -: SO_KEEPALIVE HEX: 8 ; inline -: SO_DONTROUTE HEX: 10 ; inline -: SO_BROADCAST HEX: 20 ; inline -: SO_USELOOPBACK HEX: 40 ; inline -: SO_LINGER HEX: 80 ; inline -: SO_OOBINLINE HEX: 100 ; inline +CONSTANT: SO_DEBUG HEX: 1 +CONSTANT: SO_ACCEPTCONN HEX: 2 +CONSTANT: SO_REUSEADDR HEX: 4 +CONSTANT: SO_KEEPALIVE HEX: 8 +CONSTANT: SO_DONTROUTE HEX: 10 +CONSTANT: SO_BROADCAST HEX: 20 +CONSTANT: SO_USELOOPBACK HEX: 40 +CONSTANT: SO_LINGER HEX: 80 +CONSTANT: SO_OOBINLINE HEX: 100 : SO_DONTLINGER ( -- n ) SO_LINGER bitnot ; inline -: SO_SNDBUF HEX: 1001 ; inline -: SO_RCVBUF HEX: 1002 ; inline -: SO_SNDLOWAT HEX: 1003 ; inline -: SO_RCVLOWAT HEX: 1004 ; inline -: SO_SNDTIMEO HEX: 1005 ; inline -: SO_RCVTIMEO HEX: 1006 ; inline -: SO_ERROR HEX: 1007 ; inline -: SO_TYPE HEX: 1008 ; inline +CONSTANT: SO_SNDBUF HEX: 1001 +CONSTANT: SO_RCVBUF HEX: 1002 +CONSTANT: SO_SNDLOWAT HEX: 1003 +CONSTANT: SO_RCVLOWAT HEX: 1004 +CONSTANT: SO_SNDTIMEO HEX: 1005 +CONSTANT: SO_RCVTIMEO HEX: 1006 +CONSTANT: SO_ERROR HEX: 1007 +CONSTANT: SO_TYPE HEX: 1008 -: TCP_NODELAY HEX: 1 ; inline +CONSTANT: TCP_NODELAY HEX: 1 -: AF_UNSPEC 0 ; inline -: AF_UNIX 1 ; inline -: AF_INET 2 ; inline -: AF_IMPLINK 3 ; inline -: AF_PUP 4 ; inline -: AF_CHAOS 5 ; inline -: AF_NS 6 ; inline -: AF_ISO 7 ; inline +CONSTANT: AF_UNSPEC 0 +CONSTANT: AF_UNIX 1 +CONSTANT: AF_INET 2 +CONSTANT: AF_IMPLINK 3 +CONSTANT: AF_PUP 4 +CONSTANT: AF_CHAOS 5 +CONSTANT: AF_NS 6 +CONSTANT: AF_ISO 7 ALIAS: AF_OSI AF_ISO -: AF_ECMA 8 ; inline -: AF_DATAKIT 9 ; inline -: AF_CCITT 10 ; inline -: AF_SNA 11 ; inline -: AF_DECnet 12 ; inline -: AF_DLI 13 ; inline -: AF_LAT 14 ; inline -: AF_HYLINK 15 ; inline -: AF_APPLETALK 16 ; inline -: AF_NETBIOS 17 ; inline -: AF_MAX 18 ; inline -: AF_INET6 23 ; inline -: AF_IRDA 26 ; inline -: AF_BTM 32 ; inline +CONSTANT: AF_ECMA 8 +CONSTANT: AF_DATAKIT 9 +CONSTANT: AF_CCITT 10 +CONSTANT: AF_SNA 11 +CONSTANT: AF_DECnet 12 +CONSTANT: AF_DLI 13 +CONSTANT: AF_LAT 14 +CONSTANT: AF_HYLINK 15 +CONSTANT: AF_APPLETALK 16 +CONSTANT: AF_NETBIOS 17 +CONSTANT: AF_MAX 18 +CONSTANT: AF_INET6 23 +CONSTANT: AF_IRDA 26 +CONSTANT: AF_BTM 32 -: PF_UNSPEC 0 ; inline -: PF_LOCAL 1 ; inline -: PF_INET 2 ; inline -: PF_INET6 23 ; inline +CONSTANT: PF_UNSPEC 0 +CONSTANT: PF_LOCAL 1 +CONSTANT: PF_INET 2 +CONSTANT: PF_INET6 23 -: AI_PASSIVE 1 ; inline -: AI_CANONNAME 2 ; inline -: AI_NUMERICHOST 4 ; inline +CONSTANT: AI_PASSIVE 1 +CONSTANT: AI_CANONNAME 2 +CONSTANT: AI_NUMERICHOST 4 : AI_MASK ( -- n ) { AI_PASSIVE AI_CANONNAME AI_NUMERICHOST } flags ; -: NI_NUMERICHOST 1 ; -: NI_NUMERICSERV 2 ; +CONSTANT: NI_NUMERICHOST 1 +CONSTANT: NI_NUMERICSERV 2 -: IPPROTO_TCP 6 ; inline -: IPPROTO_UDP 17 ; inline -: IPPROTO_RM 113 ; inline +CONSTANT: IPPROTO_TCP 6 +CONSTANT: IPPROTO_UDP 17 +CONSTANT: IPPROTO_RM 113 CONSTANT: WSA_FLAG_OVERLAPPED 1 ALIAS: WSA_WAIT_EVENT_0 WAIT_OBJECT_0 @@ -94,16 +94,16 @@ ALIAS: WSA_WAIT_TIMEOUT WAIT_TIMEOUT ALIAS: WSA_INFINITE INFINITE ALIAS: WSA_IO_PENDING ERROR_IO_PENDING -: INADDR_ANY 0 ; inline +CONSTANT: INADDR_ANY 0 : INVALID_SOCKET ( -- alien ) -1 ; inline -: SOCKET_ERROR -1 ; inline +CONSTANT: SOCKET_ERROR -1 -: SD_RECV 0 ; inline -: SD_SEND 1 ; inline -: SD_BOTH 2 ; inline +CONSTANT: SD_RECV 0 +CONSTANT: SD_SEND 1 +CONSTANT: SD_BOTH 2 -: SOL_SOCKET HEX: ffff ; inline +CONSTANT: SOL_SOCKET HEX: ffff ! TYPEDEF: uint in_addr_t ! C-STRUCT: in_addr @@ -207,7 +207,7 @@ C-STRUCT: QOS { "WSABUF" "ProviderSpecific" } ; TYPEDEF: QOS* LPQOS -: MAX_PROTOCOL_CHAIN 7 ; inline +CONSTANT: MAX_PROTOCOL_CHAIN 7 C-STRUCT: WSAPROTOCOLCHAIN { "int" "ChainLen" } @@ -215,7 +215,7 @@ C-STRUCT: WSAPROTOCOLCHAIN { { "DWORD" 7 } "ChainEntries" } ; TYPEDEF: WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN -: WSAPROTOCOL_LEN 255 ; inline +CONSTANT: WSAPROTOCOL_LEN 255 C-STRUCT: WSAPROTOCOL_INFOW { "DWORD" "dwServiceFlags1" } @@ -387,7 +387,7 @@ LIBRARY: mswsock FUNCTION: int AcceptEx ( void* listen, void* accept, void* out-buf, int recv-len, int addr-len, int remote-len, void* out-len, void* overlapped ) ; FUNCTION: void GetAcceptExSockaddrs ( void* a, int b, int c, int d, void* e, void* f, void* g, void* h ) ; -: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090 ; inline +CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090 : WSAID_CONNECTEX ( -- GUID ) "GUID" diff --git a/core/words/words-docs.factor b/core/words/words-docs.factor index 389f16c68e..91b10936c0 100644 --- a/core/words/words-docs.factor +++ b/core/words/words-docs.factor @@ -46,7 +46,7 @@ ARTICLE: "symbols" "Symbols" "Symbols are just compound definitions in disguise. The following two lines are equivalent:" { $code "SYMBOL: foo" - ": foo \\ foo ;" + ": foo ( -- value ) \\ foo ;" } ; ARTICLE: "primitives" "Primitives" diff --git a/extra/fuel/fuel.factor b/extra/fuel/fuel.factor index bf36969219..4535ac7fd6 100644 --- a/extra/fuel/fuel.factor +++ b/extra/fuel/fuel.factor @@ -112,7 +112,7 @@ M: source-file fuel-pprint path>> fuel-pprint ; error get fuel-eval-result get-global fuel-eval-output get-global - 3array fuel-pprint ; + 3array fuel-pprint flush nl "EOT:" write ; : fuel-forget-error ( -- ) f error set-global ; inline : fuel-forget-result ( -- ) f fuel-eval-result set-global ; inline diff --git a/extra/otug-talk/2bi.png b/extra/otug-talk/2bi.png new file mode 100644 index 0000000000..8f431f87ce Binary files /dev/null and b/extra/otug-talk/2bi.png differ diff --git a/extra/otug-talk/2bi_at.png b/extra/otug-talk/2bi_at.png new file mode 100644 index 0000000000..55d42c2a4c Binary files /dev/null and b/extra/otug-talk/2bi_at.png differ diff --git a/extra/otug-talk/2bi_star.png b/extra/otug-talk/2bi_star.png new file mode 100644 index 0000000000..0fff37624b Binary files /dev/null and b/extra/otug-talk/2bi_star.png differ diff --git a/extra/otug-talk/authors.txt b/extra/otug-talk/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/extra/otug-talk/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/extra/otug-talk/bi.png b/extra/otug-talk/bi.png new file mode 100644 index 0000000000..2470c9fab1 Binary files /dev/null and b/extra/otug-talk/bi.png differ diff --git a/extra/otug-talk/bi_at.png b/extra/otug-talk/bi_at.png new file mode 100644 index 0000000000..282f2f118d Binary files /dev/null and b/extra/otug-talk/bi_at.png differ diff --git a/extra/otug-talk/bi_star.png b/extra/otug-talk/bi_star.png new file mode 100644 index 0000000000..e94e3710cf Binary files /dev/null and b/extra/otug-talk/bi_star.png differ diff --git a/extra/otug-talk/otug-talk.factor b/extra/otug-talk/otug-talk.factor new file mode 100644 index 0000000000..3c6ea50597 --- /dev/null +++ b/extra/otug-talk/otug-talk.factor @@ -0,0 +1,368 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: slides help.markup math arrays hashtables namespaces +sequences kernel sequences parser memoize io.encodings.binary +locals kernel.private tools.vocabs.browser assocs quotations + tools.vocabs tools.annotations tools.crossref +help.topics math.functions compiler.tree.optimizer +compiler.cfg.optimizer fry graphics.bitmap graphics.viewer +ui.gadgets.panes tetris tetris.game combinators generalizations +multiline sequences.private ; +IN: otug-talk + +USING: cairo cairo.samples cairo.ffi cairo.gadgets accessors +io.backend ui.gadgets ; + +TUPLE: png-gadget < cairo-gadget surface ; + +: ( file -- gadget ) + png-gadget new-gadget + swap normalize-path + cairo_image_surface_create_from_png >>surface ; inline + +M: png-gadget pref-dim* ( gadget -- ) + surface>> + [ cairo_image_surface_get_width ] + [ cairo_image_surface_get_height ] + bi 2array ; + +M: png-gadget render-cairo* ( gadget -- ) + cr swap surface>> 0 0 cairo_set_source_surface + cr cairo_paint ; + +M: png-gadget ungraft* ( gadget -- ) + surface>> cairo_surface_destroy ; + +: $bitmap ( element -- ) + [ first gadget. ] ($block) ; + +: $tetris ( element -- ) + drop [ gadget. ] ($block) ; + +: otug-slides +{ + { $slide "Factor!" + { $url "http://factorcode.org" } + "Development started in 2003" + "Open source (BSD license)" + "Influenced by Forth, Lisp, and Smalltalk" + "Blurs the line between language and library" + "Interactive development" + } + { $slide "Part 1: the language" } + { $slide "Basics" + "Stack based, dynamically typed" + { "A " { $emphasis "word" } " is a named piece of code" } + { "Values are passed between words on a " { $emphasis "stack" } } + "Code evaluates left to right" + "Example:" + { $code "2 3 + ." } + } + { $slide "Quotations" + { "A " { $emphasis "quotation" } " is a block of code pushed on the stack" } + { "Syntax: " { $snippet "[ ... ]" } } + "Example:" + { $code + "\"/etc/passwd\" ascii file-lines" + "[ \"#\" head? not ] filter" + "[ \":\" split first ] map" + "." + } + } + { $slide "Words" + { "We can define new words with " { $snippet ": name ... ;" } " syntax" } + { $code ": remove-comments ( lines -- lines' )" " [ \"#\" head? not ] filter ;" } + { "Words are grouped into " { $emphasis "vocabularies" } } + { $link "vocab-index" } + "Libraries and applications are vocabularies" + { $vocab-link "spheres" } + } + { $slide "Constructing quotations" + { "Suppose we want a " { $snippet "remove-comments*" } " word" } + { $code ": remove-comments* ( lines string -- lines' )" " [ ??? head? not ] filter ;" } + { "We use " { $link POSTPONE: '[ } " instead of " { $link POSTPONE: [ } } + { "Create “holes” with " { $link _ } } + "Holes filled in left to right when quotation pushed on the stack" + } + { $slide "Constructing quotations" + { $code ": remove-comments* ( lines string -- lines' )" " '[ _ head? not ] filter ;" "" ": remove-comments ( lines -- lines' )" " \"#\" remove-comments* ;" } + { { $link @ } " inserts a quotation" } + { $code ": replicate ( n quot -- seq )" " '[ drop @ ] map ;" } + { $code "10 [ 1 10 [a,b] random ] replicate ." } + } + { $slide "Combinators" + { "A " { $emphasis "combinator" } " is a word taking quotations as input" } + { "Used for control flow, data flow, iteration" } + { $code "100 [ 5 mod 3 = [ \"Fizz!\" print ] when ] each" } + { "Control flow: " { $link if } ", " { $link when } ", " { $link unless } ", " { $link cond } } + { "Iteration: " { $link map } ", " { $link filter } ", " { $link all? } ", ..." } + } + { $slide "Data flow combinators - simple example" + "All examples so far used “pipeline style”" + "What about using a value more than once, or operating on values not at top of stack?" + { $code "{ 10 70 54 } [ sum ] [ length ] bi / ." } + { $code "5 [ 1 + ] [ sqrt ] [ 1 - ] tri 3array ." } + } + { $slide "Data flow combinators - cleave family" + { { $link bi } ", " { $link tri } ", " { $link cleave } } + { $bitmap "resource:extra/otug-talk/bi.png" } + } + { $slide "Data flow combinators - cleave family" + { { $link 2bi } ", " { $link 2tri } ", " { $link 2cleave } } + { $bitmap "resource:extra/otug-talk/2bi.png" } + } + { $slide "Data flow combinators" + "First, let's define a data type:" + { $code "TUPLE: person first-name last-name ;" } + "Make an instance:" + { $code "person new" " \"Joe\" >>first-name" " \"Sixpack\" >>last-name" } + } + { $slide "Data flow combinators" + "Let's do stuff with it:" + { $code + "[ first-name>> ] [ last-name>> ] bi" + "[ 2 head ] [ 5 head ] bi*" + "[ >upper ] bi@" + "\".\" glue ." + } + } + { $slide "Data flow combinators - spread family" + { { $link bi* } ", " { $link tri* } ", " { $link spread } } + { $bitmap "resource:extra/otug-talk/bi_star.png" } + } + { $slide "Data flow combinators - spread family" + { { $link 2bi* } } + { $bitmap "resource:extra/otug-talk/2bi_star.png" } + } + { $slide "Data flow combinators - apply family" + { { $link bi@ } ", " { $link tri@ } ", " { $link napply } } + { $bitmap "resource:extra/otug-talk/bi_at.png" } + } + { $slide "Data flow combinators - apply family" + { { $link 2bi@ } } + { $bitmap "resource:extra/otug-talk/2bi_at.png" } + } + { $slide "Shuffle words" + "When data flow combinators are not enough" + { $link "shuffle-words" } + "Lower-level, Forth/PostScript-style stack manipulation" + } + { $slide "Locals" + "When data flow combinators and shuffle words are not enough" + "Name your input parameters" + "Used in about 1% of all words" + } + { $slide "Locals example" + "Area of a triangle using Heron's formula" + { $code + <" :: area ( a b c -- x ) + a b c + + 2 / :> p + p + p a - * + p b - * + p c - * sqrt ;"> + } + } + { $slide "Previous example without locals" + "A bit unwieldy..." + { $code + <" : area ( a b c -- x ) + [ ] [ + + 2 / ] 3bi + [ '[ _ - ] tri@ ] [ neg ] bi + * * * sqrt ;"> } + } + { $slide "More idiomatic version" + "But there's a trick: put the points in an array" + { $code <" : v-n ( v n -- w ) '[ _ - ] map ; + +: area ( points -- x ) + [ 0 suffix ] [ sum 2 / ] bi + v-n product sqrt ;"> } + } + ! { $slide "The parser" + ! "All data types have a literal syntax" + ! "Literal hashtables and arrays are very useful in data-driven code" + ! { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" } + ! "Libraries can define new parsing words" + ! } + { $slide "Programming without named values" + "Minimal glue between words" + "Easy multiple return values" + { "Avoid useless variable names: " { $snippet "x" } ", " { $snippet "n" } ", " { $snippet "a" } ", ..." } + { { $link at } " and " { $link at* } } + { $code "at* [ ... ] [ ... ] if" } + } + { $slide "Stack language idioms" + "Enables new idioms not possible before" + "We get the effect of “keyword parameters” for free" + { $vocab-link "smtp-example" } + } + { $slide "“Perfect” factoring" + { $table + { { $link head } { $link head-slice } } + { { $link tail } { $link tail-slice } } + } + { "Modifier: " { $link from-end } } + { "Modifier: " { $link short } } + "4*2*2=16 operations, 6 words!" + } + { $slide "Modifiers" + "“Modifiers” can express MN combinations using M+N words" + { $code + "\"Hello, Joe\" 4 head ." + "\"Hello, Joe\" 3 tail ." + "\"Hello, Joe\" 3 from-end tail ." + } + { $code + "\"Hello world\" 5 short head ." + "\"Hi\" 5 short tail ." + } + } + { $slide "Modifiers" + { "C-style " { $snippet "while" } " and " { $snippet "do while" } " loops" } + } + { $slide "Modifiers" + { $code ": bank ( n -- n )" " readln string>number +" " dup \"Balance: $\" write . ;" } + { $code "0 [ dup 0 > ] [ bank ] [ ] while" } + } + { $slide "Modifiers" + { $code "0 [ dup 0 > ] [ bank ] [ ] do while" } + { { $link do } " executes one iteration of a " { $link while } " loop" } + { { $link while } " calls " { $link do } } + } + { $slide "More “pipeline style” code" + { "Suppose we want to get the price of the customer's first order, but any one of the steps along the way could be a nil value (" { $link f } " in Factor):" } + { $code + "dup [ orders>> ] when" + "dup [ first ] when" + "dup [ price>> ] when" + } + } + { $slide "This is hard with mainstream syntax!" + { $code + <" var customer = ...; +var orders = (customer == null ? null : customer.orders); +var order = (orders == null ? null : orders[0]); +var price = (order == null ? null : order.price);"> } + } + { $slide "An ad-hoc solution" + "Something like..." + { $code "var price = customer.?orders.?[0].?price;" } + } + ! { $slide "Stack languages are fundamental" + ! "Very simple semantics" + ! "Easy to generate stack code programatically" + ! "Everything is almost entirely library code in Factor" + ! "Factor is easy to extend" + ! } + { $slide "Part 2: the implementation" } + { $slide "Interactive development" + { $tetris } + } + { $slide "Application deployment" + { $vocab-link "webkit-demo" } + "Demonstrates Cocoa binding" + "Let's deploy a stand-alone binary with the deploy tool" + "Deploy tool generates binaries with no external dependencies" + } + { $slide "The UI" + "Renders with OpenGL" + "Backends for Cocoa, Windows, X11: managing windows, input events, clipboard" + "Cross-platform API" + } + { $slide "UI example" + { $code + <" + { 5 5 } >>gap + 1 >>fill + "Hello world!"