diff --git a/doc/tutorial/ffi.md b/doc/tutorial/ffi.md
new file mode 100644
index 00000000000..1b000bb7298
--- /dev/null
+++ b/doc/tutorial/ffi.md
@@ -0,0 +1,3 @@
+# Interacting with foreign code
+
+FIXME to be written
diff --git a/doc/tutorial/index.md b/doc/tutorial/index.md
index d8c9be56568..b2defa836b6 100644
--- a/doc/tutorial/index.md
+++ b/doc/tutorial/index.md
@@ -1 +1,3 @@
# Rust language tutorial
+
+
Dev snapshot. Not yet suitable for public consumption.
diff --git a/doc/tutorial/intro.md b/doc/tutorial/intro.md
index 9976d7f14e6..7f59fa861f8 100644
--- a/doc/tutorial/intro.md
+++ b/doc/tutorial/intro.md
@@ -46,3 +46,14 @@ function, `ret` for return.
You should, however, not conclude that Rust is simply an evolution of
C. As will become clear in the rest of this tutorial, it goes into
quite a different direction.
+
+## Conventions
+
+Throughout the tutorial, words that indicate language keywords or
+identifiers defined in the example code are displayed in `code font`.
+
+Code snippets are indented, and also shown in a monospace font. Not
+all snippets constitute whole programs. For brevity, we'll often show
+fragments of programs that don't compile on their own. To try them
+out, you'll have to wrap them in `fn main() { ... }`, and make sure
+they don't contain references to things that aren't actually defined.
diff --git a/doc/tutorial/mod.md b/doc/tutorial/mod.md
index d7a0e6417f3..352b51c1db5 100644
--- a/doc/tutorial/mod.md
+++ b/doc/tutorial/mod.md
@@ -1,3 +1,224 @@
# Modules and crates
-FIXME include name resolution details
+The Rust namespace is divided in modules. Each source file starts with
+its own, empty module.
+
+## Local modules
+
+The `mod` keyword can be used to open a new, local module. In the
+example below, `chicken` lives in the module `farm`, so, unless you
+explicitly import it, you must refer to it by its long name,
+`farm::chicken`.
+
+ mod farm {
+ fn chicken() -> str { "cluck cluck" }
+ fn cow() -> str { "mooo" }
+ }
+ fn main() {
+ log_err farm::chicken();
+ }
+
+Modules can be nested to arbitrary depth.
+
+## Crates
+
+The unit of independent compilation in Rust is the crate. Libraries
+tend to be packaged as crates, and your own programs may consist of
+one or more crates.
+
+When compiling a single `.rs` file, the file acts as the whole crate.
+You can compile it with the `--lib` compiler switch to create a shared
+library, or without, provided that your file contains a `fn main`
+somewhere, to create an executable.
+
+It is also possible to include multiple files in a crate. For this
+purpose, you create a `.rc` crate file, which references any number of
+`.rs` code files. A crate file could look like this:
+
+ #[link(name = "farm", vers = "2.5", author = "mjh")]
+ mod cow;
+ mod chicken;
+ mod horse;
+
+Compiling this file will cause `rustc` to look for files named
+`cow.rs`, `chicken.rs`, `horse.rs` in the same directory as the `.rc`
+file, compile them all together, and, depending on the presence of the
+`--lib` switch, output a shared library or an executable.
+
+The `#[link(...)]` part provides meta information about the module,
+which other crates can use to load the right module. More about that
+in a moment.
+
+To have a nested directory structure for your source files, you can
+nest mods in your `.rc` file:
+
+ mod poultry {
+ mod chicken;
+ mod turkey;
+ }
+
+The compiler will now look for `poultry/chicken.rs` and
+`poultry/turkey.rs`, and export their content in `poultry::chicken`
+and `poultry::turkey`. You can also provide a `poultry.rs` to add
+content to the `poultry` module itself.
+
+## Using other crates
+
+Having compiled a crate with `--lib`, you can use it in another crate
+with a `use` directive. We've already seen `use std` in several of the
+examples, which loads in the standard library.
+
+`use` directives can appear in a crate file, or at the top level of a
+single-file `.rs` crate. They will cause the compiler to search its
+library search path (which you can extend with `-L` switch) for a Rust
+crate library with the right name. This name is deduced from the crate
+name in a platform-dependent way. The `farm` library will be called
+`farm.dll` on Windows, `libfarm.so` on Linux, and `libfarm.dylib` on
+OS X.
+
+It is possible to provide more specific information when using an
+external crate.
+
+ use myfarm (name = "farm", vers = "2.7");
+
+When a comma-separated list of name/value pairs is given after `use`,
+these are matched against the attributes provided in the `link`
+attribute of the crate file, and a crate is only used when the two
+match. A `name` value can be given to override the name used to search
+for the crate. So the above would import the `farm` crate under the
+local name `myfarm`.
+
+Our example crate declared this set of `link` attributes:
+
+ #[link(name = "farm", vers = "2.5", author = "mjh")]
+
+The version does not match the one provided in the `use` directive, so
+unless the compiler can find another crate with the right version
+somewhere, it will complain that no matching crate was found.
+
+## A minimal example
+
+Now for something that you can actually compile yourself. We have
+these two files:
+
+ // mylib.rs
+ fn world() -> str { "world" }
+
+ // main.rs
+ use mylib;
+ fn main() { log_err "hello " + mylib::world(); }
+
+FIXME the compiler currently complains about missing link metas when you compile this
+
+Now compile and run like this (adjust to your platform if necessary):
+
+ > rustc --lib mylib.rs
+ > rustc main.rs -L .
+ > ./main
+ "hello world"
+
+## Importing
+
+When using identifiers from other modules, it can get tiresome to
+qualify them with the full module path every time (especially when
+that path is several modules deep). Rust allows you to import
+identifiers at the top of a file or module.
+
+ use std;
+ import std::io::println;
+ fn main() {
+ println("that was easy");
+ }
+
+It is also possible to import just the name of a module (`import
+std::io;`, then use `io::println`), import all identifiers exported by
+a given module (`import std::io::*`), or to import a specific set of
+identifiers (`import std::math::{min, max, pi}`).
+
+It is also possible to rename an identifier when importing, using the
+`=` operator:
+
+ import prnt = std::io::println;
+
+## Exporting
+
+By default, a module exports everything that it defines. This can be
+restricted with `export` directives at the top of the module or file.
+
+ mod enc {
+ export encrypt, decrypt;
+ const super_secret_number: int = 10;
+ fn encrypt(n: int) { n + super_secret_number }
+ fn decrypt(n: int) { n - super_secret_number }
+ }
+
+This defines a rock-solid encryption algorithm. Code outside of the
+module can refer to the `enc::encrypt` and `enc::decrypt` identifiers
+just fine, but it does not have access to `enc::syper_secret_number`.
+
+## Namespaces
+
+Rust uses three different namespaces. One for modules, one for types,
+and one for values. This means that this code is valid:
+
+ mod buffalo {
+ type buffalo = int;
+ fn buffalo(buffalo: buffalo) -> buffalo { buffalo }
+ }
+ fn main() {
+ let buffalo: buffalo::buffalo = 1;
+ buffalo::buffalo(buffalo::buffalo(buffalo));
+ }
+
+You don't want to write things like that, but it *is* very practical
+to not have to worry about name clashes between types, values, and
+modules. This allows us to have a module `std::str`, for example, even
+though `str` is a built-in type name.
+
+## Resolution
+
+The resolution process in Rust simply goes up the chain of contexts,
+looking for the name in each context. Nested functions and modules
+create new contexts inside their parent function or module. A file
+that's part of a bigger crate will have that crate's context as parent
+context.
+
+Identifiers can shadow each others. In this program, `x` is of type
+`int`:
+
+ type x = str;
+ fn main() {
+ type x = int;
+ let x: int;
+ }
+
+An `import` directive will only import into the namespaces for which
+identifiers are actually found. Consider this example:
+
+ type bar = uint;
+ mod foo { fn bar() {} }
+ mod baz {
+ import foo::bar;
+ const x: bar = 20u;
+ }
+
+When resolving the type name `bar` in the `const` definition, the
+resolver will first look at the module context for `baz`. This has an
+import named `bar`, but that's a function, not a type, So it continues
+to the top level and finds a type named `bar` defined there.
+
+Normally, multiple definitions of the same identifier in a scope are
+disallowed. Local variables defined with `let` are an exception to
+this—multiple `let` directives can redefine the same variable in a
+single scope. When resolving the name of such a variable, the most
+recent definition is used.
+
+ fn main() {
+ let x = 10;
+ let x = x + 10;
+ assert x == 20;
+ }
+
+This makes it possible to rebind a variable without actually mutating
+it, which is mostly useful for destructuring (which can rebind, but
+not assign).
diff --git a/doc/tutorial/order b/doc/tutorial/order
index 54b7314a2dd..d7ed3605db7 100644
--- a/doc/tutorial/order
+++ b/doc/tutorial/order
@@ -7,3 +7,5 @@ data
args
generic
mod
+ffi
+task
diff --git a/doc/tutorial/syntax.md b/doc/tutorial/syntax.md
index a40c9822152..8c6a54f50d4 100644
--- a/doc/tutorial/syntax.md
+++ b/doc/tutorial/syntax.md
@@ -86,6 +86,27 @@ The double-colon (`::`) is used as a module separator, so
`std::io::println` means 'the thing named `println` in the module
named `io` in the module named `std`'.
+Rust will normally emit warning about unused variables. These can be
+suppressed by using a variable name that starts with an underscore.
+
+ fn this_warns(x: int) {}
+ fn this_doesnt(_x: int) {}
+
+## Variable declaration
+
+The `let` keyword, as we've seen, introduces a local variable. Global
+constants can be defined with `const`:
+
+ import std;
+ const repeat: uint = 5u;
+ fn main() {
+ let count = 0u;
+ while count < repeat {
+ std::io::println("Hi!");
+ count += 1u;
+ }
+ }
+
## Types
The `-> bool` in the last example is the way a function's return type
@@ -256,3 +277,7 @@ exists, convert the result of the expression to the given type.
let x: float = 4.0;
let y: uint = x as uint;
assert y == 4u;
+
+## Attributes
+
+FIXME Briefly introduce attributes
diff --git a/doc/tutorial/task.md b/doc/tutorial/task.md
new file mode 100644
index 00000000000..50a7ad193ec
--- /dev/null
+++ b/doc/tutorial/task.md
@@ -0,0 +1,3 @@
+# Tasks
+
+FIXME to be written