Merge branch 'master' of git://factorcode.org/git/factor

db4
John Benediktsson 2008-12-17 13:19:42 -08:00
commit 0df70f72bd
25 changed files with 595 additions and 151 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ;
<PRIVATE
: windows-file-size ( path -- size )
normalize-path 0 "WIN32_FILE_ATTRIBUTE_DATA" <c-object>
[ 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 ;

View File

@ -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 [
<process>
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 [
<process>
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 [
<process>
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 [
<process>
vm "-script" "env.factor" 3array >>command
ascii <process-reader> contents
@ -97,7 +100,7 @@ IN: io.launcher.windows.nt.tests
] unit-test
[ t ] [
"resource:basis/io/windows/nt/launcher/test" [
launcher-test-path [
<process>
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 [
<process>
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 [
<process>
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 [
<process>
vm "-script" "append.factor" 3array >>command
"append-test" temp-file <appender> >>stdout

View File

@ -15,74 +15,74 @@ TYPEDEF: void* SOCKET
: <wsadata> ( -- byte-array )
HEX: 190 <byte-array> ;
: 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 <alien> ; 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" <c-object>

View File

@ -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"

View File

@ -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

BIN
extra/otug-talk/2bi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
extra/otug-talk/2bi_at.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1 @@
Slava Pestov

BIN
extra/otug-talk/bi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
extra/otug-talk/bi_at.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
extra/otug-talk/bi_star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -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 ;
: <png-gadget> ( 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 <png-gadget> gadget. ] ($block) ;
: $tetris ( element -- )
drop [ <default-tetris> <tetris-gadget> 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
<" <pile>
{ 5 5 } >>gap
1 >>fill
"Hello world!" <label> add-gadget
"Click me!" [ drop beep ]
<bevel-button> add-gadget
<editor> <scroller> add-gadget
"UI test" open-window "> }
}
{ $slide "Help system"
"Help markup is just literal data"
{ "Look at the help for " { $link T{ link f + } } }
"These slides are built with the help system and a custom style sheet"
{ $vocab-link "otug-talk" }
}
{ $slide "The VM"
"Lowest level is the VM: ~12,000 lines of C"
"Generational garbage collection"
"Non-optimizing compiler"
"Loads an image file and runs it"
"Initial image generated from another Factor instance:"
{ $code "\"x86.32\" make-image" }
}
{ $slide "The core library"
"Core library, ~9,000 lines of Factor"
"Source parser, arrays, strings, math, hashtables, basic I/O, ..."
"Packaged into boot image because VM doesn't have a parser"
}
{ $slide "The basis library"
"Basis library, ~80,000 lines of Factor"
"Bootstrap process loads code from basis, runs compiler, saves image"
"Loaded by default: optimizing compiler, tools, help system, UI, ..."
"Optional: HTTP server, XML, database access, ..."
}
{ $slide "Non-optimizing compiler"
"Glues together chunks of machine code"
"Most words compiled as calls, some inlined"
"Used for listener interactions, and bootstrap"
}
{ $slide "Optimizing compiler"
"Converts Factor code into high-level SSA form"
"Performs global optimizations"
"Converts high-level SSA into low-level SSA"
"Performs local optimizations"
"Register allocation"
"Machine code generation: x86, x86-64, PowerPC"
}
{ $slide "Optimizing compiler"
"Makes high-level language features cheap to use"
"Eliminate redundant method dispatch by inferring types"
"Eliminate redundant integer overflow checks by inferring ranges"
}
{ $slide "Optimizing compiler"
"Eliminate redundant memory allocation (escape analysis)"
"Eliminate redundant loads/stores (alias analysis)"
"Eliminate redundant computations (value numbering)"
}
{ $slide "Project infrastructure"
{ $url "http://factorcode.org" }
{ $url "http://concatenative.org" }
{ $url "http://docs.factorcode.org" }
{ $url "http://planet.factorcode.org" }
"Uses our HTTP server, SSL, DB, Atom libraries..."
}
{ $slide "Project infrastructure"
"Build farm, written in Factor"
"12 platforms"
"Builds Factor and all libraries, runs tests, makes binaries"
"Good for increasing stability"
}
{ $slide "Community"
"#concatenative irc.freenode.net: 60-70 users"
"factor-talk@lists.sf.net: 189 subscribers"
"About 30 people have code in the Factor repository"
"Easy to get started: binaries, lots of docs, friendly community..."
}
{ $slide "Selling points"
"Expressive language"
"Comprehensive library"
"Efficient implementation"
"Powerful interactive tools"
"Stand-alone application deployment"
"Moving fast"
}
{ $slide "That's all, folks"
"It is hard to cover everything in a single talk"
"Factor has many cool things that I didn't talk about"
"Questions?"
}
} ;
: otug-talk ( -- ) otug-slides slides-window ;
MAIN: otug-talk

View File

@ -0,0 +1 @@
Slides from a talk at OTUG by Slava Pestov, December 2008

1
extra/otug-talk/tags.txt Normal file
View File

@ -0,0 +1 @@
demos

View File

@ -47,8 +47,8 @@ M-x customize-group fuel will show you how many.
Quick key reference
-------------------
(Chords ending in a single letter <x> accept also C-<x> (e.g. C-cC-z is
the same as C-cz)).
(Triple chords ending in a single letter <x> accept also C-<x> (e.g.
C-cC-eC-r is the same as C-cC-er)).
* In factor source files:
@ -57,7 +57,8 @@ the same as C-cz)).
- M-. : edit word at point in Emacs
- M-TAB : complete word at point
- C-cC-ev : edit vocabulary
- C-cC-ev : edit vocabulary (M-x fuel-edit-vocabulary)
- C-cC-ew : edit word (M-x fuel-edit-word)
- C-cr, C-cC-er : eval region
- C-M-r, C-cC-ee : eval region, extending it to definition boundaries

View File

@ -143,6 +143,15 @@ terminates a current completion."
(vs (and cv `("syntax" ,cv ,@(fuel-syntax--usings)))))
(fuel-completion--words prefix vs)))
(defsubst fuel-completion--all-words-list (prefix)
(fuel-completion--words prefix nil))
(defvar fuel-completion--word-list-func
(completion-table-dynamic 'fuel-completion--word-list))
(defvar fuel-completion--all-words-list-func
(completion-table-dynamic 'fuel-completion--all-words-list))
(defun fuel-completion--complete (prefix)
(let* ((words (fuel-completion--word-list prefix))
(completions (all-completions prefix words))
@ -150,6 +159,14 @@ terminates a current completion."
(partial (if (eq partial t) prefix partial)))
(cons completions partial)))
(defsubst fuel-completion--read-word (prompt &optional default history all)
(completing-read prompt
(if all fuel-completion--all-words-list-func
fuel-completion--word-list-func)
nil nil nil
history
(or default (fuel-syntax-symbol-at-point))))
(defun fuel-completion--complete-symbol ()
"Complete the symbol at point.
Perform completion similar to Emacs' complete-symbol."

View File

@ -14,8 +14,11 @@
;;; Code:
(require 'fuel-base)
(require 'fuel-log)
(require 'fuel-base)
(require 'comint)
(require 'advice)
;;; Default connection:
@ -123,19 +126,34 @@
;;; Connection setup:
(defun fuel-con--cleanup-connection (c)
(fuel-con--connection-cancel-timer c))
(defun fuel-con--setup-connection (buffer)
(set-buffer buffer)
(fuel-con--cleanup-connection fuel-con--connection)
(let ((conn (fuel-con--make-connection buffer)))
(fuel-con--setup-comint)
(prog1
(setq fuel-con--connection conn)
(fuel-con--connection-start-timer conn))))
(defconst fuel-con--prompt-regex "( .+ ) ")
(defconst fuel-con--eot-marker "EOT:")
(defconst fuel-con--init-stanza (format "USE: fuel %S write" fuel-con--eot-marker))
(defconst fuel-con--comint-finished-regex
(format "%s%s" fuel-con--eot-marker fuel-con--prompt-regex))
(defun fuel-con--setup-comint ()
(comint-redirect-cleanup)
(add-hook 'comint-redirect-filter-functions
'fuel-con--comint-redirect-filter t t)
(add-hook 'comint-redirect-hook
'fuel-con--comint-redirect-hook))
'fuel-con--comint-redirect-hook nil t))
(defadvice comint-redirect-setup (after fuel-con--advice activate)
(setq comint-redirect-finished-regexp fuel-con--comint-finished-regex))
;;; Requests handling:
@ -169,6 +187,8 @@
(error (fuel-log--error "<%s>: continuation failed %S \n\t%s"
id rstr cerr))))))
(defvar fuel-con--debug-comint-p nil)
(defun fuel-con--comint-redirect-filter (str)
(if (not fuel-con--connection)
(fuel-log--error "No connection in buffer (%s)" str)
@ -176,13 +196,13 @@
(if (not req) (fuel-log--error "No current request (%s)" str)
(fuel-con--request-output req str)
(fuel-log--info "<%s>: in progress" (fuel-con--request-id req)))))
(fuel--shorten-str str 70))
(if fuel-con--debug-comint-p (fuel--shorten-str str 256) ""))
(defun fuel-con--comint-redirect-hook ()
(if (not fuel-con--connection)
(fuel-log--error "No connection in buffer")
(let ((req (fuel-con--connection-current-request fuel-con--connection)))
(if (not req) (fuel-log--error "No current request (%s)" str)
(if (not req) (fuel-log--error "No current request")
(fuel-con--process-completed-request req)
(fuel-con--connection-clean-current-request fuel-con--connection)))))

View File

@ -76,7 +76,6 @@
((listp usings) `(:array ,@usings))
(t (error "Invalid 'usings' (%s)" usings))))
;;; Code sending:

View File

@ -14,9 +14,10 @@
;;; Code:
(require 'fuel-base)
(require 'fuel-font-lock)
(require 'fuel-eval)
(require 'fuel-completion)
(require 'fuel-font-lock)
(require 'fuel-base)
;;; Customization:
@ -108,14 +109,15 @@ displayed in the minibuffer."
;;; Help browser history:
(defvar fuel-help--history
(list nil
(make-ring fuel-help-history-cache-size)
(make-ring fuel-help-history-cache-size)))
(list nil ; current
(make-ring fuel-help-history-cache-size) ; previous
(make-ring fuel-help-history-cache-size))) ; next
(defvar fuel-help--history-idx 0)
(defun fuel-help--history-push (term)
(when (car fuel-help--history)
(when (and (car fuel-help--history)
(not (string= (caar fuel-help--history) (car term))))
(ring-insert (nth 1 fuel-help--history) (car fuel-help--history)))
(setcar fuel-help--history term))
@ -135,7 +137,7 @@ displayed in the minibuffer."
;;; Fuel help buffer and internals:
(defun fuel-help--help-buffer ()
(with-current-buffer (get-buffer-create "*fuel-help*")
(with-current-buffer (get-buffer-create "*fuel help*")
(fuel-help-mode)
(current-buffer)))
@ -148,7 +150,9 @@ displayed in the minibuffer."
(ask (or (not (memq major-mode '(factor-mode fuel-help-mode)))
(not def)
fuel-help-always-ask))
(def (if ask (read-string prompt nil 'fuel-help--prompt-history def)
(def (if ask (fuel-completion--read-word prompt
def
'fuel-help--prompt-history)
def))
(cmd `(:fuel* ((:quote ,def) ,(if see 'see 'help)) t)))
(message "Looking up '%s' ..." def)
@ -157,7 +161,7 @@ displayed in the minibuffer."
(defun fuel-help--show-help-cont (def ret)
(let ((out (fuel-eval--retort-output ret)))
(if (or (fuel-eval--retort-error ret) (empty-string-p out))
(message "No help for '%s'" ret)
(message "No help for '%s'" def)
(fuel-help--insert-contents def out))))
(defun fuel-help--insert-contents (def str &optional nopush)
@ -167,14 +171,15 @@ displayed in the minibuffer."
(set-buffer hb)
(erase-buffer)
(insert str)
(goto-char (point-min))
(when (re-search-forward (format "^%s" def) nil t)
(beginning-of-line)
(kill-region (point-min) (point))
(next-line)
(open-line 1))
(unless nopush
(goto-char (point-min))
(when (re-search-forward (format "^%s" def) nil t)
(beginning-of-line)
(kill-region (point-min) (point))
(next-line)
(open-line 1)
(fuel-help--history-push (cons def (buffer-string)))))
(set-buffer-modified-p nil)
(unless nopush (fuel-help--history-push (cons def str)))
(pop-to-buffer hb)
(goto-char (point-min))
(message "%s" def)))

View File

@ -14,9 +14,11 @@
;;; Code:
(require 'fuel-eval)
(require 'fuel-base)
(require 'fuel-completion)
(require 'fuel-connection)
(require 'fuel-syntax)
(require 'fuel-base)
(require 'comint)
@ -63,19 +65,21 @@ buffer."
(defun fuel-listener--start-process ()
(let ((factor (expand-file-name fuel-listener-factor-binary))
(image (expand-file-name fuel-listener-factor-image)))
(image (expand-file-name fuel-listener-factor-image))
(comint-redirect-perform-sanity-check nil))
(unless (file-executable-p factor)
(error "Could not run factor: %s is not executable" factor))
(unless (file-readable-p image)
(error "Could not run factor: image file %s not readable" image))
(message "Starting FUEL listener ...")
(comint-exec (fuel-listener--buffer) "factor"
factor nil `("-run=listener" ,(format "-i=%s" image)))
(pop-to-buffer (fuel-listener--buffer))
(goto-char (point-max))
(comint-send-string nil "USE: fuel \"FUEL loaded\\n\" write\n")
(fuel-listener--wait-for-prompt 30)
(message "FUEL listener up and running!")))
(make-comint-in-buffer "fuel listener" (current-buffer) factor nil
"-run=listener" (format "-i=%s" image))
(fuel-listener--wait-for-prompt 10000)
(fuel-con--send-string/wait (current-buffer)
fuel-con--init-stanza
'(lambda (s) (message "FUEL listener up and running!"))
20000)))
(defun fuel-listener--process (&optional start)
(or (and (buffer-live-p (fuel-listener--buffer))
@ -87,21 +91,15 @@ buffer."
(setq fuel-eval--default-proc-function 'fuel-listener--process)
;;; Prompt chasing
(defun fuel-listener--wait-for-prompt (&optional timeout)
(let ((proc (get-buffer-process (fuel-listener--buffer)))
(seen))
(with-current-buffer (fuel-listener--buffer)
(goto-char (or comint-last-input-end (point-max)))
(while (and (not seen)
(accept-process-output proc (or timeout 10) nil t))
(sleep-for 0 1)
(goto-char comint-last-input-end)
(setq seen (re-search-forward comint-prompt-regexp nil t)))
(goto-char (point-max))
(unless seen (error "No prompt found!")))))
(defun fuel-listener--wait-for-prompt (timeout)
(let ((p (point)) (seen))
(while (and (not seen) (> timeout 0))
(sleep-for 0.1)
(setq timeout (- timeout 100))
(goto-char p)
(setq seen (re-search-forward comint-prompt-regexp nil t)))
(goto-char (point-max))
(unless seen (error "No prompt found!"))))
;;; Completion support
@ -132,12 +130,10 @@ buffer."
;;; Fuel listener mode:
(defconst fuel-listener--prompt-regex ".* ) ")
(define-derived-mode fuel-listener-mode comint-mode "Fuel Listener"
"Major mode for interacting with an inferior Factor listener process.
\\{fuel-listener-mode-map}"
(set (make-local-variable 'comint-prompt-regexp) fuel-listener--prompt-regex)
(set (make-local-variable 'comint-prompt-regexp) fuel-con--prompt-regex)
(set (make-local-variable 'comint-prompt-read-only) t)
(fuel-listener--setup-completion))

View File

@ -114,18 +114,26 @@ buffer in case of errors."
"Opens a new window visiting the definition of the word at point.
With prefix, asks for the word to edit."
(interactive "P")
(let* ((word (fuel-syntax-symbol-at-point))
(ask (or arg (not word)))
(word (if ask
(read-string nil
(format "Edit word%s: "
(if word (format " (%s)" word) ""))
word)
word)))
(let ((cmd `(:fuel ((:quote ,word) fuel-get-edit-location))))
(condition-case nil
(fuel--try-edit (fuel-eval--send/wait cmd))
(error (fuel-edit-vocabulary nil word))))))
(let* ((word (or (and (not arg) (fuel-syntax-symbol-at-point))
(fuel-completion--read-word "Edit word: ")))
(cmd `(:fuel ((:quote ,word) fuel-get-edit-location))))
(condition-case nil
(fuel--try-edit (fuel-eval--send/wait cmd))
(error (fuel-edit-vocabulary nil word)))))
(defvar fuel-mode--word-history nil)
(defun fuel-edit-word (&optional arg)
"Asks for a word to edit, with completion.
With prefix, only words visible in the current vocabulary are
offered."
(interactive "P")
(let* ((word (fuel-completion--read-word "Edit word: "
nil
fuel-mode--word-history
arg))
(cmd `(:fuel ((:quote ,word) fuel-get-edit-location))))
(fuel--try-edit (fuel-eval--send/wait cmd))))
(defvar fuel--vocabs-prompt-history nil)
@ -195,7 +203,7 @@ interacting with a factor listener is at your disposal.
(fuel-mode--key ?e ?e 'fuel-eval-extended-region)
(fuel-mode--key ?e ?r 'fuel-eval-region)
(fuel-mode--key ?e ?v 'fuel-edit-vocabulary)
(fuel-mode--key ?e ?w 'fuel-edit-word-at-point)
(fuel-mode--key ?e ?w 'fuel-edit-word)
(fuel-mode--key ?e ?x 'fuel-eval-definition)
(fuel-mode--key ?d ?a 'fuel-autodoc-mode)