docs: Make supplemental tutorials testable

This commit is contained in:
Brian Anderson 2012-09-15 18:06:20 -07:00
parent 82e79f765c
commit 864cca14ee
5 changed files with 182 additions and 30 deletions

3
configure vendored
View file

@ -505,6 +505,9 @@ do
make_dir $h/test/perf make_dir $h/test/perf
make_dir $h/test/pretty make_dir $h/test/pretty
make_dir $h/test/doc-tutorial make_dir $h/test/doc-tutorial
make_dir $h/test/doc-tutorial-ffi
make_dir $h/test/doc-tutorial-macros
make_dir $h/test/doc-tutorial-borrowed-ptr
make_dir $h/test/doc-ref make_dir $h/test/doc-ref
done done

View file

@ -40,6 +40,7 @@ example, in this code, each of these three local variables contains a
point, but allocated in a different place: point, but allocated in a different place:
~~~ ~~~
# type point = {x: float, y: float};
let on_the_stack : point = {x: 3.0, y: 4.0}; let on_the_stack : point = {x: 3.0, y: 4.0};
let shared_box : @point = @{x: 5.0, y: 1.0}; let shared_box : @point = @{x: 5.0, y: 1.0};
let unique_box : ~point = ~{x: 7.0, y: 9.0}; let unique_box : ~point = ~{x: 7.0, y: 9.0};
@ -58,6 +59,8 @@ define a function that takes the points by pointer. We can use
borrowed pointers to do this: borrowed pointers to do this:
~~~ ~~~
# type point = {x: float, y: float};
# fn sqrt(f: float) -> float { 0f }
fn compute_distance(p1: &point, p2: &point) -> float { fn compute_distance(p1: &point, p2: &point) -> float {
let x_d = p1.x - p2.x; let x_d = p1.x - p2.x;
let y_d = p1.y - p2.y; let y_d = p1.y - p2.y;
@ -67,7 +70,12 @@ fn compute_distance(p1: &point, p2: &point) -> float {
Now we can call `compute_distance()` in various ways: Now we can call `compute_distance()` in various ways:
~~~ ~~~ {.xfail-test}
# type point = {x: float, y: float};
# let on_the_stack : point = {x: 3.0, y: 4.0};
# let shared_box : @point = @{x: 5.0, y: 1.0};
# let unique_box : ~point = ~{x: 7.0, y: 9.0};
# fn compute_distance(p1: &point, p2: &point) -> float { 0f }
compute_distance(&on_the_stack, shared_box) compute_distance(&on_the_stack, shared_box)
compute_distance(shared_box, unique_box) compute_distance(shared_box, unique_box)
~~~ ~~~
@ -100,6 +108,7 @@ it again.
In the previous example, the value `on_the_stack` was defined like so: In the previous example, the value `on_the_stack` was defined like so:
~~~ ~~~
# type point = {x: float, y: float};
let on_the_stack : point = {x: 3.0, y: 4.0}; let on_the_stack : point = {x: 3.0, y: 4.0};
~~~ ~~~
@ -109,6 +118,7 @@ pointer. Sometimes however it is more convenient to move the &
operator into the definition of `on_the_stack`: operator into the definition of `on_the_stack`:
~~~ ~~~
# type point = {x: float, y: float};
let on_the_stack2 : &point = &{x: 3.0, y: 4.0}; let on_the_stack2 : &point = &{x: 3.0, y: 4.0};
~~~ ~~~
@ -116,6 +126,7 @@ Applying `&` to an rvalue (non-assignable location) is just a convenient
shorthand for creating a temporary and taking its address: shorthand for creating a temporary and taking its address:
~~~ ~~~
# type point = {x: float, y: float};
let tmp = {x: 3.0, y: 4.0}; let tmp = {x: 3.0, y: 4.0};
let on_the_stack2 : &point = &tmp; let on_the_stack2 : &point = &tmp;
~~~ ~~~
@ -144,7 +155,14 @@ let rect_unique = ~{origin: {x: 5, y: 6}, size: {w: 3, h: 4}};
In each case I can use the `&` operator to extact out individual In each case I can use the `&` operator to extact out individual
subcomponents. For example, I could write: subcomponents. For example, I could write:
~~~ ~~~ {.xfail-test}
# type point = {x: float, y: float};
# type size = {w: float, h: float}; // as before
# type rectangle = {origin: point, size: size};
# let rect_stack = &{origin: {x: 1, y: 2}, size: {w: 3, h: 4}};
# let rect_shared = @{origin: {x: 3, y: 4}, size: {w: 3, h: 4}};
# let rect_unique = ~{origin: {x: 5, y: 6}, size: {w: 3, h: 4}};
# fn compute_distance(p1: &point, p2: &point) -> float { 0f }
compute_distance(&rect_stack.origin, &rect_shared.origin); compute_distance(&rect_stack.origin, &rect_shared.origin);
~~~ ~~~
@ -238,14 +256,16 @@ mean that the unique box is stored in immutable memory. For example,
the following function is legal: the following function is legal:
~~~ ~~~
# fn some_condition() -> bool { true }
fn example3() -> int { fn example3() -> int {
let mut x = ~{f: 3}; let mut x = ~{f: 3};
if some_condition { if some_condition() {
let y = &x.f; // -+ L let y = &x.f; // -+ L
ret *y; // | return *y; // |
} // -+ } // -+
x = ~{f: 4}; x = ~{f: 4};
... ...
# return 0;
} }
~~~ ~~~
@ -261,7 +281,7 @@ _as soon as their owning reference is changed or goes out of
scope_. Therefore, a program like this is illegal (and would be scope_. Therefore, a program like this is illegal (and would be
rejected by the compiler): rejected by the compiler):
~~~ ~~~ {.xfail-test}
fn example3() -> int { fn example3() -> int {
let mut x = ~{f: 3}; let mut x = ~{f: 3};
let y = &x.f; let y = &x.f;
@ -308,7 +328,7 @@ frame_. So we could modify the previous example to introduce
additional unique pointers and records, and the compiler will still be additional unique pointers and records, and the compiler will still be
able to detect possible mutations: able to detect possible mutations:
~~~ ~~~ {.xfail-test}
fn example3() -> int { fn example3() -> int {
let mut x = ~{mut f: ~{g: 3}}; let mut x = ~{mut f: ~{g: 3}};
let y = &x.f.g; let y = &x.f.g;
@ -326,8 +346,8 @@ Things get tricker when the unique box is not uniquely owned by the
stack frame (or when the compiler doesnt know who the owner stack frame (or when the compiler doesnt know who the owner
is). Consider a program like this: is). Consider a program like this:
~~~ ~~~ {.xfail-test}
fn example5a(x: @{mut f: ~{g: int}}, ...) -> int { fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
let y = &x.f.g; // Error reported here. let y = &x.f.g; // Error reported here.
... ...
} }
@ -359,9 +379,10 @@ unique found in aliasable memory is to ensure that it is stored within
unique fields, as in the following example: unique fields, as in the following example:
~~~ ~~~
fn example5b(x: @{f: ~{g: int}}, ...) -> int { fn example5b(x: @{f: ~{g: int}}) -> int {
let y = &x.f.g; let y = &x.f.g;
... ...
# return 0;
} }
~~~ ~~~
@ -373,13 +394,15 @@ If you do have a unique box in a mutable field, and you wish to borrow
it, one option is to use the swap operator to bring that unique box it, one option is to use the swap operator to bring that unique box
onto your stack: onto your stack:
~~~ ~~~ {.xfail-test}
fn example5c(x: @{mut f: ~int}, ...) -> int { fn example5c(x: @{mut f: ~int}) -> int {
let mut v = ~0; let mut v = ~0;
v <-> x.f; // Swap v and x.f v <-> x.f; // Swap v and x.f
let y = &v; let y = &v;
... ...
x.f <- v; // Replace x.f x.f <- v; // Replace x.f
...
# return 0;
} }
~~~ ~~~
@ -412,8 +435,15 @@ function takes a borrowed pointer to a shape to avoid the need of
copying them. copying them.
~~~ ~~~
# type point = {x: float, y: float}; // as before
# type size = {w: float, h: float}; // as before
# enum shape {
# circle(point, float), // origin, radius
# rectangle(point, size) // upper-left, dimensions
# }
# const tau: float = 6.28f;
fn compute_area(shape: &shape) -> float { fn compute_area(shape: &shape) -> float {
alt *shape { match *shape {
circle(_, radius) => 0.5 * tau * radius * radius, circle(_, radius) => 0.5 * tau * radius * radius,
rectangle(_, ref size) => size.w * size.h rectangle(_, ref size) => size.w * size.h
} }
@ -502,7 +532,7 @@ but as well see this is more limited.
For example, we could write a subroutine like this: For example, we could write a subroutine like this:
~~~ ~~~ {.xfail-test}
type point = {x: float, y: float}; type point = {x: float, y: float};
fn get_x(p: &point) -> &float { &p.x } fn get_x(p: &point) -> &float { &p.x }
~~~ ~~~
@ -535,7 +565,7 @@ the compiler is satisfied with the function `get_x()`.
To drill in this point, lets look at a variation on the example, this To drill in this point, lets look at a variation on the example, this
time one which does not compile: time one which does not compile:
~~~ ~~~ {.xfail-test}
type point = {x: float, y: float}; type point = {x: float, y: float};
fn get_x_sh(p: @point) -> &float { fn get_x_sh(p: @point) -> &float {
&p.x // Error reported here &p.x // Error reported here
@ -574,7 +604,14 @@ pointer. However, sometimes if a function takes many parameters, it is
useful to be able to group those parameters by lifetime. For example, useful to be able to group those parameters by lifetime. For example,
consider this function: consider this function:
~~~ ~~~ {.xfail-test}
# type point = {x: float, y: float}; // as before
# type size = {w: float, h: float}; // as before
# enum shape {
# circle(point, float), // origin, radius
# rectangle(point, size) // upper-left, dimensions
# }
# fn compute_area(shape: &shape) -> float { 0f }
fn select<T>(shape: &shape, threshold: float, fn select<T>(shape: &shape, threshold: float,
a: &T, b: &T) -> &T { a: &T, b: &T) -> &T {
if compute_area(shape) > threshold {a} else {b} if compute_area(shape) > threshold {a} else {b}
@ -588,7 +625,19 @@ lifetime of the returned value will be the intersection of the
lifetime of the three region parameters. This may be overloy lifetime of the three region parameters. This may be overloy
conservative, as in this example: conservative, as in this example:
~~~ ~~~ {.xfail-test}
# type point = {x: float, y: float}; // as before
# type size = {w: float, h: float}; // as before
# enum shape {
# circle(point, float), // origin, radius
# rectangle(point, size) // upper-left, dimensions
# }
# fn compute_area(shape: &shape) -> float { 0f }
# fn select<T>(shape: &shape, threshold: float,
# a: &T, b: &T) -> &T {
# if compute_area(shape) > threshold {a} else {b}
# }
// -+ L // -+ L
fn select_based_on_unit_circle<T>( // |-+ B fn select_based_on_unit_circle<T>( // |-+ B
threshold: float, a: &T, b: &T) -> &T { // | | threshold: float, a: &T, b: &T) -> &T { // | |
@ -618,7 +667,14 @@ second lifetime parameter for the function; named lifetime parameters
do not need to be declared, you just use them. Here is how the new do not need to be declared, you just use them. Here is how the new
`select()` might look: `select()` might look:
~~~ ~~~ {.xfail-test}
# type point = {x: float, y: float}; // as before
# type size = {w: float, h: float}; // as before
# enum shape {
# circle(point, float), // origin, radius
# rectangle(point, size) // upper-left, dimensions
# }
# fn compute_area(shape: &shape) -> float { 0f }
fn select<T>(shape: &tmp/shape, threshold: float, fn select<T>(shape: &tmp/shape, threshold: float,
a: &T, b: &T) -> &T { a: &T, b: &T) -> &T {
if compute_area(shape) > threshold {a} else {b} if compute_area(shape) > threshold {a} else {b}
@ -632,7 +688,14 @@ lifetime parameter.
You could also write `select()` using all named lifetime parameters, You could also write `select()` using all named lifetime parameters,
which might look like: which might look like:
~~~ ~~~ {.xfail-test}
# type point = {x: float, y: float}; // as before
# type size = {w: float, h: float}; // as before
# enum shape {
# circle(point, float), // origin, radius
# rectangle(point, size) // upper-left, dimensions
# }
# fn compute_area(shape: &shape) -> float { 0f }
fn select<T>(shape: &tmp/shape, threshold: float, fn select<T>(shape: &tmp/shape, threshold: float,
a: &r/T, b: &r/T) -> &r/T { a: &r/T, b: &r/T) -> &r/T {
if compute_area(shape) > threshold {a} else {b} if compute_area(shape) > threshold {a} else {b}
@ -658,7 +721,7 @@ a unique box found in an aliasable, mutable location, only now weve
replaced the `...` with some specific code: replaced the `...` with some specific code:
~~~ ~~~
fn example5a(x: @{mut f: ~{g: int}}, ...) -> int { fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
let y = &x.f.g; // Unsafe let y = &x.f.g; // Unsafe
*y + 1 *y + 1
} }
@ -676,8 +739,9 @@ fn add_one(x: &int) -> int { *x + 1 }
We can now update `example5a()` to use `add_one()`: We can now update `example5a()` to use `add_one()`:
~~~ ~~~ {.xfail-test}
fn example5a(x: @{mut f: ~{g: int}}, ...) -> int { # fn add_one(x: &int) -> int { *x + 1 }
fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
let y = &x.f.g; let y = &x.f.g;
add_one(y) // Error reported here add_one(y) // Error reported here
} }

View file

@ -28,9 +28,9 @@ fn as_hex(data: ~[u8]) -> ~str {
fn sha1(data: ~str) -> ~str unsafe { fn sha1(data: ~str) -> ~str unsafe {
let bytes = str::to_bytes(data); let bytes = str::to_bytes(data);
let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes), let hash = crypto::SHA1(vec::raw::to_ptr(bytes),
vec::len(bytes) as c_uint, ptr::null()); vec::len(bytes) as c_uint, ptr::null());
return as_hex(vec::unsafe::from_buf(hash, 20u)); return as_hex(vec::raw::from_buf(hash, 20u));
} }
fn main(args: ~[~str]) { fn main(args: ~[~str]) {
@ -128,9 +128,9 @@ The `sha1` function is the most obscure part of the program.
fn sha1(data: ~str) -> ~str { fn sha1(data: ~str) -> ~str {
unsafe { unsafe {
let bytes = str::to_bytes(data); let bytes = str::to_bytes(data);
let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes), let hash = crypto::SHA1(vec::raw::to_ptr(bytes),
vec::len(bytes), ptr::null()); vec::len(bytes), ptr::null());
return as_hex(vec::unsafe::from_buf(hash, 20u)); return as_hex(vec::raw::from_buf(hash, 20u));
} }
} }
~~~~ ~~~~
@ -171,15 +171,15 @@ Let's look at our `sha1` function again.
# fn x(data: ~str) -> ~str { # fn x(data: ~str) -> ~str {
# unsafe { # unsafe {
let bytes = str::to_bytes(data); let bytes = str::to_bytes(data);
let hash = crypto::SHA1(vec::unsafe::to_ptr(bytes), let hash = crypto::SHA1(vec::raw::to_ptr(bytes),
vec::len(bytes), ptr::null()); vec::len(bytes), ptr::null());
return as_hex(vec::unsafe::from_buf(hash, 20u)); return as_hex(vec::raw::from_buf(hash, 20u));
# } # }
# } # }
~~~~ ~~~~
The `str::to_bytes` function is perfectly safe: it converts a string to The `str::to_bytes` function is perfectly safe: it converts a string to
a `[u8]`. This byte array is then fed to `vec::unsafe::to_ptr`, which a `[u8]`. This byte array is then fed to `vec::raw::to_ptr`, which
returns an unsafe pointer to its contents. returns an unsafe pointer to its contents.
This pointer will become invalid as soon as the vector it points into This pointer will become invalid as soon as the vector it points into
@ -193,7 +193,7 @@ unsafe null pointer of the correct type (Rust generics are awesome
like that—they can take the right form depending on the type that they like that—they can take the right form depending on the type that they
are expected to return). are expected to return).
Finally, `vec::unsafe::from_buf` builds up a new `[u8]` from the Finally, `vec::raw::from_buf` builds up a new `[u8]` from the
unsafe pointer that was returned by `SHA1`. SHA1 digests are always unsafe pointer that was returned by `SHA1`. SHA1 digests are always
twenty bytes long, so we can pass `20u` for the length of the new twenty bytes long, so we can pass `20u` for the length of the new
vector. vector.

View file

@ -164,6 +164,21 @@ doc-tutorial-extract$(1):
$$(Q)rm -f $(1)/test/doc-tutorial/*.rs $$(Q)rm -f $(1)/test/doc-tutorial/*.rs
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial.md $(1)/test/doc-tutorial $$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial.md $(1)/test/doc-tutorial
doc-tutorial-ffi-extract$(1):
@$$(call E, extract: tutorial-ffi tests)
$$(Q)rm -f $(1)/test/doc-tutorial-ffi/*.rs
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-ffi.md $(1)/test/doc-tutorial-ffi
doc-tutorial-macros-extract$(1):
@$$(call E, extract: tutorial-macros tests)
$$(Q)rm -f $(1)/test/doc-tutorial-macros/*.rs
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-macros.md $(1)/test/doc-tutorial-macros
doc-tutorial-borrowed-ptr-extract$(1):
@$$(call E, extract: tutorial-borrowed-ptr tests)
$$(Q)rm -f $(1)/test/doc-tutorial-borrowed-ptr/*.rs
$$(Q)$$(EXTRACT_TESTS) $$(S)doc/tutorial-borrowed-ptr.md $(1)/test/doc-tutorial-borrowed-ptr
doc-ref-extract$(1): doc-ref-extract$(1):
@$$(call E, extract: ref tests) @$$(call E, extract: ref tests)
$$(Q)rm -f $(1)/test/doc-ref/*.rs $$(Q)rm -f $(1)/test/doc-ref/*.rs
@ -211,6 +226,9 @@ check-stage$(1)-T-$(2)-H-$(3): \
check-stage$(1)-T-$(2)-H-$(3)-rustdoc \ check-stage$(1)-T-$(2)-H-$(3)-rustdoc \
check-stage$(1)-T-$(2)-H-$(3)-cargo \ check-stage$(1)-T-$(2)-H-$(3)-cargo \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial \ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr \
check-stage$(1)-T-$(2)-H-$(3)-doc-ref check-stage$(1)-T-$(2)-H-$(3)-doc-ref
check-stage$(1)-T-$(2)-H-$(3)-core: \ check-stage$(1)-T-$(2)-H-$(3)-core: \
@ -271,6 +289,15 @@ check-stage$(1)-T-$(2)-H-$(3)-cargo: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial: \ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-dummy check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-dummy
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi-dummy
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros-dummy
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr: \
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy
check-stage$(1)-T-$(2)-H-$(3)-doc-ref: \ check-stage$(1)-T-$(2)-H-$(3)-doc-ref: \
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy
@ -440,6 +467,24 @@ DOC_TUTORIAL_ARGS$(1)-T-$(2)-H-$(3) := \
--build-base $(3)/test/doc-tutorial/ \ --build-base $(3)/test/doc-tutorial/ \
--mode run-pass --mode run-pass
DOC_TUTORIAL_FFI_ARGS$(1)-T-$(2)-H-$(3) := \
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
--src-base $(3)/test/doc-tutorial-ffi/ \
--build-base $(3)/test/doc-tutorial-ffi/ \
--mode run-pass
DOC_TUTORIAL_MACROS_ARGS$(1)-T-$(2)-H-$(3) := \
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
--src-base $(3)/test/doc-tutorial-macros/ \
--build-base $(3)/test/doc-tutorial-macros/ \
--mode run-pass
DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3) := \
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
--src-base $(3)/test/doc-tutorial-borrowed-ptr/ \
--build-base $(3)/test/doc-tutorial-borrowed-ptr/ \
--mode run-pass
DOC_REF_ARGS$(1)-T-$(2)-H-$(3) := \ DOC_REF_ARGS$(1)-T-$(2)-H-$(3) := \
$$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \ $$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
--src-base $(3)/test/doc-ref/ \ --src-base $(3)/test/doc-ref/ \
@ -542,6 +587,30 @@ check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-dummy: \
$$(DOC_TUTORIAL_ARGS$(1)-T-$(2)-H-$(3)) \ $$(DOC_TUTORIAL_ARGS$(1)-T-$(2)-H-$(3)) \
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial.log --logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial.log
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi-dummy: \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
doc-tutorial-ffi-extract$(3)
@$$(call E, run doc-tutorial-ffi: $$<)
$$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
$$(DOC_TUTORIAL_FFI_ARGS$(1)-T-$(2)-H-$(3)) \
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-ffi.log
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros-dummy: \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
doc-tutorial-macros-extract$(3)
@$$(call E, run doc-tutorial-macros: $$<)
$$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
$$(DOC_TUTORIAL_MACROS_ARGS$(1)-T-$(2)-H-$(3)) \
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-macros.log
check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr-dummy: \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
doc-tutorial-borrowed-ptr-extract$(3)
@$$(call E, run doc-tutorial-borrowed-ptr: $$<)
$$(Q)$$(call CFG_RUN_CTEST,$(1),$$<,$(3)) \
$$(DOC_TUTORIAL_BORROWED_PTR_ARGS$(1)-T-$(2)-H-$(3)) \
--logfile tmp/check-stage$(1)-T-$(2)-H-$(3)-doc-tutorial-borrowed-ptr.log
check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy: \ check-stage$(1)-T-$(2)-H-$(3)-doc-ref-dummy: \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
doc-ref-extract$(3) doc-ref-extract$(3)
@ -670,6 +739,15 @@ check-stage$(1)-H-$(2)-cargo: \
check-stage$(1)-H-$(2)-doc-tutorial: \ check-stage$(1)-H-$(2)-doc-tutorial: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial) check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial)
check-stage$(1)-H-$(2)-doc-tutorial-ffi: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-ffi)
check-stage$(1)-H-$(2)-doc-tutorial-macros: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-macros)
check-stage$(1)-H-$(2)-doc-tutorial-borrowed-ptr: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-tutorial-borrowed-ptr)
check-stage$(1)-H-$(2)-doc-ref: \ check-stage$(1)-H-$(2)-doc-ref: \
$$(foreach target,$$(CFG_TARGET_TRIPLES), \ $$(foreach target,$$(CFG_TARGET_TRIPLES), \
check-stage$(1)-T-$$(target)-H-$(2)-doc-ref) check-stage$(1)-T-$$(target)-H-$(2)-doc-ref)
@ -778,6 +856,9 @@ check-stage$(1)-pretty-pretty: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-pretty-pret
check-stage$(1)-rustdoc: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-rustdoc check-stage$(1)-rustdoc: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-rustdoc
check-stage$(1)-cargo: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-cargo check-stage$(1)-cargo: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-cargo
check-stage$(1)-doc-tutorial: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial check-stage$(1)-doc-tutorial: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial
check-stage$(1)-doc-tutorial-ffi: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-ffi
check-stage$(1)-doc-tutorial-macros: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-macros
check-stage$(1)-doc-tutorial-borrowed-ptr: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-tutorial-borrowed-ptr
check-stage$(1)-doc-ref: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-ref check-stage$(1)-doc-ref: check-stage$(1)-H-$$(CFG_HOST_TRIPLE)-doc-ref
endef endef

View file

@ -47,7 +47,11 @@ while cur < len(lines):
if re.match("~~~", line): if re.match("~~~", line):
break break
else: else:
block += re.sub("^# ", "", line) # Lines beginning with '# ' are turned into valid code
line = re.sub("^# ", "", line)
# Allow elipses in code snippets
line = re.sub("\.\.\.", "/*...*/", line)
block += line
if not ignore: if not ignore:
if not re.search(r"\bfn main\b", block): if not re.search(r"\bfn main\b", block):
block = "fn main() {\n" + block + "\n}\n" block = "fn main() {\n" + block + "\n}\n"