summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Benediktsson <mrjbq7@gmail.com>2021-03-16 21:35:26 -0700
committerJohn Benediktsson <mrjbq7@gmail.com>2021-03-16 21:35:26 -0700
commit33e869d5385c7efbc6eb097b2f98613fb3a52bfa (patch)
tree0f62002b38ee3560333bdb9216b5094624c25da8
parent3ee083299d0a81b7b2a9fdd3733502a8d02ee4f0 (diff)
Adding all the talks.
-rw-r--r--README.md12
-rw-r--r--chicago-talk/authors.txt1
-rw-r--r--chicago-talk/chicago-talk.factor53
-rw-r--r--chicago-talk/deploy.factor11
-rw-r--r--chicago-talk/summary.txt1
-rw-r--r--chicago-talk/tags.txt1
-rw-r--r--galois-talk/authors.txt1
-rw-r--r--galois-talk/galois-talk.factor312
-rw-r--r--galois-talk/summary.txt1
-rw-r--r--galois-talk/tags.txt1
-rw-r--r--google-tech-talk/authors.txt1
-rw-r--r--google-tech-talk/google-tech-talk.factor570
-rw-r--r--google-tech-talk/summary.txt1
-rw-r--r--google-tech-talk/tags.txt1
-rw-r--r--hmc-talk/hmc-talk.factor491
-rw-r--r--jvm-summit-talk/authors.txt1
-rw-r--r--jvm-summit-talk/jvm-summit-talk.factor358
-rw-r--r--jvm-summit-talk/summary.txt1
-rw-r--r--jvm-summit-talk/tags.txt1
-rw-r--r--minneapolis-talk/authors.txt1
-rw-r--r--minneapolis-talk/deploy.factor11
-rw-r--r--minneapolis-talk/minneapolis-talk.factor183
-rw-r--r--minneapolis-talk/summary.txt1
-rw-r--r--minneapolis-talk/tags.txt1
-rw-r--r--otug-talk/2bi.tiffbin0 -> 11744 bytes
-rw-r--r--otug-talk/2bi_at.tiffbin0 -> 13728 bytes
-rw-r--r--otug-talk/2bi_star.tiffbin0 -> 13924 bytes
-rw-r--r--otug-talk/authors.txt1
-rw-r--r--otug-talk/bi.tiffbin0 -> 8872 bytes
-rw-r--r--otug-talk/bi_at.tiffbin0 -> 8848 bytes
-rw-r--r--otug-talk/bi_star.tiffbin0 -> 9784 bytes
-rw-r--r--otug-talk/otug-talk.factor342
-rw-r--r--otug-talk/summary.txt1
-rw-r--r--otug-talk/tags.txt1
-rw-r--r--tc-lisp-talk/authors.txt1
-rw-r--r--tc-lisp-talk/tags.txt1
-rw-r--r--tc-lisp-talk/tc-lisp-talk.factor535
-rw-r--r--vpri-talk/authors.txt1
-rw-r--r--vpri-talk/summary.txt1
-rw-r--r--vpri-talk/tags.txt1
-rw-r--r--vpri-talk/vpri-talk.factor492
41 files changed, 3393 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a5aa3e8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,12 @@
+# Factor
+
+The Factor project is maintained and mirrored at
+[https://github.com/factor/factor](https://github.com/factor/factor)
+
+## Talks and Presentations
+
+Various talks and presentations that have been given are included here as
+runnable vocabularies.
+
+If you'd like to run these, you can add this directory as a ``vocab-root``
+and then ``"name-of-the-talk-to-launch" run``.
diff --git a/chicago-talk/authors.txt b/chicago-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/chicago-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/chicago-talk/chicago-talk.factor b/chicago-talk/chicago-talk.factor
new file mode 100644
index 0000000..02ddc42
--- /dev/null
+++ b/chicago-talk/chicago-talk.factor
@@ -0,0 +1,53 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: slides help.markup ;
+IN: talks.chicago-talk
+
+CONSTANT: chicago-slides
+{
+ { $slide "factor"
+ { $url "http://factorcode.org" }
+ }
+ { $slide "goals"
+ "high level language"
+ "expressive and extensible"
+ "reasonable performance"
+ "interactive development with arbitrary redefinition"
+ "standalone app deployment (strip out compiler and REPL)"
+ }
+ { $slide "challenges"
+
+ "higher-order functions"
+ "dynamic typing"
+ "memory allocation"
+ "float boxing/unboxing"
+ "integer overflow checks"
+ "user-defined abstractions"
+ }
+ { $slide "implementation"
+ "VM: 12 kloc of C, library: >100 kloc of Factor"
+ "generational copying garbage collection, card marking write barrier"
+ "full continuations, tail calls"
+ "simple non-optimizing “bootstrap” compiler"
+ "optimizing compiler"
+ }
+ { $slide "optimizing compiler"
+ "about 12,000 lines of Factor code"
+ "targets x86-32, x86-64, PowerPC"
+ "factor code ⇒ high-level SSA ⇒ low-level SSA ⇒ machine code"
+ }
+ { $slide "high-level optimizer"
+ "macro expansion, defunctionalization"
+ "type and interval inference, sparse conditional constant propagation, method inlining"
+ "escape analysis and tuple unboxing"
+ }
+ { $slide "low-level optimizer"
+ "alias analysis, value numbering, write barrier elimination"
+ "linear scan register allocation"
+ }
+}
+
+: chicago-talk ( -- )
+ chicago-slides "Chicago talk" slides-window ;
+
+MAIN: chicago-talk
diff --git a/chicago-talk/deploy.factor b/chicago-talk/deploy.factor
new file mode 100644
index 0000000..ce8739e
--- /dev/null
+++ b/chicago-talk/deploy.factor
@@ -0,0 +1,11 @@
+USING: tools.deploy.config ;
+V{
+ { deploy-ui? t }
+ { deploy-io 3 }
+ { deploy-reflection 1 }
+ { deploy-math? t }
+ { deploy-word-props? f }
+ { deploy-c-types? f }
+ { "stop-after-last-window?" t }
+ { deploy-name "Chicago Talk" }
+}
diff --git a/chicago-talk/summary.txt b/chicago-talk/summary.txt
new file mode 100644
index 0000000..229e1a3
--- /dev/null
+++ b/chicago-talk/summary.txt
@@ -0,0 +1 @@
+Slides for a talk at the Pycon VM Summit, Chicago, IL, March 2009
diff --git a/chicago-talk/tags.txt b/chicago-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/chicago-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/galois-talk/authors.txt b/galois-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/galois-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/galois-talk/galois-talk.factor b/galois-talk/galois-talk.factor
new file mode 100644
index 0000000..87e7914
--- /dev/null
+++ b/galois-talk/galois-talk.factor
@@ -0,0 +1,312 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: slides help.markup math arrays hashtables namespaces
+sequences kernel parser memoize io.encodings.binary
+locals kernel.private help.vocabs assocs quotations
+urls peg.ebnf tools.annotations tools.crossref
+help.topics math.functions compiler.tree.optimizer
+compiler.cfg.optimizer fry ;
+IN: talks.galois-talk
+
+CONSTANT: galois-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 "Words and the stack"
+ "Stack based, dynamically typed"
+ { $code "{ 1 1 3 4 4 8 9 9 } dup duplicates diff ." }
+ "Words: named code snippets"
+ { $code ": remove-duplicates ( seq -- seq' )" " dup duplicates diff ;" }
+ { $code "{ 1 1 3 4 4 8 9 9 } remove-duplicates ." }
+ }
+ { $slide "Vocabularies"
+ "Vocabularies: named sets of words"
+ { $link "vocab-index" }
+ { { $link POSTPONE: USING: } " loads dependencies" }
+ "Source, docs, tests in one place"
+ }
+ { $slide "Interactive development"
+ "Programming is hard, let's play tetris"
+ { $vocab-link "tetris" }
+ "Tetris is hard too... let's cheat"
+ "Factor workflow: change code, F2, test, repeat"
+ }
+ { $slide "Quotations"
+ "Quotation: unnamed block of code"
+ "Combinators: words taking quotations"
+ { $code "10 dup 0 < [ 1 - ] [ 1 + ] if ." }
+ { $code "{ -1 1 -2 0 3 } [ 0 max ] map ." }
+ "Partial application:"
+ { $code ": clamp ( seq n -- seq' ) '[ _ max ] map ;" "{ -1 1 -2 0 3 } 0 clamp" }
+ }
+ { $slide "Object system"
+ "CLOS with single dispatch"
+ "A tuple is a user-defined class which holds named values."
+ { $code
+ "TUPLE: rectangle width height ;"
+ "TUPLE: circle radius ;"
+ }
+ }
+ { $slide "Object system"
+ "Constructing instances:"
+ { $code "rectangle new" }
+ { $code "rectangle boa" }
+ "Let's encapsulate:"
+ { $code
+ ": <rectangle> ( w h -- r ) rectangle boa ;"
+ ": <circle> ( r -- c ) circle boa ;"
+ }
+ }
+ { $slide "Object system"
+ "Generic words and methods"
+ { $code "GENERIC: area ( shape -- n )" }
+ "Two methods:"
+ { $code
+ "USE: math.constants"
+ ""
+ "M: rectangle area"
+ " [ width>> ] [ height>> ] bi * ;"
+ ""
+ "M: circle area radius>> sq pi * ;"
+ }
+ }
+ { $slide "Object system"
+ "We can compute areas now."
+ { $code "100 20 <rectangle> area ." }
+ { $code "3 <circle> area ." }
+ }
+ { $slide "Object system"
+ "Object system handles dynamic redefinition very well"
+ { $code "TUPLE: person name age occupation ;" }
+ "Make an instance..."
+ }
+ { $slide "Object system"
+ "Let's add a new slot:"
+ { $code "TUPLE: person name age address occupation ;" }
+ "Fill it in with inspector..."
+ "Change the order:"
+ { $code "TUPLE: person name occupation address ;" }
+ }
+ { $slide "Object system"
+ "How does it work?"
+ "Objects are not hashtables; slot access is very fast"
+ "Redefinition walks the heap; expensive but rare"
+ }
+ { $slide "Object system"
+ "Supports \"duck typing\""
+ "Two tuples can have a slot with the same name"
+ "Code that uses accessors will work on both"
+ "Accessors are auto-generated generic words"
+ }
+ { $slide "Object system"
+ "Predicate classes"
+ { $code
+ "PREDICATE: positive < integer 0 > ;"
+ "PREDICATE: negative < integer 0 < ;"
+ ""
+ "GENERIC: abs ( n -- )"
+ ""
+ "M: positive abs ;"
+ "M: negative abs -1 * ;"
+ "M: integer abs ;"
+ }
+ }
+ { $slide "Object system"
+ "More: inheritance, type declarations, read-only slots, union, intersection, singleton classes, reflection"
+ "Object system is entirely implemented in Factor"
+ }
+ { $slide "The parser"
+ "All data types have a literal syntax"
+ "Literal hashtables and arrays are very useful in data-driven code"
+ "\"Code is data\" because quotations are objects (enables Lisp-style macros)"
+ { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" }
+ "Libraries can define new parsing words"
+ }
+ { $slide "Example: regexp"
+ { $vocab-link "regexp" }
+ "Pre-compiles regexp at parse time"
+ "Implemented with library code"
+ { $code "USE: regexp" }
+ { $code "\"ababbc\" \"[ab]+c\" <regexp> matches? ." }
+ { $code "\"ababbc\" R/ [ab]+c/ matches? ." }
+ }
+ { $slide "Example: memoization"
+ { "Memoization with " { $link POSTPONE: MEMO: } }
+ { $code
+ ": fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Very slow! Let's profile it..."
+ }
+ { $slide "Example: memoization"
+ { "Let's use " { $link POSTPONE: MEMO: } " instead of " { $link POSTPONE: : } }
+ { $code
+ "MEMO: fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Much faster"
+ }
+ { $slide "Meta-circularity"
+ { { $link POSTPONE: MEMO: } " is just a library word" }
+ { "But so is " { $link POSTPONE: : } }
+ "Factor's parser is written in Factor"
+ { "All syntax is just parsing words: " { $link POSTPONE: [ } ", " { $link POSTPONE: " } }
+ }
+ { $slide "Extensible syntax, DSLs"
+ "Most parsing words fall in one of two categories"
+ "First category: literal syntax for new data types"
+ "Second category: defining new types of words"
+ "Some parsing words are more complicated"
+ }
+ { $slide "Example: printf"
+ { { $link POSTPONE: EBNF: } ": a complex parsing word" }
+ "Implements a custom syntax for expressing parsers: like OMeta!"
+ { "Example: " { $vocab-link "printf-example" } }
+ { $code "\"cheese\" \"vegan\" \"%s is not %s\\n\" printf" }
+ { $code "\"Factor\" 5 \"%s is %d years old\\n\" printf" }
+ }
+ { $slide "Example: simple web browser"
+ { $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 "Locals and lexical scope"
+ "Sometimes, there's no good stack solution to a problem"
+ "Or, you're porting existing code in a quick-and-dirty way"
+ "Our solution: implement named locals as a DSL in Factor"
+ "Influenced by Scheme and Lisp"
+ }
+ { $slide "Locals and lexical scope"
+ { "Define lambda words with " { $link POSTPONE: :: } }
+ { "Establish bindings with " { $link POSTPONE: [let } " and " { $snippet "[let*" } }
+ "Mutable bindings with correct semantics"
+ { "Named inputs for quotations with " { $link POSTPONE: [| } }
+ "Full closures"
+ }
+ { $slide "Locals and lexical scope"
+ "Combinator with 5 parameters!"
+ { $code
+ ":: branch ( a b neg zero pos -- )"
+ " a b = zero [ a b < neg pos if ] if ; inline"
+ }
+ "Unwieldy with the stack"
+ }
+ { $slide "Locals and lexical scope"
+ { $code
+ ": check-drinking-age ( age -- )"
+ " 21"
+ " [ \"You're underage!\" print ]"
+ " [ \"Grats, you're now legal\" print ]"
+ " [ \"Go get hammered\" print ]"
+ " branch ;"
+ }
+ }
+ { $slide "Locals and lexical scope"
+ "Locals are entirely implemented in Factor"
+ "Example of compile-time meta-programming"
+ "No performance penalty -vs- using the stack"
+ "In the base image, only 59 words out of 13,000 use locals"
+ }
+ { $slide "More about partial application"
+ { { $link POSTPONE: '[ } " is \"fry syntax\"" }
+ { $code "'[ _ + ] == [ + ] curry" }
+ { $code "'[ @ t ] == [ t ] compose" }
+ { $code "'[ _ nth @ ] == [ [ nth ] curry ] dip compose" }
+ { $code "'[ [ _ ] dip nth ] == [ [ ] curry dip nth ] curry" }
+ { "Fry and locals desugar to " { $link curry } ", " { $link compose } }
+ }
+ { $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 "talks.galois-talk" }
+ }
+ { $slide "Why stack-based?"
+ "Because nobody else is doing it"
+ "Interesting properties: concatenation is composition, chaining functions together, \"fluent\" interfaces, new combinators"
+ { $vocab-link "smtp-example" }
+ { $code
+ "{ \"chicken\" \"beef\" \"pork\" \"turkey\" }"
+ "[ 5 short head ] map ."
+ }
+ }
+ { $slide "Implementation"
+ "VM: garbage collection, bignums, ..."
+ "Bootstrap image: parser, hashtables, object system, ..."
+ "Non-optimizing compiler"
+ "Stage 2 bootstrap: optimizing compiler, UI, ..."
+ "Full image contains machine code"
+ }
+ { $slide "Compiler"
+ { "Let's look at " { $vocab-link "benchmark.mandel" } }
+ "A naive implementation would be very slow"
+ "Combinators, partial application"
+ "Boxed complex numbers"
+ "Boxed floats"
+ { "Redundancy in " { $link absq } " and " { $link sq } }
+ }
+ { $slide "Compiler: high-level optimizer"
+ "High-level SSA IR"
+ "Type inference (classes, intervals, arrays with a fixed length, literals, ...)"
+ "Escape analysis and tuple unboxing"
+ }
+ { $slide "Compiler: high-level optimizer"
+ "Loop index becomes a fixnum, complex numbers unboxed, generic arithmetic inlined, higher-order code become first-order..."
+ { $code "[ c pixel ] optimized." }
+ }
+ { $slide "Compiler: low-level optimizer"
+ "Low-level SSA IR"
+ "Alias analysis"
+ "Value numbering"
+ "Linear scan register allocation"
+ }
+ { $slide "Compiler: low-level optimizer"
+ "Redundant stack operations eliminated, intermediate floats unboxed..."
+ { $code "[ c pixel ] regs." }
+ }
+ { $slide "Garbage collection"
+ "All roots are identified precisely"
+ "Generational copying for data"
+ "Mark sweep for native code"
+ }
+ { $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"
+ "Saves us from the burden of making releases by hand"
+ "Maintains stability"
+ }
+ { $slide "Community"
+ "#concatenative irc.freenode.net: 50-60 members"
+ "factor-talk@lists.sf.net: 180 subscribers"
+ "About 30 people have code in the Factor repository"
+ "Easy to get started: binaries, lots of docs, friendly community..."
+ }
+ { $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?"
+ }
+}
+
+: galois-talk ( -- ) galois-slides "Galois talk" slides-window ;
+
+MAIN: galois-talk
diff --git a/galois-talk/summary.txt b/galois-talk/summary.txt
new file mode 100644
index 0000000..00f30ac
--- /dev/null
+++ b/galois-talk/summary.txt
@@ -0,0 +1 @@
+Slides from a talk at Galois by Slava Pestov, October 2008
diff --git a/galois-talk/tags.txt b/galois-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/galois-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/google-tech-talk/authors.txt b/google-tech-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/google-tech-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/google-tech-talk/google-tech-talk.factor b/google-tech-talk/google-tech-talk.factor
new file mode 100644
index 0000000..a0b511f
--- /dev/null
+++ b/google-tech-talk/google-tech-talk.factor
@@ -0,0 +1,570 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: slides help.markup math arrays hashtables namespaces
+kernel sequences parser memoize io.encodings.binary
+locals kernel.private help.vocabs assocs quotations
+urls peg.ebnf tools.annotations tools.crossref
+help.topics math.functions compiler.tree.optimizer
+compiler.cfg.optimizer fry ;
+IN: talks.google-tech-talk
+
+CONSTANT: google-slides
+{
+ { $slide "Factor!"
+ { $url "http://factorcode.org" }
+ "Development started in 2003"
+ "Open source (BSD license)"
+ "First result for \"Factor\" on Google :-)"
+ "Influenced by Forth, Lisp, and Smalltalk (but don't worry if you don't know them)"
+ }
+ { $slide "Language overview"
+ "Words operate on a stack"
+ "Functional"
+ "Object-oriented"
+ "Rich collections library"
+ "Rich input/output library"
+ "Optional named local variables"
+ "Extensible syntax"
+ }
+ { $slide "Example: factorial"
+ "Lame example, but..."
+ { $code "USE: math.ranges" ": factorial ( n -- n! )" " 1 [a,b] product ;" }
+ { $code "100 factorial ." }
+ }
+ { $slide "Example: sending an e-mail"
+ { $vocab-link "smtp-example" }
+ "Demonstrates basic stack syntax and tuple slot setters"
+ }
+ { $slide "Functional programming"
+ "Code is data in Factor"
+ { { $snippet "[ ... ]" } " is a block of code pushed on the stack" }
+ { "We call them " { $emphasis "quotations" } }
+ { "Words which take quotations as input are called " { $emphasis "combinators" } }
+ }
+ { $slide "Functional programming"
+ { $code "10 dup 0 < [ 1 - ] [ 1 + ] if ." }
+ { $code "10 [ \"Hello Googlers!\" print ] times" }
+ { $code
+ "USING: io.encodings.ascii unicode ;"
+ "{ \"tomato\" \"orange\" \"banana\" }"
+ "\"out.txt\" ascii ["
+ " [ >upper print ] each"
+ "] with-file-writer"
+ }
+ }
+ { $slide "Object system: motivation"
+ "Encapsulation, polymorphism, inheritance"
+ "Smalltalk, Python, Java approach: methods inside classes"
+ "Often the \"message sending\" metaphor is used to describe such systems"
+ }
+ { $slide "Object system: motivation"
+ { $code
+ "class Rect {"
+ " int x, y;"
+ " int area() { ... }"
+ " int perimeter() { ... }"
+ "}"
+ ""
+ "class Circle {"
+ " int radius;"
+ " int area() { ... }"
+ " int perimeter() { ... }"
+ "}"
+ }
+ }
+ { $slide "Object system: motivation"
+ "Classical functional language approach: functions switch on a type"
+ { $code
+ "data Shape = Rect w h | Circle r"
+ ""
+ "area s = s of"
+ " (Rect w h) = ..."
+ "| (Circle r) = ..."
+ ""
+ "perimeter s = s of"
+ " (Rect w h) = ..."
+ "| (Circle r) = ..."
+ }
+ }
+ { $slide "Object system: motivation"
+ "First approach: hard to extend existing types with new operations (open classes, etc are a hack)"
+ "Second approach: hard to extend existing operations with new types"
+ "Common Lisp Object System (CLOS): decouples classes from methods."
+ "Factor's object system is a simplified CLOS"
+ }
+ { $slide "Object system"
+ "A tuple is a user-defined class which holds named values."
+ { $code
+ "TUPLE: rectangle width height ;"
+ "TUPLE: circle radius ;"
+ }
+ }
+ { $slide "Object system"
+ "Constructing instances:"
+ { $code "rectangle new" }
+ { $code "rectangle boa" }
+ "Let's encapsulate:"
+ { $code
+ ": <rectangle> ( w h -- r ) rectangle boa ;"
+ ": <circle> ( r -- c ) circle boa ;"
+ }
+ }
+ { $slide "Object system"
+ "Generic words and methods"
+ { $code "GENERIC: area ( shape -- n )" }
+ "Two methods:"
+ { $code
+ "USE: math.constants"
+ ""
+ "M: rectangle area"
+ " [ width>> ] [ height>> ] bi * ;"
+ ""
+ "M: circle area radius>> sq pi * ;"
+ }
+ }
+ { $slide "Object system"
+ "We can compute areas now."
+ { $code "100 20 <rectangle> area ." }
+ { $code "3 <circle> area ." }
+ }
+ { $slide "Object system"
+ "New operation, existing types:"
+ { $code
+ "GENERIC: perimeter ( shape -- n )"
+ ""
+ "M: rectangle perimeter"
+ " [ width>> ] [ height>> ] bi + 2 * ;"
+ ""
+ "M: circle perimeter"
+ " radius>> 2 * pi * ;"
+ }
+ }
+ { $slide "Object system"
+ "We can compute perimeters now."
+ { $code "100 20 <rectangle> perimeter ." }
+ { $code "3 <circle> perimeter ." }
+ }
+ { $slide "Object system"
+ "New type, extending existing operations:"
+ { $code
+ "TUPLE: triangle base height ;"
+ ""
+ ": <triangle> ( b h -- t ) triangle boa ;"
+ ""
+ "M: triangle area"
+ " [ base>> ] [ height>> ] bi * 2 / ;"
+ }
+ }
+ { $slide "Object system"
+ "New type, extending existing operations:"
+ { $code
+ ": hypotenuse ( x y -- z ) [ sq ] bi@ + sqrt ;"
+ ""
+ "M: triangle perimeter"
+ " [ base>> ] [ height>> ] bi"
+ " [ + ] [ hypotenuse ] 2bi + ;"
+ }
+ }
+ { $slide "Object system"
+ "We can ask an object if its a rectangle:"
+ { $code "70 65 <rectangle> rectangle? ." }
+ { $code "13 <circle> rectangle? ." }
+ { "How do we tell if something is a " { $emphasis "shape" } "?" }
+ }
+ { $slide "Object system"
+ "We define a mixin class for shapes, and add our existing data types as instances:"
+ { $code
+ "MIXIN: shape"
+ "INSTANCE: rectangle shape"
+ "INSTANCE: circle shape"
+ "INSTANCE: triangle shape"
+ }
+ }
+ { $slide "Object system"
+ "Now, we can ask objects if they are shapes or not:"
+ { $code "13 <circle> shape? ." }
+ { $code "3.14 shape? ." }
+ }
+ { $slide "Object system"
+ "Or put methods on shapes:"
+ { $code
+ "GENERIC: tell-me ( obj -- )"
+ ""
+ "M: shape tell-me"
+ " \"My area is \" write area . ;"
+ ""
+ "M: integer tell-me"
+ " \"I am \" write"
+ " even? \"even\" \"odd\" ? print ;"
+ }
+ }
+ { $slide "Object system"
+ "Let's test our new generic word:"
+ { $code "13 <circle> tell-me" }
+ { $code "103 76 <rectangle> tell-me" }
+ { $code "101 tell-me" }
+ { { $link integer } ", " { $link array } ", and others are built-in classes" }
+ }
+ { $slide "Object system"
+ "Anyone can define new shapes..."
+ { $code
+ "TUPLE: parallelogram ... ;"
+ ""
+ "INSTANCE: parallelogram shape"
+ ""
+ "M: parallelogram area ... ;"
+ ""
+ "M: parallelogram perimeter ... ;"
+ }
+ }
+ { $slide "Object system"
+ "More: inheritance, type declarations, read-only slots, predicate, intersection, singleton classes, reflection"
+ "Object system is entirely implemented in Factor: 2184 lines"
+ { { $vocab-link "generic" } ", " { $vocab-link "classes" } ", " { $vocab-link "slots" } }
+ }
+ { $slide "Collections"
+ "Sequences (arrays, vector, strings, ...)"
+ "Associative mappings (hashtables, ...)"
+ { "More: deques, heaps, purely functional structures, disjoint sets, and more: "
+ { $link T{ vocab-tag f "collections" } } }
+ }
+ { $slide "Sequences"
+ { "Protocol: " { $link length } ", " { $link set-length } ", " { $link nth } ", " { $link set-nth } }
+ { "Combinators: " { $link each } ", " { $link map } ", " { $link filter } ", " { $link produce } ", and more: " { $link "sequences-combinators" } }
+ { "Utilities: " { $link append } ", " { $link reverse } ", " { $link first } ", " { $link second } ", ..." }
+ }
+ { $slide "Example: bin packing"
+ { "We have " { $emphasis "m" } " objects and " { $emphasis "n" } " bins, and we want to distribute these objects as evenly as possible." }
+ { $vocab-link "distribute-example" }
+ "Demonstrates various sequence utilities and vector words"
+ { $code "20 13 distribute ." }
+ }
+ { $slide "Unicode strings"
+ "Strings are sequences of 21-bit Unicode code points"
+ "Efficient implementation: ASCII byte string unless it has chars > 127"
+ "If a byte char has high bit set, the remaining 14 bits come from auxiliary vector"
+ }
+ { $slide "Unicode strings"
+ "Unicode-aware case conversion, char classes, collation, word breaks, and so on..."
+ { $code "USE: unicode" "\"ß\" >upper ." }
+ }
+ { $slide "Unicode strings"
+ "All external byte I/O is encoded/decoded"
+ "ASCII, UTF8, UTF16, EBCDIC..."
+ { $code "USE: io.encodings.utf8" "\"document.txt\" utf8" "[ readln ] with-file-reader" }
+ { "Binary I/O is supported as well with the " { $link binary } " encoding" }
+ }
+ { $slide "Associative mappings"
+ { "Protocol: " { $link assoc-size } ", " { $link at* } ", " { $link set-at } ", " { $link delete-at } }
+ { "Combinators: " { $link assoc-each } ", " { $link assoc-map } ", " { $link assoc-filter } ", and more: " { $link "assocs-combinators" } }
+ { "Utilities: " { $link at } ", " { $link key? } ", ..." }
+ }
+ ! { $slide "Example: soundex"
+ ! { $vocab-link "soundex" }
+ ! "From Wikipedia: \"Soundex is a phonetic algorithm for indexing names by sound, as pronounced in English.\""
+ ! "Factored into many small words, uses sequence and assoc operations, no explicit loops"
+ ! }
+ { $slide "Locals and lexical scope"
+ "Sometimes, there's no good stack solution to a problem"
+ "Or, you're porting existing code in a quick-and-dirty way"
+ "Our solution: implement named locals as a DSL in Factor"
+ "Influenced by Scheme and Lisp"
+ }
+ { $slide "Locals and lexical scope"
+ { "Define lambda words with " { $link POSTPONE: :: } }
+ { "Establish bindings with " { $link POSTPONE: [let } " and " { $snippet "[let*" } }
+ "Mutable bindings with correct semantics"
+ { "Named inputs for quotations with " { $link POSTPONE: [| } }
+ "Full closures"
+ }
+ { $slide "Locals and lexical scope"
+ "Two examples:"
+ { $vocab-link "lambda-quadratic" }
+ { $vocab-link "closures-example" }
+ }
+ { $slide "Locals and lexical scope"
+ "Locals are entirely implemented in Factor: 477 lines"
+ "Example of compile-time meta-programming"
+ "No performance penalty -vs- using the stack"
+ "In the base image, only 59 words out of 13,000 use locals"
+ }
+ { $slide "The parser"
+ "All data types have a literal syntax"
+ "Literal hashtables and arrays are very useful in data-driven code"
+ "\"Code is data\" because quotations are objects (enables Lisp-style macros)"
+ { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" }
+ "Libraries can define new parsing words"
+ }
+ { $slide "The parser"
+ { "Example: URLs define a " { $link POSTPONE: URL" } " word" }
+ { $code "URL\" http://paste.factorcode.org/paste?id=81\"" }
+ }
+ { $slide "Example: memoization"
+ { "Memoization with " { $link POSTPONE: MEMO: } }
+ { $code
+ ": fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Very slow! Let's profile it..."
+ }
+ { $slide "Example: memoization"
+ { "Let's use " { $link POSTPONE: : } " instead of " { $link POSTPONE: MEMO: } }
+ { $code
+ "MEMO: fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Much faster"
+ }
+ { $slide "Meta-circularity"
+ { { $link POSTPONE: MEMO: } " is just a library word" }
+ { "But so is " { $link POSTPONE: : } }
+ "Factor's parser is written in Factor"
+ { "All syntax is just parsing words: " { $link POSTPONE: [ } ", " { $link POSTPONE: " } }
+ }
+ { $slide "Extensible syntax, DSLs"
+ "Most parsing words fall in one of two categories"
+ "First category: literal syntax for new data types"
+ "Second category: defining new types of words"
+ "Some parsing words are more complicated"
+ }
+ { $slide "Parser expression grammars"
+ { { $link POSTPONE: EBNF: } ": a complex parsing word" }
+ "Implements a custom syntax for expressing parsers"
+ { "Example: " { $vocab-link "printf-example" } }
+ { $code "\"cheese\" \"vegan\" \"%s is not %s\\n\" printf" }
+ { $code "\"Factor\" 5 \"%s is %d years old\\n\" printf" }
+ }
+ { $slide "Input/output library"
+ "One of Factor's strongest points: portable, full-featured, efficient"
+ { $vocab-link "io.files" }
+ { $vocab-link "io.launcher" }
+ { $vocab-link "io.monitors" }
+ { $vocab-link "io.mmap" }
+ { $vocab-link "http.client" }
+ "... and so on"
+ }
+ { $slide "Example: file system monitors"
+ { $code
+ "USE: io.monitors"
+ ""
+ ": forever ( quot -- ) '[ @ t ] loop ; inline"
+ ""
+ "\"/tmp\" t <monitor>"
+ "'[ _ next-change . ] forever"
+ }
+ }
+ { $slide "Example: time server"
+ { $vocab-link "time-server" }
+ { "Demonstrates " { $vocab-link "io.servers" } " vocabulary, threads" }
+ }
+ { $slide "Example: what is my IP?"
+ { $vocab-link "webapps.ip" }
+ "Simple web app, defines a single action, use an XHTML template"
+ "Web framework supports more useful features: sessions, SSL, form validation, ..."
+ }
+ { $slide "Example: Yahoo! web search"
+ { $vocab-link "yahoo" }
+ { "Demonstrates " { $vocab-link "http.client" } ", " { $vocab-link "xml" } }
+ }
+ { $slide "Example: simple web browser"
+ { $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 "Example: environment variables"
+ { $vocab-link "environment" }
+ "Hooks are generic words which dispatch on dynamically-scoped variables"
+ { "Implemented in an OS-specific way: " { $vocab-link "environment.unix" } ", " { $vocab-link "environment.windows" } }
+ }
+ { $slide "Example: environment variables"
+ "Implementations use C FFI"
+ "Call C functions, call function pointers, call Factor from C, structs, floats, ..."
+ "No need to write C wrapper code"
+ }
+ { $slide "Implementation"
+ "VM: 12,000 lines of C"
+ "Generational garbage collection"
+ "core: 9,000 lines of Factor"
+ "Optimizing native code compiler for x86, PowerPC"
+ "basis: 80,000 lines of Factor"
+ }
+ { $slide "Compiler"
+ { "Let's look at " { $vocab-link "benchmark.mandel" } }
+ "A naive implementation would be very slow"
+ "Combinators, currying, partial application"
+ "Boxed complex numbers"
+ "Boxed floats"
+ { "Redundancy in " { $link absq } " and " { $link sq } }
+ }
+ { $slide "Compiler: front-end"
+ "Builds high-level tree SSA IR"
+ "Stack code with uniquely-named values"
+ "Inlines combinators and calls to quotations"
+ { $code "USING: compiler.tree.builder compiler.tree.debugger ;" "[ c pixel ] build-tree nodes>quot ." }
+ }
+ { $slide "Compiler: high-level optimizer"
+ "12 optimization passes"
+ { $link optimize-tree }
+ "Some passes collect information, others use the results of past analysis to rewrite the code"
+ }
+ { $slide "Compiler: propagation pass"
+ "Propagation pass computes types with type function"
+ { "Example: output type of " { $link + } " depends on the types of inputs" }
+ "Type: can be a class, a numeric interval, array with a certain length, tuple with certain type slots, literal value, ..."
+ "Mandelbrot: we infer that we're working on complex floats"
+ }
+ { $slide "Compiler: propagation pass"
+ "Propagation also supports \"constraints\""
+ { $code "[ dup array? [ first ] when ] optimized." }
+ { $code "[ >fixnum dup 0 < [ 1 + ] when ] optimized." }
+ { $code
+ "["
+ " >fixnum"
+ " dup [ -10 > ] [ 10 < ] bi and"
+ " [ 1 + ] when"
+ "] optimized."
+ }
+ }
+ { $slide "Compiler: propagation pass"
+ "Eliminates method dispatch, inlines method bodies"
+ "Mandelbrot: we infer that integer indices are fixnums"
+ "Mandelbrot: we eliminate generic arithmetic"
+ }
+ { $slide "Compiler: escape analysis"
+ "We identify allocations for tuples which are never returned or passed to other words (except slot access)"
+ { "Partial application with " { $link POSTPONE: '[ } }
+ "Complex numbers"
+ }
+ { $slide "Compiler: escape analysis"
+ { "Virtual sequences: " { $link <slice> } ", " { $link <reversed> } }
+ { $code "[ <reversed> [ . ] each ] optimized." }
+ { "Mandelbrot: we unbox " { $link curry } ", complex number allocations" }
+ }
+ { $slide "Compiler: dead code elimination"
+ "Cleans up the mess from previous optimizations"
+ "After inlining and dispatch elimination, dead code comes up because of unused generality"
+ { "No-ops like " { $snippet "0 +" } ", " { $snippet "1 *" } }
+ "Literals which are never used"
+ "Side-effect-free words whose outputs are dropped"
+ }
+ { $slide "Compiler: low level IR"
+ "Register-based SSA"
+ "Stack operations expand into low-level instructions"
+ { $code "[ 5 ] regs." }
+ { $code "[ swap ] regs." }
+ { $code "[ append reverse ] regs." }
+ }
+ { $slide "Compiler: low-level optimizer"
+ "5 optimization passes"
+ { $link optimize-cfg }
+ "Gets rid of redundancy which is hidden in high-level stack code"
+ }
+ { $slide "Compiler: optimize memory"
+ "First pass optimizes stack and memory operations"
+ { "Example: " { $link 2array } }
+ { { $link <array> } " fills array with initial value" }
+ "What if we immediately store new values into the array?"
+ { $code "\\ 2array regs." }
+ "Mandelbrot: we optimize stack operations"
+ }
+ { $slide "Compiler: value numbering"
+ "Identifies expressions which are computed more than once in a basic block"
+ "Simplifies expressions with various identities"
+ "Mandelbrot: redundant float boxing and unboxing, redundant arithmetic"
+ }
+ { $slide "Compiler: dead code elimination"
+ "Dead code elimination for low-level IR"
+ "Again, cleans up results of prior optimizations"
+ }
+ { $slide "Compiler: register allocation"
+ "IR assumes an infinite number of registers which are only assigned once"
+ "Real CPUs have a finite set of registers which can be assigned any number of times"
+ "\"Linear scan register allocation with second-chance binpacking\""
+ }
+ { $slide "Compiler: register allocation"
+ "3 steps:"
+ "Compute live intervals"
+ "Allocate registers"
+ "Assign registers and insert spills"
+ }
+ { $slide "Compiler: register allocation"
+ "Step 1: compute live intervals"
+ "We number all instructions consecutively"
+ "A live interval associates a virtual register with a list of usages"
+ }
+ { $slide "Compiler: register allocation"
+ "Step 2: allocate registers"
+ "We scan through sorted live intervals"
+ "If a physical register is available, assign"
+ "Otherwise, find live interval with furthest away use, split it, look at both parts again"
+ }
+ { $slide "Compiler: register allocation"
+ "Step 3: assign registers and insert spills"
+ "Simple IR rewrite step"
+ "After register allocation, one vreg may have several live intervals, and different physical registers at different points in time"
+ "Hence, \"second chance\""
+ { "Mandelbrot: " { $code "[ c pixel ] regs." } }
+ }
+ { $slide "Compiler: code generation"
+ "Iterate over list of instructions"
+ "Extract tuple slots and call hooks"
+ { $vocab-link "cpu.architecture" }
+ "Finally, we hand the code to the VM"
+ { $code "\\ 2array disassemble" }
+ }
+ { $slide "Garbage collection"
+ "All roots are identified precisely"
+ "Generational copying for data"
+ "Mark sweep for native code"
+ }
+ { $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"
+ "Saves us from the burden of making releases by hand"
+ "Maintains stability"
+ }
+ { $slide "Community"
+ "#concatenative irc.freenode.net: 50-60 members"
+ "factor-talk@lists.sf.net: 180 subscribers"
+ "About 30 people have code in the Factor repository"
+ "Easy to get started: binaries, lots of docs, friendly community..."
+ }
+ { $slide "Future direction: Factor 1.0"
+ "Continue doing what we're doing:"
+ "Polish off some language features"
+ "Stability"
+ "Performance"
+ "Documentation"
+ "Developer tools"
+ }
+ { $slide "Future direction: Factor 2.0"
+ "Native threads"
+ "Syntax-aware Factor editor"
+ "Embedding Factor in C apps"
+ "Cross-compilation for smaller devices"
+ }
+ { $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"
+ "Put your prejudices aside and give it a shot!"
+ }
+ { $slide "Questions?" }
+}
+
+: google-talk ( -- )
+ google-slides "Google Tech talk" slides-window ;
+
+MAIN: google-talk
diff --git a/google-tech-talk/summary.txt b/google-tech-talk/summary.txt
new file mode 100644
index 0000000..1747a56
--- /dev/null
+++ b/google-tech-talk/summary.txt
@@ -0,0 +1 @@
+Slides from Google Tech Talk by Slava Pestov, October 2008
diff --git a/google-tech-talk/tags.txt b/google-tech-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/google-tech-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/hmc-talk/hmc-talk.factor b/hmc-talk/hmc-talk.factor
new file mode 100644
index 0000000..9a225f9
--- /dev/null
+++ b/hmc-talk/hmc-talk.factor
@@ -0,0 +1,491 @@
+USING: fry help.markup help.topics kernel locals math
+math.functions memoize peg.ebnf slides ;
+IN: talks.hmc-talk
+
+CONSTANT: hmc-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 "Concepts"
+ "Concatenative"
+ "Dynamic types"
+ "Extensible syntax"
+ "Fully-compiled"
+ "Cross-platform"
+ "Interactive Development"
+ "Code is data"
+ "Pervasive unit testing"
+ "Clickable"
+ }
+
+ { $slide "Words and the stack"
+ "Stack based, dynamically typed"
+ { $code "{ 1 1 3 4 4 8 9 9 } dup duplicates diff ." }
+ "Words: named code snippets"
+ { $code ": remove-duplicates ( seq -- seq' )" " dup duplicates diff ;" }
+ { $code "{ 1 1 3 4 4 8 9 9 } remove-duplicates ." }
+ }
+
+ { $slide "Words and the stack"
+ { $code
+ "\"/usr/local/opt/fortune/share/games/fortunes/science\""
+ "ascii file-lines"
+ "{ \"%\" } split random"
+ "[ print ] each"
+ }
+ { $code
+ ": fortune ( -- )"
+ " \"/usr/local/opt/fortune/share/games/fortunes/science\""
+ " ascii file-lines"
+ " { \"%\" } split random"
+ " [ print ] each ;"
+ }
+ { $code
+ "5 [ fortune nl ] times"
+ }
+ }
+
+ { $slide "Vocabularies"
+ "Vocabularies: named sets of words"
+ { $link "vocab-index" }
+ { { $link POSTPONE: USING: } " loads dependencies" }
+ "Source, docs, tests in one place"
+ }
+ { $slide "Interactive development"
+ "Programming is hard, let's play tetris"
+ { $vocab-link "tetris" }
+ "Tetris is hard too... let's cheat"
+ "Factor workflow: change code, F2, test, repeat"
+ }
+ { $slide "Quotations"
+ "Quotation: unnamed block of code"
+ "Combinators: words taking quotations"
+ { $code "10 dup 0 < [ 1 - ] [ 1 + ] if ." }
+ { $code "{ -1 1 -2 0 3 } [ 0 max ] map ." }
+ "Partial application:"
+ { $code ": clamp ( seq n -- seq' ) '[ _ max ] map ;" "{ -1 1 -2 0 3 } 0 clamp" }
+ }
+ { $slide "Object system"
+ "CLOS with single dispatch"
+ "A tuple is a user-defined class which holds named values."
+ { $code
+ "TUPLE: rectangle width height ;"
+ "TUPLE: circle radius ;"
+ }
+ }
+ { $slide "Object system"
+ "Constructing instances:"
+ { $code "rectangle new" }
+ { $code "rectangle boa" }
+ "Let's encapsulate:"
+ { $code
+ ": <rectangle> ( w h -- r ) rectangle boa ;"
+ ": <circle> ( r -- c ) circle boa ;"
+ }
+ }
+ { $slide "Object system"
+ "Generic words and methods"
+ { $code "GENERIC: area ( shape -- n )" }
+ "Two methods:"
+ { $code
+ "USE: math.constants"
+ ""
+ "M: rectangle area"
+ " [ width>> ] [ height>> ] bi * ;"
+ ""
+ "M: circle area radius>> sq pi * ;"
+ }
+ }
+ { $slide "Object system"
+ "We can compute areas now."
+ { $code "100 20 <rectangle> area ." }
+ { $code "3 <circle> area ." }
+ }
+ { $slide "Object system"
+ "Object system handles dynamic redefinition very well"
+ { $code "TUPLE: person name age occupation ;" }
+ "Make an instance..."
+ }
+ { $slide "Object system"
+ "Let's add a new slot:"
+ { $code "TUPLE: person name age address occupation ;" }
+ "Fill it in with inspector..."
+ "Change the order:"
+ { $code "TUPLE: person name occupation address ;" }
+ }
+ { $slide "Object system"
+ "How does it work?"
+ "Objects are not hashtables; slot access is very fast"
+ "Redefinition walks the heap; expensive but rare"
+ }
+ { $slide "Object system"
+ "Supports \"duck typing\""
+ "Two tuples can have a slot with the same name"
+ "Code that uses accessors will work on both"
+ "Accessors are auto-generated generic words"
+ }
+ { $slide "Object system"
+ "Predicate classes"
+ { $code
+ "PREDICATE: positive < integer 0 > ;"
+ "PREDICATE: negative < integer 0 < ;"
+ ""
+ "GENERIC: abs ( n -- )"
+ ""
+ "M: positive abs ;"
+ "M: negative abs -1 * ;"
+ "M: integer abs ;"
+ }
+ }
+ { $slide "Object system"
+ "More: inheritance, type declarations, read-only slots, union, intersection, singleton classes, reflection"
+ "Object system is entirely implemented in Factor"
+ }
+ { $slide "The parser"
+ "All data types have a literal syntax"
+ "Literal hashtables and arrays are very useful in data-driven code"
+ "\"Code is data\" because quotations are objects (enables Lisp-style macros)"
+ { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" }
+ "Libraries can define new parsing words"
+ }
+ { $slide "Example: regexp"
+ { $vocab-link "regexp" }
+ "Pre-compiles regexp at parse time"
+ "Implemented with library code"
+ { $code "USE: regexp" }
+ { $code "\"ababbc\" \"[ab]+c\" <regexp> matches? ." }
+ { $code "\"ababbc\" R/ [ab]+c/ matches? ." }
+ }
+ { $slide "Example: memoization"
+ { "Memoization with " { $link POSTPONE: MEMO: } }
+ { $code
+ ": fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Very slow! Let's profile it..."
+ }
+ { $slide "Example: memoization"
+ { "Let's use " { $link POSTPONE: MEMO: } " instead of " { $link POSTPONE: : } }
+ { $code
+ "MEMO: fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Much faster"
+ }
+ { $slide "Meta-circularity"
+ { { $link POSTPONE: MEMO: } " is just a library word" }
+ { "But so is " { $link POSTPONE: : } }
+ "Factor's parser is written in Factor"
+ { "All syntax is just parsing words: " { $link POSTPONE: [ } ", " { $link POSTPONE: " } }
+ }
+ { $slide "Extensible syntax, DSLs"
+ "Most parsing words fall in one of two categories"
+ "First category: literal syntax for new data types"
+ "Second category: defining new types of words"
+ "Some parsing words are more complicated"
+ }
+
+ { $slide "Example: printf"
+ { { $link POSTPONE: EBNF: } ": a complex parsing word" }
+ "Implements a custom syntax for expressing parsers: like OMeta!"
+ { "Example: " { $vocab-link "printf" } }
+ { $code "\"cheese\" \"vegan\" \"%s is not %s\\n\" printf" }
+ { $code "\"Factor\" 5 \"%s is %d years old\\n\" printf" }
+ { $code "[ \"%s monkeys\" printf ] expand-macros" }
+ }
+ { $slide "Locals and lexical scope"
+ "Sometimes, there's no good stack solution to a problem"
+ "Or, you're porting existing code in a quick-and-dirty way"
+ "Our solution: implement named locals as a DSL in Factor"
+ "Influenced by Scheme and Lisp"
+ }
+ { $slide "Locals and lexical scope"
+ { "Define lambda words with " { $link POSTPONE: :: } }
+ { "Establish bindings with " { $link POSTPONE: [let } " and " { $snippet "[let*" } }
+ "Mutable bindings with correct semantics"
+ { "Named inputs for quotations with " { $link POSTPONE: [| } }
+ "Full closures"
+ }
+ { $slide "Locals and lexical scope"
+ "Combinator with 5 parameters!"
+ { $code
+ ":: branch ( a b neg zero pos -- )"
+ " a b = zero [ a b < neg pos if ] if ; inline"
+ }
+ "Unwieldy with the stack"
+ }
+ { $slide "Locals and lexical scope"
+ { $code
+ ": check-drinking-age ( age -- )"
+ " 21"
+ " [ \"You're underage!\" print ]"
+ " [ \"Grats, you're now legal\" print ]"
+ " [ \"Go get hammered\" print ]"
+ " branch ;"
+ }
+ }
+ { $slide "Locals and lexical scope"
+ "Locals are entirely implemented in Factor"
+ "Example of compile-time meta-programming"
+ "No performance penalty -vs- using the stack"
+ "In the base image, only 59 words out of 13,000 use locals"
+ }
+ { $slide "More about partial application"
+ { { $link POSTPONE: '[ } " is \"fry syntax\"" }
+ { $code "'[ _ + ] == [ + ] curry" }
+ { $code "'[ @ t ] == [ t ] compose" }
+ { $code "'[ _ nth @ ] == [ [ nth ] curry ] dip compose" }
+ { $code "'[ [ _ ] dip nth ] == [ [ ] curry dip nth ] curry" }
+ { "Fry and locals desugar to " { $link curry } ", " { $link compose } }
+ }
+ { $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 "talks.hmc-talk" }
+ }
+ { $slide "Why stack-based?"
+ "Because nobody else is doing it"
+ "Interesting properties: concatenation is composition, chaining functions together, \"fluent\" interfaces, new combinators"
+ { $vocab-link "simple-rpg" }
+ { $code
+ "{ \"chicken\" \"beef\" \"pork\" \"turkey\" }"
+ "[ 5 short head ] map ."
+ }
+ }
+ { $slide "Implementation"
+ "VM: garbage collection, bignums, ..."
+ "Bootstrap image: parser, hashtables, object system, ..."
+ "Non-optimizing compiler"
+ "Stage 2 bootstrap: optimizing compiler, UI, ..."
+ "Full image contains machine code"
+ }
+ { $slide "Compiler"
+ { "Let's look at " { $vocab-link "benchmark.mandel" } }
+ "A naive implementation would be very slow"
+ "Combinators, partial application"
+ "Boxed complex numbers"
+ "Boxed floats"
+ { "Redundancy in " { $link absq } " and " { $link sq } }
+ }
+ { $slide "Compiler: high-level optimizer"
+ "High-level SSA IR"
+ "Type inference (classes, intervals, arrays with a fixed length, literals, ...)"
+ "Escape analysis and tuple unboxing"
+ }
+ { $slide "Compiler: high-level optimizer"
+ "Loop index becomes a fixnum, complex numbers unboxed, generic arithmetic inlined, higher-order code become first-order..."
+ { $code "[ c pixel ] optimized." }
+ }
+ { $slide "Compiler: low-level optimizer"
+ "Low-level SSA IR"
+ "Alias analysis"
+ "Value numbering"
+ "Linear scan register allocation"
+ }
+ { $slide "Compiler: low-level optimizer"
+ "Redundant stack operations eliminated, intermediate floats unboxed..."
+ { $code "[ c pixel ] regs." }
+ }
+ { $slide "Compiler: assembly"
+ "Generic assembly generated..."
+ { $code "[ c pixel ] disassemble" }
+ }
+ { $slide "Compiler: assembly"
+ "Efficient assembly generated..."
+ { $code "[ { fixnum fixnum } declare c pixel ] disassemble" }
+ }
+ { $slide "Garbage collection"
+ "All roots are identified precisely"
+ "Generational copying for data"
+ "Mark sweep for native code"
+ }
+
+ { $slide "Project infrastructure"
+ { $url "http://factorcode.org" }
+ { $url "http://concatenative.org" }
+ { $url "http://docs.factorcode.org" }
+ { $url "http://planet.factorcode.org" }
+ { $url "http://paste.factorcode.org" }
+ "Uses our HTTP server, SSL, DB, Atom libraries..."
+ }
+ { $slide "Project infrastructure"
+ "Build farm, written in Factor"
+ "Multiple OS and architecture"
+ "Builds Factor and all libraries, runs tests, makes binaries"
+ "Saves us from the burden of making releases by hand"
+ "Maintains stability"
+ }
+
+ { $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?"
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USE: xkcd"
+ "XKCD: 138"
+ }
+ { $code
+ "USE: reddit"
+ "\"programming\" subreddit."
+ }
+ }
+
+ { $slide "Cool things"
+ { $vocab-link "minesweeper" }
+ { $vocab-link "game-of-life" }
+ { $vocab-link "boids" }
+ }
+
+ { $slide "Cool things"
+ "8080 cpu emulator"
+ { $code
+ "\"resource:roms\" rom-root set-global"
+ }
+ { $vocab-link "roms.space-invaders" }
+ }
+
+ { $slide "Cool things"
+ { $vocab-link "bloom-filters" }
+ { $vocab-link "cuckoo-filters" }
+ { $vocab-link "persistent" }
+ { $vocab-link "trees" }
+ { $vocab-link "tuple-arrays" }
+ { $vocab-link "specialized-arrays" }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USE: text-to-speech"
+ "\"hello\" speak-text"
+ }
+ { $code
+ "USE: morse"
+ "\"hello\" play-as-morse"
+ }
+ { $code
+ "USE flip-text"
+ "\"hello\" flip-text ."
+ }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "{ 12 18 24 72 }"
+ "[ \"Bigger\" swap font-size associate format nl ] each"
+ }
+
+ { $code
+ "10 <iota> ["
+ " \"Hello world\""
+ " swap 10 / 1 over - over 1 <rgba>"
+ " background associate format nl"
+ "] each"
+ }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USE: google.charts"
+ "\"x = \\\\frac{-b \\\\pm \\\\sqrt {b^2-4ac}}{2a}\""
+ "<formula> 200 >>width 75 >>height chart."
+ }
+ { $code
+ "100 [ 100 random ] replicate"
+ "100 [ 100 random ] replicate"
+ "zip <scatter> chart."
+ }
+ { $code
+ "\"/usr/share/dict/words\" utf8 file-lines"
+ "[ >lower 1 head ] histogram-by"
+ "sort-keys <bar>"
+ " COLOR: green >>foreground"
+ " 400 >>width"
+ " 10 >>bar-width"
+ "chart."
+ }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USE: http.client"
+ "\\ http-get see"
+ }
+ { $code
+ "\"http\" apropos"
+ }
+ { $code
+ "USE: images.http"
+ "\"https://factorcode.org/logo.png\" http-image."
+ }
+ }
+
+ { $slide "Cool things"
+ "Tab completion"
+ { $code
+ "http"
+ }
+ { $code
+ "P\" vocab:math"
+ }
+ { $code
+ "COLOR: "
+ }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USE: emojify"
+ "\"I :heart: Factor! :+1!\" emojify ."
+ }
+ { $code
+ "USE: dice"
+ "ROLL: 2d8+4"
+ "\"You do %s points of damage!\" printf"
+ }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USING: sequences xml.syntax xml.writer ;"
+ "{ \"three\" \"blind\" \"mice\" }"
+ "[ [XML <li><-></li> XML] ] map"
+ "[XML <ul><-></ul> XML]"
+ "pprint-xml"
+ }
+ }
+
+ { $slide "Cool things"
+ { $code
+ "USE: io.streams.256color"
+ "[ listener ] with-256color"
+ "\"math\" about"
+ }
+ }
+
+ { $slide "Cool things"
+ { $code "./factor -run=tetris" }
+ { $code "./factor -run=file-server" }
+ { $code "./factor -run=file-monitor" }
+ { $code "./factor -run=tools.dns microsoft.com" }
+ { $code "./factor -run=tools.cal" }
+ }
+}
+
+: hmc-talk ( -- ) hmc-slides "HMC Talk" slides-window ;
+
+MAIN: hmc-talk
diff --git a/jvm-summit-talk/authors.txt b/jvm-summit-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/jvm-summit-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/jvm-summit-talk/jvm-summit-talk.factor b/jvm-summit-talk/jvm-summit-talk.factor
new file mode 100644
index 0000000..b91bf01
--- /dev/null
+++ b/jvm-summit-talk/jvm-summit-talk.factor
@@ -0,0 +1,358 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: slides help.markup math math.private kernel sequences
+slots.private ;
+IN: talks.jvm-summit-talk
+
+CONSTANT: jvm-summit-slides
+{
+ { $slide "Factor language implementation"
+ "Goals: expressiveness, metaprogramming, performance"
+ "We want a language for anything from scripting DSLs to high-performance numerics"
+ "I assume you know a bit about compiler implementation: parser -> frontend -> optimizer -> codegen"
+ { "This is " { $strong "not" } " a talk about the Factor language" }
+ { "Go to " { $url "http://factorcode.org" } " to learn the language" }
+ }
+ { $slide "Why are dynamic languages slow?"
+ "Branching and indirection!"
+ "Runtime type checks and dispatch"
+ "Integer overflow checks"
+ "Boxed integers and floats"
+ "Lots of allocation of temporary objects"
+ }
+ { $slide "Interactive development"
+ "Code can be reloaded at any time"
+ "Class hierarchy might change"
+ "Slots may be added and removed"
+ "Functions might be redefined"
+ }
+ { $slide "Factor's solution"
+ "Factor implements most of the library in Factor"
+ "Library contains very generic, high-level code"
+ "Always compiles to native code"
+ "Compiler removes unused generality from high-level code"
+ "Inlining, specialization, partial evaluation"
+ "And deoptimize when assumptions change"
+ }
+ { $slide "Introduction: SSA form"
+ "Every identifier only has one global definition"
+ {
+ "Not SSA:"
+ { $code
+ "x = 1"
+ "y = 2"
+ "x = x + y"
+ "if(z < 0)"
+ " t = x + y"
+ "else"
+ " t = x - y"
+ "print(t)"
+ }
+ }
+ }
+ { $slide "Introduction: SSA form"
+ "Rename re-definitions and subsequent usages"
+ {
+ "Still not SSA:"
+ { $code
+ "x = 1"
+ "y = 2"
+ "x1 = x + y"
+ "if(z < 0)"
+ " t = x1 + y"
+ "else"
+ " t = x1 - y"
+ "print(t)"
+ }
+ }
+ }
+ { $slide "Introduction: SSA form"
+ "Introduce “φ functions” at control-flow merge points"
+ {
+ "This is SSA:"
+ { $code
+ "x = 1"
+ "y = 2"
+ "x1 = x + y"
+ "if(z < 0)"
+ " t1 = x1 + y"
+ "else"
+ " t2 = x1 - y"
+ "t3 = φ(t1,t2)"
+ "print(t3)"
+ }
+ }
+ }
+ { $slide "Why SSA form?"
+ {
+ "Def-use chains:"
+ { $list
+ "Defs-of: instructions that define a value"
+ "Uses-of: instructions that use a value"
+ }
+ "With SSA, defs-of has exactly one element"
+ }
+ }
+ { $slide "Def-use chains"
+ "Simpler def-use makes analysis more accurate."
+ {
+ "Non-SSA example:"
+ { $code
+ "if(x < 0)"
+ " s = new Circle"
+ " a = area(s1)"
+ "else"
+ " s = new Rectangle"
+ " a = area(s2)"
+ }
+ }
+ }
+ { $slide "Def-use chains"
+ {
+ "SSA example:"
+ { $code
+ "if(x < 0)"
+ " s1 = new Circle"
+ " a1 = area(s1)"
+ "else"
+ " s2 = new Rectangle"
+ " a2 = area(s2)"
+ "a = φ(a1,a2)"
+ }
+
+ }
+ }
+ { $slide "Factor compiler overview"
+ "High-level SSA IR constructed from stack code"
+ "High level optimizer transforms high-level IR"
+ "Low-level SSA IR is constructed from high-level IR"
+ "Low level optimizer transforms low-level IR"
+ "Register allocator runs on low-level IR"
+ "Machine IR is constructed from low-level IR"
+ "Code generation"
+ }
+ { $slide "High-level optimizer"
+ "Frontend: expands macros, inline higher order functions"
+ "Propagation: inline methods, constant folding"
+ "Escape analysis: unbox tuples"
+ "Dead code elimination: clean up"
+ }
+ { $slide "Higher-order functions"
+ "Almost all control flow is done with higher-order functions"
+ { { $link if } ", " { $link times } ", " { $link each } }
+ "Calling a block is an indirect jump"
+ "Solution: inline higher order functions at the call site"
+ "Inline the block body at the higher order call site in the function"
+ "Record inlining in deoptimization database"
+ }
+ { $slide "Generic functions"
+ "A generic function contains multiple method bodies"
+ "Dispatches on the class of argument(s)"
+ "In Factor, generic functions are single dispatch"
+ "Almost equivalent to message passing"
+ }
+ { $slide "Tuple slot access"
+ "Slot readers and writers are generic functions"
+ "Generated automatically when you define a tuple class"
+ { "The generated methods call " { $link slot } ", " { $link set-slot } " primitives" }
+ "These primitives are not type safe; the generic dispatch performs the type checking for us"
+ "If class of dispatch value known statically, inline method"
+ "This may result in more methods inlining from additional specialization"
+ }
+ { $slide "Generic arithmetic"
+ { { $link + } ", " { $link * } ", etc perform a double dispatch on arguments" }
+ { "Fixed-precision integers (" { $link fixnum } "s) upgrade to " { $link bignum } "s automatically" }
+ "Floats and complex numbers are boxed, heap-allocated"
+ "Propagation of classes helps for floats"
+ "But not for fixnums, because of overflow checks"
+ "So we also propagate integer intervals"
+ "Interval arithmetic: etc, [a,b] + [c,d] = [a+c,b+d]"
+ }
+ { $slide "Slot value propagation"
+ "Complex numbers are even trickier"
+ "We can have a complex number with integer components, float components"
+ "Even if we inline complex arithmetic methods, still dispatching on components"
+ "Solution: propagate slot info"
+ }
+ { $slide "Constraint propagation"
+ "Contrieved example:"
+ { $code
+ "x = •"
+ "b = isa(x,array)"
+ "if(b)"
+ " a = length(x)"
+ "else"
+ " b = length(x)"
+ "c = φ(a,b)"
+ }
+ { "We should be able to inline the call to " { $snippet "length" } " in the true branch" }
+ }
+ { $slide "Constraint propagation"
+ "We build a table:"
+ { $code
+ "b true => x is array"
+ "b false => x is ~array"
+ }
+ { "In true branch, apply all " { $snippet "b true" } " constraints" }
+ { "In false branch, apply all " { $snippet "b false" } " constraints" }
+ }
+ { $slide "Going further"
+ "High-level optimizer eliminates some dispatch overhead and allocation"
+ {
+ { "Let's take a look at the " { $link float+ } " primitive" }
+ { $list
+ "No type checking anymore... but"
+ "Loads two tagged pointers from operand stack"
+ "Unboxes floats"
+ "Adds two floats"
+ "Boxes float result and perform a GC check"
+ }
+ }
+ }
+ { $slide "Low-level optimizer"
+ "Frontend: construct LL SSA IR from HL SSA IR"
+ "Alias analysis: remove redundant slot loads/stores"
+ "Value numbering: simplify arithmetic"
+ "Representation selection: eliminate boxing"
+ "Dead code elimination: clean up"
+ "Register allocation"
+ }
+ { $slide "Constructing low-level IR"
+ { "Low-level IR is a " { $emphasis "control flow graph" } " of " { $emphasis "basic blocks" } }
+ "A basic block is a list of instructions"
+ "Register-based IR; infinite, uniform register file"
+ { "Instructions:"
+ { $list
+ "Subroutine calls"
+ "Machine arithmetic"
+ "Load/store values on operand stack"
+ "Box/unbox values"
+ }
+ }
+ }
+ { $slide "Inline allocation and GC checks"
+ {
+ "Allocation of small objects can be done in a few instructions:"
+ { $list
+ "Bump allocation pointer"
+ "Write object header"
+ "Fill in payload"
+ }
+ }
+ "Multiple allocations in the same basic block only need a single GC check; saves on a conditional branch"
+ }
+ { $slide "Alias analysis"
+ "Factor constructors are just ordinary functions"
+ { "They call a primitive constructor: " { $link new } }
+ "When a new object is constructed, it has to be initialized"
+ "... but the user's constructor probably fills in all the slots again with actual values"
+ "Local alias analysis eliminates redundant slot loads and stores"
+ }
+ { $slide "Value numbering"
+ { "A form of " { $emphasis "redundancy elimination" } }
+ "Requires use of SSA form in order to work"
+ "Define an equivalence relation over SSA values"
+ "Assign a “value number” to each SSA value"
+ "If two values have the same number, they will always be equal at runtime"
+ }
+ { $slide "Types of value numbering"
+ "Many variations: algebraic simplifications, various rewrite rules can be tacked on"
+ "Local value numbering: in basic blocks"
+ "Global value numbering: entire procedure"
+ "Factor only does local value numbering"
+ }
+ { $slide "Value graph and expressions"
+ { $table
+ {
+ {
+ "Basic block:"
+ { $code
+ "x = •"
+ "y = •"
+ "a = x + 1"
+ "b = a + 1"
+ "c = x + 2"
+ "d = b - c"
+ "e = y + d"
+ }
+ }
+ {
+ "Value numbers:"
+ { $code
+ "V1: •"
+ "V2: •"
+ "V3: 1"
+ "V4: 2"
+ "V5: (V1 + V3)"
+ "V6: (V5 + V3)"
+ "V7: (V3 + V4)"
+ "V8: (V6 - V7)"
+ "V9: (V2 + V8)"
+ }
+ }
+ }
+ }
+ }
+ { $slide "Expression simplification"
+ {
+ "Constant folding: if V1 and V2 are constants "
+ { $snippet "(V1 op V2)" }
+ " can be evaluated at compile-time"
+ }
+ {
+ "Reassociation: if V2 and V3 are constants "
+ { $code "((V1 op V2) op V3) => (V1 op (V2 op V3))" }
+ }
+ {
+ "Algebraic identities: if V2 is constant 0, "
+ { $code "(V1 + V2) => V1" }
+ }
+ {
+ "Strength reduction: if V2 is a constant power of two, "
+ { $code "(V1 * V2) => (V1 << log2(V2))" }
+ }
+ "etc, etc, etc"
+ }
+ { $slide "Representation selection overview"
+ "Floats and SIMD vectors need to be boxed"
+ "Representation: tagged pointer, unboxed float, unboxed SIMD value..."
+ "When IR is built, no boxing or unboxing instructions inserted"
+ "Representation selection pass makes IR consistent"
+ }
+ { $slide "Representation selection algorithm"
+ {
+ "For each SSA value:"
+ { $list
+ "Compute possible representations"
+ "Compute cost of each representation"
+ "Pick representation with minimum cost"
+ }
+ }
+ {
+ "For each instruction:"
+ { $list
+ "If it expects a value to be in a different representation, insert box or unbox code"
+ }
+ }
+ }
+ { $slide "Register allocation"
+ "Linear scan algorithm used in Java HotSpot Client"
+ "Described in Christian Wimmer's masters thesis"
+ "Works fine on x86-64, not too great on x86-32"
+ "Good enough since basic blocks tend to be short, with lots of procedure calls"
+ "Might switch to graph coloring eventually"
+ }
+ { $slide "Compiler tools"
+ "Printing high level IR"
+ "Printing low level IR"
+ "Disassembly"
+ "Display call tree"
+ "Display control flow graph"
+ "Display dominator tree"
+ }
+}
+
+: jvm-summit-talk ( -- )
+ jvm-summit-slides "JVM Summit talk" slides-window ;
+
+MAIN: jvm-summit-talk
diff --git a/jvm-summit-talk/summary.txt b/jvm-summit-talk/summary.txt
new file mode 100644
index 0000000..769abbc
--- /dev/null
+++ b/jvm-summit-talk/summary.txt
@@ -0,0 +1 @@
+Slides from Slava's talk at JVM Language Summit 2009
diff --git a/jvm-summit-talk/tags.txt b/jvm-summit-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/jvm-summit-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/minneapolis-talk/authors.txt b/minneapolis-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/minneapolis-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/minneapolis-talk/deploy.factor b/minneapolis-talk/deploy.factor
new file mode 100644
index 0000000..ea200ce
--- /dev/null
+++ b/minneapolis-talk/deploy.factor
@@ -0,0 +1,11 @@
+USING: tools.deploy.config ;
+V{
+ { deploy-ui? t }
+ { deploy-io 3 }
+ { deploy-reflection 1 }
+ { deploy-math? t }
+ { deploy-word-props? f }
+ { deploy-c-types? f }
+ { "stop-after-last-window?" t }
+ { deploy-name "Minnesota Talk" }
+}
diff --git a/minneapolis-talk/minneapolis-talk.factor b/minneapolis-talk/minneapolis-talk.factor
new file mode 100644
index 0000000..4cae92b
--- /dev/null
+++ b/minneapolis-talk/minneapolis-talk.factor
@@ -0,0 +1,183 @@
+USING: slides help.markup math arrays hashtables namespaces
+sequences kernel parser memoize ;
+IN: talks.minneapolis-talk
+
+CONSTANT: minneapolis-slides
+{
+ { $slide "What is Factor?"
+ "Dynamically typed, stack language"
+ "Have our cake and eat it too"
+ "Research -vs- production"
+ "High level -vs- performance"
+ "Interactive -vs- stand-alone apps"
+ }
+ { $slide "The view from 10,000 feet"
+ "Influenced by Forth, Lisp, Joy, Smalltalk, even Java..."
+ "Vocabularies: modules"
+ "Words: named functions, classes, variables"
+ "Combinators: higher-order functions"
+ "Quotations: anonymous functions"
+ }
+ { $slide "Stack-based programming"
+ { "Most languages are " { $emphasis "applicative" } }
+ "Words pop inputs from the stack and push outputs on the stack"
+ "Literals are pushed on the stack"
+ { $code "{ 1 2 } { 7 } append reverse sum ." }
+ }
+ { $slide "Stack-based programming"
+ "With the stack you can omit unnecessary names"
+ "You can still name things: lexical/dynamic variables, sequences, associations, objects, ..."
+ }
+ { $slide "Functional programming"
+ "A quotation is a sequence of literals and words"
+ "Combinators replace imperative-style loops"
+ "A simple example:"
+ { $code "10 [ \"Hello world\" print ] times" }
+ { "Partial application: " { $link curry } }
+ { $code "{ 3 1 3 3 7 } [ 5 + ] map ." }
+ { $code "{ 3 1 3 3 7 } 5 [ + ] curry map ." }
+ }
+ { $slide "Word definitions"
+ { $code ": name ( inputs -- outputs )"
+ " definition ;" }
+ "Stack effect comments document stack inputs and outputs."
+ "Example from previous slide:"
+ { $code ": add-each ( seq n -- newseq )"
+ " [ + ] curry map ;" }
+ { $code "{ 3 1 3 3 7 } 5 add-each ." }
+ }
+ { $slide "Object-oriented programming"
+ { "Define a tuple class and a constructor:"
+ { $code
+ "TUPLE: person name address ;"
+ "C: <person> person"
+ } }
+ { "Create an instance:"
+ { $code
+ "\"Cosmo Kramer\""
+ "\"100 Blah blah St, New York\""
+ "<person>"
+ } }
+ }
+ { $slide "Object-oriented programming"
+ "We can inspect it and edit objects"
+ "We can reshape the class!"
+ { $code "TUPLE: person" "name address age phone-number ;" }
+ { $code "TUPLE: person" "name address phone-number age ;" }
+ }
+ { $slide "An example"
+ { $code
+ "TUPLE: square dimension ;"
+ "C: <square> square"
+ ""
+ "TUPLE: circle radius ;"
+ "C: <circle> circle"
+ ""
+ "TUPLE: rectangle width height ;"
+ "C: <rectangle> rectangle"
+ }
+ }
+ STRIP-TEASE:
+ $slide "An example"
+ { $code
+ "USE: math.constants"
+ "GENERIC: area ( shape -- meters^2 )"
+ "M: square area square-dimension sq ;"
+ "M: circle area circle-radius sq pi * ;"
+ "M: rectangle area"
+ " dup rectangle-width"
+ " swap rectangle-height * ;"
+ }
+ ;
+
+ { $slide "An example"
+ { $code "10 <square> area ." }
+ { $code "18 <circle> area ." }
+ { $code "20 40 <rectangle> area ." }
+ }
+ { $slide "Meta language"
+ "Here's fibonacci:"
+ { $code
+ ": fib ( x -- y )"
+ " dup 1 > ["
+ " 1 - dup fib swap 1 - fib +"
+ " ] when ;"
+ }
+ "It is slow:"
+ { $code
+ "35 <iota> [ fib ] map ."
+ }
+ "Let's profile it!"
+ }
+ { $slide "Memoization"
+ { { $link POSTPONE: : } " is just another word" }
+ "What if we could define a word which caches its results?"
+ { "The " { $vocab-link "memoize" } " library provides such a feature" }
+ { "Just change " { $link POSTPONE: : } " to " { $link POSTPONE: MEMO: } }
+ }
+ { $slide "Memoization"
+ { $code
+ "USE: memoize"
+ ""
+ "MEMO: fib ( x -- y )"
+ " dup 1 > ["
+ " 1 - dup fib swap 1 - fib +"
+ " ] when ;"
+ }
+ "It is faster:"
+ { $code
+ "35 <iota> [ fib ] map ."
+ }
+ }
+ { $slide "The Factor UI"
+ "Written in Factor"
+ "Renders with OpenGL"
+ "Backends for Windows, X11, Cocoa"
+ "You can call Windows, X11, Cocoa APIs directly too"
+ "OpenGL 2.1 shaders, OpenAL 3D audio..."
+ }
+ { $slide "Live coding demo"
+
+ }
+ { $slide "C library interface"
+ "Efficient"
+ "No need to write C code"
+ "Supports floats, structs, unions, ..."
+ "Function pointers, callbacks"
+ }
+ { $slide "Live coding demo"
+
+ }
+ { $slide "Deployment"
+ { "Let's play " { $vocab-link "tetris" } }
+ }
+ { $slide "Implementation"
+ "Portable: Windows, Mac OS X, Linux"
+ "Non-optimizing compiler"
+ "Optimizing compiler: x86, x86-64, PowerPC, ARM"
+ "Generational garbage collector"
+ "Non-blocking I/O"
+ }
+ { $slide "Some statistics"
+ "VM: 11,800 lines of C"
+ "Core library: 22,600 lines of Factor"
+ "Docs, tests, extra libraries: 117,000 lines of Factor"
+ }
+ { $slide "But wait, there's more!"
+ "Web server and framework, syntax highlighting, Ogg Theora video, SMTP, embedded Prolog, efficient unboxed arrays, XML, Unicode 5.0, memory mapped files, regular expressions, LDAP, database access, coroutines, Factor->JavaScript compiler, JSON, pattern matching, advanced math, parser generators, serialization, RSS/Atom, ..."
+ }
+ { $slide "Community"
+ "Factor development began in 2003"
+ "About a dozen contributors"
+ "Handful of \"core contributors\""
+ { "Web site: " { $url "http://factorcode.org" } }
+ "IRC: #concatenative on irc.freenode.net"
+ "Mailing list: factor-talk@lists.sf.net"
+ }
+ { $slide "Questions?" }
+}
+
+: minneapolis-talk ( -- )
+ minneapolis-slides "Minneapolis talk" slides-window ;
+
+MAIN: minneapolis-talk
diff --git a/minneapolis-talk/summary.txt b/minneapolis-talk/summary.txt
new file mode 100644
index 0000000..ef8d1bd
--- /dev/null
+++ b/minneapolis-talk/summary.txt
@@ -0,0 +1 @@
+Slides for a talk at Ruby.mn, Minneapolis, MN, January 2008
diff --git a/minneapolis-talk/tags.txt b/minneapolis-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/minneapolis-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/otug-talk/2bi.tiff b/otug-talk/2bi.tiff
new file mode 100644
index 0000000..16c0777
--- /dev/null
+++ b/otug-talk/2bi.tiff
Binary files differ
diff --git a/otug-talk/2bi_at.tiff b/otug-talk/2bi_at.tiff
new file mode 100644
index 0000000..e41ab98
--- /dev/null
+++ b/otug-talk/2bi_at.tiff
Binary files differ
diff --git a/otug-talk/2bi_star.tiff b/otug-talk/2bi_star.tiff
new file mode 100644
index 0000000..f457ce5
--- /dev/null
+++ b/otug-talk/2bi_star.tiff
Binary files differ
diff --git a/otug-talk/authors.txt b/otug-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/otug-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/otug-talk/bi.tiff b/otug-talk/bi.tiff
new file mode 100644
index 0000000..ad0ce97
--- /dev/null
+++ b/otug-talk/bi.tiff
Binary files differ
diff --git a/otug-talk/bi_at.tiff b/otug-talk/bi_at.tiff
new file mode 100644
index 0000000..07d25bc
--- /dev/null
+++ b/otug-talk/bi_at.tiff
Binary files differ
diff --git a/otug-talk/bi_star.tiff b/otug-talk/bi_star.tiff
new file mode 100644
index 0000000..17f3350
--- /dev/null
+++ b/otug-talk/bi_star.tiff
Binary files differ
diff --git a/otug-talk/otug-talk.factor b/otug-talk/otug-talk.factor
new file mode 100644
index 0000000..bb18d72
--- /dev/null
+++ b/otug-talk/otug-talk.factor
@@ -0,0 +1,342 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: slides help.markup math arrays hashtables namespaces
+kernel sequences parser memoize io.encodings.binary
+locals kernel.private help.vocabs assocs quotations
+tools.annotations tools.crossref help.topics math.functions
+compiler.tree.optimizer compiler.cfg.optimizer fry
+ui.gadgets.panes tetris tetris.game combinators generalizations
+multiline sequences.private ;
+IN: talks.otug-talk
+
+: $tetris ( element -- )
+ drop [ <default-tetris> <tetris-gadget> gadget. ] ($block) ;
+
+CONSTANT: 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? ] reject"
+ "[ \":\" split first ] map"
+ "."
+ }
+ }
+ { $slide "Words"
+ { "We can define new words with " { $snippet ": name ... ;" } " syntax" }
+ { $code ": remove-comments ( lines -- lines' )" " [ \"#\" head? ] reject ;" }
+ { "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? ] reject ;" }
+ { "We use " { $link POSTPONE: '[ } " instead of " { $link POSTPONE: [ } }
+ { "Create “holes” with " { $link POSTPONE: _ } }
+ "Holes filled in left to right when quotation pushed on the stack"
+ }
+ { $slide "Constructing quotations"
+ { $code ": remove-comments* ( lines string -- lines' )" " '[ _ head? ] reject ;" "" ": remove-comments ( lines -- lines' )" " \"#\" remove-comments* ;" }
+ { { $link POSTPONE: @ } " 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 <iota> [ 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 } }
+ { $image "resource:extra/talks/otug-talk/bi.tiff" }
+ }
+ { $slide "Data flow combinators - cleave family"
+ { { $link 2bi } ", " { $link 2tri } ", " { $link 2cleave } }
+ { $image "resource:extra/talks/otug-talk/2bi.tiff" }
+ }
+ { $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 } }
+ { $image "resource:extra/talks/otug-talk/bi_star.tiff" }
+ }
+ { $slide "Data flow combinators - spread family"
+ { { $link 2bi* } }
+ { $image "resource:extra/talks/otug-talk/2bi_star.tiff" }
+ }
+ { $slide "Data flow combinators - apply family"
+ { { $link bi@ } ", " { $link tri@ } ", " { $link napply } }
+ { $image "resource:extra/talks/otug-talk/bi_at.tiff" }
+ }
+ { $slide "Data flow combinators - apply family"
+ { { $link 2bi@ } }
+ { $image "resource:extra/talks/otug-talk/2bi_at.tiff" }
+ }
+ { $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 programmatically"
+ ! "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 ]
+ <border-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 "talks.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 "OTUG talk" slides-window ;
+
+MAIN: otug-talk
diff --git a/otug-talk/summary.txt b/otug-talk/summary.txt
new file mode 100644
index 0000000..571a4c2
--- /dev/null
+++ b/otug-talk/summary.txt
@@ -0,0 +1 @@
+Slides from a talk at OTUG by Slava Pestov, December 2008
diff --git a/otug-talk/tags.txt b/otug-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/otug-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/tc-lisp-talk/authors.txt b/tc-lisp-talk/authors.txt
new file mode 100644
index 0000000..7c1b2f2
--- /dev/null
+++ b/tc-lisp-talk/authors.txt
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/tc-lisp-talk/tags.txt b/tc-lisp-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/tc-lisp-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/tc-lisp-talk/tc-lisp-talk.factor b/tc-lisp-talk/tc-lisp-talk.factor
new file mode 100644
index 0000000..8d60e10
--- /dev/null
+++ b/tc-lisp-talk/tc-lisp-talk.factor
@@ -0,0 +1,535 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: assocs combinators constructors eval help.markup kernel
+multiline namespaces parser sequences sequences.private slides
+vocabs.refresh words fry ;
+IN: talks.tc-lisp-talk
+
+CONSTANT: tc-lisp-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 "First, some examples"
+ { $code "3 weeks ago noon monday ." }
+ { $code "USE: roman 2009 >roman ." }
+ { $code ": average ( seq -- x )
+ [ sum ] [ length ] bi / ;" }
+ { $code "1 miles [ km ] undo >float ." }
+ { $code "[ readln eval>string print t ] loop" }
+ }
+ { $slide "XML Literals"
+ { $code
+ "USING: splitting xml.writer xml.syntax ;
+{ \"one\" \"two\" \"three\" }
+[ [XML <item><-></item> XML] ] map
+<XML <doc><-></doc> XML> pprint-xml"
+ }
+ }
+ { $slide "Differences between Factor and Lisp"
+ "Single-implementation language"
+ "Less nesting, shorter word length"
+ { "Dynamic reloading of code from files with " { $link refresh-all } }
+ "More generic protocols -- sequences, assocs, streams"
+ "More cross-platform"
+ "No standard for the language"
+ "Evaluates left to right"
+ }
+ { $slide "Terminology"
+ { "Words - functions" }
+ { "Vocabularies - collections of code in the same namespace" }
+ { "Quotations - blocks of code" { $code "[ dup reverse append ]" } }
+ { "Combinators - higher order functions" }
+ { "Static stack effect - known stack effect at compile-time" }
+ }
+ { $slide "Defining a word"
+ "Defined at parse time"
+ "Parts: name, stack effect, definition"
+ "Composed of tokens separated by whitespace"
+ { $code ": palindrome? ( string -- ? ) dup reverse = ;" }
+ }
+ { $slide "Non-static stack effect"
+ "Not a good practice, nor useful"
+ "Not compiled by the optimizing compiler"
+ { $code "100 <iota> [ ] each" }
+ }
+ { $slide "Module system"
+ "Code divided up into vocabulary roots"
+ "core/ -- just enough code to bootstrap Factor"
+ "basis/ -- optimizing compiler, the UI, tools, libraries"
+ "extra/ -- demos, unpolished code, experiments"
+ "work/ -- your works in progress"
+ }
+ { $slide "Module system (part 2)"
+ "Each vocabulary corresponds to a directory on disk, with documentation and test files"
+ { "Code for the " { $snippet "math" } " vocabulary: " { $snippet "~/factor/core/math/math.factor" } }
+ { "Documentation for the " { $snippet "math" } " vocabulary: " { $snippet "~/factor/core/math/math-docs.factor" } }
+ { "Unit tests for the " { $snippet "math" } " vocabulary: " { $snippet " ~/factor/core/math/math-tests.factor" } }
+ }
+ { $slide "Using a library"
+ "Each file starts with a USING: list"
+ "To use a library, simply include it in this list"
+ "Refreshing code loads dependencies correctly"
+ }
+ { $slide "Object system"
+ "Based on CLOS"
+ { "We define generic words that operate on the top of the stack with " { $link POSTPONE: GENERIC: } " or on an implicit parameter with " { $link POSTPONE: HOOK: } }
+ }
+ { $slide "Object system example: shape protocol"
+ "In ~/factor/work/shapes/shapes.factor"
+ { $code "IN: shapes
+
+GENERIC: area ( shape -- x )
+GENERIC: perimeter ( shape -- x )"
+ }
+ }
+ { $slide "Implementing the shape protocol: circles"
+ "In ~/factor/work/shapes/circle/circle.factor"
+ { $code "USING: shapes constructors math
+math.constants ;
+IN: shapes.circle
+
+TUPLE: circle radius ;
+CONSTRUCTOR: <circle> circle ( radius -- obj ) ;
+M: circle area radius>> sq pi * ;
+M: circle perimeter radius>> pi * 2 * ;"
+ }
+ }
+ { $slide "Dynamic variables"
+ "Implemented as a stack of hashtables"
+ { "Useful words are " { $link get } ", " { $link set } }
+ "Input, output, error streams are stored in dynamic variables"
+ { $code "\"Today is the first day of the rest of your life.\"
+[
+ readln print
+] with-string-reader"
+ }
+ }
+ { $slide "The global namespace"
+ "The global namespace is just the namespace at the bottom of the namespace stack"
+ { "Useful words are " { $link get-global } ", " { $link set-global } }
+ "Factor idiom for changing a particular namespace"
+ { $code "SYMBOL: king
+global [ \"Henry VIII\" king set ] with-variables"
+ }
+ { $code "with-scope" }
+ { $code "namestack" }
+ }
+ { $slide "Hooks"
+ "Dispatch on a dynamic variable"
+ { $code "HOOK: computer-name os ( -- string )
+M: macosx computer-name uname first ;
+macosx \ os set-global
+computer-name"
+ }
+ }
+ { $slide "Interpolate"
+ "Replaces variables in a string"
+ { $code
+"\"Dawg\" \"name\" set
+\"rims\" \"noun\" set
+\"bling\" \"verb1\" set
+\"roll\" \"verb2\" set
+[
+ \"Sup ${name}, we heard you liked ${noun}, so we put ${noun} on your car so you can ${verb1} while you ${verb2}.\"
+ interpolate
+] with-string-writer print "
+ }
+ }
+ { $slide "Sequence protocol"
+ "All sequences obey a protocol of generics"
+ { "Is an object a " { $link sequence? } }
+ { "Getting the " { $link length } }
+ { "Accessing the " { $link nth } " element" }
+ { "Setting an element - " { $link set-nth } }
+ }
+ { $slide "Examples of sequences in Factor"
+ "Arrays are mutable"
+ "Vectors are mutable and growable"
+ { "Arrays " { $code "{ \"abc\" \"def\" 50 }" } }
+ { "Vectors " { $code "V{ \"abc\" \"def\" 50 }" } }
+ { "Byte-arrays " { $code "B{ 1 2 3 }" } }
+ { "Byte-vectors " { $code "BV{ 11 22 33 }" } }
+ }
+ { $slide "Specialized arrays and vectors"
+ { "Specialized int arrays " { $code "int-array{ -20 -30 40 }" } }
+ { "Specialized uint arrays " { $code "uint-array{ 20 30 40 }" } }
+ { "Specialized float vectors " { $code "float-vector{ 20 30 40 }" } }
+ "35 others C-type arrays"
+ }
+ { $slide "Specialized arrays code"
+ "One line per array/vector"
+ { "In ~/factor/basis/specialized-arrays/float/float.factor"
+ { $code "<< \"float\" define-array >>" }
+ }
+ { "In ~/factor/basis/specialized-vectors/float/float.factor"
+ { $code "<< \"float\" define-vector >>" }
+ }
+ }
+
+ { $slide "Specialized arrays are implemented using functors"
+ "Like C++ templates"
+ "Eliminate boilerplate in ways other abstractions don't"
+ "Contains a definition section and a functor body"
+ "Uses the interpolate vocabulary"
+ }
+ { $slide "Functor for sorting"
+ { $code
+ "<FUNCTOR: define-sorting ( NAME QUOT -- )
+
+NAME<=> DEFINES ${NAME}<=>
+NAME>=< DEFINES ${NAME}>=<
+
+WHERE
+
+: NAME<=> ( obj1 obj2 -- <=> ) QUOT compare ;
+: NAME>=< ( obj1 obj2 -- >=< )
+ NAME<=> invert-comparison ;
+
+;FUNCTOR>"
+ }
+ }
+ { $slide "Example of sorting functor"
+ { $code "USING: sorting.functor ;
+<< \"length\" [ length ] define-sorting >>"
+ }
+ { $code
+ "{ { 1 2 3 } { 1 2 } { 1 } }
+[ length<=> ] sort"
+ }
+ }
+ { $slide "Combinators"
+ "Used to implement higher order functions (dataflow and control flow)"
+ "Compiler optimizes away quotations completely"
+ "Optimized code is just tight loops in registers"
+ "Most loops can be expressed with combinators or tail-recursion"
+ }
+ { $slide "Combinators that act on one value"
+ { $link bi }
+ { $code "10 [ 1 - ] [ 1 + ] bi" }
+ { $link tri }
+ { $code "10 [ 1 - ] [ 1 + ] [ 2 * ] tri" }
+ }
+ { $slide "Combinators that act on two values"
+ { $link 2bi }
+ { $code "10 1 [ - ] [ + ] 2bi" }
+ { $link bi* }
+ { $code "10 20 [ 1 - ] [ 1 + ] bi*" }
+ { $link bi@ }
+ { $code "5 9 [ sq ] bi@" }
+ }
+ { $slide "Sequence combinators"
+
+ { $link each }
+ { $code "{ 1 2 3 4 5 } [ sq . ] each" }
+ { $link map }
+ { $code "{ 1 2 3 4 5 } [ sq ] map" }
+ { $link filter }
+ { $code "{ 1 2 3 4 5 } [ even? ] filter" }
+ }
+ { $slide "Multiple sequence combinators"
+
+ { $link 2each }
+ { $code "{ 1 2 3 } { 10 20 30 } [ + . ] 2each" }
+ { $link 2map }
+ { $code "{ 1 2 3 } { 10 20 30 } [ + ] 2map" }
+ }
+ { $slide "Control flow: if"
+ { $link if }
+ { $code "10 random dup even? [ 2 / ] [ 1 - ] if" }
+ { $link when }
+ { $code "10 random dup even? [ 2 / ] when" }
+ { $link unless }
+ { $code "10 random dup even? [ 1 - ] unless" }
+ }
+ { $slide "Control flow: case"
+ { $link case }
+ { $code "ERROR: not-possible obj ;
+10 random 5 <=> {
+ { +lt+ [ \"Less\" ] }
+ { +gt+ [ \"More\" ] }
+ { +eq+ [ \"Equal\" ] }
+ [ not-possible ]
+} case"
+ }
+ }
+ { $slide "Fry"
+ "Used to construct quotations"
+ { "'Holes', represented by " { $snippet "_" } " are filled left to right" }
+ { $code "10 4 '[ _ + ] call" }
+ { $code "3 4 '[ _ sq _ + ] call" }
+ }
+ { $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 lengths in an array"
+ { $code ": v-n ( v n -- w ) '[ _ - ] map ;
+
+: area ( seq -- x )
+ [ 0 suffix ] [ sum 2 / ] bi
+ v-n product sqrt ;" }
+ }
+ { $slide "Implementing an abstraction"
+ { "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 "Macros in Factor"
+ "Expand at compile-time"
+ "Return a quotation to be compiled"
+ "Can express non-static stack effects"
+ "Not as widely used as combinators, 60 macros so far"
+ { $code "{ 1 2 3 4 5 } 5 firstn" }
+ }
+ { $slide "A macro solution"
+ "Returns a quotation to the compiler"
+ "Constructed using map, fry, and concat"
+ { $code "MACRO: plox ( seq -- quot )
+ [
+ '[ dup _ when ]
+ ] map [ ] concat-as ;"
+ }
+ }
+ { $slide "Macro example"
+ "Return the caaar of a sequence"
+ { "Return " { $snippet "f" } " on failure" }
+ { $code ": caaar ( seq/f -- x/f )
+ {
+ [ first ]
+ [ first ]
+ [ first ]
+ } plox ;"
+ }
+ { $code "{ { f } } caaar" }
+ { $code "{ { { 1 2 3 } } } caaar" }
+ }
+ { $slide "Smart combinators"
+ "Use stack checker to infer inputs and outputs"
+ "Even fewer uses than macros"
+ { $code "{ 1 10 20 34 } sum" }
+ { $code "[ 1 10 20 34 ] sum-outputs" }
+ { $code "[ 2 2 [ even? ] both? ] [ + ] [ - ] smart-if" }
+ }
+ { $slide "Fibonacci"
+ "Not tail recursive"
+ "Call tree is huge"
+ { $code ": fib ( n -- x )
+ dup 1 <= [
+ [ 1 - fib ] [ 2 - fib ] bi +
+ ] unless ;"
+ }
+ { $code "36 <iota> [ fib ] map ." }
+ }
+ { $slide "Memoized Fibonacci"
+ "Change one word and it's efficient"
+ { $code "MEMO: fib ( n -- x )
+ dup 1 <= [
+ [ 1 - fib ] [ 2 - fib ] bi +
+ ] unless ;"
+ }
+ { $code "36 <iota> [ fib ] map ." }
+ }
+ { $slide "Destructors"
+ "Deterministic resource disposal"
+ "Any step can fail and we don't want to leak resources"
+ "We want to conditionally clean up sometimes -- if everything succeeds, we might wish to retain the buffer"
+ }
+
+ { $slide "Example in C"
+ { $code
+"void do_stuff()
+{
+ void *obj1, *obj2;
+ if(!(*obj1 = malloc(256))) goto end;
+ if(!(*obj2 = malloc(256))) goto cleanup1;
+ ... work goes here...
+cleanup2: free(*obj2);
+cleanup1: free(*obj1);
+end: return;
+}"
+ }
+ }
+ { $slide "Example: allocating and disposing two buffers"
+ { $code ": do-stuff ( -- )
+ [
+ 256 malloc &free
+ 256 malloc &free
+ ... work goes here ...
+ ] with-destructors ;"
+ }
+ }
+ { $slide "Example: allocating two buffers for later"
+ { $code ": do-stuff ( -- )
+ [
+ 256 malloc |free
+ 256 malloc |free
+ ... work goes here ...
+ ] with-destructors ;"
+ }
+ }
+ { $slide "Example: disposing of an output port"
+ { $code "M: output-port dispose*
+ [
+ {
+ [ handle>> &dispose drop ]
+ [ buffer>> &dispose drop ]
+ [ port-flush ]
+ [ handle>> shutdown ]
+ } cleave
+ ] with-destructors ;"
+ }
+ }
+ { $slide "Rapid application development"
+ "We lost the dice to Settlers of Catan: Cities and Knights"
+ "Two regular dice, one special die"
+ { $vocab-link "dice" }
+ }
+ { $slide "The essence of Factor"
+ "Nicely named words abstract away the stack, leaving readable code"
+ { $code ": surround ( seq left right -- seq' )
+ swapd 3append ;"
+ }
+ { $code ": glue ( left right middle -- seq' )
+ swap 3append ;"
+ }
+ { $code HEREDOC: xyz
+"a" "b" "c" 3append
+"a" """""""" surround
+"a" "b" ", " glue
+xyz
+ }
+ }
+ { $slide "C FFI demo"
+ "Easy to call C functions from Factor"
+ "Handles C structures, C types, callbacks"
+ "Used extensively in the Windows and Unix backends"
+ { $code
+ "FUNCTION: double pow ( double x, double y ) ;
+2 5.0 pow ."
+ }
+ }
+ { $slide "Windows win32 example"
+ { $code
+"M: windows gmt-offset
+ ( -- hours minutes seconds )
+ \"TIME_ZONE_INFORMATION\" <c-object>
+ dup GetTimeZoneInformation {
+ { TIME_ZONE_ID_INVALID [
+ win32-error
+ ] }
+ { TIME_ZONE_ID_STANDARD [
+ TIME_ZONE_INFORMATION-Bias
+ ] }
+ } case neg 60 /mod 0 ;"
+ }
+ }
+ { $slide "Struct and function"
+ { $code "C-STRUCT: TIME_ZONE_INFORMATION
+ { \"LONG\" \"Bias\" }
+ { { \"WCHAR\" 32 } \"StandardName\" }
+ { \"SYSTEMTIME\" \"StandardDate\" }
+ { \"LONG\" \"StandardBias\" }
+ { { \"WCHAR\" 32 } \"DaylightName\" }
+ { \"SYSTEMTIME\" \"DaylightDate\" }
+ { \"LONG\" \"DaylightBias\" } ;"
+ }
+ { $code "FUNCTION: DWORD GetTimeZoneInformation (
+ LPTIME_ZONE_INFORMATION
+ lpTimeZoneInformation
+) ;"
+ }
+
+ }
+ { $slide "Cocoa FFI"
+ { $code "IMPORT: NSAlert [
+ NSAlert -> new
+ [ -> retain ] [
+ \"Raptor\" <CFString> &CFRelease
+ -> setMessageText:
+ ] [
+ \"Look out!\" <CFString> &CFRelease
+ -> setInformativeText:
+ ] tri -> runModal drop
+] with-destructors"
+ }
+ }
+ { $slide "Deployment demo"
+ "Vocabularies can be deployed"
+ "Standalone .app on Mac"
+ "An executable and dll on Windows"
+ { $vocab-link "webkit-demo" }
+ }
+ { $slide "Interesting programs"
+ { $vocab-link "terrain" }
+ { $vocab-link "gpu.demos.raytrace" }
+ { $vocab-link "gpu.demos.bunny" }
+ }
+ { $slide "Factor's source tree"
+ "Lines of code in core/: 9,500"
+ "Lines of code in basis/: 120,000"
+ "Lines of code in extra/: 51,000"
+ "Lines of tests: 44,000"
+ "Lines of documentation: 44,500"
+ }
+ { $slide "VM trivia"
+ "Lines of C++ code: 12860"
+ "Generational garbage collection"
+ "Non-optimizing compiler"
+ "Loads an image file and runs it"
+ }
+ { $slide "Why should I use Factor?"
+ "More abstractions over time"
+ "We fix reported bugs quickly"
+ "Stackable, fluent language"
+ "Supports extreme programming"
+ "Beer-friendly programming"
+ }
+ { $slide "Questions?"
+ }
+}
+
+: tc-lisp-talk ( -- )
+ tc-lisp-slides "TC Lisp talk" slides-window ;
+
+MAIN: tc-lisp-talk
diff --git a/vpri-talk/authors.txt b/vpri-talk/authors.txt
new file mode 100644
index 0000000..1901f27
--- /dev/null
+++ b/vpri-talk/authors.txt
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/vpri-talk/summary.txt b/vpri-talk/summary.txt
new file mode 100644
index 0000000..1ebcc4b
--- /dev/null
+++ b/vpri-talk/summary.txt
@@ -0,0 +1 @@
+Slides from a talk at VPRI by Slava Pestov, October 2008
diff --git a/vpri-talk/tags.txt b/vpri-talk/tags.txt
new file mode 100644
index 0000000..8ee64cd
--- /dev/null
+++ b/vpri-talk/tags.txt
@@ -0,0 +1 @@
+talks
diff --git a/vpri-talk/vpri-talk.factor b/vpri-talk/vpri-talk.factor
new file mode 100644
index 0000000..9903d22
--- /dev/null
+++ b/vpri-talk/vpri-talk.factor
@@ -0,0 +1,492 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: slides help.markup math arrays hashtables namespaces
+kernel sequences parser memoize io.encodings.binary
+locals kernel.private help.vocabs assocs quotations urls
+peg.ebnf tools.annotations tools.crossref help.topics
+math.functions compiler.tree.optimizer compiler.cfg.optimizer
+fry ;
+IN: talks.vpri-talk
+
+CONSTANT: vpri-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 "Programming is hard"
+ "Let's play tetris instead"
+ { $vocab-link "tetris" }
+ "Tetris is hard too... let's cheat"
+ "Factor workflow: change code, F2, test, repeat"
+ }
+ { $slide "Basics"
+ "Stack based, dynamically typed"
+ { $code "{ 1 1 3 4 4 8 9 9 } dup duplicates diff ." }
+ "Words: named code snippets"
+ { $code ": remove-duplicates ( seq -- seq' )" " dup duplicates diff ;" }
+ { $code "{ 1 1 3 4 4 8 9 9 } remove-duplicates ." }
+ "Vocabularies: named sets of words"
+ { $link "vocab-index" }
+ }
+ { $slide "Quotations"
+ "Quotation: unnamed block of code"
+ "Combinators: words taking quotations"
+ { $code "{ 1 1 3 4 4 8 9 9 }" "[ { 1 3 8 } member? ] filter ." }
+ { $code "{ -1 1 -2 0 3 } [ 0 max ] map" }
+ "Partial application:"
+ { $code ": clamp ( seq n -- seq' ) '[ _ max ] map" "{ -1 1 -2 0 3 } 0 clamp ;" }
+ }
+ { $slide "Object system"
+ "CLOS with single dispatch"
+ "A tuple is a user-defined class which holds named values."
+ { $code
+ "TUPLE: rectangle width height ;"
+ "TUPLE: circle radius ;"
+ }
+ }
+ { $slide "Object system"
+ "Constructing instances:"
+ { $code "rectangle new" }
+ { $code "rectangle boa" }
+ "Let's encapsulate:"
+ { $code
+ ": <rectangle> ( w h -- r ) rectangle boa ;"
+ ": <circle> ( r -- c ) circle boa ;"
+ }
+ }
+ { $slide "Object system"
+ "Generic words and methods"
+ { $code "GENERIC: area ( shape -- n )" }
+ "Two methods:"
+ { $code
+ "USE: math.constants"
+ ""
+ "M: rectangle area"
+ " [ width>> ] [ height>> ] bi * ;"
+ ""
+ "M: circle area radius>> sq pi * ;"
+ }
+ }
+ { $slide "Object system"
+ "We can compute areas now."
+ { $code "100 20 <rectangle> area ." }
+ { $code "3 <circle> area ." }
+ }
+ { $slide "Object system"
+ "New operation, existing types:"
+ { $code
+ "GENERIC: perimeter ( shape -- n )"
+ ""
+ "M: rectangle perimeter"
+ " [ width>> ] [ height>> ] bi + 2 * ;"
+ ""
+ "M: circle perimeter"
+ " radius>> 2 * pi * ;"
+ }
+ }
+ { $slide "Object system"
+ "We can compute perimeters now."
+ { $code "100 20 <rectangle> perimeter ." }
+ { $code "3 <circle> perimeter ." }
+ }
+ { $slide "Object system"
+ "New type, extending existing operations:"
+ { $code
+ "TUPLE: triangle base height ;"
+ ""
+ ": <triangle> ( b h -- t ) triangle boa ;"
+ ""
+ "M: triangle area"
+ " [ base>> ] [ height>> ] bi * 2 / ;"
+ }
+ }
+ { $slide "Object system"
+ "New type, extending existing operations:"
+ { $code
+ ": hypotenuse ( x y -- z ) [ sq ] bi@ + sqrt ;"
+ ""
+ "M: triangle perimeter"
+ " [ base>> ] [ height>> ] bi"
+ " [ + ] [ hypotenuse ] 2bi + ;"
+ }
+ }
+ { $slide "Object system"
+ "Object system handles dynamic redefinition very well"
+ { $code "TUPLE: person name age occupation ;" }
+ "Make an instance..."
+ }
+ { $slide "Object system"
+ "Let's add a new slot:"
+ { $code "TUPLE: person name age address occupation ;" }
+ "Fill it in with inspector..."
+ "Change the order:"
+ { $code "TUPLE: person name occupation address ;" }
+ }
+ { $slide "Object system"
+ "How does it work?"
+ "Objects are not hashtables; slot access is very fast"
+ "Redefinition walks the heap; expensive but rare"
+ }
+ { $slide "Object system"
+ "Supports \"duck typing\""
+ "Two tuples can have a slot with the same name"
+ "Code that uses accessors will work on both"
+ "Accessors are auto-generated generic words"
+ }
+ { $slide "Object system"
+ "More: inheritance, type declarations, read-only slots, predicate, intersection, singleton classes, reflection"
+ "Object system is entirely implemented in Factor"
+ { { $vocab-link "generic" } ", " { $vocab-link "classes" } ", " { $vocab-link "slots" } }
+ }
+ { $slide "The parser"
+ "All data types have a literal syntax"
+ "Literal hashtables and arrays are very useful in data-driven code"
+ "\"Code is data\" because quotations are objects (enables Lisp-style macros)"
+ { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" }
+ "Libraries can define new parsing words"
+ }
+ { $slide "Example: float arrays"
+ { $vocab-link "specialized-arrays.float" }
+ "Avoids boxing and unboxing overhead"
+ "Implemented with library code"
+ { $code "float-array{ 3.14 7.6 10.3 }" }
+ }
+ { $slide "Example: memoization"
+ { "Memoization with " { $link POSTPONE: MEMO: } }
+ { $code
+ ": fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Very slow! Let's profile it..."
+ }
+ { $slide "Example: memoization"
+ { "Let's use " { $link POSTPONE: : } " instead of " { $link POSTPONE: MEMO: } }
+ { $code
+ "MEMO: fib ( m -- n )"
+ " dup 1 > ["
+ " [ 1 - fib ] [ 2 - fib ] bi +"
+ " ] when ;"
+ }
+ "Much faster"
+ }
+ { $slide "Meta-circularity"
+ { { $link POSTPONE: MEMO: } " is just a library word" }
+ { "But so is " { $link POSTPONE: : } }
+ "Factor's parser is written in Factor"
+ { "All syntax is just parsing words: " { $link POSTPONE: [ } ", " { $link POSTPONE: " } }
+ }
+ { $slide "Extensible syntax, DSLs"
+ "Most parsing words fall in one of two categories"
+ "First category: literal syntax for new data types"
+ "Second category: defining new types of words"
+ "Some parsing words are more complicated"
+ }
+ { $slide "Example: printf"
+ { { $link POSTPONE: EBNF: } ": a complex parsing word" }
+ "Implements a custom syntax for expressing parsers: like OMeta!"
+ { "Example: " { $vocab-link "printf-example" } }
+ { $code "\"cheese\" \"vegan\" \"%s is not %s\\n\" printf" }
+ { $code "\"Factor\" 5 \"%s is %d years old\\n\" printf" }
+ }
+ { $slide "Example: simple web browser"
+ { $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 "Locals and lexical scope"
+ "Sometimes, there's no good stack solution to a problem"
+ "Or, you're porting existing code in a quick-and-dirty way"
+ "Our solution: implement named locals as a DSL in Factor"
+ "Influenced by Scheme and Lisp"
+ }
+ { $slide "Locals and lexical scope"
+ { "Define lambda words with " { $link POSTPONE: :: } }
+ { "Establish bindings with " { $link POSTPONE: [let } " and " { $snippet "[let*" } }
+ "Mutable bindings with correct semantics"
+ { "Named inputs for quotations with " { $link POSTPONE: [| } }
+ "Full closures"
+ }
+ { $slide "Locals and lexical scope"
+ "Combinator with 5 parameters!"
+ { $code
+ ":: branch ( a b neg zero pos -- )"
+ " a b = zero [ a b < neg pos if ] if ; inline"
+ }
+ "Unwieldy with the stack"
+ }
+ { $slide "Locals and lexical scope"
+ { $code
+ "ERROR: underage-exception ;"
+ ""
+ ": check-drinking-age ( age -- )"
+ " 21"
+ " [ underage-exception ]"
+ " [ \"Grats, you're now legal\" print ]"
+ " [ \"Go get hammered\" print ]"
+ " branch ;"
+ }
+ }
+ { $slide "Locals and lexical scope"
+ "Locals are entirely implemented in Factor"
+ "Example of compile-time meta-programming"
+ "No performance penalty -vs- using the stack"
+ "In the base image, only 59 words out of 13,000 use locals"
+ }
+ { $slide "More about partial application"
+ { { $link POSTPONE: '[ } " is \"fry syntax\"" }
+ { $code "'[ _ + ] == [ + ] curry" }
+ { $code "'[ @ t ] == [ t ] compose" }
+ { $code "'[ _ nth @ ] == [ [ nth ] curry ] dip compose" }
+ { $code "'[ [ _ ] dip nth ] == [ [ ] curry dip nth ] curry" }
+ { "Fry and locals desugar to " { $link curry } ", " { $link compose } }
+ }
+ { $slide "More about partial application"
+ { { $link call } " is fundamental" }
+ { { $link quotation } ", " { $link curry } " and " { $link compose } " are classes" }
+ { $code
+ "GENERIC: call ( quot -- )"
+ "M: curried call uncurry call ;"
+ "M: composed call uncompose slip call ;"
+ "M: quotation call (call) ;"
+ }
+ { "So " { $link curry } ", " { $link compose } " are library features" }
+ }
+ { $slide "Why stack-based?"
+ "Because nobody else is doing it"
+ "Interesting properties: concatenation is composition, chaining functions together, \"fluent\" interfaces, new combinators"
+ { $vocab-link "smtp-example" }
+ { $code
+ "{ \"chicken\" \"beef\" \"pork\" \"turkey\" }"
+ "[ 5 short head ] map ."
+ }
+ "To rattle people's cages"
+ }
+ { $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 "talks.vpri-talk" }
+ }
+ { $slide "Some line counts"
+ "VM: 12,000 lines of C"
+ "core: 9,000 lines of Factor"
+ "basis: 80,000 lines of Factor"
+ }
+ { $slide "More line counts"
+ "Object system (core): 2184 lines"
+ "Dynamic variables (core): 40 lines"
+ "Deterministic scoped destructors (core): 56 lines"
+ "Optimizing compiler (basis): 12938 lines"
+ "Lexical variables and closures (basis): 477 lines"
+ "Fry (basis): 51 lines"
+ "Help system (basis): 1831 lines"
+ }
+ { $slide "Implementation"
+ "VM: garbage collection, bignums, ..."
+ "Bootstrap image: parser, hashtables, object system, ..."
+ "Non-optimizing compiler"
+ "Stage 2 bootstrap: optimizing compiler, UI, ..."
+ "Full image contains machine code"
+ }
+ { $slide "Compiler"
+ { "Let's look at " { $vocab-link "benchmark.mandel" } }
+ "A naive implementation would be very slow"
+ "Combinators, currying, partial application"
+ "Boxed complex numbers"
+ "Boxed floats"
+ { "Redundancy in " { $link absq } " and " { $link sq } }
+ }
+ { $slide "Compiler: front-end"
+ "Builds high-level tree SSA IR"
+ "Stack code with uniquely-named values"
+ "Inlines combinators and calls to quotations"
+ { $code "USING: compiler.tree.builder compiler.tree.debugger ;" "[ c pixel ] build-tree nodes>quot ." }
+ }
+ { $slide "Compiler: high-level optimizer"
+ "12 optimization passes"
+ { $link optimize-tree }
+ "Some passes collect information, others use the results of past analysis to rewrite the code"
+ }
+ { $slide "Compiler: propagation pass"
+ "Propagation pass computes types with type function"
+ { "Example: output type of " { $link + } " depends on the types of inputs" }
+ "Type: can be a class, a numeric interval, array with a certain length, tuple with certain type slots, literal value, ..."
+ "Mandelbrot: we infer that we're working on complex floats"
+ }
+ { $slide "Compiler: propagation pass"
+ "Propagation also supports \"constraints\""
+ { $code "[ dup array? [ first ] when ] optimized." }
+ { $code "[ >fixnum dup 0 < [ 1 + ] when ] optimized." }
+ { $code
+ "["
+ " >fixnum"
+ " dup [ -10 > ] [ 10 < ] bi and"
+ " [ 1 + ] when"
+ "] optimized."
+ }
+ }
+ { $slide "Compiler: propagation pass"
+ "Eliminates method dispatch, inlines method bodies"
+ "Mandelbrot: we infer that integer indices are fixnums"
+ "Mandelbrot: we eliminate generic arithmetic"
+ }
+ { $slide "Compiler: escape analysis"
+ "We identify allocations for tuples which are never returned or passed to other words (except slot access)"
+ { "Partial application with " { $link curry } " and " { $link compose } }
+ "Complex numbers"
+ }
+ { $slide "Compiler: escape analysis"
+ { "Virtual sequences: " { $link <slice> } ", " { $link <reversed> } }
+ { $code "[ <reversed> [ . ] each ] optimized." }
+ { "Mandelbrot: we unbox " { $link curry } ", complex number allocations" }
+ }
+ { $slide "Compiler: dead code elimination"
+ "Cleans up the mess from previous optimizations"
+ "After inlining and dispatch elimination, dead code comes up because of unused generality"
+ { "No-ops like " { $snippet "0 +" } ", " { $snippet "1 *" } }
+ "Literals which are never used"
+ "Side-effect-free words whose outputs are dropped"
+ { $code "[ c pixel ] optimized." }
+ }
+ { $slide "Compiler: low level IR"
+ "Register-based SSA"
+ "Stack operations expand into low-level instructions"
+ { $code "[ 5 ] regs." }
+ { $code "[ swap ] regs." }
+ { $code "[ append reverse ] regs." }
+ }
+ { $slide "Compiler: low-level optimizer"
+ "5 optimization passes"
+ { $link optimize-cfg }
+ "Gets rid of redundancy which is hidden in high-level stack code"
+ }
+ { $slide "Compiler: optimize memory"
+ "First pass optimizes stack and memory operations"
+ { "Example: " { $link 2array } }
+ { { $link <array> } " fills array with initial value" }
+ "What if we immediately store new values into the array?"
+ { $code "\\ 2array regs." }
+ "Mandelbrot: we optimize stack operations"
+ }
+ { $slide "Compiler: value numbering"
+ "Identifies expressions which are computed more than once in a basic block"
+ "Simplifies expressions with various identities"
+ "Mandelbrot: redundant float boxing and unboxing, redundant arithmetic"
+ }
+ { $slide "Compiler: dead code elimination"
+ "Dead code elimination for low-level IR"
+ "Again, cleans up results of prior optimizations"
+ }
+ { $slide "Compiler: register allocation"
+ "IR assumes an infinite number of registers which are only assigned once"
+ "Real CPUs have a finite set of registers which can be assigned any number of times"
+ "\"Linear scan register allocation with second-chance binpacking\""
+ }
+ { $slide "Compiler: register allocation"
+ "3 steps:"
+ "Compute live intervals"
+ "Allocate registers"
+ "Assign registers and insert spills"
+ }
+ { $slide "Compiler: register allocation"
+ "Step 1: compute live intervals"
+ "We number all instructions consecutively"
+ "A live interval associates a virtual register with a list of usages"
+ }
+ { $slide "Compiler: register allocation"
+ "Step 2: allocate registers"
+ "We scan through sorted live intervals"
+ "If a physical register is available, assign"
+ "Otherwise, find live interval with furthest away use, split it, look at both parts again"
+ }
+ { $slide "Compiler: register allocation"
+ "Step 3: assign registers and insert spills"
+ "Simple IR rewrite step"
+ "After register allocation, one vreg may have several live intervals, and different physical registers at different points in time"
+ "Hence, \"second chance\""
+ { "Mandelbrot: " { $code "[ c pixel ] regs." } }
+ }
+ { $slide "Compiler: code generation"
+ "Iterate over list of instructions"
+ "Extract tuple slots and call hooks"
+ { $vocab-link "cpu.architecture" }
+ "Finally, we hand the code to the VM"
+ { $code "\\ 2array disassemble" }
+ }
+ { $slide "Garbage collection"
+ "All roots are identified precisely"
+ "Generational copying for data"
+ "Mark sweep for native code"
+ }
+ { $slide "History"
+ "Started in 2003, implemented in Java"
+ "Scripting language for a 2D shooter game"
+ "Interactive development is addictive"
+ "I wanted to write entire applications in Factor"
+ "Added JVM bytecode compiler pretty early on"
+ }
+ { $slide "History"
+ "Wrote native C implementation, mid-2004"
+ "Added native compiler at some point"
+ "Added an FFI, SDL bindings, then UI"
+ "Switched UI to OpenGL and native APIs"
+ "Generational GC"
+ "Got rid of interpreter"
+ }
+ { $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"
+ "Saves us from the burden of making releases by hand"
+ "Maintains stability"
+ }
+ { $slide "Community"
+ "#concatenative irc.freenode.net: 50-60 members"
+ "factor-talk@lists.sf.net: 180 subscribers"
+ "About 30 people have code in the Factor repository"
+ "Easy to get started: binaries, lots of docs, friendly community..."
+ }
+ { $slide "Future direction: Factor 1.0"
+ "Continue doing what we're doing:"
+ "Polish off some language features"
+ "Stability"
+ "Performance"
+ "Documentation"
+ "Developer tools"
+ }
+ { $slide "Future direction: Factor 2.0"
+ "Native threads"
+ "Syntax-aware Factor editor"
+ "Embedding Factor in C apps"
+ "Cross-compilation for smaller devices"
+ }
+ { $slide "Research areas"
+ "Identify areas where stack languages are lacking, and try to find idioms, abstractions or DSLs to solve these problems"
+ "Factor is a good platform for DSLs (fry, locals, EBNF, help, ...); what about implementing a complete language on top?"
+ "Static typing, soft typing, for stack-based languages"
+ }
+ { $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?"
+ }
+}
+
+: vpri-talk ( -- ) vpri-slides "VPRI talk" slides-window ;
+
+MAIN: vpri-talk