]> git.lizzy.rs Git - rust.git/commitdiff
docs: Make supplemental tutorials testable
authorBrian Anderson <banderson@mozilla.com>
Sun, 16 Sep 2012 01:06:20 +0000 (18:06 -0700)
committerBrian Anderson <banderson@mozilla.com>
Sun, 16 Sep 2012 01:06:20 +0000 (18:06 -0700)
configure
doc/tutorial-borrowed-ptr.md
doc/tutorial-ffi.md
mk/tests.mk
src/etc/extract-tests.py

index 8cc6f02c7dbb1b56d594f0b20dce663444e9314b..632768a5f867f0f301f415eba917f4626afeee30 100755 (executable)
--- a/configure
+++ b/configure
@@ -505,6 +505,9 @@ do
     make_dir $h/test/perf
     make_dir $h/test/pretty
     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
 done
 
index 34e3bfb1947582507d1e0e82ff02b235d6d2279b..4c187ca622c76f08ebab66fe8adc73d09c91193e 100644 (file)
@@ -40,6 +40,7 @@ example, in this code, each of these three local variables contains a
 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 shared_box   : @point = @{x: 5.0, y: 1.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:
 
 ~~~
+# type point = {x: float, y: float};
+# fn sqrt(f: float) -> float { 0f }
 fn compute_distance(p1: &point, p2: &point) -> float {
     let x_d = p1.x - p2.x;
     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:
 
-~~~
+~~~ {.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(shared_box, unique_box)
 ~~~
@@ -100,6 +108,7 @@ it again.
 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};
 ~~~
 
@@ -109,6 +118,7 @@ pointer. Sometimes however it is more convenient to move the &
 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};
 ~~~
 
@@ -116,6 +126,7 @@ Applying `&` to an rvalue (non-assignable location) is just a convenient
 shorthand for creating a temporary and taking its address:
 
 ~~~
+# type point = {x: float, y: float};
 let tmp = {x: 3.0, y: 4.0};
 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
 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);
 ~~~
 
@@ -238,14 +256,16 @@ mean that the unique box is stored in immutable memory. For example,
 the following function is legal:
 
 ~~~
+# fn some_condition() -> bool { true }
 fn example3() -> int {
     let mut x = ~{f: 3};
-    if some_condition {
+    if some_condition() {
         let y = &x.f;      // -+ L
-        ret *y;            //  |
+        return *y;         //  |
     }                      // -+
     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
 rejected by the compiler):
 
-~~~
+~~~ {.xfail-test}
 fn example3() -> int {
     let mut x = ~{f: 3};
     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
 able to detect possible mutations:
 
-~~~
+~~~ {.xfail-test}
 fn example3() -> int {
     let mut x = ~{mut f: ~{g: 3}};
     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 doesn’t know who the owner
 is). Consider a program like this:
 
-~~~
-fn example5a(x: @{mut f: ~{g: int}}, ...) -> int {
+~~~ {.xfail-test}
+fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
     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:
 
 ~~~
-fn example5b(x: @{f: ~{g: int}}, ...) -> int {
+fn example5b(x: @{f: ~{g: int}}) -> int {
     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
 onto your stack:
 
-~~~
-fn example5c(x: @{mut f: ~int}, ...) -> int {
+~~~ {.xfail-test}
+fn example5c(x: @{mut f: ~int}) -> int {
     let mut v = ~0;
     v <-> x.f;         // Swap v and x.f
     let y = &v;
     ...
     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.
 
 ~~~
+# 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 {
-    alt *shape {
+    match *shape {
         circle(_, radius) => 0.5 * tau * radius * radius,
         rectangle(_, ref size) => size.w * size.h
     }
@@ -502,7 +532,7 @@ but as we’ll see this is more limited.
 
 For example, we could write a subroutine like this:
 
-~~~
+~~~ {.xfail-test}
 type point = {x: float, y: float};
 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, let’s look at a variation on the example, this
 time one which does not compile:
 
-~~~
+~~~ {.xfail-test}
 type point = {x: float, y: float};
 fn get_x_sh(p: @point) -> &float {
     &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,
 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,
              a: &T, b: &T) -> &T {
     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
 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
 fn select_based_on_unit_circle<T>(            //  |-+ B
     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
 `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,
              a: &T, b: &T) -> &T {
     if compute_area(shape) > threshold {a} else {b}
@@ -632,7 +688,14 @@ lifetime parameter.
 You could also write `select()` using all named lifetime parameters,
 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,
              a: &r/T, b: &r/T) -> &r/T {
     if compute_area(shape) > threshold {a} else {b}
@@ -658,7 +721,7 @@ a unique box found in an aliasable, mutable location, only now we’ve
 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
     *y + 1        
 }
@@ -676,8 +739,9 @@ fn add_one(x: &int) -> int { *x + 1 }
 
 We can now update `example5a()` to use `add_one()`:
 
-~~~
-fn example5a(x: @{mut f: ~{g: int}}, ...) -> int {
+~~~ {.xfail-test}
+# fn add_one(x: &int) -> int { *x + 1 }
+fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
     let y = &x.f.g;
     add_one(y)        // Error reported here
 }
index c9e0c1a4fc6b7a9db49d7333a3fb24614c91a23a..c51d12aff8dede6bba08d00dd1ab55b4dde919e7 100644 (file)
@@ -28,9 +28,9 @@ fn as_hex(data: ~[u8]) -> ~str {
 
 fn sha1(data: ~str) -> ~str unsafe {
     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());
-    return as_hex(vec::unsafe::from_buf(hash, 20u));
+    return as_hex(vec::raw::from_buf(hash, 20u));
 }
 
 fn main(args: ~[~str]) {
@@ -128,9 +128,9 @@ The `sha1` function is the most obscure part of the program.
 fn sha1(data: ~str) -> ~str {
     unsafe {
         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());
-        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 {
 # unsafe {
 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());
-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
-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.
 
 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
 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
 twenty bytes long, so we can pass `20u` for the length of the new
 vector.
index 851c5b85d52ce42c35e57400cbca1d061acf0ecb..3b092833cad3e964a74f114e6cffbc5783abdc00 100644 (file)
@@ -164,6 +164,21 @@ doc-tutorial-extract$(1):
        $$(Q)rm -f $(1)/test/doc-tutorial/*.rs
        $$(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):
        @$$(call E, extract: ref tests)
        $$(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)-cargo       \
     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)-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-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-dummy
 
@@ -440,6 +467,24 @@ DOC_TUTORIAL_ARGS$(1)-T-$(2)-H-$(3) :=                     \
         --build-base $(3)/test/doc-tutorial/           \
         --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) :=                      \
                $$(CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3)) \
         --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)) \
                --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:            \
                $$(TEST_SREQ$(1)_T_$(2)_H_$(3))         \
                 doc-ref-extract$(3)
@@ -670,6 +739,15 @@ check-stage$(1)-H-$(2)-cargo:                                      \
 check-stage$(1)-H-$(2)-doc-tutorial:                           \
        $$(foreach target,$$(CFG_TARGET_TRIPLES),       \
         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:                                \
        $$(foreach target,$$(CFG_TARGET_TRIPLES),       \
         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)-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-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
 
 endef
index 0e8792c244b90d7def1b628f989d552835e93220..9308bf6d5ee04a244623548a6bd96ea296856f4c 100644 (file)
@@ -47,7 +47,11 @@ while cur < len(lines):
             if re.match("~~~", line):
                 break
             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 re.search(r"\bfn main\b", block):
                 block = "fn main() {\n" + block + "\n}\n"