+++ /dev/null
-Slava Pestov
+++ /dev/null
-! 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
+++ /dev/null
-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" }
-}
+++ /dev/null
-Slides for a talk at the Pycon VM Summit, Chicago, IL, March 2009
+++ /dev/null
-Slava Pestov
+++ /dev/null
-! 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
+++ /dev/null
-Slides from a talk at Galois by Slava Pestov, October 2008
+++ /dev/null
-Slava Pestov
+++ /dev/null
-! 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
+++ /dev/null
-Slides from Google Tech Talk by Slava Pestov, October 2008
+++ /dev/null
-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
+++ /dev/null
-Slava Pestov
+++ /dev/null
-! 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
+++ /dev/null
-Slides from Slava's talk at JVM Language Summit 2009
+++ /dev/null
-Slava Pestov
+++ /dev/null
-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" }
-}
+++ /dev/null
-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
+++ /dev/null
-Slides for a talk at Ruby.mn, Minneapolis, MN, January 2008
+++ /dev/null
-Slava Pestov
+++ /dev/null
-! 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
+++ /dev/null
-Slides from a talk at OTUG by Slava Pestov, December 2008
+++ /dev/null
-Doug Coleman
+++ /dev/null
-! 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
+++ /dev/null
-Slava Pestov
+++ /dev/null
-Slides from a talk at VPRI by Slava Pestov, October 2008
+++ /dev/null
-! 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