Armin Ronacher <armin.ronacher@active-4.com>
Austin Seipp <mad.one@gmail.com>
auREAX <mark@xn--hwg34fba.ws>
+Ben Alpert <ben@benalpert.com>
Ben Blum <bblum@andrew.cmu.edu>
Ben Striegel <ben.striegel@gmail.com>
Benjamin Herr <ben@0x539.de>
Erik Rose <erik@mozilla.com>
Evan McClanahan <evan@evanmcc.com>
Francisco Souza <f@souza.cc>
+Franklin Chen <franklinchen@franklinchen.com>
Gabriel <g2p.code@gmail.com>
Gareth Daniel Smith <garethdanielsmith@gmail.com>
Glenn Willen <gwillen@nerdnet.org>
Haitao Li <lihaitao@gmail.com>
Huon Wilson <dbau.pp+github@gmail.com>
Ian D. Bollinger <ian.bollinger@gmail.com>
+Ilyong Cho <ilyoan@gmail.com>
Isaac Aggrey <isaac.aggrey@gmail.com>
Ivano Coppola <rgbfirefox@gmail.com>
Jacob Harris Cryer Kragh <jhckragh@gmail.com>
Jim Blandy <jimb@red-bean.com>
Jimmy Lu <jimmy.lu.2011@gmail.com>
Joe Pletcher <joepletcher@gmail.com>
+John Clements <clements@racket-lang.org>
Jon Morton <jonanin@gmail.com>
Jonathan Sternberg <jonathansternberg@gmail.com>
Josh Matthews <josh@joshmatthews.net>
Kevin Atkinson <kevina@cs.utah.edu>
Kevin Cantu <me@kevincantu.org>
Lennart Kudling <github@kudling.de>
-Lindsey Kuper <lindsey@rockstargirl.org>
+Lindsey Kuper <lindsey@composition.al>
Luca Bruno <lucab@debian.org>
Luqman Aden <laden@csclub.uwaterloo.ca>
Magnus Auvinen <magnus.auvinen@gmail.com>
Mahmut Bulut <mahmutbulut0@gmail.com>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu>
Marijn Haverbeke <marijnh@gmail.com>
+Mark Lacey <641@rudkx.com>
Martin DeMello <martindemello@gmail.com>
Matt Brubeck <mbrubeck@limpet.net>
Matthew O'Connor <thegreendragon@gmail.com>
Paul Stansifer <paul.stansifer@gmail.com>
Paul Woolcock <pwoolcoc+github@gmail.com>
Peter Hull <peterhull90@gmail.com>
+Peter Williams <peter@newton.cx>
Philipp Brüschweiler <blei42@gmail.com>
Rafael Ávila de Espíndola <respindola@mozilla.com>
Ralph Giles <giles@thaumas.net>
Roy Frostig <rfrostig@mozilla.com>
Ryan Scheel <ryan.havvy@gmail.com>
Sean Stangl <sstangl@mozilla.com>
+Sebastian N. Fernandez <cachobot@gmail.com>
Simon Barber-Dueck <sbarberdueck@gmail.com>
startling <tdixon51793@gmail.com>
Stefan Plantikow <stefan.plantikow@googlemail.com>
+Steve Klabnik <steve@steveklabnik.com>
Taras Shpot <mrshpot@gmail.com>
Ted Horst <ted.horst@earthlink.net>
Tim Chevalier <chevalier@alum.wellesley.edu>
Viktor Dahl <pazaconyoman@gmail.com>
Vincent Belliard <vincent@famillebelliard.fr>
Wade Mealing <wmealing@gmail.com>
+William Ting <william.h.ting@gmail.com>
Yasuhiro Fujii <y-fujii@mimosa-pudica.net>
Zack Corr <zackcorr95@gmail.com>
--- /dev/null
+## Pull request procedure
+
+Pull requests should be targeted at Rust's `incoming` branch (note that by default Github will aim them at the `master` branch) -- see "Changing The Commit Range and Destination Repository" in Github's documentation on [pull requests](https://help.github.com/articles/using-pull-requests). Before pushing to your Github repo and issuing the pull request, please do two things:
+
+1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your local changes against the `incoming` branch. Resolve any conflicts that arise.
+2. Run the full Rust test suite with the `make check` command. You're not off the hook even if you just stick to documentation; code examples in the docs are tested as well!
+
+Pull requests will be treated as "review requests", and we will give feedback we expect to see corrected on [style](https://github.com/mozilla/rust/wiki/Note-style-guide) and substance before pulling. Changes contributed via pull request should focus on a single issue at a time, like any other. We will not look kindly on pull-requests that try to "sneak" unrelated changes in.
+
+Normally, all pull requests must include regression tests (see [[Note-testsuite]]) that test your change. Occasionally, a change will be very difficult to test for. In those cases, please include a note in your commit message explaining why.
+
+For more details, please refer to [[Note-development-policy]].
\ No newline at end of file
######################################################################
# FIXME: x86-ism
-LLVM_COMPONENTS=x86 ipo bitreader bitwriter linker asmparser jit mcjit \
+LLVM_COMPONENTS=x86 arm ipo bitreader bitwriter linker asmparser jit mcjit \
interpreter
define DEF_LLVM_VARS
## License
-Rust is primarily distributed under the terms of the MIT license, with
-portions covered by various BSD-like licenses.
+Rust is primarily distributed under the terms of both the MIT license
+and the Apache License (Version 2.0), with portions covered by various
+BSD-like licenses.
-See LICENSE.txt for details.
+See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details.
## More help
| cut -d ' ' -f 2)
case $CFG_CLANG_VERSION in
- (3.0svn | 3.0 | 3.1 | 4.0 | 4.1)
+ (3.0svn | 3.0 | 3.1 | 3.2 | 4.0 | 4.1)
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
CFG_C_COMPILER="clang"
;;
do
make_dir rt/$t
for i in \
- isaac linenoise bigint sync test arch/i386 arch/x86_64 \
+ isaac linenoise sync test arch/i386 arch/x86_64 \
libuv libuv/src/ares libuv/src/eio libuv/src/ev
do
make_dir rt/$t/$i
then
msg "configuring LLVM for $t"
- LLVM_TARGETS="--enable-targets=x86,x86_64"
+ LLVM_TARGETS="--enable-targets=x86,x86_64,arm"
LLVM_BUILD="--build=$t"
LLVM_HOST="--host=$t"
LLVM_TARGET="--target=$t"
a = Cat;
~~~~
+Enumeration constructors can have either named or unnamed fields:
+~~~~
+enum Animal {
+ Dog (~str, float),
+ Cat { name: ~str, weight: float }
+}
+
+let mut a: Animal = Dog(~"Cocoa", 37.2);
+a = Cat{ name: ~"Spotty", weight: 2.7 };
+~~~~
+
+In this example, `Cat` is a _struct-like enum variant_,
+whereas `Dog` is simply called an enum variant.
### Constants
~~~~~~~~ {.ebnf .gram}
with the extension removed. In that case, to turn on logging for a program
compiled from, e.g. `helloworld.rs`, `RUST_LOG` should be set to `helloworld`.
-As a convenience, the logging spec can also be set to a special psuedo-crate,
+As a convenience, the logging spec can also be set to a special pseudo-crate,
`::help`. In this case, when the application starts, the runtime will
simply output a list of loaded modules containing log expressions, then exit.
The Rust runtime itself generates logging information. The runtime's logs are
-generated for a number of artificial modules in the `::rt` psuedo-crate,
+generated for a number of artificial modules in the `::rt` pseudo-crate,
and can be enabled just like the logs for any standard module. The full list
of runtime logging modules follows.
* The Newsqueak (1988), Alef (1995), and Limbo (1996) family. These
languages were developed by Rob Pike, Phil Winterbottom, Sean Dorward and
- others in their group at Bell labs Computing Sciences Research Center
+ others in their group at Bell Labs Computing Sciences Research Center
(Murray Hill, NJ, USA).
* The Napier (1985) and Napier88 (1988) family. These languages were
_ => {}
}
);
-);
+)
// ...
early_return!(input_1 special_a);
// ...
The right-hand side must be enclosed by delimiters, which are ignored by the
transcriber (therefore `() => ((1,2,3))` is a macro that expands to a tuple
expression, `() => (let $x=$val)` is a macro that expands to a statement, and
-`() => (1,2,3)` is a macro that expands to a syntax errror).
+`() => (1,2,3)` is a macro that expands to a syntax error).
Except for permissibility of `$name` (and `$(...)*`, discussed below), the
right-hand side of a macro definition is ordinary Rust syntax. In particular,
_ => {}
}
);
-);
+)
// ...
early_return!(input_1, [special_a|special_c|special_d]);
// ...
tutorials](#what-next) cover specific language features in greater
depth.
-This tutorial assumes that the reader is already familiar with one or more
+This tutorial assumes that the reader is already familiar with one or
more languages in the C family. Understanding of pointers and general
memory management techniques will help.
> "[getting started][wiki-start]" notes on the wiki. Even when using
> the binary installer, the Windows build requires a MinGW installation,
> the precise details of which are not discussed here. Finally, `rustc` may
-> need to be [referred to as `rustc.exe`][bug-3319]. It's a bummer, I
+> need to be [referred to as `rustc.exe`][bug-3319]. It's a bummer, we
> know.
[bug-3319]: https://github.com/mozilla/rust/issues/3319
When complete, `make install` will place several programs into
`/usr/local/bin`: `rustc`, the Rust compiler; `rustdoc`, the
-API-documentation tool, `cargo`, the Rust package manager,
+API-documentation tool; `cargo`, the Rust package manager;
and `rusti`, the Rust REPL.
[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust
for branching and looping, like the familiar `if` and `while`; function
calls are written `myfunc(arg1, arg2)`; operators are written the same
and mostly have the same precedence as in C; comments are again like C;
-module names are separated with double-colon, `::`, as with C++.
+module names are separated with double-colon (`::`) as with C++.
The main surface difference to be aware of is that the condition at
-the head of control structures like `if` and `while` do not require
+the head of control structures like `if` and `while` does not require
parentheses, while their bodies *must* be wrapped in
braces. Single-statement, unbraced bodies are not allowed.
~~~~
Local variables may shadow earlier declarations, as in the previous example:
-`monster_size` was first declared as a `float`, and then then a second
-`monster_size` was declared as an int. If you were to actually compile this
-example, though, the compiler will determine that the second `monster_size` is
+`monster_size` was first declared as a `float`, and then a second
+`monster_size` was declared as an `int`. If you were to actually compile this
+example, though, the compiler would determine that the first `monster_size` is
unused and issue a warning (because this situation is likely to indicate a
programmer error). For occasions where unused variables are intentional, their
-name may be prefixed with an underscore to silence the warning, like `let
+names may be prefixed with an underscore to silence the warning, like `let
_monster_size = 50;`.
Rust identifiers start with an alphabetic
was taken.
In short, everything that's not a declaration (declarations are `let` for
-variables, `fn` for functions, and any top-level named items such as
+variables; `fn` for functions; and any top-level named items such as
[traits](#traits), [enum types](#enums), and [constants](#constants)) is an
expression, including function bodies.
## Primitive types and literals
-There are general signed and unsigned integer types, `int`, and `uint`,
-as well as 8-, 16-, 32-, and 64-bit variations, `i8`, `u16`, etc.
+There are general signed and unsigned integer types, `int` and `uint`,
+as well as 8-, 16-, 32-, and 64-bit variants, `i8`, `u16`, etc.
Integers can be written in decimal (`144`), hexadecimal (`0x90`), or
binary (`0b10010000`) base. Each integral type has a corresponding literal
suffix that can be used to indicate the type of a literal: `i` for `int`,
let d = 1000i32; // d is an i32
~~~~
-There are three floating point types, `float`, `f32`, and `f64`.
-Floating point numbers are written `0.0`, `1e6`, or `2.1e-4`.
-Like integers, floating point literals are inferred to the correct type.
-Suffixes `f`, `f32` and `f64` can be used to create literals of a specific type.
+There are three floating-point types: `float`, `f32`, and `f64`.
+Floating-point numbers are written `0.0`, `1e6`, or `2.1e-4`.
+Like integers, floating-point literals are inferred to the correct type.
+Suffixes `f`, `f32`, and `f64` can be used to create literals of a specific type.
The keywords `true` and `false` produce literals of type `bool`.
-Characters, the `char` type, are 4-byte unicode codepoints,
+Characters, the `char` type, are four-byte Unicode codepoints,
whose literals are written between single quotes, as in `'x'`.
Just like C, Rust understands a number of character escapes, using the backslash
character, such as `\n`, `\r`, and `\t`. String literals,
## Operators
Rust's set of operators contains very few surprises. Arithmetic is done with
-`*`, `/`, `%`, `+`, and `-` (multiply, divide, take remainder, add, subtract). `-` is
-also a unary prefix operator that negates numbers. As in C, the bit operators
+`*`, `/`, `%`, `+`, and `-` (multiply, divide, take remainder, add, and subtract). `-` is
+also a unary prefix operator that negates numbers. As in C, the bitwise operators
`>>`, `<<`, `&`, `|`, and `^` are also supported.
Note that, if applied to an integer value, `!` flips all the bits (like `~` in
}
~~~~
-Unlike in C, there is no 'falling through' between arms: only one arm
+Unlike in C, there is no "falling through" between arms: only one arm
executes, and it doesn't have to explicitly `break` out of the
construct when it is finished.
A variable name in a pattern matches any value, *and* binds that name
to the value of the matched value inside of the arm's action. Thus, `(0f,
y)` matches any tuple whose first element is zero, and binds `y` to
-the second element. `(x, y)` matches any tuple, and binds both
+the second element. `(x, y)` matches any two-element tuple, and binds both
elements to variables.
Any `match` arm can have a guard clause (written `if EXPR`), called a
memory (so you can read from a Rust struct in C, and vice-versa). Use the dot
operator to access struct fields, as in `mypoint.x`.
-Fields that you want to mutate must be explicitly marked `mut`.
+Inherited mutability means that any field of a struct may be mutable, if the
+struct is in a mutable slot (or a field of a struct in a mutable slot, and
+so forth).
+
+A struct that is not mutable due to inherited mutability may declare some
+of its fields nevertheless mutable, using the `mut` keyword.
~~~~
struct Stack {
~~~~
With a value of such a type, you can do `mystack.head += 1`. If `mut` were
-omitted from the type, such an assignment would result in a type error.
+omitted from the type, such an assignment to a struct without inherited
+mutability would result in a type error.
`match` patterns destructure structs. The basic syntax is
-`Name {fieldname: pattern, ...}`:
+`Name { fieldname: pattern, ... }`:
~~~~
# struct Point { x: float, y: float }
In general, the field names of a struct do not have to appear in the same
order they appear in the type. When you are not interested in all
the fields of a struct, a struct pattern may end with `, _` (as in
-`Name {field1, _}`) to indicate that you're ignoring all other fields.
+`Name { field1, _ }`) to indicate that you're ignoring all other fields.
Additionally, struct fields have a shorthand matching form that simply
reuses the field name as the binding name.
`Point` struct and a float, or a `Rectangle`, in which case it contains
two `Point` structs. The run-time representation of such a value
includes an identifier of the actual form that it holds, much like the
-'tagged union' pattern in C, but with better static guarantees.
+"tagged union" pattern in C, but with better static guarantees.
The above declaration will define a type `Shape` that can refer to
such shapes, and two functions, `Circle` and `Rectangle`, which can be
used to construct values of the type (taking arguments of the
-specified types). So `Circle(Point {x: 0f, y: 0f}, 10f)` is the way to
+specified types). So `Circle(Point { x: 0f, y: 0f }, 10f)` is the way to
create a new circle.
-Enum variants need not have type parameters. This `enum` declaration,
+Enum variants need not have parameters. This `enum` declaration,
for example, is equivalent to a C enum:
~~~~
the value of `North` is 0, `East` is 1, `South` is 2, and `West` is 3.
When an enum is C-like, you can apply the `as` cast operator to
-convert it to its discriminator value as an int.
+convert it to its discriminator value as an `int`.
<a name="single_variant_enum"></a>
fn area(sh: Shape) -> float {
match sh {
Circle(_, size) => float::consts::pi * size * size,
- Rectangle(Point {x, y}, Point {x: x2, y: y2}) => (x2 - x) * (y2 - y)
+ Rectangle(Point { x, y }, Point { x: x2, y: y2 }) => (x2 - x) * (y2 - y)
}
}
~~~~
parentheses.
~~~~
-# struct Point {x: float, y: float}
+# struct Point { x: float, y: float }
# enum Direction { North, East, South, West }
fn point_from_direction(dir: Direction) -> Point {
match dir {
- North => Point {x: 0f, y: 1f},
- East => Point {x: 1f, y: 0f},
- South => Point {x: 0f, y: -1f},
- West => Point {x: -1f, y: 0f}
+ North => Point { x: 0f, y: 1f },
+ East => Point { x: 1f, y: 0f },
+ South => Point { x: 0f, y: -1f },
+ West => Point { x: -1f, y: 0f }
+ }
+}
+~~~~
+
+Enum variants may also be structs. For example:
+
+~~~~
+# use core::float;
+# struct Point { x: float, y: float }
+# fn square(x: float) -> float { x * x }
+enum Shape {
+ Circle { center: Point, radius: float },
+ Rectangle { top_left: Point, bottom_right: Point }
+}
+fn area(sh: Shape) -> float {
+ match sh {
+ Circle { radius: radius, _ } => float::consts::pi * square(radius),
+ Rectangle { top_left: top_left, bottom_right: bottom_right } => {
+ (bottom_right.x - top_left.x) * (bottom_right.y - top_left.y)
+ }
}
}
~~~~
The `return` keyword immediately returns from the body of a function. It
is optionally followed by an expression to return. A function can
-also return a value by having its top level block produce an
+also return a value by having its top-level block produce an
expression.
~~~~
As with `match` expressions and `let` bindings, function arguments support
pattern destructuring. Like `let`, argument patterns must be irrefutable,
-as in this example that unpacks a tuple and returns it.
+as in this example that unpacks the first value from a tuple and returns it.
~~~
fn first((value, _): (int, float)) -> int { value }
~~~
-
-# The Rust memory model
-
-At this junction, let's take a detour to explain the concepts involved
-in Rust's memory model. We've seen some of Rust's pointer sigils (`@`,
-`~`, and `&`) float by in a few examples, and we aren't going to get
-much further without explaining them. Rust has a very particular
-approach to memory management that plays a significant role in shaping
-the subjective experience of programming in the
-language. Understanding the memory landscape will illuminate several
-of Rust's unique features as we encounter them.
-
-Rust has three competing goals that inform its view of memory:
-
-* Memory safety: Memory that the Rust language can observe must be
- guaranteed to be valid. Under normal circumstances, it must be
- impossible for Rust to trigger a segmentation fault or leak memory.
-* Performance: High-performance low-level code must be able to use
- a number of different allocation strategies. Tracing garbage collection must be
- optional and, if it is not desired, memory safety must not be compromised.
- Less performance-critical, high-level code should be able to employ a single,
- garbage-collection-based, heap allocation strategy.
-* Concurrency: Rust code must be free of in-memory data races. (Note that other
- types of races are still possible.)
-
-## How performance considerations influence the memory model
-
-Most languages that offer strong memory safety guarantees rely on a
-garbage-collected heap to manage all of the objects. This approach is
-straightforward both in concept and in implementation, but has
-significant costs. Languages that follow this path tend to
-aggressively pursue ways to ameliorate allocation costs (think the
-Java Virtual Machine). Rust supports this strategy with _managed
-boxes_: memory allocated on the heap whose lifetime is managed
-by the garbage collector.
-
-By comparison, languages like C++ offer very precise control over
-where objects are allocated. In particular, it is common to allocate them
-directly on the stack, avoiding expensive heap allocation. In Rust
-this is possible as well, and the compiler uses a [clever _pointer
-lifetime analysis_][borrow] to ensure that no variable can refer to stack
-objects after they are destroyed.
-
-[borrow]: tutorial-borrowed-ptr.html
-
-## How concurrency considerations influence the memory model
-
-Memory safety in a concurrent environment involves avoiding race
-conditions between two threads of execution accessing the same
-memory. Even high-level languages often require programmers to make
-correct use of locking to ensure that a program is free of races.
-
-Rust starts from the position that memory cannot be shared between
-tasks. Experience in other languages has proven that isolating each
-task's heap from the others is a reliable strategy and one that is
-easy for programmers to reason about. Heap isolation has the
-additional benefit that garbage collection must only be done
-per-heap. Rust never "stops the world" to reclaim memory.
-
-Complete isolation of heaps between tasks would, however, mean that
-any data transferred between tasks must be copied. While this is a
-fine and useful way to implement communication between tasks, it is
-also very inefficient for large data structures. To reduce the amount
-of copying, Rust also uses a global _exchange heap_. Objects allocated
-in the exchange heap have _ownership semantics_, meaning that there is
-only a single variable that refers to them. For this reason, they are
-referred to as _owned boxes_. All tasks may allocate objects on the
-exchange heap, then transfer ownership of those objects to other
-tasks, avoiding expensive copies.
-
# Boxes and pointers
Many modern languages have a so-called "uniform representation" for
as pointers to heap memory by default. In contrast, Rust, like C and
C++, represents such types directly. Another way to say this is that
aggregate data in Rust are *unboxed*. This means that if you `let x =
-Point {x: 1f, y: 1f};`, you are creating a struct on the stack. If you
+Point { x: 1f, y: 1f };`, you are creating a struct on the stack. If you
then copy it into a data structure, you copy the entire struct, not
just a pointer.
the stack or on the heap, and refer to that through a pointer.
Rust supports several types of pointers. The safe pointer types are
-`@T` for managed boxes allocated on the local heap, `~T`, for
+`@T`, for managed boxes allocated on the local heap, `~T`, for
uniquely-owned boxes allocated on the exchange heap, and `&T`, for
borrowed pointers, which may point to any memory, and whose lifetimes
are governed by the call stack.
## Managed boxes
-Managed boxes are pointers to heap-allocated, garbage collected
-memory. Applying the unary `@` operator to an expression creates a
+Managed boxes are pointers to heap-allocated, garbage-collected
+memory. Applying the unary `@` operator to an expression creates a
managed box. The resulting box contains the result of the
expression. Copying a managed box, as happens during assignment, only
copies a pointer, never the contents of the box.
~~~
struct Point {
- x: float, y: float
+ x: float,
+ y: float
}
~~~~
~~~
# struct Point { x: float, y: float }
-let on_the_stack : Point = Point {x: 3.0, y: 4.0};
-let managed_box : @Point = @Point {x: 5.0, y: 1.0};
-let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};
+let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
+let managed_box : @Point = @Point { x: 5.0, y: 1.0 };
+let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
~~~
Suppose we wanted to write a procedure that computed the distance
~~~
# struct Point{ x: float, y: float };
-# let on_the_stack : Point = Point {x: 3.0, y: 4.0};
-# let managed_box : @Point = @Point {x: 5.0, y: 1.0};
-# let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};
+# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
+# let managed_box : @Point = @Point { x: 5.0, y: 1.0 };
+# let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }
compute_distance(&on_the_stack, managed_box);
compute_distance(managed_box, owned_box);
`on_the_stack`; this is because `on_the_stack` has the type `Point`
(that is, a struct value) and we have to take its address to get a
value. We also call this _borrowing_ the local variable
-`on_the_stack`, because we are created an alias: that is, another
+`on_the_stack`, because we are creating an alias: that is, another
route to the same data.
In the case of the boxes `managed_box` and `owned_box`, however, no
explicit action is necessary. The compiler will automatically convert
a box like `@point` or `~point` to a borrowed pointer like
`&point`. This is another form of borrowing; in this case, the
-contents of the managed/owned box is being lent out.
+contents of the managed/owned box are being lent out.
Whenever a value is borrowed, there are some limitations on what you
can do with the original. For example, if the contents of a variable
~~~
To combat this ugliness the dot operator applies _automatic pointer
-dereferencing_ to the receiver (the value on the left hand side of the
+dereferencing_ to the receiver (the value on the left-hand side of the
dot), so in most cases, explicitly dereferencing the receiver is not necessary.
~~~
// A fixed-size stack vector
let stack_crayons: [Crayon * 3] = [Almond, AntiqueBrass, Apricot];
-// A borrowed pointer to stack allocated vector
+// A borrowed pointer to stack-allocated vector
let stack_crayons: &[Crayon] = &[Aquamarine, Asparagus, AtomicTangerine];
// A local heap (managed) vector of crayons
vectors, though the string literal without a storage sigil (for
example, `"foo"`) is treated differently than a comparable vector
(`[foo]`). Whereas plain vectors are stack-allocated fixed-length
-vectors, plain strings are region pointers to read-only
+vectors, plain strings are borrowed pointers to read-only (static)
memory. All strings are immutable.
~~~
}
~~~~
-Look at all those bars and parentheses - that's two empty argument
+Look at all those bars and parentheses -- that's two empty argument
lists back to back. Since that is so unsightly, empty argument lists
may be omitted from `do` expressions.
~~~~
Notice that, because `each` passes each value by borrowed pointer,
-the iteratee needs to dereference it before using.
+the iteratee needs to dereference it before using it.
In these situations it can be convenient to lean on Rust's
argument patterns to bind `x` to the actual value, not the pointer.
// ... and dereferenced
(& &s).draw_borrowed();
-// ... and dereferenced, and borrowed, and
+// ... and dereferenced and borrowed
(&@~s).draw_borrowed();
~~~
(capitalized by convention) stand for opaque types. All you can do
with instances of these types is pass them around: you can't apply any
operations to them or pattern-match on them. Note that instances of
-generic types are often passed by pointer. For example, the parameter
+generic types are often passed by pointer. For example, the parameter
`function()` is supplied with a pointer to a value of type `T` and not
-a value of type `T` itself. This ensures that the function works with
+a value of type `T` itself. This ensures that the function works with
the broadest set of types possible, since some types are expensive or
illegal to copy and pass by value.
~~~~
These declarations can be instantiated to valid types like `Set<int>`,
-`Stack<int>` and `Option<int>`.
+`Stack<int>`, and `Option<int>`.
The last type in that example, `Option`, appears frequently in Rust code.
Because Rust does not have null pointers (except in unsafe code), we need
a function that returns `Option<T>` instead of `T`.
~~~~
-# struct Point {x: float, y: float}
+# struct Point { x: float, y: float }
# enum Shape { Circle(Point, float), Rectangle(Point, Point) }
fn radius(shape: Shape) -> Option<float> {
- match shape {
- Circle(_, radius) => Some(radius),
- Rectangle(*) => None
- }
+ match shape {
+ Circle(_, radius) => Some(radius),
+ Rectangle(*) => None
+ }
}
~~~~
traits are automatically derived and implemented for all applicable
types by the compiler, and may not be overridden:
-* `Copy` - Types that can be copied: either implicitly, or explicitly with the
+* `Copy` - Types that can be copied, either implicitly, or explicitly with the
`copy` operator. All types are copyable unless they have destructors or
contain types with destructors.
* `Owned` - Owned types. Types are owned unless they contain managed
- boxes, managed closures, or borrowed pointers. Owned types may or
+ boxes, managed closures, or borrowed pointers. Owned types may or
may not be copyable.
* `Const` - Constant (immutable) types. These are types that do not contain
~~~
struct TimeBomb {
- explosivity: uint,
+ explosivity: uint
}
impl TimeBomb : Drop {
Traits may be implemented for specific types with [impls]. An impl
that implements a trait includes the name of the trait at the start of
the definition, as in the following impls of `Printable` for `int`
-and `~str`.
+and `&str`.
[impls]: #functions-and-methods
// In a trait, `self` refers both to the self argument
// and to the type implementing the trait
trait Eq {
- fn equals(&self, other: &self) -> bool;
+ fn equals(&self, other: &self) -> bool;
}
// In an impl, `self` refers just to the value of the receiver
impl int: Eq {
- fn equals(&self, other: &int) -> bool { *other == *self }
+ fn equals(&self, other: &int) -> bool { *other == *self }
}
~~~~
static fn new(area: float) -> Circle { Circle { radius: sqrt(area / pi) } }
}
impl Square: Shape {
- static fn new(area: float) -> Square { Square { length: sqrt(area) } }
+ static fn new(area: float) -> Square { Square { length: sqrt(area) } }
}
let area = 42.5;
# draw_all(~[c]);
~~~~
-You can call that on an array of circles, or an array of squares
+You can call that on an array of circles, or an array of rectangles
(assuming those have suitable `Drawable` traits defined), but not on
-an array containing both circles and squares. When such behavior is
+an array containing both circles and rectangles. When such behavior is
needed, a trait name can alternately be used as a type, called
an _object_.
# fn square(x: float) -> float { x * x }
struct CircleStruct { center: Point, radius: float }
impl CircleStruct: Circle {
- fn radius(&self) -> float { sqrt(self.area() / pi) }
+ fn radius(&self) -> float { sqrt(self.area() / pi) }
}
impl CircleStruct: Shape {
- fn area(&self) -> float { pi * square(self.radius) }
+ fn area(&self) -> float { pi * square(self.radius) }
}
~~~~
~~~
These farm animal functions have a new keyword, `pub`, attached to
-them. The `pub` keyword modifies an item's visibility, making it
+them. The `pub` keyword modifies an item's visibility, making it
visible outside its containing module. An expression with `::`, like
`farm::chicken`, can name an item outside of its containing
module. Items, such as those declared with `fn`, `struct`, `enum`,
is quite different from most object-oriented languages that also
enforce restrictions on objects themselves. That's not to say that
Rust doesn't support encapsulation: both struct fields and methods can
-be private. But this encapsulation is at the module level, not the
+be private. But this encapsulation is at the module level, not the
struct level. Note that fields and methods are _public_ by default.
~~~
mod farm {
+# use farm;
+# pub type Chicken = int;
+# type Cow = int;
+# enum Human = int;
+# impl Human { fn rest(&self) { } }
# pub fn make_me_a_farm() -> farm::Farm { farm::Farm { chickens: ~[], cows: ~[], farmer: Human(0) } }
pub struct Farm {
priv mut chickens: ~[Chicken],
farm::feed_animals(&f);
f.farmer.rest();
}
-# type Chicken = int;
-# type Cow = int;
-# enum Human = int;
# fn make_me_a_farm() -> farm::Farm { farm::make_me_a_farm() }
-# fn make_me_a_chicken() -> Chicken { 0 }
-# impl Human { fn rest(&self) { } }
+# fn make_me_a_chicken() -> farm::Chicken { 0 }
~~~
## Crates
The unit of independent compilation in Rust is the crate: rustc
compiles a single crate at a time, from which it produces either a
-library or executable.
+library or an executable.
When compiling a single `.rs` source file, the file acts as the whole crate.
You can compile it with the `--lib` compiler switch to create a shared
`cow.rs`, `chicken.rs`, and `horse.rs` in the same directory as the
`.rc` file, compile them all together, and, based on the presence of
the `crate_type = "lib"` attribute, output a shared library or an
-executable. (If the line `#[crate_type = "lib"];` was omitted,
+executable. (If the line `#[crate_type = "lib"];` was omitted,
`rustc` would create an executable.)
The `#[link(...)]` attribute provides meta information about the
doc/rust.g: rust.md $(S)src/etc/extract_grammar.py
@$(call E, extract_grammar: $@)
- $(Q)$(S)src/etc/extract_grammar.py $< >$@
+ $(Q)$(CFG_PYTHON) $(S)src/etc/extract_grammar.py $< >$@
verify-grammar: doc/rust.g
@$(call E, LLnextgen: $<)
--- /dev/null
+# We borrow heavily from the kernel build setup, though we are simpler since
+# we don't have Kconfig tweaking settings on us.
+
+# The implicit make rules have it looking for RCS files, among other things.
+# We instead explicitly write all the rules we care about.
+# It's even quicker (saves ~200ms) to pass -r on the command line.
+MAKEFLAGS=-r
+
+# The source directory tree.
+srcdir := ../../../../..
+abs_srcdir := $(abspath $(srcdir))
+
+# The name of the builddir.
+builddir_name ?= out
+
+# The V=1 flag on command line makes us verbosely print command lines.
+ifdef V
+ quiet=
+else
+ quiet=quiet_
+endif
+
+# Specify BUILDTYPE=Release on the command line for a release build.
+BUILDTYPE ?= Debug
+
+# Directory all our build output goes into.
+# Note that this must be two directories beneath src/ for unit tests to pass,
+# as they reach into the src/ directory for data with relative paths.
+builddir ?= $(builddir_name)/$(BUILDTYPE)
+abs_builddir := $(abspath $(builddir))
+depsdir := $(builddir)/.deps
+
+# Object output directory.
+obj := $(builddir)/obj
+abs_obj := $(abspath $(obj))
+
+# We build up a list of every single one of the targets so we can slurp in the
+# generated dependency rule Makefiles in one pass.
+all_deps :=
+
+
+
+# C++ apps need to be linked with g++.
+#
+# Note: flock is used to seralize linking. Linking is a memory-intensive
+# process so running parallel links can often lead to thrashing. To disable
+# the serialization, override LINK via an envrionment variable as follows:
+#
+# export LINK=g++
+#
+# This will allow make to invoke N linker processes as specified in -jN.
+LINK ?= flock $(builddir)/linker.lock $(CXX)
+
+CC.target ?= $(CC)
+CFLAGS.target ?= $(CFLAGS)
+CXX.target ?= $(CXX)
+CXXFLAGS.target ?= $(CXXFLAGS)
+LINK.target ?= $(LINK)
+LDFLAGS.target ?= $(LDFLAGS)
+AR.target ?= $(AR)
+ARFLAGS.target ?= crsT
+
+# N.B.: the logic of which commands to run should match the computation done
+# in gyp's make.py where ARFLAGS.host etc. is computed.
+# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
+# to replicate this environment fallback in make as well.
+CC.host ?= gcc
+CFLAGS.host ?=
+CXX.host ?= g++
+CXXFLAGS.host ?=
+LINK.host ?= g++
+LDFLAGS.host ?=
+AR.host ?= ar
+ARFLAGS.host := crs
+
+# Define a dir function that can handle spaces.
+# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
+# "leading spaces cannot appear in the text of the first argument as written.
+# These characters can be put into the argument value by variable substitution."
+empty :=
+space := $(empty) $(empty)
+
+# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
+replace_spaces = $(subst $(space),?,$1)
+unreplace_spaces = $(subst ?,$(space),$1)
+dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
+
+# Flags to make gcc output dependency info. Note that you need to be
+# careful here to use the flags that ccache and distcc can understand.
+# We write to a dep file on the side first and then rename at the end
+# so we can't end up with a broken dep file.
+depfile = $(depsdir)/$(call replace_spaces,$@).d
+DEPFLAGS = -MMD -MF $(depfile).raw
+
+# We have to fixup the deps output in a few ways.
+# (1) the file output should mention the proper .o file.
+# ccache or distcc lose the path to the target, so we convert a rule of
+# the form:
+# foobar.o: DEP1 DEP2
+# into
+# path/to/foobar.o: DEP1 DEP2
+# (2) we want missing files not to cause us to fail to build.
+# We want to rewrite
+# foobar.o: DEP1 DEP2 \
+# DEP3
+# to
+# DEP1:
+# DEP2:
+# DEP3:
+# so if the files are missing, they're just considered phony rules.
+# We have to do some pretty insane escaping to get those backslashes
+# and dollar signs past make, the shell, and sed at the same time.
+# Doesn't work with spaces, but that's fine: .d files have spaces in
+# their names replaced with other characters.
+define fixup_dep
+# The depfile may not exist if the input file didn't have any #includes.
+touch $(depfile).raw
+# Fixup path as in (1).
+sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
+# Add extra rules as in (2).
+# We remove slashes and replace spaces with new lines;
+# remove blank lines;
+# delete the first line and append a colon to the remaining lines.
+sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
+ grep -v '^$$' |\
+ sed -e 1d -e 's|$$|:|' \
+ >> $(depfile)
+rm $(depfile).raw
+endef
+
+# Command definitions:
+# - cmd_foo is the actual command to run;
+# - quiet_cmd_foo is the brief-output summary of the command.
+
+quiet_cmd_cc = CC($(TOOLSET)) $@
+cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
+
+quiet_cmd_cxx = CXX($(TOOLSET)) $@
+cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+
+quiet_cmd_touch = TOUCH $@
+cmd_touch = touch $@
+
+quiet_cmd_copy = COPY $@
+# send stderr to /dev/null to ignore messages when linking directories.
+cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
+
+quiet_cmd_alink = AR($(TOOLSET)) $@
+cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
+
+# Due to circular dependencies between libraries :(, we wrap the
+# special "figure out circular dependencies" flags around the entire
+# input list during linking.
+quiet_cmd_link = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
+
+# We support two kinds of shared objects (.so):
+# 1) shared_library, which is just bundling together many dependent libraries
+# into a link line.
+# 2) loadable_module, which is generating a module intended for dlopen().
+#
+# They differ only slightly:
+# In the former case, we want to package all dependent code into the .so.
+# In the latter case, we want to package just the API exposed by the
+# outermost module.
+# This means shared_library uses --whole-archive, while loadable_module doesn't.
+# (Note that --whole-archive is incompatible with the --start-group used in
+# normal linking.)
+
+# Other shared-object link notes:
+# - Set SONAME to the library filename so our binaries don't reference
+# the local, absolute paths used on the link command-line.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
+
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
+
+
+# Define an escape_quotes function to escape single quotes.
+# This allows us to handle quotes properly as long as we always use
+# use single quotes and escape_quotes.
+escape_quotes = $(subst ','\'',$(1))
+# This comment is here just to include a ' to unconfuse syntax highlighting.
+# Define an escape_vars function to escape '$' variable syntax.
+# This allows us to read/write command lines with shell variables (e.g.
+# $LD_LIBRARY_PATH), without triggering make substitution.
+escape_vars = $(subst $$,$$$$,$(1))
+# Helper that expands to a shell command to echo a string exactly as it is in
+# make. This uses printf instead of echo because printf's behaviour with respect
+# to escape sequences is more portable than echo's across different shells
+# (e.g., dash, bash).
+exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
+
+# Helper to compare the command we're about to run against the command
+# we logged the last time we ran the command. Produces an empty
+# string (false) when the commands match.
+# Tricky point: Make has no string-equality test function.
+# The kernel uses the following, but it seems like it would have false
+# positives, where one string reordered its arguments.
+# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
+# $(filter-out $(cmd_$@), $(cmd_$(1))))
+# We instead substitute each for the empty string into the other, and
+# say they're equal if both substitutions produce the empty string.
+# .d files contain ? instead of spaces, take that into account.
+command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
+ $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
+
+# Helper that is non-empty when a prerequisite changes.
+# Normally make does this implicitly, but we force rules to always run
+# so we can check their command lines.
+# $? -- new prerequisites
+# $| -- order-only dependencies
+prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
+
+# Helper that executes all postbuilds, and deletes the output file when done
+# if any of the postbuilds failed.
+define do_postbuilds
+ @E=0;\
+ for p in $(POSTBUILDS); do\
+ eval $$p;\
+ F=$$?;\
+ if [ $$F -ne 0 ]; then\
+ E=$$F;\
+ fi;\
+ done;\
+ if [ $$E -ne 0 ]; then\
+ rm -rf "$@";\
+ exit $$E;\
+ fi
+endef
+
+# do_cmd: run a command via the above cmd_foo names, if necessary.
+# Should always run for a given target to handle command-line changes.
+# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
+# Third argument, if non-zero, makes it do POSTBUILDS processing.
+# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
+# spaces already and dirx strips the ? characters.
+define do_cmd
+$(if $(or $(command_changed),$(prereq_changed)),
+ @$(call exact_echo, $($(quiet)cmd_$(1)))
+ @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
+ $(if $(findstring flock,$(word 1,$(cmd_$1))),
+ @$(cmd_$(1))
+ @echo " $(quiet_cmd_$(1)): Finished",
+ @$(cmd_$(1))
+ )
+ @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
+ @$(if $(2),$(fixup_dep))
+ $(if $(and $(3), $(POSTBUILDS)),
+ $(call do_postbuilds)
+ )
+)
+endef
+
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
+.PHONY: all
+all:
+
+# Use FORCE_DO_CMD to force a target to run. Should be coupled with
+# do_cmd.
+.PHONY: FORCE_DO_CMD
+FORCE_DO_CMD:
+
+TOOLSET := target
+# Suffix rules, putting all outputs into $(obj).
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# Try building from generated source, too.
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+
+ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
+ $(findstring $(join ^,$(prefix)),\
+ $(join ^,src/libuv/run-benchmarks.target.mk)))),)
+ include src/libuv/run-benchmarks.target.mk
+endif
+ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
+ $(findstring $(join ^,$(prefix)),\
+ $(join ^,src/libuv/run-tests.target.mk)))),)
+ include src/libuv/run-tests.target.mk
+endif
+ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
+ $(findstring $(join ^,$(prefix)),\
+ $(join ^,src/libuv/uv.target.mk)))),)
+ include src/libuv/uv.target.mk
+endif
+
+#quiet_cmd_regen_makefile = ACTION Regenerating $@
+#cmd_regen_makefile = ./src/libuv/build/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -Isrc/libuv/common.gypi "--depth=." "--generator-output=mk/libuv/arm/unix/android" "-Ddefault_configuration=Default" "-Dcomponent=static_library" "-Dlibrary=static_library" "-Dtarget_arch=arm" "-DOS=linux" src/libuv/uv.gyp
+#Makefile: $(srcdir)/src/libuv/uv.gyp $(srcdir)/src/libuv/common.gypi
+# $(call do_cmd,regen_makefile)
+
+# "all" is a concatenation of the "all" targets from all the included
+# sub-makefiles. This is just here to clarify.
+all:
+
+# Add in dependency-tracking rules. $(all_deps) is the list of every single
+# target in our tree. Only consider the ones with .d (dependency) info:
+d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
+ifneq ($(d_files),)
+ # Rather than include each individual .d file, concatenate them into a
+ # single file which make is able to load faster. We split this into
+ # commands that take 1000 files at a time to avoid overflowing the
+ # command line.
+ $(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
+
+ ifneq ($(word 1001,$(d_files)),)
+ $(error Found unprocessed dependency files (gyp didn't generate enough rules!))
+ endif
+
+ # make looks for ways to re-generate included makefiles, but in our case, we
+ # don't have a direct way. Explicitly telling make that it has nothing to do
+ # for them makes it go faster.
+ $(depsdir)/all.deps: ;
+
+ include $(depsdir)/all.deps
+endif
--- /dev/null
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := run-benchmarks
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_GNU_SOURCE' \
+ '-DEIO_STACKSIZE=262144' \
+ '-DDEBUG' \
+ '-D_DEBUG' \
+ '-DEV_VERIFY=2'
+
+# Flags passed to all source files.
+CFLAGS_Debug := \
+ -Wall \
+ -ansi \
+ -fvisibility=hidden \
+ -g \
+ -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := -fno-rtti \
+ -fno-exceptions
+
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_GNU_SOURCE' \
+ '-DEIO_STACKSIZE=262144' \
+ '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := \
+ -Wall \
+ -ansi \
+ -fvisibility=hidden \
+ -O3 \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+ -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include
+
+OBJS := $(obj).target/$(TARGET)/src/libuv/test/benchmark-ares.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-getaddrinfo.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-ping-pongs.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-pound.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-pump.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-sizes.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-spawn.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-thread.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-tcp-write-batch.o \
+ $(obj).target/$(TARGET)/src/libuv/test/benchmark-udp-packet-storm.o \
+ $(obj).target/$(TARGET)/src/libuv/test/dns-server.o \
+ $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
+ $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
+ $(obj).target/$(TARGET)/src/libuv/test/run-benchmarks.o \
+ $(obj).target/$(TARGET)/src/libuv/test/runner.o \
+ $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# Make sure our dependencies are built before any of us.
+$(OBJS): | $(obj).target/src/libuv/libuv.a
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+
+$(builddir)/run-benchmarks: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(builddir)/run-benchmarks: LIBS := $(LIBS)
+$(builddir)/run-benchmarks: LD_INPUTS := $(OBJS) $(obj).target/src/libuv/libuv.a
+$(builddir)/run-benchmarks: TOOLSET := $(TOOLSET)
+$(builddir)/run-benchmarks: $(OBJS) $(obj).target/src/libuv/libuv.a FORCE_DO_CMD
+ $(call do_cmd,link)
+
+all_deps += $(builddir)/run-benchmarks
+# Add target alias
+.PHONY: run-benchmarks
+run-benchmarks: $(builddir)/run-benchmarks
+
+# Add executable to "all" target.
+.PHONY: all
+all: $(builddir)/run-benchmarks
+
--- /dev/null
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := run-tests
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_GNU_SOURCE' \
+ '-DEIO_STACKSIZE=262144' \
+ '-DDEBUG' \
+ '-D_DEBUG' \
+ '-DEV_VERIFY=2'
+
+# Flags passed to all source files.
+CFLAGS_Debug := \
+ -Wall \
+ -ansi \
+ -fvisibility=hidden \
+ -g \
+ -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := -fno-rtti \
+ -fno-exceptions
+
+INCS_Debug := -I$(srcdir)/src/libuv/include
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_GNU_SOURCE' \
+ '-DEIO_STACKSIZE=262144' \
+ '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := \
+ -Wall \
+ -ansi \
+ -fvisibility=hidden \
+ -O3 \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+ -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include
+
+OBJS := $(obj).target/$(TARGET)/src/libuv/test/blackhole-server.o \
+ $(obj).target/$(TARGET)/src/libuv/test/echo-server.o \
+ $(obj).target/$(TARGET)/src/libuv/test/run-tests.o \
+ $(obj).target/$(TARGET)/src/libuv/test/runner.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-get-loadavg.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-util.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-async.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-callback-stack.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-connection-fail.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-cwd-and-chdir.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-delayed-accept.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-eio-overflow.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-fail-always.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-fs.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-fs-event.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-get-currentexe.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-get-memory.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-getaddrinfo.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-gethostbyname.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-getsockname.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-hrtime.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-idle.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-ipc.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-ipc-threads.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-loop-handles.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-multiple-listen.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-pass-always.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-ping-pong.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-pipe-bind-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-pipe-connect-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-platform-output.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-process-title.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-ref.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-shutdown-eof.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-spawn.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-stdio-over-pipes.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-bind-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-bind6-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-close.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-flags.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-connect-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-connect6-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-error.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-write-to-half-open-connection.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tcp-writealot.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-threadpool.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-mutexes.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-thread.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-timer-again.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-timer.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-tty.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-udp-dgram-too-big.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-udp-ipv6.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-udp-options.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-udp-send-and-recv.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-udp-multicast-join.o \
+ $(obj).target/$(TARGET)/src/libuv/test/test-counters-init.o \
+ $(obj).target/$(TARGET)/src/libuv/test/runner-unix.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# Make sure our dependencies are built before any of us.
+$(OBJS): | $(obj).target/src/libuv/libuv.a
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+
+$(builddir)/run-tests: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(builddir)/run-tests: LIBS := $(LIBS)
+$(builddir)/run-tests: LD_INPUTS := $(OBJS) $(obj).target/src/libuv/libuv.a
+$(builddir)/run-tests: TOOLSET := $(TOOLSET)
+$(builddir)/run-tests: $(OBJS) $(obj).target/src/libuv/libuv.a FORCE_DO_CMD
+ $(call do_cmd,link)
+
+all_deps += $(builddir)/run-tests
+# Add target alias
+.PHONY: run-tests
+run-tests: $(builddir)/run-tests
+
+# Add executable to "all" target.
+.PHONY: all
+all: $(builddir)/run-tests
+
--- /dev/null
+# This file is generated by gyp; do not edit.
+
+export builddir_name ?= mk/libuv/arm/unix/android/./src/libuv/out
+.PHONY: all
+all:
+ $(MAKE) -C ../.. uv run-benchmarks run-tests
--- /dev/null
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := uv
+DEFS_Debug := '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_GNU_SOURCE' \
+ '-DEIO_STACKSIZE=262144' \
+ '-DHAVE_CONFIG_H' \
+ '-DEV_CONFIG_H="config_android.h"' \
+ '-DEIO_CONFIG_H="config_android.h"' \
+ '-DDEBUG' \
+ '-D_DEBUG' \
+ '-DEV_VERIFY=2'
+
+# Flags passed to all source files.
+CFLAGS_Debug := \
+ -Wall \
+ -ansi \
+ -fvisibility=hidden \
+ -g \
+ --std=gnu89 \
+ -pedantic \
+ -Wall \
+ -Wextra \
+ -Wno-unused-parameter \
+ -g \
+ -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := -fno-rtti \
+ -fno-exceptions
+
+INCS_Debug := -I$(srcdir)/src/libuv/include \
+ -I$(srcdir)/src/libuv/include/uv-private \
+ -I$(srcdir)/src/libuv/src \
+ -I$(srcdir)/src/libuv/src/unix/ev \
+ -I$(srcdir)/src/libuv/src/ares/config_android
+
+DEFS_Release := '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_GNU_SOURCE' \
+ '-DEIO_STACKSIZE=262144' \
+ '-DHAVE_CONFIG_H' \
+ '-DEV_CONFIG_H="config_android.h"' \
+ '-DEIO_CONFIG_H="config_android.h"' \
+ '-DNDEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Release := \
+ -Wall \
+ -ansi \
+ -fvisibility=hidden \
+ -g \
+ --std=gnu89 \
+ -pedantic \
+ -Wall \
+ -Wextra \
+ -Wno-unused-parameter \
+ -O3 \
+ -fomit-frame-pointer \
+ -fdata-sections \
+ -ffunction-sections
+
+# Flags passed to only C files.
+CFLAGS_C_Release :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := -fno-rtti \
+ -fno-exceptions
+
+INCS_Release := -I$(srcdir)/src/libuv/include \
+ -I$(srcdir)/src/libuv/include/uv-private \
+ -I$(srcdir)/src/libuv/src \
+ -I$(srcdir)/src/libuv/src/unix/ev \
+ -I$(srcdir)/src/libuv/src/ares/config_android
+
+OBJS := $(obj).target/$(TARGET)/src/libuv/src/uv-common.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_cancel.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares__close_sockets.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_data.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_destroy.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_expand_name.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_expand_string.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_fds.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_free_hostent.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_free_string.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_gethostbyaddr.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_gethostbyname.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares__get_hostent.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getnameinfo.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getopt.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_getsock.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_init.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_library_init.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_llist.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_mkquery.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_nowarn.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_options.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_aaaa_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_a_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_mx_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_ns_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_ptr_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_srv_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_parse_txt_reply.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_process.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_query.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares__read_line.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_search.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_send.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strcasecmp.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strdup.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_strerror.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_timeout.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares__timeval.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_version.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/ares_writev.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/bitncmp.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/inet_net_pton.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/inet_ntop.o \
+ $(obj).target/$(TARGET)/src/libuv/src/ares/windows_port.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/core.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/uv-eio.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/fs.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/udp.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/tcp.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/pipe.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/tty.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/stream.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/cares.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/dl.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/error.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/thread.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/process.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/eio/eio.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/ev/ev.o \
+ $(obj).target/$(TARGET)/src/libuv/src/unix/linux.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+
+LIBS := -lm
+
+$(obj).target/src/libuv/libuv.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(obj).target/src/libuv/libuv.a: LIBS := $(LIBS)
+$(obj).target/src/libuv/libuv.a: TOOLSET := $(TOOLSET)
+$(obj).target/src/libuv/libuv.a: $(OBJS) FORCE_DO_CMD
+ $(call do_cmd,alink)
+
+all_deps += $(obj).target/src/libuv/libuv.a
+# Add target alias
+.PHONY: uv
+uv: $(obj).target/src/libuv/libuv.a
+
+# Add target alias to "all" target.
+.PHONY: all
+all: uv
+
ifdef CFG_INSTALL_SNAP
snap-stage$(1)-H-$(2): $$(HSREQ$(1)_H_$(2))
- $(S)src/etc/make-snapshot.py stage$(1) $(2) install
+ $(CFG_PYTHON) $(S)src/etc/make-snapshot.py stage$(1) $(2) install
else
snap-stage$(1)-H-$(2): $$(HSREQ$(1)_H_$(2))
- $(S)src/etc/make-snapshot.py stage$(1) $(2)
+ $(CFG_PYTHON) $(S)src/etc/make-snapshot.py stage$(1) $(2)
endif
endef
snap-stage2: snap-stage2-H-$(CFG_HOST_TRIPLE)
-snap-stage3: snap-stage3-H-$(CFG_HOST_TRIPLE)
\ No newline at end of file
+snap-stage3: snap-stage3-H-$(CFG_HOST_TRIPLE)
ifdef CFG_ENABLE_LOCAL_RUST
$(Q)$(S)src/etc/local_stage0.sh $(CFG_HOST_TRIPLE) $(CFG_LOCAL_RUST_ROOT)
else
- $(Q)$(S)src/etc/get-snapshot.py $(CFG_HOST_TRIPLE) $(SNAPSHOT_FILE)
+ $(Q)$(CFG_PYTHON) $(S)src/etc/get-snapshot.py $(CFG_HOST_TRIPLE) $(SNAPSHOT_FILE)
ifdef CFG_ENABLE_PAX_FLAGS
@$(call E, apply PaX flags: $@)
@"$(CFG_PAXCTL)" -cm "$@"
$(RPASS_TESTS) \
$(S)src/etc/combine-tests.py
@$(call E, check: building combined stage2 test runner)
- $(Q)$(S)src/etc/combine-tests.py
+ $(Q)$(CFG_PYTHON) $(S)src/etc/combine-tests.py
define DEF_CHECK_FAST_FOR_T_H
# $(1) unused
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use cmp;
+
enum mode { mode_compile_fail, mode_run_fail, mode_run_pass, mode_pretty, }
impl mode : cmp::Eq {
fn make_test(config: config, testfile: &Path) ->
test::TestDesc {
- {
+ test::TestDesc {
name: make_test_name(config, testfile),
testfn: make_test_closure(config, testfile),
ignore: header::is_test_ignored(config, testfile),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use common::config;
+use io;
use io::ReaderUtil;
+use str;
export load_errors;
export expected_error;
let error_tag = ~"//~";
let mut idx;
match str::find_str(line, error_tag) {
- option::None => return ~[],
- option::Some(nn) => { idx = (nn as uint) + str::len(error_tag); }
+ None => return ~[],
+ Some(nn) => { idx = (nn as uint) + str::len(error_tag); }
}
// "//~^^^ kind msg" denotes a message expected
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use common;
use common::config;
+use io;
use io::ReaderUtil;
+use os;
+use str;
export test_props;
export load_props;
let mut error_patterns = ~[];
let mut aux_builds = ~[];
let mut exec_env = ~[];
- let mut compile_flags = option::None;
- let mut pp_exact = option::None;
+ let mut compile_flags = None;
+ let mut pp_exact = None;
for iter_header(testfile) |ln| {
match parse_error_pattern(ln) {
- option::Some(ep) => error_patterns.push(ep),
- option::None => ()
+ Some(ep) => error_patterns.push(ep),
+ None => ()
};
if compile_flags.is_none() {
return found;
fn xfail_target() -> ~str {
- ~"xfail-" + os::sysname()
+ ~"xfail-" + str::from_slice(os::SYSNAME)
}
}
fn parse_pp_exact(line: ~str, testfile: &Path) -> Option<Path> {
match parse_name_value_directive(line, ~"pp-exact") {
- option::Some(s) => option::Some(Path(s)),
- option::None => {
+ Some(s) => Some(Path(s)),
+ None => {
if parse_name_directive(line, ~"pp-exact") {
- option::Some(testfile.file_path())
+ Some(testfile.file_path())
} else {
- option::None
+ None
}
}
}
directive: ~str) -> Option<~str> unsafe {
let keycolon = directive + ~":";
match str::find_str(line, keycolon) {
- option::Some(colon) => {
+ Some(colon) => {
let value = str::slice(line, colon + str::len(keycolon),
str::len(line));
debug!("%s: %s", directive, value);
- option::Some(value)
+ Some(value)
}
- option::None => option::None
+ None => None
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use run::spawn_process;
+use core::prelude::*;
+
+use io;
use io::{ReaderUtil, WriterUtil};
+use libc;
use libc::{c_int, pid_t};
+use os;
+use run;
+use run::spawn_process;
+use pipes;
+use str;
+use task;
+use vec;
export run;
}
fn readclose(fd: c_int) -> ~str {
- // Copied from run::program_output
- let file = os::fdopen(fd);
- let reader = io::FILE_reader(file, false);
- let mut buf = ~"";
- while !reader.eof() {
- let bytes = reader.read_bytes(4096u);
- str::push_str(&mut buf, str::from_bytes(bytes));
+ unsafe {
+ // Copied from run::program_output
+ let file = os::fdopen(fd);
+ let reader = io::FILE_reader(file, false);
+ let mut buf = ~"";
+ while !reader.eof() {
+ let bytes = reader.read_bytes(4096u);
+ str::push_str(&mut buf, str::from_bytes(bytes));
+ }
+ os::fclose(file);
+ return buf;
}
- os::fclose(file);
- return buf;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use io;
use io::WriterUtil;
+use os;
+use str;
+use uint;
+use vec;
+use common;
use common::mode_run_pass;
use common::mode_run_fail;
use common::mode_compile_fail;
use common::mode_pretty;
use common::config;
+use errors;
+use header;
use header::load_props;
use header::test_props;
+use procsrv;
+use util;
use util::logv;
export run;
} else { logv(config, ~"testing for converging pretty-printing"); }
let rounds =
- match props.pp_exact { option::Some(_) => 1, option::None => 2 };
+ match props.pp_exact { Some(_) => 1, None => 2 };
let mut srcs = ~[io::read_whole_file_str(testfile).get()];
let mut expected =
match props.pp_exact {
- option::Some(file) => {
+ Some(file) => {
let filepath = testfile.dir_path().push_rel(&file);
io::read_whole_file_str(&filepath).get()
}
- option::None => { srcs[vec::len(srcs) - 2u] }
+ None => { srcs[vec::len(srcs) - 2u] }
};
let mut actual = srcs[vec::len(srcs) - 1u];
fn print_source(config: config, testfile: &Path, src: ~str) -> procres {
compose_and_run(config, testfile, make_pp_args(config, testfile),
- ~[], config.compile_lib_path, option::Some(src))
+ ~[], config.compile_lib_path, Some(src))
}
fn make_pp_args(config: config, _testfile: &Path) -> procargs {
compose_and_run_compiler(
config, props, testfile,
make_typecheck_args(config, testfile),
- option::Some(src))
+ Some(src))
}
fn make_typecheck_args(config: config, testfile: &Path) -> procargs {
compose_and_run(config, testfile,
make_run_args(config, props, testfile),
props.exec_env,
- config.run_lib_path, option::None)
+ config.run_lib_path, None)
}
fn compose_and_run_compiler(
make_compile_args(config, props, ~[~"--lib"] + extra_link_args,
|a,b| make_lib_name(a, b, testfile), &abs_ab);
let auxres = compose_and_run(config, &abs_ab, aux_args, ~[],
- config.compile_lib_path, option::None);
+ config.compile_lib_path, None);
if auxres.status != 0 {
fatal_procres(
fmt!("auxiliary build of %s failed to compile: ",
}
fn make_exe_name(config: config, testfile: &Path) -> Path {
- Path(output_base_name(config, testfile).to_str() + os::exe_suffix())
+ Path(output_base_name(config, testfile).to_str() +
+ str::from_slice(os::EXE_SUFFIX))
}
fn make_run_args(config: config, _props: test_props, testfile: &Path) ->
// then split apart its command
let runtool =
match config.runtool {
- option::Some(s) => option::Some(s),
- option::None => option::None
+ Some(s) => Some(s),
+ None => None
};
split_maybe_args(runtool)
};
fn split_maybe_args(argstr: Option<~str>) -> ~[~str] {
fn rm_whitespace(v: ~[~str]) -> ~[~str] {
- vec::filter(v, |s| !str::is_whitespace(*s))
+ v.filtered(|s| !str::is_whitespace(*s))
}
match argstr {
- option::Some(s) => rm_whitespace(str::split_char(s, ' ')),
- option::None => ~[]
+ Some(s) => rm_whitespace(str::split_char(s, ' ')),
+ None => ~[]
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use io;
+use os;
use os::getenv;
+use common;
use common::config;
fn make_new_path(path: ~str) -> ~str {
// Windows just uses PATH as the library search path, so we have to
// maintain the current value while adding our own
match getenv(lib_path_env_var()) {
- option::Some(curr) => {
+ Some(curr) => {
fmt!("%s%s%s", path, path_div(), curr)
}
- option::None => path
+ None => path
}
}
extern mod core(vers = "0.6");
#[cfg(cargo)]
-extern mod self(name = "cargo", vers = "0.6");
+extern mod this(name = "cargo", vers = "0.6");
#[cfg(fuzzer)]
-extern mod self(name = "fuzzer", vers = "0.6");
+extern mod this(name = "fuzzer", vers = "0.6");
#[cfg(rustdoc)]
-extern mod self(name = "rustdoc", vers = "0.6");
+extern mod this(name = "rustdoc", vers = "0.6");
#[cfg(rusti)]
-extern mod self(name = "rusti", vers = "0.6");
+extern mod this(name = "rusti", vers = "0.6");
#[cfg(rustc)]
-extern mod self(name = "rustc", vers = "0.6");
+extern mod this(name = "rustc", vers = "0.6");
-fn main() { self::main() }
\ No newline at end of file
+fn main() { this::main() }
-#!/usr/bin/python
+#!/usr/bin/env python
#
# this script attempts to turn doc comment attributes (#[doc = "..."])
" Language: Rust
" Maintainer: Patrick Walton <pcwalton@mozilla.com>
" Maintainer: Ben Blum <bblum@cs.cmu.edu>
-" Last Change: 2012 Dec 14
+" Last Change: 2012 Dec 25
if version < 600
syntax clear
syn keyword rustTrait Const Copy Send Owned " inherent traits
syn keyword rustTrait Eq Ord Num Ptr
-syn keyword rustTrait Add Sub Mul Div Modulo Neg BitAnd BitOr BitXor
-syn keyword rustTrait Shl Shr Index
+syn keyword rustTrait Drop Add Sub Mul Div Modulo Neg BitAnd BitOr
+syn keyword rustTrait BitXor Shl Shr Index
syn keyword rustSelf self
syn keyword rustBoolean true false
let mut uuid = None;
for mis.each |a| {
match a.node {
- ast::meta_name_value(v, {node: ast::lit_str(s), span: _}) => {
+ ast::meta_name_value(v, ast::spanned { node: ast::lit_str(s),
+ _ }) => {
match v {
~"name" => name = Some(*s),
~"vers" => vers = Some(*s),
for c.node.attrs.each |a| {
match a.node.value.node {
- ast::meta_name_value(v, {node: ast::lit_str(_), span: _}) => {
+ ast::meta_name_value(v, ast::spanned { node: ast::lit_str(_),
+ _ }) => {
match v {
~"desc" => desc = Some(v),
~"sigs" => sigs = Some(v),
let e = @{
mut deps: ~[]
};
- let v = visit::mk_simple_visitor(@{
+ let v = visit::mk_simple_visitor(@visit::SimpleVisitor {
visit_view_item: |a| goto_view_item(sess, e, a),
visit_item: |a| goto_item(e, a),
.. *visit::default_simple_visitor()
Some(bp) => bp
};
let newv = os::list_dir_path(&buildpath);
- let exec_suffix = os::exe_suffix();
+ let exec_suffix = str::from_slice(os::EXE_SUFFIX);
for newv.each |ct| {
if (exec_suffix != ~"" && str::ends_with(ct.to_str(),
exec_suffix)) ||
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::os;
+use core::path::Path;
+use core::run;
+
fn gpgv(args: ~[~str]) -> { status: int, out: ~str, err: ~str } {
return run::program_output(~"gpgv", args);
}
#[forbid(deprecated_pattern)];
use cast::transmute;
+use kinds::Copy;
+use iter;
+use libc;
+use option::Option;
use ptr::addr_of;
+use sys;
+use uint;
+use vec;
/// Code for dealing with @-vectors. This is pretty incomplete, and
/// contains a bunch of duplication from the code for ~-vectors.
#[abi = "cdecl"]
-extern mod rustrt {
+pub extern mod rustrt {
#[legacy_exports];
- fn vec_reserve_shared_actual(++t: *sys::TypeDesc,
- ++v: **vec::raw::VecRepr,
- ++n: libc::size_t);
+ unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc,
+ ++v: **vec::raw::VecRepr,
+ ++n: libc::size_t);
}
#[abi = "rust-intrinsic"]
-extern mod rusti {
+pub extern mod rusti {
#[legacy_exports];
fn move_val_init<T>(dst: &mut T, -src: T);
}
#[inline(always)]
pub pure fn build_sized_opt<A>(size: Option<uint>,
builder: &fn(push: pure fn(v: A))) -> @[A] {
- build_sized(size.get_default(4), builder)
+ build_sized(size.get_or_default(4), builder)
}
// Appending
#[cfg(notest)]
pub mod traits {
+ use at_vec::append;
+ use kinds::Copy;
+ use ops::Add;
+
pub impl<T: Copy> @[T] : Add<&[const T],@[T]> {
#[inline(always)]
pure fn add(&self, rhs: & &self/[const T]) -> @[T] {
pub mod traits {}
pub mod raw {
+ use at_vec::{capacity, rusti, rustrt};
+ use cast::transmute;
+ use libc;
+ use ptr::addr_of;
+ use ptr;
+ use sys;
+ use uint;
+ use vec;
+
pub type VecRepr = vec::raw::VecRepr;
pub type SliceRepr = vec::raw::SliceRepr;
//! Boolean logic
+use bool;
+use cmp;
use cmp::Eq;
+use option::{None, Option, Some};
/// Negation / inverse
pub pure fn not(v: bool) -> bool { !v }
#[cfg(test)]
pub mod tests {
+ use cast::{bump_box_refcount, reinterpret_cast, transmute};
+
#[test]
pub fn test_reinterpret_cast() {
assert 1u == unsafe { reinterpret_cast(&1) };
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use char;
use cmp::Eq;
+use option::{None, Option, Some};
+use str;
+use u32;
+use uint;
+use unicode;
/*
Lu Uppercase_Letter an uppercase letter
* Indicates whether a character is in lower case, defined
* in terms of the Unicode General Category 'Ll'
*/
+#[inline(always)]
pub pure fn is_lowercase(c: char) -> bool {
return unicode::general_category::Ll(c);
}
* Indicates whether a character is in upper case, defined
* in terms of the Unicode General Category 'Lu'.
*/
+#[inline(always)]
pub pure fn is_uppercase(c: char) -> bool {
return unicode::general_category::Lu(c);
}
* terms of the Unicode General Categories 'Zs', 'Zl', 'Zp'
* additional 'Cc'-category control codes in the range [0x09, 0x0d]
*/
+#[inline(always)]
pub pure fn is_whitespace(c: char) -> bool {
return ('\x09' <= c && c <= '\x0d')
|| unicode::general_category::Zs(c)
* defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No'
* and the Derived Core Property 'Alphabetic'.
*/
+#[inline(always)]
pub pure fn is_alphanumeric(c: char) -> bool {
return unicode::derived_property::Alphabetic(c) ||
unicode::general_category::Nd(c) ||
}
/// Indicates whether the character is an ASCII character
+#[inline(always)]
pub pure fn is_ascii(c: char) -> bool {
c - ('\x7F' & c) == '\x00'
}
/// Indicates whether the character is numeric (Nd, Nl, or No)
+#[inline(always)]
pub pure fn is_digit(c: char) -> bool {
return unicode::general_category::Nd(c) ||
unicode::general_category::Nl(c) ||
* 'b' or 'B', 11, etc. Returns none if the char does not
* refer to a digit in the given radix.
*/
+#[inline]
pub pure fn to_digit(c: char, radix: uint) -> Option<uint> {
let val = match c {
'0' .. '9' => c as uint - ('0' as uint),
*
* -1 if a < b, 0 if a == b, +1 if a > b
*/
+#[inline(always)]
pub pure fn cmp(a: char, b: char) -> int {
return if b > a { -1 }
else if b < a { 1 }
struct MemoryRegion { priv opaque: () }
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
struct Registers {
data: [u32 * 16]
}
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
struct Context {
regs: Registers,
next: *Context,
}
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
struct Task {
// Public fields
refcount: intptr_t, // 0
extern mod rustrt {
#[legacy_exports];
#[rust_stack]
- /*priv*/ fn rust_get_task() -> *c_void;
+ // FIXME (#4386): Unable to make following method private.
+ /* priv */ unsafe fn rust_get_task() -> *c_void;
}
}
impl (): Clone {
+ #[inline(always)]
fn clone(&self) -> () { () }
}
// Alpabetically sorted by link_name
- pure fn acos(n: c_double) -> c_double;
- pure fn asin(n: c_double) -> c_double;
- pure fn atan(n: c_double) -> c_double;
- pure fn atan2(a: c_double, b: c_double) -> c_double;
- pure fn cbrt(n: c_double) -> c_double;
- pure fn ceil(n: c_double) -> c_double;
- pure fn copysign(x: c_double, y: c_double) -> c_double;
- pure fn cos(n: c_double) -> c_double;
- pure fn cosh(n: c_double) -> c_double;
- pure fn erf(n: c_double) -> c_double;
- pure fn erfc(n: c_double) -> c_double;
- pure fn exp(n: c_double) -> c_double;
- pure fn expm1(n: c_double) -> c_double;
- pure fn exp2(n: c_double) -> c_double;
- #[link_name="fabs"] pure fn abs(n: c_double) -> c_double;
+ unsafe fn acos(n: c_double) -> c_double;
+ unsafe fn asin(n: c_double) -> c_double;
+ unsafe fn atan(n: c_double) -> c_double;
+ unsafe fn atan2(a: c_double, b: c_double) -> c_double;
+ unsafe fn cbrt(n: c_double) -> c_double;
+ unsafe fn ceil(n: c_double) -> c_double;
+ unsafe fn copysign(x: c_double, y: c_double) -> c_double;
+ unsafe fn cos(n: c_double) -> c_double;
+ unsafe fn cosh(n: c_double) -> c_double;
+ unsafe fn erf(n: c_double) -> c_double;
+ unsafe fn erfc(n: c_double) -> c_double;
+ unsafe fn exp(n: c_double) -> c_double;
+ unsafe fn expm1(n: c_double) -> c_double;
+ unsafe fn exp2(n: c_double) -> c_double;
+ #[link_name="fabs"] unsafe fn abs(n: c_double) -> c_double;
// rename: for clarity and consistency with add/sub/mul/div
- #[link_name="fdim"] pure fn abs_sub(a: c_double, b: c_double) -> c_double;
- pure fn floor(n: c_double) -> c_double;
+ #[link_name="fdim"]
+ unsafe fn abs_sub(a: c_double, b: c_double) -> c_double;
+ unsafe fn floor(n: c_double) -> c_double;
// rename: for clarity and consistency with add/sub/mul/div
- #[link_name="fma"] pure fn mul_add(a: c_double, b: c_double,
+ #[link_name="fma"] unsafe fn mul_add(a: c_double, b: c_double,
c: c_double) -> c_double;
- #[link_name="fmax"] pure fn fmax(a: c_double, b: c_double) -> c_double;
- #[link_name="fmin"] pure fn fmin(a: c_double, b: c_double) -> c_double;
- pure fn nextafter(x: c_double, y: c_double) -> c_double;
- pure fn frexp(n: c_double, value: &mut c_int) -> c_double;
- pure fn hypot(x: c_double, y: c_double) -> c_double;
- pure fn ldexp(x: c_double, n: c_int) -> c_double;
+ #[link_name="fmax"] unsafe fn fmax(a: c_double, b: c_double) -> c_double;
+ #[link_name="fmin"] unsafe fn fmin(a: c_double, b: c_double) -> c_double;
+ unsafe fn nextafter(x: c_double, y: c_double) -> c_double;
+ unsafe fn frexp(n: c_double, value: &mut c_int) -> c_double;
+ unsafe fn hypot(x: c_double, y: c_double) -> c_double;
+ unsafe fn ldexp(x: c_double, n: c_int) -> c_double;
#[cfg(unix)]
- #[link_name="lgamma_r"] pure fn lgamma(n: c_double,
+ #[link_name="lgamma_r"] unsafe fn lgamma(n: c_double,
sign: &mut c_int) -> c_double;
#[cfg(windows)]
- #[link_name="__lgamma_r"] pure fn lgamma(n: c_double,
+ #[link_name="__lgamma_r"] unsafe fn lgamma(n: c_double,
sign: &mut c_int) -> c_double;
// renamed: log is a reserved keyword; ln seems more natural, too
- #[link_name="log"] pure fn ln(n: c_double) -> c_double;
+ #[link_name="log"] unsafe fn ln(n: c_double) -> c_double;
// renamed: "logb" /often/ is confused for log2 by beginners
- #[link_name="logb"] pure fn log_radix(n: c_double) -> c_double;
+ #[link_name="logb"] unsafe fn log_radix(n: c_double) -> c_double;
// renamed: to be consitent with log as ln
- #[link_name="log1p"] pure fn ln1p(n: c_double) -> c_double;
- pure fn log10(n: c_double) -> c_double;
- pure fn log2(n: c_double) -> c_double;
- #[link_name="ilogb"] pure fn ilog_radix(n: c_double) -> c_int;
- pure fn modf(n: c_double, iptr: &mut c_double) -> c_double;
- pure fn pow(n: c_double, e: c_double) -> c_double;
+ #[link_name="log1p"] unsafe fn ln1p(n: c_double) -> c_double;
+ unsafe fn log10(n: c_double) -> c_double;
+ unsafe fn log2(n: c_double) -> c_double;
+ #[link_name="ilogb"] unsafe fn ilog_radix(n: c_double) -> c_int;
+ unsafe fn modf(n: c_double, iptr: &mut c_double) -> c_double;
+ unsafe fn pow(n: c_double, e: c_double) -> c_double;
// FIXME (#1379): enable when rounding modes become available
-// pure fn rint(n: c_double) -> c_double;
- pure fn round(n: c_double) -> c_double;
+// unsafe fn rint(n: c_double) -> c_double;
+ unsafe fn round(n: c_double) -> c_double;
// rename: for consistency with logradix
- #[link_name="scalbn"] pure fn ldexp_radix(n: c_double, i: c_int) ->
+ #[link_name="scalbn"] unsafe fn ldexp_radix(n: c_double, i: c_int) ->
c_double;
- pure fn sin(n: c_double) -> c_double;
- pure fn sinh(n: c_double) -> c_double;
- pure fn sqrt(n: c_double) -> c_double;
- pure fn tan(n: c_double) -> c_double;
- pure fn tanh(n: c_double) -> c_double;
- pure fn tgamma(n: c_double) -> c_double;
- pure fn trunc(n: c_double) -> c_double;
+ unsafe fn sin(n: c_double) -> c_double;
+ unsafe fn sinh(n: c_double) -> c_double;
+ unsafe fn sqrt(n: c_double) -> c_double;
+ unsafe fn tan(n: c_double) -> c_double;
+ unsafe fn tanh(n: c_double) -> c_double;
+ unsafe fn tgamma(n: c_double) -> c_double;
+ unsafe fn trunc(n: c_double) -> c_double;
// These are commonly only available for doubles
- pure fn j0(n: c_double) -> c_double;
- pure fn j1(n: c_double) -> c_double;
- pure fn jn(i: c_int, n: c_double) -> c_double;
+ unsafe fn j0(n: c_double) -> c_double;
+ unsafe fn j1(n: c_double) -> c_double;
+ unsafe fn jn(i: c_int, n: c_double) -> c_double;
- pure fn y0(n: c_double) -> c_double;
- pure fn y1(n: c_double) -> c_double;
- pure fn yn(i: c_int, n: c_double) -> c_double;
+ unsafe fn y0(n: c_double) -> c_double;
+ unsafe fn y1(n: c_double) -> c_double;
+ unsafe fn yn(i: c_int, n: c_double) -> c_double;
}
#[link_name = "m"]
// Alpabetically sorted by link_name
- #[link_name="acosf"] pure fn acos(n: c_float) -> c_float;
- #[link_name="asinf"] pure fn asin(n: c_float) -> c_float;
- #[link_name="atanf"] pure fn atan(n: c_float) -> c_float;
- #[link_name="atan2f"] pure fn atan2(a: c_float, b: c_float) -> c_float;
- #[link_name="cbrtf"] pure fn cbrt(n: c_float) -> c_float;
- #[link_name="ceilf"] pure fn ceil(n: c_float) -> c_float;
- #[link_name="copysignf"] pure fn copysign(x: c_float,
+ #[link_name="acosf"] unsafe fn acos(n: c_float) -> c_float;
+ #[link_name="asinf"] unsafe fn asin(n: c_float) -> c_float;
+ #[link_name="atanf"] unsafe fn atan(n: c_float) -> c_float;
+ #[link_name="atan2f"] unsafe fn atan2(a: c_float, b: c_float) -> c_float;
+ #[link_name="cbrtf"] unsafe fn cbrt(n: c_float) -> c_float;
+ #[link_name="ceilf"] unsafe fn ceil(n: c_float) -> c_float;
+ #[link_name="copysignf"] unsafe fn copysign(x: c_float,
y: c_float) -> c_float;
- #[link_name="cosf"] pure fn cos(n: c_float) -> c_float;
- #[link_name="coshf"] pure fn cosh(n: c_float) -> c_float;
- #[link_name="erff"] pure fn erf(n: c_float) -> c_float;
- #[link_name="erfcf"] pure fn erfc(n: c_float) -> c_float;
- #[link_name="expf"] pure fn exp(n: c_float) -> c_float;
- #[link_name="expm1f"]pure fn expm1(n: c_float) -> c_float;
- #[link_name="exp2f"] pure fn exp2(n: c_float) -> c_float;
- #[link_name="fabsf"] pure fn abs(n: c_float) -> c_float;
- #[link_name="fdimf"] pure fn abs_sub(a: c_float, b: c_float) -> c_float;
- #[link_name="floorf"] pure fn floor(n: c_float) -> c_float;
- #[link_name="frexpf"] pure fn frexp(n: c_float,
+ #[link_name="cosf"] unsafe fn cos(n: c_float) -> c_float;
+ #[link_name="coshf"] unsafe fn cosh(n: c_float) -> c_float;
+ #[link_name="erff"] unsafe fn erf(n: c_float) -> c_float;
+ #[link_name="erfcf"] unsafe fn erfc(n: c_float) -> c_float;
+ #[link_name="expf"] unsafe fn exp(n: c_float) -> c_float;
+ #[link_name="expm1f"]unsafe fn expm1(n: c_float) -> c_float;
+ #[link_name="exp2f"] unsafe fn exp2(n: c_float) -> c_float;
+ #[link_name="fabsf"] unsafe fn abs(n: c_float) -> c_float;
+ #[link_name="fdimf"] unsafe fn abs_sub(a: c_float, b: c_float) -> c_float;
+ #[link_name="floorf"] unsafe fn floor(n: c_float) -> c_float;
+ #[link_name="frexpf"] unsafe fn frexp(n: c_float,
value: &mut c_int) -> c_float;
- #[link_name="fmaf"] pure fn mul_add(a: c_float,
+ #[link_name="fmaf"] unsafe fn mul_add(a: c_float,
b: c_float, c: c_float) -> c_float;
- #[link_name="fmaxf"] pure fn fmax(a: c_float, b: c_float) -> c_float;
- #[link_name="fminf"] pure fn fmin(a: c_float, b: c_float) -> c_float;
- #[link_name="nextafterf"] pure fn nextafter(x: c_float,
+ #[link_name="fmaxf"] unsafe fn fmax(a: c_float, b: c_float) -> c_float;
+ #[link_name="fminf"] unsafe fn fmin(a: c_float, b: c_float) -> c_float;
+ #[link_name="nextafterf"] unsafe fn nextafter(x: c_float,
y: c_float) -> c_float;
- #[link_name="hypotf"] pure fn hypot(x: c_float, y: c_float) -> c_float;
- #[link_name="ldexpf"] pure fn ldexp(x: c_float, n: c_int) -> c_float;
+ #[link_name="hypotf"] unsafe fn hypot(x: c_float, y: c_float) -> c_float;
+ #[link_name="ldexpf"] unsafe fn ldexp(x: c_float, n: c_int) -> c_float;
#[cfg(unix)]
- #[link_name="lgammaf_r"] pure fn lgamma(n: c_float,
+ #[link_name="lgammaf_r"] unsafe fn lgamma(n: c_float,
sign: &mut c_int) -> c_float;
#[cfg(windows)]
- #[link_name="__lgammaf_r"] pure fn lgamma(n: c_float,
+ #[link_name="__lgammaf_r"] unsafe fn lgamma(n: c_float,
sign: &mut c_int) -> c_float;
- #[link_name="logf"] pure fn ln(n: c_float) -> c_float;
- #[link_name="logbf"] pure fn log_radix(n: c_float) -> c_float;
- #[link_name="log1pf"] pure fn ln1p(n: c_float) -> c_float;
- #[link_name="log2f"] pure fn log2(n: c_float) -> c_float;
- #[link_name="log10f"] pure fn log10(n: c_float) -> c_float;
- #[link_name="ilogbf"] pure fn ilog_radix(n: c_float) -> c_int;
- #[link_name="modff"] pure fn modf(n: c_float,
+ #[link_name="logf"] unsafe fn ln(n: c_float) -> c_float;
+ #[link_name="logbf"] unsafe fn log_radix(n: c_float) -> c_float;
+ #[link_name="log1pf"] unsafe fn ln1p(n: c_float) -> c_float;
+ #[link_name="log2f"] unsafe fn log2(n: c_float) -> c_float;
+ #[link_name="log10f"] unsafe fn log10(n: c_float) -> c_float;
+ #[link_name="ilogbf"] unsafe fn ilog_radix(n: c_float) -> c_int;
+ #[link_name="modff"] unsafe fn modf(n: c_float,
iptr: &mut c_float) -> c_float;
- #[link_name="powf"] pure fn pow(n: c_float, e: c_float) -> c_float;
+ #[link_name="powf"] unsafe fn pow(n: c_float, e: c_float) -> c_float;
// FIXME (#1379): enable when rounding modes become available
-// #[link_name="rintf"] pure fn rint(n: c_float) -> c_float;
- #[link_name="roundf"] pure fn round(n: c_float) -> c_float;
- #[link_name="scalbnf"] pure fn ldexp_radix(n: c_float, i: c_int)
+// #[link_name="rintf"] unsafe fn rint(n: c_float) -> c_float;
+ #[link_name="roundf"] unsafe fn round(n: c_float) -> c_float;
+ #[link_name="scalbnf"] unsafe fn ldexp_radix(n: c_float, i: c_int)
-> c_float;
- #[link_name="sinf"] pure fn sin(n: c_float) -> c_float;
- #[link_name="sinhf"] pure fn sinh(n: c_float) -> c_float;
- #[link_name="sqrtf"] pure fn sqrt(n: c_float) -> c_float;
- #[link_name="tanf"] pure fn tan(n: c_float) -> c_float;
- #[link_name="tanhf"] pure fn tanh(n: c_float) -> c_float;
- #[link_name="tgammaf"] pure fn tgamma(n: c_float) -> c_float;
- #[link_name="truncf"] pure fn trunc(n: c_float) -> c_float;
+ #[link_name="sinf"] unsafe fn sin(n: c_float) -> c_float;
+ #[link_name="sinhf"] unsafe fn sinh(n: c_float) -> c_float;
+ #[link_name="sqrtf"] unsafe fn sqrt(n: c_float) -> c_float;
+ #[link_name="tanf"] unsafe fn tan(n: c_float) -> c_float;
+ #[link_name="tanhf"] unsafe fn tanh(n: c_float) -> c_float;
+ #[link_name="tgammaf"] unsafe fn tgamma(n: c_float) -> c_float;
+ #[link_name="truncf"] unsafe fn trunc(n: c_float) -> c_float;
}
// PORT check these by running src/etc/machconsts.c for your architecture
*
* Eventually this may be simplified to only require
* an `eq` method, with the other generated from
-* a default implementation.
+* a default implementation. However it should
+* remain possible to implement `ne` separately, for
+* compatibility with floating-point NaN semantics
+* (cf. IEEE 754-2008 section 5.11).
*/
#[lang="eq"]
pub trait Eq {
*
* Eventually this may be simplified to only require
* an `le` method, with the others generated from
-* default implementations.
+* default implementations. However it should remain
+* possible to implement the others separately, for
+* compatibility with floating-point NaN semantics
+* (cf. IEEE 754-2008 section 5.11).
*/
#[lang="ord"]
pub trait Ord {
pure fn gt(&self, other: &self) -> bool;
}
+#[inline(always)]
pub pure fn lt<T: Ord>(v1: &T, v2: &T) -> bool {
(*v1).lt(v2)
}
-pub pure fn le<T: Ord Eq>(v1: &T, v2: &T) -> bool {
- (*v1).lt(v2) || (*v1).eq(v2)
+#[inline(always)]
+pub pure fn le<T: Ord>(v1: &T, v2: &T) -> bool {
+ (*v1).le(v2)
}
+#[inline(always)]
pub pure fn eq<T: Eq>(v1: &T, v2: &T) -> bool {
(*v1).eq(v2)
}
+#[inline(always)]
pub pure fn ne<T: Eq>(v1: &T, v2: &T) -> bool {
(*v1).ne(v2)
}
+#[inline(always)]
pub pure fn ge<T: Ord>(v1: &T, v2: &T) -> bool {
(*v1).ge(v2)
}
+#[inline(always)]
pub pure fn gt<T: Ord>(v1: &T, v2: &T) -> bool {
(*v1).gt(v2)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use prelude::*;
+use task;
+use task::local_data::{local_data_pop, local_data_set};
+
// helper for transmutation, shown below.
-type RustClosure = (int,int);
+type RustClosure = (int, int);
+
pub struct Handler<T, U> {
handle: RustClosure,
prev: Option<@Handler<T, U>>,
pub struct Condition<T, U> {
name: &static/str,
- key: task::local_data::LocalDataKey<Handler<T,U>>
+ key: task::local_data::LocalDataKey<Handler<T, U>>
}
-impl<T, U> Condition<T,U> {
-
- fn trap(&self, h: &self/fn(&T) ->U) -> Trap/&self<T,U> {
+impl<T, U> Condition<T, U> {
+ fn trap(&self, h: &self/fn(T) -> U) -> Trap/&self<T, U> {
unsafe {
let p : *RustClosure = ::cast::transmute(&h);
let prev = task::local_data::local_data_get(self.key);
- let h = @Handler{handle: *p, prev: prev};
- move Trap { cond: self, handler: h }
+ let h = @Handler { handle: *p, prev: prev };
+ Trap { cond: self, handler: h }
}
}
- fn raise(t:&T) -> U {
- do self.raise_default(t) {
- fail fmt!("Unhandled condition: %s: %?",
- self.name,
- t);
- }
+ fn raise(t: T) -> U {
+ let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
+ self.raise_default(t, || fail copy msg)
}
- fn raise_default(t:&T, default: fn() -> U) -> U {
+ fn raise_default(t: T, default: &fn() -> U) -> U {
unsafe {
- match task::local_data::local_data_pop(self.key) {
+ match local_data_pop(self.key) {
None => {
debug!("Condition.raise: found no handler");
default()
}
-
Some(handler) => {
debug!("Condition.raise: found handler");
match handler.prev {
- None => (),
- Some(hp) =>
- task::local_data::local_data_set(self.key, hp)
+ None => {}
+ Some(hp) => local_data_set(self.key, hp)
}
- let handle : &fn(&T) -> U =
+ let handle : &fn(T) -> U =
::cast::transmute(handler.handle);
let u = handle(t);
- task::local_data::local_data_set(self.key,
- handler);
- move u
+ local_data_set(self.key, handler);
+ u
}
}
}
}
}
-
-
struct Trap<T, U> {
- cond: &Condition<T,U>,
+ cond: &Condition<T, U>,
handler: @Handler<T, U>
}
-impl<T, U> Trap<T,U> {
+impl<T, U> Trap<T, U> {
fn in<V>(&self, inner: &self/fn() -> V) -> V {
unsafe {
let _g = Guard { cond: self.cond };
debug!("Trap: pushing handler to TLS");
- task::local_data::local_data_set(self.cond.key, self.handler);
+ local_data_set(self.cond.key, self.handler);
inner()
}
}
}
struct Guard<T, U> {
- cond: &Condition<T,U>,
- drop {
+ cond: &Condition<T, U>
+}
+
+impl<T, U> Guard<T, U> : Drop {
+ fn finalize(&self) {
unsafe {
debug!("Guard: popping handler from TLS");
- let curr = task::local_data::local_data_pop(self.cond.key);
+ let curr = local_data_pop(self.cond.key);
match curr {
- None => (),
- Some(h) =>
- match h.prev {
- None => (),
- Some(hp) => {
- task::local_data::local_data_set(self.cond.key, hp)
- }
+ None => {}
+ Some(h) => match h.prev {
+ None => {}
+ Some(hp) => local_data_set(self.cond.key, hp)
}
}
}
}
}
-
#[cfg(test)]
mod test {
-
condition! {
sadness: int -> int;
}
fn trouble(i: int) {
- debug!("trouble: raising conition");
- let j = sadness::cond.raise(&i);
+ debug!("trouble: raising condition");
+ let j = sadness::cond.raise(i);
debug!("trouble: handler recovered with %d", j);
}
fn nested_trap_test_inner() {
-
let mut inner_trapped = false;
do sadness::cond.trap(|_j| {
#[test]
fn nested_trap_test_outer() {
-
let mut outer_trapped = false;
do sadness::cond.trap(|_j| {
}
fn nested_reraise_trap_test_inner() {
-
let mut inner_trapped = false;
do sadness::cond.trap(|_j| {
inner_trapped = true;
let i = 10;
debug!("nested_reraise_trap_test_inner: handler re-raising");
- sadness::cond.raise(&i)
+ sadness::cond.raise(i)
}).in {
debug!("nested_reraise_trap_test_inner: in protected block");
trouble(1);
#[test]
fn nested_reraise_trap_test_outer() {
-
let mut outer_trapped = false;
do sadness::cond.trap(|_j| {
#[test]
fn test_default() {
-
let mut trapped = false;
do sadness::cond.trap(|j| {
debug!("test_default: in handler");
- sadness::cond.raise_default(j, || {trapped=true; 5})
+ sadness::cond.raise_default(j, || { trapped=true; 5 })
}).in {
debug!("test_default: in protected block");
trouble(1);
assert trapped;
}
-
}
#[warn(vecs_implicitly_copyable)];
#[deny(non_camel_case_types)];
+/* The Prelude. */
+
+pub mod prelude;
/* Primitive types */
pub use kinds::{Const, Copy, Owned, Durable};
pub use ops::{Drop};
-pub use ops::{Add, Sub, Mul, Div, Modulo, Neg};
+pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Shl, Shr, Index};
pub use str::{StrSlice, Trimmable};
pub use vec::{ConstVector, CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
-pub use vec::{MutableVector, MutableCopyableVector};
+pub use vec::{OwnedVector, OwnedCopyableVector};
pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
// 'core' so that macro-expanded references to core::error and such
// can be resolved within libcore.
#[doc(hidden)] // FIXME #3538
-mod core {
+pub mod core {
pub const error : u32 = 1_u32;
pub const warn : u32 = 2_u32;
pub const info : u32 = 3_u32;
pub use cmp;
pub use condition;
-}
-
-
-// Similar to above. Some magic to make core testable.
-#[cfg(test)]
-mod std {
- extern mod std(vers = "0.6");
- pub use std::std::test;
+ pub use option;
+ pub use kinds;
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use kinds::Copy;
+use managed;
+use option::{None, Option, Some};
+use option;
+use vec;
+
type DListLink<T> = Option<DListNode<T>>;
enum DListNode<T> = @{
}
/// Creates a new dlist node with the given data.
-pure fn new_dlist_node<T>(data: T) -> DListNode<T> {
+pub pure fn new_dlist_node<T>(data: T) -> DListNode<T> {
DListNode(@{data: move data, mut linked: false,
mut prev: None, mut next: None})
}
/// Creates a new, empty dlist.
-pure fn DList<T>() -> DList<T> {
+pub pure fn DList<T>() -> DList<T> {
DList_(@{mut size: 0, mut hd: None, mut tl: None})
}
/// Produce a list from a list of lists, leaving no elements behind in the
/// input. O(number of sub-lists).
-fn concat<T>(lists: DList<DList<T>>) -> DList<T> {
+pub fn concat<T>(lists: DList<DList<T>>) -> DList<T> {
let result = DList();
while !lists.is_empty() {
result.append(lists.pop().get());
#[cfg(test)]
mod tests {
#[legacy_exports];
+
+ use dlist::{DList, concat, from_vec, new_dlist_node};
+ use iter;
+ use option::{None, Some};
+ use vec;
+
#[test]
fn test_dlist_concat() {
let a = from_vec(~[1,2]);
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use cast;
use cast::reinterpret_cast;
+use prelude::*;
use ptr::null;
+use vec;
/**
* A growable, modifiable vector type that accumulates elements into a
//! A type that represents one of two alternatives
use cmp::Eq;
+use cmp;
+use kinds::Copy;
use result::Result;
+use result;
+use vec;
/// The either type
#[deriving_eq]
Right(U)
}
+#[inline(always)]
pub fn either<T, U, V>(f_left: fn(&T) -> V,
f_right: fn(&U) -> V, value: &Either<T, U>) -> V {
/*!
}
}
-// XXX bad copies. take arg by val
-pub fn partition<T: Copy, U: Copy>(eithers: &[Either<T, U>])
+pub fn partition<T, U>(eithers: ~[Either<T, U>])
-> (~[T], ~[U]) {
/*!
* Extracts from a vector of either all the left values and right values
let mut lefts: ~[T] = ~[];
let mut rights: ~[U] = ~[];
- for vec::each(eithers) |elt| {
- match *elt {
- Left(copy l) => lefts.push(l),
- Right(copy r) => rights.push(r)
+ do vec::consume(eithers) |_i, elt| {
+ match elt {
+ Left(l) => lefts.push(l),
+ Right(r) => rights.push(r)
}
}
return (move lefts, move rights);
}
-// XXX bad copies
-pub pure fn flip<T: Copy, U: Copy>(eith: &Either<T, U>) -> Either<U, T> {
+#[inline(always)]
+pub pure fn flip<T, U>(eith: Either<T, U>) -> Either<U, T> {
//! Flips between left and right of a given either
- match *eith {
- Right(copy r) => Left(r),
- Left(copy l) => Right(l)
+ match eith {
+ Right(r) => Left(r),
+ Left(l) => Right(l)
}
}
-// XXX bad copies
-pub pure fn to_result<T: Copy, U: Copy>(eith: &Either<T, U>)
+#[inline(always)]
+pub pure fn to_result<T, U>(eith: Either<T, U>)
-> Result<U, T> {
/*!
* Converts either::t to a result::t
* an ok result, and the "left" choice a fail
*/
- match *eith {
- Right(copy r) => result::Ok(r),
- Left(copy l) => result::Err(l)
+ match eith {
+ Right(r) => result::Ok(r),
+ Left(l) => result::Err(l)
}
}
+#[inline(always)]
pub pure fn is_left<T, U>(eith: &Either<T, U>) -> bool {
//! Checks whether the given value is a left
match *eith { Left(_) => true, _ => false }
}
+#[inline(always)]
pub pure fn is_right<T, U>(eith: &Either<T, U>) -> bool {
//! Checks whether the given value is a right
match *eith { Right(_) => true, _ => false }
}
-// tjc: fix the next two after a snapshot
+#[inline(always)]
pub pure fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
//! Retrieves the value in the left branch. Fails if the either is Right.
}
}
+#[inline(always)]
pub pure fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
//! Retrieves the value in the right branch. Fails if the either is Left.
use cmp::Eq;
use option::{Some, None};
-
+use prelude::*;
+use str;
/*
* We have a 'ct' (compile-time) module that parses format strings into a
// Functions used by the fmt extension at compile time
#[doc(hidden)]
pub mod ct {
+ use char;
+ use prelude::*;
+ use str;
+ use vec;
+
+ #[deriving_eq]
pub enum Signedness { Signed, Unsigned, }
+
+ #[deriving_eq]
pub enum Caseness { CaseUpper, CaseLower, }
+
+ #[deriving_eq]
pub enum Ty {
TyBool,
TyStr,
TyFloat,
TyPoly,
}
+
+ #[deriving_eq]
pub enum Flag {
FlagLeftJustify,
FlagLeftZeroPad,
FlagSignAlways,
FlagAlternate,
}
+
+ #[deriving_eq]
pub enum Count {
CountIs(uint),
CountIsParam(uint),
CountImplied,
}
- // A formatted conversion from an expression to a string
- pub type Conv =
- {param: Option<uint>,
- flags: ~[Flag],
- width: Count,
- precision: Count,
- ty: Ty};
+ #[deriving_eq]
+ struct Parsed<T> {
+ val: T,
+ next: uint
+ }
+ impl<T> Parsed<T> {
+ static pure fn new(val: T, next: uint) -> Parsed<T> {
+ Parsed {val: val, next: next}
+ }
+ }
+
+ // A formatted conversion from an expression to a string
+ #[deriving_eq]
+ pub struct Conv {
+ param: Option<uint>,
+ flags: ~[Flag],
+ width: Count,
+ precision: Count,
+ ty: Ty
+ }
// A fragment of the output sequence
+ #[deriving_eq]
pub enum Piece { PieceString(~str), PieceConv(Conv), }
- pub type ErrorFn = fn@(&str) -> ! ;
+
+ pub type ErrorFn = @fn(&str) -> !;
pub fn parse_fmt_string(s: &str, err: ErrorFn) -> ~[Piece] {
- let mut pieces: ~[Piece] = ~[];
- let lim = str::len(s);
- let mut buf = ~"";
- fn flush_buf(buf: ~str, pieces: &mut ~[Piece]) -> ~str {
- if buf.len() > 0 {
- let piece = PieceString(move buf);
- pieces.push(move piece);
+ fn push_slice(ps: &mut ~[Piece], s: &str, from: uint, to: uint) {
+ if to > from {
+ ps.push(PieceString(s.slice(from, to)));
}
- return ~"";
}
+
+ let lim = s.len();
+ let mut h = 0;
let mut i = 0;
+ let mut pieces = ~[];
+
while i < lim {
- let size = str::utf8_char_width(s[i]);
- let curr = str::slice(s, i, i+size);
- if curr == ~"%" {
+ if s[i] == '%' as u8 {
i += 1;
+
if i >= lim {
err(~"unterminated conversion at end of string");
- }
- let curr2 = str::slice(s, i, i+1);
- if curr2 == ~"%" {
- buf += curr2;
+ } else if s[i] == '%' as u8 {
+ push_slice(&mut pieces, s, h, i);
i += 1;
} else {
- buf = flush_buf(move buf, &mut pieces);
- let rs = parse_conversion(s, i, lim, err);
- pieces.push(copy rs.piece);
- i = rs.next;
+ push_slice(&mut pieces, s, h, i - 1);
+ let Parsed {val, next} = parse_conversion(s, i, lim, err);
+ pieces.push(val);
+ i = next;
}
- } else { buf += curr; i += size; }
+
+ h = i;
+ } else {
+ i += str::utf8_char_width(s[i]);
+ }
}
- flush_buf(move buf, &mut pieces);
- move pieces
+
+ push_slice(&mut pieces, s, h, i);
+ pieces
}
- pub fn peek_num(s: &str, i: uint, lim: uint) ->
- Option<{num: uint, next: uint}> {
- let mut j = i;
- let mut accum = 0u;
+
+ pub fn peek_num(s: &str, i: uint, lim: uint) -> Option<Parsed<uint>> {
+ let mut i = i;
+ let mut accum = 0;
let mut found = false;
- while j < lim {
- match char::to_digit(s[j] as char, 10) {
+
+ while i < lim {
+ match char::to_digit(s[i] as char, 10) {
Some(x) => {
found = true;
accum *= 10;
accum += x;
- j += 1;
- },
+ i += 1;
+ }
None => break
}
}
+
if found {
- Some({num: accum, next: j})
+ Some(Parsed::new(accum, i))
} else {
None
}
}
- pub fn parse_conversion(s: &str, i: uint, lim: uint,
- err: ErrorFn) ->
- {piece: Piece, next: uint} {
- let parm = parse_parameter(s, i, lim);
- let flags = parse_flags(s, parm.next, lim);
- let width = parse_count(s, flags.next, lim);
+
+ pub fn parse_conversion(s: &str, i: uint, lim: uint, err: ErrorFn) ->
+ Parsed<Piece> {
+ let param = parse_parameter(s, i, lim);
+ // avoid copying ~[Flag] by destructuring
+ let Parsed {val: flags_val, next: flags_next} = parse_flags(s,
+ param.next, lim);
+ let width = parse_count(s, flags_next, lim);
let prec = parse_precision(s, width.next, lim);
let ty = parse_type(s, prec.next, lim, err);
- return {piece:
- PieceConv({param: parm.param,
- flags: copy flags.flags,
- width: width.count,
- precision: prec.count,
- ty: ty.ty}),
- next: ty.next};
+
+ Parsed::new(PieceConv(Conv {
+ param: param.val,
+ flags: flags_val,
+ width: width.val,
+ precision: prec.val,
+ ty: ty.val}), ty.next)
}
+
pub fn parse_parameter(s: &str, i: uint, lim: uint) ->
- {param: Option<uint>, next: uint} {
- if i >= lim { return {param: None, next: i}; }
- let num = peek_num(s, i, lim);
- return match num {
- None => {param: None, next: i},
- Some(t) => {
- let n = t.num;
- let j = t.next;
- if j < lim && s[j] == '$' as u8 {
- {param: Some(n), next: j + 1}
- } else { {param: None, next: i} }
- }
+ Parsed<Option<uint>> {
+ if i >= lim { return Parsed::new(None, i); }
+
+ match peek_num(s, i, lim) {
+ Some(num) if num.next < lim && s[num.next] == '$' as u8 =>
+ Parsed::new(Some(num.val), num.next + 1),
+ _ => Parsed::new(None, i)
+ }
+ }
+
+ pub fn parse_flags(s: &str, i: uint, lim: uint) -> Parsed<~[Flag]> {
+ let mut i = i;
+ let mut flags = ~[];
+
+ while i < lim {
+ let f = match s[i] {
+ '-' as u8 => FlagLeftJustify,
+ '0' as u8 => FlagLeftZeroPad,
+ ' ' as u8 => FlagSpaceForSign,
+ '+' as u8 => FlagSignAlways,
+ '#' as u8 => FlagAlternate,
+ _ => break
};
+
+ flags.push(f);
+ i += 1;
+ }
+
+ Parsed::new(flags, i)
}
- pub fn parse_flags(s: &str, i: uint, lim: uint) ->
- {flags: ~[Flag], next: uint} {
- let noflags: ~[Flag] = ~[];
- if i >= lim { return {flags: move noflags, next: i}; }
-
- fn more(f: Flag, s: &str, i: uint, lim: uint) ->
- {flags: ~[Flag], next: uint} {
- let next = parse_flags(s, i + 1u, lim);
- let rest = copy next.flags;
- let j = next.next;
- let curr: ~[Flag] = ~[f];
- return {flags: vec::append(move curr, rest), next: j};
+
+ pub fn parse_count(s: &str, i: uint, lim: uint) -> Parsed<Count> {
+ if i >= lim {
+ Parsed::new(CountImplied, i)
+ } else if s[i] == '*' as u8 {
+ let param = parse_parameter(s, i + 1, lim);
+ let j = param.next;
+
+ match param.val {
+ None => Parsed::new(CountIsNextParam, j),
+ Some(n) => Parsed::new(CountIsParam(n), j)
+ }
+ } else {
+ match peek_num(s, i, lim) {
+ None => Parsed::new(CountImplied, i),
+ Some(num) => Parsed::new(CountIs(num.val), num.next)
+ }
}
- // Unfortunate, but because s is borrowed, can't use a closure
- // fn more(f: Flag, s: &str) { more_(f, s, i, lim); }
- let f = s[i];
- return if f == '-' as u8 {
- more(FlagLeftJustify, s, i, lim)
- } else if f == '0' as u8 {
- more(FlagLeftZeroPad, s, i, lim)
- } else if f == ' ' as u8 {
- more(FlagSpaceForSign, s, i, lim)
- } else if f == '+' as u8 {
- more(FlagSignAlways, s, i, lim)
- } else if f == '#' as u8 {
- more(FlagAlternate, s, i, lim)
- } else { {flags: move noflags, next: i} };
- }
- pub fn parse_count(s: &str, i: uint, lim: uint)
- -> {count: Count, next: uint} {
- return if i >= lim {
- {count: CountImplied, next: i}
- } else if s[i] == '*' as u8 {
- let param = parse_parameter(s, i + 1, lim);
- let j = param.next;
- match param.param {
- None => {count: CountIsNextParam, next: j},
- Some(n) => {count: CountIsParam(n), next: j}
- }
- } else {
- let num = peek_num(s, i, lim);
- match num {
- None => {count: CountImplied, next: i},
- Some(num) => {
- count: CountIs(num.num),
- next: num.next
- }
- }
- };
}
- pub fn parse_precision(s: &str, i: uint, lim: uint) ->
- {count: Count, next: uint} {
- return if i >= lim {
- {count: CountImplied, next: i}
- } else if s[i] == '.' as u8 {
- let count = parse_count(s, i + 1u, lim);
+ pub fn parse_precision(s: &str, i: uint, lim: uint) -> Parsed<Count> {
+ if i < lim && s[i] == '.' as u8 {
+ let count = parse_count(s, i + 1, lim);
- // If there were no digits specified, i.e. the precision
- // was ".", then the precision is 0
- match count.count {
- CountImplied => {count: CountIs(0), next: count.next},
- _ => count
- }
- } else { {count: CountImplied, next: i} };
+ // If there were no digits specified, i.e. the precision
+ // was ".", then the precision is 0
+ match count.val {
+ CountImplied => Parsed::new(CountIs(0), count.next),
+ _ => count
+ }
+ } else {
+ Parsed::new(CountImplied, i)
+ }
}
+
pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) ->
- {ty: Ty, next: uint} {
+ Parsed<Ty> {
if i >= lim { err(~"missing type in conversion"); }
- let tstr = str::slice(s, i, i+1u);
+
// FIXME (#2249): Do we really want two signed types here?
// How important is it to be printf compatible?
- let t =
- if tstr == ~"b" {
- TyBool
- } else if tstr == ~"s" {
- TyStr
- } else if tstr == ~"c" {
- TyChar
- } else if tstr == ~"d" || tstr == ~"i" {
- TyInt(Signed)
- } else if tstr == ~"u" {
- TyInt(Unsigned)
- } else if tstr == ~"x" {
- TyHex(CaseLower)
- } else if tstr == ~"X" {
- TyHex(CaseUpper)
- } else if tstr == ~"t" {
- TyBits
- } else if tstr == ~"o" {
- TyOctal
- } else if tstr == ~"f" {
- TyFloat
- } else if tstr == ~"?" {
- TyPoly
- } else { err(~"unknown type in conversion: " + tstr) };
- return {ty: t, next: i + 1u};
+ let t = match s[i] {
+ 'b' as u8 => TyBool,
+ 's' as u8 => TyStr,
+ 'c' as u8 => TyChar,
+ 'd' as u8 | 'i' as u8 => TyInt(Signed),
+ 'u' as u8 => TyInt(Unsigned),
+ 'x' as u8 => TyHex(CaseLower),
+ 'X' as u8 => TyHex(CaseUpper),
+ 't' as u8 => TyBits,
+ 'o' as u8 => TyOctal,
+ 'f' as u8 => TyFloat,
+ '?' as u8 => TyPoly,
+ _ => err(~"unknown type in conversion: " + s.substr(i, 1))
+ };
+
+ Parsed::new(t, i + 1)
+ }
+
+ #[cfg(test)]
+ fn die(s: &str) -> ! { fail s.to_owned() }
+
+ #[test]
+ fn test_parse_count() {
+ fn test(s: &str, count: Count, next: uint) -> bool {
+ parse_count(s, 0, s.len()) == Parsed::new(count, next)
+ }
+
+ assert test("", CountImplied, 0);
+ assert test("*", CountIsNextParam, 1);
+ assert test("*1", CountIsNextParam, 1);
+ assert test("*1$", CountIsParam(1), 3);
+ assert test("123", CountIs(123), 3);
+ }
+
+ #[test]
+ fn test_parse_flags() {
+ fn pack(fs: &[Flag]) -> uint {
+ fs.foldl(0, |&p, &f| p | (1 << f as uint))
+ }
+
+ fn test(s: &str, flags: &[Flag], next: uint) {
+ let f = parse_flags(s, 0, s.len());
+ assert pack(f.val) == pack(flags);
+ assert f.next == next;
+ }
+
+ test("", [], 0);
+ test("!#-+ 0", [], 0);
+ test("#-+", [FlagAlternate, FlagLeftJustify, FlagSignAlways], 3);
+ test(" 0", [FlagSpaceForSign, FlagLeftZeroPad], 2);
+ }
+
+ #[test]
+ fn test_parse_fmt_string() {
+ assert parse_fmt_string("foo %s bar", die) == ~[
+ PieceString(~"foo "),
+ PieceConv(Conv {param: None, flags: ~[], width: CountImplied,
+ precision: CountImplied, ty: TyStr}),
+ PieceString(~" bar")];
+
+ assert parse_fmt_string("%s", die) == ~[
+ PieceConv(Conv {param: None, flags: ~[], width: CountImplied,
+ precision: CountImplied, ty: TyStr })];
+
+ assert parse_fmt_string("%%%%", die) == ~[
+ PieceString(~"%"), PieceString(~"%")];
+ }
+
+ #[test]
+ fn test_parse_parameter() {
+ fn test(s: &str, param: Option<uint>, next: uint) -> bool {
+ parse_parameter(s, 0, s.len()) == Parsed::new(param, next)
+ }
+
+ assert test("", None, 0);
+ assert test("foo", None, 0);
+ assert test("123", None, 0);
+ assert test("123$", Some(123), 4);
+ }
+
+ #[test]
+ fn test_parse_precision() {
+ fn test(s: &str, count: Count, next: uint) -> bool {
+ parse_precision(s, 0, s.len()) == Parsed::new(count, next)
+ }
+
+ assert test("", CountImplied, 0);
+ assert test(".", CountIs(0), 1);
+ assert test(".*", CountIsNextParam, 2);
+ assert test(".*1", CountIsNextParam, 2);
+ assert test(".*1$", CountIsParam(1), 4);
+ assert test(".123", CountIs(123), 4);
+ }
+
+ #[test]
+ fn test_parse_type() {
+ fn test(s: &str, ty: Ty) -> bool {
+ parse_type(s, 0, s.len(), die) == Parsed::new(ty, 1)
+ }
+
+ assert test("b", TyBool);
+ assert test("c", TyChar);
+ assert test("d", TyInt(Signed));
+ assert test("f", TyFloat);
+ assert test("i", TyInt(Signed));
+ assert test("o", TyOctal);
+ assert test("s", TyStr);
+ assert test("t", TyBits);
+ assert test("x", TyHex(CaseLower));
+ assert test("X", TyHex(CaseUpper));
+ assert test("?", TyPoly);
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_parse_type_missing() {
+ parse_type("", 0, 0, die);
+ }
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_parse_type_unknown() {
+ parse_type("!", 0, 1, die);
+ }
+
+ #[test]
+ fn test_peek_num() {
+ let s1 = "";
+ assert peek_num(s1, 0, s1.len()).is_none();
+
+ let s2 = "foo";
+ assert peek_num(s2, 0, s2.len()).is_none();
+
+ let s3 = "123";
+ assert peek_num(s3, 0, s3.len()) == Some(Parsed::new(123, 3));
+
+ let s4 = "123foo";
+ assert peek_num(s4, 0, s4.len()) == Some(Parsed::new(123, 3));
}
}
// implement it 0this way, I think.
#[doc(hidden)]
pub mod rt {
+ use float;
+ use str;
+ use sys;
+ use uint;
+ use vec;
+
pub const flag_none : u32 = 0u32;
pub const flag_left_justify : u32 = 0b00000000000001u32;
pub const flag_left_zero_pad : u32 = 0b00000000000010u32;
//! Operations and constants for `f32`
-pub use cmath::c_float_utils::*;
+use cmath;
+use cmp;
+use libc::{c_float, c_int};
+use num;
+
pub use cmath::c_float_targ_consts::*;
+macro_rules! delegate(
+ (
+ fn $name:ident(
+ $(
+ $arg:ident : $arg_ty:ty
+ ),*
+ ) -> $rv:ty = $bound_name:path
+ ) => (
+ pub pure fn $name($( $arg : $arg_ty ),*) -> $rv {
+ unsafe {
+ $bound_name($( $arg ),*)
+ }
+ }
+ )
+)
+
+delegate!(fn acos(n: c_float) -> c_float = cmath::c_float_utils::acos)
+delegate!(fn asin(n: c_float) -> c_float = cmath::c_float_utils::asin)
+delegate!(fn atan(n: c_float) -> c_float = cmath::c_float_utils::atan)
+delegate!(fn atan2(a: c_float, b: c_float) -> c_float =
+ cmath::c_float_utils::atan2)
+delegate!(fn cbrt(n: c_float) -> c_float = cmath::c_float_utils::cbrt)
+delegate!(fn ceil(n: c_float) -> c_float = cmath::c_float_utils::ceil)
+delegate!(fn copysign(x: c_float, y: c_float) -> c_float =
+ cmath::c_float_utils::copysign)
+delegate!(fn cos(n: c_float) -> c_float = cmath::c_float_utils::cos)
+delegate!(fn cosh(n: c_float) -> c_float = cmath::c_float_utils::cosh)
+delegate!(fn erf(n: c_float) -> c_float = cmath::c_float_utils::erf)
+delegate!(fn erfc(n: c_float) -> c_float = cmath::c_float_utils::erfc)
+delegate!(fn exp(n: c_float) -> c_float = cmath::c_float_utils::exp)
+delegate!(fn expm1(n: c_float) -> c_float = cmath::c_float_utils::expm1)
+delegate!(fn exp2(n: c_float) -> c_float = cmath::c_float_utils::exp2)
+delegate!(fn abs(n: c_float) -> c_float = cmath::c_float_utils::abs)
+delegate!(fn abs_sub(a: c_float, b: c_float) -> c_float =
+ cmath::c_float_utils::abs_sub)
+delegate!(fn floor(n: c_float) -> c_float = cmath::c_float_utils::floor)
+delegate!(fn mul_add(a: c_float, b: c_float, c: c_float) -> c_float =
+ cmath::c_float_utils::mul_add)
+delegate!(fn fmax(a: c_float, b: c_float) -> c_float =
+ cmath::c_float_utils::fmax)
+delegate!(fn fmin(a: c_float, b: c_float) -> c_float =
+ cmath::c_float_utils::fmin)
+delegate!(fn nextafter(x: c_float, y: c_float) -> c_float =
+ cmath::c_float_utils::nextafter)
+delegate!(fn frexp(n: c_float, value: &mut c_int) -> c_float =
+ cmath::c_float_utils::frexp)
+delegate!(fn hypot(x: c_float, y: c_float) -> c_float =
+ cmath::c_float_utils::hypot)
+delegate!(fn ldexp(x: c_float, n: c_int) -> c_float =
+ cmath::c_float_utils::ldexp)
+delegate!(fn lgamma(n: c_float, sign: &mut c_int) -> c_float =
+ cmath::c_float_utils::lgamma)
+delegate!(fn ln(n: c_float) -> c_float = cmath::c_float_utils::ln)
+delegate!(fn log_radix(n: c_float) -> c_float =
+ cmath::c_float_utils::log_radix)
+delegate!(fn ln1p(n: c_float) -> c_float = cmath::c_float_utils::ln1p)
+delegate!(fn log10(n: c_float) -> c_float = cmath::c_float_utils::log10)
+delegate!(fn log2(n: c_float) -> c_float = cmath::c_float_utils::log2)
+delegate!(fn ilog_radix(n: c_float) -> c_int =
+ cmath::c_float_utils::ilog_radix)
+delegate!(fn modf(n: c_float, iptr: &mut c_float) -> c_float =
+ cmath::c_float_utils::modf)
+delegate!(fn pow(n: c_float, e: c_float) -> c_float =
+ cmath::c_float_utils::pow)
+delegate!(fn round(n: c_float) -> c_float = cmath::c_float_utils::round)
+delegate!(fn ldexp_radix(n: c_float, i: c_int) -> c_float =
+ cmath::c_float_utils::ldexp_radix)
+delegate!(fn sin(n: c_float) -> c_float = cmath::c_float_utils::sin)
+delegate!(fn sinh(n: c_float) -> c_float = cmath::c_float_utils::sinh)
+delegate!(fn sqrt(n: c_float) -> c_float = cmath::c_float_utils::sqrt)
+delegate!(fn tan(n: c_float) -> c_float = cmath::c_float_utils::tan)
+delegate!(fn tanh(n: c_float) -> c_float = cmath::c_float_utils::tanh)
+delegate!(fn tgamma(n: c_float) -> c_float = cmath::c_float_utils::tgamma)
+delegate!(fn trunc(n: c_float) -> c_float = cmath::c_float_utils::trunc)
+
// These are not defined inside consts:: for consistency with
// the integer types
pub const neg_infinity: f32 = -1.0_f32/0.0_f32;
+#[inline(always)]
pub pure fn is_NaN(f: f32) -> bool { f != f }
+#[inline(always)]
pub pure fn add(x: f32, y: f32) -> f32 { return x + y; }
+#[inline(always)]
pub pure fn sub(x: f32, y: f32) -> f32 { return x - y; }
+#[inline(always)]
pub pure fn mul(x: f32, y: f32) -> f32 { return x * y; }
+#[inline(always)]
pub pure fn div(x: f32, y: f32) -> f32 { return x / y; }
+#[inline(always)]
pub pure fn rem(x: f32, y: f32) -> f32 { return x % y; }
+#[inline(always)]
pub pure fn lt(x: f32, y: f32) -> bool { return x < y; }
+#[inline(always)]
pub pure fn le(x: f32, y: f32) -> bool { return x <= y; }
+#[inline(always)]
pub pure fn eq(x: f32, y: f32) -> bool { return x == y; }
+#[inline(always)]
pub pure fn ne(x: f32, y: f32) -> bool { return x != y; }
+#[inline(always)]
pub pure fn ge(x: f32, y: f32) -> bool { return x >= y; }
+#[inline(always)]
pub pure fn gt(x: f32, y: f32) -> bool { return x > y; }
// FIXME (#1999): replace the predicates below with llvm intrinsics or
// calls to the libmath macros in the rust runtime for performance.
/// Returns true if `x` is a positive number, including +0.0f320 and +Infinity
+#[inline(always)]
pub pure fn is_positive(x: f32) -> bool
{ return x > 0.0f32 || (1.0f32/x) == infinity; }
/// Returns true if `x` is a negative number, including -0.0f320 and -Infinity
+#[inline(always)]
pub pure fn is_negative(x: f32) -> bool
{ return x < 0.0f32 || (1.0f32/x) == neg_infinity; }
*
* This is the same as `f32::is_negative`.
*/
+#[inline(always)]
pub pure fn is_nonpositive(x: f32) -> bool {
return x < 0.0f32 || (1.0f32/x) == neg_infinity;
}
*
* This is the same as `f32::is_positive`.)
*/
+#[inline(always)]
pub pure fn is_nonnegative(x: f32) -> bool {
return x > 0.0f32 || (1.0f32/x) == infinity;
}
/// Returns true if `x` is a zero number (positive or negative zero)
+#[inline(always)]
pub pure fn is_zero(x: f32) -> bool {
return x == 0.0f32 || x == -0.0f32;
}
/// Returns true if `x`is an infinite number
+#[inline(always)]
pub pure fn is_infinite(x: f32) -> bool {
return x == infinity || x == neg_infinity;
}
/// Returns true if `x`is a finite number
+#[inline(always)]
pub pure fn is_finite(x: f32) -> bool {
return !(is_NaN(x) || is_infinite(x));
}
pub const ln_10: f32 = 2.30258509299404568401799145468436421_f32;
}
+#[inline(always)]
pub pure fn signbit(x: f32) -> int {
if is_negative(x) { return 1; } else { return 0; }
}
+#[inline(always)]
pub pure fn logarithm(n: f32, b: f32) -> f32 {
return log2(n) / log2(b);
}
#[cfg(notest)]
impl f32 : cmp::Eq {
+ #[inline(always)]
pure fn eq(&self, other: &f32) -> bool { (*self) == (*other) }
+ #[inline(always)]
pure fn ne(&self, other: &f32) -> bool { (*self) != (*other) }
}
#[cfg(notest)]
impl f32 : cmp::Ord {
+ #[inline(always)]
pure fn lt(&self, other: &f32) -> bool { (*self) < (*other) }
+ #[inline(always)]
pure fn le(&self, other: &f32) -> bool { (*self) <= (*other) }
+ #[inline(always)]
pure fn ge(&self, other: &f32) -> bool { (*self) >= (*other) }
+ #[inline(always)]
pure fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
}
impl f32: num::Num {
+ #[inline(always)]
pure fn add(&self, other: &f32) -> f32 { return *self + *other; }
+ #[inline(always)]
pure fn sub(&self, other: &f32) -> f32 { return *self - *other; }
+ #[inline(always)]
pure fn mul(&self, other: &f32) -> f32 { return *self * *other; }
+ #[inline(always)]
pure fn div(&self, other: &f32) -> f32 { return *self / *other; }
+ #[inline(always)]
pure fn modulo(&self, other: &f32) -> f32 { return *self % *other; }
+ #[inline(always)]
pure fn neg(&self) -> f32 { return -*self; }
+ #[inline(always)]
pure fn to_int(&self) -> int { return *self as int; }
+ #[inline(always)]
static pure fn from_int(n: int) -> f32 { return n as f32; }
}
impl f32: num::Zero {
+ #[inline(always)]
static pure fn zero() -> f32 { 0.0 }
}
impl f32: num::One {
+ #[inline(always)]
static pure fn one() -> f32 { 1.0 }
}
//! Operations and constants for `f64`
-pub use cmath::c_double_utils::*;
+use cmath;
+use cmp;
+use libc::{c_double, c_int};
+use libc;
+use num;
+
pub use cmath::c_double_targ_consts::*;
+macro_rules! delegate(
+ (
+ fn $name:ident(
+ $(
+ $arg:ident : $arg_ty:ty
+ ),*
+ ) -> $rv:ty = $bound_name:path
+ ) => (
+ pub pure fn $name($( $arg : $arg_ty ),*) -> $rv {
+ unsafe {
+ $bound_name($( $arg ),*)
+ }
+ }
+ )
+)
+
+delegate!(fn acos(n: c_double) -> c_double = cmath::c_double_utils::acos)
+delegate!(fn asin(n: c_double) -> c_double = cmath::c_double_utils::asin)
+delegate!(fn atan(n: c_double) -> c_double = cmath::c_double_utils::atan)
+delegate!(fn atan2(a: c_double, b: c_double) -> c_double =
+ cmath::c_double_utils::atan2)
+delegate!(fn cbrt(n: c_double) -> c_double = cmath::c_double_utils::cbrt)
+delegate!(fn ceil(n: c_double) -> c_double = cmath::c_double_utils::ceil)
+delegate!(fn copysign(x: c_double, y: c_double) -> c_double =
+ cmath::c_double_utils::copysign)
+delegate!(fn cos(n: c_double) -> c_double = cmath::c_double_utils::cos)
+delegate!(fn cosh(n: c_double) -> c_double = cmath::c_double_utils::cosh)
+delegate!(fn erf(n: c_double) -> c_double = cmath::c_double_utils::erf)
+delegate!(fn erfc(n: c_double) -> c_double = cmath::c_double_utils::erfc)
+delegate!(fn exp(n: c_double) -> c_double = cmath::c_double_utils::exp)
+delegate!(fn expm1(n: c_double) -> c_double = cmath::c_double_utils::expm1)
+delegate!(fn exp2(n: c_double) -> c_double = cmath::c_double_utils::exp2)
+delegate!(fn abs(n: c_double) -> c_double = cmath::c_double_utils::abs)
+delegate!(fn abs_sub(a: c_double, b: c_double) -> c_double =
+ cmath::c_double_utils::abs_sub)
+delegate!(fn floor(n: c_double) -> c_double = cmath::c_double_utils::floor)
+delegate!(fn mul_add(a: c_double, b: c_double, c: c_double) -> c_double =
+ cmath::c_double_utils::mul_add)
+delegate!(fn fmax(a: c_double, b: c_double) -> c_double =
+ cmath::c_double_utils::fmax)
+delegate!(fn fmin(a: c_double, b: c_double) -> c_double =
+ cmath::c_double_utils::fmin)
+delegate!(fn nextafter(x: c_double, y: c_double) -> c_double =
+ cmath::c_double_utils::nextafter)
+delegate!(fn frexp(n: c_double, value: &mut c_int) -> c_double =
+ cmath::c_double_utils::frexp)
+delegate!(fn hypot(x: c_double, y: c_double) -> c_double =
+ cmath::c_double_utils::hypot)
+delegate!(fn ldexp(x: c_double, n: c_int) -> c_double =
+ cmath::c_double_utils::ldexp)
+delegate!(fn lgamma(n: c_double, sign: &mut c_int) -> c_double =
+ cmath::c_double_utils::lgamma)
+delegate!(fn ln(n: c_double) -> c_double = cmath::c_double_utils::ln)
+delegate!(fn log_radix(n: c_double) -> c_double =
+ cmath::c_double_utils::log_radix)
+delegate!(fn ln1p(n: c_double) -> c_double = cmath::c_double_utils::ln1p)
+delegate!(fn log10(n: c_double) -> c_double = cmath::c_double_utils::log10)
+delegate!(fn log2(n: c_double) -> c_double = cmath::c_double_utils::log2)
+delegate!(fn ilog_radix(n: c_double) -> c_int =
+ cmath::c_double_utils::ilog_radix)
+delegate!(fn modf(n: c_double, iptr: &mut c_double) -> c_double =
+ cmath::c_double_utils::modf)
+delegate!(fn pow(n: c_double, e: c_double) -> c_double =
+ cmath::c_double_utils::pow)
+delegate!(fn round(n: c_double) -> c_double = cmath::c_double_utils::round)
+delegate!(fn ldexp_radix(n: c_double, i: c_int) -> c_double =
+ cmath::c_double_utils::ldexp_radix)
+delegate!(fn sin(n: c_double) -> c_double = cmath::c_double_utils::sin)
+delegate!(fn sinh(n: c_double) -> c_double = cmath::c_double_utils::sinh)
+delegate!(fn sqrt(n: c_double) -> c_double = cmath::c_double_utils::sqrt)
+delegate!(fn tan(n: c_double) -> c_double = cmath::c_double_utils::tan)
+delegate!(fn tanh(n: c_double) -> c_double = cmath::c_double_utils::tanh)
+delegate!(fn tgamma(n: c_double) -> c_double = cmath::c_double_utils::tgamma)
+delegate!(fn trunc(n: c_double) -> c_double = cmath::c_double_utils::trunc)
+delegate!(fn j0(n: c_double) -> c_double = cmath::c_double_utils::j0)
+delegate!(fn j1(n: c_double) -> c_double = cmath::c_double_utils::j1)
+delegate!(fn jn(i: c_int, n: c_double) -> c_double =
+ cmath::c_double_utils::jn)
+delegate!(fn y0(n: c_double) -> c_double = cmath::c_double_utils::y0)
+delegate!(fn y1(n: c_double) -> c_double = cmath::c_double_utils::y1)
+delegate!(fn yn(i: c_int, n: c_double) -> c_double =
+ cmath::c_double_utils::yn)
+
// FIXME (#1433): obtain these in a different way
// These are not defined inside consts:: for consistency with
pub const neg_infinity: f64 = -1.0_f64/0.0_f64;
+#[inline(always)]
pub pure fn is_NaN(f: f64) -> bool { f != f }
+#[inline(always)]
pub pure fn add(x: f64, y: f64) -> f64 { return x + y; }
+#[inline(always)]
pub pure fn sub(x: f64, y: f64) -> f64 { return x - y; }
+#[inline(always)]
pub pure fn mul(x: f64, y: f64) -> f64 { return x * y; }
+#[inline(always)]
pub pure fn div(x: f64, y: f64) -> f64 { return x / y; }
+#[inline(always)]
pub pure fn rem(x: f64, y: f64) -> f64 { return x % y; }
+#[inline(always)]
pub pure fn lt(x: f64, y: f64) -> bool { return x < y; }
+#[inline(always)]
pub pure fn le(x: f64, y: f64) -> bool { return x <= y; }
+#[inline(always)]
pub pure fn eq(x: f64, y: f64) -> bool { return x == y; }
+#[inline(always)]
pub pure fn ne(x: f64, y: f64) -> bool { return x != y; }
+#[inline(always)]
pub pure fn ge(x: f64, y: f64) -> bool { return x >= y; }
+#[inline(always)]
pub pure fn gt(x: f64, y: f64) -> bool { return x > y; }
-pub pure fn sqrt(x: f64) -> f64 {
- cmath::c_double_utils::sqrt(x as libc::c_double) as f64
-}
-
/// Returns true if `x` is a positive number, including +0.0f640 and +Infinity
+#[inline(always)]
pub pure fn is_positive(x: f64) -> bool
{ return x > 0.0f64 || (1.0f64/x) == infinity; }
/// Returns true if `x` is a negative number, including -0.0f640 and -Infinity
+#[inline(always)]
pub pure fn is_negative(x: f64) -> bool
{ return x < 0.0f64 || (1.0f64/x) == neg_infinity; }
*
* This is the same as `f64::is_negative`.
*/
+#[inline(always)]
pub pure fn is_nonpositive(x: f64) -> bool {
return x < 0.0f64 || (1.0f64/x) == neg_infinity;
}
*
* This is the same as `f64::positive`.
*/
+#[inline(always)]
pub pure fn is_nonnegative(x: f64) -> bool {
return x > 0.0f64 || (1.0f64/x) == infinity;
}
/// Returns true if `x` is a zero number (positive or negative zero)
+#[inline(always)]
pub pure fn is_zero(x: f64) -> bool {
return x == 0.0f64 || x == -0.0f64;
}
/// Returns true if `x`is an infinite number
+#[inline(always)]
pub pure fn is_infinite(x: f64) -> bool {
return x == infinity || x == neg_infinity;
}
/// Returns true if `x`is a finite number
+#[inline(always)]
pub pure fn is_finite(x: f64) -> bool {
return !(is_NaN(x) || is_infinite(x));
}
pub const ln_10: f64 = 2.30258509299404568401799145468436421_f64;
}
+#[inline(always)]
pub pure fn signbit(x: f64) -> int {
if is_negative(x) { return 1; } else { return 0; }
}
+#[inline(always)]
pub pure fn logarithm(n: f64, b: f64) -> f64 {
return log2(n) / log2(b);
}
#[cfg(notest)]
impl f64 : cmp::Eq {
+ #[inline(always)]
pure fn eq(&self, other: &f64) -> bool { (*self) == (*other) }
+ #[inline(always)]
pure fn ne(&self, other: &f64) -> bool { (*self) != (*other) }
}
#[cfg(notest)]
impl f64 : cmp::Ord {
+ #[inline(always)]
pure fn lt(&self, other: &f64) -> bool { (*self) < (*other) }
+ #[inline(always)]
pure fn le(&self, other: &f64) -> bool { (*self) <= (*other) }
+ #[inline(always)]
pure fn ge(&self, other: &f64) -> bool { (*self) >= (*other) }
+ #[inline(always)]
pure fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
}
impl f64: num::Num {
+ #[inline(always)]
pure fn add(&self, other: &f64) -> f64 { return *self + *other; }
+ #[inline(always)]
pure fn sub(&self, other: &f64) -> f64 { return *self - *other; }
+ #[inline(always)]
pure fn mul(&self, other: &f64) -> f64 { return *self * *other; }
+ #[inline(always)]
pure fn div(&self, other: &f64) -> f64 { return *self / *other; }
+ #[inline(always)]
pure fn modulo(&self, other: &f64) -> f64 { return *self % *other; }
+ #[inline(always)]
pure fn neg(&self) -> f64 { return -*self; }
+ #[inline(always)]
pure fn to_int(&self) -> int { return *self as int; }
+ #[inline(always)]
static pure fn from_int(n: int) -> f64 { return n as f64; }
}
impl f64: num::Zero {
+ #[inline(always)]
static pure fn zero() -> f64 { 0.0 }
}
impl f64: num::One {
+ #[inline(always)]
static pure fn one() -> f64 { 1.0 }
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use libc;
use libc::{c_void, size_t, c_int};
+use ptr;
+use rand;
+use vec;
extern mod rustrt {
- fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
- src_buf_len: size_t,
- pout_len: *size_t,
- flags: c_int) -> *c_void;
+ unsafe fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
+ src_buf_len: size_t,
+ pout_len: *size_t,
+ flags: c_int) -> *c_void;
- fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
- src_buf_len: size_t,
- pout_len: *size_t,
- flags: c_int) -> *c_void;
+ unsafe fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
+ src_buf_len: size_t,
+ pout_len: *size_t,
+ flags: c_int) -> *c_void;
}
const lz_none : c_int = 0x0; // Huffman-coding only.
}
debug!("de/inflate of %u bytes of random word-sequences",
in.len());
- let cmp = flate::deflate_bytes(in);
- let out = flate::inflate_bytes(cmp);
+ let cmp = deflate_bytes(in);
+ let out = inflate_bytes(cmp);
debug!("%u bytes deflated to %u (%.1f%% size)",
in.len(), cmp.len(),
100.0 * ((cmp.len() as float) / (in.len() as float)));
use m_float = f64;
+use cmp::{Eq, Ord};
+use cmp;
+use f64;
+use num;
+use num::Num::from_int;
+use option::{None, Option, Some};
+use str;
+use uint;
+
pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt};
pub use f64::logarithm;
pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor};
pub use f64::{modf, pow, round, sinh, tanh, tgamma, trunc};
pub use f64::signbit;
pub use f64::{j0, j1, jn, y0, y1, yn};
-use cmp::{Eq, Ord};
-use num::Num::from_int;
pub const NaN: float = 0.0/0.0;
* * num - The float value
* * digits - The number of significant digits
*/
+#[inline(always)]
pub pure fn to_str_exact(num: float, digits: uint) -> ~str {
to_str_common(num, digits, true)
}
* * num - The float value
* * digits - The number of significant digits
*/
+#[inline(always)]
pub pure fn to_str(num: float, digits: uint) -> ~str {
to_str_common(num, digits, false)
}
return total;
}
+#[inline(always)]
pub pure fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
+#[inline(always)]
pub pure fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
+#[inline(always)]
pub pure fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
+#[inline(always)]
pub pure fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
+#[inline(always)]
pub pure fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
+#[inline(always)]
pub pure fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
+#[inline(always)]
pub pure fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
+#[inline(always)]
pub pure fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
-pub pure fn abs(x: float) -> float { f64::abs(x as f64) as float }
-pub pure fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float }
-pub pure fn atan(x: float) -> float { f64::atan(x as f64) as float }
-pub pure fn sin(x: float) -> float { f64::sin(x as f64) as float }
-pub pure fn cos(x: float) -> float { f64::cos(x as f64) as float }
-pub pure fn tan(x: float) -> float { f64::tan(x as f64) as float }
+#[inline(always)]
+pub pure fn abs(x: float) -> float {
+ unsafe { f64::abs(x as f64) as float }
+}
+#[inline(always)]
+pub pure fn sqrt(x: float) -> float {
+ unsafe { f64::sqrt(x as f64) as float }
+}
+#[inline(always)]
+pub pure fn atan(x: float) -> float {
+ unsafe { f64::atan(x as f64) as float }
+}
+#[inline(always)]
+pub pure fn sin(x: float) -> float {
+ unsafe { f64::sin(x as f64) as float }
+}
+#[inline(always)]
+pub pure fn cos(x: float) -> float {
+ unsafe { f64::cos(x as f64) as float }
+}
+#[inline(always)]
+pub pure fn tan(x: float) -> float {
+ unsafe { f64::tan(x as f64) as float }
+}
#[cfg(notest)]
impl float : Eq {
}
impl float: num::Zero {
+ #[inline(always)]
static pure fn zero() -> float { 0.0 }
}
impl float: num::One {
+ #[inline(always)]
static pure fn one() -> float { 1.0 }
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
-pub use stackwalk::Word;
-use libc::size_t;
-use libc::uintptr_t;
+use cast;
+use io;
+use libc::{size_t, uintptr_t};
+use option::{None, Option, Some};
+use ptr;
use send_map::linear::LinearMap;
+use stackwalk;
+use sys;
+
+pub use stackwalk::Word;
// Mirrors rust_stack.h stk_seg
struct StackSegment {
extern mod rustrt {
#[legacy_exports];
#[rust_stack]
- fn rust_call_tydesc_glue(root: *Word, tydesc: *Word, field: size_t);
+ unsafe fn rust_call_tydesc_glue(root: *Word,
+ tydesc: *Word,
+ field: size_t);
#[rust_stack]
- fn rust_gc_metadata() -> *Word;
+ unsafe fn rust_gc_metadata() -> *Word;
- fn rust_get_stack_segment() -> *StackSegment;
+ unsafe fn rust_get_stack_segment() -> *StackSegment;
}
unsafe fn bump<T, U>(ptr: *T, count: uint) -> *U {
roots.insert(*root, ());
if ptr::is_null(tydesc) {
- // XXX: Destroy this box
+ // FIXME #4420: Destroy this box
} else {
rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
}
* CPRNG like rand::rng.
*/
-use io::Writer;
-use io::WriterUtil;
+use io;
+use io::{Writer, WriterUtil};
+use os;
use to_bytes::IterBytes;
+use uint;
+use vec;
/**
* Types that can meaningfully be hashed should implement this.
use T = self::inst::T;
+use char;
use cmp::{Eq, Ord};
+use cmp;
use from_str::FromStr;
+use iter;
+use num;
use num::Num::from_int;
+use prelude::*;
+use str;
+use uint;
+use vec;
pub const bits : uint = inst::bits;
pub const bytes : uint = (inst::bits / 8);
pub const min_value: T = (-1 as T) << (bits - 1);
pub const max_value: T = min_value - 1 as T;
+#[inline(always)]
pub pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
+#[inline(always)]
pub pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }
+#[inline(always)]
pub pure fn add(x: T, y: T) -> T { x + y }
+#[inline(always)]
pub pure fn sub(x: T, y: T) -> T { x - y }
+#[inline(always)]
pub pure fn mul(x: T, y: T) -> T { x * y }
+#[inline(always)]
pub pure fn div(x: T, y: T) -> T { x / y }
+#[inline(always)]
pub pure fn rem(x: T, y: T) -> T { x % y }
+#[inline(always)]
pub pure fn lt(x: T, y: T) -> bool { x < y }
+#[inline(always)]
pub pure fn le(x: T, y: T) -> bool { x <= y }
+#[inline(always)]
pub pure fn eq(x: T, y: T) -> bool { x == y }
+#[inline(always)]
pub pure fn ne(x: T, y: T) -> bool { x != y }
+#[inline(always)]
pub pure fn ge(x: T, y: T) -> bool { x >= y }
+#[inline(always)]
pub pure fn gt(x: T, y: T) -> bool { x > y }
+#[inline(always)]
pub pure fn is_positive(x: T) -> bool { x > 0 as T }
+#[inline(always)]
pub pure fn is_negative(x: T) -> bool { x < 0 as T }
+#[inline(always)]
pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
+#[inline(always)]
pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
#[inline(always)]
}
/// Computes the bitwise complement
+#[inline(always)]
pub pure fn compl(i: T) -> T {
-1 as T ^ i
}
/// Computes the absolute value
+#[inline(always)]
pub pure fn abs(i: T) -> T {
if is_negative(i) { -i } else { i }
}
#[cfg(notest)]
impl T : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &T) -> bool { return (*self) < (*other); }
+ #[inline(always)]
pure fn le(&self, other: &T) -> bool { return (*self) <= (*other); }
+ #[inline(always)]
pure fn ge(&self, other: &T) -> bool { return (*self) >= (*other); }
+ #[inline(always)]
pure fn gt(&self, other: &T) -> bool { return (*self) > (*other); }
}
#[cfg(notest)]
impl T : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &T) -> bool { return (*self) == (*other); }
+ #[inline(always)]
pure fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
}
impl T: num::Num {
+ #[inline(always)]
pure fn add(&self, other: &T) -> T { return *self + *other; }
+ #[inline(always)]
pure fn sub(&self, other: &T) -> T { return *self - *other; }
+ #[inline(always)]
pure fn mul(&self, other: &T) -> T { return *self * *other; }
+ #[inline(always)]
pure fn div(&self, other: &T) -> T { return *self / *other; }
+ #[inline(always)]
pure fn modulo(&self, other: &T) -> T { return *self % *other; }
+ #[inline(always)]
pure fn neg(&self) -> T { return -*self; }
+ #[inline(always)]
pure fn to_int(&self) -> int { return *self as int; }
+ #[inline(always)]
static pure fn from_int(n: int) -> T { return n as T; }
}
impl T: num::Zero {
+ #[inline(always)]
static pure fn zero() -> T { 0 }
}
impl T: num::One {
+ #[inline(always)]
static pure fn one() -> T { 1 }
}
}
/// Parse a string to an int
+#[inline(always)]
pub pure fn from_str(s: &str) -> Option<T>
{
parse_bytes(str::to_bytes(s), 10u)
}
impl T : FromStr {
+ #[inline(always)]
static pure fn from_str(s: &str) -> Option<T> { from_str(s) }
}
/// Convert to a string in a given base
+#[inline(always)]
pub pure fn to_str(n: T, radix: uint) -> ~str {
do to_str_bytes(n, radix) |slice| {
do vec::as_imm_buf(slice) |p, len| {
}
}
+#[inline(always)]
pub pure fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U {
if n < 0 as T {
uint::to_str_bytes(true, -n as uint, radix, f)
}
/// Convert to a string
+#[inline(always)]
pub pure fn str(i: T) -> ~str { return to_str(i, 10u); }
#[test]
mod inst {
pub type T = i16;
- pub const bits: uint = u16::bits;
-}
\ No newline at end of file
+ pub const bits: uint = ::u16::bits;
+}
mod inst {
pub type T = i32;
- pub const bits: uint = u32::bits;
+ pub const bits: uint = ::u32::bits;
}
mod inst {
pub type T = i64;
- pub const bits: uint = u64::bits;
-}
\ No newline at end of file
+ pub const bits: uint = ::u64::bits;
+}
mod inst {
pub type T = i8;
- pub const bits: uint = u8::bits;
-}
\ No newline at end of file
+ pub const bits: uint = ::u8::bits;
+}
mod inst {
pub type T = int;
- pub const bits: uint = uint::bits;
+ pub const bits: uint = ::uint::bits;
/// Returns `base` raised to the power of `exponent`
pub pure fn pow(base: int, exponent: uint) -> int {
#[test]
fn test_overflows() {
- assert (max_value > 0);
- assert (min_value <= 0);
- assert (min_value + max_value + 1 == 0);
+ assert (::int::max_value > 0);
+ assert (::int::min_value <= 0);
+ assert (::int::min_value + ::int::max_value + 1 == 0);
}
}
use cmp::Eq;
use dvec::DVec;
+use int;
+use libc;
use libc::{c_int, c_long, c_uint, c_void, size_t, ssize_t};
use libc::consts::os::posix88::*;
use libc::consts::os::extra::*;
+use option;
+use os;
+use prelude::*;
+use ptr;
+use result;
+use str;
+use uint;
+use vec;
#[allow(non_camel_case_types)] // not sure what to do about this
-type fd_t = c_int;
+pub type fd_t = c_int;
#[abi = "cdecl"]
extern mod rustrt {
- fn rust_get_stdin() -> *libc::FILE;
- fn rust_get_stdout() -> *libc::FILE;
- fn rust_get_stderr() -> *libc::FILE;
+ unsafe fn rust_get_stdin() -> *libc::FILE;
+ unsafe fn rust_get_stdout() -> *libc::FILE;
+ unsafe fn rust_get_stderr() -> *libc::FILE;
}
// Reading
impl *libc::FILE: Reader {
fn read(&self, bytes: &[mut u8], len: uint) -> uint {
- do vec::as_mut_buf(bytes) |buf_p, buf_len| {
- assert buf_len >= len;
+ unsafe {
+ do vec::as_mut_buf(bytes) |buf_p, buf_len| {
+ assert buf_len >= len;
- let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
- len as size_t, *self);
+ let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
+ len as size_t, *self);
- count as uint
+ count as uint
+ }
+ }
+ }
+ fn read_byte(&self) -> int {
+ unsafe {
+ libc::fgetc(*self) as int
+ }
+ }
+ fn eof(&self) -> bool {
+ unsafe {
+ return libc::feof(*self) != 0 as c_int;
}
}
- fn read_byte(&self) -> int { return libc::fgetc(*self) as int; }
- fn eof(&self) -> bool { return libc::feof(*self) != 0 as c_int; }
fn seek(&self, offset: int, whence: SeekStyle) {
- assert libc::fseek(*self, offset as c_long, convert_whence(whence))
- == 0 as c_int;
+ unsafe {
+ assert libc::fseek(*self,
+ offset as c_long,
+ convert_whence(whence)) == 0 as c_int;
+ }
+ }
+ fn tell(&self) -> uint {
+ unsafe {
+ return libc::ftell(*self) as uint;
+ }
}
- fn tell(&self) -> uint { return libc::ftell(*self) as uint; }
}
// A forwarding impl of reader that also holds on to a resource for the
fn tell(&self) -> uint { self.base.tell() }
}
-struct FILERes {
+pub struct FILERes {
f: *libc::FILE,
- drop { libc::fclose(self.f); }
+ drop {
+ unsafe {
+ libc::fclose(self.f);
+ }
+ }
}
-fn FILERes(f: *libc::FILE) -> FILERes {
+pub fn FILERes(f: *libc::FILE) -> FILERes {
FILERes {
f: f
}
// top-level functions that take a reader, or a set of default methods on
// reader (which can then be called reader)
-pub fn stdin() -> Reader { rustrt::rust_get_stdin() as Reader }
+pub fn stdin() -> Reader {
+ unsafe {
+ rustrt::rust_get_stdin() as Reader
+ }
+}
pub fn file_reader(path: &Path) -> Result<Reader, ~str> {
- let f = os::as_c_charp(path.to_str(), |pathbuf| {
- os::as_c_charp("r", |modebuf|
- libc::fopen(pathbuf, modebuf)
- )
- });
- return if f as uint == 0u { result::Err(~"error opening "
- + path.to_str()) }
- else {
- result::Ok(FILE_reader(f, true))
+ unsafe {
+ let f = os::as_c_charp(path.to_str(), |pathbuf| {
+ os::as_c_charp("r", |modebuf|
+ libc::fopen(pathbuf, modebuf)
+ )
+ });
+ return if f as uint == 0u { result::Err(~"error opening "
+ + path.to_str()) }
+ else {
+ result::Ok(FILE_reader(f, true))
+ }
}
}
let count = uint::min(len, self.bytes.len() - self.pos);
let view = vec::view(self.bytes, self.pos, self.bytes.len());
- vec::bytes::memcpy(bytes, view, count);
+ vec::bytes::copy_memory(bytes, view, count);
self.pos += count;
impl *libc::FILE: Writer {
fn write(&self, v: &[const u8]) {
- do vec::as_const_buf(v) |vbuf, len| {
- let nout = libc::fwrite(vbuf as *c_void, 1, len as size_t, *self);
- if nout != len as size_t {
- error!("error writing buffer");
- log(error, os::last_os_error());
- fail;
+ unsafe {
+ do vec::as_const_buf(v) |vbuf, len| {
+ let nout = libc::fwrite(vbuf as *c_void,
+ 1,
+ len as size_t,
+ *self);
+ if nout != len as size_t {
+ error!("error writing buffer");
+ log(error, os::last_os_error());
+ fail;
+ }
}
}
}
fn seek(&self, offset: int, whence: SeekStyle) {
- assert libc::fseek(*self, offset as c_long, convert_whence(whence))
- == 0 as c_int;
+ unsafe {
+ assert libc::fseek(*self,
+ offset as c_long,
+ convert_whence(whence)) == 0 as c_int;
+ }
+ }
+ fn tell(&self) -> uint {
+ unsafe {
+ libc::ftell(*self) as uint
+ }
+ }
+ fn flush(&self) -> int {
+ unsafe {
+ libc::fflush(*self) as int
+ }
}
- fn tell(&self) -> uint { libc::ftell(*self) as uint }
- fn flush(&self) -> int { libc::fflush(*self) as int }
fn get_type(&self) -> WriterType {
- let fd = libc::fileno(*self);
- if libc::isatty(fd) == 0 { File }
- else { Screen }
+ unsafe {
+ let fd = libc::fileno(*self);
+ if libc::isatty(fd) == 0 { File }
+ else { Screen }
+ }
}
}
impl fd_t: Writer {
fn write(&self, v: &[const u8]) {
- let mut count = 0u;
- do vec::as_const_buf(v) |vbuf, len| {
- while count < len {
- let vb = ptr::const_offset(vbuf, count) as *c_void;
- let nout = libc::write(*self, vb, len as size_t);
- if nout < 0 as ssize_t {
- error!("error writing buffer");
- log(error, os::last_os_error());
- fail;
+ unsafe {
+ let mut count = 0u;
+ do vec::as_const_buf(v) |vbuf, len| {
+ while count < len {
+ let vb = ptr::const_offset(vbuf, count) as *c_void;
+ let nout = libc::write(*self, vb, len as size_t);
+ if nout < 0 as ssize_t {
+ error!("error writing buffer");
+ log(error, os::last_os_error());
+ fail;
+ }
+ count += nout as uint;
}
- count += nout as uint;
}
}
}
}
fn flush(&self) -> int { 0 }
fn get_type(&self) -> WriterType {
- if libc::isatty(*self) == 0 { File } else { Screen }
+ unsafe {
+ if libc::isatty(*self) == 0 { File } else { Screen }
+ }
}
}
-struct FdRes {
+pub struct FdRes {
fd: fd_t,
- drop { libc::close(self.fd); }
+ drop {
+ unsafe {
+ libc::close(self.fd);
+ }
+ }
}
-fn FdRes(fd: fd_t) -> FdRes {
+pub fn FdRes(fd: fd_t) -> FdRes {
FdRes {
fd: fd
}
NoFlag => ()
}
}
- let fd = do os::as_c_charp(path.to_str()) |pathbuf| {
- libc::open(pathbuf, fflags,
- (S_IRUSR | S_IWUSR) as c_int)
+ let fd = unsafe {
+ do os::as_c_charp(path.to_str()) |pathbuf| {
+ libc::open(pathbuf, fflags,
+ (S_IRUSR | S_IWUSR) as c_int)
+ }
};
if fd < (0 as c_int) {
result::Err(fmt!("error opening %s: %s", path.to_str(),
// FIXME: fileflags // #2004
pub fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
- let f = do os::as_c_charp(path.to_str()) |pathbuf| {
- do os::as_c_charp("w") |modebuf| {
- libc::fopen(pathbuf, modebuf)
- }
- };
- return if f as uint == 0u { result::Err(~"error opening "
- + path.to_str()) }
- else { result::Ok(FILE_writer(f, true)) }
+ unsafe {
+ let f = do os::as_c_charp(path.to_str()) |pathbuf| {
+ do os::as_c_charp("w") |modebuf| {
+ libc::fopen(pathbuf, modebuf)
+ }
+ };
+ return if f as uint == 0u { result::Err(~"error opening "
+ + path.to_str()) }
+ else { result::Ok(FILE_writer(f, true)) }
+ }
}
// FIXME (#2004) it would be great if this could be a const
{
let view = vec::mut_view(bytes, self.pos, count);
- vec::bytes::memcpy(view, v, v_len);
+ vec::bytes::copy_memory(view, v, v_len);
}
self.pos += v_len;
// fsync related
pub mod fsync {
+ use io::{FILERes, FdRes, fd_t};
+ use kinds::Copy;
+ use libc;
+ use option::Option;
+ use option;
+ use os;
pub enum Level {
// whatever fsync does on that platform
// outer res
pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
blk: fn(v: Res<*libc::FILE>)) {
- blk(move Res({
- val: file.f, opt_level: opt_level,
- fsync_fn: fn@(file: *libc::FILE, l: Level) -> int {
- return os::fsync_fd(libc::fileno(file), l) as int;
- }
- }));
+ unsafe {
+ blk(move Res({
+ val: file.f, opt_level: opt_level,
+ fsync_fn: fn@(file: *libc::FILE, l: Level) -> int {
+ unsafe {
+ return os::fsync_fd(libc::fileno(file), l) as int;
+ }
+ }
+ }));
+ }
}
// fsync fd after executing blk
#[cfg(test)]
mod tests {
+ use debug;
+ use i32;
+ use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
+ use io;
+ use path::Path;
+ use result;
+ use str;
+ use u64;
+ use vec;
#[test]
fn test_simple() {
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord};
+use iter::BaseIter;
+use iter;
+use kinds::Copy;
+use option::Option;
use self::inst::{IMPL_T, EACH, SIZE_HINT};
impl<A> IMPL_T<A>: iter::BaseIter<A> {
+ #[inline(always)]
pure fn each(&self, blk: fn(v: &A) -> bool) { EACH(self, blk) }
+ #[inline(always)]
pure fn size_hint(&self) -> Option<uint> { SIZE_HINT(self) }
}
impl<A> IMPL_T<A>: iter::ExtendedIter<A> {
+ #[inline(always)]
pure fn eachi(&self, blk: fn(uint, v: &A) -> bool) {
iter::eachi(self, blk)
}
+ #[inline(always)]
pure fn all(&self, blk: fn(&A) -> bool) -> bool {
iter::all(self, blk)
}
+ #[inline(always)]
pure fn any(&self, blk: fn(&A) -> bool) -> bool {
iter::any(self, blk)
}
+ #[inline(always)]
pure fn foldl<B>(&self, b0: B, blk: fn(&B, &A) -> B) -> B {
iter::foldl(self, move b0, blk)
}
+ #[inline(always)]
pure fn position(&self, f: fn(&A) -> bool) -> Option<uint> {
iter::position(self, f)
}
+ #[inline(always)]
pure fn map_to_vec<B>(&self, op: fn(&A) -> B) -> ~[B] {
iter::map_to_vec(self, op)
}
+ #[inline(always)]
pure fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: fn(&A) -> IB)
-> ~[B] {
iter::flat_map_to_vec(self, op)
}
impl<A: Eq> IMPL_T<A>: iter::EqIter<A> {
+ #[inline(always)]
pure fn contains(&self, x: &A) -> bool { iter::contains(self, x) }
+ #[inline(always)]
pure fn count(&self, x: &A) -> uint { iter::count(self, x) }
}
impl<A: Copy> IMPL_T<A>: iter::CopyableIter<A> {
+ #[inline(always)]
pure fn filter_to_vec(&self, pred: fn(&A) -> bool) -> ~[A] {
iter::filter_to_vec(self, pred)
}
+ #[inline(always)]
pure fn to_vec(&self) -> ~[A] { iter::to_vec(self) }
+ #[inline(always)]
pure fn find(&self, f: fn(&A) -> bool) -> Option<A> {
iter::find(self, f)
}
}
impl<A: Copy Ord> IMPL_T<A>: iter::CopyableOrderedIter<A> {
+ #[inline(always)]
pure fn min(&self) -> A { iter::min(self) }
+ #[inline(always)]
pure fn max(&self) -> A { iter::max(self) }
}
// except according to those terms.
mod inst {
+ use dlist;
+ use managed;
+ use option::{Option, Some};
+ use option;
+
#[allow(non_camel_case_types)]
pub type IMPL_T<A> = dlist::DList<A>;
}
}
+ #[inline(always)]
pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> {
Some(self.len())
}
-}
\ No newline at end of file
+}
// except according to those terms.
mod inst {
+ use dvec;
+ use option::{Option, Some};
+
#[allow(non_camel_case_types)]
pub type IMPL_T<A> = dvec::DVec<A>;
*
* Attempts to access this dvec during iteration will fail.
*/
+ #[inline(always)]
pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) {
unsafe {
do self.swap |v| {
}
}
+ #[inline(always)]
pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> {
Some(self.len())
}
-}
\ No newline at end of file
+}
// except according to those terms.
mod inst {
+ use option::{None, Option, Some};
+
#[allow(non_camel_case_types)]
pub type IMPL_T<A> = Option<A>;
+ #[inline(always)]
pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) {
match *self {
None => (),
}
}
+ #[inline(always)]
pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> {
match *self {
None => Some(0),
Some(_) => Some(1)
}
}
-}
\ No newline at end of file
+}
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord};
+use kinds::Copy;
+use option::{None, Option, Some};
+use vec;
/// A function used to initialize the elements of a sequence
pub type InitOp<T> = &fn(uint) -> T;
* # Arguments
*
* * size - A hint for an initial size of the sequence
- * * builder - A function that will construct the sequence. It recieves
+ * * builder - A function that will construct the sequence. It receives
* as an argument a function that will push an element
* onto the sequence being constructed.
*/
builder: fn(push: pure fn(A))) -> self;
}
+#[inline(always)]
pub pure fn eachi<A,IA:BaseIter<A>>(self: &IA,
blk: fn(uint, &A) -> bool) {
let mut i = 0;
}
}
+#[inline(always)]
pub pure fn all<A,IA:BaseIter<A>>(self: &IA,
blk: fn(&A) -> bool) -> bool {
for self.each |a| {
return true;
}
+#[inline(always)]
pub pure fn any<A,IA:BaseIter<A>>(self: &IA,
blk: fn(&A) -> bool) -> bool {
for self.each |a| {
return false;
}
+#[inline(always)]
pub pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(
self: &IA, prd: fn(&A) -> bool) -> ~[A] {
do vec::build_sized_opt(self.size_hint()) |push| {
}
}
+#[inline(always)]
pub pure fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA,
op: fn(&A) -> B)
-> ~[B] {
}
}
+#[inline(always)]
pub pure fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(
self: &IA, op: fn(&A) -> IB) -> ~[B] {
do vec::build |push| {
}
}
+#[inline(always)]
pub pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B,
blk: fn(&B, &A) -> B)
-> B {
move b
}
+#[inline(always)]
pub pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
}
+#[inline(always)]
pub pure fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
for self.each |a| {
if *a == *x { return true; }
return false;
}
+#[inline(always)]
pub pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
do foldl(self, 0) |count, value| {
if *value == *x {
}
}
+#[inline(always)]
pub pure fn position<A,IA:BaseIter<A>>(self: &IA, f: fn(&A) -> bool)
-> Option<uint>
{
// iter interface, such as would provide "reach" in addition to "each". as is,
// it would have to be implemented with foldr, which is too inefficient.
+#[inline(always)]
pub pure fn repeat(times: uint, blk: fn() -> bool) {
let mut i = 0;
while i < times {
}
}
+#[inline(always)]
pub pure fn min<A:Copy Ord,IA:BaseIter<A>>(self: &IA) -> A {
match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
match a {
}
}
+#[inline(always)]
pub pure fn max<A:Copy Ord,IA:BaseIter<A>>(self: &IA) -> A {
match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
match a {
}
}
+#[inline(always)]
pub pure fn find<A: Copy,IA:BaseIter<A>>(self: &IA,
f: fn(&A) -> bool) -> Option<A> {
for self.each |i| {
*
* # Arguments
*
- * * builder - A function that will construct the sequence. It recieves
+ * * builder - A function that will construct the sequence. It receives
* as an argument a function that will push an element
* onto the sequence being constructed.
*/
*
* * size - An option, maybe containing initial size of the sequence
* to reserve
- * * builder - A function that will construct the sequence. It recieves
+ * * builder - A function that will construct the sequence. It receives
* as an argument a function that will push an element
* onto the sequence being constructed.
*/
size: Option<uint>,
builder: fn(push: pure fn(A))) -> B {
- Buildable::build_sized(size.get_default(4), builder)
+ Buildable::build_sized(size.get_or_default(4), builder)
}
// Functions that combine iteration and building
/// Apply a function to each element of an iterable and return the results
+#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: fn(&T) -> U)
-> BU {
do build_sized_opt(v.size_hint()) |push| {
* Creates a generic sequence of size `n_elts` and initializes the elements
* to the value returned by the function `op`.
*/
+#[inline(always)]
pub pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint,
op: InitOp<T>) -> BT {
do Buildable::build_sized(n_elts) |push| {
* Creates an immutable vector of size `n_elts` and initializes the elements
* to the value `t`.
*/
+#[inline(always)]
pub pure fn from_elem<T: Copy,BT: Buildable<T>>(n_elts: uint,
t: T) -> BT {
do Buildable::build_sized(n_elts) |push| {
pub use libc::funcs::posix88::unistd::{rmdir, unlink, write};
-mod types {
+pub mod types {
// Types tend to vary *per architecture* so we pull their definitions out
// into this module.
// Standard types that are scalar but vary by OS and arch.
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
pub mod os {
pub mod common {
pub mod posix01 {}
}
#[cfg(target_arch = "x86")]
+ #[cfg(target_arch = "arm")]
pub mod arch {
pub mod c95 {
pub type c_char = i8;
pub type uintptr_t = uint;
}
pub mod posix88 {
+ use prelude::*;
+
pub type off_t = i32;
pub type dev_t = u64;
pub type ino_t = u32;
pub type ssize_t = i32;
}
pub mod posix01 {
+ use libc::types::os::arch::c95::{c_int, c_short, c_long,
+ time_t};
+ use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+ use libc::types::os::arch::posix88::{mode_t, off_t};
+ use libc::types::os::arch::posix88::{uid_t};
+
pub type nlink_t = u32;
pub type blksize_t = i32;
pub type blkcnt_t = i32;
pub type ssize_t = i64;
}
pub mod posix01 {
+ use libc::types::os::arch::c95::{c_int, c_long, time_t};
+ use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+ use libc::types::os::arch::posix88::{mode_t, off_t};
+ use libc::types::os::arch::posix88::{uid_t};
+
pub type nlink_t = u64;
pub type blksize_t = i64;
pub type blkcnt_t = i64;
pub type ssize_t = i64;
}
pub mod posix01 {
+ use libc::types::common::c99::{uint8_t, uint32_t, int32_t};
+ use libc::types::os::arch::c95::{c_long, time_t};
+ use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+ use libc::types::os::arch::posix88::{mode_t, off_t};
+ use libc::types::os::arch::posix88::{uid_t};
+
pub type nlink_t = u16;
pub type blksize_t = i64;
pub type blkcnt_t = i64;
pub mod os {
pub mod common {
pub mod posix01 {
+ use libc::types::os::arch::c95::{c_int, c_short};
+ use libc::types::os::arch::extra::{int64, time64_t};
+ use libc::types::os::arch::posix88::{dev_t, ino_t};
+ use libc::types::os::arch::posix88::mode_t;
+
// Note: this is the struct called stat64 in win32. Not stat,
// nor stati64.
pub struct stat {
st_uid: c_short,
st_gid: c_short,
st_rdev: dev_t,
- st_size: int64_t,
+ st_size: int64,
st_atime: time64_t,
st_mtime: time64_t,
st_ctime: time64_t,
pub mod bsd44 {
}
pub mod extra {
+ use libc::types::common::c95::c_void;
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint};
+ use libc::types::os::arch::c95::{c_long, c_ulong};
+ use libc::types::os::arch::c95::{wchar_t};
+ use libc::types::os::arch::c99::{c_ulonglong};
+
pub type BOOL = c_int;
pub type BYTE = u8;
pub type CCHAR = c_char;
pub type WORD = u16;
pub type time64_t = i64;
+ pub type int64 = i64;
}
}
}
pub mod os {
pub mod common {
pub mod posix01 {
- pub type nlink_t = u16;
- pub type blksize_t = i64;
- pub type blkcnt_t = i32;
- pub struct stat {
- st_dev: dev_t,
- st_mode: mode_t,
- st_nlink: nlink_t,
- st_ino: ino_t,
- st_uid: uid_t,
- st_gid: gid_t,
- st_rdev: dev_t,
- st_atime: time_t,
- st_atime_nsec: c_long,
- st_mtime: time_t,
- st_mtime_nsec: c_long,
- st_ctime: time_t,
- st_ctime_nsec: c_long,
- st_birthtime: time_t,
- st_birthtime_nsec: c_long,
- st_size: off_t,
- st_blocks: blkcnt_t,
- st_blksize: blksize_t,
- st_flags: uint32_t,
- st_gen: uint32_t,
- st_lspare: int32_t,
- st_qspare: [int64_t * 2],
- }
}
}
pub type ssize_t = i32;
}
pub mod posix01 {
+ use libc::types::common::c99::{int32_t, int64_t, uint32_t};
+ use libc::types::os::arch::c95::{c_long, time_t};
+ use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t,
+ mode_t, off_t, uid_t};
+
+ pub type nlink_t = u16;
+ pub type blksize_t = i64;
+ pub type blkcnt_t = i32;
+
+ pub struct stat {
+ st_dev: dev_t,
+ st_mode: mode_t,
+ st_nlink: nlink_t,
+ st_ino: ino_t,
+ st_uid: uid_t,
+ st_gid: gid_t,
+ st_rdev: dev_t,
+ st_atime: time_t,
+ st_atime_nsec: c_long,
+ st_mtime: time_t,
+ st_mtime_nsec: c_long,
+ st_ctime: time_t,
+ st_ctime_nsec: c_long,
+ st_birthtime: time_t,
+ st_birthtime_nsec: c_long,
+ st_size: off_t,
+ st_blocks: blkcnt_t,
+ st_blksize: blksize_t,
+ st_flags: uint32_t,
+ st_gen: uint32_t,
+ st_lspare: int32_t,
+ st_qspare: [int64_t * 2],
+ }
}
pub mod posix08 {
}
pub type ssize_t = i64;
}
pub mod posix01 {
+ use libc::types::common::c99::{int32_t, int64_t};
+ use libc::types::common::c99::{uint32_t};
+ use libc::types::os::arch::c95::{c_long, time_t};
+ use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+ use libc::types::os::arch::posix88::{mode_t, off_t, uid_t};
+
+ pub type nlink_t = u16;
+ pub type blksize_t = i64;
+ pub type blkcnt_t = i32;
+
+ pub struct stat {
+ st_dev: dev_t,
+ st_mode: mode_t,
+ st_nlink: nlink_t,
+ st_ino: ino_t,
+ st_uid: uid_t,
+ st_gid: gid_t,
+ st_rdev: dev_t,
+ st_atime: time_t,
+ st_atime_nsec: c_long,
+ st_mtime: time_t,
+ st_mtime_nsec: c_long,
+ st_ctime: time_t,
+ st_ctime_nsec: c_long,
+ st_birthtime: time_t,
+ st_birthtime_nsec: c_long,
+ st_size: off_t,
+ st_blocks: blkcnt_t,
+ st_blksize: blksize_t,
+ st_flags: uint32_t,
+ st_gen: uint32_t,
+ st_lspare: int32_t,
+ st_qspare: [int64_t * 2],
+ }
}
pub mod posix08 {
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
pub mod os {
pub mod c95 {
pub const EXIT_FAILURE : int = 1;
// or anything. The same is not true of POSIX.
pub mod c95 {
+ use libc::types::common::c95::{FILE, c_void, fpos_t};
+ use libc::types::common::posix88::dirent_t;
+ use libc::types::os::arch::c95::{c_char, c_double, c_int, c_long};
+ use libc::types::os::arch::c95::{c_uint, c_ulong, c_void, size_t};
+
#[nolink]
#[abi = "cdecl"]
pub extern mod ctype {
- fn isalnum(c: c_int) -> c_int;
- fn isalpha(c: c_int) -> c_int;
- fn iscntrl(c: c_int) -> c_int;
- fn isdigit(c: c_int) -> c_int;
- fn isgraph(c: c_int) -> c_int;
- fn islower(c: c_int) -> c_int;
- fn isprint(c: c_int) -> c_int;
- fn ispunct(c: c_int) -> c_int;
- fn isspace(c: c_int) -> c_int;
- fn isupper(c: c_int) -> c_int;
- fn isxdigit(c: c_int) -> c_int;
- fn tolower(c: c_char) -> c_char;
- fn toupper(c: c_char) -> c_char;
+ unsafe fn isalnum(c: c_int) -> c_int;
+ unsafe fn isalpha(c: c_int) -> c_int;
+ unsafe fn iscntrl(c: c_int) -> c_int;
+ unsafe fn isdigit(c: c_int) -> c_int;
+ unsafe fn isgraph(c: c_int) -> c_int;
+ unsafe fn islower(c: c_int) -> c_int;
+ unsafe fn isprint(c: c_int) -> c_int;
+ unsafe fn ispunct(c: c_int) -> c_int;
+ unsafe fn isspace(c: c_int) -> c_int;
+ unsafe fn isupper(c: c_int) -> c_int;
+ unsafe fn isxdigit(c: c_int) -> c_int;
+ unsafe fn tolower(c: c_char) -> c_char;
+ unsafe fn toupper(c: c_char) -> c_char;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod stdio {
- fn fopen(filename: *c_char, mode: *c_char) -> *FILE;
- fn freopen(filename: *c_char, mode: *c_char,
+ unsafe fn fopen(filename: *c_char, mode: *c_char) -> *FILE;
+ unsafe fn freopen(filename: *c_char, mode: *c_char,
file: *FILE) -> *FILE;
- fn fflush(file: *FILE) -> c_int;
- fn fclose(file: *FILE) -> c_int;
- fn remove(filename: *c_char) -> c_int;
- fn rename(oldname: *c_char, newname: *c_char) -> c_int;
- fn tmpfile() -> *FILE;
- fn setvbuf(stream: *FILE, buffer: *c_char,
+ unsafe fn fflush(file: *FILE) -> c_int;
+ unsafe fn fclose(file: *FILE) -> c_int;
+ unsafe fn remove(filename: *c_char) -> c_int;
+ unsafe fn rename(oldname: *c_char, newname: *c_char) -> c_int;
+ unsafe fn tmpfile() -> *FILE;
+ unsafe fn setvbuf(stream: *FILE, buffer: *c_char,
mode: c_int, size: size_t) -> c_int;
- fn setbuf(stream: *FILE, buf: *c_char);
+ unsafe fn setbuf(stream: *FILE, buf: *c_char);
// Omitted: printf and scanf variants.
- fn fgetc(stream: *FILE) -> c_int;
- fn fgets(buf: *mut c_char, n: c_int,
+ unsafe fn fgetc(stream: *FILE) -> c_int;
+ unsafe fn fgets(buf: *mut c_char, n: c_int,
stream: *FILE) -> *c_char;
- fn fputc(c: c_int, stream: *FILE) -> c_int;
- fn fputs(s: *c_char, stream: *FILE) -> *c_char;
+ unsafe fn fputc(c: c_int, stream: *FILE) -> c_int;
+ unsafe fn fputs(s: *c_char, stream: *FILE) -> *c_char;
// Omitted: getc, getchar (might be macros).
// Omitted: gets, so ridiculously unsafe that it should not
// survive.
// Omitted: putc, putchar (might be macros).
- fn puts(s: *c_char) -> c_int;
- fn ungetc(c: c_int, stream: *FILE) -> c_int;
- fn fread(ptr: *mut c_void, size: size_t,
+ unsafe fn puts(s: *c_char) -> c_int;
+ unsafe fn ungetc(c: c_int, stream: *FILE) -> c_int;
+ unsafe fn fread(ptr: *mut c_void, size: size_t,
nobj: size_t, stream: *FILE) -> size_t;
- fn fwrite(ptr: *c_void, size: size_t,
+ unsafe fn fwrite(ptr: *c_void, size: size_t,
nobj: size_t, stream: *FILE) -> size_t;
- fn fseek(stream: *FILE, offset: c_long,
+ unsafe fn fseek(stream: *FILE, offset: c_long,
whence: c_int) -> c_int;
- fn ftell(stream: *FILE) -> c_long;
- fn rewind(stream: *FILE);
- fn fgetpos(stream: *FILE, ptr: *fpos_t) -> c_int;
- fn fsetpos(stream: *FILE, ptr: *fpos_t) -> c_int;
- fn feof(stream: *FILE) -> c_int;
- fn ferror(stream: *FILE) -> c_int;
- fn perror(s: *c_char);
+ unsafe fn ftell(stream: *FILE) -> c_long;
+ unsafe fn rewind(stream: *FILE);
+ unsafe fn fgetpos(stream: *FILE, ptr: *fpos_t) -> c_int;
+ unsafe fn fsetpos(stream: *FILE, ptr: *fpos_t) -> c_int;
+ unsafe fn feof(stream: *FILE) -> c_int;
+ unsafe fn ferror(stream: *FILE) -> c_int;
+ unsafe fn perror(s: *c_char);
}
#[nolink]
#[abi = "cdecl"]
pub extern mod stdlib {
- fn abs(i: c_int) -> c_int;
- fn labs(i: c_long) -> c_long;
+ unsafe fn abs(i: c_int) -> c_int;
+ unsafe fn labs(i: c_long) -> c_long;
// Omitted: div, ldiv (return pub type incomplete).
- fn atof(s: *c_char) -> c_double;
- fn atoi(s: *c_char) -> c_int;
- fn strtod(s: *c_char, endp: **c_char) -> c_double;
- fn strtol(s: *c_char, endp: **c_char, base: c_int) -> c_long;
- fn strtoul(s: *c_char, endp: **c_char,
- base: c_int) -> c_ulong;
- fn calloc(nobj: size_t, size: size_t) -> *c_void;
- fn malloc(size: size_t) -> *c_void;
- fn realloc(p: *c_void, size: size_t) -> *c_void;
- fn free(p: *c_void);
- fn abort() -> !;
- fn exit(status: c_int) -> !;
+ unsafe fn atof(s: *c_char) -> c_double;
+ unsafe fn atoi(s: *c_char) -> c_int;
+ unsafe fn strtod(s: *c_char, endp: **c_char) -> c_double;
+ unsafe fn strtol(s: *c_char, endp: **c_char, base: c_int)
+ -> c_long;
+ unsafe fn strtoul(s: *c_char, endp: **c_char, base: c_int)
+ -> c_ulong;
+ unsafe fn calloc(nobj: size_t, size: size_t) -> *c_void;
+ unsafe fn malloc(size: size_t) -> *c_void;
+ unsafe fn realloc(p: *c_void, size: size_t) -> *c_void;
+ unsafe fn free(p: *c_void);
+ unsafe fn abort() -> !;
+ unsafe fn exit(status: c_int) -> !;
// Omitted: atexit.
- fn system(s: *c_char) -> c_int;
- fn getenv(s: *c_char) -> *c_char;
+ unsafe fn system(s: *c_char) -> c_int;
+ unsafe fn getenv(s: *c_char) -> *c_char;
// Omitted: bsearch, qsort
- fn rand() -> c_int;
- fn srand(seed: c_uint);
+ unsafe fn rand() -> c_int;
+ unsafe fn srand(seed: c_uint);
}
#[nolink]
#[abi = "cdecl"]
pub extern mod string {
- fn strcpy(dst: *c_char, src: *c_char) -> *c_char;
- fn strncpy(dst: *c_char, src: *c_char, n: size_t) -> *c_char;
- fn strcat(s: *c_char, ct: *c_char) -> *c_char;
- fn strncat(s: *c_char, ct: *c_char, n: size_t) -> *c_char;
- fn strcmp(cs: *c_char, ct: *c_char) -> c_int;
- fn strncmp(cs: *c_char, ct: *c_char, n: size_t) -> c_int;
- fn strcoll(cs: *c_char, ct: *c_char) -> c_int;
- fn strchr(cs: *c_char, c: c_int) -> *c_char;
- fn strrchr(cs: *c_char, c: c_int) -> *c_char;
- fn strspn(cs: *c_char, ct: *c_char) -> size_t;
- fn strcspn(cs: *c_char, ct: *c_char) -> size_t;
- fn strpbrk(cs: *c_char, ct: *c_char) -> *c_char;
- fn strstr(cs: *c_char, ct: *c_char) -> *c_char;
- fn strlen(cs: *c_char) -> size_t;
- fn strerror(n: c_int) -> *c_char;
- fn strtok(s: *c_char, t: *c_char) -> *c_char;
- fn strxfrm(s: *c_char, ct: *c_char, n: size_t) -> size_t;
- fn memcpy(s: *c_void, ct: *c_void, n: size_t) -> *c_void;
- fn memmove(s: *c_void, ct: *c_void, n: size_t) -> *c_void;
- fn memcmp(cx: *c_void, ct: *c_void, n: size_t) -> c_int;
- fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void;
- fn memset(s: *c_void, c: c_int, n: size_t) -> *c_void;
+ unsafe fn strcpy(dst: *c_char, src: *c_char) -> *c_char;
+ unsafe fn strncpy(dst: *c_char, src: *c_char, n: size_t)
+ -> *c_char;
+ unsafe fn strcat(s: *c_char, ct: *c_char) -> *c_char;
+ unsafe fn strncat(s: *c_char, ct: *c_char, n: size_t) -> *c_char;
+ unsafe fn strcmp(cs: *c_char, ct: *c_char) -> c_int;
+ unsafe fn strncmp(cs: *c_char, ct: *c_char, n: size_t) -> c_int;
+ unsafe fn strcoll(cs: *c_char, ct: *c_char) -> c_int;
+ unsafe fn strchr(cs: *c_char, c: c_int) -> *c_char;
+ unsafe fn strrchr(cs: *c_char, c: c_int) -> *c_char;
+ unsafe fn strspn(cs: *c_char, ct: *c_char) -> size_t;
+ unsafe fn strcspn(cs: *c_char, ct: *c_char) -> size_t;
+ unsafe fn strpbrk(cs: *c_char, ct: *c_char) -> *c_char;
+ unsafe fn strstr(cs: *c_char, ct: *c_char) -> *c_char;
+ unsafe fn strlen(cs: *c_char) -> size_t;
+ unsafe fn strerror(n: c_int) -> *c_char;
+ unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char;
+ unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t) -> size_t;
+ unsafe fn memcpy(s: *c_void, ct: *c_void, n: size_t) -> *c_void;
+ unsafe fn memmove(s: *c_void, ct: *c_void, n: size_t) -> *c_void;
+ unsafe fn memcmp(cx: *c_void, ct: *c_void, n: size_t) -> c_int;
+ unsafe fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void;
+ unsafe fn memset(s: *c_void, c: c_int, n: size_t) -> *c_void;
}
}
#[nolink]
#[abi = "cdecl"]
pub extern mod stat_ {
+ use libc::types::os::common::posix01::stat;
+ use libc::types::os::arch::c95::{c_int, c_char};
+
#[link_name = "_chmod"]
- fn chmod(path: *c_char, mode: c_int) -> c_int;
+ unsafe fn chmod(path: *c_char, mode: c_int) -> c_int;
#[link_name = "_mkdir"]
- fn mkdir(path: *c_char) -> c_int;
+ unsafe fn mkdir(path: *c_char) -> c_int;
#[link_name = "_fstat64"]
- fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+ unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
#[link_name = "_stat64"]
- fn stat(path: *c_char, buf: *mut stat) -> c_int;
+ unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod stdio {
+ use libc::types::common::c95::FILE;
+ use libc::types::os::arch::c95::{c_int, c_char};
+
#[link_name = "_popen"]
- fn popen(command: *c_char, mode: *c_char) -> *FILE;
+ unsafe fn popen(command: *c_char, mode: *c_char) -> *FILE;
#[link_name = "_pclose"]
- fn pclose(stream: *FILE) -> c_int;
+ unsafe fn pclose(stream: *FILE) -> c_int;
#[link_name = "_fdopen"]
- fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
+ unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
#[link_name = "_fileno"]
- fn fileno(stream: *FILE) -> c_int;
+ unsafe fn fileno(stream: *FILE) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod fcntl {
+ use libc::types::os::arch::c95::{c_int, c_char};
+
#[link_name = "_open"]
- fn open(path: *c_char, oflag: c_int, mode: c_int) -> c_int;
+ unsafe fn open(path: *c_char, oflag: c_int, mode: c_int) -> c_int;
#[link_name = "_creat"]
- fn creat(path: *c_char, mode: c_int) -> c_int;
+ unsafe fn creat(path: *c_char, mode: c_int) -> c_int;
}
#[nolink]
#[nolink]
#[abi = "cdecl"]
pub extern mod unistd {
+ use libc::types::common::c95::c_void;
+ use libc::types::os::arch::c95::{c_int, c_uint, c_char,
+ c_long, size_t};
+ use libc::types::os::arch::c99::intptr_t;
+
#[link_name = "_access"]
- fn access(path: *c_char, amode: c_int) -> c_int;
+ unsafe fn access(path: *c_char, amode: c_int) -> c_int;
#[link_name = "_chdir"]
- fn chdir(dir: *c_char) -> c_int;
+ unsafe fn chdir(dir: *c_char) -> c_int;
#[link_name = "_close"]
- fn close(fd: c_int) -> c_int;
+ unsafe fn close(fd: c_int) -> c_int;
#[link_name = "_dup"]
- fn dup(fd: c_int) -> c_int;
+ unsafe fn dup(fd: c_int) -> c_int;
#[link_name = "_dup2"]
- fn dup2(src: c_int, dst: c_int) -> c_int;
+ unsafe fn dup2(src: c_int, dst: c_int) -> c_int;
#[link_name = "_execv"]
- fn execv(prog: *c_char, argv: **c_char) -> intptr_t;
+ unsafe fn execv(prog: *c_char, argv: **c_char) -> intptr_t;
#[link_name = "_execve"]
- fn execve(prog: *c_char, argv: **c_char,
+ unsafe fn execve(prog: *c_char, argv: **c_char,
envp: **c_char) -> c_int;
#[link_name = "_execvp"]
- fn execvp(c: *c_char, argv: **c_char) -> c_int;
+ unsafe fn execvp(c: *c_char, argv: **c_char) -> c_int;
#[link_name = "_execvpe"]
- fn execvpe(c: *c_char, argv: **c_char,
+ unsafe fn execvpe(c: *c_char, argv: **c_char,
envp: **c_char) -> c_int;
#[link_name = "_getcwd"]
- fn getcwd(buf: *c_char, size: size_t) -> *c_char;
+ unsafe fn getcwd(buf: *c_char, size: size_t) -> *c_char;
#[link_name = "_getpid"]
- fn getpid() -> c_int;
+ unsafe fn getpid() -> c_int;
#[link_name = "_isatty"]
- fn isatty(fd: c_int) -> c_int;
+ unsafe fn isatty(fd: c_int) -> c_int;
#[link_name = "_lseek"]
- fn lseek(fd: c_int, offset: c_long, origin: c_int) -> c_long;
+ unsafe fn lseek(fd: c_int, offset: c_long, origin: c_int)
+ -> c_long;
#[link_name = "_pipe"]
- fn pipe(fds: *mut c_int, psize: c_uint,
+ unsafe fn pipe(fds: *mut c_int, psize: c_uint,
textmode: c_int) -> c_int;
#[link_name = "_read"]
- fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int;
+ unsafe fn read(fd: c_int, buf: *mut c_void, count: c_uint)
+ -> c_int;
#[link_name = "_rmdir"]
- fn rmdir(path: *c_char) -> c_int;
+ unsafe fn rmdir(path: *c_char) -> c_int;
#[link_name = "_unlink"]
- fn unlink(c: *c_char) -> c_int;
+ unsafe fn unlink(c: *c_char) -> c_int;
#[link_name = "_write"]
- fn write(fd: c_int, buf: *c_void, count: c_uint) -> c_int;
+ unsafe fn write(fd: c_int, buf: *c_void, count: c_uint) -> c_int;
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix88 {
+ use libc::types::common::c95::{FILE, c_void};
+ use libc::types::common::posix88::{DIR, dirent_t};
+ use libc::types::os::arch::c95::{c_char, c_int, c_long, c_uint};
+ use libc::types::os::arch::c95::{size_t};
+ use libc::types::os::arch::posix01::stat;
+ use libc::types::os::arch::posix88::{gid_t, mode_t, off_t, pid_t};
+ use libc::types::os::arch::posix88::{ssize_t, uid_t};
+
#[nolink]
#[abi = "cdecl"]
pub extern mod stat_ {
- fn chmod(path: *c_char, mode: mode_t) -> c_int;
- fn fchmod(fd: c_int, mode: mode_t) -> c_int;
+ unsafe fn chmod(path: *c_char, mode: mode_t) -> c_int;
+ unsafe fn fchmod(fd: c_int, mode: mode_t) -> c_int;
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
- fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+ #[cfg(target_os = "android")]
+ unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
#[cfg(target_os = "macos")]
#[link_name = "fstat64"]
- fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+ unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
- fn mkdir(path: *c_char, mode: mode_t) -> c_int;
- fn mkfifo(path: *c_char, mode: mode_t) -> c_int;
+ unsafe fn mkdir(path: *c_char, mode: mode_t) -> c_int;
+ unsafe fn mkfifo(path: *c_char, mode: mode_t) -> c_int;
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
- fn stat(path: *c_char, buf: *mut stat) -> c_int;
+ #[cfg(target_os = "android")]
+ unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
#[cfg(target_os = "macos")]
#[link_name = "stat64"]
- fn stat(path: *c_char, buf: *mut stat) -> c_int;
+ unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod stdio {
- fn popen(command: *c_char, mode: *c_char) -> *FILE;
- fn pclose(stream: *FILE) -> c_int;
- fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
- fn fileno(stream: *FILE) -> c_int;
+ unsafe fn popen(command: *c_char, mode: *c_char) -> *FILE;
+ unsafe fn pclose(stream: *FILE) -> c_int;
+ unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
+ unsafe fn fileno(stream: *FILE) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod fcntl {
- fn open(path: *c_char, oflag: c_int, mode: c_int) -> c_int;
- fn creat(path: *c_char, mode: mode_t) -> c_int;
- fn fcntl(fd: c_int, cmd: c_int) -> c_int;
+ unsafe fn open(path: *c_char, oflag: c_int, mode: c_int) -> c_int;
+ unsafe fn creat(path: *c_char, mode: mode_t) -> c_int;
+ unsafe fn fcntl(fd: c_int, cmd: c_int) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod dirent {
- fn opendir(dirname: *c_char) -> *DIR;
- fn closedir(dirp: *DIR) -> c_int;
- fn readdir(dirp: *DIR) -> *dirent_t;
- fn rewinddir(dirp: *DIR);
- fn seekdir(dirp: *DIR, loc: c_long);
- fn telldir(dirp: *DIR) -> c_long;
+ unsafe fn opendir(dirname: *c_char) -> *DIR;
+ unsafe fn closedir(dirp: *DIR) -> c_int;
+ unsafe fn readdir(dirp: *DIR) -> *dirent_t;
+ unsafe fn rewinddir(dirp: *DIR);
+ unsafe fn seekdir(dirp: *DIR, loc: c_long);
+ unsafe fn telldir(dirp: *DIR) -> c_long;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod unistd {
- fn access(path: *c_char, amode: c_int) -> c_int;
- fn alarm(seconds: c_uint) -> c_uint;
- fn chdir(dir: *c_char) -> c_int;
- fn chown(path: *c_char, uid: uid_t, gid: gid_t) -> c_int;
- fn close(fd: c_int) -> c_int;
- fn dup(fd: c_int) -> c_int;
- fn dup2(src: c_int, dst: c_int) -> c_int;
- fn execv(prog: *c_char, argv: **c_char) -> c_int;
- fn execve(prog: *c_char, argv: **c_char,
- envp: **c_char) -> c_int;
- fn execvp(c: *c_char, argv: **c_char) -> c_int;
- fn fork() -> pid_t;
- fn fpathconf(filedes: c_int, name: c_int) -> c_long;
- fn getcwd(buf: *c_char, size: size_t) -> *c_char;
- fn getegid() -> gid_t;
- fn geteuid() -> uid_t;
- fn getgid() -> gid_t ;
- fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int;
- fn getlogin() -> *c_char;
- fn getopt(argc: c_int, argv: **c_char,
- optstr: *c_char) -> c_int;
- fn getpgrp() -> pid_t;
- fn getpid() -> pid_t;
- fn getppid() -> pid_t;
- fn getuid() -> uid_t;
- fn isatty(fd: c_int) -> c_int;
- fn link(src: *c_char, dst: *c_char) -> c_int;
- fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t;
- fn pathconf(path: *c_char, name: c_int) -> c_long;
- fn pause() -> c_int;
- fn pipe(fds: *mut c_int) -> c_int;
- fn read(fd: c_int, buf: *mut c_void,
+ unsafe fn access(path: *c_char, amode: c_int) -> c_int;
+ unsafe fn alarm(seconds: c_uint) -> c_uint;
+ unsafe fn chdir(dir: *c_char) -> c_int;
+ unsafe fn chown(path: *c_char, uid: uid_t, gid: gid_t) -> c_int;
+ unsafe fn close(fd: c_int) -> c_int;
+ unsafe fn dup(fd: c_int) -> c_int;
+ unsafe fn dup2(src: c_int, dst: c_int) -> c_int;
+ unsafe fn execv(prog: *c_char, argv: **c_char) -> c_int;
+ unsafe fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
+ -> c_int;
+ unsafe fn execvp(c: *c_char, argv: **c_char) -> c_int;
+ unsafe fn fork() -> pid_t;
+ unsafe fn fpathconf(filedes: c_int, name: c_int) -> c_long;
+ unsafe fn getcwd(buf: *c_char, size: size_t) -> *c_char;
+ unsafe fn getegid() -> gid_t;
+ unsafe fn geteuid() -> uid_t;
+ unsafe fn getgid() -> gid_t ;
+ unsafe fn getgroups(ngroups_max: c_int, groups: *mut gid_t)
+ -> c_int;
+ unsafe fn getlogin() -> *c_char;
+ unsafe fn getopt(argc: c_int, argv: **c_char, optstr: *c_char)
+ -> c_int;
+ unsafe fn getpgrp() -> pid_t;
+ unsafe fn getpid() -> pid_t;
+ unsafe fn getppid() -> pid_t;
+ unsafe fn getuid() -> uid_t;
+ unsafe fn isatty(fd: c_int) -> c_int;
+ unsafe fn link(src: *c_char, dst: *c_char) -> c_int;
+ unsafe fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t;
+ unsafe fn pathconf(path: *c_char, name: c_int) -> c_long;
+ unsafe fn pause() -> c_int;
+ unsafe fn pipe(fds: *mut c_int) -> c_int;
+ unsafe fn read(fd: c_int, buf: *mut c_void,
count: size_t) -> ssize_t;
- fn rmdir(path: *c_char) -> c_int;
- fn setgid(gid: gid_t) -> c_int;
- fn setpgid(pid: pid_t, pgid: pid_t) -> c_int;
- fn setsid() -> pid_t;
- fn setuid(uid: uid_t) -> c_int;
- fn sleep(secs: c_uint) -> c_uint;
- fn sysconf(name: c_int) -> c_long;
- fn tcgetpgrp(fd: c_int) -> pid_t;
- fn ttyname(fd: c_int) -> *c_char;
- fn unlink(c: *c_char) -> c_int;
- fn write(fd: c_int, buf: *c_void, count: size_t) -> ssize_t;
+ unsafe fn rmdir(path: *c_char) -> c_int;
+ unsafe fn setgid(gid: gid_t) -> c_int;
+ unsafe fn setpgid(pid: pid_t, pgid: pid_t) -> c_int;
+ unsafe fn setsid() -> pid_t;
+ unsafe fn setuid(uid: uid_t) -> c_int;
+ unsafe fn sleep(secs: c_uint) -> c_uint;
+ unsafe fn sysconf(name: c_int) -> c_long;
+ unsafe fn tcgetpgrp(fd: c_int) -> pid_t;
+ unsafe fn ttyname(fd: c_int) -> *c_char;
+ unsafe fn unlink(c: *c_char) -> c_int;
+ unsafe fn write(fd: c_int, buf: *c_void, count: size_t)
+ -> ssize_t;
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix01 {
+ use libc::types::os::arch::c95::{c_char, c_int, size_t};
+ use libc::types::os::arch::posix01::stat;
+ use libc::types::os::arch::posix88::{pid_t, ssize_t};
+
#[nolink]
#[abi = "cdecl"]
pub extern mod stat_ {
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
- fn lstat(path: *c_char, buf: *mut stat) -> c_int;
+ #[cfg(target_os = "android")]
+ unsafe fn lstat(path: *c_char, buf: *mut stat) -> c_int;
#[cfg(target_os = "macos")]
#[link_name = "lstat64"]
- fn lstat(path: *c_char, buf: *mut stat) -> c_int;
+ unsafe fn lstat(path: *c_char, buf: *mut stat) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod unistd {
- fn readlink(path: *c_char, buf: *mut c_char,
+ unsafe fn readlink(path: *c_char, buf: *mut c_char,
bufsz: size_t) -> ssize_t;
- fn fsync(fd: c_int) -> c_int;
+ unsafe fn fsync(fd: c_int) -> c_int;
#[cfg(target_os = "linux")]
- fn fdatasync(fd: c_int) -> c_int;
+ #[cfg(target_os = "android")]
+ unsafe fn fdatasync(fd: c_int) -> c_int;
- fn setenv(name: *c_char, val: *c_char,
+ unsafe fn setenv(name: *c_char, val: *c_char,
overwrite: c_int) -> c_int;
- fn unsetenv(name: *c_char) -> c_int;
- fn putenv(string: *c_char) -> c_int;
+ unsafe fn unsetenv(name: *c_char) -> c_int;
+ unsafe fn putenv(string: *c_char) -> c_int;
+
+ unsafe fn symlink(path1: *c_char, path2: *c_char) -> c_int;
}
#[nolink]
#[abi = "cdecl"]
pub extern mod wait {
- fn waitpid(pid: pid_t, status: *mut c_int,
+ unsafe fn waitpid(pid: pid_t, status: *mut c_int,
options: c_int) -> pid_t;
}
}
#[cfg(target_os = "win32")]
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod posix08 {
#[nolink]
#[abi = "cdecl"]
pub extern mod bsd44 {
- fn sysctl(name: *c_int, namelen: c_uint,
+ use libc::types::common::c95::{c_void};
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t};
+
+ unsafe fn sysctl(name: *c_int, namelen: c_uint,
oldp: *mut c_void, oldlenp: *mut size_t,
newp: *c_void, newlen: size_t) -> c_int;
- fn sysctlbyname(name: *c_char,
+ unsafe fn sysctlbyname(name: *c_char,
oldp: *mut c_void, oldlenp: *mut size_t,
newp: *c_void, newlen: size_t) -> c_int;
- fn sysctlnametomib(name: *c_char, mibp: *mut c_int,
+ unsafe fn sysctlnametomib(name: *c_char, mibp: *mut c_int,
sizep: *mut size_t) -> c_int;
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "win32")]
pub mod bsd44 {
}
-
#[cfg(target_os = "macos")]
#[nolink]
#[abi = "cdecl"]
pub extern mod extra {
- fn _NSGetExecutablePath(buf: *mut c_char,
+ use libc::types::os::arch::c95::{c_char, c_int};
+
+ unsafe fn _NSGetExecutablePath(buf: *mut c_char,
bufsize: *mut u32) -> c_int;
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
pub mod extra {
}
#[cfg(target_os = "win32")]
pub mod extra {
+ use libc::types::os::arch::c95::c_int;
+ use libc::types::os::arch::extra::{DWORD, HMODULE, LPCWSTR, LPWSTR};
+ use libc::types::os::arch::extra::{BOOL, LPSECURITY_ATTRIBUTES};
+
#[abi = "stdcall"]
pub extern mod kernel32 {
- fn GetEnvironmentVariableW(n: LPCWSTR,
+ unsafe fn GetEnvironmentVariableW(n: LPCWSTR,
v: LPWSTR,
nsize: DWORD) -> DWORD;
- fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL;
+ unsafe fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL;
- fn GetModuleFileNameW(hModule: HMODULE,
+ unsafe fn GetModuleFileNameW(hModule: HMODULE,
lpFilename: LPWSTR,
nSize: DWORD) -> DWORD;
- fn CreateDirectoryW(lpPathName: LPCWSTR,
+ unsafe fn CreateDirectoryW(lpPathName: LPCWSTR,
lpSecurityAttributes:
LPSECURITY_ATTRIBUTES) -> BOOL;
- fn CopyFileW(lpExistingFileName: LPCWSTR,
+ unsafe fn CopyFileW(lpExistingFileName: LPCWSTR,
lpNewFileName: LPCWSTR,
bFailIfExists: BOOL) -> BOOL;
- fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
- fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
- fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+ unsafe fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
+ unsafe fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+ unsafe fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
- fn GetLastError() -> DWORD;
+ unsafe fn GetLastError() -> DWORD;
}
#[abi = "cdecl"]
#[nolink]
pub extern mod msvcrt {
#[link_name = "_commit"]
- pub fn commit(fd: c_int) -> c_int;
+ unsafe fn commit(fd: c_int) -> c_int;
}
}
}
#[forbid(deprecated_pattern)];
use cast::transmute;
+use io;
+use libc;
+use repr;
+use vec;
#[nolink]
extern mod rustrt {
- fn rust_log_console_on();
- fn rust_log_console_off();
- fn rust_log_str(level: u32, string: *libc::c_char, size: libc::size_t);
+ unsafe fn rust_log_console_on();
+ unsafe fn rust_log_console_off();
+ unsafe fn rust_log_str(level: u32,
+ string: *libc::c_char,
+ size: libc::size_t);
}
/// Turns on logging to stdout globally
pub fn console_on() {
- rustrt::rust_log_console_on();
+ unsafe {
+ rustrt::rust_log_console_on();
+ }
}
/**
* the RUST_LOG environment variable
*/
pub fn console_off() {
- rustrt::rust_log_console_off();
+ unsafe {
+ rustrt::rust_log_console_off();
+ }
}
#[cfg(notest)]
#[forbid(deprecated_pattern)];
use cmp::{Eq, Ord};
-use intrinsic::TyDesc;
+use prelude::*;
+use ptr;
pub mod raw {
+ use intrinsic::TyDesc;
+
pub struct BoxHeaderRepr {
ref_count: uint,
type_desc: *TyDesc,
}
+#[inline(always)]
pub pure fn ptr_eq<T>(a: @T, b: @T) -> bool {
//! Determine if two shared boxes point to the same object
unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) }
#[cfg(notest)]
impl<T:Eq> @const T : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &@const T) -> bool { *(*self) == *(*other) }
+ #[inline(always)]
pure fn ne(&self, other: &@const T) -> bool { *(*self) != *(*other) }
}
#[cfg(notest)]
impl<T:Ord> @const T : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &@const T) -> bool { *(*self) < *(*other) }
+ #[inline(always)]
pure fn le(&self, other: &@const T) -> bool { *(*self) <= *(*other) }
+ #[inline(always)]
pure fn ge(&self, other: &@const T) -> bool { *(*self) >= *(*other) }
+ #[inline(always)]
pure fn gt(&self, other: &@const T) -> bool { *(*self) > *(*other) }
}
#[cfg(notest)]
impl () : Eq {
+ #[inline(always)]
pure fn eq(&self, _other: &()) -> bool { true }
+ #[inline(always)]
pure fn ne(&self, _other: &()) -> bool { false }
}
#[cfg(notest)]
impl () : Ord {
+ #[inline(always)]
pure fn lt(&self, _other: &()) -> bool { false }
+ #[inline(always)]
pure fn le(&self, _other: &()) -> bool { true }
+ #[inline(always)]
pure fn ge(&self, _other: &()) -> bool { true }
+ #[inline(always)]
pure fn gt(&self, _other: &()) -> bool { false }
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use cast;
+use either;
use either::Either;
+use iter;
+use libc;
use libc::size_t;
+use prelude::*;
+use ptr;
+use result;
+use sys;
+use task;
+use vec;
+
// After snapshot, change p2::addr_of => addr_of
/**
/// Constructs a port
pub fn Port<T: Owned>() -> Port<T> {
- Port_(@PortPtr(rustrt::new_port(sys::size_of::<T>() as size_t)))
+ unsafe {
+ Port_(@PortPtr(rustrt::new_port(sys::nonzero_size_of::<T>()
+ as size_t)))
+ }
}
impl<T: Owned> Port<T> {
struct PortRef {
p: *rust_port,
- drop {
- if !ptr::is_null(self.p) {
- rustrt::rust_port_drop(self.p);
- }
- }
+ drop {
+ unsafe {
+ if !ptr::is_null(self.p) {
+ rustrt::rust_port_drop(self.p);
+ }
+ }
+ }
}
fn PortRef(p: *rust_port) -> PortRef {
}
}
- let p = PortRef(rustrt::rust_port_take(*ch));
+ unsafe {
+ let p = PortRef(rustrt::rust_port_take(*ch));
- if ptr::is_null(p.p) {
- fail ~"unable to locate port for channel"
- } else if rustrt::get_task_id() != rustrt::rust_port_task(p.p) {
- fail ~"unable to access unowned port"
- }
+ if ptr::is_null(p.p) {
+ fail ~"unable to locate port for channel"
+ } else if rustrt::get_task_id() != rustrt::rust_port_task(p.p) {
+ fail ~"unable to access unowned port"
+ }
- f(p.p)
+ f(p.p)
+ }
}
/**
* construct it.
*/
pub fn Chan<T: Owned>(p: &Port<T>) -> Chan<T> {
- Chan_(rustrt::get_port_id((**p).po))
+ unsafe {
+ Chan_(rustrt::get_port_id((**p).po))
+ }
}
/**
* whereupon the caller loses access to it.
*/
pub fn send<T: Owned>(ch: Chan<T>, data: T) {
- let Chan_(p) = ch;
- let data_ptr = ptr::addr_of(&data) as *();
- let res = rustrt::rust_port_id_send(p, data_ptr);
- if res != 0 unsafe {
- // Data sent successfully
- cast::forget(move data);
+ unsafe {
+ let Chan_(p) = ch;
+ let data_ptr = ptr::addr_of(&data) as *();
+ let res = rustrt::rust_port_id_send(p, data_ptr);
+ if res != 0 unsafe {
+ // Data sent successfully
+ cast::forget(move data);
+ }
+ task::yield();
}
- task::yield();
}
/**
/// Receive on a raw port pointer
fn recv_<T: Owned>(p: *rust_port) -> T {
- let yield = 0;
- let yieldp = ptr::addr_of(&yield);
- let mut res;
- res = rusti::init::<T>();
- rustrt::port_recv(ptr::addr_of(&res) as *uint, p, yieldp);
-
- if yield != 0 {
- // Data isn't available yet, so res has not been initialized.
- task::yield();
- } else {
- // In the absence of compiler-generated preemption points
- // this is a good place to yield
- task::yield();
+ unsafe {
+ let yield = 0;
+ let yieldp = ptr::addr_of(&yield);
+ let mut res;
+ res = rusti::init::<T>();
+ rustrt::port_recv(ptr::addr_of(&res) as *uint, p, yieldp);
+
+ if yield != 0 {
+ // Data isn't available yet, so res has not been initialized.
+ task::yield();
+ } else {
+ // In the absence of compiler-generated preemption points
+ // this is a good place to yield
+ task::yield();
+ }
+ move res
}
- move res
}
fn peek_(p: *rust_port) -> bool {
- // Yield here before we check to see if someone sent us a message
- // FIXME #524, if the compiler generates yields, we don't need this
- task::yield();
- rustrt::rust_port_size(p) != 0 as libc::size_t
+ unsafe {
+ // Yield here before we check to see if someone sent us a message
+ // FIXME #524, if the compiler generates yields, we don't need this
+ task::yield();
+ rustrt::rust_port_size(p) != 0 as libc::size_t
+ }
}
/// Receive on one of two ports
pub fn select2<A: Owned, B: Owned>(p_a: Port<A>, p_b: Port<B>)
-> Either<A, B> {
- let ports = ~[(**p_a).po, (**p_b).po];
- let yield = 0, yieldp = ptr::addr_of(&yield);
-
- let mut resport: *rust_port;
- resport = rusti::init::<*rust_port>();
- do vec::as_imm_buf(ports) |ports, n_ports| {
- rustrt::rust_port_select(ptr::addr_of(&resport), ports,
- n_ports as size_t, yieldp);
- }
+ unsafe {
+ let ports = ~[(**p_a).po, (**p_b).po];
+ let yield = 0, yieldp = ptr::addr_of(&yield);
+
+ let mut resport: *rust_port;
+ resport = rusti::init::<*rust_port>();
+ do vec::as_imm_buf(ports) |ports, n_ports| {
+ rustrt::rust_port_select(ptr::addr_of(&resport), ports,
+ n_ports as size_t, yieldp);
+ }
- if yield != 0 {
- // Wait for data
- task::yield();
- } else {
- // As in recv, this is a good place to yield anyway until
- // the compiler generates yield calls
- task::yield();
- }
+ if yield != 0 {
+ // Wait for data
+ task::yield();
+ } else {
+ // As in recv, this is a good place to yield anyway until
+ // the compiler generates yield calls
+ task::yield();
+ }
- // Now we know the port we're supposed to receive from
- assert resport != ptr::null();
+ // Now we know the port we're supposed to receive from
+ assert resport != ptr::null();
- if resport == (**p_a).po {
- either::Left(recv(p_a))
- } else if resport == (**p_b).po {
- either::Right(recv(p_b))
- } else {
- fail ~"unexpected result from rust_port_select";
+ if resport == (**p_a).po {
+ either::Left(recv(p_a))
+ } else if resport == (**p_b).po {
+ either::Right(recv(p_b))
+ } else {
+ fail ~"unexpected result from rust_port_select";
+ }
}
}
#[abi = "cdecl"]
extern mod rustrt {
- fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;
+ unsafe fn rust_port_id_send(target_port: port_id, data: *())
+ -> libc::uintptr_t;
- fn new_port(unit_sz: libc::size_t) -> *rust_port;
- fn del_port(po: *rust_port);
- fn rust_port_begin_detach(po: *rust_port,
+ unsafe fn new_port(unit_sz: libc::size_t) -> *rust_port;
+ unsafe fn del_port(po: *rust_port);
+ unsafe fn rust_port_begin_detach(po: *rust_port,
yield: *libc::uintptr_t);
- fn rust_port_end_detach(po: *rust_port);
- fn get_port_id(po: *rust_port) -> port_id;
- fn rust_port_size(po: *rust_port) -> libc::size_t;
- fn port_recv(dptr: *uint, po: *rust_port,
+ unsafe fn rust_port_end_detach(po: *rust_port);
+ unsafe fn get_port_id(po: *rust_port) -> port_id;
+ unsafe fn rust_port_size(po: *rust_port) -> libc::size_t;
+ unsafe fn port_recv(dptr: *uint, po: *rust_port,
yield: *libc::uintptr_t);
- fn rust_port_select(dptr: **rust_port, ports: **rust_port,
+ unsafe fn rust_port_select(dptr: **rust_port, ports: **rust_port,
n_ports: libc::size_t,
yield: *libc::uintptr_t);
- fn rust_port_take(port_id: port_id) -> *rust_port;
- fn rust_port_drop(p: *rust_port);
- fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
- fn get_task_id() -> libc::uintptr_t;
+ unsafe fn rust_port_take(port_id: port_id) -> *rust_port;
+ unsafe fn rust_port_drop(p: *rust_port);
+ unsafe fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
+ unsafe fn get_task_id() -> libc::uintptr_t;
}
#[abi = "rust-intrinsic"]
#[lang="drop"]
pub trait Drop {
- fn finalize(&self); // XXX: Rename to "drop"? --pcwalton
+ fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton
}
#[lang="add"]
pure fn neg(&self) -> Result;
}
+#[lang="not"]
+pub trait Not<Result> {
+ pure fn not(&self) -> Result;
+}
+
#[lang="bitand"]
pub trait BitAnd<RHS,Result> {
pure fn bitand(&self, rhs: &RHS) -> Result;
pub trait Index<Index,Result> {
pure fn index(&self, index: Index) -> Result;
}
-
#[forbid(deprecated_pattern)];
use cmp::Eq;
+use kinds::Copy;
+use option;
+use ptr;
+use str;
+use util;
+use num::Zero;
/// The option type
#[deriving_eq]
Some(T),
}
+#[inline(always)]
pub pure fn get<T: Copy>(opt: Option<T>) -> T {
/*!
Gets the value out of an option
}
}
+#[inline(always)]
pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
/*!
Gets an immutable reference to the value inside an option.
}
}
+#[inline(always)]
pub pure fn map<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
//! Maps a `some` value by reference from one type to another
match *opt { Some(ref x) => Some(f(x)), None => None }
}
+#[inline(always)]
pub pure fn map_consume<T, U>(opt: Option<T>,
f: fn(v: T) -> U) -> Option<U> {
/*!
* As `map`, but consumes the option and gives `f` ownership to avoid
* copying.
*/
- if opt.is_some() { Some(f(option::unwrap(move opt))) } else { None }
+ match opt { None => None, Some(v) => Some(f(v)) }
}
+#[inline(always)]
pub pure fn chain<T, U>(opt: Option<T>,
f: fn(t: T) -> Option<U>) -> Option<U> {
/*!
}
}
+#[inline(always)]
pub pure fn chain_ref<T, U>(opt: &Option<T>,
f: fn(x: &T) -> Option<U>) -> Option<U> {
/*!
match *opt { Some(ref x) => f(x), None => None }
}
+#[inline(always)]
pub pure fn or<T>(opta: Option<T>, optb: Option<T>) -> Option<T> {
/*!
* Returns the leftmost some() value, or none if both are none.
}
}
+#[inline(always)]
pub pure fn is_none<T>(opt: &Option<T>) -> bool {
//! Returns true if the option equals `none`
match *opt { None => true, Some(_) => false }
}
+#[inline(always)]
pub pure fn is_some<T>(opt: &Option<T>) -> bool {
//! Returns true if the option contains some value
!is_none(opt)
}
-pub pure fn get_default<T: Copy>(opt: Option<T>, def: T) -> T {
+#[inline(always)]
+pub pure fn get_or_zero<T: Copy Zero>(opt: Option<T>) -> T {
+ //! Returns the contained value or zero (for this type)
+
+ match opt { Some(copy x) => x, None => Zero::zero() }
+}
+
+#[inline(always)]
+pub pure fn get_or_default<T: Copy>(opt: Option<T>, def: T) -> T {
//! Returns the contained value or a default
match opt { Some(copy x) => x, None => def }
}
+#[inline(always)]
pub pure fn map_default<T, U>(opt: &Option<T>, def: U,
f: fn(x: &T) -> U) -> U {
//! Applies a function to the contained value or returns a default
match *opt { None => move def, Some(ref t) => f(t) }
}
+#[inline(always)]
pub pure fn iter<T>(opt: &Option<T>, f: fn(x: &T)) {
//! Performs an operation on the contained value by reference
match *opt { None => (), Some(ref t) => f(t) }
unwrap(util::replace(opt, None))
}
+#[inline(always)]
pub pure fn expect<T>(opt: Option<T>, reason: &str) -> T {
//! As unwrap, but with a specified failure message.
match move opt {
#[inline(always)]
pure fn map<U>(&self, f: fn(x: &T) -> U) -> Option<U> { map(self, f) }
+ /// As `map`, but consumes the option and gives `f` ownership to avoid
+ /// copying.
+ #[inline(always)]
+ pure fn map_consume<U>(self, f: fn(v: T) -> U) -> Option<U> {
+ map_consume(self, f)
+ }
+
/// Applies a function to the contained value or returns a default
#[inline(always)]
pure fn map_default<U>(&self, def: U, f: fn(x: &T) -> U) -> U {
map_default(self, move def, f)
}
+ /// As `map_default`, but consumes the option and gives `f`
+ /// ownership to avoid copying.
+ #[inline(always)]
+ pure fn map_consume_default<U>(self, def: U, f: fn(v: T) -> U) -> U {
+ match self { None => def, Some(v) => f(v) }
+ }
+
+ /// Apply a function to the contained value or do nothing
+ fn mutate(&mut self, f: fn(T) -> T) {
+ if self.is_some() {
+ *self = Some(f(self.swap_unwrap()));
+ }
+ }
+
+ /// Apply a function to the contained value or set it to a default
+ fn mutate_default(&mut self, def: T, f: fn(T) -> T) {
+ if self.is_some() {
+ *self = Some(f(self.swap_unwrap()));
+ } else {
+ *self = Some(def);
+ }
+ }
+
/// Performs an operation on the contained value by reference
#[inline(always)]
pure fn iter(&self, f: fn(x: &T)) { iter(self, f) }
#[inline(always)]
pure fn unwrap(self) -> T { unwrap(self) }
+ /**
+ * The option dance. Moves a value out of an option type and returns it,
+ * replacing the original with `None`.
+ *
+ * # Failure
+ *
+ * Fails if the value equals `None`.
+ */
+ #[inline(always)]
+ fn swap_unwrap(&mut self) -> T { swap_unwrap(self) }
+
/**
* Gets the value out of an option, printing a specified message on
* failure
pure fn get(self) -> T { get(self) }
#[inline(always)]
- pure fn get_default(self, def: T) -> T { get_default(self, def) }
+ pure fn get_or_default(self, def: T) -> T { get_or_default(self, def) }
/// Applies a function zero or more times until the result is none.
#[inline(always)]
}
}
+impl<T: Copy Zero> Option<T> {
+ #[inline(always)]
+ pure fn get_or_zero(self) -> T { get_or_zero(self) }
+}
+
#[test]
fn test_unwrap_ptr() {
let x = ~0;
assert i == 11;
}
+#[test]
+fn test_get_or_zero() {
+ let some_stuff = Some(42);
+ assert some_stuff.get_or_zero() == 42;
+ let no_stuff: Option<int> = None;
+ assert no_stuff.get_or_zero() == 0;
+}
+
// Local Variables:
// mode: rust;
// fill-column: 78;
* to write OS-ignorant code by default.
*/
-use libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t,
- mode_t, pid_t, FILE};
-pub use libc::{close, fclose};
-
+use cast;
+use either;
+use io;
+use libc;
+use libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t};
+use libc::{mode_t, pid_t, FILE};
+use option;
use option::{Some, None};
+use prelude::*;
+use private;
+use ptr;
+use str;
+use task;
+use task::TaskBuilder;
+use uint;
+use vec;
+pub use libc::fclose;
pub use os::consts::*;
-use task::TaskBuilder;
// FIXME: move these to str perhaps? #2620
-extern mod rustrt {
- fn rust_get_argc() -> c_int;
- fn rust_get_argv() -> **c_char;
- fn rust_getcwd() -> ~str;
- fn rust_path_is_dir(path: *libc::c_char) -> c_int;
- fn rust_path_exists(path: *libc::c_char) -> c_int;
- fn rust_list_files2(&&path: ~str) -> ~[~str];
- fn rust_process_wait(handle: c_int) -> c_int;
- fn last_os_error() -> ~str;
- fn rust_set_exit_status(code: libc::intptr_t);
+pub fn close(fd: c_int) -> c_int {
+ unsafe {
+ libc::close(fd)
+ }
}
+extern mod rustrt {
+ unsafe fn rust_get_argc() -> c_int;
+ unsafe fn rust_get_argv() -> **c_char;
+ unsafe fn rust_getcwd() -> ~str;
+ unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int;
+ unsafe fn rust_path_exists(path: *libc::c_char) -> c_int;
+ unsafe fn rust_list_files2(&&path: ~str) -> ~[~str];
+ unsafe fn rust_process_wait(handle: c_int) -> c_int;
+ unsafe fn last_os_error() -> ~str;
+ unsafe fn rust_set_exit_status(code: libc::intptr_t);
+}
-const tmpbuf_sz : uint = 1000u;
+pub const tmpbuf_sz : uint = 1000u;
pub fn getcwd() -> Path {
- Path(rustrt::rust_getcwd())
+ unsafe {
+ Path(rustrt::rust_getcwd())
+ }
}
pub fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T {
#[cfg(windows)]
pub mod win32 {
+ use libc;
+ use vec;
+ use str;
+ use option::{None, Option};
+ use option;
+ use os::tmpbuf_sz;
use libc::types::os::arch::extra::DWORD;
pub fn fill_utf16_buf_and_decode(f: fn(*mut u16, DWORD) -> DWORD)
-> Option<~str> {
- let mut n = tmpbuf_sz as DWORD;
- let mut res = None;
- let mut done = false;
- while !done {
- let buf = vec::to_mut(vec::from_elem(n as uint, 0u16));
- do vec::as_mut_buf(buf) |b, _sz| {
- let k : DWORD = f(b, tmpbuf_sz as DWORD);
- if k == (0 as DWORD) {
- done = true;
- } else if (k == n &&
- libc::GetLastError() ==
- libc::ERROR_INSUFFICIENT_BUFFER as DWORD) {
- n *= (2 as DWORD);
- } else {
- let sub = vec::slice(buf, 0u, k as uint);
- res = option::Some(str::from_utf16(sub));
- done = true;
+ unsafe {
+ let mut n = tmpbuf_sz as DWORD;
+ let mut res = None;
+ let mut done = false;
+ while !done {
+ let buf = vec::to_mut(vec::from_elem(n as uint, 0u16));
+ do vec::as_mut_buf(buf) |b, _sz| {
+ let k : DWORD = f(b, tmpbuf_sz as DWORD);
+ if k == (0 as DWORD) {
+ done = true;
+ } else if (k == n &&
+ libc::GetLastError() ==
+ libc::ERROR_INSUFFICIENT_BUFFER as DWORD) {
+ n *= (2 as DWORD);
+ } else {
+ let sub = vec::slice(buf, 0u, k as uint);
+ res = option::Some(str::from_utf16(sub));
+ done = true;
+ }
}
}
+ return res;
}
- return res;
}
pub fn as_utf16_p<T>(s: &str, f: fn(*u16) -> T) -> T {
mod global_env {
//! Internal module for serializing access to getenv/setenv
+ use either;
+ use libc;
+ use oldcomm;
+ use option::Option;
+ use private;
+ use str;
+ use task;
extern mod rustrt {
- fn rust_global_env_chan_ptr() -> *libc::uintptr_t;
+ unsafe fn rust_global_env_chan_ptr() -> *libc::uintptr_t;
}
enum Msg {
let env_ch = get_global_env_chan();
let po = oldcomm::Port();
oldcomm::send(env_ch, MsgGetEnv(str::from_slice(n),
- oldcomm::Chan(&po)));
+ oldcomm::Chan(&po)));
oldcomm::recv(po)
}
let env_ch = get_global_env_chan();
let po = oldcomm::Port();
oldcomm::send(env_ch, MsgSetEnv(str::from_slice(n),
- str::from_slice(v),
- oldcomm::Chan(&po)));
+ str::from_slice(v),
+ oldcomm::Chan(&po)));
oldcomm::recv(po)
}
}
fn get_global_env_chan() -> oldcomm::Chan<Msg> {
- let global_ptr = rustrt::rust_global_env_chan_ptr();
unsafe {
+ let global_ptr = rustrt::rust_global_env_chan_ptr();
private::chan_from_global_ptr(global_ptr, || {
// FIXME (#2621): This would be a good place to use a very
// small foreign stack
}
mod impl_ {
+ use cast;
+ use libc;
+ use option::Option;
+ use option;
+ use ptr;
+ use str;
+ use vec;
+
extern mod rustrt {
- fn rust_env_pairs() -> ~[~str];
+ unsafe fn rust_env_pairs() -> ~[~str];
}
pub fn env() -> ~[(~str,~str)] {
- let mut pairs = ~[];
- for vec::each(rustrt::rust_env_pairs()) |p| {
- let vs = str::splitn_char(*p, '=', 1u);
- assert vec::len(vs) == 2u;
- pairs.push((copy vs[0], copy vs[1]));
+ unsafe {
+ let mut pairs = ~[];
+ for vec::each(rustrt::rust_env_pairs()) |p| {
+ let vs = str::splitn_char(*p, '=', 1u);
+ assert vec::len(vs) == 2u;
+ pairs.push((copy vs[0], copy vs[1]));
+ }
+ move pairs
}
- move pairs
}
#[cfg(unix)]
pub fn getenv(n: &str) -> Option<~str> {
unsafe {
- let s = str::as_c_str(n, libc::getenv);
+ let s = str::as_c_str(n, |s| libc::getenv(s));
return if ptr::null::<u8>() == cast::reinterpret_cast(&s) {
option::None::<~str>
} else {
#[cfg(windows)]
pub fn getenv(n: &str) -> Option<~str> {
- use os::win32::*;
- do as_utf16_p(n) |u| {
- do fill_utf16_buf_and_decode() |buf, sz| {
- libc::GetEnvironmentVariableW(u, buf, sz)
+ unsafe {
+ use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
+ do as_utf16_p(n) |u| {
+ do fill_utf16_buf_and_decode() |buf, sz| {
+ libc::GetEnvironmentVariableW(u, buf, sz)
+ }
}
}
}
#[cfg(unix)]
pub fn setenv(n: &str, v: &str) {
- do str::as_c_str(n) |nbuf| {
- do str::as_c_str(v) |vbuf| {
- libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1i32);
+ unsafe {
+ do str::as_c_str(n) |nbuf| {
+ do str::as_c_str(v) |vbuf| {
+ libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
+ }
}
}
}
#[cfg(windows)]
pub fn setenv(n: &str, v: &str) {
- use os::win32::*;
- do as_utf16_p(n) |nbuf| {
- do as_utf16_p(v) |vbuf| {
- libc::SetEnvironmentVariableW(nbuf, vbuf);
+ unsafe {
+ use os::win32::as_utf16_p;
+ do as_utf16_p(n) |nbuf| {
+ do as_utf16_p(v) |vbuf| {
+ libc::SetEnvironmentVariableW(nbuf, vbuf);
+ }
}
}
}
}
pub fn fdopen(fd: c_int) -> *FILE {
- return do as_c_charp("r") |modebuf| {
- libc::fdopen(fd, modebuf)
- };
+ unsafe {
+ return do as_c_charp("r") |modebuf| {
+ libc::fdopen(fd, modebuf)
+ };
+ }
}
#[cfg(windows)]
pub fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
- use libc::funcs::extra::msvcrt::*;
- return commit(fd);
+ unsafe {
+ use libc::funcs::extra::msvcrt::*;
+ return commit(fd);
+ }
}
#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
- use libc::funcs::posix01::unistd::*;
- match level {
- io::fsync::FSync
- | io::fsync::FullFSync => return fsync(fd),
- io::fsync::FDataSync => return fdatasync(fd)
+ unsafe {
+ use libc::funcs::posix01::unistd::*;
+ match level {
+ io::fsync::FSync
+ | io::fsync::FullFSync => return fsync(fd),
+ io::fsync::FDataSync => return fdatasync(fd)
+ }
}
}
#[cfg(target_os = "macos")]
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
- use libc::consts::os::extra::*;
- use libc::funcs::posix88::fcntl::*;
- use libc::funcs::posix01::unistd::*;
- match level {
- io::fsync::FSync => return fsync(fd),
- _ => {
- // According to man fnctl, the ok retval is only specified to be !=-1
- if (fcntl(F_FULLFSYNC as c_int, fd) == -1 as c_int)
- { return -1 as c_int; }
- else
- { return 0 as c_int; }
- }
+ unsafe {
+ use libc::consts::os::extra::*;
+ use libc::funcs::posix88::fcntl::*;
+ use libc::funcs::posix01::unistd::*;
+ match level {
+ io::fsync::FSync => return fsync(fd),
+ _ => {
+ // According to man fnctl, the ok retval is only specified to be
+ // !=-1
+ if (fcntl(F_FULLFSYNC as c_int, fd) == -1 as c_int)
+ { return -1 as c_int; }
+ else
+ { return 0 as c_int; }
+ }
+ }
}
}
#[cfg(target_os = "freebsd")]
pub fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int {
- use libc::funcs::posix01::unistd::*;
- return fsync(fd);
+ unsafe {
+ use libc::funcs::posix01::unistd::*;
+ return fsync(fd);
+ }
}
#[cfg(windows)]
pub fn waitpid(pid: pid_t) -> c_int {
- return rustrt::rust_process_wait(pid);
+ unsafe {
+ return rustrt::rust_process_wait(pid);
+ }
}
#[cfg(unix)]
pub fn waitpid(pid: pid_t) -> c_int {
- use libc::funcs::posix01::wait::*;
- let status = 0 as c_int;
+ unsafe {
+ use libc::funcs::posix01::wait::*;
+ let status = 0 as c_int;
- assert (waitpid(pid, ptr::mut_addr_of(&status),
- 0 as c_int) != (-1 as c_int));
- return status;
+ assert (waitpid(pid, ptr::mut_addr_of(&status),
+ 0 as c_int) != (-1 as c_int));
+ return status;
+ }
}
#[cfg(unix)]
pub fn pipe() -> {in: c_int, out: c_int} {
- let fds = {mut in: 0 as c_int,
- mut out: 0 as c_int };
- assert (libc::pipe(ptr::mut_addr_of(&(fds.in))) == (0 as c_int));
- return {in: fds.in, out: fds.out};
+ unsafe {
+ let fds = {mut in: 0 as c_int,
+ mut out: 0 as c_int };
+ assert (libc::pipe(ptr::mut_addr_of(&(fds.in))) == (0 as c_int));
+ return {in: fds.in, out: fds.out};
+ }
}
#[cfg(windows)]
pub fn pipe() -> {in: c_int, out: c_int} {
- // Windows pipes work subtly differently than unix pipes, and their
- // inheritance has to be handled in a different way that I do not fully
- // understand. Here we explicitly make the pipe non-inheritable, which
- // means to pass it to a subprocess they need to be duplicated first, as
- // in rust_run_program.
- let fds = { mut in: 0 as c_int,
- mut out: 0 as c_int };
- let res = libc::pipe(ptr::mut_addr_of(&(fds.in)),
- 1024 as c_uint,
- (libc::O_BINARY | libc::O_NOINHERIT) as c_int);
- assert (res == 0 as c_int);
- assert (fds.in != -1 as c_int && fds.in != 0 as c_int);
- assert (fds.out != -1 as c_int && fds.in != 0 as c_int);
- return {in: fds.in, out: fds.out};
+ unsafe {
+ // Windows pipes work subtly differently than unix pipes, and their
+ // inheritance has to be handled in a different way that I do not
+ // fully understand. Here we explicitly make the pipe non-inheritable,
+ // which means to pass it to a subprocess they need to be duplicated
+ // first, as in rust_run_program.
+ let fds = { mut in: 0 as c_int,
+ mut out: 0 as c_int };
+ let res = libc::pipe(ptr::mut_addr_of(&(fds.in)),
+ 1024 as c_uint,
+ (libc::O_BINARY | libc::O_NOINHERIT) as c_int);
+ assert (res == 0 as c_int);
+ assert (fds.in != -1 as c_int && fds.in != 0 as c_int);
+ assert (fds.out != -1 as c_int && fds.in != 0 as c_int);
+ return {in: fds.in, out: fds.out};
+ }
}
fn dup2(src: c_int, dst: c_int) -> c_int {
- libc::dup2(src, dst)
+ unsafe {
+ libc::dup2(src, dst)
+ }
}
pub fn dll_filename(base: &str) -> ~str {
- return pre() + str::from_slice(base) + dll_suffix();
-
- #[cfg(unix)]
- fn pre() -> ~str { ~"lib" }
-
- #[cfg(windows)]
- fn pre() -> ~str { ~"" }
+ return str::from_slice(DLL_PREFIX) + str::from_slice(base) +
+ str::from_slice(DLL_SUFFIX)
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
fn load_self() -> Option<~str> {
- use libc::funcs::posix01::unistd::readlink;
- do fill_charp_buf() |buf, sz| {
- do as_c_charp("/proc/self/exe") |proc_self_buf| {
- readlink(proc_self_buf, buf, sz) != (-1 as ssize_t)
+ unsafe {
+ use libc::funcs::posix01::unistd::readlink;
+
+ let mut path_str = str::with_capacity(tmpbuf_sz);
+ let len = do str::as_c_str(path_str) |buf| {
+ let buf = buf as *mut c_char;
+ do as_c_charp("/proc/self/exe") |proc_self_buf| {
+ readlink(proc_self_buf, buf, tmpbuf_sz as size_t)
+ }
+ };
+ if len == -1 {
+ None
+ } else {
+ str::raw::set_len(&mut path_str, len as uint);
+ Some(path_str)
}
}
}
#[cfg(target_os = "macos")]
fn load_self() -> Option<~str> {
- do fill_charp_buf() |buf, sz| {
- libc::funcs::extra::_NSGetExecutablePath(
- buf, ptr::mut_addr_of(&(sz as u32))) == (0 as c_int)
+ unsafe {
+ do fill_charp_buf() |buf, sz| {
+ libc::funcs::extra::_NSGetExecutablePath(
+ buf, ptr::mut_addr_of(&(sz as u32))) == (0 as c_int)
+ }
}
}
#[cfg(windows)]
fn load_self() -> Option<~str> {
- use os::win32::*;
- do fill_utf16_buf_and_decode() |buf, sz| {
- libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
+ unsafe {
+ use os::win32::fill_utf16_buf_and_decode;
+ do fill_utf16_buf_and_decode() |buf, sz| {
+ libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
+ }
}
}
#[cfg(unix)]
#[allow(non_implicitly_copyable_typarams)]
fn lookup() -> Path {
- option::get_default(getenv_nonempty("TMPDIR"),
+ option::get_or_default(getenv_nonempty("TMPDIR"),
Path("/tmp"))
}
#[cfg(windows)]
#[allow(non_implicitly_copyable_typarams)]
fn lookup() -> Path {
- option::get_default(
+ option::get_or_default(
option::or(getenv_nonempty("TMP"),
option::or(getenv_nonempty("TEMP"),
option::or(getenv_nonempty("USERPROFILE"),
/// Indicates whether a path represents a directory
pub fn path_is_dir(p: &Path) -> bool {
- do str::as_c_str(p.to_str()) |buf| {
- rustrt::rust_path_is_dir(buf) != 0 as c_int
+ unsafe {
+ do str::as_c_str(p.to_str()) |buf| {
+ rustrt::rust_path_is_dir(buf) != 0 as c_int
+ }
}
}
/// Indicates whether a path exists
pub fn path_exists(p: &Path) -> bool {
- do str::as_c_str(p.to_str()) |buf| {
- rustrt::rust_path_exists(buf) != 0 as c_int
+ unsafe {
+ do str::as_c_str(p.to_str()) |buf| {
+ rustrt::rust_path_exists(buf) != 0 as c_int
+ }
}
}
#[cfg(windows)]
fn mkdir(p: &Path, _mode: c_int) -> bool {
- use os::win32::*;
- // FIXME: turn mode into something useful? #2623
- do as_utf16_p(p.to_str()) |buf| {
- libc::CreateDirectoryW(buf, unsafe {
- cast::reinterpret_cast(&0)
- })
- != (0 as libc::BOOL)
+ unsafe {
+ use os::win32::as_utf16_p;
+ // FIXME: turn mode into something useful? #2623
+ do as_utf16_p(p.to_str()) |buf| {
+ libc::CreateDirectoryW(buf, unsafe {
+ cast::reinterpret_cast(&0)
+ })
+ != (0 as libc::BOOL)
+ }
}
}
#[cfg(unix)]
fn mkdir(p: &Path, mode: c_int) -> bool {
- do as_c_charp(p.to_str()) |c| {
- libc::mkdir(c, mode as mode_t) == (0 as c_int)
+ unsafe {
+ do as_c_charp(p.to_str()) |c| {
+ libc::mkdir(c, mode as mode_t) == (0 as c_int)
+ }
}
}
}
/// Lists the contents of a directory
#[allow(non_implicitly_copyable_typarams)]
pub fn list_dir(p: &Path) -> ~[~str] {
+ unsafe {
+ #[cfg(unix)]
+ fn star(p: &Path) -> Path { copy *p }
- #[cfg(unix)]
- fn star(p: &Path) -> Path { copy *p }
-
- #[cfg(windows)]
- fn star(p: &Path) -> Path { p.push("*") }
+ #[cfg(windows)]
+ fn star(p: &Path) -> Path { p.push("*") }
- do rustrt::rust_list_files2(star(p).to_str()).filter |filename| {
- *filename != ~"." && *filename != ~".."
+ do rustrt::rust_list_files2(star(p).to_str()).filtered |filename| {
+ *filename != ~"." && *filename != ~".."
+ }
}
}
#[cfg(windows)]
fn rmdir(p: &Path) -> bool {
- use os::win32::*;
- return do as_utf16_p(p.to_str()) |buf| {
- libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
- };
+ unsafe {
+ use os::win32::as_utf16_p;
+ return do as_utf16_p(p.to_str()) |buf| {
+ libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
+ };
+ }
}
#[cfg(unix)]
fn rmdir(p: &Path) -> bool {
- return do as_c_charp(p.to_str()) |buf| {
- libc::rmdir(buf) == (0 as c_int)
- };
+ unsafe {
+ return do as_c_charp(p.to_str()) |buf| {
+ libc::rmdir(buf) == (0 as c_int)
+ };
+ }
}
}
#[cfg(windows)]
fn chdir(p: &Path) -> bool {
- use os::win32::*;
- return do as_utf16_p(p.to_str()) |buf| {
- libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
- };
+ unsafe {
+ use os::win32::as_utf16_p;
+ return do as_utf16_p(p.to_str()) |buf| {
+ libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
+ };
+ }
}
#[cfg(unix)]
fn chdir(p: &Path) -> bool {
- return do as_c_charp(p.to_str()) |buf| {
- libc::chdir(buf) == (0 as c_int)
- };
+ unsafe {
+ return do as_c_charp(p.to_str()) |buf| {
+ libc::chdir(buf) == (0 as c_int)
+ };
+ }
}
}
#[cfg(windows)]
fn do_copy_file(from: &Path, to: &Path) -> bool {
- use os::win32::*;
- return do as_utf16_p(from.to_str()) |fromp| {
- do as_utf16_p(to.to_str()) |top| {
- libc::CopyFileW(fromp, top, (0 as libc::BOOL)) !=
- (0 as libc::BOOL)
+ unsafe {
+ use os::win32::as_utf16_p;
+ return do as_utf16_p(from.to_str()) |fromp| {
+ do as_utf16_p(to.to_str()) |top| {
+ libc::CopyFileW(fromp, top, (0 as libc::BOOL)) !=
+ (0 as libc::BOOL)
+ }
}
}
}
#[cfg(unix)]
fn do_copy_file(from: &Path, to: &Path) -> bool {
- let istream = do as_c_charp(from.to_str()) |fromp| {
- do as_c_charp("rb") |modebuf| {
- libc::fopen(fromp, modebuf)
+ unsafe {
+ let istream = do as_c_charp(from.to_str()) |fromp| {
+ do as_c_charp("rb") |modebuf| {
+ libc::fopen(fromp, modebuf)
+ }
+ };
+ if istream as uint == 0u {
+ return false;
}
- };
- if istream as uint == 0u {
- return false;
- }
- let ostream = do as_c_charp(to.to_str()) |top| {
- do as_c_charp("w+b") |modebuf| {
- libc::fopen(top, modebuf)
+ let ostream = do as_c_charp(to.to_str()) |top| {
+ do as_c_charp("w+b") |modebuf| {
+ libc::fopen(top, modebuf)
+ }
+ };
+ if ostream as uint == 0u {
+ fclose(istream);
+ return false;
}
- };
- if ostream as uint == 0u {
- fclose(istream);
- return false;
- }
- let bufsize = 8192u;
- let mut buf = vec::with_capacity::<u8>(bufsize);
- let mut done = false;
- let mut ok = true;
- while !done {
- do vec::as_mut_buf(buf) |b, _sz| {
- let nread = libc::fread(b as *mut c_void, 1u as size_t,
- bufsize as size_t,
- istream);
- if nread > 0 as size_t {
- if libc::fwrite(b as *c_void, 1u as size_t, nread,
- ostream) != nread {
- ok = false;
+ let bufsize = 8192u;
+ let mut buf = vec::with_capacity::<u8>(bufsize);
+ let mut done = false;
+ let mut ok = true;
+ while !done {
+ do vec::as_mut_buf(buf) |b, _sz| {
+ let nread = libc::fread(b as *mut c_void, 1u as size_t,
+ bufsize as size_t,
+ istream);
+ if nread > 0 as size_t {
+ if libc::fwrite(b as *c_void, 1u as size_t, nread,
+ ostream) != nread {
+ ok = false;
+ done = true;
+ }
+ } else {
done = true;
}
- } else {
- done = true;
}
- }
+ }
+ fclose(istream);
+ fclose(ostream);
+ return ok;
}
- fclose(istream);
- fclose(ostream);
- return ok;
}
}
#[cfg(windows)]
fn unlink(p: &Path) -> bool {
- use os::win32::*;
- return do as_utf16_p(p.to_str()) |buf| {
- libc::DeleteFileW(buf) != (0 as libc::BOOL)
- };
+ unsafe {
+ use os::win32::as_utf16_p;
+ return do as_utf16_p(p.to_str()) |buf| {
+ libc::DeleteFileW(buf) != (0 as libc::BOOL)
+ };
+ }
}
#[cfg(unix)]
fn unlink(p: &Path) -> bool {
- return do as_c_charp(p.to_str()) |buf| {
- libc::unlink(buf) == (0 as c_int)
- };
+ unsafe {
+ return do as_c_charp(p.to_str()) |buf| {
+ libc::unlink(buf) == (0 as c_int)
+ };
+ }
}
}
/// Get a string representing the platform-dependent last error
pub fn last_os_error() -> ~str {
- rustrt::last_os_error()
+ unsafe {
+ rustrt::last_os_error()
+ }
}
/**
* ignored and the process exits with the default failure status
*/
pub fn set_exit_status(code: int) {
- rustrt::rust_set_exit_status(code as libc::intptr_t);
+ unsafe {
+ rustrt::rust_set_exit_status(code as libc::intptr_t);
+ }
}
unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
* Returns a list of the command line arguments.
*/
#[cfg(target_os = "macos")]
-fn real_args() -> ~[~str] {
+pub fn real_args() -> ~[~str] {
unsafe {
let (argc, argv) = (*_NSGetArgc() as c_int,
*_NSGetArgv() as **c_char);
}
#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
-fn real_args() -> ~[~str] {
+pub fn real_args() -> ~[~str] {
unsafe {
let argc = rustrt::rust_get_argc();
let argv = rustrt::rust_get_argv();
}
#[cfg(windows)]
-fn real_args() -> ~[~str] {
+pub fn real_args() -> ~[~str] {
let mut nArgs: c_int = 0;
let lpArgCount = ptr::to_mut_unsafe_ptr(&mut nArgs);
let lpCmdLine = GetCommandLineW();
pub fn _NSGetArgv() -> ***c_char;
}
-#[cfg(unix)]
-pub fn family() -> ~str { ~"unix" }
+pub mod consts {
-#[cfg(windows)]
-pub fn family() -> ~str { ~"windows" }
+ #[cfg(unix)]
+ use os::consts::unix::*;
-#[cfg(target_os = "macos")]
-mod consts {
- pub fn sysname() -> ~str { ~"macos" }
- pub fn exe_suffix() -> ~str { ~"" }
- pub fn dll_suffix() -> ~str { ~".dylib" }
-}
+ #[cfg(windows)]
+ use os::consts::windows::*;
-#[cfg(target_os = "freebsd")]
-mod consts {
- pub fn sysname() -> ~str { ~"freebsd" }
- pub fn exe_suffix() -> ~str { ~"" }
- pub fn dll_suffix() -> ~str { ~".so" }
-}
+ pub mod unix {
+ pub const FAMILY: &str = "unix";
+ }
-#[cfg(target_os = "linux")]
-mod consts {
- pub fn sysname() -> ~str { ~"linux" }
- pub fn exe_suffix() -> ~str { ~"" }
- pub fn dll_suffix() -> ~str { ~".so" }
-}
+ pub mod windows {
+ pub const FAMILY: &str = "windows";
+ }
-#[cfg(target_os = "win32")]
-mod consts {
- pub fn sysname() -> ~str { ~"win32" }
- pub fn exe_suffix() -> ~str { ~".exe" }
- pub fn dll_suffix() -> ~str { ~".dll" }
-}
+ #[cfg(target_os = "macos")]
+ use os::consts::macos::*;
+
+ #[cfg(target_os = "freebsd")]
+ use os::consts::freebsd::*;
+
+ #[cfg(target_os = "linux")]
+ use os::consts::linux::*;
+
+ #[cfg(target_os = "android")]
+ use os::consts::android::*;
+
+ #[cfg(target_os = "win32")]
+ use os::consts::win32::*;
+
+ pub mod macos {
+ pub const SYSNAME: &str = "macos";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".dylib";
+ pub const EXE_SUFFIX: &str = "";
+ }
-#[cfg(target_arch = "x86")]
-pub fn arch() -> ~str { ~"x86" }
+ pub mod freebsd {
+ pub const SYSNAME: &str = "freebsd";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".so";
+ pub const EXE_SUFFIX: &str = "";
+ }
+
+ pub mod linux {
+ pub const SYSNAME: &str = "linux";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".so";
+ pub const EXE_SUFFIX: &str = "";
+ }
+
+ pub mod android {
+ pub const SYSNAME: &str = "android";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".so";
+ pub const EXE_SUFFIX: &str = "";
+ }
-#[cfg(target_arch = "x86_64")]
-pub fn arch() -> ~str { ~"x86_64" }
+ pub mod win32 {
+ pub const SYSNAME: &str = "win32";
+ pub const DLL_PREFIX: &str = "";
+ pub const DLL_SUFFIX: &str = ".dll";
+ pub const EXE_SUFFIX: &str = ".exe";
+ }
+
+
+ #[cfg(target_arch = "x86")]
+ use os::consts::x86::*;
-#[cfg(target_arch = "arm")]
-pub fn arch() -> str { ~"arm" }
+ #[cfg(target_arch = "x86_64")]
+ use os::consts::x86_64::*;
+
+ #[cfg(target_arch = "arm")]
+ use os::consts::arm::*;
+
+ pub mod x86 {
+ pub const ARCH: &str = "x86";
+ }
+ pub mod x86_64 {
+ pub const ARCH: &str = "x86_64";
+ }
+ pub mod arm {
+ pub const ARCH: &str = "arm";
+ }
+}
#[cfg(test)]
#[allow(non_implicitly_copyable_typarams)]
mod tests {
+ use debug;
+ use libc::{c_int, c_void, size_t};
+ use libc;
+ use option::{None, Option, Some};
+ use option;
+ use os::{as_c_charp, env, getcwd, getenv, make_absolute, real_args};
+ use os::{remove_file, setenv};
+ use os;
+ use path::Path;
+ use rand;
+ use run;
+ use str;
+ use vec;
#[test]
pub fn last_os_error() {
- log(debug, last_os_error());
+ log(debug, os::last_os_error());
}
#[test]
#[test]
fn copy_file_ok() {
- let tempdir = getcwd(); // would like to use $TMPDIR,
- // doesn't seem to work on Linux
- assert (str::len(tempdir.to_str()) > 0u);
- let in = tempdir.push("in.txt");
- let out = tempdir.push("out.txt");
-
- /* Write the temp input file */
- let ostream = do as_c_charp(in.to_str()) |fromp| {
- do as_c_charp("w+b") |modebuf| {
- libc::fopen(fromp, modebuf)
- }
- };
- assert (ostream as uint != 0u);
- let s = ~"hello";
- let mut buf = vec::to_mut(str::to_bytes(s) + ~[0 as u8]);
- do vec::as_mut_buf(buf) |b, _len| {
- assert (libc::fwrite(b as *c_void, 1u as size_t,
- (str::len(s) + 1u) as size_t, ostream)
- == buf.len() as size_t)};
- assert (libc::fclose(ostream) == (0u as c_int));
- let rs = os::copy_file(&in, &out);
- if (!os::path_exists(&in)) {
- fail (fmt!("%s doesn't exist", in.to_str()));
- }
- assert(rs);
- let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
- assert (rslt == 0);
- assert (remove_file(&in));
- assert (remove_file(&out));
+ unsafe {
+ let tempdir = getcwd(); // would like to use $TMPDIR,
+ // doesn't seem to work on Linux
+ assert (str::len(tempdir.to_str()) > 0u);
+ let in = tempdir.push("in.txt");
+ let out = tempdir.push("out.txt");
+
+ /* Write the temp input file */
+ let ostream = do as_c_charp(in.to_str()) |fromp| {
+ do as_c_charp("w+b") |modebuf| {
+ libc::fopen(fromp, modebuf)
+ }
+ };
+ assert (ostream as uint != 0u);
+ let s = ~"hello";
+ let mut buf = vec::to_mut(str::to_bytes(s) + ~[0 as u8]);
+ do vec::as_mut_buf(buf) |b, _len| {
+ assert (libc::fwrite(b as *c_void, 1u as size_t,
+ (str::len(s) + 1u) as size_t, ostream)
+ == buf.len() as size_t)};
+ assert (libc::fclose(ostream) == (0u as c_int));
+ let rs = os::copy_file(&in, &out);
+ if (!os::path_exists(&in)) {
+ fail (fmt!("%s doesn't exist", in.to_str()));
+ }
+ assert(rs);
+ let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
+ assert (rslt == 0);
+ assert (remove_file(&in));
+ assert (remove_file(&out));
+ }
}
}
#[cfg(notest)]
impl<T:Eq> ~const T : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &~const T) -> bool { *(*self) == *(*other) }
+ #[inline(always)]
pure fn ne(&self, other: &~const T) -> bool { *(*self) != *(*other) }
}
#[cfg(notest)]
impl<T:Ord> ~const T : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &~const T) -> bool { *(*self) < *(*other) }
+ #[inline(always)]
pure fn le(&self, other: &~const T) -> bool { *(*self) <= *(*other) }
+ #[inline(always)]
pure fn ge(&self, other: &~const T) -> bool { *(*self) >= *(*other) }
+ #[inline(always)]
pure fn gt(&self, other: &~const T) -> bool { *(*self) > *(*other) }
}
#[forbid(deprecated_pattern)];
use cmp::Eq;
+use libc;
+use option::{None, Option, Some};
+use ptr;
+use str;
+use to_str::ToStr;
#[deriving_eq]
pub struct WindowsPath {
}
#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
mod stat {
#[cfg(target_arch = "x86")]
+ #[cfg(target_arch = "arm")]
pub mod arch {
+ use libc;
+
pub fn default_stat() -> libc::stat {
libc::stat {
st_dev: 0,
#[cfg(target_arch = "x86_64")]
pub mod arch {
+ use libc;
+
pub fn default_stat() -> libc::stat {
libc::stat {
st_dev: 0,
mod stat {
#[cfg(target_arch = "x86_64")]
pub mod arch {
+ use libc;
+
pub fn default_stat() -> libc::stat {
libc::stat {
st_dev: 0,
#[cfg(target_os = "macos")]
mod stat {
pub mod arch {
+ use libc;
+
pub fn default_stat() -> libc::stat {
libc::stat {
st_dev: 0,
#[cfg(target_os = "win32")]
mod stat {
pub mod arch {
+ use libc;
pub fn default_stat() -> libc::stat {
libc::stat {
st_dev: 0,
impl Path {
fn stat(&self) -> Option<libc::stat> {
- do str::as_c_str(self.to_str()) |buf| {
- let mut st = stat::arch::default_stat();
- let r = libc::stat(buf, ptr::mut_addr_of(&st));
+ unsafe {
+ do str::as_c_str(self.to_str()) |buf| {
+ let mut st = stat::arch::default_stat();
+ let r = libc::stat(buf, ptr::mut_addr_of(&st));
- if r == 0 { Some(move st) } else { None }
+ if r == 0 { Some(move st) } else { None }
+ }
}
}
#[cfg(unix)]
fn lstat(&self) -> Option<libc::stat> {
- do str::as_c_str(self.to_str()) |buf| {
- let mut st = stat::arch::default_stat();
- let r = libc::lstat(buf, ptr::mut_addr_of(&st));
+ unsafe {
+ do str::as_c_str(self.to_str()) |buf| {
+ let mut st = stat::arch::default_stat();
+ let r = libc::lstat(buf, ptr::mut_addr_of(&st));
- if r == 0 { Some(move st) } else { None }
+ if r == 0 { Some(move st) } else { None }
+ }
}
}
}
// Various windows helpers, and tests for the impl.
-mod windows {
+pub mod windows {
+ use libc;
+ use option::{None, Option, Some};
+ use to_str::ToStr;
+
#[inline(always)]
pub pure fn is_sep(u: u8) -> bool {
u == '/' as u8 || u == '\\' as u8
#[cfg(test)]
mod tests {
+ use option::{None, Some};
+ use path::{PosixPath, WindowsPath, windows};
+ use str;
+
#[test]
fn test_double_slash_collapsing() {
let path = PosixPath("tmp/");
use cmp::Eq;
use cast::{forget, reinterpret_cast, transmute};
use either::{Either, Left, Right};
+use kinds::Owned;
+use libc;
+use option;
use option::unwrap;
+use pipes;
+use ptr;
+use prelude::*;
+use private;
+use task;
+use vec;
#[doc(hidden)]
const SPIN_COUNT: uint = 0;
unsafe fn unblock() {
let old_task = swap_task(&mut self.blocked_task, ptr::null());
- if !old_task.is_null() { rustrt::rust_task_deref(old_task) }
+ if !old_task.is_null() {
+ unsafe {
+ rustrt::rust_task_deref(old_task)
+ }
+ }
match swap_state_acq(&mut self.state, Empty) {
Empty | Blocked => (),
Terminated => self.state = Terminated,
#[doc(hidden)]
pub trait HasBuffer {
- // XXX This should not have a trailing underscore
+ // FIXME #4421: This should not have a trailing underscore
fn set_buffer_(b: *libc::c_void);
}
#[doc(hidden)]
extern mod rustrt {
#[rust_stack]
- fn rust_get_task() -> *rust_task;
+ unsafe fn rust_get_task() -> *rust_task;
#[rust_stack]
- fn rust_task_ref(task: *rust_task);
- fn rust_task_deref(task: *rust_task);
+ unsafe fn rust_task_ref(task: *rust_task);
+ unsafe fn rust_task_deref(task: *rust_task);
#[rust_stack]
- fn task_clear_event_reject(task: *rust_task);
+ unsafe fn task_clear_event_reject(task: *rust_task);
- fn task_wait_event(this: *rust_task, killed: &mut *libc::c_void) -> bool;
- pure fn task_signal_event(target: *rust_task, event: *libc::c_void);
+ unsafe fn task_wait_event(this: *rust_task, killed: &mut *libc::c_void)
+ -> bool;
+ unsafe fn task_signal_event(target: *rust_task, event: *libc::c_void);
}
#[doc(hidden)]
fn wait_event(this: *rust_task) -> *libc::c_void {
- let mut event = ptr::null();
+ unsafe {
+ let mut event = ptr::null();
- let killed = rustrt::task_wait_event(this, &mut event);
- if killed && !task::failing() {
- fail ~"killed"
+ let killed = rustrt::task_wait_event(this, &mut event);
+ if killed && !task::failing() {
+ fail ~"killed"
+ }
+ event
}
- event
}
#[doc(hidden)]
debug!("waking up task for %?", p_);
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
if !old_task.is_null() {
- rustrt::task_signal_event(
- old_task, ptr::addr_of(&(p.header)) as *libc::c_void);
- rustrt::rust_task_deref(old_task);
+ unsafe {
+ rustrt::task_signal_event(
+ old_task,
+ ptr::addr_of(&(p.header)) as *libc::c_void);
+ rustrt::rust_task_deref(old_task);
+ }
}
// The receiver will eventually clean this up.
let old_task = swap_task(&mut self.p.blocked_task,
ptr::null());
if !old_task.is_null() {
- rustrt::rust_task_deref(old_task);
+ unsafe {
+ rustrt::rust_task_deref(old_task);
+ }
}
}
}
}
// regular path
- let this = rustrt::rust_get_task();
- rustrt::task_clear_event_reject(this);
- rustrt::rust_task_ref(this);
+ let this = unsafe { rustrt::rust_get_task() };
+ unsafe {
+ rustrt::task_clear_event_reject(this);
+ rustrt::rust_task_ref(this);
+ };
debug!("blocked = %x this = %x", p.header.blocked_task as uint,
this as uint);
let old_task = swap_task(&mut p.header.blocked_task, this);
let mut first = true;
let mut count = SPIN_COUNT;
loop {
- rustrt::task_clear_event_reject(this);
+ unsafe {
+ rustrt::task_clear_event_reject(this);
+ }
+
let old_state = swap_state_acq(&mut p.header.state,
Blocked);
match old_state {
payload <-> p.payload;
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
if !old_task.is_null() {
- rustrt::rust_task_deref(old_task);
+ unsafe {
+ rustrt::rust_task_deref(old_task);
+ }
}
p.header.state = Empty;
return Some(option::unwrap(move payload))
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
if !old_task.is_null() {
- rustrt::rust_task_deref(old_task);
+ unsafe {
+ rustrt::rust_task_deref(old_task);
+ }
}
return None;
}
// wake up the target
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
if !old_task.is_null() {
- rustrt::task_signal_event(
- old_task,
- ptr::addr_of(&(p.header)) as *libc::c_void);
- rustrt::rust_task_deref(old_task);
+ unsafe {
+ rustrt::task_signal_event(
+ old_task,
+ ptr::addr_of(&(p.header)) as *libc::c_void);
+ rustrt::rust_task_deref(old_task);
+ }
}
// The receiver will eventually clean up.
}
Blocked => {
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
if !old_task.is_null() {
- rustrt::rust_task_deref(old_task);
- assert old_task == rustrt::rust_get_task();
+ unsafe {
+ rustrt::rust_task_deref(old_task);
+ assert old_task == rustrt::rust_get_task();
+ }
}
}
Terminated | Full => {
*/
fn wait_many<T: Selectable>(pkts: &[T]) -> uint {
- let this = rustrt::rust_get_task();
+ let this = unsafe { rustrt::rust_get_task() };
+
+ unsafe {
+ rustrt::task_clear_event_reject(this);
+ }
- rustrt::task_clear_event_reject(this);
let mut data_avail = false;
let mut ready_packet = pkts.len();
for pkts.eachi |i, p| unsafe {
}
pub mod rt {
+ use option::{None, Option, Some};
+
// These are used to hide the option constructors from the
// compiler because their names are changing
pub fn make_some<T>(val: T) -> Option<T> { Some(move val) }
#[cfg(test)]
pub mod test {
+ use either::{Either, Left, Right};
+ use pipes::{Chan, Port, oneshot, recv_one, stream};
+ use pipes;
+
#[test]
pub fn test_select2() {
let (p1, c1) = pipes::stream();
--- /dev/null
+// This file is imported into every module by default.
+
+/* Reexported core operators */
+
+pub use kinds::{Const, Copy, Owned, Durable};
+pub use ops::{Drop};
+pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not};
+pub use ops::{BitAnd, BitOr, BitXor};
+pub use ops::{Shl, Shr, Index};
+pub use option::{Option, Some, None};
+pub use result::{Result, Ok, Err};
+
+/* Reexported types and traits */
+
+pub use path::Path;
+pub use path::GenericPath;
+pub use path::WindowsPath;
+pub use path::PosixPath;
+
+pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
+pub use str::{StrSlice, Trimmable};
+pub use vec::{ConstVector, CopyableVector, ImmutableVector};
+pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
+pub use vec::{OwnedVector, OwnedCopyableVector};
+pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
+pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
+
+pub use num::Num;
+pub use ptr::Ptr;
+pub use to_str::ToStr;
+pub use clone::Clone;
+
+pub use cmp::{Eq, Ord};
+pub use hash::Hash;
+pub use to_bytes::IterBytes;
+
+/* Reexported modules */
+
+pub use at_vec;
+pub use bool;
+pub use cast;
+pub use char;
+pub use cmp;
+pub use dvec;
+pub use either;
+pub use extfmt;
+pub use f32;
+pub use f64;
+pub use float;
+pub use i16;
+pub use i32;
+pub use i64;
+pub use i8;
+pub use int;
+pub use io;
+pub use iter;
+pub use libc;
+pub use num;
+pub use oldcomm;
+pub use ops;
+pub use option;
+pub use os;
+pub use path;
+pub use pipes;
+pub use private;
+pub use ptr;
+pub use rand;
+pub use result;
+pub use str;
+pub use sys;
+pub use task;
+pub use to_str;
+pub use u16;
+pub use u32;
+pub use u64;
+pub use u8;
+pub use uint;
+pub use vec;
+
+/*
+ * Export the log levels as global constants. Higher levels mean
+ * more-verbosity. Error is the bottom level, default logging level is
+ * warn-and-below.
+ */
+
+/// The error log level
+pub const error : u32 = 1_u32;
+/// The warning log level
+pub const warn : u32 = 2_u32;
+/// The info log level
+pub const info : u32 = 3_u32;
+/// The debug log level
+pub const debug : u32 = 4_u32;
#[doc(hidden)];
-use task::TaskBuilder;
-use task::atomically;
+use cast;
+use iter;
+use libc;
+use oldcomm;
+use option;
+use pipes;
+use prelude::*;
+use ptr;
+use result;
+use task;
+use task::{TaskBuilder, atomically};
+use uint;
extern mod rustrt {
#[legacy_exports];
- fn rust_task_weaken(ch: rust_port_id);
- fn rust_task_unweaken(ch: rust_port_id);
+ unsafe fn rust_task_weaken(ch: rust_port_id);
+ unsafe fn rust_task_unweaken(ch: rust_port_id);
- fn rust_create_little_lock() -> rust_little_lock;
- fn rust_destroy_little_lock(lock: rust_little_lock);
- fn rust_lock_little_lock(lock: rust_little_lock);
- fn rust_unlock_little_lock(lock: rust_little_lock);
+ unsafe fn rust_create_little_lock() -> rust_little_lock;
+ unsafe fn rust_destroy_little_lock(lock: rust_little_lock);
+ unsafe fn rust_lock_little_lock(lock: rust_little_lock);
+ unsafe fn rust_unlock_little_lock(lock: rust_little_lock);
+
+ unsafe fn rust_raw_thread_start(f: &fn()) -> *raw_thread;
+ unsafe fn rust_raw_thread_join_delete(thread: *raw_thread);
}
#[abi = "rust-intrinsic"]
extern mod rusti {
-
fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
fn atomic_xadd(dst: &mut int, src: int) -> int;
fn atomic_xsub(dst: &mut int, src: int) -> int;
}
+#[allow(non_camel_case_types)] // runtime type
+type raw_thread = libc::c_void;
+
+/**
+
+Start a new thread outside of the current runtime context and wait
+for it to terminate.
+
+The executing thread has no access to a task pointer and will be using
+a normal large stack.
+*/
+pub unsafe fn run_in_bare_thread(f: ~fn()) {
+ let (port, chan) = pipes::stream();
+ // XXX Unfortunate that this creates an extra scheduler but it's necessary
+ // since rust_raw_thread_join_delete is blocking
+ do task::spawn_sched(task::SingleThreaded) unsafe {
+ let closure: &fn() = || {
+ f()
+ };
+ let thread = rustrt::rust_raw_thread_start(closure);
+ rustrt::rust_raw_thread_join_delete(thread);
+ chan.send(());
+ }
+ port.recv();
+}
+
+#[test]
+fn test_run_in_bare_thread() unsafe {
+ let i = 100;
+ do run_in_bare_thread {
+ assert i == 100;
+ }
+}
+
#[allow(non_camel_case_types)] // runtime type
type rust_port_id = uint;
let (setup1_po, setup1_ch) = pipes::stream();
let (setup2_po, setup2_ch) = pipes::stream();
- // XXX: Ugly type inference hints
- let setup1_po: pipes::Port<oldcomm::Chan<T>> = setup1_po;
+ // FIXME #4422: Ugly type inference hint
let setup2_po: pipes::Port<Msg> = setup2_po;
do task_fn().spawn |move f, move setup1_ch, move setup2_po| {
struct LittleLock {
l: rust_little_lock,
- drop { rustrt::rust_destroy_little_lock(self.l); }
+ drop {
+ unsafe {
+ rustrt::rust_destroy_little_lock(self.l);
+ }
+ }
}
fn LittleLock() -> LittleLock {
- LittleLock {
- l: rustrt::rust_create_little_lock()
+ unsafe {
+ LittleLock {
+ l: rustrt::rust_create_little_lock()
+ }
}
}
unsafe fn lock<T>(f: fn() -> T) -> T {
struct Unlock {
l: rust_little_lock,
- drop { rustrt::rust_unlock_little_lock(self.l); }
+ drop {
+ unsafe {
+ rustrt::rust_unlock_little_lock(self.l);
+ }
+ }
}
fn Unlock(l: rust_little_lock) -> Unlock {
#[cfg(test)]
pub mod tests {
+ use core::option::{None, Some};
+
+ use option;
+ use pipes;
+ use private::{exclusive, unwrap_exclusive};
+ use result;
+ use task;
+ use uint;
+
#[test]
pub fn exclusive_arc() {
let mut futures = ~[];
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use cast;
use cmp::{Eq, Ord};
+use libc;
use libc::{c_void, size_t};
+use ptr;
+use str;
+use sys;
+use vec;
#[nolink]
#[abi = "cdecl"]
extern mod libc_ {
#[rust_stack]
- fn memcpy(dest: *mut c_void, src: *const c_void,
- n: libc::size_t) -> *c_void;
+ unsafe fn memcpy(dest: *mut c_void,
+ src: *const c_void,
+ n: libc::size_t)
+ -> *c_void;
#[rust_stack]
- fn memmove(dest: *mut c_void, src: *const c_void,
- n: libc::size_t) -> *c_void;
+ unsafe fn memmove(dest: *mut c_void,
+ src: *const c_void,
+ n: libc::size_t)
+ -> *c_void;
#[rust_stack]
- fn memset(dest: *mut c_void, c: libc::c_int,
- len: libc::size_t) -> *c_void;
+ unsafe fn memset(dest: *mut c_void,
+ c: libc::c_int,
+ len: libc::size_t)
+ -> *c_void;
}
#[abi = "rust-intrinsic"]
pub pure fn mut_null<T>() -> *mut T { unsafe { cast::reinterpret_cast(&0u) } }
/// Returns true if the pointer is equal to the null pointer.
+#[inline(always)]
pub pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
/// Returns true if the pointer is not equal to the null pointer.
+#[inline(always)]
pub pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
/**
* and destination may not overlap.
*/
#[inline(always)]
-pub unsafe fn memcpy<T>(dst: *mut T, src: *const T, count: uint) {
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
let n = count * sys::size_of::<T>();
libc_::memcpy(dst as *mut c_void, src as *c_void, n as size_t);
}
* and destination may overlap.
*/
#[inline(always)]
-pub unsafe fn memmove<T>(dst: *mut T, src: *const T, count: uint) {
+pub unsafe fn copy_overlapping_memory<T>(dst: *mut T, src: *const T,
+ count: uint) {
let n = count * sys::size_of::<T>();
libc_::memmove(dst as *mut c_void, src as *c_void, n as size_t);
}
#[inline(always)]
-pub unsafe fn memset<T>(dst: *mut T, c: int, count: uint) {
+pub unsafe fn set_memory<T>(dst: *mut T, c: int, count: uint) {
let n = count * sys::size_of::<T>();
libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t);
}
// Equality for pointers
#[cfg(notest)]
impl<T> *const T : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &*const T) -> bool unsafe {
let a: uint = cast::reinterpret_cast(&(*self));
let b: uint = cast::reinterpret_cast(&(*other));
return a == b;
}
+ #[inline(always)]
pure fn ne(&self, other: &*const T) -> bool { !(*self).eq(other) }
}
// Comparison for pointers
#[cfg(notest)]
impl<T> *const T : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &*const T) -> bool unsafe {
let a: uint = cast::reinterpret_cast(&(*self));
let b: uint = cast::reinterpret_cast(&(*other));
return a < b;
}
+ #[inline(always)]
pure fn le(&self, other: &*const T) -> bool unsafe {
let a: uint = cast::reinterpret_cast(&(*self));
let b: uint = cast::reinterpret_cast(&(*other));
return a <= b;
}
+ #[inline(always)]
pure fn ge(&self, other: &*const T) -> bool unsafe {
let a: uint = cast::reinterpret_cast(&(*self));
let b: uint = cast::reinterpret_cast(&(*other));
return a >= b;
}
+ #[inline(always)]
pure fn gt(&self, other: &*const T) -> bool unsafe {
let a: uint = cast::reinterpret_cast(&(*self));
let b: uint = cast::reinterpret_cast(&(*other));
// Equality for region pointers
#[cfg(notest)]
impl<T:Eq> &const T : Eq {
+ #[inline(always)]
pure fn eq(&self, other: & &self/const T) -> bool {
return *(*self) == *(*other);
}
+ #[inline(always)]
pure fn ne(&self, other: & &self/const T) -> bool {
return *(*self) != *(*other);
}
// Comparison for region pointers
#[cfg(notest)]
impl<T:Ord> &const T : Ord {
+ #[inline(always)]
pure fn lt(&self, other: & &self/const T) -> bool {
*(*self) < *(*other)
}
+ #[inline(always)]
pure fn le(&self, other: & &self/const T) -> bool {
*(*self) <= *(*other)
}
+ #[inline(always)]
pure fn ge(&self, other: & &self/const T) -> bool {
*(*self) >= *(*other)
}
+ #[inline(always)]
pure fn gt(&self, other: & &self/const T) -> bool {
*(*self) > *(*other)
}
let mut v0 = ~[32000u16, 32001u16, 32002u16];
let mut v1 = ~[0u16, 0u16, 0u16];
- ptr::memcpy(ptr::mut_offset(vec::raw::to_mut_ptr(v1), 1u),
+ ptr::copy_memory(ptr::mut_offset(vec::raw::to_mut_ptr(v1), 1u),
ptr::offset(vec::raw::to_ptr(v0), 1u), 1u);
assert (v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
- ptr::memcpy(vec::raw::to_mut_ptr(v1),
+ ptr::copy_memory(vec::raw::to_mut_ptr(v1),
ptr::offset(vec::raw::to_ptr(v0), 2u), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
- ptr::memcpy(ptr::mut_offset(vec::raw::to_mut_ptr(v1), 2u),
+ ptr::copy_memory(ptr::mut_offset(vec::raw::to_mut_ptr(v1), 2u),
vec::raw::to_ptr(v0), 1u);
assert (v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use int;
+use prelude::*;
+use str;
+use task;
+use u32;
+use uint;
+use util;
+use vec;
+
#[allow(non_camel_case_types)] // runtime type
enum rctx {}
#[abi = "cdecl"]
extern mod rustrt {
- fn rand_seed() -> ~[u8];
- fn rand_new() -> *rctx;
- fn rand_new_seeded2(&&seed: ~[u8]) -> *rctx;
- fn rand_next(c: *rctx) -> u32;
- fn rand_free(c: *rctx);
+ unsafe fn rand_seed() -> ~[u8];
+ unsafe fn rand_new() -> *rctx;
+ unsafe fn rand_new_seeded2(&&seed: ~[u8]) -> *rctx;
+ unsafe fn rand_next(c: *rctx) -> u32;
+ unsafe fn rand_free(c: *rctx);
}
/// A random number generator
struct RandRes {
c: *rctx,
- drop { rustrt::rand_free(self.c); }
+ drop {
+ unsafe {
+ rustrt::rand_free(self.c);
+ }
+ }
}
fn RandRes(c: *rctx) -> RandRes {
}
impl @RandRes: Rng {
- fn next() -> u32 { return rustrt::rand_next((*self).c); }
+ fn next() -> u32 {
+ unsafe {
+ return rustrt::rand_next((*self).c);
+ }
+ }
}
/// Create a new random seed for seeded_rng
pub fn seed() -> ~[u8] {
- rustrt::rand_seed()
+ unsafe {
+ rustrt::rand_seed()
+ }
}
/// Create a random number generator with a system specified seed
pub fn Rng() -> Rng {
- @RandRes(rustrt::rand_new()) as Rng
+ unsafe {
+ @RandRes(rustrt::rand_new()) as Rng
+ }
}
/**
* length.
*/
pub fn seeded_rng(seed: &~[u8]) -> Rng {
- @RandRes(rustrt::rand_new_seeded2(*seed)) as Rng
+ unsafe {
+ @RandRes(rustrt::rand_new_seeded2(*seed)) as Rng
+ }
}
type XorShiftState = {
}
match r {
None => {
- let rng = @RandRes(rustrt::rand_new());
unsafe {
+ let rng = @RandRes(rustrt::rand_new());
task::local_data::local_data_set(tls_rng_state, rng);
+ rng as Rng
}
- rng as Rng
}
Some(rng) => rng as Rng
}
#[cfg(test)]
pub mod tests {
+ use debug;
+ use option::{None, Option, Some};
+ use rand;
+
#[test]
pub fn rng_seeded() {
let seed = rand::seed();
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
use libc::c_void;
+use sys;
+use vec;
/**
* Trait for visitor that wishes to reflect on data. To use this, create a
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
-use io::{Writer, WriterUtil};
-use libc::c_void;
-use to_str::ToStr;
use cast::transmute;
+use cast;
+use char;
+use dvec::DVec;
+use intrinsic;
use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
+use io;
+use io::{Writer, WriterUtil};
+use libc::c_void;
+use managed;
+use managed::raw::BoxHeaderRepr;
+use ptr;
+use reflect;
use reflect::{MovePtr, MovePtrAdaptor, align};
+use repr;
+use str;
+use sys;
+use sys::TypeDesc;
+use to_str::ToStr;
+use uint;
use vec::UnboxedVecRepr;
use vec::raw::{VecRepr, SliceRepr};
+use vec;
+
pub use managed::raw::BoxRepr;
-use dvec::DVec;
/// Helpers
'"' => self.write_str("\\\""),
'\x20'..'\x7e' => self.write_char(ch),
_ => {
- // XXX: This is inefficient because it requires a malloc.
+ // FIXME #4423: This is inefficient because it requires a
+ // malloc.
self.write_str(char::escape_unicode(ch))
}
}
fn write_repr(writer: @Writer) { writer.write_int(self as int); }
}
impl i64 : Repr {
- // XXX: This can lose precision.
+ // FIXME #4424: This can lose precision.
fn write_repr(writer: @Writer) { writer.write_int(self as int); }
}
fn write_repr(writer: @Writer) { writer.write_uint(self as uint); }
}
impl u64 : Repr {
- // XXX: This can lose precision.
+ // FIXME #4424: This can lose precision.
fn write_repr(writer: @Writer) { writer.write_uint(self as uint); }
}
impl float : Repr {
- // XXX: This mallocs.
+ // FIXME #4423: This mallocs.
fn write_repr(writer: @Writer) { writer.write_str(self.to_str()); }
}
impl f32 : Repr {
- // XXX: This mallocs.
+ // FIXME #4423 This mallocs.
fn write_repr(writer: @Writer) { writer.write_str(self.to_str()); }
}
impl f64 : Repr {
- // XXX: This mallocs.
+ // FIXME #4423: This mallocs.
fn write_repr(writer: @Writer) { writer.write_str(self.to_str()); }
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use cmp;
use cmp::Eq;
+use either;
use either::Either;
+use kinds::Copy;
+use option::{None, Option, Some};
+use vec;
/// The result type
#[deriving_eq]
*
* If the result is an error
*/
+#[inline(always)]
pub pure fn get<T: Copy, U>(res: &Result<T, U>) -> T {
match *res {
Ok(copy t) => t,
*
* If the result is an error
*/
+#[inline(always)]
pub pure fn get_ref<T, U>(res: &a/Result<T, U>) -> &a/T {
match *res {
Ok(ref t) => t,
*
* If the result is not an error
*/
+#[inline(always)]
pub pure fn get_err<T, U: Copy>(res: &Result<T, U>) -> U {
match *res {
Err(copy u) => u,
}
/// Returns true if the result is `ok`
+#[inline(always)]
pub pure fn is_ok<T, U>(res: &Result<T, U>) -> bool {
match *res {
Ok(_) => true,
}
/// Returns true if the result is `err`
+#[inline(always)]
pub pure fn is_err<T, U>(res: &Result<T, U>) -> bool {
!is_ok(res)
}
* `ok` result variants are converted to `either::right` variants, `err`
* result variants are converted to `either::left`.
*/
+#[inline(always)]
pub pure fn to_either<T: Copy, U: Copy>(res: &Result<U, T>)
-> Either<T, U> {
match *res {
* ok(parse_bytes(buf))
* }
*/
+#[inline(always)]
pub pure fn chain<T, U, V>(res: Result<T, V>, op: fn(T)
-> Result<U, V>) -> Result<U, V> {
match move res {
* immediately returned. This function can be used to pass through a
* successful result while handling an error.
*/
+#[inline(always)]
pub pure fn chain_err<T, U, V>(
res: Result<T, V>,
op: fn(t: V) -> Result<T, U>)
* print_buf(buf)
* }
*/
+#[inline(always)]
pub pure fn iter<T, E>(res: &Result<T, E>, f: fn(&T)) {
match *res {
Ok(ref t) => f(t),
* This function can be used to pass through a successful result while
* handling an error.
*/
+#[inline(always)]
pub pure fn iter_err<T, E>(res: &Result<T, E>, f: fn(&E)) {
match *res {
Ok(_) => (),
* parse_bytes(buf)
* }
*/
+#[inline(always)]
pub pure fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: fn(&T) -> U)
-> Result<U, E> {
match *res {
* is immediately returned. This function can be used to pass through a
* successful result while handling an error.
*/
+#[inline(always)]
pub pure fn map_err<T: Copy, E, F: Copy>(res: &Result<T, E>, op: fn(&E) -> F)
-> Result<T, F> {
match *res {
* assert incd == ~[2u, 3u, 4u];
* }
*/
+#[inline(always)]
pub fn map_vec<T,U:Copy,V:Copy>(
ts: &[T], op: fn(&T) -> Result<V,U>) -> Result<~[V],U> {
return Ok(move vs);
}
+#[inline(always)]
pub fn map_opt<T,U:Copy,V:Copy>(
o_t: &Option<T>, op: fn(&T) -> Result<V,U>) -> Result<Option<V>,U> {
* used in 'careful' code contexts where it is both appropriate and easy
* to accommodate an error like the vectors being of different lengths.
*/
+#[inline(always)]
pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
op: fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
* error. This could be implemented using `map2()` but it is more efficient
* on its own as no result vector is built.
*/
+#[inline(always)]
pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
op: fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
#[allow(non_implicitly_copyable_typarams)]
mod tests {
#[legacy_exports];
+
+ use result::{Err, Ok, Result, chain, get, get_err};
+ use result;
+
fn op1() -> result::Result<int, ~str> { result::Ok(666) }
fn op2(i: int) -> result::Result<uint, ~str> {
#[forbid(deprecated_pattern)];
//! Runtime calls emitted by the compiler.
-use libc::c_char;
-use libc::c_void;
-use libc::size_t;
-use libc::uintptr_t;
+use libc::{c_char, c_void, size_t, uintptr_t};
+use str;
+use sys;
use gc::{cleanup_stack_for_failure, gc, Word};
extern mod rustrt {
#[rust_stack]
- fn rust_upcall_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char;
+ unsafe fn rust_upcall_exchange_malloc(td: *c_char, size: uintptr_t)
+ -> *c_char;
#[rust_stack]
- fn rust_upcall_exchange_free(ptr: *c_char);
+ unsafe fn rust_upcall_exchange_free(ptr: *c_char);
#[rust_stack]
- fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;
+ unsafe fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;
#[rust_stack]
- fn rust_upcall_free(ptr: *c_char);
+ unsafe fn rust_upcall_free(ptr: *c_char);
}
-// FIXME (#2861): This needs both the attribute, and the name prefixed with
-// 'rt_', otherwise the compiler won't find it. To fix this, see
-// gather_rust_rtcalls.
#[rt(fail_)]
+#[lang="fail_"]
pub fn rt_fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
sys::begin_unwind_(expr, file, line);
}
#[rt(fail_bounds_check)]
-pub fn rt_fail_bounds_check(file: *c_char, line: size_t,
- index: size_t, len: size_t) {
+#[lang="fail_bounds_check"]
+pub unsafe fn rt_fail_bounds_check(file: *c_char, line: size_t,
+ index: size_t, len: size_t) {
let msg = fmt!("index out of bounds: the len is %d but the index is %d",
len as int, index as int);
do str::as_buf(msg) |p, _len| {
}
#[rt(exchange_malloc)]
-pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
+#[lang="exchange_malloc"]
+pub unsafe fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
return rustrt::rust_upcall_exchange_malloc(td, size);
}
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[rt(exchange_free)]
-pub fn rt_exchange_free(ptr: *c_char) {
+#[lang="exchange_free"]
+pub unsafe fn rt_exchange_free(ptr: *c_char) {
rustrt::rust_upcall_exchange_free(ptr);
}
#[rt(malloc)]
-pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
+#[lang="malloc"]
+pub unsafe fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
return rustrt::rust_upcall_malloc(td, size);
}
// inside a landing pad may corrupt the state of the exception handler. If a
// problem occurs, call exit instead.
#[rt(free)]
-pub fn rt_free(ptr: *c_char) {
+#[lang="free"]
+pub unsafe fn rt_free(ptr: *c_char) {
rustrt::rust_upcall_free(ptr);
}
#[forbid(deprecated_pattern)];
//! Process spawning
-use option::{Some, None};
-use libc::{pid_t, c_void, c_int};
+use io;
use io::ReaderUtil;
+use libc;
+use libc::{pid_t, c_void, c_int};
+use oldcomm;
+use option::{Some, None};
+use os;
+use prelude::*;
+use ptr;
+use run;
+use str;
+use task;
+use vec;
#[abi = "cdecl"]
extern mod rustrt {
- fn rust_run_program(argv: **libc::c_char, envp: *c_void,
- dir: *libc::c_char,
- in_fd: c_int, out_fd: c_int, err_fd: c_int)
- -> pid_t;
+ unsafe fn rust_run_program(argv: **libc::c_char, envp: *c_void,
+ dir: *libc::c_char,
+ in_fd: c_int, out_fd: c_int, err_fd: c_int)
+ -> pid_t;
}
/// A value representing a child process
env: &Option<~[(~str,~str)]>,
dir: &Option<~str>,
in_fd: c_int, out_fd: c_int, err_fd: c_int)
- -> pid_t {
- do with_argv(prog, args) |argv| {
- do with_envp(env) |envp| {
- do with_dirp(dir) |dirp| {
- rustrt::rust_run_program(argv, envp, dirp,
- in_fd, out_fd, err_fd)
+ -> pid_t {
+ unsafe {
+ do with_argv(prog, args) |argv| {
+ do with_envp(env) |envp| {
+ do with_dirp(dir) |dirp| {
+ rustrt::rust_run_program(argv, envp, dirp,
+ in_fd, out_fd, err_fd)
+ }
}
}
}
* A class with a <program> field
*/
pub fn start_program(prog: &str, args: &[~str]) -> Program {
- let pipe_input = os::pipe();
- let pipe_output = os::pipe();
- let pipe_err = os::pipe();
- let pid =
- spawn_process(prog, args, &None, &None,
- pipe_input.in, pipe_output.out,
- pipe_err.out);
+ unsafe {
+ let pipe_input = os::pipe();
+ let pipe_output = os::pipe();
+ let pipe_err = os::pipe();
+ let pid =
+ spawn_process(prog, args, &None, &None,
+ pipe_input.in, pipe_output.out,
+ pipe_err.out);
+
+ unsafe {
+ if pid == -1 as pid_t { fail; }
+ libc::close(pipe_input.in);
+ libc::close(pipe_output.out);
+ libc::close(pipe_err.out);
+ }
- if pid == -1 as pid_t { fail; }
- libc::close(pipe_input.in);
- libc::close(pipe_output.out);
- libc::close(pipe_err.out);
-
- type ProgRepr = {pid: pid_t,
- mut in_fd: c_int,
- out_file: *libc::FILE,
- err_file: *libc::FILE,
- mut finished: bool};
-
- fn close_repr_input(r: &ProgRepr) {
- let invalid_fd = -1i32;
- if r.in_fd != invalid_fd {
- libc::close(r.in_fd);
- r.in_fd = invalid_fd;
+ type ProgRepr = {pid: pid_t,
+ mut in_fd: c_int,
+ out_file: *libc::FILE,
+ err_file: *libc::FILE,
+ mut finished: bool};
+
+ fn close_repr_input(r: &ProgRepr) {
+ let invalid_fd = -1i32;
+ if r.in_fd != invalid_fd {
+ unsafe {
+ libc::close(r.in_fd);
+ }
+ r.in_fd = invalid_fd;
+ }
+ }
+ fn finish_repr(r: &ProgRepr) -> int {
+ if r.finished { return 0; }
+ r.finished = true;
+ close_repr_input(r);
+ return waitpid(r.pid);
+ }
+ fn destroy_repr(r: &ProgRepr) {
+ unsafe {
+ finish_repr(r);
+ libc::fclose(r.out_file);
+ libc::fclose(r.err_file);
+ }
+ }
+ struct ProgRes {
+ r: ProgRepr,
+ drop { destroy_repr(&self.r); }
}
- }
- fn finish_repr(r: &ProgRepr) -> int {
- if r.finished { return 0; }
- r.finished = true;
- close_repr_input(r);
- return waitpid(r.pid);
- }
- fn destroy_repr(r: &ProgRepr) {
- finish_repr(r);
- libc::fclose(r.out_file);
- libc::fclose(r.err_file);
- }
- struct ProgRes {
- r: ProgRepr,
- drop { destroy_repr(&self.r); }
- }
- fn ProgRes(r: ProgRepr) -> ProgRes {
- ProgRes {
- r: move r
+ fn ProgRes(r: ProgRepr) -> ProgRes {
+ ProgRes {
+ r: move r
+ }
}
- }
- impl ProgRes: Program {
- fn get_id() -> pid_t { return self.r.pid; }
- fn input() -> io::Writer { io::fd_writer(self.r.in_fd, false) }
- fn output() -> io::Reader { io::FILE_reader(self.r.out_file, false) }
- fn err() -> io::Reader { io::FILE_reader(self.r.err_file, false) }
- fn close_input() { close_repr_input(&self.r); }
- fn finish() -> int { finish_repr(&self.r) }
- fn destroy() { destroy_repr(&self.r); }
+ impl ProgRes: Program {
+ fn get_id() -> pid_t { return self.r.pid; }
+ fn input() -> io::Writer {
+ io::fd_writer(self.r.in_fd, false)
+ }
+ fn output() -> io::Reader {
+ io::FILE_reader(self.r.out_file, false)
+ }
+ fn err() -> io::Reader {
+ io::FILE_reader(self.r.err_file, false)
+ }
+ fn close_input() { close_repr_input(&self.r); }
+ fn finish() -> int { finish_repr(&self.r) }
+ fn destroy() { destroy_repr(&self.r); }
+ }
+ let repr = {pid: pid,
+ mut in_fd: pipe_input.out,
+ out_file: os::fdopen(pipe_output.in),
+ err_file: os::fdopen(pipe_err.in),
+ mut finished: false};
+ return ProgRes(move repr) as Program;
}
- let repr = {pid: pid,
- mut in_fd: pipe_input.out,
- out_file: os::fdopen(pipe_output.in),
- err_file: os::fdopen(pipe_err.in),
- mut finished: false};
- return ProgRes(move repr) as Program;
}
fn read_all(rd: io::Reader) -> ~str {
*/
pub fn program_output(prog: &str, args: &[~str]) ->
{status: int, out: ~str, err: ~str} {
+ unsafe {
+ let pipe_in = os::pipe();
+ let pipe_out = os::pipe();
+ let pipe_err = os::pipe();
+ let pid = spawn_process(prog, args, &None, &None,
+ pipe_in.in, pipe_out.out, pipe_err.out);
- let pipe_in = os::pipe();
- let pipe_out = os::pipe();
- let pipe_err = os::pipe();
- let pid = spawn_process(prog, args, &None, &None,
- pipe_in.in, pipe_out.out, pipe_err.out);
+ os::close(pipe_in.in);
+ os::close(pipe_out.out);
+ os::close(pipe_err.out);
+ if pid == -1i32 {
+ os::close(pipe_in.out);
+ os::close(pipe_out.in);
+ os::close(pipe_err.in);
+ fail;
+ }
- os::close(pipe_in.in);
- os::close(pipe_out.out);
- os::close(pipe_err.out);
- if pid == -1i32 {
os::close(pipe_in.out);
- os::close(pipe_out.in);
- os::close(pipe_err.in);
- fail;
- }
- os::close(pipe_in.out);
-
- // Spawn two entire schedulers to read both stdout and sterr
- // in parallel so we don't deadlock while blocking on one
- // or the other. FIXME (#2625): Surely there's a much more
- // clever way to do this.
- let p = oldcomm::Port();
- let ch = oldcomm::Chan(&p);
- do task::spawn_sched(task::SingleThreaded) {
- let errput = readclose(pipe_err.in);
- oldcomm::send(ch, (2, move errput));
- };
- do task::spawn_sched(task::SingleThreaded) {
- let output = readclose(pipe_out.in);
- oldcomm::send(ch, (1, move output));
- };
- let status = run::waitpid(pid);
- let mut errs = ~"";
- let mut outs = ~"";
- let mut count = 2;
- while count > 0 {
- let stream = oldcomm::recv(p);
- match stream {
- (1, copy s) => {
- outs = move s;
- }
- (2, copy s) => {
- errs = move s;
- }
- (n, _) => {
- fail(fmt!("program_output received an unexpected file \
- number: %u", n));
- }
+ // Spawn two entire schedulers to read both stdout and sterr
+ // in parallel so we don't deadlock while blocking on one
+ // or the other. FIXME (#2625): Surely there's a much more
+ // clever way to do this.
+ let p = oldcomm::Port();
+ let ch = oldcomm::Chan(&p);
+ do task::spawn_sched(task::SingleThreaded) {
+ let errput = readclose(pipe_err.in);
+ oldcomm::send(ch, (2, move errput));
+ };
+ do task::spawn_sched(task::SingleThreaded) {
+ let output = readclose(pipe_out.in);
+ oldcomm::send(ch, (1, move output));
+ };
+ let status = run::waitpid(pid);
+ let mut errs = ~"";
+ let mut outs = ~"";
+ let mut count = 2;
+ while count > 0 {
+ let stream = oldcomm::recv(p);
+ match stream {
+ (1, copy s) => {
+ outs = move s;
+ }
+ (2, copy s) => {
+ errs = move s;
+ }
+ (n, _) => {
+ fail(fmt!("program_output received an unexpected file \
+ number: %u", n));
+ }
+ };
+ count -= 1;
};
- count -= 1;
- };
- return {status: status, out: move outs, err: move errs};
+ return {status: status, out: move outs, err: move errs};
+ }
}
-fn writeclose(fd: c_int, s: ~str) {
+pub fn writeclose(fd: c_int, s: ~str) {
use io::WriterUtil;
error!("writeclose %d, %s", fd as int, s);
os::close(fd);
}
-fn readclose(fd: c_int) -> ~str {
- let file = os::fdopen(fd);
- let reader = io::FILE_reader(file, false);
- let buf = io::with_bytes_writer(|writer| {
- let mut bytes = [mut 0, ..4096];
- while !reader.eof() {
- let nread = reader.read(bytes, bytes.len());
- writer.write(bytes.view(0, nread));
- }
- });
- os::fclose(file);
- str::from_bytes(buf)
+pub fn readclose(fd: c_int) -> ~str {
+ unsafe {
+ let file = os::fdopen(fd);
+ let reader = io::FILE_reader(file, false);
+ let buf = io::with_bytes_writer(|writer| {
+ let mut bytes = [mut 0, ..4096];
+ while !reader.eof() {
+ let nread = reader.read(bytes, bytes.len());
+ writer.write(bytes.view(0, nread));
+ }
+ });
+ os::fclose(file);
+ str::from_bytes(buf)
+ }
}
/// Waits for a process to exit and returns the exit code
#[cfg(unix)]
fn waitpid_os(pid: pid_t) -> int {
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
fn WIFEXITED(status: i32) -> bool {
(status & 0xffi32) == 0i32
}
}
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
fn WEXITSTATUS(status: i32) -> i32 {
(status >> 8i32) & 0xffi32
}
#[cfg(test)]
mod tests {
+ use debug;
use io::WriterUtil;
+ use option::{None, Some};
+ use os;
+ use run::{readclose, writeclose};
+ use run;
// Regression test for memory leaks
#[ignore(cfg(windows))] // FIXME (#2626)
use cmp::Eq;
use hash::Hash;
+use prelude::*;
use to_bytes::IterBytes;
pub trait SendMap<K:Eq Hash, V: Copy> {
/// Open addressing with linear probing.
pub mod linear {
+ use cmp::Eq;
+ use cmp;
+ use hash::Hash;
+ use kinds::Copy;
+ use option::{None, Option, Some};
+ use option;
+ use rand;
+ use to_bytes::IterBytes;
+ use uint;
+ use vec;
+
const INITIAL_CAPACITY: uint = 32u; // 2^5
struct Bucket<K:Eq Hash,V> {
let mut old_buckets = vec::from_fn(new_capacity, |_i| None);
self.buckets <-> old_buckets;
+ self.size = 0;
for uint::range(0, old_capacity) |i| {
let mut bucket = None;
bucket <-> old_buckets[i];
#[test]
pub mod test {
+ use option::{None, Some};
use send_map::linear::LinearMap;
+ use send_map::linear;
+ use uint;
#[test]
pub fn inserts() {
assert m1 == m2;
}
+
+ #[test]
+ pub fn test_expand() {
+ let mut m = ~LinearMap();
+
+ assert m.len() == 0;
+ assert m.is_empty();
+
+ let mut i = 0u;
+ let old_resize_at = m.resize_at;
+ while old_resize_at == m.resize_at {
+ m.insert(i, i);
+ i += 1;
+ }
+
+ assert m.len() == i;
+ assert !m.is_empty();
+ }
}
#[legacy_modes]; // tjc: remove after snapshot
// NB: transitionary, de-mode-ing.
-// XXX: Can't forbid this because frame_address needs a deprecated mode.
+// FIXME #4425: Can't forbid this because frame_address needs a deprecated
+// mode.
#[allow(deprecated_mode)];
#[forbid(deprecated_pattern)];
}
fn breakpoint() {
- rustrt::rust_dbg_breakpoint()
+ unsafe {
+ rustrt::rust_dbg_breakpoint()
+ }
}
fn frame_address(f: fn(++x: *u8)) {
- rusti::frame_address(f)
+ unsafe {
+ rusti::frame_address(f)
+ }
}
extern mod rustrt {
#[legacy_exports];
- fn rust_dbg_breakpoint();
+ unsafe fn rust_dbg_breakpoint();
}
#[abi = "rust-intrinsic"]
extern mod rusti {
#[legacy_exports];
- fn frame_address(f: fn(++x: *u8));
+ fn frame_address(f: &once fn(++x: *u8));
}
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use at_vec;
+use cast;
+use char;
use cmp::{Eq, Ord};
+use libc;
use libc::size_t;
use io::WriterUtil;
+use option::{None, Option, Some};
+use ptr;
+use str;
use to_str::ToStr;
+use u8;
+use uint;
+use vec;
/*
Section: Creating a string
do as_buf(rhs) |rbuf, _rlen| {
let dst = ptr::offset(lbuf, llen);
let dst = ::cast::transmute_mut_unsafe(dst);
- ptr::memcpy(dst, rbuf, rlen);
+ ptr::copy_memory(dst, rbuf, rlen);
}
}
raw::set_len(lhs, llen + rlen);
do as_buf(rhs) |rbuf, _rlen| {
let dst = ptr::offset(lbuf, llen);
let dst = ::cast::transmute_mut_unsafe(dst);
- ptr::memcpy(dst, rbuf, rlen);
+ ptr::copy_memory(dst, rbuf, rlen);
}
}
raw::set_len(lhs, llen + rlen);
/// Unsafe operations
pub mod raw {
+ use cast;
+ use libc;
+ use ptr;
+ use str::raw;
+ use str::{as_buf, is_utf8, len, reserve_at_least};
+ use vec;
/// Create a Rust string from a null-terminated *u8 buffer
pub unsafe fn from_buf(buf: *u8) -> ~str {
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> ~str {
let mut v: ~[u8] = vec::with_capacity(len + 1);
vec::as_mut_buf(v, |vbuf, _len| {
- ptr::memcpy(vbuf, buf as *u8, len)
+ ptr::copy_memory(vbuf, buf as *u8, len)
});
vec::raw::set_len(&mut v, len);
v.push(0u8);
do vec::as_imm_buf(v) |vbuf, _vlen| {
let vbuf = ::cast::transmute_mut_unsafe(vbuf);
let src = ptr::offset(sbuf, begin);
- ptr::memcpy(vbuf, src, end - begin);
+ ptr::copy_memory(vbuf, src, end - begin);
}
vec::raw::set_len(&mut v, end - begin);
v.push(0u8);
#[cfg(notest)]
pub mod traits {
+ use ops::Add;
+ use str::append;
+
impl ~str : Add<&str,~str> {
#[inline(always)]
pure fn add(&self, rhs: & &self/str) -> ~str {
#[cfg(test)]
mod tests {
-
+ use char;
+ use debug;
use libc::c_char;
+ use libc;
+ use ptr;
+ use str::*;
+ use vec;
#[test]
fn test_eq() {
#[test]
fn test_to_lower() {
- assert ~"" == map(~"", |c| libc::tolower(c as c_char) as char);
- assert ~"ymca" == map(~"YMCA",
- |c| libc::tolower(c as c_char) as char);
+ unsafe {
+ assert ~"" == map(~"", |c| libc::tolower(c as c_char) as char);
+ assert ~"ymca" == map(~"YMCA",
+ |c| libc::tolower(c as c_char) as char);
+ }
}
#[test]
#[test]
fn test_map() {
- assert ~"" == map(~"", |c| libc::toupper(c as c_char) as char);
- assert ~"YMCA" == map(~"ymca",
- |c| libc::toupper(c as c_char) as char);
+ unsafe {
+ assert ~"" == map(~"", |c| libc::toupper(c as c_char) as char);
+ assert ~"YMCA" == map(~"ymca",
+ |c| libc::toupper(c as c_char) as char);
+ }
}
#[test]
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use cast;
use cmp::{Eq, Ord};
+use gc;
+use io;
+use libc;
use libc::{c_void, c_char, size_t};
+use ptr;
+use repr;
+use str;
+use vec;
pub type FreeGlue = fn(*TypeDesc, *c_void);
extern mod rustrt {
#[rust_stack]
- fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
+ unsafe fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
}
/// Compares contents of two pointers using the default method.
unsafe { rusti::size_of::<T>() }
}
+/**
+ * Returns the size of a type, or 1 if the actual size is zero.
+ *
+ * Useful for building structures containing variable-length arrays.
+ */
+#[inline(always)]
+pub pure fn nonzero_size_of<T>() -> uint {
+ let s = size_of::<T>();
+ if s == 0 { 1 } else { s }
+}
+
/**
* Returns the ABI-required minimum alignment of a type
*
}
}
-// XXX: Temorary until rt::rt_fail_ goes away
+// FIXME #4427: Temporary until rt::rt_fail_ goes away
pub pure fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
unsafe {
gc::cleanup_stack_for_failure();
#[cfg(test)]
pub mod tests {
+ use cast;
+ use sys::{Closure, pref_align_of, size_of, nonzero_size_of};
#[test]
pub fn size_of_basic() {
assert size_of::<*uint>() == 8u;
}
+ #[test]
+ pub fn nonzero_size_of_basic() {
+ type Z = [i8 * 0];
+ assert size_of::<Z>() == 0u;
+ assert nonzero_size_of::<Z>() == 1u;
+ assert nonzero_size_of::<uint>() == size_of::<uint>();
+ }
+
#[test]
pub fn align_of_basic() {
assert pref_align_of::<u8>() == 1u;
*/
-use task::local_data_priv::{
- local_pop,
- local_get,
- local_set,
- local_modify
-};
+use prelude::*;
+use rt;
+use task::local_data_priv::{local_get, local_pop, local_modify, local_set};
+use task;
/**
* Indexes a task-local data slot. The function's code pointer is used for
#[doc(hidden)]; // FIXME #3538
+use cast;
+use cmp::Eq;
+use dvec;
+use libc;
+use option;
+use prelude::*;
+use task::rt;
use task::local_data::LocalDataKey;
#[cfg(notest)]
* ~~~
*/
+use cast;
+use cmp;
use cmp::Eq;
+use iter;
+use libc;
+use oldcomm;
+use option;
use result::Result;
use pipes::{stream, Chan, Port};
+use pipes;
+use prelude::*;
+use ptr;
+use result;
use task::local_data_priv::{local_get, local_set};
use task::rt::{task_id, rust_task};
+use task;
+use util;
use util::replace;
mod local_data_priv;
pub mod spawn;
/// A handle to a task
+#[deriving_eq]
pub enum Task {
TaskHandle(task_id)
}
-// XXX: deriving
-impl Task : cmp::Eq {
- pure fn eq(&self, other: &Task) -> bool { *(*self) == *(*other) }
- pure fn ne(&self, other: &Task) -> bool { !(*self).eq(other) }
-}
-
/**
* Indicates the manner in which a task exited.
*
#[nolink]
#[cfg(test)]
extern mod testrt {
- fn rust_dbg_lock_create() -> *libc::c_void;
- fn rust_dbg_lock_destroy(lock: *libc::c_void);
- fn rust_dbg_lock_lock(lock: *libc::c_void);
- fn rust_dbg_lock_unlock(lock: *libc::c_void);
- fn rust_dbg_lock_wait(lock: *libc::c_void);
- fn rust_dbg_lock_signal(lock: *libc::c_void);
+ unsafe fn rust_dbg_lock_create() -> *libc::c_void;
+ unsafe fn rust_dbg_lock_destroy(lock: *libc::c_void);
+ unsafe fn rust_dbg_lock_lock(lock: *libc::c_void);
+ unsafe fn rust_dbg_lock_unlock(lock: *libc::c_void);
+ unsafe fn rust_dbg_lock_wait(lock: *libc::c_void);
+ unsafe fn rust_dbg_lock_signal(lock: *libc::c_void);
}
#[test]
fn test_spawn_sched_blocking() {
+ unsafe {
- // Testing that a task in one scheduler can block in foreign code
- // without affecting other schedulers
- for iter::repeat(20u) {
+ // Testing that a task in one scheduler can block in foreign code
+ // without affecting other schedulers
+ for iter::repeat(20u) {
- let start_po = oldcomm::Port();
- let start_ch = oldcomm::Chan(&start_po);
- let fin_po = oldcomm::Port();
- let fin_ch = oldcomm::Chan(&fin_po);
+ let start_po = oldcomm::Port();
+ let start_ch = oldcomm::Chan(&start_po);
+ let fin_po = oldcomm::Port();
+ let fin_ch = oldcomm::Chan(&fin_po);
- let lock = testrt::rust_dbg_lock_create();
+ let lock = testrt::rust_dbg_lock_create();
- do spawn_sched(SingleThreaded) {
- testrt::rust_dbg_lock_lock(lock);
+ do spawn_sched(SingleThreaded) {
+ unsafe {
+ testrt::rust_dbg_lock_lock(lock);
- oldcomm::send(start_ch, ());
+ oldcomm::send(start_ch, ());
- // Block the scheduler thread
- testrt::rust_dbg_lock_wait(lock);
- testrt::rust_dbg_lock_unlock(lock);
+ // Block the scheduler thread
+ testrt::rust_dbg_lock_wait(lock);
+ testrt::rust_dbg_lock_unlock(lock);
- oldcomm::send(fin_ch, ());
- };
+ oldcomm::send(fin_ch, ());
+ }
+ };
- // Wait until the other task has its lock
- oldcomm::recv(start_po);
+ // Wait until the other task has its lock
+ oldcomm::recv(start_po);
- fn pingpong(po: oldcomm::Port<int>, ch: oldcomm::Chan<int>) {
- let mut val = 20;
- while val > 0 {
- val = oldcomm::recv(po);
- oldcomm::send(ch, val - 1);
+ fn pingpong(po: oldcomm::Port<int>, ch: oldcomm::Chan<int>) {
+ let mut val = 20;
+ while val > 0 {
+ val = oldcomm::recv(po);
+ oldcomm::send(ch, val - 1);
+ }
}
- }
-
- let setup_po = oldcomm::Port();
- let setup_ch = oldcomm::Chan(&setup_po);
- let parent_po = oldcomm::Port();
- let parent_ch = oldcomm::Chan(&parent_po);
- do spawn {
- let child_po = oldcomm::Port();
- oldcomm::send(setup_ch, oldcomm::Chan(&child_po));
- pingpong(child_po, parent_ch);
- };
- let child_ch = oldcomm::recv(setup_po);
- oldcomm::send(child_ch, 20);
- pingpong(parent_po, child_ch);
- testrt::rust_dbg_lock_lock(lock);
- testrt::rust_dbg_lock_signal(lock);
- testrt::rust_dbg_lock_unlock(lock);
- oldcomm::recv(fin_po);
- testrt::rust_dbg_lock_destroy(lock);
+ let setup_po = oldcomm::Port();
+ let setup_ch = oldcomm::Chan(&setup_po);
+ let parent_po = oldcomm::Port();
+ let parent_ch = oldcomm::Chan(&parent_po);
+ do spawn {
+ let child_po = oldcomm::Port();
+ oldcomm::send(setup_ch, oldcomm::Chan(&child_po));
+ pingpong(child_po, parent_ch);
+ };
+
+ let child_ch = oldcomm::recv(setup_po);
+ oldcomm::send(child_ch, 20);
+ pingpong(parent_po, child_ch);
+ testrt::rust_dbg_lock_lock(lock);
+ testrt::rust_dbg_lock_signal(lock);
+ testrt::rust_dbg_lock_unlock(lock);
+ oldcomm::recv(fin_po);
+ testrt::rust_dbg_lock_destroy(lock);
+ }
}
}
#[doc(hidden)]; // FIXME #3538
+use libc;
+
#[allow(non_camel_case_types)] // runtime type
pub type sched_id = int;
#[allow(non_camel_case_types)] // runtime type
#[doc(hidden)]; // FIXME #3538
#[warn(deprecated_mode)];
+use cast;
+use oldcomm;
+use option;
+use pipes::{Chan, Port};
+use pipes;
+use prelude::*;
+use private;
+use ptr;
+use send_map;
+use task::local_data_priv::{local_get, local_set};
use task::rt::rust_task;
use task::rt::rust_closure;
+use task::rt;
+use task::{Failure, ManualThreads, PlatformThread, SchedOpts, SingleThreaded};
+use task::{Success, TaskOpts, TaskResult, ThreadPerCore, ThreadPerTask};
+use task::{default_task_opts, unkillable};
+use uint;
+use util;
macro_rules! move_it (
{ $x:expr } => ( unsafe { let y = move *ptr::addr_of(&($x)); move y } )
}
// Run the box annihilator.
- // XXX: Crashy.
+ // FIXME #4428: Crashy.
// unsafe { cleanup::annihilate(); }
};
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use io;
use io::Writer;
+use option::{None, Option, Some};
+use str;
pub type Cb = fn(buf: &[const u8]) -> bool;
#[cfg(target_word_size = "32")]
pub mod x32 {
+ use to_bytes::{Cb, IterBytes};
+
pub impl uint: IterBytes {
#[inline(always)]
pure fn iter_bytes(&self, lsb0: bool, f: Cb) {
#[cfg(target_word_size = "64")]
pub mod x64 {
+ use to_bytes::{Cb, IterBytes};
+
pub impl uint: IterBytes {
#[inline(always)]
pure fn iter_bytes(&self, lsb0: bool, f: Cb) {
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
+use kinds::Copy;
+use str;
+use vec;
+
pub trait ToStr { pub pure fn to_str() -> ~str; }
impl int: ToStr {
- pure fn to_str() -> ~str { int::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::int::str(self) }
}
impl i8: ToStr {
- pure fn to_str() -> ~str { i8::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::i8::str(self) }
}
impl i16: ToStr {
- pure fn to_str() -> ~str { i16::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::i16::str(self) }
}
impl i32: ToStr {
- pure fn to_str() -> ~str { i32::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::i32::str(self) }
}
impl i64: ToStr {
- pure fn to_str() -> ~str { i64::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::i64::str(self) }
}
impl uint: ToStr {
- pure fn to_str() -> ~str { uint::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::uint::str(self) }
}
impl u8: ToStr {
- pure fn to_str() -> ~str { u8::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::u8::str(self) }
}
impl u16: ToStr {
- pure fn to_str() -> ~str { u16::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::u16::str(self) }
}
impl u32: ToStr {
- pure fn to_str() -> ~str { u32::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::u32::str(self) }
}
impl u64: ToStr {
- pure fn to_str() -> ~str { u64::str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::u64::str(self) }
}
impl float: ToStr {
- pure fn to_str() -> ~str { float::to_str(self, 4u) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::float::to_str(self, 4u) }
}
impl f32: ToStr {
- pure fn to_str() -> ~str { float::to_str(self as float, 4u) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::float::to_str(self as float, 4u) }
}
impl f64: ToStr {
- pure fn to_str() -> ~str { float::to_str(self as float, 4u) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::float::to_str(self as float, 4u) }
}
impl bool: ToStr {
- pure fn to_str() -> ~str { bool::to_str(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::bool::to_str(self) }
}
impl (): ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str { ~"()" }
}
impl ~str: ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str { copy self }
}
impl &str: ToStr {
- pure fn to_str() -> ~str { str::from_slice(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::str::from_slice(self) }
}
impl @str: ToStr {
- pure fn to_str() -> ~str { str::from_slice(self) }
+ #[inline(always)]
+ pure fn to_str() -> ~str { ::str::from_slice(self) }
}
impl<A: ToStr Copy, B: ToStr Copy> (A, B): ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str {
let (a, b) = self;
~"(" + a.to_str() + ~", " + b.to_str() + ~")"
}
}
impl<A: ToStr Copy, B: ToStr Copy, C: ToStr Copy> (A, B, C): ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str {
let (a, b, c) = self;
~"(" + a.to_str() + ~", " + b.to_str() + ~", " + c.to_str() + ~")"
}
impl<A: ToStr> ~[A]: ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str unsafe {
// Bleh -- not really unsafe
// push_str and push_char
}
impl<A: ToStr> @A: ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str { ~"@" + (*self).to_str() }
}
impl<A: ToStr> ~A: ToStr {
+ #[inline(always)]
pure fn to_str() -> ~str { ~"~" + (*self).to_str() }
}
//! Operations on tuples
use cmp::{Eq, Ord};
+use kinds::Copy;
+use vec;
pub trait CopyableTuple<T, U> {
pure fn first() -> T;
impl<T: Copy, U: Copy> (T, U): CopyableTuple<T, U> {
/// Return the first element of self
+ #[inline(always)]
pure fn first() -> T {
let (t, _) = self;
return t;
}
/// Return the second element of self
+ #[inline(always)]
pure fn second() -> U {
let (_, u) = self;
return u;
}
/// Return the results of swapping the two elements of self
+ #[inline(always)]
pure fn swap() -> (U, T) {
let (t, u) = self;
return (u, t);
}
impl<T, U> (T, U): ImmutableTuple<T, U> {
+ #[inline(always)]
pure fn first_ref(&self) -> &self/T {
match *self {
(ref t, _) => t,
}
}
+ #[inline(always)]
pure fn second_ref(&self) -> &self/U {
match *self {
(_, ref u) => u,
}
impl<A: Copy, B: Copy> (&[A], &[B]): ExtendedTupleOps<A,B> {
+ #[inline(always)]
fn zip(&self) -> ~[(A, B)] {
match *self {
(ref a, ref b) => {
}
}
+ #[inline(always)]
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
impl<A: Copy, B: Copy> (~[A], ~[B]): ExtendedTupleOps<A,B> {
+ #[inline(always)]
fn zip(&self) -> ~[(A, B)] {
match *self {
(ref a, ref b) => {
}
}
+ #[inline(always)]
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
#[cfg(notest)]
impl<A: Eq, B: Eq> (A, B) : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &(A, B)) -> bool {
match (*self) {
(ref self_a, ref self_b) => match other {
}
}
}
+ #[inline(always)]
pure fn ne(&self, other: &(A, B)) -> bool { !(*self).eq(other) }
}
#[cfg(notest)]
impl<A: Ord, B: Ord> (A, B) : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &(A, B)) -> bool {
match (*self) {
(ref self_a, ref self_b) => {
}
}
}
+ #[inline(always)]
pure fn le(&self, other: &(A, B)) -> bool { !(*other).lt(&(*self)) }
+ #[inline(always)]
pure fn ge(&self, other: &(A, B)) -> bool { !(*self).lt(other) }
+ #[inline(always)]
pure fn gt(&self, other: &(A, B)) -> bool { (*other).lt(&(*self)) }
}
#[cfg(notest)]
impl<A: Eq, B: Eq, C: Eq> (A, B, C) : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &(A, B, C)) -> bool {
match (*self) {
(ref self_a, ref self_b, ref self_c) => match other {
}
}
}
+ #[inline(always)]
pure fn ne(&self, other: &(A, B, C)) -> bool { !(*self).eq(other) }
}
#[cfg(notest)]
impl<A: Ord, B: Ord, C: Ord> (A, B, C) : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &(A, B, C)) -> bool {
match (*self) {
(ref self_a, ref self_b, ref self_c) => {
}
}
}
+ #[inline(always)]
pure fn le(&self, other: &(A, B, C)) -> bool { !(*other).lt(&(*self)) }
+ #[inline(always)]
pure fn ge(&self, other: &(A, B, C)) -> bool { !(*self).lt(other) }
+ #[inline(always)]
pure fn gt(&self, other: &(A, B, C)) -> bool { (*other).lt(&(*self)) }
}
use T = self::inst::T;
+use char;
use cmp::{Eq, Ord};
use from_str::FromStr;
+use iter;
+use num;
+use option::{None, Option, Some};
+use str;
+use uint;
+use vec;
pub const bits : uint = inst::bits;
pub const bytes : uint = (inst::bits / 8);
pub const min_value: T = 0 as T;
pub const max_value: T = 0 as T - 1 as T;
+#[inline(always)]
pub pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
+#[inline(always)]
pub pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }
+#[inline(always)]
pub pure fn add(x: T, y: T) -> T { x + y }
+#[inline(always)]
pub pure fn sub(x: T, y: T) -> T { x - y }
+#[inline(always)]
pub pure fn mul(x: T, y: T) -> T { x * y }
+#[inline(always)]
pub pure fn div(x: T, y: T) -> T { x / y }
+#[inline(always)]
pub pure fn rem(x: T, y: T) -> T { x % y }
+#[inline(always)]
pub pure fn lt(x: T, y: T) -> bool { x < y }
+#[inline(always)]
pub pure fn le(x: T, y: T) -> bool { x <= y }
+#[inline(always)]
pub pure fn eq(x: T, y: T) -> bool { x == y }
+#[inline(always)]
pub pure fn ne(x: T, y: T) -> bool { x != y }
+#[inline(always)]
pub pure fn ge(x: T, y: T) -> bool { x >= y }
+#[inline(always)]
pub pure fn gt(x: T, y: T) -> bool { x > y }
+#[inline(always)]
pub pure fn is_positive(x: T) -> bool { x > 0 as T }
+#[inline(always)]
pub pure fn is_negative(x: T) -> bool { x < 0 as T }
+#[inline(always)]
pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
+#[inline(always)]
pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
#[inline(always)]
}
/// Computes the bitwise complement
+#[inline(always)]
pub pure fn compl(i: T) -> T {
max_value ^ i
}
#[cfg(notest)]
impl T : Ord {
+ #[inline(always)]
pure fn lt(&self, other: &T) -> bool { (*self) < (*other) }
+ #[inline(always)]
pure fn le(&self, other: &T) -> bool { (*self) <= (*other) }
+ #[inline(always)]
pure fn ge(&self, other: &T) -> bool { (*self) >= (*other) }
+ #[inline(always)]
pure fn gt(&self, other: &T) -> bool { (*self) > (*other) }
}
#[cfg(notest)]
impl T : Eq {
+ #[inline(always)]
pure fn eq(&self, other: &T) -> bool { return (*self) == (*other); }
+ #[inline(always)]
pure fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
}
impl T: num::Num {
+ #[inline(always)]
pure fn add(&self, other: &T) -> T { return *self + *other; }
+ #[inline(always)]
pure fn sub(&self, other: &T) -> T { return *self - *other; }
+ #[inline(always)]
pure fn mul(&self, other: &T) -> T { return *self * *other; }
+ #[inline(always)]
pure fn div(&self, other: &T) -> T { return *self / *other; }
+ #[inline(always)]
pure fn modulo(&self, other: &T) -> T { return *self % *other; }
+ #[inline(always)]
pure fn neg(&self) -> T { return -*self; }
+ #[inline(always)]
pure fn to_int(&self) -> int { return *self as int; }
+ #[inline(always)]
static pure fn from_int(n: int) -> T { return n as T; }
}
impl T: num::Zero {
+ #[inline(always)]
static pure fn zero() -> T { 0 }
}
impl T: num::One {
+ #[inline(always)]
static pure fn one() -> T { 1 }
}
}
/// Parse a string to an int
+#[inline(always)]
pub pure fn from_str(s: &str) -> Option<T>
{
parse_bytes(str::to_bytes(s), 10u)
}
impl T : FromStr {
+ #[inline(always)]
static pure fn from_str(s: &str) -> Option<T> { from_str(s) }
}
*
* Fails if `radix` < 2 or `radix` > 16
*/
+#[inline(always)]
pub pure fn to_str(num: T, radix: uint) -> ~str {
do to_str_bytes(false, num, radix) |slice| {
do vec::as_imm_buf(slice) |p, len| {
}
/// Convert to a string
+#[inline(always)]
pub pure fn str(i: T) -> ~str { return to_str(i, 10u); }
#[test]
};
mod inst {
+ use sys;
+ use uint;
+
pub type T = uint;
#[cfg(target_arch = "x86")]
#[forbid(deprecated_pattern)];
use cmp::Eq;
+use prelude::*;
/// The identity function.
#[inline(always)]
mod tests {
#[legacy_exports];
+
+ use option::{None, Some};
+ use util::{NonCopyable, id, replace, swap};
+
#[test]
fn identity_crisis() {
// Writing a test for the identity function. How did it come to this?
#[forbid(deprecated_pattern)];
#[warn(non_camel_case_types)];
+use cast;
use cmp::{Eq, Ord};
-use option::{Some, None};
-use ptr::addr_of;
+use iter::BaseIter;
+use iter;
+use kinds::Copy;
+use libc;
use libc::size_t;
+use option::{None, Option, Some};
+use ptr;
+use ptr::addr_of;
+use sys;
+use uint;
+use vec;
#[abi = "cdecl"]
-extern mod rustrt {
- fn vec_reserve_shared(++t: *sys::TypeDesc,
- ++v: **raw::VecRepr,
- ++n: libc::size_t);
+pub extern mod rustrt {
+ unsafe fn vec_reserve_shared(++t: *sys::TypeDesc,
+ ++v: **raw::VecRepr,
+ ++n: libc::size_t);
}
#[abi = "rust-intrinsic"]
-extern mod rusti {
+pub extern mod rusti {
fn move_val_init<T>(dst: &mut T, -src: T);
fn init<T>() -> T;
}
pub pure fn capacity<T>(v: &const ~[T]) -> uint {
unsafe {
let repr: **raw::VecRepr = ::cast::transmute(v);
- (**repr).unboxed.alloc / sys::size_of::<T>()
+ (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
}
}
#[inline(always)]
pub pure fn build_sized_opt<A>(size: Option<uint>,
builder: fn(push: pure fn(v: A))) -> ~[A] {
- build_sized(size.get_default(4), builder)
+ build_sized(size.get_or_default(4), builder)
}
/// Produces a mut vector from an immutable vector.
unsafe {
::cast::reinterpret_cast(
&(ptr::offset(p, start),
- (end - start) * sys::size_of::<T>()))
+ (end - start) * sys::nonzero_size_of::<T>()))
}
}
}
unsafe {
::cast::reinterpret_cast(
&(ptr::mut_offset(p, start),
- (end - start) * sys::size_of::<T>()))
+ (end - start) * sys::nonzero_size_of::<T>()))
}
}
}
unsafe {
::cast::reinterpret_cast(
&(ptr::const_offset(p, start),
- (end - start) * sys::size_of::<T>()))
+ (end - start) * sys::nonzero_size_of::<T>()))
}
}
}
result
}
+/**
+ * Partitions a vector into two new vectors: those that satisfies the
+ * predicate, and those that do not.
+ */
+pub fn partition<T>(v: ~[T], f: fn(&T) -> bool) -> (~[T], ~[T]) {
+ let mut lefts = ~[];
+ let mut rights = ~[];
+
+ // FIXME (#4355 maybe): using v.consume here crashes
+ // do v.consume |_, elt| {
+ do consume(v) |_, elt| {
+ if f(&elt) {
+ lefts.push(elt);
+ } else {
+ rights.push(elt);
+ }
+ }
+
+ (lefts, rights)
+}
+
+/**
+ * Partitions a vector into two new vectors: those that satisfies the
+ * predicate, and those that do not.
+ */
+pub pure fn partitioned<T: Copy>(v: &[T], f: fn(&T) -> bool) -> (~[T], ~[T]) {
+ let mut lefts = ~[];
+ let mut rights = ~[];
+
+ for each(v) |elt| {
+ unsafe {
+ if f(elt) {
+ lefts.push(*elt);
+ } else {
+ rights.push(*elt);
+ }
+ }
+ }
+
+ (lefts, rights)
+}
+
// Mutators
/// Removes the first element from a vector and return it
// We still should have room to work where what last element was
assert capacity(v) >= ln;
// Pretend like we have the original length so we can use
- // the vector memcpy to overwrite the hole we just made
+ // the vector copy_memory to overwrite the hole we just made
raw::set_len(v, ln);
// Memcopy the head element (the one we want) to the location we just
// positions
let first_slice = view(*v, 0, 1);
let last_slice = mut_view(*v, next_ln, ln);
- raw::memcpy(last_slice, first_slice, 1);
+ raw::copy_memory(last_slice, first_slice, 1);
// Memcopy everything to the left one element
let init_slice = mut_view(*v, 0, next_ln);
let tail_slice = view(*v, 1, ln);
- raw::memcpy(init_slice, tail_slice, next_ln);
+ raw::copy_memory(init_slice, tail_slice, next_ln);
// Set the new length. Now the vector is back to normal
raw::set_len(v, next_ln);
}
let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
unsafe {
- // XXX: Should be rusti::uninit() - we don't need this zeroed
+ // FIXME #4204: Should be rusti::uninit() - we don't need this zeroed
let mut val = rusti::init();
val <-> *valptr;
raw::set_len(v, ln - 1u);
unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
let repr: **raw::VecRepr = ::cast::transmute(v);
let fill = (**repr).unboxed.fill;
- (**repr).unboxed.fill += sys::size_of::<T>();
+ (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
let p = addr_of(&((**repr).unboxed.data));
let p = ptr::offset(p, fill) as *mut T;
rusti::move_val_init(&mut(*p), move initval);
unsafe {
do as_mut_buf(rhs) |p, len| {
for uint::range(0, len) |i| {
- // XXX Should be rusti::uninit() - don't need to zero
+ // FIXME #4204 Should be rusti::uninit() - don't need to zero
let mut x = rusti::init();
x <-> *ptr::mut_offset(p, i);
push(v, x);
unsafe {
// This loop is optimized out for non-drop types.
for uint::range(newlen, oldlen) |i| {
- // XXX Should be rusti::uninit() - don't need to zero
+ // FIXME #4204 Should be rusti::uninit() - don't need to zero
let mut dropped = rusti::init();
dropped <-> *ptr::mut_offset(p, i);
}
// last_written < next_to_read < ln
if *ptr::mut_offset(p, next_to_read) ==
*ptr::mut_offset(p, last_written) {
- // XXX Should be rusti::uninit() - don't need to zero
+ // FIXME #4204 Should be rusti::uninit() - don't need to zero
let mut dropped = rusti::init();
dropped <-> *ptr::mut_offset(p, next_to_read);
} else {
}
#[inline(always)]
-pure fn append_mut<T: Copy>(lhs: ~[mut T], rhs: &[const T]) -> ~[mut T] {
+pub pure fn append_mut<T: Copy>(lhs: ~[mut T], rhs: &[const T]) -> ~[mut T] {
to_mut(append(from_mut(lhs), rhs))
}
* Apply function `f` to each element of `v` and return a vector containing
* only those elements for which `f` returned true.
*/
-pub pure fn filter<T: Copy>(v: &[T], f: fn(t: &T) -> bool) -> ~[T] {
+pub fn filter<T>(v: ~[T], f: fn(t: &T) -> bool) -> ~[T] {
+ let mut result = ~[];
+ // FIXME (#4355 maybe): using v.consume here crashes
+ // do v.consume |_, elem| {
+ do consume(v) |_, elem| {
+ if f(&elem) { result.push(elem); }
+ }
+ result
+}
+
+/**
+ * Construct a new vector from the elements of a vector for which some
+ * predicate holds.
+ *
+ * Apply function `f` to each element of `v` and return a vector containing
+ * only those elements for which `f` returned true.
+ */
+pub pure fn filtered<T: Copy>(v: &[T], f: fn(t: &T) -> bool) -> ~[T] {
let mut result = ~[];
for each(v) |elem| {
if f(elem) { unsafe { result.push(*elem); } }
}
/**
- * Iterates over a vector, with option to break
+ * Iterates over a vector, yielding each element to a closure.
*
- * Return true to continue, false to break.
+ * # Arguments
+ *
+ * * `v` - A vector, to be iterated over
+ * * `f` - A closure to do the iterating. Within this closure, return true to
+ * * continue iterating, false to break.
+ *
+ * # Examples
+ * ~~~
+ * [1,2,3].each(|&i| {
+ * io::println(int::str(i));
+ * true
+ * });
+ * ~~~
+ *
+ * ~~~
+ * [1,2,3,4,5].each(|&i| {
+ * if i < 4 {
+ * io::println(int::str(i));
+ * true
+ * }
+ * else {
+ * false
+ * }
+ * });
+ * ~~~
+ *
+ * You probably will want to use each with a `for`/`do` expression, depending
+ * on your iteration needs:
+ *
+ * ~~~
+ * for [1,2,3].each |&i| {
+ * io::println(int::str(i));
+ * }
+ * ~~~
*/
#[inline(always)]
pub pure fn each<T>(v: &r/[T], f: fn(&r/T) -> bool) {
let v : *(*T,uint) =
::cast::reinterpret_cast(&addr_of(&s));
let (buf,len) = *v;
- f(buf, len / sys::size_of::<T>())
+ f(buf, len / sys::nonzero_size_of::<T>())
}
}
let v : *(*const T,uint) =
::cast::reinterpret_cast(&addr_of(&s));
let (buf,len) = *v;
- f(buf, len / sys::size_of::<T>())
+ f(buf, len / sys::nonzero_size_of::<T>())
}
}
let v : *(*mut T,uint) =
::cast::reinterpret_cast(&addr_of(&s));
let (buf,len) = *v;
- f(buf, len / sys::size_of::<T>())
+ f(buf, len / sys::nonzero_size_of::<T>())
}
}
#[cfg(notest)]
pub mod traits {
+ use kinds::Copy;
+ use ops::Add;
+ use vec::{append, append_mut};
+
impl<T: Copy> ~[T] : Add<&[const T],~[T]> {
#[inline(always)]
pure fn add(&self, rhs: & &self/[const T]) -> ~[T] {
}
pub trait ConstVector {
- pure fn is_empty() -> bool;
- pure fn is_not_empty() -> bool;
- pure fn len() -> uint;
+ pure fn is_empty(&self) -> bool;
+ pure fn is_not_empty(&self) -> bool;
+ pure fn len(&self) -> uint;
}
/// Extension methods for vectors
impl<T> &[const T]: ConstVector {
/// Returns true if a vector contains no elements
#[inline]
- pure fn is_empty() -> bool { is_empty(self) }
+ pure fn is_empty(&self) -> bool { is_empty(*self) }
/// Returns true if a vector contains some elements
#[inline]
- pure fn is_not_empty() -> bool { is_not_empty(self) }
+ pure fn is_not_empty(&self) -> bool { is_not_empty(*self) }
/// Returns the length of a vector
#[inline]
- pure fn len() -> uint { len(self) }
+ pure fn len(&self) -> uint { len(*self) }
}
pub trait CopyableVector<T> {
- pure fn head() -> T;
- pure fn init() -> ~[T];
- pure fn last() -> T;
- pure fn slice(start: uint, end: uint) -> ~[T];
- pure fn tail() -> ~[T];
+ pure fn head(&self) -> T;
+ pure fn init(&self) -> ~[T];
+ pure fn last(&self) -> T;
+ pure fn slice(&self, start: uint, end: uint) -> ~[T];
+ pure fn tail(&self) -> ~[T];
}
/// Extension methods for vectors
impl<T: Copy> &[const T]: CopyableVector<T> {
/// Returns the first element of a vector
#[inline]
- pure fn head() -> T { head(self) }
+ pure fn head(&self) -> T { head(*self) }
+
/// Returns all but the last elemnt of a vector
#[inline]
- pure fn init() -> ~[T] { init(self) }
+ pure fn init(&self) -> ~[T] { init(*self) }
+
/// Returns the last element of a `v`, failing if the vector is empty.
#[inline]
- pure fn last() -> T { last(self) }
+ pure fn last(&self) -> T { last(*self) }
+
/// Returns a copy of the elements from [`start`..`end`) from `v`.
#[inline]
- pure fn slice(start: uint, end: uint) -> ~[T] { slice(self, start, end) }
+ pure fn slice(&self, start: uint, end: uint) -> ~[T] {
+ slice(*self, start, end)
+ }
+
/// Returns all but the first element of a vector
#[inline]
- pure fn tail() -> ~[T] { tail(self) }
+ pure fn tail(&self) -> ~[T] { tail(*self) }
}
pub trait ImmutableVector<T> {
- pure fn view(start: uint, end: uint) -> &self/[T];
- pure fn foldr<U: Copy>(z: U, p: fn(t: &T, u: U) -> U) -> U;
- pure fn map<U>(f: fn(t: &T) -> U) -> ~[U];
- pure fn mapi<U>(f: fn(uint, t: &T) -> U) -> ~[U];
- fn map_r<U>(f: fn(x: &T) -> U) -> ~[U];
- pure fn alli(f: fn(uint, t: &T) -> bool) -> bool;
- pure fn flat_map<U>(f: fn(t: &T) -> ~[U]) -> ~[U];
- pure fn filter_map<U: Copy>(f: fn(t: &T) -> Option<U>) -> ~[U];
-}
-
-pub trait ImmutableEqVector<T: Eq> {
- pure fn position(f: fn(t: &T) -> bool) -> Option<uint>;
- pure fn position_elem(t: &T) -> Option<uint>;
- pure fn rposition(f: fn(t: &T) -> bool) -> Option<uint>;
- pure fn rposition_elem(t: &T) -> Option<uint>;
+ pure fn view(&self, start: uint, end: uint) -> &self/[T];
+ pure fn foldr<U: Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U;
+ pure fn map<U>(&self, f: fn(t: &T) -> U) -> ~[U];
+ pure fn mapi<U>(&self, f: fn(uint, t: &T) -> U) -> ~[U];
+ fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U];
+ pure fn alli(&self, f: fn(uint, t: &T) -> bool) -> bool;
+ pure fn flat_map<U>(&self, f: fn(t: &T) -> ~[U]) -> ~[U];
+ pure fn filter_map<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U];
}
/// Extension methods for vectors
impl<T> &[T]: ImmutableVector<T> {
/// Return a slice that points into another slice.
- pure fn view(start: uint, end: uint) -> &self/[T] {
- view(self, start, end)
+ #[inline]
+ pure fn view(&self, start: uint, end: uint) -> &self/[T] {
+ view(*self, start, end)
}
+
/// Reduce a vector from right to left
#[inline]
- pure fn foldr<U: Copy>(z: U, p: fn(t: &T, u: U) -> U) -> U {
- foldr(self, z, p)
+ pure fn foldr<U: Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U {
+ foldr(*self, z, p)
}
+
/// Apply a function to each element of a vector and return the results
#[inline]
- pure fn map<U>(f: fn(t: &T) -> U) -> ~[U] { map(self, f) }
+ pure fn map<U>(&self, f: fn(t: &T) -> U) -> ~[U] { map(*self, f) }
+
/**
* Apply a function to the index and value of each element in the vector
* and return the results
*/
- pure fn mapi<U>(f: fn(uint, t: &T) -> U) -> ~[U] {
- mapi(self, f)
+ pure fn mapi<U>(&self, f: fn(uint, t: &T) -> U) -> ~[U] {
+ mapi(*self, f)
}
#[inline]
- fn map_r<U>(f: fn(x: &T) -> U) -> ~[U] {
+ fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U] {
let mut r = ~[];
let mut i = 0;
while i < self.len() {
*
* If the vector is empty, true is returned.
*/
- pure fn alli(f: fn(uint, t: &T) -> bool) -> bool {
- alli(self, f)
+ pure fn alli(&self, f: fn(uint, t: &T) -> bool) -> bool {
+ alli(*self, f)
}
/**
* Apply a function to each element of a vector and return a concatenation
* of each result vector
*/
#[inline]
- pure fn flat_map<U>(f: fn(t: &T) -> ~[U]) -> ~[U] {
- flat_map(self, f)
+ pure fn flat_map<U>(&self, f: fn(t: &T) -> ~[U]) -> ~[U] {
+ flat_map(*self, f)
}
/**
* Apply a function to each element of a vector and return the results
* the resulting vector.
*/
#[inline]
- pure fn filter_map<U: Copy>(f: fn(t: &T) -> Option<U>) -> ~[U] {
- filter_map(self, f)
+ pure fn filter_map<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U] {
+ filter_map(*self, f)
}
}
+pub trait ImmutableEqVector<T: Eq> {
+ pure fn position(&self, f: fn(t: &T) -> bool) -> Option<uint>;
+ pure fn position_elem(&self, t: &T) -> Option<uint>;
+ pure fn rposition(&self, f: fn(t: &T) -> bool) -> Option<uint>;
+ pure fn rposition_elem(&self, t: &T) -> Option<uint>;
+}
+
impl<T: Eq> &[T]: ImmutableEqVector<T> {
/**
* Find the first index matching some predicate
* elements then none is returned.
*/
#[inline]
- pure fn position(f: fn(t: &T) -> bool) -> Option<uint> {
- position(self, f)
+ pure fn position(&self, f: fn(t: &T) -> bool) -> Option<uint> {
+ position(*self, f)
}
/// Find the first index containing a matching value
#[inline]
- pure fn position_elem(x: &T) -> Option<uint> {
- position_elem(self, x)
+ pure fn position_elem(&self, x: &T) -> Option<uint> {
+ position_elem(*self, x)
}
/**
* returned. If `f` matches no elements then none is returned.
*/
#[inline]
- pure fn rposition(f: fn(t: &T) -> bool) -> Option<uint> {
- rposition(self, f)
+ pure fn rposition(&self, f: fn(t: &T) -> bool) -> Option<uint> {
+ rposition(*self, f)
}
/// Find the last index containing a matching value
#[inline]
- pure fn rposition_elem(t: &T) -> Option<uint> {
- rposition_elem(self, t)
+ pure fn rposition_elem(&self, t: &T) -> Option<uint> {
+ rposition_elem(*self, t)
}
}
pub trait ImmutableCopyableVector<T> {
- pure fn filter(f: fn(t: &T) -> bool) -> ~[T];
-
- pure fn rfind(f: fn(t: &T) -> bool) -> Option<T>;
+ pure fn filtered(&self, f: fn(&T) -> bool) -> ~[T];
+ pure fn rfind(&self, f: fn(t: &T) -> bool) -> Option<T>;
+ pure fn partitioned(&self, f: fn(&T) -> bool) -> (~[T], ~[T]);
}
/// Extension methods for vectors
* containing only those elements for which `f` returned true.
*/
#[inline]
- pure fn filter(f: fn(t: &T) -> bool) -> ~[T] {
- filter(self, f)
+ pure fn filtered(&self, f: fn(t: &T) -> bool) -> ~[T] {
+ filtered(*self, f)
}
/**
* returned. If `f` matches no elements then none is returned.
*/
#[inline]
- pure fn rfind(f: fn(t: &T) -> bool) -> Option<T> { rfind(self, f) }
+ pure fn rfind(&self, f: fn(t: &T) -> bool) -> Option<T> {
+ rfind(*self, f)
+ }
+
+ /**
+ * Partitions the vector into those that satisfies the predicate, and
+ * those that do not.
+ */
+ #[inline]
+ pure fn partitioned(&self, f: fn(&T) -> bool) -> (~[T], ~[T]) {
+ partitioned(*self, f)
+ }
}
-pub trait MutableVector<T> {
+pub trait OwnedVector<T> {
fn push(&mut self, t: T);
fn push_all_move(&mut self, rhs: ~[T]);
fn pop(&mut self) -> T;
fn swap_remove(&mut self, index: uint) -> T;
fn truncate(&mut self, newlen: uint);
fn retain(&mut self, f: pure fn(t: &T) -> bool);
+ fn consume(self, f: fn(uint, v: T));
+ fn filter(self, f: fn(t: &T) -> bool) -> ~[T];
+ fn partition(self, f: pure fn(&T) -> bool) -> (~[T], ~[T]);
}
-pub trait MutableCopyableVector<T: Copy> {
- fn push_all(&mut self, rhs: &[const T]);
- fn grow(&mut self, n: uint, initval: &T);
- fn grow_fn(&mut self, n: uint, op: iter::InitOp<T>);
- fn grow_set(&mut self, index: uint, initval: &T, val: T);
-}
-
-trait MutableEqVector<T: Eq> {
- fn dedup(&mut self);
-}
-
-impl<T> ~[T]: MutableVector<T> {
+impl<T> ~[T]: OwnedVector<T> {
+ #[inline]
fn push(&mut self, t: T) {
push(self, t);
}
+ #[inline]
fn push_all_move(&mut self, rhs: ~[T]) {
push_all_move(self, rhs);
}
+ #[inline]
fn pop(&mut self) -> T {
pop(self)
}
+ #[inline]
fn shift(&mut self) -> T {
shift(self)
}
+ #[inline]
fn unshift(&mut self, x: T) {
unshift(self, x)
}
+ #[inline]
fn insert(&mut self, i: uint, x:T) {
insert(self, i, x)
}
+ #[inline]
fn remove(&mut self, i: uint) -> T {
remove(self, i)
}
+ #[inline]
fn swap_remove(&mut self, index: uint) -> T {
swap_remove(self, index)
}
+ #[inline]
fn truncate(&mut self, newlen: uint) {
truncate(self, newlen);
}
+ #[inline]
fn retain(&mut self, f: pure fn(t: &T) -> bool) {
retain(self, f);
}
+
+ #[inline]
+ fn consume(self, f: fn(uint, v: T)) {
+ consume(self, f)
+ }
+
+ #[inline]
+ fn filter(self, f: fn(&T) -> bool) -> ~[T] {
+ filter(self, f)
+ }
+
+ /**
+ * Partitions the vector into those that satisfies the predicate, and
+ * those that do not.
+ */
+ #[inline]
+ fn partition(self, f: fn(&T) -> bool) -> (~[T], ~[T]) {
+ partition(self, f)
+ }
}
-impl<T: Copy> ~[T]: MutableCopyableVector<T> {
+pub trait OwnedCopyableVector<T: Copy> {
+ fn push_all(&mut self, rhs: &[const T]);
+ fn grow(&mut self, n: uint, initval: &T);
+ fn grow_fn(&mut self, n: uint, op: iter::InitOp<T>);
+ fn grow_set(&mut self, index: uint, initval: &T, val: T);
+}
+
+impl<T: Copy> ~[T]: OwnedCopyableVector<T> {
+ #[inline]
fn push_all(&mut self, rhs: &[const T]) {
push_all(self, rhs);
}
+ #[inline]
fn grow(&mut self, n: uint, initval: &T) {
grow(self, n, initval);
}
+ #[inline]
fn grow_fn(&mut self, n: uint, op: iter::InitOp<T>) {
grow_fn(self, n, op);
}
+ #[inline]
fn grow_set(&mut self, index: uint, initval: &T, val: T) {
grow_set(self, index, initval, val);
}
}
-impl<T: Eq> ~[T]: MutableEqVector<T> {
+trait OwnedEqVector<T: Eq> {
+ fn dedup(&mut self);
+}
+
+impl<T: Eq> ~[T]: OwnedEqVector<T> {
+ #[inline]
fn dedup(&mut self) {
dedup(self)
}
}
-
/**
* Constructs a vector from an unsafe pointer to a buffer
*
/// Unsafe operations
pub mod raw {
+ use kinds::Copy;
+ use managed;
+ use option::{None, Some};
+ use option;
+ use ptr::addr_of;
+ use ptr;
+ use sys;
+ use vec::{UnboxedVecRepr, as_const_buf, as_mut_buf, len, with_capacity};
+ use vec::rusti;
/// The internal representation of a (boxed) vector
pub struct VecRepr {
#[inline(always)]
pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
let repr: **VecRepr = ::cast::transmute(v);
- (**repr).unboxed.fill = new_len * sys::size_of::<T>();
+ (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
}
/**
pub unsafe fn buf_as_slice<T,U>(p: *T,
len: uint,
f: fn(v: &[T]) -> U) -> U {
- let pair = (p, len * sys::size_of::<T>());
+ let pair = (p, len * sys::nonzero_size_of::<T>());
let v : *(&blk/[T]) =
::cast::reinterpret_cast(&addr_of(&pair));
f(*v)
pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] {
let mut dst = with_capacity(elts);
set_len(&mut dst, elts);
- as_mut_buf(dst, |p_dst, _len_dst| ptr::memcpy(p_dst, ptr, elts));
+ as_mut_buf(dst, |p_dst, _len_dst| ptr::copy_memory(p_dst, ptr, elts));
dst
}
* Copies `count` bytes from `src` to `dst`. The source and destination
* may overlap.
*/
- pub unsafe fn memcpy<T>(dst: &[mut T], src: &[const T], count: uint) {
+ pub unsafe fn copy_memory<T>(dst: &[mut T], src: &[const T],
+ count: uint) {
+ assert dst.len() >= count;
+ assert src.len() >= count;
+
do as_mut_buf(dst) |p_dst, _len_dst| {
do as_const_buf(src) |p_src, _len_src| {
- ptr::memcpy(p_dst, p_src, count)
+ ptr::copy_memory(p_dst, p_src, count)
}
}
}
* Copies `count` bytes from `src` to `dst`. The source and destination
* may overlap.
*/
- pub unsafe fn memmove<T>(dst: &[mut T], src: &[const T], count: uint) {
+ pub unsafe fn copy_overlapping_memory<T>(dst: &[mut T], src: &[const T],
+ count: uint) {
+ assert dst.len() >= count;
+ assert src.len() >= count;
+
do as_mut_buf(dst) |p_dst, _len_dst| {
do as_const_buf(src) |p_src, _len_src| {
- ptr::memmove(p_dst, p_src, count)
+ ptr::copy_overlapping_memory(p_dst, p_src, count)
}
}
}
/// Operations on `[u8]`
pub mod bytes {
+ use libc;
+ use uint;
+ use vec::len;
+ use vec::raw;
+ use vec;
/// Bytewise string comparison
pub pure fn cmp(a: &~[u8], b: &~[u8]) -> int {
* Copies `count` bytes from `src` to `dst`. The source and destination
* may not overlap.
*/
- pub fn memcpy(dst: &[mut u8], src: &[const u8], count: uint) {
- assert dst.len() >= count;
- assert src.len() >= count;
-
- unsafe { vec::raw::memcpy(dst, src, count) }
+ pub fn copy_memory(dst: &[mut u8], src: &[const u8], count: uint) {
+ // Bound checks are done at vec::raw::copy_memory.
+ unsafe { vec::raw::copy_memory(dst, src, count) }
}
/**
* Copies `count` bytes from `src` to `dst`. The source and destination
* may overlap.
*/
- pub fn memmove(dst: &[mut u8], src: &[const u8], count: uint) {
- assert dst.len() >= count;
- assert src.len() >= count;
-
- unsafe { vec::raw::memmove(dst, src, count) }
+ pub fn copy_overlapping_memory(dst: &[mut u8], src: &[const u8],
+ count: uint) {
+ // Bound checks are done at vec::raw::copy_overlapping_memory.
+ unsafe { vec::raw::copy_overlapping_memory(dst, src, count) }
}
}
#[cfg(test)]
mod tests {
+ use option::{None, Option, Some};
+ use option;
+ use vec::*;
fn square(n: uint) -> uint { return n * n; }
assert (!is_not_empty::<int>(~[]));
}
+ #[test]
+ fn test_len_divzero() {
+ type Z = [i8 * 0];
+ let v0 : &[Z] = &[];
+ let v1 : &[Z] = &[[]];
+ let v2 : &[Z] = &[[], []];
+ assert(sys::size_of::<Z>() == 0);
+ assert(len(v0) == 0);
+ assert(len(v1) == 1);
+ assert(len(v2) == 2);
+ }
+
#[test]
fn test_head() {
let a = ~[11, 12];
fn halve(i: &int) -> Option<int> {
if *i % 2 == 0 {
return option::Some::<int>(*i / 2);
- } else { return option::None::<int>; }
+ } else {
+ return option::None::<int>;
+ }
}
fn halve_for_sure(i: &int) -> int { return *i / 2; }
let all_even: ~[int] = ~[0, 2, 8, 6];
~[~[1, 2, 3, 4], ~[5]];
}
+ #[test]
+ fn test_partition() {
+ // FIXME (#4355 maybe): using v.partition here crashes
+ assert partition(~[], |x: &int| *x < 3) == (~[], ~[]);
+ assert partition(~[1, 2, 3], |x: &int| *x < 4) == (~[1, 2, 3], ~[]);
+ assert partition(~[1, 2, 3], |x: &int| *x < 2) == (~[1], ~[2, 3]);
+ assert partition(~[1, 2, 3], |x: &int| *x < 0) == (~[], ~[1, 2, 3]);
+ }
+
+ #[test]
+ fn test_partitioned() {
+ assert (~[]).partitioned(|x: &int| *x < 3) == (~[], ~[]);
+ assert (~[1, 2, 3]).partitioned(|x: &int| *x < 4) ==
+ (~[1, 2, 3], ~[]);
+ assert (~[1, 2, 3]).partitioned(|x: &int| *x < 2) ==
+ (~[1], ~[2, 3]);
+ assert (~[1, 2, 3]).partitioned(|x: &int| *x < 0) ==
+ (~[], ~[1, 2, 3]);
+ }
+
#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_filter_fail() {
let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
let mut i = 0;
- do filter(v) |_elt| {
+ do v.filtered |_elt| {
if i == 2 {
fail
}
}
#[test]
- #[ignore(windows)]
+ #[ignore(cfg(windows))]
#[should_fail]
fn test_as_mut_buf_fail() {
let v = [mut (~0, @0), (~0, @0), (~0, @0), (~0, @0)];
fail
}
}
+
+ #[test]
+ #[should_fail]
+ #[ignore(cfg(windows))]
+ fn test_copy_memory_oob() unsafe {
+ let a = [mut 1, 2, 3, 4];
+ let b = [1, 2, 3, 4, 5];
+ raw::copy_memory(a, b, 5);
+ }
+
}
// Local Variables:
}
fn dsl(l: ast::lit_) -> ast::lit {
- { node: l, span: ast_util::dummy_sp() }
+ ast::spanned { node: l, span: ast_util::dummy_sp() }
}
~[dse(ast::expr_break(option::None)),
fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff {
let exprs = @mut ~[];
let tys = @mut ~[];
- let v = visit::mk_simple_visitor(@{
+ let v = visit::mk_simple_visitor(@visit::SimpleVisitor {
visit_expr: |a| stash_expr_if(safe_to_steal_expr, exprs, a, tm),
visit_ty: |a| stash_ty_if(safe_to_steal_ty, tys, a, tm),
.. *visit::default_simple_visitor()
fold::noop_fold_expr(original, fld)
}
}
- let afp = @{
+ let afp = @fold::AstFoldFns {
fold_expr: fold::wrap(|a,b| {
fold_expr_rep(j, i, newexpr.node, a, b, tm)
}),
newty_
} else { fold::noop_fold_ty(original, fld) }
}
- let afp = @{
+ let afp = @fold::AstFoldFns {
fold_ty: fold::wrap(|a,b| fold_ty_rep(j, i, newty.node, a, b, tm) ),
.. *fold::default_ast_fold()
};
fn check_variants_of_ast(crate: ast::crate, codemap: @codemap::CodeMap,
filename: &Path, cx: context) {
let stolen = steal(crate, cx.mode);
- let extra_exprs = vec::filter(common_exprs(),
- |a| safe_to_use_expr(*a, cx.mode) );
+ let extra_exprs = do common_exprs().filtered |a| {
+ safe_to_use_expr(*a, cx.mode)
+ };
check_variants_T(crate, codemap, filename, ~"expr",
extra_exprs + stolen.exprs, pprust::expr_to_str,
replace_expr_in_crate, cx);
}
}
let v =
- visit::mk_simple_visitor(@{visit_ty: |a| visit_ty(has_rp, a),
- .. *visit::default_simple_visitor()});
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_ty: |a| visit_ty(has_rp, a),
+ .. *visit::default_simple_visitor()});
visit::visit_crate(c, (), v);
return *has_rp;
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use back::target_strs;
+use driver::session;
+use session::sess_os_to_meta_os;
+use metadata::loader::meta_section_name;
+
+fn get_target_strs(target_os: session::os) -> target_strs::t {
+ return {
+ module_asm: ~"",
+
+ meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)),
+
+ data_layout: match target_os {
+ session::os_macos => {
+ ~"e-p:32:32:32" +
+ ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
+ ~"-f32:32:32-f64:64:64" +
+ ~"-v64:64:64-v128:64:128" +
+ ~"-a0:0:64-n32"
+ }
+
+ session::os_win32 => {
+ ~"e-p:32:32:32" +
+ ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
+ ~"-f32:32:32-f64:64:64" +
+ ~"-v64:64:64-v128:64:128" +
+ ~"-a0:0:64-n32"
+ }
+
+ session::os_linux => {
+ ~"e-p:32:32:32" +
+ ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
+ ~"-f32:32:32-f64:64:64" +
+ ~"-v64:64:64-v128:64:128" +
+ ~"-a0:0:64-n32"
+ }
+
+ session::os_android => {
+ ~"e-p:32:32:32" +
+ ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
+ ~"-f32:32:32-f64:64:64" +
+ ~"-v64:64:64-v128:64:128" +
+ ~"-a0:0:64-n32"
+ }
+
+ session::os_freebsd => {
+ ~"e-p:32:32:32" +
+ ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
+ ~"-f32:32:32-f64:64:64" +
+ ~"-v64:64:64-v128:64:128" +
+ ~"-a0:0:64-n32"
+ }
+ },
+
+ target_triple: match target_os {
+ session::os_macos => ~"arm-apple-darwin",
+ session::os_win32 => ~"arm-pc-mingw32",
+ session::os_linux => ~"arm-unknown-linux",
+ session::os_android => ~"arm-unknown-android",
+ session::os_freebsd => ~"arm-unknown-freebsd"
+ },
+
+ cc_args: ~[~"-marm"]
+ };
+}
+
+
+//
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
+//
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use libc::{c_int, c_uint, c_char};
+use core::prelude::*;
+
+use back::rpath;
use driver::session;
-use session::Session;
use lib::llvm::llvm;
-use syntax::attr;
-use middle::ty;
+use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False};
+use lib::llvm::{PassManagerRef, FileType};
+use lib;
+use metadata::common::link_meta;
+use metadata::filesearch;
use metadata::{encoder, cstore};
use middle::trans::common::crate_ctxt;
-use metadata::common::link_meta;
+use middle::ty;
+use session::Session;
+use session;
+use util::ppaux;
+
+use core::char;
+use core::cmp;
+use core::hash;
+use core::io::{Writer, WriterUtil};
+use core::libc::{c_int, c_uint, c_char};
+use core::os::consts::{macos, freebsd, linux, android, win32};
+use core::os;
+use core::ptr;
+use core::run;
+use core::str;
+use core::vec;
use std::map::HashMap;
use std::sha1::sha1;
use syntax::ast;
-use syntax::print::pprust;
-use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False,
- PassManagerRef, FileType};
-use metadata::filesearch;
use syntax::ast_map::{path, path_mod, path_name};
-use io::{Writer, WriterUtil};
+use syntax::attr;
+use syntax::print::pprust;
enum output_type {
output_type_none,
pure fn ne(&self, other: &output_type) -> bool { !(*self).eq(other) }
}
-fn llvm_err(sess: Session, msg: ~str) -> ! unsafe {
+pub fn llvm_err(sess: Session, +msg: ~str) -> ! unsafe {
let cstr = llvm::LLVMRustGetLastError();
if cstr == ptr::null() {
sess.fatal(msg);
- } else { sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); }
+ } else {
+ sess.fatal(msg + ~": " + str::raw::from_c_str(cstr));
+ }
}
-fn WriteOutputFile(sess: Session,
+pub fn WriteOutputFile(sess: Session,
PM: lib::llvm::PassManagerRef, M: ModuleRef,
Triple: *c_char,
// FIXME: When #2334 is fixed, change
Output: *c_char, FileType: c_uint,
OptLevel: c_int,
EnableSegmentedStacks: bool) {
- let result = llvm::LLVMRustWriteOutputFile(
- PM, M, Triple, Output, FileType, OptLevel, EnableSegmentedStacks);
- if (!result) {
- llvm_err(sess, ~"Could not write output");
+ unsafe {
+ let result = llvm::LLVMRustWriteOutputFile(
+ PM,
+ M,
+ Triple,
+ Output,
+ FileType,
+ OptLevel,
+ EnableSegmentedStacks);
+ if (!result) {
+ llvm_err(sess, ~"Could not write output");
+ }
}
}
-mod jit {
+pub mod jit {
#[legacy_exports];
+
+ use back::link::llvm_err;
+ use lib::llvm::llvm;
+ use lib::llvm::{ModuleRef, PassManagerRef, mk_target_data};
+ use metadata::cstore;
+ use session::Session;
+
+ use core::cast;
+ use core::libc::c_int;
+ use core::ptr;
+ use core::str;
+
#[nolink]
#[abi = "rust-intrinsic"]
extern mod rusti {
};
let func: fn(++argv: ~[~str]) = cast::transmute(move closure);
- func(~[sess.opts.binary]);
+ func(~[/*bad*/copy sess.opts.binary]);
}
}
}
mod write {
#[legacy_exports];
+
+ use back::link::jit;
+ use back::link::{ModuleRef, WriteOutputFile, output_type};
+ use back::link::{output_type_assembly, output_type_bitcode};
+ use back::link::{output_type_exe, output_type_llvm_assembly};
+ use back::link::{output_type_object};
+ use driver::session;
+ use lib::llvm::llvm;
+ use lib::llvm::{False, True, mk_pass_manager, mk_target_data};
+ use lib;
+ use session::Session;
+
+ use core::char;
+ use core::libc::{c_char, c_int, c_uint};
+ use core::path::Path;
+ use core::str;
+ use core::vec;
+
fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
if ot == output_type_assembly || ot == output_type_object ||
ot == output_type_exe {
}
fn run_passes(sess: Session, llmod: ModuleRef, output: &Path) {
- let opts = sess.opts;
- if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
- let mut pm = mk_pass_manager();
- let td = mk_target_data(
- sess.targ_cfg.target_strs.data_layout);
- llvm::LLVMAddTargetData(td.lltd, pm.llpm);
- // FIXME (#2812): run the linter here also, once there are llvm-c
- // bindings for it.
-
- // Generate a pre-optimization intermediate file if -save-temps was
- // specified.
-
-
- if opts.save_temps {
- match opts.output_type {
- output_type_bitcode => {
- if opts.optimize != session::No {
- let filename = output.with_filetype("no-opt.bc");
+ unsafe {
+ let opts = sess.opts;
+ if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
+ let mut pm = mk_pass_manager();
+ let td = mk_target_data(
+ /*bad*/copy sess.targ_cfg.target_strs.data_layout);
+ llvm::LLVMAddTargetData(td.lltd, pm.llpm);
+ // FIXME (#2812): run the linter here also, once there are llvm-c
+ // bindings for it.
+
+ // Generate a pre-optimization intermediate file if -save-temps
+ // was specified.
+
+
+ if opts.save_temps {
+ match opts.output_type {
+ output_type_bitcode => {
+ if opts.optimize != session::No {
+ let filename = output.with_filetype("no-opt.bc");
+ str::as_c_str(filename.to_str(), |buf| {
+ llvm::LLVMWriteBitcodeToFile(llmod, buf)
+ });
+ }
+ }
+ _ => {
+ let filename = output.with_filetype("bc");
str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf)
});
+ }
}
- }
- _ => {
- let filename = output.with_filetype("bc");
- str::as_c_str(filename.to_str(), |buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf)
- });
- }
- }
- }
- if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
- // FIXME (#2396): This is mostly a copy of the bits of opt's -O2 that
- // are available in the C api.
- // Also: We might want to add optimization levels like -O1, -O2,
- // -Os, etc
- // Also: Should we expose and use the pass lists used by the opt
- // tool?
-
- if opts.optimize != session::No {
- let fpm = mk_pass_manager();
- llvm::LLVMAddTargetData(td.lltd, fpm.llpm);
-
- let FPMB = llvm::LLVMPassManagerBuilderCreate();
- llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint);
- llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(FPMB,
- fpm.llpm);
- llvm::LLVMPassManagerBuilderDispose(FPMB);
-
- llvm::LLVMRunPassManager(fpm.llpm, llmod);
- let mut threshold = 225;
- if opts.optimize == session::Aggressive { threshold = 275; }
-
- let MPMB = llvm::LLVMPassManagerBuilderCreate();
- llvm::LLVMPassManagerBuilderSetOptLevel(MPMB,
- opts.optimize as c_uint);
- llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False);
- llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB, False);
- llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB, False);
- llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB,
- False);
-
- if threshold != 0u {
- llvm::LLVMPassManagerBuilderUseInlinerWithThreshold
- (MPMB, threshold as c_uint);
}
- llvm::LLVMPassManagerBuilderPopulateModulePassManager(MPMB,
- pm.llpm);
+ if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
+ // FIXME (#2396): This is mostly a copy of the bits of opt's -O2
+ // that are available in the C api.
+ // Also: We might want to add optimization levels like -O1, -O2,
+ // -Os, etc
+ // Also: Should we expose and use the pass lists used by the opt
+ // tool?
+
+ if opts.optimize != session::No {
+ let fpm = mk_pass_manager();
+ llvm::LLVMAddTargetData(td.lltd, fpm.llpm);
+
+ let FPMB = llvm::LLVMPassManagerBuilderCreate();
+ llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint);
+ llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(
+ FPMB, fpm.llpm);
+ llvm::LLVMPassManagerBuilderDispose(FPMB);
+
+ llvm::LLVMRunPassManager(fpm.llpm, llmod);
+ let mut threshold = 225;
+ if opts.optimize == session::Aggressive { threshold = 275; }
+
+ let MPMB = llvm::LLVMPassManagerBuilderCreate();
+ llvm::LLVMPassManagerBuilderSetOptLevel(MPMB,
+ opts.optimize as
+ c_uint);
+ llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False);
+ llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB,
+ False);
+ llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB,
+ False);
+ llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB,
+ False);
+
+ if threshold != 0u {
+ llvm::LLVMPassManagerBuilderUseInlinerWithThreshold
+ (MPMB, threshold as c_uint);
+ }
+ llvm::LLVMPassManagerBuilderPopulateModulePassManager(
+ MPMB, pm.llpm);
- llvm::LLVMPassManagerBuilderDispose(MPMB);
- }
- if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
- if is_object_or_assembly_or_exe(opts.output_type) || opts.jit {
- let LLVMOptNone = 0 as c_int; // -O0
- let LLVMOptLess = 1 as c_int; // -O1
- let LLVMOptDefault = 2 as c_int; // -O2, -Os
- let LLVMOptAggressive = 3 as c_int; // -O3
-
- let mut CodeGenOptLevel = match opts.optimize {
- session::No => LLVMOptNone,
- session::Less => LLVMOptLess,
- session::Default => LLVMOptDefault,
- session::Aggressive => LLVMOptAggressive
- };
+ llvm::LLVMPassManagerBuilderDispose(MPMB);
+ }
+ if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); }
+ if is_object_or_assembly_or_exe(opts.output_type) || opts.jit {
+ let LLVMOptNone = 0 as c_int; // -O0
+ let LLVMOptLess = 1 as c_int; // -O1
+ let LLVMOptDefault = 2 as c_int; // -O2, -Os
+ let LLVMOptAggressive = 3 as c_int; // -O3
+
+ let mut CodeGenOptLevel = match opts.optimize {
+ session::No => LLVMOptNone,
+ session::Less => LLVMOptLess,
+ session::Default => LLVMOptDefault,
+ session::Aggressive => LLVMOptAggressive
+ };
- if opts.jit {
- // If we are using JIT, go ahead and create and
- // execute the engine now.
- // JIT execution takes ownership of the module,
- // so don't dispose and return.
+ if opts.jit {
+ // If we are using JIT, go ahead and create and
+ // execute the engine now.
+ // JIT execution takes ownership of the module,
+ // so don't dispose and return.
- jit::exec(sess, pm.llpm, llmod, CodeGenOptLevel, true);
+ jit::exec(sess, pm.llpm, llmod, CodeGenOptLevel, true);
- if sess.time_llvm_passes() {
- llvm::LLVMRustPrintPassTimings();
+ if sess.time_llvm_passes() {
+ llvm::LLVMRustPrintPassTimings();
+ }
+ return;
}
- return;
- }
- let mut FileType;
- if opts.output_type == output_type_object ||
- opts.output_type == output_type_exe {
- FileType = lib::llvm::ObjectFile;
- } else { FileType = lib::llvm::AssemblyFile; }
- // Write optimized bitcode if --save-temps was on.
+ let mut FileType;
+ if opts.output_type == output_type_object ||
+ opts.output_type == output_type_exe {
+ FileType = lib::llvm::ObjectFile;
+ } else { FileType = lib::llvm::AssemblyFile; }
+ // Write optimized bitcode if --save-temps was on.
- if opts.save_temps {
- // Always output the bitcode file with --save-temps
+ if opts.save_temps {
+ // Always output the bitcode file with --save-temps
- let filename = output.with_filetype("opt.bc");
- llvm::LLVMRunPassManager(pm.llpm, llmod);
- str::as_c_str(filename.to_str(), |buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf)
- });
- pm = mk_pass_manager();
- // Save the assembly file if -S is used
+ let filename = output.with_filetype("opt.bc");
+ llvm::LLVMRunPassManager(pm.llpm, llmod);
+ str::as_c_str(filename.to_str(), |buf| {
+ llvm::LLVMWriteBitcodeToFile(llmod, buf)
+ });
+ pm = mk_pass_manager();
+ // Save the assembly file if -S is used
+
+ if opts.output_type == output_type_assembly {
+ let _: () = str::as_c_str(
+ sess.targ_cfg.target_strs.target_triple,
+ |buf_t| {
+ str::as_c_str(output.to_str(), |buf_o| {
+ WriteOutputFile(
+ sess,
+ pm.llpm,
+ llmod,
+ buf_t,
+ buf_o,
+ lib::llvm::AssemblyFile as c_uint,
+ CodeGenOptLevel,
+ true)
+ })
+ });
+ }
- if opts.output_type == output_type_assembly {
- let _: () = str::as_c_str(
- sess.targ_cfg.target_strs.target_triple,
- |buf_t| {
- str::as_c_str(output.to_str(), |buf_o| {
- WriteOutputFile(
- sess,
- pm.llpm,
- llmod,
- buf_t,
- buf_o,
- lib::llvm::AssemblyFile as c_uint,
- CodeGenOptLevel,
- true)
- })
- });
- }
+ // Save the object file for -c or --save-temps alone
+ // This .o is needed when an exe is built
+ if opts.output_type == output_type_object ||
+ opts.output_type == output_type_exe {
+ let _: () = str::as_c_str(
+ sess.targ_cfg.target_strs.target_triple,
+ |buf_t| {
+ str::as_c_str(output.to_str(), |buf_o| {
+ WriteOutputFile(
+ sess,
+ pm.llpm,
+ llmod,
+ buf_t,
+ buf_o,
+ lib::llvm::ObjectFile as c_uint,
+ CodeGenOptLevel,
+ true)
+ })
+ });
+ }
+ } else {
+ // If we aren't saving temps then just output the file
+ // type corresponding to the '-c' or '-S' flag used
- // Save the object file for -c or --save-temps alone
- // This .o is needed when an exe is built
- if opts.output_type == output_type_object ||
- opts.output_type == output_type_exe {
let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple,
|buf_t| {
llmod,
buf_t,
buf_o,
- lib::llvm::ObjectFile as c_uint,
+ FileType as c_uint,
CodeGenOptLevel,
true)
})
});
}
+ // Clean up and return
+
+ llvm::LLVMDisposeModule(llmod);
+ if sess.time_llvm_passes() {
+ llvm::LLVMRustPrintPassTimings();
+ }
+ return;
+ }
+
+ if opts.output_type == output_type_llvm_assembly {
+ // Given options "-S --emit-llvm": output LLVM assembly
+ str::as_c_str(output.to_str(), |buf_o| {
+ llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)});
} else {
- // If we aren't saving temps then just output the file
- // type corresponding to the '-c' or '-S' flag used
-
- let _: () = str::as_c_str(
- sess.targ_cfg.target_strs.target_triple,
- |buf_t| {
- str::as_c_str(output.to_str(), |buf_o| {
- WriteOutputFile(
- sess,
- pm.llpm,
- llmod,
- buf_t,
- buf_o,
- FileType as c_uint,
- CodeGenOptLevel,
- true)
- })
- });
+ // If only a bitcode file is asked for by using the
+ // '--emit-llvm' flag, then output it here
+ llvm::LLVMRunPassManager(pm.llpm, llmod);
+ str::as_c_str(output.to_str(),
+ |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
}
- // Clean up and return
llvm::LLVMDisposeModule(llmod);
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
- return;
}
-
- if opts.output_type == output_type_llvm_assembly {
- // Given options "-S --emit-llvm": output LLVM assembly
- str::as_c_str(output.to_str(), |buf_o| {
- llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)});
- } else {
- // If only a bitcode file is asked for by using the '--emit-llvm'
- // flag, then output it here
- llvm::LLVMRunPassManager(pm.llpm, llmod);
- str::as_c_str(output.to_str(),
- |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
- }
-
- llvm::LLVMDisposeModule(llmod);
- if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
}
}
let mut name: Option<~str> = None;
let mut vers: Option<~str> = None;
let mut cmh_items: ~[@ast::meta_item] = ~[];
- let linkage_metas = attr::find_linkage_metas(c.node.attrs);
- attr::require_unique_names(sess.diagnostic(), linkage_metas);
+ let linkage_metas =
+ attr::find_linkage_metas(/*bad*/copy c.node.attrs);
+ // XXX: Bad copy.
+ attr::require_unique_names(sess.diagnostic(), copy linkage_metas);
for linkage_metas.each |meta| {
if attr::get_meta_item_name(*meta) == ~"name" {
match attr::get_meta_item_value_str(*meta) {
- Some(ref v) => { name = Some((*v)); }
+ Some(ref v) => { name = Some((/*bad*/copy *v)); }
None => cmh_items.push(*meta)
}
} else if attr::get_meta_item_name(*meta) == ~"vers" {
match attr::get_meta_item_value_str(*meta) {
- Some(ref v) => { vers = Some((*v)); }
+ Some(ref v) => { vers = Some((/*bad*/copy *v)); }
None => cmh_items.push(*meta)
}
} else { cmh_items.push(*meta); }
return len_and_str(pprust::lit_to_str(@l));
}
- let cmh_items = attr::sort_meta_items(metas.cmh_items);
+ let cmh_items = attr::sort_meta_items(/*bad*/copy metas.cmh_items);
symbol_hasher.reset();
for cmh_items.each |m| {
fn crate_meta_name(sess: Session, _crate: ast::crate,
output: &Path, metas: provided_metas) -> ~str {
return match metas.name {
- Some(ref v) => (*v),
+ Some(ref v) => (/*bad*/copy *v),
None => {
let name = match output.filestem() {
None => sess.fatal(fmt!("output file name `%s` doesn't\
appear to have a stem",
output.to_str())),
- Some(ref s) => (*s)
+ Some(ref s) => (/*bad*/copy *s)
};
- warn_missing(sess, ~"name", name);
+ // XXX: Bad copy.
+ warn_missing(sess, ~"name", copy name);
name
}
};
fn crate_meta_vers(sess: Session, _crate: ast::crate,
metas: provided_metas) -> ~str {
return match metas.vers {
- Some(ref v) => (*v),
+ Some(ref v) => (/*bad*/copy *v),
None => {
let vers = ~"0.0";
- warn_missing(sess, ~"vers", vers);
+ // Bad copy.
+ warn_missing(sess, ~"vers", copy vers);
vers
}
};
fn get_symbol_hash(ccx: @crate_ctxt, t: ty::t) -> ~str {
match ccx.type_hashcodes.find(t) {
- Some(ref h) => return (*h),
+ Some(ref h) => return (/*bad*/copy *h),
None => {
let hash = symbol_hash(ccx.tcx, ccx.symbol_hasher, t, ccx.link_meta);
- ccx.type_hashcodes.insert(t, hash);
+ // XXX: Bad copy. Prefer `@str`?
+ ccx.type_hashcodes.insert(t, copy hash);
return hash;
}
}
n
}
-fn exported_name(sess: Session, path: path, hash: ~str, vers: ~str) -> ~str {
+fn exported_name(sess: Session,
+ +path: path,
+ +hash: ~str,
+ +vers: ~str) -> ~str {
return mangle(sess,
vec::append_one(
vec::append_one(path, path_name(sess.ident_of(hash))),
path_name(sess.ident_of(vers))));
}
-fn mangle_exported_name(ccx: @crate_ctxt, path: path, t: ty::t) -> ~str {
+fn mangle_exported_name(ccx: @crate_ctxt, +path: path, t: ty::t) -> ~str {
let hash = get_symbol_hash(ccx, t);
- return exported_name(ccx.sess, path, hash, ccx.link_meta.vers);
+ return exported_name(ccx.sess, path,
+ hash,
+ /*bad*/copy ccx.link_meta.vers);
}
fn mangle_internal_name_by_type_only(ccx: @crate_ctxt,
- t: ty::t, name: ~str) ->
- ~str {
- let s = util::ppaux::ty_to_short_str(ccx.tcx, t);
+ t: ty::t,
+ +name: ~str) -> ~str {
+ let s = ppaux::ty_to_short_str(ccx.tcx, t);
let hash = get_symbol_hash(ccx, t);
return mangle(ccx.sess,
~[path_name(ccx.sess.ident_of(name)),
path_name(ccx.sess.ident_of(hash))]);
}
-fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: path,
- flav: ~str) -> ~str {
+fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt,
+ +path: path,
+ +flav: ~str) -> ~str {
return mangle(ccx.sess,
vec::append_one(path, path_name((ccx.names)(flav))));
}
-fn mangle_internal_name_by_path(ccx: @crate_ctxt, path: path) -> ~str {
+fn mangle_internal_name_by_path(ccx: @crate_ctxt, +path: path) -> ~str {
return mangle(ccx.sess, path);
}
-fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: ~str) -> ~str {
+fn mangle_internal_name_by_seq(ccx: @crate_ctxt, +flav: ~str) -> ~str {
return fmt!("%s_%u", flav, (ccx.names)(flav).repr);
}
+
+fn output_dll_filename(os: session::os, lm: &link_meta) -> ~str {
+ let libname = fmt!("%s-%s-%s", lm.name, lm.extras_hash, lm.vers);
+ let (dll_prefix, dll_suffix) = match os {
+ session::os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
+ session::os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
+ session::os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
+ session::os_android => (android::DLL_PREFIX, android::DLL_SUFFIX),
+ session::os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
+ };
+ return str::from_slice(dll_prefix) + libname +
+ str::from_slice(dll_suffix);
+}
+
// If the user wants an exe generated we need to invoke
// cc to link the object file with some libs
fn link_binary(sess: Session,
out_filename: &Path,
lm: link_meta) {
// Converts a library file-stem into a cc -l argument
- fn unlib(config: @session::config, stem: ~str) -> ~str {
+ fn unlib(config: @session::config, +stem: ~str) -> ~str {
if stem.starts_with("lib") &&
config.os != session::os_win32 {
stem.slice(3, stem.len())
}
let output = if sess.building_library {
- let long_libname =
- os::dll_filename(fmt!("%s-%s-%s",
- lm.name, lm.extras_hash, lm.vers));
+ let long_libname = output_dll_filename(sess.targ_cfg.os, &lm);
debug!("link_meta.name: %s", lm.name);
debug!("long_libname: %s", long_libname);
debug!("out_filename: %s", out_filename.to_str());
out_filename.dir_path().push(long_libname)
} else {
- *out_filename
+ /*bad*/copy *out_filename
};
log(debug, ~"output: " + output.to_str());
// For win32, there is no cc command,
// so we add a condition to make it use gcc.
let cc_prog: ~str =
- if sess.targ_cfg.os == session::os_win32 { ~"gcc" } else { ~"cc" };
+ if sess.targ_cfg.os == session::os_android {
+ ~"arm-linux-androideabi-g++"
+ } else if sess.targ_cfg.os == session::os_win32 { ~"gcc" }
+ else { ~"cc" };
// The invocations of cc share some flags across platforms
let mut cc_args =
}
let ula = cstore::get_used_link_args(cstore);
- for ula.each |arg| { cc_args.push(*arg); }
+ for ula.each |arg| { cc_args.push(/*bad*/copy *arg); }
// # Extern library linking
// to be found at compile time so it is still entirely up to outside
// forces to make sure that library can be found at runtime.
- let addl_paths = sess.opts.addl_lib_search_paths;
+ let addl_paths = /*bad*/copy sess.opts.addl_lib_search_paths;
for addl_paths.each |path| { cc_args.push(~"-L" + path.to_str()); }
// The names of the extern libraries
// have to be explicit about linking to it. See #2510
cc_args.push(~"-lm");
}
+ else if sess.targ_cfg.os == session::os_android {
+ cc_args.push_all(~[~"-ldl", ~"-llog", ~"-lsupc++",
+ ~"-lgnustl_shared"]);
+ cc_args.push(~"-lm");
+ }
if sess.targ_cfg.os == session::os_freebsd {
cc_args.push_all(~[~"-pthread", ~"-lrt",
}
// Stack growth requires statically linking a __morestack function
+ if sess.targ_cfg.os != session::os_android {
cc_args.push(~"-lmorestack");
+ }
// FIXME (#2397): At some point we want to rpath our guesses as to where
// extern libraries might live, based on the addl_lib_search_paths
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map;
-use std::map::HashMap;
-use metadata::cstore;
+use core::prelude::*;
+
use driver::session;
+use metadata::cstore;
use metadata::filesearch;
+use core::os;
+use core::uint;
+use core::util;
+use core::vec;
+use std::map::HashMap;
+use std::map;
+
+export get_absolute_rpath;
+export get_install_prefix_rpath;
+export get_relative_to;
export get_rpath_flags;
+export get_rpath_relative_to_output;
+export minimize_rpaths;
+export rpaths_to_flags;
pure fn not_win32(os: session::os) -> bool {
match os {
// where rustrt is and we know every rust program needs it
let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));
- let target_triple = sess.opts.target_triple;
+ let target_triple = /*bad*/copy sess.opts.target_triple;
let rpaths = get_rpaths(os, &sysroot, output, libs, target_triple);
rpaths_to_flags(rpaths)
}
fn get_rpath_relative_to_output(os: session::os,
output: &Path,
- lib: &Path) -> Path {
+ lib: &Path)
+ -> Path {
+ use core::os;
+
assert not_win32(os);
// Mac doesn't appear to support $ORIGIN
let prefix = match os {
- session::os_linux | session::os_freebsd => "$ORIGIN",
+ session::os_android |session::os_linux | session::os_freebsd
+ => "$ORIGIN",
session::os_macos => "@executable_path",
- session::os_win32 => core::util::unreachable()
+ session::os_win32 => util::unreachable()
};
Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
let abs2 = abs2.normalize();
debug!("finding relative path from %s to %s",
abs1.to_str(), abs2.to_str());
- let split1 = abs1.components;
- let split2 = abs2.components;
+ let split1 = /*bad*/copy abs1.components;
+ let split2 = /*bad*/copy abs2.components;
let len1 = vec::len(split1);
let len2 = vec::len(split2);
assert len1 > 0;
for rpaths.each |rpath| {
let s = rpath.to_str();
if !set.contains_key(s) {
- minimized.push(*rpath);
+ minimized.push(/*bad*/copy *rpath);
set.insert(s, ());
}
}
#[cfg(unix)]
mod test {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
+ use back::rpath::{get_relative_to, get_rpath_relative_to_output};
+ use back::rpath::{minimize_rpaths, rpaths_to_flags};
+ use driver::session;
+
+ use core::os;
+ use core::str;
+
#[test]
fn test_rpaths_to_flags() {
let flags = rpaths_to_flags(~[Path("path1"),
#[test]
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "andorid")]
fn test_rpath_relative() {
let o = session::os_linux;
let res = get_rpath_relative_to_output(o,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
type t = {
module_asm: ~str,
meta_sect_name: ~str,
fn nothrow(f: ValueRef) -> ValueRef {
base::set_no_unwind(f); f
}
- let d = |a,b,c| decl(llmod, ~"upcall_", a, b, c);
- let dv = |a,b| decl(llmod, ~"upcall_", a, b, T_void());
+ let d: &fn(+a: ~str, +b: ~[TypeRef], +c: TypeRef) -> ValueRef =
+ |a,b,c| decl(llmod, ~"upcall_", a, b, c);
+ let dv: &fn(+a: ~str, +b: ~[TypeRef]) -> ValueRef =
+ |a,b| decl(llmod, ~"upcall_", a, b, T_void());
let int_t = T_int(targ_cfg);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
+use back::target_strs;
use driver::session;
-use session::sess_os_to_meta_os;
use metadata::loader::meta_section_name;
+use session::sess_os_to_meta_os;
fn get_target_strs(target_os: session::os) -> target_strs::t {
return {
session::os_linux => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
}
+ session::os_android => {
+ ~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
+ }
session::os_freebsd => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
session::os_macos => ~"i686-apple-darwin",
session::os_win32 => ~"i686-pc-mingw32",
session::os_linux => ~"i686-unknown-linux-gnu",
+ session::os_android => ~"i686-unknown-android-gnu",
session::os_freebsd => ~"i686-unknown-freebsd"
},
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
+use back::target_strs;
use driver::session;
-use session::sess_os_to_meta_os;
use metadata::loader::meta_section_name;
+use session::sess_os_to_meta_os;
fn get_target_strs(target_os: session::os) -> target_strs::t {
return {
~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
~"s0:64:64-f80:128:128-n8:16:32:64-S128"
}
+ session::os_android => {
+ ~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
+ ~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
+ ~"s0:64:64-f80:128:128-n8:16:32:64-S128"
+ }
session::os_freebsd => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
session::os_macos => ~"x86_64-apple-darwin",
session::os_win32 => ~"x86_64-pc-mingw32",
session::os_linux => ~"x86_64-unknown-linux-gnu",
+ session::os_android => ~"x86_64-unknown-android-gnu",
session::os_freebsd => ~"x86_64-unknown-freebsd",
},
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use back::link;
+use back::{arm, x86, x86_64};
+use front;
+use lib::llvm::llvm;
use metadata::{creader, cstore, filesearch};
-use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive};
-use syntax::parse;
-use syntax::{ast, codemap};
-use syntax::attr;
+use metadata;
use middle::{trans, freevars, kind, ty, typeck, lint};
-use syntax::print::{pp, pprust};
+use middle;
+use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive};
+use session;
use util::ppaux;
-use back::link;
-use result::{Ok, Err};
-use std::getopts;
-use std::getopts::{opt_present};
-use std::getopts::groups;
+
+use core::cmp;
+use core::int;
+use core::io::WriterUtil;
+use core::io;
+use core::option;
+use core::os;
+use core::result::{Ok, Err};
+use core::str;
+use core::vec;
use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts};
-use io::WriterUtil;
-use back::{x86, x86_64};
+use std::getopts::groups;
+use std::getopts::{opt_present};
+use std::getopts;
use std::map::HashMap;
-use lib::llvm::llvm;
-
-enum pp_mode {ppm_normal, ppm_expanded, ppm_typed, ppm_identified,
- ppm_expanded_identified }
+use std;
+use syntax::ast;
+use syntax::ast_map;
+use syntax::attr;
+use syntax::codemap;
+use syntax::diagnostic;
+use syntax::parse;
+use syntax::print::{pp, pprust};
+use syntax;
+
+enum pp_mode {
+ ppm_normal,
+ ppm_expanded,
+ ppm_typed,
+ ppm_identified,
+ ppm_expanded_identified
+}
/**
* The name used for source code that doesn't originate in a file
}
}
-fn default_configuration(sess: Session, argv0: ~str, input: input) ->
+fn default_configuration(sess: Session, +argv0: ~str, input: input) ->
ast::crate_cfg {
let libc = match sess.targ_cfg.os {
session::os_win32 => ~"msvcrt.dll",
session::os_macos => ~"libc.dylib",
session::os_linux => ~"libc.so.6",
+ session::os_android => ~"libc.so",
session::os_freebsd => ~"libc.so.7"
// _ { "libc.so" }
};
+ let tos = match sess.targ_cfg.os {
+ session::os_win32 => ~"win32",
+ session::os_macos => ~"macos",
+ session::os_linux => ~"linux",
+ session::os_android => ~"android",
+ session::os_freebsd => ~"freebsd"
+ // _ { "libc.so" }
+ };
let mk = attr::mk_name_value_item_str;
};
return ~[ // Target bindings.
- attr::mk_word_item(os::family()),
- mk(~"target_os", os::sysname()),
- mk(~"target_family", os::family()),
+ attr::mk_word_item(str::from_slice(os::FAMILY)),
+ mk(~"target_os", tos),
+ mk(~"target_family", str::from_slice(os::FAMILY)),
mk(~"target_arch", arch),
mk(~"target_word_size", wordsz),
mk(~"target_libc", libc),
mk(~"build_input", source_name(input))];
}
-fn append_configuration(cfg: ast::crate_cfg, name: ~str) -> ast::crate_cfg {
- if attr::contains_name(cfg, name) {
+fn append_configuration(+cfg: ast::crate_cfg, +name: ~str) -> ast::crate_cfg {
+ // XXX: Bad copy.
+ if attr::contains_name(copy cfg, copy name) {
return cfg;
} else {
return vec::append_one(cfg, attr::mk_word_item(name));
}
}
-fn build_configuration(sess: Session, argv0: ~str, input: input) ->
+fn build_configuration(sess: Session, +argv0: ~str, input: input) ->
ast::crate_cfg {
// Combine the configuration requested by the session (command line) with
// some default and generated configuration items
let default_cfg = default_configuration(sess, argv0, input);
- let user_cfg = sess.opts.cfg;
+ let user_cfg = /*bad*/copy sess.opts.cfg;
// If the user wants a test runner, then add the test cfg
let user_cfg = append_configuration(
user_cfg,
// meta_word variant.
let mut words = ~[];
for cfgspecs.each |s| {
- words.push(attr::mk_word_item(*s));
+ words.push(attr::mk_word_item(/*bad*/copy *s));
}
return words;
}
str_input(~str)
}
-fn parse_input(sess: Session, cfg: ast::crate_cfg, input: input)
+fn parse_input(sess: Session, +cfg: ast::crate_cfg, input: input)
-> @ast::crate {
match input {
file_input(ref file) => {
str_input(ref src) => {
// FIXME (#2319): Don't really want to box the source string
parse::parse_crate_from_source_str(
- anon_src(), @(*src), cfg, sess.parse_sess)
+ anon_src(), @(/*bad*/copy *src), cfg, sess.parse_sess)
}
}
}
-> {crate: @ast::crate, tcx: Option<ty::ctxt>} {
let time_passes = sess.time_passes();
let mut crate = time(time_passes, ~"parsing",
- ||parse_input(sess, cfg, input) );
+ || parse_input(sess, copy cfg, input) );
if upto == cu_parse { return {crate: crate, tcx: None}; }
sess.building_library = session::building_library(
front::test::modify_for_testing(sess, crate));
crate = time(time_passes, ~"expansion", ||
- syntax::ext::expand::expand_crate(sess.parse_sess, cfg,
+ syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg,
crate));
if upto == cu_expand { return {crate: crate, tcx: None}; }
time(time_passes, ~"mode computation", ||
middle::mode::compute_modes(ty_cx, method_map, crate));
- time(time_passes, ~"alt checking", ||
- middle::check_alt::check_crate(ty_cx, method_map, crate));
+ time(time_passes, ~"match checking", ||
+ middle::check_match::check_crate(ty_cx, method_map, crate));
let last_use_map =
time(time_passes, ~"liveness checking", ||
return {crate: crate, tcx: None};
}
-fn compile_input(sess: Session, cfg: ast::crate_cfg, input: input,
+fn compile_input(sess: Session, +cfg: ast::crate_cfg, input: input,
outdir: &Option<Path>, output: &Option<Path>) {
let upto = if sess.opts.parse_only { cu_parse }
compile_upto(sess, cfg, input, upto, Some(outputs));
}
-fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: input,
+fn pretty_print_input(sess: Session, +cfg: ast::crate_cfg, input: input,
ppm: pp_mode) {
fn ann_paren_for_expr(node: pprust::ann_node) {
match node {
let ann = match ppm {
ppm_typed => {
- {pre: ann_paren_for_expr,
- post: |a| ann_typed_post(tcx.get(), a) }
+ pprust::pp_ann {pre: ann_paren_for_expr,
+ post: |a| ann_typed_post(tcx.get(), a) }
}
ppm_identified | ppm_expanded_identified => {
- {pre: ann_paren_for_expr, post: ann_identified_post}
+ pprust::pp_ann {pre: ann_paren_for_expr,
+ post: ann_identified_post}
+ }
+ ppm_expanded | ppm_normal => {
+ pprust::no_ann()
}
- ppm_expanded | ppm_normal => pprust::no_ann()
};
let is_expanded = upto != cu_parse;
let src = sess.codemap.get_filemap(source_name(input)).src;
Some(session::os_macos)
} else if str::contains(triple, ~"linux") {
Some(session::os_linux)
+ } else if str::contains(triple, ~"android") {
+ Some(session::os_android)
} else if str::contains(triple, ~"freebsd") {
Some(session::os_freebsd)
} else { None }
let target_strs = match arch {
session::arch_x86 => x86::get_target_strs(os),
session::arch_x86_64 => x86_64::get_target_strs(os),
- session::arch_arm => x86::get_target_strs(os)
+ session::arch_arm => arm::get_target_strs(os)
};
let target_cfg: @session::config =
@{os: os, arch: arch, target_strs: target_strs, int_type: int_type,
};
}
-fn build_session_options(binary: ~str,
+fn build_session_options(+binary: ~str,
matches: &getopts::Matches,
demitter: diagnostic::emitter) -> @session::options {
let crate_type = if opt_present(matches, ~"lib") {
for debug_flags.each |debug_flag| {
let mut this_bit = 0u;
for debug_map.each |pair| {
- let (name, _, bit) = *pair;
+ let (name, _, bit) = /*bad*/copy *pair;
if name == *debug_flag { this_bit = bit; break; }
}
if this_bit == 0u {
debugging_opts |= this_bit;
}
if debugging_opts & session::debug_llvm != 0 {
- llvm::LLVMSetDebug(1);
+ unsafe {
+ llvm::LLVMSetDebug(1);
+ }
}
let jit = opt_present(matches, ~"jit");
let target =
match target_opt {
None => host_triple(),
- Some(ref s) => (*s)
+ Some(ref s) => (/*bad*/copy *s)
};
let addl_lib_search_paths =
let filesearch = filesearch::mk_filesearch(
sopts.maybe_sysroot,
sopts.target_triple,
- sopts.addl_lib_search_paths);
+ /*bad*/copy sopts.addl_lib_search_paths);
let lint_settings = lint::mk_lint_settings();
Session_(@{targ_cfg: target_cfg,
opts: sopts,
// have to make up a name
// We want to toss everything after the final '.'
let dirpath = match *odir {
- Some(ref d) => (*d),
+ Some(ref d) => (/*bad*/copy *d),
None => match input {
str_input(_) => os::getcwd(),
file_input(ref ifile) => (*ifile).dir_path()
}
Some(ref out_file) => {
- out_path = (*out_file);
+ out_path = (/*bad*/copy *out_file);
obj_path = if stop_after_codegen {
- (*out_file)
+ (/*bad*/copy *out_file)
} else {
(*out_file).with_filetype(obj_suffix)
};
mod test {
#[legacy_exports];
+ use core::prelude::*;
+
+ use driver::driver::{build_configuration, build_session};
+ use driver::driver::{build_session_options, optgroups, str_input};
+
+ use core::vec;
+ use std::getopts::groups::getopts;
+ use std::getopts;
+ use syntax::attr;
+ use syntax::diagnostic;
+
// When the user supplies --test we should implicitly supply --cfg test
#[test]
fn test_switch_implies_cfg_test() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
use back::link;
use back::target_strs;
+use back;
+use driver;
+use driver::session;
use metadata::filesearch;
+use metadata;
use middle::lint;
+use core::cmp;
+use core::option;
use syntax::ast::node_id;
use syntax::ast::{int_ty, uint_ty, float_ty};
use syntax::codemap::span;
+use syntax::diagnostic;
use syntax::parse::parse_sess;
use syntax::{ast, codemap};
+use syntax;
-
-enum os { os_win32, os_macos, os_linux, os_freebsd, }
+enum os { os_win32, os_macos, os_linux, os_android, os_freebsd, }
impl os : cmp::Eq {
pure fn eq(&self, other: &os) -> bool {
fn unimpl(msg: ~str) -> ! {
self.span_diagnostic.handler().unimpl(msg)
}
- fn span_lint_level(level: lint::level,
- sp: span, msg: ~str) {
+ fn span_lint_level(level: lint::level, sp: span, +msg: ~str) {
match level {
lint::allow => { },
lint::warn => self.span_warn(sp, msg),
}
}
fn span_lint(lint_mode: lint::lint,
- expr_id: ast::node_id, item_id: ast::node_id,
- span: span, msg: ~str) {
+ expr_id: ast::node_id,
+ item_id: ast::node_id,
+ span: span,
+ +msg: ~str) {
let level = lint::get_lint_settings_level(
self.lint_settings, lint_mode, expr_id, item_id);
self.span_lint_level(level, span, msg);
}
fn str_of(id: ast::ident) -> ~str {
- *self.parse_sess.interner.get(id)
+ /*bad*/copy *self.parse_sess.interner.get(id)
}
- fn ident_of(st: ~str) -> ast::ident {
+ fn ident_of(+st: ~str) -> ast::ident {
self.parse_sess.interner.intern(@st)
}
fn intr() -> @syntax::parse::token::ident_interner {
match os {
os_win32 => loader::os_win32,
os_linux => loader::os_linux,
+ os_android => loader::os_android,
os_macos => loader::os_macos,
os_freebsd => loader::os_freebsd
}
#[cfg(test)]
mod test {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use driver::session::{bin_crate, building_library, lib_crate};
+ use driver::session::{unknown_crate};
+
+ use syntax::ast;
use syntax::ast_util;
- fn make_crate_type_attr(t: ~str) -> ast::attribute {
+ fn make_crate_type_attr(+t: ~str) -> ast::attribute {
ast_util::respan(ast_util::dummy_sp(), {
style: ast::attr_outer,
value: ast_util::respan(ast_util::dummy_sp(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use syntax::{ast, fold, attr};
+use core::option;
+use core::vec;
+
export strip_unconfigured_items;
export metas_in_cfg;
export strip_items;
-type in_cfg_pred = fn@(~[ast::attribute]) -> bool;
+type in_cfg_pred = fn@(+attrs: ~[ast::attribute]) -> bool;
type ctxt = @{
in_cfg: in_cfg_pred
// any items that do not belong in the current configuration
fn strip_unconfigured_items(crate: @ast::crate) -> @ast::crate {
do strip_items(crate) |attrs| {
- in_cfg(crate.node.config, attrs)
+ in_cfg(/*bad*/copy crate.node.config, attrs)
}
}
let ctxt = @{in_cfg: in_cfg};
- let precursor =
- @{fold_mod: |a,b| fold_mod(ctxt, a, b),
+ let precursor = @fold::AstFoldFns {
+ fold_mod: |a,b| fold_mod(ctxt, a, b),
fold_block: fold::wrap(|a,b| fold_block(ctxt, a, b) ),
fold_foreign_mod: |a,b| fold_foreign_mod(ctxt, a, b),
- fold_item_underscore: |a,b| fold_item_underscore(ctxt, a, b),
+ fold_item_underscore: |a,b| {
+ // Bad copy.
+ fold_item_underscore(ctxt, copy a, b)
+ },
.. *fold::default_ast_fold()};
let fold = fold::make_fold(precursor);
};
}
-fn fold_item_underscore(cx: ctxt, item: ast::item_,
+fn fold_item_underscore(cx: ctxt, +item: ast::item_,
fld: fold::ast_fold) -> ast::item_ {
let item = match item {
ast::item_impl(a, b, c, methods) => {
- let methods = methods.filter(|m| method_in_cfg(cx, *m) );
+ let methods = methods.filtered(|m| method_in_cfg(cx, *m) );
ast::item_impl(a, b, c, methods)
}
- ast::item_trait(a, b, ref methods) => {
- let methods = methods.filter(|m| trait_method_in_cfg(cx, m) );
- ast::item_trait(a, b, methods)
+ ast::item_trait(ref a, ref b, ref methods) => {
+ let methods = methods.filtered(|m| trait_method_in_cfg(cx, m) );
+ ast::item_trait(/*bad*/copy *a, /*bad*/copy *b, methods)
}
- _ => item
+ item => item
};
fold::noop_fold_item_underscore(item, fld)
fn fold_block(cx: ctxt, b: ast::blk_, fld: fold::ast_fold) ->
ast::blk_ {
let filtered_stmts = vec::filter_map(b.stmts, |a| filter_stmt(cx, *a));
- return {view_items: b.view_items,
+ return {view_items: /*bad*/copy b.view_items,
stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)),
expr: option::map(&b.expr, |x| fld.fold_expr(*x)),
id: b.id,
}
fn item_in_cfg(cx: ctxt, item: @ast::item) -> bool {
- return (cx.in_cfg)(item.attrs);
+ return (cx.in_cfg)(/*bad*/copy item.attrs);
}
fn foreign_item_in_cfg(cx: ctxt, item: @ast::foreign_item) -> bool {
- return (cx.in_cfg)(item.attrs);
+ return (cx.in_cfg)(/*bad*/copy item.attrs);
}
fn view_item_in_cfg(cx: ctxt, item: @ast::view_item) -> bool {
- return (cx.in_cfg)(item.attrs);
+ return (cx.in_cfg)(/*bad*/copy item.attrs);
}
fn method_in_cfg(cx: ctxt, meth: @ast::method) -> bool {
- return (cx.in_cfg)(meth.attrs);
+ return (cx.in_cfg)(/*bad*/copy meth.attrs);
}
fn trait_method_in_cfg(cx: ctxt, meth: &ast::trait_method) -> bool {
match *meth {
- ast::required(ref meth) => (cx.in_cfg)(meth.attrs),
- ast::provided(@ref meth) => (cx.in_cfg)(meth.attrs)
+ ast::required(ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs),
+ ast::provided(@ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs)
}
}
// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
-fn in_cfg(cfg: ast::crate_cfg, attrs: ~[ast::attribute]) -> bool {
+fn in_cfg(+cfg: ast::crate_cfg, +attrs: ~[ast::attribute]) -> bool {
metas_in_cfg(cfg, attr::attr_metas(attrs))
}
-fn metas_in_cfg(cfg: ast::crate_cfg, metas: ~[@ast::meta_item]) -> bool {
-
+fn metas_in_cfg(cfg: ast::crate_cfg, +metas: ~[@ast::meta_item]) -> bool {
// The "cfg" attributes on the item
let cfg_metas = attr::find_meta_items_by_name(metas, ~"cfg");
if !has_cfg_metas { return true; }
for cfg_metas.each |cfg_mi| {
- if attr::contains(cfg, *cfg_mi) { return true; }
+ if attr::contains(/*bad*/copy cfg, *cfg_mi) { return true; }
}
return false;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use driver::session::Session;
-use syntax::codemap;
+
+use core::vec;
use syntax::ast;
use syntax::ast_util::*;
use syntax::attr;
+use syntax::codemap;
+use syntax::fold;
export maybe_inject_libcore_ref;
+const CORE_VERSION: &static/str = "0.6";
+
fn maybe_inject_libcore_ref(sess: Session,
crate: @ast::crate) -> @ast::crate {
if use_core(crate) {
fn inject_libcore_ref(sess: Session,
crate: @ast::crate) -> @ast::crate {
-
- fn spanned<T: Copy>(x: T) -> @ast::spanned<T> {
- return @{node: x,
- span: dummy_sp()};
+ fn spanned<T: Copy>(x: T) -> ast::spanned<T> {
+ ast::spanned { node: x, span: dummy_sp() }
}
- let n1 = sess.next_node_id();
- let n2 = sess.next_node_id();
-
- let vi1 = @{node: ast::view_item_use(sess.ident_of(~"core"), ~[], n1),
- attrs: ~[],
- vis: ast::private,
- span: dummy_sp()};
- let vp = spanned(ast::view_path_glob(
- ident_to_path(dummy_sp(), sess.ident_of(~"core")),
- n2));
- let vi2 = @{node: ast::view_item_import(~[vp]),
- attrs: ~[],
- vis: ast::private,
- span: dummy_sp()};
-
- let vis = vec::append(~[vi1, vi2], crate.node.module.view_items);
-
- return @{node: {module: { view_items: vis,.. crate.node.module },
- .. crate.node},.. *crate }
+ let precursor = @fold::AstFoldFns {
+ fold_crate: |crate, span, fld| {
+ let n1 = sess.next_node_id();
+ let vi1 = @{node: ast::view_item_use(sess.ident_of(~"core"),
+ ~[],
+ n1),
+ attrs: ~[
+ spanned({
+ style: ast::attr_inner,
+ value: spanned(ast::meta_name_value(
+ ~"vers",
+ spanned(ast::lit_str(
+ @CORE_VERSION.to_str()))
+ )),
+ is_sugared_doc: false
+ })
+ ],
+ vis: ast::private,
+ span: dummy_sp()};
+
+ let vis = vec::append(~[vi1], crate.module.view_items);
+ let mut new_module = {
+ view_items: vis,
+ ../*bad*/copy crate.module
+ };
+ new_module = fld.fold_mod(new_module);
+
+ // XXX: Bad copy.
+ let new_crate = { module: new_module, ..copy crate };
+ (new_crate, span)
+ },
+ fold_mod: |module, fld| {
+ let n2 = sess.next_node_id();
+
+ let prelude_path = @{
+ span: dummy_sp(),
+ global: false,
+ idents: ~[
+ sess.ident_of(~"core"),
+ sess.ident_of(~"prelude")
+ ],
+ rp: None,
+ types: ~[]
+ };
+
+ let vp = @spanned(ast::view_path_glob(prelude_path, n2));
+ let vi2 = @{node: ast::view_item_import(~[vp]),
+ attrs: ~[],
+ vis: ast::private,
+ span: dummy_sp()};
+
+ let vis = vec::append(~[vi2], module.view_items);
+
+ // XXX: Bad copy.
+ let new_module = { view_items: vis, ..copy module };
+ fold::noop_fold_mod(new_module, fld)
+ },
+ ..*fold::default_ast_fold()
+ };
+
+ let fold = fold::make_fold(precursor);
+ @fold.fold_crate(*crate)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use driver::session::Session;
use syntax::parse;
use syntax::ast;
-export inject_intrinsic;
+use core::vec;
-fn inject_intrinsic(sess: Session,
- crate: @ast::crate) -> @ast::crate {
+export inject_intrinsic;
+fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate {
let intrinsic_module = @(include_str!("intrinsic.rs").to_owned());
let item = parse::parse_item_from_source_str(~"<intrinsic>",
intrinsic_module,
- sess.opts.cfg,
+ /*bad*/copy sess.opts.cfg,
~[],
sess.parse_sess);
let item =
let items = vec::append(~[item], crate.node.module.items);
- return @{node: {module: { items: items ,.. crate.node.module }
- ,.. crate.node} ,.. *crate }
+ @ast::spanned {
+ node: { module: { items: items ,.. /*bad*/copy crate.node.module },
+ .. /*bad*/copy crate.node},
+ .. /*bad*/copy *crate
+ }
}
// Code that generates a test runner to run all the tests in a crate
-use syntax::{ast, ast_util};
-use syntax::ast_util::*;
-//import syntax::ast_util::dummy_sp;
-use syntax::fold;
-use syntax::print::pprust;
-use syntax::codemap::span;
+use core::prelude::*;
+
use driver::session;
+use front::config;
use session::Session;
+
+use core::dvec::DVec;
+use core::option;
+use core::vec;
+use syntax::ast_util::*;
use syntax::attr;
-use dvec::DVec;
+use syntax::codemap::span;
+use syntax::fold;
+use syntax::print::pprust;
+use syntax::{ast, ast_util};
export modify_for_testing;
// We generate the test harness when building in the 'test'
// configuration, either with the '--test' or '--cfg test'
// command line options.
- let should_test = attr::contains(crate.node.config,
+ let should_test = attr::contains(/*bad*/copy crate.node.config,
attr::mk_word_item(~"test"));
if should_test {
mut path: ~[],
testfns: DVec()};
- let precursor =
- @{fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ),
- fold_item: |a,b| fold_item(cx, a, b),
- fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()};
+ let precursor = @fold::AstFoldFns {
+ fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ),
+ fold_item: |a,b| fold_item(cx, a, b),
+ fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()};
let fold = fold::make_fold(precursor);
let res = @fold.fold_crate(*crate);
}
let mod_nomain =
- {view_items: m.view_items,
+ {view_items: /*bad*/copy m.view_items,
items: vec::filter_map(m.items, |i| nomain(cx, *i))};
return fold::noop_fold_mod(mod_nomain, fld);
}
// Add a special __test module to the crate that will contain code
// generated for the test harness
- return {module: add_test_module(cx, folded.module),.. folded};
+ return {module: add_test_module(cx, /*bad*/copy folded.module),.. folded};
}
_ => {
debug!("this is a test function");
let test = {span: i.span,
- path: cx.path, ignore: is_ignored(cx, i),
+ path: /*bad*/copy cx.path, ignore: is_ignored(cx, i),
should_fail: should_fail(i)};
cx.testfns.push(test);
debug!("have %u test functions", cx.testfns.len());
vec::len(attr::find_attrs_by_name(i.attrs, ~"test")) > 0u;
fn has_test_signature(i: @ast::item) -> bool {
- match i.node {
+ match /*bad*/copy i.node {
ast::item_fn(decl, _, tps, _) => {
let input_cnt = vec::len(decl.inputs);
let no_output = match decl.output.node {
}
fn is_ignored(cx: test_ctxt, i: @ast::item) -> bool {
- let ignoreattrs = attr::find_attrs_by_name(i.attrs, ~"ignore");
+ let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
let ignoreitems = attr::attr_metas(ignoreattrs);
let cfg_metas = vec::concat(vec::filter_map(ignoreitems,
|i| attr::get_meta_item_list(*i)));
return if vec::is_not_empty(ignoreitems) {
- config::metas_in_cfg(cx.crate.node.config, cfg_metas)
+ config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
} else {
false
}
vec::len(attr::find_attrs_by_name(i.attrs, ~"should_fail")) > 0u
}
-fn add_test_module(cx: test_ctxt, m: ast::_mod) -> ast::_mod {
+fn add_test_module(cx: test_ctxt, +m: ast::_mod) -> ast::_mod {
let testmod = mk_test_module(cx);
- return {items: vec::append_one(m.items, testmod),.. m};
+ return {items: vec::append_one(/*bad*/copy m.items, testmod),.. m};
}
/*
*/
fn mk_test_module(cx: test_ctxt) -> @ast::item {
+ // Link to std
+ let std = mk_std(cx);
+ let view_items = if is_std(cx) { ~[] } else { ~[std] };
// A function that generates a vector of test descriptors to feed to the
// test runner
let testsfn = mk_tests(cx);
// The synthesized main function which will call the console test runner
// with our list of tests
let mainfn = mk_main(cx);
- let testmod: ast::_mod = {view_items: ~[], items: ~[mainfn, testsfn]};
+ let testmod: ast::_mod = {
+ view_items: view_items, items: ~[mainfn, testsfn]
+ };
let item_ = ast::item_mod(testmod);
// This attribute tells resolve to let us call unexported functions
let resolve_unexported_attr =
span: dummy_sp()};
debug!("Synthetic test module:\n%s\n",
- pprust::item_to_str(@item, cx.sess.intr()));
+ pprust::item_to_str(@copy item, cx.sess.intr()));
return @item;
}
fn nospan<T: Copy>(t: T) -> ast::spanned<T> {
- return {node: t, span: dummy_sp()};
+ ast::spanned { node: t, span: dummy_sp() }
}
-fn path_node(ids: ~[ast::ident]) -> @ast::path {
+fn path_node(+ids: ~[ast::ident]) -> @ast::path {
@{span: dummy_sp(), global: false, idents: ids, rp: None, types: ~[]}
}
+fn path_node_global(+ids: ~[ast::ident]) -> @ast::path {
+ @{span: dummy_sp(), global: true, idents: ids, rp: None, types: ~[]}
+}
+
+fn mk_std(cx: test_ctxt) -> @ast::view_item {
+ let vers = ast::lit_str(@~"0.6");
+ let vers = nospan(vers);
+ let mi = ast::meta_name_value(~"vers", vers);
+ let mi = nospan(mi);
+ let vi = ast::view_item_use(cx.sess.ident_of(~"std"),
+ ~[@mi],
+ cx.sess.next_node_id());
+ let vi = {
+ node: vi,
+ attrs: ~[],
+ vis: ast::private,
+ span: dummy_sp()
+ };
+
+ return @vi;
+}
+
fn mk_tests(cx: test_ctxt) -> @ast::item {
let ret_ty = mk_test_desc_vec_ty(cx);
return @item;
}
-fn mk_path(cx: test_ctxt, path: ~[ast::ident]) -> ~[ast::ident] {
- // For tests that are inside of std we don't want to prefix
- // the paths with std::
+fn is_std(cx: test_ctxt) -> bool {
let is_std = {
- let items = attr::find_linkage_metas(cx.crate.node.attrs);
+ let items = attr::find_linkage_metas(/*bad*/copy cx.crate.node.attrs);
match attr::last_meta_item_value_str_by_name(items, ~"name") {
Some(~"std") => true,
_ => false
}
};
- if is_std { path }
- else { vec::append(~[cx.sess.ident_of(~"std")], path) }
+ return is_std;
+}
+
+fn mk_path(cx: test_ctxt, +path: ~[ast::ident]) -> @ast::path {
+ // For tests that are inside of std we don't want to prefix
+ // the paths with std::
+ if is_std(cx) { path_node_global(path) }
+ else {
+ path_node(
+ ~[cx.sess.ident_of(~"self"),
+ cx.sess.ident_of(~"std")]
+ + path)
+ }
}
// The ast::Ty of ~[std::test::test_desc]
fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty {
let test_desc_ty_path =
- path_node(mk_path(cx, ~[cx.sess.ident_of(~"test"),
- cx.sess.ident_of(~"TestDesc")]));
+ mk_path(cx, ~[cx.sess.ident_of(~"test"),
+ cx.sess.ident_of(~"TestDesc")]);
let test_desc_ty: ast::Ty =
{id: cx.sess.next_node_id(),
fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
let span = test.span;
- let path = test.path;
+ let path = /*bad*/copy test.path;
debug!("encoding %s", ast_util::path_name_i(path,
cx.sess.parse_sess.interner));
let name_lit: ast::lit =
- nospan(ast::lit_str(@ast_util::path_name_i(path, cx.sess.parse_sess
- .interner)));
+ nospan(ast::lit_str(@ast_util::path_name_i(
+ path, cx.sess.parse_sess.interner)));
let name_expr_inner: @ast::expr =
@{id: cx.sess.next_node_id(),
callee_id: cx.sess.next_node_id(),
nospan({mutbl: ast::m_imm, ident: cx.sess.ident_of(~"name"),
expr: @name_expr});
- let fn_path = path_node(path);
+ let fn_path = path_node_global(path);
let fn_expr: ast::expr =
{id: cx.sess.next_node_id(),
ident: cx.sess.ident_of(~"should_fail"),
expr: @fail_expr});
+ let test_desc_path =
+ mk_path(cx, ~[cx.sess.ident_of(~"test"),
+ cx.sess.ident_of(~"TestDesc")]);
+
let desc_rec_: ast::expr_ =
- ast::expr_rec(~[name_field, fn_field, ignore_field, fail_field],
+ ast::expr_struct(
+ test_desc_path,
+ ~[name_field, fn_field, ignore_field, fail_field],
option::None);
let desc_rec: ast::expr =
{id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(),
// FIXME (#1281): This can go away once fn is the type of bare function.
fn mk_test_wrapper(cx: test_ctxt,
- fn_path_expr: ast::expr,
+ +fn_path_expr: ast::expr,
span: span) -> @ast::expr {
let call_expr: ast::expr = {
id: cx.sess.next_node_id(),
let body_: ast::blk_ =
default_block(~[], option::Some(test_main_call_expr),
cx.sess.next_node_id());
- let body = {node: body_, span: dummy_sp()};
+ let body = ast::spanned { node: body_, span: dummy_sp() };
let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
let item: ast::item =
fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
// Call os::args to generate the vector of test_descs
- let args_path = path_node(~[
+ let args_path = path_node_global(~[
cx.sess.ident_of(~"os"),
cx.sess.ident_of(~"args")
]);
node: test_call_expr_, span: dummy_sp()};
// Call std::test::test_main
- let test_main_path = path_node(
+ let test_main_path =
mk_path(cx, ~[cx.sess.ident_of(~"test"),
- cx.sess.ident_of(~"test_main")]));
+ cx.sess.ident_of(~"test_main")]);
let test_main_path_expr_: ast::expr_ = ast::expr_path(test_main_path);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use core::cast;
+use core::cmp;
+use core::int;
+use core::io;
+use core::libc::{c_char, c_int, c_uint, c_longlong, c_ulonglong};
+use core::option;
+use core::ptr;
+use core::str;
+use core::uint;
+use core::vec;
use std::map::HashMap;
-use libc::{c_char, c_int, c_uint, c_longlong, c_ulonglong};
-
type Opcode = u32;
type Bool = c_uint;
+
const True: Bool = 1 as Bool;
const False: Bool = 0 as Bool;
extern mod llvm {
#[legacy_exports];
/* Create and destroy contexts. */
- fn LLVMContextCreate() -> ContextRef;
- fn LLVMGetGlobalContext() -> ContextRef;
- fn LLVMContextDispose(C: ContextRef);
- fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *c_char, SLen: c_uint) ->
- c_uint;
- fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint;
+ unsafe fn LLVMContextCreate() -> ContextRef;
+ unsafe fn LLVMGetGlobalContext() -> ContextRef;
+ unsafe fn LLVMContextDispose(C: ContextRef);
+ unsafe fn LLVMGetMDKindIDInContext(C: ContextRef,
+ Name: *c_char,
+ SLen: c_uint)
+ -> c_uint;
+ unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint;
/* Create and destroy modules. */
- fn LLVMModuleCreateWithNameInContext(ModuleID: *c_char, C: ContextRef) ->
- ModuleRef;
- fn LLVMDisposeModule(M: ModuleRef);
+ unsafe fn LLVMModuleCreateWithNameInContext(ModuleID: *c_char,
+ C: ContextRef)
+ -> ModuleRef;
+ unsafe fn LLVMDisposeModule(M: ModuleRef);
/** Data layout. See Module::getDataLayout. */
- fn LLVMGetDataLayout(M: ModuleRef) -> *c_char;
- fn LLVMSetDataLayout(M: ModuleRef, Triple: *c_char);
+ unsafe fn LLVMGetDataLayout(M: ModuleRef) -> *c_char;
+ unsafe fn LLVMSetDataLayout(M: ModuleRef, Triple: *c_char);
/** Target triple. See Module::getTargetTriple. */
- fn LLVMGetTarget(M: ModuleRef) -> *c_char;
- fn LLVMSetTarget(M: ModuleRef, Triple: *c_char);
+ unsafe fn LLVMGetTarget(M: ModuleRef) -> *c_char;
+ unsafe fn LLVMSetTarget(M: ModuleRef, Triple: *c_char);
/** See Module::dump. */
- fn LLVMDumpModule(M: ModuleRef);
+ unsafe fn LLVMDumpModule(M: ModuleRef);
/** See Module::setModuleInlineAsm. */
- fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *c_char);
+ unsafe fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *c_char);
/** See llvm::LLVMTypeKind::getTypeID. */
- fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind;
+ unsafe fn LLVMGetTypeKind(Ty: TypeRef) -> TypeKind;
/** See llvm::LLVMType::getContext. */
- fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
+ unsafe fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
/* Operations on integer types */
- fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef;
-
- fn LLVMInt1Type() -> TypeRef;
- fn LLVMInt8Type() -> TypeRef;
- fn LLVMInt16Type() -> TypeRef;
- fn LLVMInt32Type() -> TypeRef;
- fn LLVMInt64Type() -> TypeRef;
- fn LLVMIntType(NumBits: c_uint) -> TypeRef;
- fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
+ unsafe fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef;
+
+ unsafe fn LLVMInt1Type() -> TypeRef;
+ unsafe fn LLVMInt8Type() -> TypeRef;
+ unsafe fn LLVMInt16Type() -> TypeRef;
+ unsafe fn LLVMInt32Type() -> TypeRef;
+ unsafe fn LLVMInt64Type() -> TypeRef;
+ unsafe fn LLVMIntType(NumBits: c_uint) -> TypeRef;
+ unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
/* Operations on real types */
- fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
-
- fn LLVMFloatType() -> TypeRef;
- fn LLVMDoubleType() -> TypeRef;
- fn LLVMX86FP80Type() -> TypeRef;
- fn LLVMFP128Type() -> TypeRef;
- fn LLVMPPCFP128Type() -> TypeRef;
+ unsafe fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMX86FP80TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMFP128TypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
+
+ unsafe fn LLVMFloatType() -> TypeRef;
+ unsafe fn LLVMDoubleType() -> TypeRef;
+ unsafe fn LLVMX86FP80Type() -> TypeRef;
+ unsafe fn LLVMFP128Type() -> TypeRef;
+ unsafe fn LLVMPPCFP128Type() -> TypeRef;
/* Operations on function types */
- fn LLVMFunctionType(ReturnType: TypeRef, ParamTypes: *TypeRef,
+ unsafe fn LLVMFunctionType(ReturnType: TypeRef, ParamTypes: *TypeRef,
ParamCount: c_uint, IsVarArg: Bool) -> TypeRef;
- fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
- fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
- fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
- fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *TypeRef);
+ unsafe fn LLVMIsFunctionVarArg(FunctionTy: TypeRef) -> Bool;
+ unsafe fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef;
+ unsafe fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint;
+ unsafe fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *TypeRef);
/* Operations on struct types */
- fn LLVMStructTypeInContext(C: ContextRef, ElementTypes: *TypeRef,
+ unsafe fn LLVMStructTypeInContext(C: ContextRef, ElementTypes: *TypeRef,
ElementCount: c_uint,
Packed: Bool) -> TypeRef;
- fn LLVMStructType(ElementTypes: *TypeRef, ElementCount: c_uint,
+ unsafe fn LLVMStructType(ElementTypes: *TypeRef, ElementCount: c_uint,
Packed: Bool) -> TypeRef;
- fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
- fn LLVMGetStructElementTypes(StructTy: TypeRef, Dest: *mut TypeRef);
- fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
+ unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
+ unsafe fn LLVMGetStructElementTypes(StructTy: TypeRef,
+ Dest: *mut TypeRef);
+ unsafe fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
/* Operations on array, pointer, and vector types (sequence types) */
- fn LLVMArrayType(ElementType: TypeRef,
+ unsafe fn LLVMArrayType(ElementType: TypeRef,
ElementCount: c_uint) -> TypeRef;
- fn LLVMPointerType(ElementType: TypeRef,
+ unsafe fn LLVMPointerType(ElementType: TypeRef,
AddressSpace: c_uint) -> TypeRef;
- fn LLVMVectorType(ElementType: TypeRef,
+ unsafe fn LLVMVectorType(ElementType: TypeRef,
ElementCount: c_uint) -> TypeRef;
- fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
- fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
- fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
- fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
+ unsafe fn LLVMGetElementType(Ty: TypeRef) -> TypeRef;
+ unsafe fn LLVMGetArrayLength(ArrayTy: TypeRef) -> c_uint;
+ unsafe fn LLVMGetPointerAddressSpace(PointerTy: TypeRef) -> c_uint;
+ unsafe fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint;
/* Operations on other types */
- fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMLabelTypeInContext(C: ContextRef) -> TypeRef;
+ unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
- fn LLVMVoidType() -> TypeRef;
- fn LLVMLabelType() -> TypeRef;
- fn LLVMMetadataType() -> TypeRef;
+ unsafe fn LLVMVoidType() -> TypeRef;
+ unsafe fn LLVMLabelType() -> TypeRef;
+ unsafe fn LLVMMetadataType() -> TypeRef;
/* Operations on all values */
- fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
- fn LLVMGetValueName(Val: ValueRef) -> *c_char;
- fn LLVMSetValueName(Val: ValueRef, Name: *c_char);
- fn LLVMDumpValue(Val: ValueRef);
- fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
- fn LLVMHasMetadata(Val: ValueRef) -> c_int;
- fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef;
- fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
+ unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
+ unsafe fn LLVMGetValueName(Val: ValueRef) -> *c_char;
+ unsafe fn LLVMSetValueName(Val: ValueRef, Name: *c_char);
+ unsafe fn LLVMDumpValue(Val: ValueRef);
+ unsafe fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef);
+ unsafe fn LLVMHasMetadata(Val: ValueRef) -> c_int;
+ unsafe fn LLVMGetMetadata(Val: ValueRef, KindID: c_uint) -> ValueRef;
+ unsafe fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef);
/* Operations on Uses */
- fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
- fn LLVMGetNextUse(U: UseRef) -> UseRef;
- fn LLVMGetUser(U: UseRef) -> ValueRef;
- fn LLVMGetUsedValue(U: UseRef) -> ValueRef;
+ unsafe fn LLVMGetFirstUse(Val: ValueRef) -> UseRef;
+ unsafe fn LLVMGetNextUse(U: UseRef) -> UseRef;
+ unsafe fn LLVMGetUser(U: UseRef) -> ValueRef;
+ unsafe fn LLVMGetUsedValue(U: UseRef) -> ValueRef;
/* Operations on Users */
- fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
- fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef);
+ unsafe fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef;
+ unsafe fn LLVMSetOperand(Val: ValueRef, Index: c_uint, Op: ValueRef);
/* Operations on constants of any type */
- fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
+ unsafe fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
/* all zeroes */
- fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
+ unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef;
/* only for int/vector */
- fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
- fn LLVMIsConstant(Val: ValueRef) -> Bool;
- fn LLVMIsNull(Val: ValueRef) -> Bool;
- fn LLVMIsUndef(Val: ValueRef) -> Bool;
- fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef;
+ unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef;
+ unsafe fn LLVMIsConstant(Val: ValueRef) -> Bool;
+ unsafe fn LLVMIsNull(Val: ValueRef) -> Bool;
+ unsafe fn LLVMIsUndef(Val: ValueRef) -> Bool;
+ unsafe fn LLVMConstPointerNull(Ty: TypeRef) -> ValueRef;
/* Operations on metadata */
- fn LLVMMDStringInContext(C: ContextRef, Str: *c_char, SLen: c_uint) ->
- ValueRef;
- fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef;
- fn LLVMMDNodeInContext(C: ContextRef, Vals: *ValueRef, Count: c_uint) ->
- ValueRef;
- fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef;
- fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char,
+ unsafe fn LLVMMDStringInContext(C: ContextRef,
+ Str: *c_char,
+ SLen: c_uint)
+ -> ValueRef;
+ unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef;
+ unsafe fn LLVMMDNodeInContext(C: ContextRef,
+ Vals: *ValueRef,
+ Count: c_uint)
+ -> ValueRef;
+ unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef;
+ unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char,
Val: ValueRef);
/* Operations on scalar constants */
- fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) ->
- ValueRef;
- fn LLVMConstIntOfString(IntTy: TypeRef, Text: *c_char, Radix: u8) ->
- ValueRef;
- fn LLVMConstIntOfStringAndSize(IntTy: TypeRef, Text: *c_char,
+ unsafe fn LLVMConstInt(IntTy: TypeRef,
+ N: c_ulonglong,
+ SignExtend: Bool)
+ -> ValueRef;
+ unsafe fn LLVMConstIntOfString(IntTy: TypeRef,
+ Text: *c_char,
+ Radix: u8)
+ -> ValueRef;
+ unsafe fn LLVMConstIntOfStringAndSize(IntTy: TypeRef, Text: *c_char,
SLen: c_uint,
Radix: u8) -> ValueRef;
- fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
- fn LLVMConstRealOfString(RealTy: TypeRef, Text: *c_char) -> ValueRef;
- fn LLVMConstRealOfStringAndSize(RealTy: TypeRef, Text: *c_char,
+ unsafe fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
+ unsafe fn LLVMConstRealOfString(RealTy: TypeRef,
+ Text: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMConstRealOfStringAndSize(RealTy: TypeRef, Text: *c_char,
SLen: c_uint) -> ValueRef;
- fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
- fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
+ unsafe fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
+ unsafe fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
/* Operations on composite constants */
- fn LLVMConstStringInContext(C: ContextRef, Str: *c_char, Length: c_uint,
- DontNullTerminate: Bool) -> ValueRef;
- fn LLVMConstStructInContext(C: ContextRef, ConstantVals: *ValueRef,
+ unsafe fn LLVMConstStringInContext(C: ContextRef,
+ Str: *c_char,
+ Length: c_uint,
+ DontNullTerminate: Bool)
+ -> ValueRef;
+ unsafe fn LLVMConstStructInContext(C: ContextRef, ConstantVals: *ValueRef,
Count: c_uint, Packed: Bool) -> ValueRef;
- fn LLVMConstString(Str: *c_char, Length: c_uint,
+ unsafe fn LLVMConstString(Str: *c_char, Length: c_uint,
DontNullTerminate: Bool) -> ValueRef;
- fn LLVMConstArray(ElementTy: TypeRef, ConstantVals: *ValueRef,
+ unsafe fn LLVMConstArray(ElementTy: TypeRef, ConstantVals: *ValueRef,
Length: c_uint) -> ValueRef;
- fn LLVMConstStruct(ConstantVals: *ValueRef,
+ unsafe fn LLVMConstStruct(ConstantVals: *ValueRef,
Count: c_uint, Packed: Bool) -> ValueRef;
- fn LLVMConstVector(ScalarConstantVals: *ValueRef,
+ unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef,
Size: c_uint) -> ValueRef;
/* Constant expressions */
- fn LLVMAlignOf(Ty: TypeRef) -> ValueRef;
- fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
- fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
- fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef;
- fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef;
- fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
- fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
- fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstNSWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstNUWAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstNSWSub(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstNUWSub(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstNSWMul(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstNUWMul(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstExactSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
- ValueRef;
- fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
+ unsafe fn LLVMAlignOf(Ty: TypeRef) -> ValueRef;
+ unsafe fn LLVMSizeOf(Ty: TypeRef) -> ValueRef;
+ unsafe fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef;
+ unsafe fn LLVMConstNSWNeg(ConstantVal: ValueRef) -> ValueRef;
+ unsafe fn LLVMConstNUWNeg(ConstantVal: ValueRef) -> ValueRef;
+ unsafe fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef;
+ unsafe fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef;
+ unsafe fn LLVMConstAdd(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstNSWAdd(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstNUWAdd(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFAdd(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSub(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstNSWSub(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstNUWSub(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
ValueRef;
- fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef;
- fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
+ unsafe fn LLVMConstMul(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstNSWMul(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstNUWMul(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFMul(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstUDiv(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSDiv(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstExactSDiv(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFDiv(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstURem(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSRem(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFRem(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstAnd(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstOr(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstXor(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstShl(LHSConstant: ValueRef,
+ RHSConstant: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
ValueRef;
- fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
+ unsafe fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) ->
ValueRef;
- fn LLVMConstGEP(ConstantVal: ValueRef,
+ unsafe fn LLVMConstGEP(ConstantVal: ValueRef,
ConstantIndices: *ValueRef,
NumIndices: c_uint) -> ValueRef;
- fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
- ConstantIndices: *ValueRef,
- NumIndices: c_uint) -> ValueRef;
- fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstSExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstFPTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstFPExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) ->
- ValueRef;
- fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) ->
- ValueRef;
- fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef, ToType: TypeRef) ->
- ValueRef;
- fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) ->
- ValueRef;
- fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef,
+ unsafe fn LLVMConstInBoundsGEP(ConstantVal: ValueRef,
+ ConstantIndices: *ValueRef,
+ NumIndices: c_uint)
+ -> ValueRef;
+ unsafe fn LLVMConstTrunc(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSExt(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstZExt(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFPTrunc(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFPExt(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstUIToFP(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSIToFP(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFPToUI(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstFPToSI(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstPtrToInt(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstIntToPtr(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstBitCast(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstZExtOrBitCast(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSExtOrBitCast(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstTruncOrBitCast(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstPointerCast(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef,
isSigned: Bool) -> ValueRef;
- fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef;
- fn LLVMConstSelect(ConstantCondition: ValueRef, ConstantIfTrue: ValueRef,
- ConstantIfFalse: ValueRef) -> ValueRef;
- fn LLVMConstExtractElement(VectorConstant: ValueRef,
+ unsafe fn LLVMConstFPCast(ConstantVal: ValueRef,
+ ToType: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMConstSelect(ConstantCondition: ValueRef,
+ ConstantIfTrue: ValueRef,
+ ConstantIfFalse: ValueRef)
+ -> ValueRef;
+ unsafe fn LLVMConstExtractElement(VectorConstant: ValueRef,
IndexConstant: ValueRef) -> ValueRef;
- fn LLVMConstInsertElement(VectorConstant: ValueRef,
+ unsafe fn LLVMConstInsertElement(VectorConstant: ValueRef,
ElementValueConstant: ValueRef,
IndexConstant: ValueRef) -> ValueRef;
- fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
+ unsafe fn LLVMConstShuffleVector(VectorAConstant: ValueRef,
VectorBConstant: ValueRef,
MaskConstant: ValueRef) -> ValueRef;
- fn LLVMConstExtractValue(AggConstant: ValueRef, IdxList: *c_uint,
+ unsafe fn LLVMConstExtractValue(AggConstant: ValueRef, IdxList: *c_uint,
NumIdx: c_uint) -> ValueRef;
- fn LLVMConstInsertValue(AggConstant: ValueRef,
+ unsafe fn LLVMConstInsertValue(AggConstant: ValueRef,
ElementValueConstant: ValueRef, IdxList: *c_uint,
NumIdx: c_uint) -> ValueRef;
- fn LLVMConstInlineAsm(Ty: TypeRef, AsmString: *c_char,
+ unsafe fn LLVMConstInlineAsm(Ty: TypeRef, AsmString: *c_char,
Constraints: *c_char, HasSideEffects: Bool,
IsAlignStack: Bool) -> ValueRef;
- fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef;
+ unsafe fn LLVMBlockAddress(F: ValueRef, BB: BasicBlockRef) -> ValueRef;
/* Operations on global variables, functions, and aliases (globals) */
- fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
- fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
- fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
- fn LLVMSetLinkage(Global: ValueRef, Link: c_uint);
- fn LLVMGetSection(Global: ValueRef) -> *c_char;
- fn LLVMSetSection(Global: ValueRef, Section: *c_char);
- fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
- fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint);
- fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
- fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
+ unsafe fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
+ unsafe fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
+ unsafe fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
+ unsafe fn LLVMSetLinkage(Global: ValueRef, Link: c_uint);
+ unsafe fn LLVMGetSection(Global: ValueRef) -> *c_char;
+ unsafe fn LLVMSetSection(Global: ValueRef, Section: *c_char);
+ unsafe fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
+ unsafe fn LLVMSetVisibility(Global: ValueRef, Viz: c_uint);
+ unsafe fn LLVMGetAlignment(Global: ValueRef) -> c_uint;
+ unsafe fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint);
/* Operations on global variables */
- fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *c_char) -> ValueRef;
- fn LLVMAddGlobalInAddressSpace(M: ModuleRef, Ty: TypeRef, Name: *c_char,
- AddressSpace: c_uint) -> ValueRef;
- fn LLVMGetNamedGlobal(M: ModuleRef, Name: *c_char) -> ValueRef;
- fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
- fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef;
- fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
- fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef;
- fn LLVMDeleteGlobal(GlobalVar: ValueRef);
- fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
- fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
- fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool;
- fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
- fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
- fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
+ unsafe fn LLVMAddGlobal(M: ModuleRef,
+ Ty: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMAddGlobalInAddressSpace(M: ModuleRef,
+ Ty: TypeRef,
+ Name: *c_char,
+ AddressSpace: c_uint)
+ -> ValueRef;
+ unsafe fn LLVMGetNamedGlobal(M: ModuleRef, Name: *c_char) -> ValueRef;
+ unsafe fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef;
+ unsafe fn LLVMGetLastGlobal(M: ModuleRef) -> ValueRef;
+ unsafe fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetPreviousGlobal(GlobalVar: ValueRef) -> ValueRef;
+ unsafe fn LLVMDeleteGlobal(GlobalVar: ValueRef);
+ unsafe fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
+ unsafe fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
+ unsafe fn LLVMIsThreadLocal(GlobalVar: ValueRef) -> Bool;
+ unsafe fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
+ unsafe fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
+ unsafe fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
/* Operations on aliases */
- fn LLVMAddAlias(M: ModuleRef, Ty: TypeRef, Aliasee: ValueRef,
+ unsafe fn LLVMAddAlias(M: ModuleRef, Ty: TypeRef, Aliasee: ValueRef,
Name: *c_char) -> ValueRef;
/* Operations on functions */
- fn LLVMAddFunction(M: ModuleRef, Name: *c_char, FunctionTy: TypeRef) ->
- ValueRef;
- fn LLVMGetNamedFunction(M: ModuleRef, Name: *c_char) -> ValueRef;
- fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
- fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef;
- fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
- fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef;
- fn LLVMDeleteFunction(Fn: ValueRef);
- fn LLVMGetOrInsertFunction(M: ModuleRef, Name: *c_char,
+ unsafe fn LLVMAddFunction(M: ModuleRef,
+ Name: *c_char,
+ FunctionTy: TypeRef)
+ -> ValueRef;
+ unsafe fn LLVMGetNamedFunction(M: ModuleRef, Name: *c_char) -> ValueRef;
+ unsafe fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef;
+ unsafe fn LLVMGetLastFunction(M: ModuleRef) -> ValueRef;
+ unsafe fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetPreviousFunction(Fn: ValueRef) -> ValueRef;
+ unsafe fn LLVMDeleteFunction(Fn: ValueRef);
+ unsafe fn LLVMGetOrInsertFunction(M: ModuleRef, Name: *c_char,
FunctionTy: TypeRef) -> ValueRef;
- fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint;
- fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint;
- fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
- fn LLVMGetGC(Fn: ValueRef) -> *c_char;
- fn LLVMSetGC(Fn: ValueRef, Name: *c_char);
- fn LLVMAddFunctionAttr(Fn: ValueRef, PA: c_ulonglong, HighPA:
+ unsafe fn LLVMGetIntrinsicID(Fn: ValueRef) -> c_uint;
+ unsafe fn LLVMGetFunctionCallConv(Fn: ValueRef) -> c_uint;
+ unsafe fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
+ unsafe fn LLVMGetGC(Fn: ValueRef) -> *c_char;
+ unsafe fn LLVMSetGC(Fn: ValueRef, Name: *c_char);
+ unsafe fn LLVMAddFunctionAttr(Fn: ValueRef, PA: c_ulonglong, HighPA:
c_ulonglong);
- fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
- fn LLVMRemoveFunctionAttr(Fn: ValueRef, PA: c_ulonglong, HighPA:
+ unsafe fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
+ unsafe fn LLVMRemoveFunctionAttr(Fn: ValueRef, PA: c_ulonglong, HighPA:
c_ulonglong);
/* Operations on parameters */
- fn LLVMCountParams(Fn: ValueRef) -> c_uint;
- fn LLVMGetParams(Fn: ValueRef, Params: *ValueRef);
- fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
- fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef;
- fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef;
- fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
- fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
- fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
- fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
- fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
- fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
- fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
+ unsafe fn LLVMCountParams(Fn: ValueRef) -> c_uint;
+ unsafe fn LLVMGetParams(Fn: ValueRef, Params: *ValueRef);
+ unsafe fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef;
+ unsafe fn LLVMGetParamParent(Inst: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetFirstParam(Fn: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
+ unsafe fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
+ unsafe fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
+ unsafe fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
+ unsafe fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
/* Operations on basic blocks */
- fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
- fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool;
- fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef;
- fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
- fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint;
- fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *ValueRef);
- fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
- fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef;
- fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
- fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
- fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef;
-
- fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef,
+ unsafe fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef;
+ unsafe fn LLVMValueIsBasicBlock(Val: ValueRef) -> Bool;
+ unsafe fn LLVMValueAsBasicBlock(Val: ValueRef) -> BasicBlockRef;
+ unsafe fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef;
+ unsafe fn LLVMCountBasicBlocks(Fn: ValueRef) -> c_uint;
+ unsafe fn LLVMGetBasicBlocks(Fn: ValueRef, BasicBlocks: *ValueRef);
+ unsafe fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+ unsafe fn LLVMGetLastBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+ unsafe fn LLVMGetNextBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
+ unsafe fn LLVMGetPreviousBasicBlock(BB: BasicBlockRef) -> BasicBlockRef;
+ unsafe fn LLVMGetEntryBasicBlock(Fn: ValueRef) -> BasicBlockRef;
+
+ unsafe fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef,
Name: *c_char) -> BasicBlockRef;
- fn LLVMInsertBasicBlockInContext(C: ContextRef, BB: BasicBlockRef,
+ unsafe fn LLVMInsertBasicBlockInContext(C: ContextRef, BB: BasicBlockRef,
Name: *c_char) -> BasicBlockRef;
- fn LLVMAppendBasicBlock(Fn: ValueRef, Name: *c_char) -> BasicBlockRef;
- fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef, Name: *c_char) ->
- BasicBlockRef;
- fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
+ unsafe fn LLVMAppendBasicBlock(Fn: ValueRef,
+ Name: *c_char)
+ -> BasicBlockRef;
+ unsafe fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef,
+ Name: *c_char)
+ -> BasicBlockRef;
+ unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
/* Operations on instructions */
- fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
- fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
- fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef;
- fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
- fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef;
+ unsafe fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef;
+ unsafe fn LLVMGetLastInstruction(BB: BasicBlockRef) -> ValueRef;
+ unsafe fn LLVMGetNextInstruction(Inst: ValueRef) -> ValueRef;
+ unsafe fn LLVMGetPreviousInstruction(Inst: ValueRef) -> ValueRef;
/* Operations on call sites */
- fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
- fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint;
- fn LLVMAddInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint);
- fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint,
+ unsafe fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint);
+ unsafe fn LLVMGetInstructionCallConv(Instr: ValueRef) -> c_uint;
+ unsafe fn LLVMAddInstrAttribute(Instr: ValueRef,
+ index: c_uint,
+ IA: c_uint);
+ unsafe fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint,
IA: c_uint);
- fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint,
+ unsafe fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint,
align: c_uint);
/* Operations on call instructions (only) */
- fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
- fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
+ unsafe fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
+ unsafe fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool);
/* Operations on phi nodes */
- fn LLVMAddIncoming(PhiNode: ValueRef, IncomingValues: *ValueRef,
+ unsafe fn LLVMAddIncoming(PhiNode: ValueRef, IncomingValues: *ValueRef,
IncomingBlocks: *BasicBlockRef, Count: c_uint);
- fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint;
- fn LLVMGetIncomingValue(PhiNode: ValueRef, Index: c_uint) -> ValueRef;
- fn LLVMGetIncomingBlock(PhiNode: ValueRef,
+ unsafe fn LLVMCountIncoming(PhiNode: ValueRef) -> c_uint;
+ unsafe fn LLVMGetIncomingValue(PhiNode: ValueRef,
+ Index: c_uint)
+ -> ValueRef;
+ unsafe fn LLVMGetIncomingBlock(PhiNode: ValueRef,
Index: c_uint) -> BasicBlockRef;
/* Instruction builders */
- fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
- fn LLVMCreateBuilder() -> BuilderRef;
- fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef,
+ unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
+ unsafe fn LLVMCreateBuilder() -> BuilderRef;
+ unsafe fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef,
Instr: ValueRef);
- fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef);
- fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef);
- fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
- fn LLVMClearInsertionPosition(Builder: BuilderRef);
- fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef);
- fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef, Instr: ValueRef,
- Name: *c_char);
- fn LLVMDisposeBuilder(Builder: BuilderRef);
+ unsafe fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef);
+ unsafe fn LLVMPositionBuilderAtEnd(Builder: BuilderRef,
+ Block: BasicBlockRef);
+ unsafe fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef;
+ unsafe fn LLVMClearInsertionPosition(Builder: BuilderRef);
+ unsafe fn LLVMInsertIntoBuilder(Builder: BuilderRef, Instr: ValueRef);
+ unsafe fn LLVMInsertIntoBuilderWithName(Builder: BuilderRef,
+ Instr: ValueRef,
+ Name: *c_char);
+ unsafe fn LLVMDisposeBuilder(Builder: BuilderRef);
/* Metadata */
- fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
- fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
- fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
+ unsafe fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef);
+ unsafe fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef;
+ unsafe fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef);
/* Terminators */
- fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
- fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
- fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *ValueRef,
+ unsafe fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef;
+ unsafe fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef;
+ unsafe fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *ValueRef,
N: c_uint) -> ValueRef;
- fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
- fn LLVMBuildCondBr(B: BuilderRef, If: ValueRef, Then: BasicBlockRef,
- Else: BasicBlockRef) -> ValueRef;
- fn LLVMBuildSwitch(B: BuilderRef, V: ValueRef, Else: BasicBlockRef,
+ unsafe fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef;
+ unsafe fn LLVMBuildCondBr(B: BuilderRef,
+ If: ValueRef,
+ Then: BasicBlockRef,
+ Else: BasicBlockRef)
+ -> ValueRef;
+ unsafe fn LLVMBuildSwitch(B: BuilderRef, V: ValueRef, Else: BasicBlockRef,
NumCases: c_uint) -> ValueRef;
- fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef,
+ unsafe fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef,
NumDests: c_uint) -> ValueRef;
- fn LLVMBuildInvoke(B: BuilderRef, Fn: ValueRef, Args: *ValueRef,
+ unsafe fn LLVMBuildInvoke(B: BuilderRef, Fn: ValueRef, Args: *ValueRef,
NumArgs: c_uint, Then: BasicBlockRef,
Catch: BasicBlockRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildLandingPad(B: BuilderRef, Ty: TypeRef, PersFn: ValueRef,
- NumClauses: c_uint, Name: *c_char) -> ValueRef;
- fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
- fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
+ unsafe fn LLVMBuildLandingPad(B: BuilderRef,
+ Ty: TypeRef,
+ PersFn: ValueRef,
+ NumClauses: c_uint,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
+ unsafe fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;
/* Add a case to the switch instruction */
- fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef);
+ unsafe fn LLVMAddCase(Switch: ValueRef,
+ OnVal: ValueRef,
+ Dest: BasicBlockRef);
/* Add a destination to the indirectbr instruction */
- fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef);
+ unsafe fn LLVMAddDestination(IndirectBr: ValueRef, Dest: BasicBlockRef);
/* Add a clause to the landing pad instruction */
- fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
+ unsafe fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef);
/* Set the cleanup on a landing pad instruction */
- fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
+ unsafe fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool);
/* Arithmetic */
- fn LLVMBuildAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildNSWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildNSWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildNUWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildNUWAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildFAdd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildNSWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildNSWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildNUWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildNUWSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildFSub(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildNSWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildNSWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildNUWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildNUWMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildFMul(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildUDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildUDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildExactSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildExactSDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildFDiv(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildURem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildURem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildSRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildSRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildFRem(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildShl(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildShl(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildLShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildLShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildAShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildAShr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildAnd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildAnd(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildOr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildOr(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildXor(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildXor(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildBinOp(B: BuilderRef, Op: Opcode, LHS: ValueRef, RHS: ValueRef,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *c_char) -> ValueRef;
+ unsafe fn LLVMBuildBinOp(B: BuilderRef,
+ Op: Opcode,
+ LHS: ValueRef,
+ RHS: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildNeg(B: BuilderRef,
+ V: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildNSWNeg(B: BuilderRef,
+ V: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildNUWNeg(B: BuilderRef,
+ V: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildFNeg(B: BuilderRef,
+ V: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildNot(B: BuilderRef,
+ V: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
/* Memory */
- fn LLVMBuildMalloc(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildArrayMalloc(B: BuilderRef, Ty: TypeRef, Val: ValueRef,
+ unsafe fn LLVMBuildMalloc(B: BuilderRef,
+ Ty: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildArrayMalloc(B: BuilderRef, Ty: TypeRef, Val: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildArrayAlloca(B: BuilderRef, Ty: TypeRef, Val: ValueRef,
+ unsafe fn LLVMBuildAlloca(B: BuilderRef,
+ Ty: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildArrayAlloca(B: BuilderRef, Ty: TypeRef, Val: ValueRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
- fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *c_char) ->
- ValueRef;
- fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) ->
+ unsafe fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef;
+ unsafe fn LLVMBuildLoad(B: BuilderRef,
+ PointerVal: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) ->
ValueRef;
- fn LLVMBuildGEP(B: BuilderRef, Pointer: ValueRef, Indices: *ValueRef,
- NumIndices: c_uint, Name: *c_char) -> ValueRef;
- fn LLVMBuildInBoundsGEP(B: BuilderRef, Pointer: ValueRef,
+ unsafe fn LLVMBuildGEP(B: BuilderRef,
+ Pointer: ValueRef,
+ Indices: *ValueRef,
+ NumIndices: c_uint,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildInBoundsGEP(B: BuilderRef, Pointer: ValueRef,
Indices: *ValueRef, NumIndices: c_uint,
Name: *c_char)
-> ValueRef;
- fn LLVMBuildStructGEP(B: BuilderRef, Pointer: ValueRef, Idx: c_uint,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildGlobalString(B: BuilderRef, Str: *c_char, Name: *c_char) ->
- ValueRef;
- fn LLVMBuildGlobalStringPtr(B: BuilderRef, Str: *c_char, Name: *c_char) ->
- ValueRef;
+ unsafe fn LLVMBuildStructGEP(B: BuilderRef,
+ Pointer: ValueRef,
+ Idx: c_uint,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildGlobalString(B: BuilderRef,
+ Str: *c_char,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildGlobalStringPtr(B: BuilderRef,
+ Str: *c_char,
+ Name: *c_char)
+ -> ValueRef;
/* Casts */
- fn LLVMBuildTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildZExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildZExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildSExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildSExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFPToUI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildFPToUI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFPToSI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildFPToSI(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildUIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildUIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildSIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildSIToFP(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFPTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildFPTrunc(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFPExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildFPExt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildPtrToInt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildPtrToInt(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildIntToPtr(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildIntToPtr(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildZExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildSExtOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildTruncOrBitCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildCast(B: BuilderRef, Op: Opcode, Val: ValueRef,
+ unsafe fn LLVMBuildZExtOrBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildSExtOrBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildTruncOrBitCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildCast(B: BuilderRef, Op: Opcode, Val: ValueRef,
DestTy: TypeRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildPointerCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildIntCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildPointerCast(B: BuilderRef,
+ Val: ValueRef,
+ DestTy: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildIntCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
- fn LLVMBuildFPCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
+ unsafe fn LLVMBuildFPCast(B: BuilderRef, Val: ValueRef, DestTy: TypeRef,
Name: *c_char) -> ValueRef;
/* Comparisons */
- fn LLVMBuildICmp(B: BuilderRef, Op: c_uint, LHS: ValueRef,
+ unsafe fn LLVMBuildICmp(B: BuilderRef, Op: c_uint, LHS: ValueRef,
RHS: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildFCmp(B: BuilderRef, Op: c_uint, LHS: ValueRef,
+ unsafe fn LLVMBuildFCmp(B: BuilderRef, Op: c_uint, LHS: ValueRef,
RHS: ValueRef, Name: *c_char) -> ValueRef;
/* Miscellaneous instructions */
- fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: *ValueRef,
+ unsafe fn LLVMBuildPhi(B: BuilderRef,
+ Ty: TypeRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: *ValueRef,
NumArgs: c_uint, Name: *c_char) -> ValueRef;
- fn LLVMBuildSelect(B: BuilderRef, If: ValueRef, Then: ValueRef,
+ unsafe fn LLVMBuildSelect(B: BuilderRef, If: ValueRef, Then: ValueRef,
Else: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildVAArg(B: BuilderRef, list: ValueRef, Ty: TypeRef,
+ unsafe fn LLVMBuildVAArg(B: BuilderRef, list: ValueRef, Ty: TypeRef,
Name: *c_char)
-> ValueRef;
- fn LLVMBuildExtractElement(B: BuilderRef, VecVal: ValueRef,
- Index: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildInsertElement(B: BuilderRef, VecVal: ValueRef,
- EltVal: ValueRef, Index: ValueRef,
- Name: *c_char)
- -> ValueRef;
- fn LLVMBuildShuffleVector(B: BuilderRef, V1: ValueRef, V2: ValueRef,
- Mask: ValueRef, Name: *c_char) -> ValueRef;
- fn LLVMBuildExtractValue(B: BuilderRef, AggVal: ValueRef, Index: c_uint,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildInsertValue(B: BuilderRef, AggVal: ValueRef, EltVal: ValueRef,
- Index: c_uint, Name: *c_char) -> ValueRef;
-
- fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef,
- Name: *c_char) -> ValueRef;
- fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *c_char) ->
- ValueRef;
- fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
+ unsafe fn LLVMBuildExtractElement(B: BuilderRef,
+ VecVal: ValueRef,
+ Index: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildInsertElement(B: BuilderRef,
+ VecVal: ValueRef,
+ EltVal: ValueRef,
+ Index: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildShuffleVector(B: BuilderRef,
+ V1: ValueRef,
+ V2: ValueRef,
+ Mask: ValueRef,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildExtractValue(B: BuilderRef,
+ AggVal: ValueRef,
+ Index: c_uint,
+ Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildInsertValue(B: BuilderRef,
+ AggVal: ValueRef,
+ EltVal: ValueRef,
+ Index: c_uint,
+ Name: *c_char)
+ -> ValueRef;
+
+ unsafe fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *c_char)
+ -> ValueRef;
+ unsafe fn LLVMBuildPtrDiff(B: BuilderRef, LHS: ValueRef, RHS: ValueRef,
Name: *c_char) -> ValueRef;
/* Atomic Operations */
- fn LLVMBuildAtomicCmpXchg(B: BuilderRef, LHS: ValueRef,
+ unsafe fn LLVMBuildAtomicCmpXchg(B: BuilderRef, LHS: ValueRef,
CMP: ValueRef, RHS: ValueRef,
++Order: AtomicOrdering) -> ValueRef;
- fn LLVMBuildAtomicRMW(B: BuilderRef, ++Op: AtomicBinOp,
+ unsafe fn LLVMBuildAtomicRMW(B: BuilderRef, ++Op: AtomicBinOp,
LHS: ValueRef, RHS: ValueRef,
++Order: AtomicOrdering) -> ValueRef;
/* Selected entries from the downcasts. */
- fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
+ unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;
/** Writes a module to the specified path. Returns 0 on success. */
- fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *c_char) -> c_int;
+ unsafe fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *c_char) -> c_int;
/** Creates target data from a target layout string. */
- fn LLVMCreateTargetData(StringRep: *c_char) -> TargetDataRef;
+ unsafe fn LLVMCreateTargetData(StringRep: *c_char) -> TargetDataRef;
/** Adds the target data to the given pass manager. The pass manager
references the target data only weakly. */
- fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
+ unsafe fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
/** Number of bytes clobbered when doing a Store to *T. */
- fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
+ unsafe fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
+ -> c_ulonglong;
/** Number of bytes clobbered when doing a Store to *T. */
- fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef) -> c_ulonglong;
+ unsafe fn LLVMSizeOfTypeInBits(TD: TargetDataRef, Ty: TypeRef)
+ -> c_ulonglong;
/** Distance between successive elements in an array of T.
Includes ABI padding. */
- fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint;
+ unsafe fn LLVMABISizeOfType(TD: TargetDataRef, Ty: TypeRef) -> c_uint;
/** Returns the preferred alignment of a type. */
- fn LLVMPreferredAlignmentOfType(TD: TargetDataRef,
+ unsafe fn LLVMPreferredAlignmentOfType(TD: TargetDataRef,
Ty: TypeRef) -> c_uint;
/** Returns the minimum alignment of a type. */
- fn LLVMABIAlignmentOfType(TD: TargetDataRef,
+ unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef,
Ty: TypeRef) -> c_uint;
/** Returns the minimum alignment of a type when part of a call frame. */
- fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef,
+ unsafe fn LLVMCallFrameAlignmentOfType(TD: TargetDataRef,
Ty: TypeRef) -> c_uint;
/** Disposes target data. */
- fn LLVMDisposeTargetData(TD: TargetDataRef);
+ unsafe fn LLVMDisposeTargetData(TD: TargetDataRef);
/** Creates a pass manager. */
- fn LLVMCreatePassManager() -> PassManagerRef;
+ unsafe fn LLVMCreatePassManager() -> PassManagerRef;
/** Disposes a pass manager. */
- fn LLVMDisposePassManager(PM: PassManagerRef);
+ unsafe fn LLVMDisposePassManager(PM: PassManagerRef);
/** Runs a pass manager on a module. */
- fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
+ unsafe fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool;
/** Adds a verification pass. */
- fn LLVMAddVerifierPass(PM: PassManagerRef);
-
- fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
- fn LLVMAddIPSCCPPass(PM: PassManagerRef);
- fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef);
- fn LLVMAddInstructionCombiningPass(PM: PassManagerRef);
- fn LLVMAddCFGSimplificationPass(PM: PassManagerRef);
- fn LLVMAddFunctionInliningPass(PM: PassManagerRef);
- fn LLVMAddFunctionAttrsPass(PM: PassManagerRef);
- fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef);
- fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef);
- fn LLVMAddJumpThreadingPass(PM: PassManagerRef);
- fn LLVMAddConstantPropagationPass(PM: PassManagerRef);
- fn LLVMAddReassociatePass(PM: PassManagerRef);
- fn LLVMAddLoopRotatePass(PM: PassManagerRef);
- fn LLVMAddLICMPass(PM: PassManagerRef);
- fn LLVMAddLoopUnswitchPass(PM: PassManagerRef);
- fn LLVMAddLoopDeletionPass(PM: PassManagerRef);
- fn LLVMAddLoopUnrollPass(PM: PassManagerRef);
- fn LLVMAddGVNPass(PM: PassManagerRef);
- fn LLVMAddMemCpyOptPass(PM: PassManagerRef);
- fn LLVMAddSCCPPass(PM: PassManagerRef);
- fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef);
- fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef);
- fn LLVMAddConstantMergePass(PM: PassManagerRef);
- fn LLVMAddArgumentPromotionPass(PM: PassManagerRef);
- fn LLVMAddTailCallEliminationPass(PM: PassManagerRef);
- fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef);
- fn LLVMAddAggressiveDCEPass(PM: PassManagerRef);
- fn LLVMAddGlobalDCEPass(PM: PassManagerRef);
- fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef);
- fn LLVMAddPruneEHPass(PM: PassManagerRef);
- fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef);
- fn LLVMAddLoopIdiomPass(PM: PassManagerRef);
- fn LLVMAddEarlyCSEPass(PM: PassManagerRef);
- fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef);
- fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef);
-
- fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
- fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
- fn LLVMPassManagerBuilderSetOptLevel(PMB: PassManagerBuilderRef,
+ unsafe fn LLVMAddVerifierPass(PM: PassManagerRef);
+
+ unsafe fn LLVMAddGlobalOptimizerPass(PM: PassManagerRef);
+ unsafe fn LLVMAddIPSCCPPass(PM: PassManagerRef);
+ unsafe fn LLVMAddDeadArgEliminationPass(PM: PassManagerRef);
+ unsafe fn LLVMAddInstructionCombiningPass(PM: PassManagerRef);
+ unsafe fn LLVMAddCFGSimplificationPass(PM: PassManagerRef);
+ unsafe fn LLVMAddFunctionInliningPass(PM: PassManagerRef);
+ unsafe fn LLVMAddFunctionAttrsPass(PM: PassManagerRef);
+ unsafe fn LLVMAddScalarReplAggregatesPass(PM: PassManagerRef);
+ unsafe fn LLVMAddScalarReplAggregatesPassSSA(PM: PassManagerRef);
+ unsafe fn LLVMAddJumpThreadingPass(PM: PassManagerRef);
+ unsafe fn LLVMAddConstantPropagationPass(PM: PassManagerRef);
+ unsafe fn LLVMAddReassociatePass(PM: PassManagerRef);
+ unsafe fn LLVMAddLoopRotatePass(PM: PassManagerRef);
+ unsafe fn LLVMAddLICMPass(PM: PassManagerRef);
+ unsafe fn LLVMAddLoopUnswitchPass(PM: PassManagerRef);
+ unsafe fn LLVMAddLoopDeletionPass(PM: PassManagerRef);
+ unsafe fn LLVMAddLoopUnrollPass(PM: PassManagerRef);
+ unsafe fn LLVMAddGVNPass(PM: PassManagerRef);
+ unsafe fn LLVMAddMemCpyOptPass(PM: PassManagerRef);
+ unsafe fn LLVMAddSCCPPass(PM: PassManagerRef);
+ unsafe fn LLVMAddDeadStoreEliminationPass(PM: PassManagerRef);
+ unsafe fn LLVMAddStripDeadPrototypesPass(PM: PassManagerRef);
+ unsafe fn LLVMAddConstantMergePass(PM: PassManagerRef);
+ unsafe fn LLVMAddArgumentPromotionPass(PM: PassManagerRef);
+ unsafe fn LLVMAddTailCallEliminationPass(PM: PassManagerRef);
+ unsafe fn LLVMAddIndVarSimplifyPass(PM: PassManagerRef);
+ unsafe fn LLVMAddAggressiveDCEPass(PM: PassManagerRef);
+ unsafe fn LLVMAddGlobalDCEPass(PM: PassManagerRef);
+ unsafe fn LLVMAddCorrelatedValuePropagationPass(PM: PassManagerRef);
+ unsafe fn LLVMAddPruneEHPass(PM: PassManagerRef);
+ unsafe fn LLVMAddSimplifyLibCallsPass(PM: PassManagerRef);
+ unsafe fn LLVMAddLoopIdiomPass(PM: PassManagerRef);
+ unsafe fn LLVMAddEarlyCSEPass(PM: PassManagerRef);
+ unsafe fn LLVMAddTypeBasedAliasAnalysisPass(PM: PassManagerRef);
+ unsafe fn LLVMAddBasicAliasAnalysisPass(PM: PassManagerRef);
+
+ unsafe fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef;
+ unsafe fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef);
+ unsafe fn LLVMPassManagerBuilderSetOptLevel(PMB: PassManagerBuilderRef,
OptimizationLevel: c_uint);
- fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef,
+ unsafe fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef,
Value: Bool);
- fn LLVMPassManagerBuilderSetDisableUnitAtATime(PMB: PassManagerBuilderRef,
- Value: Bool);
- fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: PassManagerBuilderRef,
- Value: Bool);
- fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls
+ unsafe fn LLVMPassManagerBuilderSetDisableUnitAtATime(
+ PMB: PassManagerBuilderRef, Value: Bool);
+ unsafe fn LLVMPassManagerBuilderSetDisableUnrollLoops(
+ PMB: PassManagerBuilderRef, Value: Bool);
+ unsafe fn LLVMPassManagerBuilderSetDisableSimplifyLibCalls
(PMB: PassManagerBuilderRef, Value: Bool);
- fn LLVMPassManagerBuilderUseInlinerWithThreshold
+ unsafe fn LLVMPassManagerBuilderUseInlinerWithThreshold
(PMB: PassManagerBuilderRef, threshold: c_uint);
- fn LLVMPassManagerBuilderPopulateModulePassManager
+ unsafe fn LLVMPassManagerBuilderPopulateModulePassManager
(PMB: PassManagerBuilderRef, PM: PassManagerRef);
- fn LLVMPassManagerBuilderPopulateFunctionPassManager
+ unsafe fn LLVMPassManagerBuilderPopulateFunctionPassManager
(PMB: PassManagerBuilderRef, PM: PassManagerRef);
/** Destroys a memory buffer. */
- fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
+ unsafe fn LLVMDisposeMemoryBuffer(MemBuf: MemoryBufferRef);
/* Stuff that's in rustllvm/ because it's not upstream yet. */
/** Opens an object file. */
- fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
+ unsafe fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef;
/** Closes an object file. */
- fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
+ unsafe fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef);
/** Enumerates the sections in an object file. */
- fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
+ unsafe fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef;
/** Destroys a section iterator. */
- fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
+ unsafe fn LLVMDisposeSectionIterator(SI: SectionIteratorRef);
/** Returns true if the section iterator is at the end of the section
list: */
- fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
+ unsafe fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef,
SI: SectionIteratorRef) -> Bool;
/** Moves the section iterator to point to the next section. */
- fn LLVMMoveToNextSection(SI: SectionIteratorRef);
+ unsafe fn LLVMMoveToNextSection(SI: SectionIteratorRef);
/** Returns the current section name. */
- fn LLVMGetSectionName(SI: SectionIteratorRef) -> *c_char;
+ unsafe fn LLVMGetSectionName(SI: SectionIteratorRef) -> *c_char;
/** Returns the current section size. */
- fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
+ unsafe fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
/** Returns the current section contents as a string buffer. */
- fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *c_char;
+ unsafe fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *c_char;
/** Reads the given file and returns it as a memory buffer. Use
LLVMDisposeMemoryBuffer() to get rid of it. */
- fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *c_char) ->
+ unsafe fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *c_char) ->
MemoryBufferRef;
- fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef,
+ unsafe fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef,
Triple: *c_char,
// FIXME: When #2334 is fixed, change
// c_uint to FileType
/** Returns a string describing the last error caused by an LLVMRust*
call. */
- fn LLVMRustGetLastError() -> *c_char;
+ unsafe fn LLVMRustGetLastError() -> *c_char;
/** Prepare the JIT. Returns a memory manager that can load crates. */
- fn LLVMRustPrepareJIT(__morestack: *()) -> *();
+ unsafe fn LLVMRustPrepareJIT(__morestack: *()) -> *();
/** Load a crate into the memory manager. */
- fn LLVMRustLoadCrate(MM: *(),
+ unsafe fn LLVMRustLoadCrate(MM: *(),
Filename: *c_char) -> bool;
/** Execute the JIT engine. */
- fn LLVMRustExecuteJIT(MM: *(),
+ unsafe fn LLVMRustExecuteJIT(MM: *(),
PM: PassManagerRef,
M: ModuleRef,
OptLevel: c_int,
EnableSegmentedStacks: bool) -> *();
/** Parses the bitcode in the given memory buffer. */
- fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;
+ unsafe fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;
/** Parses LLVM asm in the given file */
- fn LLVMRustParseAssemblyFile(Filename: *c_char) -> ModuleRef;
+ unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char) -> ModuleRef;
- fn LLVMRustAddPrintModulePass(PM: PassManagerRef, M: ModuleRef,
+ unsafe fn LLVMRustAddPrintModulePass(PM: PassManagerRef, M: ModuleRef,
Output: *c_char);
/** Turn on LLVM pass-timing. */
- fn LLVMRustEnableTimePasses();
+ unsafe fn LLVMRustEnableTimePasses();
/** Print the pass timings since static dtors aren't picking them up. */
- fn LLVMRustPrintPassTimings();
+ unsafe fn LLVMRustPrintPassTimings();
- fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef;
+ unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char) -> TypeRef;
- fn LLVMStructSetBody(StructTy: TypeRef, ElementTypes: *TypeRef,
+ unsafe fn LLVMStructSetBody(StructTy: TypeRef, ElementTypes: *TypeRef,
ElementCount: c_uint, Packed: Bool);
- fn LLVMConstNamedStruct(S: TypeRef, ConstantVals: *ValueRef,
+ unsafe fn LLVMConstNamedStruct(S: TypeRef, ConstantVals: *ValueRef,
Count: c_uint) -> ValueRef;
/** Enables LLVM debug output. */
- fn LLVMSetDebug(Enabled: c_int);
+ unsafe fn LLVMSetDebug(Enabled: c_int);
}
fn SetInstructionCallConv(Instr: ValueRef, CC: CallConv) {
- llvm::LLVMSetInstructionCallConv(Instr, CC as c_uint);
+ unsafe {
+ llvm::LLVMSetInstructionCallConv(Instr, CC as c_uint);
+ }
}
fn SetFunctionCallConv(Fn: ValueRef, CC: CallConv) {
- llvm::LLVMSetFunctionCallConv(Fn, CC as c_uint);
+ unsafe {
+ llvm::LLVMSetFunctionCallConv(Fn, CC as c_uint);
+ }
}
fn SetLinkage(Global: ValueRef, Link: Linkage) {
- llvm::LLVMSetLinkage(Global, Link as c_uint);
+ unsafe {
+ llvm::LLVMSetLinkage(Global, Link as c_uint);
+ }
}
/* Memory-managed object interface to type handles. */
-type type_names = @{type_names: std::map::HashMap<TypeRef, ~str>,
- named_types: std::map::HashMap<~str, TypeRef>};
+type type_names = @{type_names: HashMap<TypeRef, ~str>,
+ named_types: HashMap<~str, TypeRef>};
-fn associate_type(tn: type_names, s: ~str, t: TypeRef) {
- assert tn.type_names.insert(t, s);
+fn associate_type(tn: type_names, +s: ~str, t: TypeRef) {
+ // XXX: Bad copy, use @str instead?
+ assert tn.type_names.insert(t, copy s);
assert tn.named_types.insert(s, t);
}
return tn.type_names.find(t);
}
-fn name_has_type(tn: type_names, s: ~str) -> Option<TypeRef> {
+fn name_has_type(tn: type_names, +s: ~str) -> Option<TypeRef> {
return tn.named_types.find(s);
}
fn mk_type_names() -> type_names {
- @{type_names: std::map::HashMap(),
- named_types: std::map::HashMap()}
+ @{type_names: HashMap(),
+ named_types: HashMap()}
}
fn type_to_str(names: type_names, ty: TypeRef) -> ~str {
return type_to_str_inner(names, ~[], ty);
}
-fn type_to_str_inner(names: type_names, outer0: ~[TypeRef], ty: TypeRef) ->
+fn type_to_str_inner(names: type_names, +outer0: ~[TypeRef], ty: TypeRef) ->
~str {
- match type_has_name(names, ty) {
- option::Some(ref n) => return (*n),
- _ => {}
- }
+ unsafe {
+ match type_has_name(names, ty) {
+ option::Some(ref n) => return (/*bad*/copy *n),
+ _ => {}
+ }
- let outer = vec::append_one(outer0, ty);
+ // XXX: Bad copy.
+ let outer = vec::append_one(copy outer0, ty);
- let kind = llvm::LLVMGetTypeKind(ty);
+ let kind = llvm::LLVMGetTypeKind(ty);
- fn tys_str(names: type_names, outer: ~[TypeRef],
- tys: ~[TypeRef]) -> ~str {
- let mut s: ~str = ~"";
- let mut first: bool = true;
- for tys.each |t| {
- if first { first = false; } else { s += ~", "; }
- s += type_to_str_inner(names, outer, *t);
+ fn tys_str(names: type_names, outer: ~[TypeRef],
+ tys: ~[TypeRef]) -> ~str {
+ let mut s: ~str = ~"";
+ let mut first: bool = true;
+ for tys.each |t| {
+ if first { first = false; } else { s += ~", "; }
+ s += type_to_str_inner(names, outer, *t);
+ }
+ return s;
}
- return s;
- }
- match kind {
- Void => return ~"Void",
- Half => return ~"Half",
- Float => return ~"Float",
- Double => return ~"Double",
- X86_FP80 => return ~"X86_FP80",
- FP128 => return ~"FP128",
- PPC_FP128 => return ~"PPC_FP128",
- Label => return ~"Label",
- Integer => {
- return ~"i" + int::str(llvm::LLVMGetIntTypeWidth(ty) as int);
- }
- Function => {
- let mut s = ~"fn(";
- let out_ty: TypeRef = llvm::LLVMGetReturnType(ty);
- let n_args = llvm::LLVMCountParamTypes(ty) as uint;
- let args = vec::from_elem(n_args, 0 as TypeRef);
- unsafe {
- llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args));
- }
- s += tys_str(names, outer, args);
- s += ~") -> ";
- s += type_to_str_inner(names, outer, out_ty);
- return s;
- }
- Struct => {
- let mut s: ~str = ~"{";
- let n_elts = llvm::LLVMCountStructElementTypes(ty) as uint;
- let mut elts = vec::from_elem(n_elts, 0 as TypeRef);
- llvm::LLVMGetStructElementTypes(ty,
- ptr::to_mut_unsafe_ptr(&mut elts[0]));
- s += tys_str(names, outer, elts);
- s += ~"}";
- return s;
- }
- Array => {
- let el_ty = llvm::LLVMGetElementType(ty);
- return ~"[" + type_to_str_inner(names, outer, el_ty) + ~" x " +
- uint::str(llvm::LLVMGetArrayLength(ty) as uint) + ~"]";
- }
- Pointer => {
- let mut i: uint = 0u;
- for outer0.each |tout| {
- i += 1u;
- if *tout as int == ty as int {
- let n: uint = vec::len::<TypeRef>(outer0) - i;
- return ~"*\\" + int::str(n as int);
+ match kind {
+ Void => return ~"Void",
+ Half => return ~"Half",
+ Float => return ~"Float",
+ Double => return ~"Double",
+ X86_FP80 => return ~"X86_FP80",
+ FP128 => return ~"FP128",
+ PPC_FP128 => return ~"PPC_FP128",
+ Label => return ~"Label",
+ Integer => {
+ return ~"i" + int::str(llvm::LLVMGetIntTypeWidth(ty) as int);
+ }
+ Function => {
+ let mut s = ~"fn(";
+ let out_ty: TypeRef = llvm::LLVMGetReturnType(ty);
+ let n_args = llvm::LLVMCountParamTypes(ty) as uint;
+ let args = vec::from_elem(n_args, 0 as TypeRef);
+ unsafe {
+ llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args));
}
- }
- let addrstr = {
- let addrspace = llvm::LLVMGetPointerAddressSpace(ty) as uint;
- if addrspace == 0u {
- ~""
- } else {
- fmt!("addrspace(%u)", addrspace)
+ s += tys_str(names, outer, args);
+ s += ~") -> ";
+ s += type_to_str_inner(names, outer, out_ty);
+ return s;
+ }
+ Struct => {
+ let mut s: ~str = ~"{";
+ let n_elts = llvm::LLVMCountStructElementTypes(ty) as uint;
+ let mut elts = vec::from_elem(n_elts, 0 as TypeRef);
+ if elts.len() > 0 {
+ llvm::LLVMGetStructElementTypes(
+ ty, ptr::to_mut_unsafe_ptr(&mut elts[0]));
}
- };
- return addrstr + ~"*" +
- type_to_str_inner(names, outer, llvm::LLVMGetElementType(ty));
- }
- Vector => return ~"Vector",
- Metadata => return ~"Metadata",
- X86_MMX => return ~"X86_MMAX"
+ s += tys_str(names, outer, elts);
+ s += ~"}";
+ return s;
+ }
+ Array => {
+ let el_ty = llvm::LLVMGetElementType(ty);
+ return ~"[" + type_to_str_inner(names, outer, el_ty) + ~" x " +
+ uint::str(llvm::LLVMGetArrayLength(ty) as uint) + ~"]";
+ }
+ Pointer => {
+ let mut i: uint = 0u;
+ for outer0.each |tout| {
+ i += 1u;
+ if *tout as int == ty as int {
+ let n: uint = vec::len::<TypeRef>(outer0) - i;
+ return ~"*\\" + int::str(n as int);
+ }
+ }
+ let addrstr = {
+ let addrspace = llvm::LLVMGetPointerAddressSpace(ty) as uint;
+ if addrspace == 0u {
+ ~""
+ } else {
+ fmt!("addrspace(%u)", addrspace)
+ }
+ };
+ return addrstr + ~"*" +
+ type_to_str_inner(names,
+ outer,
+ llvm::LLVMGetElementType(ty));
+ }
+ Vector => return ~"Vector",
+ Metadata => return ~"Metadata",
+ X86_MMX => return ~"X86_MMAX"
+ }
}
}
fn float_width(llt: TypeRef) -> uint {
- return match llvm::LLVMGetTypeKind(llt) as int {
- 1 => 32u,
- 2 => 64u,
- 3 => 80u,
- 4 | 5 => 128u,
- _ => fail ~"llvm_float_width called on a non-float type"
- };
+ unsafe {
+ return match llvm::LLVMGetTypeKind(llt) as int {
+ 1 => 32u,
+ 2 => 64u,
+ 3 => 80u,
+ 4 | 5 => 128u,
+ _ => fail ~"llvm_float_width called on a non-float type"
+ };
+ }
}
fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] unsafe {
- let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint,
- 0 as TypeRef);
- llvm::LLVMGetParamTypes(fn_ty, vec::raw::to_ptr(args));
- return args;
+ unsafe {
+ let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint,
+ 0 as TypeRef);
+ llvm::LLVMGetParamTypes(fn_ty, vec::raw::to_ptr(args));
+ return args;
+ }
}
fn struct_element_types(struct_ty: TypeRef) -> ~[TypeRef] {
let mut buf: ~[TypeRef] =
vec::from_elem(count as uint,
cast::transmute::<uint,TypeRef>(0));
- llvm::LLVMGetStructElementTypes(struct_ty,
- ptr::to_mut_unsafe_ptr(&mut buf[0]));
+ if buf.len() > 0 {
+ llvm::LLVMGetStructElementTypes(
+ struct_ty, ptr::to_mut_unsafe_ptr(&mut buf[0]));
+ }
return move buf;
}
}
struct target_data_res {
TD: TargetDataRef,
- drop { llvm::LLVMDisposeTargetData(self.TD); }
+ drop {
+ unsafe {
+ llvm::LLVMDisposeTargetData(self.TD);
+ }
+ }
}
fn target_data_res(TD: TargetDataRef) -> target_data_res {
fn mk_target_data(string_rep: ~str) -> target_data {
let lltd =
- str::as_c_str(string_rep, |buf| llvm::LLVMCreateTargetData(buf) );
+ str::as_c_str(string_rep, |buf| unsafe {
+ llvm::LLVMCreateTargetData(buf)
+ });
return {lltd: lltd, dtor: @target_data_res(lltd)};
}
struct pass_manager_res {
PM: PassManagerRef,
- drop { llvm::LLVMDisposePassManager(self.PM); }
+ drop {
+ unsafe {
+ llvm::LLVMDisposePassManager(self.PM);
+ }
+ }
}
fn pass_manager_res(PM: PassManagerRef) -> pass_manager_res {
type pass_manager = {llpm: PassManagerRef, dtor: @pass_manager_res};
fn mk_pass_manager() -> pass_manager {
- let llpm = llvm::LLVMCreatePassManager();
- return {llpm: llpm, dtor: @pass_manager_res(llpm)};
+ unsafe {
+ let llpm = llvm::LLVMCreatePassManager();
+ return {llpm: llpm, dtor: @pass_manager_res(llpm)};
+ }
}
/* Memory-managed interface to object files. */
struct object_file_res {
ObjectFile: ObjectFileRef,
- drop { llvm::LLVMDisposeObjectFile(self.ObjectFile); }
+ drop {
+ unsafe {
+ llvm::LLVMDisposeObjectFile(self.ObjectFile);
+ }
+ }
}
fn object_file_res(ObjFile: ObjectFileRef) -> object_file_res {
type object_file = {llof: ObjectFileRef, dtor: @object_file_res};
fn mk_object_file(llmb: MemoryBufferRef) -> Option<object_file> {
- let llof = llvm::LLVMCreateObjectFile(llmb);
- if llof as int == 0 { return option::None::<object_file>; }
- return option::Some({llof: llof, dtor: @object_file_res(llof)});
+ unsafe {
+ let llof = llvm::LLVMCreateObjectFile(llmb);
+ if llof as int == 0 { return option::None::<object_file>; }
+ return option::Some({llof: llof, dtor: @object_file_res(llof)});
+ }
}
/* Memory-managed interface to section iterators. */
struct section_iter_res {
SI: SectionIteratorRef,
- drop { llvm::LLVMDisposeSectionIterator(self.SI); }
+ drop {
+ unsafe {
+ llvm::LLVMDisposeSectionIterator(self.SI);
+ }
+ }
}
fn section_iter_res(SI: SectionIteratorRef) -> section_iter_res {
type section_iter = {llsi: SectionIteratorRef, dtor: @section_iter_res};
fn mk_section_iter(llof: ObjectFileRef) -> section_iter {
- let llsi = llvm::LLVMGetSections(llof);
- return {llsi: llsi, dtor: @section_iter_res(llsi)};
+ unsafe {
+ let llsi = llvm::LLVMGetSections(llof);
+ return {llsi: llsi, dtor: @section_iter_res(llsi)};
+ }
}
//
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// EBML enum definitions and utils shared by the encoder and decoder
const tag_items: uint = 0x02u;
const tag_item_impl_type_basename: uint = 0x71;
+// Language items are a top-level directory (for speed). Hierarchy:
+//
+// tag_lang_items
+// - tag_lang_items_item
+// - tag_lang_items_item_id: u32
+// - tag_lang_items_item_node_id: u32
+
+const tag_lang_items: uint = 0x72;
+const tag_lang_items_item: uint = 0x73;
+const tag_lang_items_item_id: uint = 0x74;
+const tag_lang_items_item_node_id: uint = 0x75;
+
type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
//! Validates all used crates and extern libraries and loads their metadata
-use syntax::diagnostic::span_handler;
-use syntax::{ast, ast_util};
+use core::prelude::*;
+
+use metadata::cstore;
+use metadata::common::*;
+use metadata::decoder;
+use metadata::filesearch::FileSearch;
+use metadata::loader;
+
+use core::dvec::DVec;
+use core::either;
+use core::option;
+use core::vec;
use syntax::attr;
-use syntax::visit;
use syntax::codemap::span;
-use std::map::HashMap;
-use syntax::print::pprust;
-use metadata::filesearch::FileSearch;
-use metadata::common::*;
-use dvec::DVec;
+use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
+use syntax::print::pprust;
+use syntax::visit;
+use syntax::{ast, ast_util};
+use std::map::HashMap;
export read_crates;
// Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc.
-fn read_crates(diag: span_handler, crate: ast::crate,
- cstore: cstore::CStore, filesearch: FileSearch,
- os: loader::os, static: bool, intr: @ident_interner) {
+fn read_crates(diag: span_handler,
+ crate: ast::crate,
+ cstore: cstore::CStore,
+ filesearch: FileSearch,
+ os: loader::os,
+ static: bool,
+ intr: @ident_interner) {
let e = @{diag: diag,
filesearch: filesearch,
cstore: cstore,
mut next_crate_num: 1,
intr: intr};
let v =
- visit::mk_simple_visitor(@{visit_view_item:
- |a| visit_view_item(e, a),
- visit_item: |a| visit_item(e, a)
- ,.. *visit::default_simple_visitor()});
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_view_item: |a| visit_view_item(e, a),
+ visit_item: |a| visit_item(e, a),
+ .. *visit::default_simple_visitor()});
visit::visit_crate(crate, (), v);
dump_crates(e.crate_cache);
warn_if_multiple_versions(e, diag, e.crate_cache.get());
use either::*;
if crate_cache.len() != 0u {
- let name = loader::crate_name_from_metas(*crate_cache.last().metas);
+ let name = loader::crate_name_from_metas(
+ /*bad*/copy *crate_cache.last().metas);
let (matches, non_matches) =
partition(crate_cache.map_to_vec(|&entry| {
- let othername = loader::crate_name_from_metas(*entry.metas);
+ let othername = loader::crate_name_from_metas(
+ copy *entry.metas);
if name == othername {
Left(entry)
} else {
for matches.each |match_| {
diag.span_note(match_.span, ~"used here");
let attrs = ~[
- attr::mk_attr(attr::mk_list_item(~"link", *match_.metas))
+ attr::mk_attr(attr::mk_list_item(
+ ~"link", /*bad*/copy *match_.metas))
];
loader::note_linkage_attrs(e.intr, diag, attrs);
}
intr: @ident_interner};
fn visit_view_item(e: env, i: @ast::view_item) {
- match i.node {
+ match /*bad*/copy i.node {
ast::view_item_use(ident, meta_items, id) => {
debug!("resolving use stmt. ident: %?, meta: %?", ident, meta_items);
let cnum = resolve_crate(e, ident, meta_items, ~"", i.span);
}
fn visit_item(e: env, i: @ast::item) {
- match i.node {
+ match /*bad*/copy i.node {
ast::item_foreign_mod(fm) => {
match attr::foreign_abi(i.attrs) {
either::Right(abi) => {
let cstore = e.cstore;
let mut already_added = false;
- let link_args = attr::find_attrs_by_name(i.attrs, ~"link_args");
+ let link_args = attr::find_attrs_by_name(i.attrs, "link_args");
match fm.sort {
ast::named => {
i.span,
~"empty #[link_name] not allowed; use #[nolink].");
}
- (*nn)
+ (/*bad*/copy *nn)
}
- None => *e.intr.get(i.ident)
+ None => /*bad*/copy *e.intr.get(i.ident)
};
if attr::find_attrs_by_name(i.attrs, ~"nolink").is_empty() {
already_added = !cstore::add_used_library(cstore,
for link_args.each |a| {
match attr::get_meta_item_value_str(attr::attr_meta(*a)) {
Some(ref linkarg) => {
- cstore::add_used_link_args(cstore, (*linkarg));
+ cstore::add_used_link_args(cstore, (/*bad*/copy *linkarg));
}
None => {/* fallthrough */ }
}
}
}
-fn metas_with(ident: ~str, key: ~str, metas: ~[@ast::meta_item])
+fn metas_with(+ident: ~str, +key: ~str, +metas: ~[@ast::meta_item])
-> ~[@ast::meta_item] {
- let name_items = attr::find_meta_items_by_name(metas, key);
+ // XXX: Bad copies.
+ let name_items = attr::find_meta_items_by_name(copy metas, copy key);
if name_items.is_empty() {
vec::append_one(metas, attr::mk_name_value_item_str(key, ident))
} else {
}
}
-fn metas_with_ident(ident: ~str, metas: ~[@ast::meta_item])
+fn metas_with_ident(+ident: ~str, +metas: ~[@ast::meta_item])
-> ~[@ast::meta_item] {
metas_with(ident, ~"name", metas)
}
return None;
}
-fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
- hash: ~str, span: span) -> ast::crate_num {
- let metas = metas_with_ident(*e.intr.get(ident), metas);
+fn resolve_crate(e: env, ident: ast::ident, +metas: ~[@ast::meta_item],
+ +hash: ~str, span: span) -> ast::crate_num {
+ let metas = metas_with_ident(/*bad*/copy *e.intr.get(ident), metas);
match existing_match(e, metas, hash) {
None => {
filesearch: e.filesearch,
span: span,
ident: ident,
- metas: metas,
+ metas: copy metas, // XXX: Bad copy.
hash: hash,
os: e.os,
static: e.static,
let cname =
match attr::last_meta_item_value_str_by_name(metas, ~"name") {
- option::Some(ref v) => (*v),
- option::None => *e.intr.get(ident)
+ option::Some(ref v) => (/*bad*/copy *v),
+ option::None => /*bad*/copy *e.intr.get(ident)
};
let cmeta = @{name: cname, data: cdata,
cnum_map: cnum_map, cnum: cnum};
for decoder::get_crate_deps(e.intr, cdata).each |dep| {
let extrn_cnum = dep.cnum;
let cname = dep.name;
- let cmetas = metas_with(dep.vers, ~"vers", ~[]);
+ let cmetas = metas_with(/*bad*/copy dep.vers, ~"vers", ~[]);
debug!("resolving dep crate %s ver: %s hash: %s",
*e.intr.get(dep.name), dep.vers, dep.hash);
match existing_match(e, metas_with_ident(*e.intr.get(cname), cmetas),
// FIXME (#2404): Need better error reporting than just a bogus
// span.
let fake_span = ast_util::dummy_sp();
- let local_cnum = resolve_crate(e, cname, cmetas, dep.hash,
- fake_span);
+ let local_cnum = resolve_crate(e, cname, cmetas,
+ /*bad*/copy dep.hash, fake_span);
cnum_map.insert(extrn_cnum, local_cnum);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// Searching for information from the cstore
+use core::prelude::*;
+
use metadata::common::*;
+use metadata::cstore;
+use metadata::decoder;
+use metadata;
use middle::ty;
use core::dvec::DVec;
-use core::option::{Some, None};
+use core::vec;
use reader = std::ebml::reader;
use std::ebml;
use std::map::HashMap;
export get_type_name_if_impl;
export get_static_methods_if_impl;
export get_item_attrs;
+export each_lang_item;
export each_path;
export get_type;
export get_impl_traits;
export get_impl_method;
export get_item_path;
+export get_lang_items;
export maybe_get_item_ast, found_ast, found, found_parent, not_found;
export ProvidedTraitMethodInfo;
export StaticMethodInfo;
return decoder::get_type_param_count(cdata, def.node);
}
+/// Iterates over all the language items in the given crate.
+fn each_lang_item(cstore: cstore::CStore,
+ cnum: ast::crate_num,
+ f: &fn(ast::node_id, uint) -> bool) {
+ let crate_data = cstore::get_crate_data(cstore, cnum);
+ decoder::each_lang_item(crate_data, f)
+}
+
/// Iterates over all the paths in the given crate.
fn each_path(cstore: cstore::CStore, cnum: ast::crate_num,
f: fn(decoder::path_entry) -> bool) {
// FIXME #1920: This path is not always correct if the crate is not linked
// into the root namespace.
- vec::append(~[ast_map::path_mod(tcx.sess.ident_of(cdata.name))], path)
+ vec::append(~[ast_map::path_mod(tcx.sess.ident_of(
+ /*bad*/copy cdata.name))], path)
}
enum found_ast {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// The crate store - a central repo for information collected about external
// crates and libraries
-use std::map;
+use core::prelude::*;
+
+use metadata::creader;
+use metadata::cstore;
+use metadata::decoder;
+
+use core::option;
+use core::str;
+use core::vec;
use std::map::HashMap;
+use std::map;
+use std;
use syntax::{ast, attr};
use syntax::parse::token::ident_interner;
export add_use_stmt_cnum;
export find_use_stmt_cnum;
export get_dep_hashes;
-export get_path;
// A map from external crate numbers (as decoded from some crate file) to
// own crate numbers.
type cnum_map = map::HashMap<ast::crate_num, ast::crate_num>;
-// Multiple items may have the same def_id in crate metadata. They may be
-// renamed imports or reexports. This map keeps the "real" module path
-// and def_id.
-type mod_path_map = map::HashMap<ast::def_id, @~str>;
-
type crate_metadata = @{name: ~str,
data: @~[u8],
cnum_map: cnum_map,
type cstore_private =
@{metas: map::HashMap<ast::crate_num, crate_metadata>,
use_crate_map: use_crate_map,
- mod_path_map: mod_path_map,
mut used_crate_files: ~[Path],
mut used_libraries: ~[~str],
mut used_link_args: ~[~str],
fn mk_cstore(intr: @ident_interner) -> CStore {
let meta_cache = map::HashMap();
let crate_map = map::HashMap();
- let mod_path_map = HashMap();
return private(@{metas: meta_cache,
use_crate_map: crate_map,
- mod_path_map: mod_path_map,
mut used_crate_files: ~[],
mut used_libraries: ~[],
mut used_link_args: ~[],
return decoder::get_crate_vers(cdata.data);
}
-fn set_crate_data(cstore: CStore, cnum: ast::crate_num,
+fn set_crate_data(cstore: CStore,
+ cnum: ast::crate_num,
data: crate_metadata) {
p(cstore).metas.insert(cnum, data);
- let get_crate_data: decoder::GetCrateDataCb = |cnum| {
- cstore::get_crate_data(cstore, cnum)
- };
- for vec::each(decoder::get_crate_module_paths(cstore.intr, data,
- get_crate_data)) |dp| {
- let (did, path) = *dp;
- let d = {crate: cnum, node: did.node};
- p(cstore).mod_path_map.insert(d, @path);
- }
}
fn have_crate_data(cstore: CStore, cnum: ast::crate_num) -> bool {
}
fn get_used_crate_files(cstore: CStore) -> ~[Path] {
- return p(cstore).used_crate_files;
+ return /*bad*/copy p(cstore).used_crate_files;
}
-fn add_used_library(cstore: CStore, lib: ~str) -> bool {
+fn add_used_library(cstore: CStore, +lib: ~str) -> bool {
assert lib != ~"";
if vec::contains(p(cstore).used_libraries, &lib) { return false; }
}
fn get_used_libraries(cstore: CStore) -> ~[~str] {
- return p(cstore).used_libraries;
+ return /*bad*/copy p(cstore).used_libraries;
}
fn add_used_link_args(cstore: CStore, args: ~str) {
}
fn get_used_link_args(cstore: CStore) -> ~[~str] {
- return p(cstore).used_link_args;
+ return /*bad*/copy p(cstore).used_link_args;
}
fn add_use_stmt_cnum(cstore: CStore, use_id: ast::node_id,
let cdata = cstore::get_crate_data(cstore, cnum);
let hash = decoder::get_crate_hash(cdata.data);
debug!("Add hash[%s]: %s", cdata.name, hash);
- result.push({name: cdata.name, hash: hash});
+ result.push({name: /*bad*/copy cdata.name, hash: hash});
};
pure fn lteq(a: &crate_hash, b: &crate_hash) -> bool {a.name <= b.name}
let sorted = std::sort::merge_sort(result, lteq);
for sorted.each |x| {
debug!(" hash[%s]: %s", x.name, x.hash);
}
- fn mapper(ch: &crate_hash) -> ~str { return ch.hash; }
+ fn mapper(ch: &crate_hash) -> ~str { return /*bad*/copy ch.hash; }
return vec::map(sorted, mapper);
}
-fn get_path(cstore: CStore, d: ast::def_id) -> ~[~str] {
- option::map_default(&p(cstore).mod_path_map.find(d), ~[],
- |ds| str::split_str(**ds, ~"::"))
-}
// Local Variables:
// mode: rust
// fill-column: 78;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// Decoding metadata from a single crate's metadata
+use core::prelude::*;
+
use cmd = metadata::cstore::crate_metadata;
use dvec::DVec;
use hash::{Hash, HashUtil};
use io::WriterUtil;
use metadata::common::*;
use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
+use metadata::csearch;
+use metadata::cstore;
+use metadata::decoder;
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
use metadata::tydecode::{parse_ident};
use middle::ty;
use util::ppaux::ty_to_str;
-use reader = std::ebml::reader;
+use core::cmp;
+use core::dvec;
+use core::int;
+use core::io;
+use core::option;
+use core::str;
+use core::vec;
+use std::ebml::reader;
use std::ebml;
use std::map::HashMap;
use std::map;
export get_method_names_if_trait;
export get_type_name_if_impl;
export get_item_attrs;
-export get_crate_module_paths;
export def_like;
export dl_def;
export dl_impl;
export dl_field;
export path_entry;
+export each_lang_item;
export each_path;
export get_item_path;
export maybe_find_item; // sketchy
def_like: def_like,
}
-fn path_entry(path_string: ~str, def_like: def_like) -> path_entry {
+fn path_entry(+path_string: ~str, def_like: def_like) -> path_entry {
path_entry {
path_string: path_string,
def_like: def_like
}
}
+/// Iterates over the language items in the given crate.
+fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) {
+ let root = reader::Doc(cdata.data);
+ let lang_items = reader::get_doc(root, tag_lang_items);
+ for reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| {
+ let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
+ let id = reader::doc_as_u32(id_doc) as uint;
+ let node_id_doc = reader::get_doc(item_doc,
+ tag_lang_items_item_node_id);
+ let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id;
+
+ if !f(node_id, id) {
+ break;
+ }
+ }
+}
+
/// Iterates over all the paths in the given crate.
fn each_path(intr: @ident_interner, cdata: cmd,
get_crate_data: GetCrateDataCb,
let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);
// Hand the information off to the iteratee.
- let this_path_entry = path_entry(path, def_like);
+ // XXX: Bad copy.
+ let this_path_entry = path_entry(copy path, def_like);
if !f(this_path_entry) {
broken = true; // XXX: This is awful.
}
let item_doc = lookup_item(id, cdata.data);
let path = vec::init(item_path(intr, item_doc));
match decode_inlined_item(cdata, tcx, path, item_doc) {
- Some(ref ii) => csearch::found((*ii)),
+ Some(ref ii) => csearch::found((/*bad*/copy *ii)),
None => {
match item_parent_item(item_doc) {
Some(did) => {
let parent_item = lookup_item(did.node, cdata.data);
match decode_inlined_item(cdata, tcx, path,
parent_item) {
- Some(ref ii) => csearch::found_parent(did, (*ii)),
+ Some(ref ii) => csearch::found_parent(did, (/*bad*/copy *ii)),
None => csearch::not_found
}
}
let ty = doc_type(mth, tcx, cdata);
let def_id = item_def_id(mth, cdata);
let fty = match ty::get(ty).sty {
- ty::ty_fn(ref f) => (*f),
+ ty::ty_fn(ref f) => (/*bad*/copy *f),
_ => {
tcx.diag.handler().bug(
~"get_trait_methods: id has non-function type");
let fty;
match ty::get(ty).sty {
- ty::ty_fn(ref f) => fty = (*f),
+ ty::ty_fn(ref f) => fty = (/*bad*/copy *f),
_ => {
tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
has non-function type");
assert (vec::len(meta_items) == 1u);
let meta_item = meta_items[0];
attrs.push(
- {node: {style: ast::attr_outer, value: *meta_item,
- is_sugared_doc: false},
- span: ast_util::dummy_sp()});
+ ast::spanned { node: { style: ast::attr_outer,
+ value: /*bad*/copy *meta_item,
+ is_sugared_doc: false },
+ span: ast_util::dummy_sp()});
};
}
option::None => ()
let attrs = decoder::get_crate_attributes(data);
return match attr::last_meta_item_value_str_by_name(
attr::find_linkage_metas(attrs), ~"vers") {
- Some(ref ver) => (*ver),
+ Some(ref ver) => (/*bad*/copy *ver),
None => ~"0.0"
};
}
fn iter_crate_items(intr: @ident_interner, cdata: cmd,
get_crate_data: GetCrateDataCb,
- proc: fn(~str, ast::def_id)) {
+ proc: fn(+path: ~str, ast::def_id)) {
for each_path(intr, cdata, get_crate_data) |path_entry| {
match path_entry.def_like {
dl_impl(*) | dl_field => {}
dl_def(def) => {
- proc(path_entry.path_string, ast_util::def_id_of_def(def))
+ proc(/*bad*/copy path_entry.path_string,
+ ast_util::def_id_of_def(def))
}
}
}
}
-fn get_crate_module_paths(intr: @ident_interner, cdata: cmd,
- get_crate_data: GetCrateDataCb)
- -> ~[(ast::def_id, ~str)] {
- fn mod_of_path(p: ~str) -> ~str {
- str::connect(vec::init(str::split_str(p, ~"::")), ~"::")
- }
-
- // find all module (path, def_ids), which are not
- // fowarded path due to renamed import or reexport
- let mut res = ~[];
- let mods = map::HashMap();
- do iter_crate_items(intr, cdata, get_crate_data) |path, did| {
- let m = mod_of_path(path);
- if str::is_not_empty(m) {
- // if m has a sub-item, it must be a module
- mods.insert(m, true);
- }
- // Collect everything by now. There might be multiple
- // paths pointing to the same did. Those will be
- // unified later by using the mods map
- res.push((did, path));
- }
- return do vec::filter(res) |x| {
- let (_, xp) = *x;
- mods.contains_key(xp)
- }
-}
-
fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8],
out: io::Writer) {
let hash = get_crate_hash(bytes);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// Metadata encoding
+use core::prelude::*;
+
+use metadata::common::*;
+use metadata::csearch;
+use metadata::cstore;
+use metadata::decoder;
+use metadata::tyencode;
+use middle::resolve;
+use middle::ty::node_id_to_type;
+use middle::ty;
+use middle;
use util::ppaux::ty_to_str;
-use std::{ebml, map};
+use core::dvec;
+use core::flate;
+use core::float;
+use core::hash::{Hash, HashUtil};
+use core::int;
+use core::io::WriterUtil;
+use core::io;
+use core::str::to_bytes;
+use core::str;
+use core::to_bytes::IterBytes;
+use core::uint;
+use core::vec;
use std::map::HashMap;
-use io::WriterUtil;
-use writer = std::ebml::writer;
+use std::{ebml, map};
+use std;
use syntax::ast::*;
-use syntax::print::pprust;
-use syntax::{ast_util, visit};
-use syntax::ast_util::*;
-use metadata::common::*;
-use middle::ty;
-use middle::ty::node_id_to_type;
-use middle::resolve;
+use syntax::ast;
use syntax::ast_map;
+use syntax::ast_util::*;
use syntax::attr;
-use str::to_bytes;
-use syntax::ast;
use syntax::diagnostic::span_handler;
-
-use hash::{Hash, HashUtil};
-use to_bytes::IterBytes;
+use syntax::print::pprust;
+use syntax::{ast_util, visit};
+use syntax;
+use writer = std::ebml::writer;
export encode_parms;
export encode_metadata;
mut inline_bytes: uint,
mut attr_bytes: uint,
mut dep_bytes: uint,
+ mut lang_item_bytes: uint,
mut item_bytes: uint,
mut index_bytes: uint,
mut zero_bytes: uint,
fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @encode_ctxt,
params: @~[ty::param_bounds]) {
- let ty_str_ctxt = @{diag: ecx.diag,
- ds: def_to_str,
- tcx: ecx.tcx,
- reachable: |a| reachable(ecx, a),
- abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+ let ty_str_ctxt = @tyencode::ctxt {
+ diag: ecx.diag,
+ ds: def_to_str,
+ tcx: ecx.tcx,
+ reachable: |a| reachable(ecx, a),
+ abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
for params.each |param| {
ebml_w.start_tag(tag_items_data_item_ty_param_bounds);
tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param);
}
fn write_type(ecx: @encode_ctxt, ebml_w: writer::Encoder, typ: ty::t) {
- let ty_str_ctxt =
- @{diag: ecx.diag,
- ds: def_to_str,
- tcx: ecx.tcx,
- reachable: |a| reachable(ecx, a),
- abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+ let ty_str_ctxt = @tyencode::ctxt {
+ diag: ecx.diag,
+ ds: def_to_str,
+ tcx: ecx.tcx,
+ reachable: |a| reachable(ecx, a),
+ abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
}
fn write_vstore(ecx: @encode_ctxt, ebml_w: writer::Encoder,
vstore: ty::vstore) {
- let ty_str_ctxt =
- @{diag: ecx.diag,
- ds: def_to_str,
- tcx: ecx.tcx,
- reachable: |a| reachable(ecx, a),
- abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
+ let ty_str_ctxt = @tyencode::ctxt {
+ diag: ecx.diag,
+ ds: def_to_str,
+ tcx: ecx.tcx,
+ reachable: |a| reachable(ecx, a),
+ abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
}
fn encode_symbol(ecx: @encode_ctxt, ebml_w: writer::Encoder, id: node_id) {
ebml_w.start_tag(tag_items_data_item_symbol);
let sym = match ecx.item_symbols.find(id) {
- Some(ref x) => (*x),
+ Some(ref x) => (/*bad*/copy *x),
None => {
ecx.diag.handler().bug(
fmt!("encode_symbol: id not found %d", id));
encode_type(ecx, ebml_w,
node_id_to_type(ecx.tcx, variant.node.id));
match variant.node.kind {
- ast::tuple_variant_kind(args)
+ ast::tuple_variant_kind(ref args)
if args.len() > 0 && ty_params.len() == 0 => {
encode_symbol(ecx, ebml_w, variant.node.id);
}
encode_disr_val(ecx, ebml_w, vi[i].disr_val);
disr_val = vi[i].disr_val;
}
- encode_type_param_bounds(ebml_w, ecx, ty_params);
- encode_path(ecx, ebml_w, path, ast_map::path_name(variant.node.name));
+ encode_type_param_bounds(ebml_w, ecx, /*bad*/copy ty_params);
+ encode_path(ecx, ebml_w, /*bad*/copy path,
+ ast_map::path_name(variant.node.name));
ebml_w.end_tag();
disr_val += 1;
i += 1;
}
fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: writer::Encoder,
- md: _mod, id: node_id, path: ast_map::path,
+ md: _mod, id: node_id, +path: ast_map::path,
name: ident) {
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(id));
tcx.sess.str_of(nm), id);
encode_visibility(ebml_w, vis);
encode_name(ecx, ebml_w, nm);
- encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
+ encode_path(ecx, ebml_w, /*bad*/copy path,
+ ast_map::path_name(nm));
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
encode_mutability(ebml_w, mt);
encode_def_id(ebml_w, local_def(id));
unnamed_field => {}
}
}
- *index
+ /*bad*/copy *index
}
// This is for encoding info for ctors and dtors
fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: writer::Encoder,
- id: node_id, ident: ident, path: ast_map::path,
- item: Option<inlined_item>, tps: ~[ty_param]) {
+ id: node_id, ident: ident, +path: ast_map::path,
+ item: Option<inlined_item>, +tps: ~[ty_param]) {
ebml_w.start_tag(tag_items_data_item);
encode_name(ecx, ebml_w, ident);
encode_def_id(ebml_w, local_def(id));
let its_ty = node_id_to_type(ecx.tcx, id);
debug!("fn name = %s ty = %s its node id = %d",
ecx.tcx.sess.str_of(ident),
- util::ppaux::ty_to_str(ecx.tcx, its_ty), id);
+ ty_to_str(ecx.tcx, its_ty), id);
encode_type(ecx, ebml_w, its_ty);
- encode_path(ecx, ebml_w, path, ast_map::path_name(ident));
+ // XXX: Bad copy.
+ encode_path(ecx, ebml_w, copy path, ast_map::path_name(ident));
match item {
Some(ref it) => {
(ecx.encode_inlined_item)(ecx, ebml_w, path, (*it));
ebml_w.end_tag();
}
-fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: writer::Encoder,
- impl_path: ast_map::path, should_inline: bool,
+fn encode_info_for_method(ecx: @encode_ctxt,
+ ebml_w: writer::Encoder,
+ +impl_path: ast_map::path,
+ should_inline: bool,
parent_id: node_id,
- m: @method, all_tps: ~[ty_param]) {
+ m: @method,
+ +all_tps: ~[ty_param]) {
debug!("encode_info_for_method: %d %s %u", m.id,
ecx.tcx.sess.str_of(m.ident), all_tps.len());
ebml_w.start_tag(tag_items_data_item);
}
_ => encode_family(ebml_w, purity_fn_family(m.purity))
}
+ let len = all_tps.len();
encode_type_param_bounds(ebml_w, ecx, all_tps);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
encode_name(ecx, ebml_w, m.ident);
- encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
+ // XXX: Bad copy.
+ encode_path(ecx, ebml_w, copy impl_path, ast_map::path_name(m.ident));
encode_self_type(ebml_w, m.self_ty.node);
- if all_tps.len() > 0u || should_inline {
+ if len > 0u || should_inline {
(ecx.encode_inlined_item)(
ecx, ebml_w, impl_path,
ii_method(local_def(parent_id), m));
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
item: @item, index: @mut ~[entry<int>],
- path: ast_map::path) {
+ +path: ast_map::path) {
let tcx = ecx.tcx;
let must_write =
debug!("encoding info for item at %s",
ecx.tcx.sess.codemap.span_to_str(item.span));
- match item.node {
+ match /*bad*/copy item.node {
item_const(_, _) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, purity_fn_family(purity));
+ let tps_len = tps.len();
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
- encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
- encode_attributes(ebml_w, item.attrs);
- if tps.len() > 0u || should_inline(item.attrs) {
+ // XXX: Bad copy.
+ encode_path(ecx, ebml_w, copy path, ast_map::path_name(item.ident));
+ encode_attributes(ebml_w, /*bad*/copy item.attrs);
+ if tps_len > 0u || should_inline(item.attrs) {
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
} else {
encode_symbol(ecx, ebml_w, item.id);
encode_region_param(ecx, ebml_w, item);
ebml_w.end_tag();
}
- item_enum(ref enum_definition, tps) => {
+ item_enum(ref enum_definition, ref tps) => {
add_to_index();
do ebml_w.wr_tag(tag_items_data_item) {
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 't');
- encode_type_param_bounds(ebml_w, ecx, tps);
+ encode_type_param_bounds(ebml_w, ecx, /*bad*/copy *tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident);
for (*enum_definition).variants.each |v| {
encode_variant_id(ebml_w, local_def(v.node.id));
}
- (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
- encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
+ (ecx.encode_inlined_item)(ecx, ebml_w, /*bad*/copy path,
+ ii_item(item));
+ encode_path(ecx, ebml_w, /*bad*/copy path,
+ ast_map::path_name(item.ident));
encode_region_param(ecx, ebml_w, item);
}
encode_enum_variant_info(ecx,
ebml_w,
item.id,
- (*enum_definition).variants,
+ /*bad*/copy (*enum_definition).variants,
path,
index,
- tps);
+ /*bad*/copy *tps);
}
item_struct(struct_def, tps) => {
/* First, encode the fields
These come first because we need to write them to make
the index, and the index needs to be in the item for the
class itself */
- let idx = encode_info_for_struct(ecx, ebml_w, path,
- struct_def.fields, index);
+ // XXX: Bad copy of `path`.
+ let idx = encode_info_for_struct(ecx, ebml_w, copy path,
+ /*bad*/copy struct_def.fields, index);
/* Encode the dtor */
do struct_def.dtor.iter |dtor| {
index.push({val: dtor.node.id, pos: ebml_w.writer.tell()});
ecx.tcx.sess.ident_of(
ecx.tcx.sess.str_of(item.ident) +
~"_dtor"),
- path, if tps.len() > 0u {
+ /*bad*/copy path, if tps.len() > 0u {
Some(ii_dtor(*dtor, item.ident, tps,
local_def(item.id))) }
- else { None }, tps);
+ else { None }, /*bad*/copy tps);
}
/* Index the class*/
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i');
encode_region_param(ecx, ebml_w, item);
- encode_type_param_bounds(ebml_w, ecx, tps);
+ // XXX: Bad copy.
+ encode_type_param_bounds(ebml_w, ecx, copy tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident);
- encode_attributes(ebml_w, item.attrs);
+ encode_attributes(ebml_w, /*bad*/copy item.attrs);
match ty.node {
ast::ty_path(path, _) if path.idents.len() == 1 => {
encode_impl_type_basename(ecx, ebml_w,
do opt_trait.iter() |associated_trait| {
encode_trait_ref(ebml_w, ecx, *associated_trait);
}
- encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
+ // XXX: Bad copy.
+ encode_path(ecx, ebml_w, copy path, ast_map::path_name(item.ident));
ebml_w.end_tag();
let impl_path = vec::append_one(path,
ast_map::path_name(item.ident));
for methods.each |m| {
index.push({val: m.id, pos: ebml_w.writer.tell()});
- encode_info_for_method(ecx, ebml_w, impl_path,
- should_inline(m.attrs), item.id, *m,
- vec::append(tps, m.tps));
+ encode_info_for_method(ecx, ebml_w, /*bad*/copy impl_path,
+ should_inline(/*bad*/copy m.attrs),
+ item.id, *m,
+ vec::append(/*bad*/copy tps, m.tps));
}
}
- item_trait(tps, traits, ref ms) => {
+ item_trait(ref tps, ref traits, ref ms) => {
let provided_methods = dvec::DVec();
add_to_index();
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'I');
encode_region_param(ecx, ebml_w, item);
- encode_type_param_bounds(ebml_w, ecx, tps);
+ encode_type_param_bounds(ebml_w, ecx, /*bad*/copy *tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident);
- encode_attributes(ebml_w, item.attrs);
+ encode_attributes(ebml_w, /*bad*/copy item.attrs);
let mut i = 0u;
for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
match (*ms)[i] {
ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, local_def((*ty_m).id));
encode_name(ecx, ebml_w, mty.ident);
- encode_type_param_bounds(ebml_w, ecx, (*ty_m).tps);
- encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
+ encode_type_param_bounds(ebml_w, ecx,
+ /*bad*/copy (*ty_m).tps);
+ encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
encode_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'r');
ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, local_def(m.id));
encode_name(ecx, ebml_w, mty.ident);
- encode_type_param_bounds(ebml_w, ecx, m.tps);
- encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
+ encode_type_param_bounds(ebml_w, ecx, /*bad*/copy m.tps);
+ encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
encode_self_type(ebml_w, mty.self_ty);
encode_method_sort(ebml_w, 'p');
}
i += 1u;
}
- encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
+ // XXX: Bad copy.
+ encode_path(ecx, ebml_w, copy path, ast_map::path_name(item.ident));
for traits.each |associated_trait| {
encode_trait_ref(ebml_w, ecx, *associated_trait)
}
let polyty = ecx.tcx.tcache.get(local_def(ty_m.id));
encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds);
encode_type(ecx, ebml_w, polyty.ty);
- let m_path = vec::append_one(path,
+ let m_path = vec::append_one(/*bad*/copy path,
ast_map::path_name(item.ident));
encode_path(ecx, ebml_w, m_path, ast_map::path_name(ty_m.ident));
ebml_w.end_tag();
// Finally, output all the provided methods as items.
for provided_methods.each |m| {
index.push({val: m.id, pos: ebml_w.writer.tell()});
- encode_info_for_method(ecx, ebml_w, path, true, item.id, *m,
- m.tps);
+ encode_info_for_method(ecx, ebml_w, /*bad*/copy path,
+ true, item.id, *m, /*bad*/copy m.tps);
}
}
item_mac(*) => fail ~"item macros unimplemented"
}
}
-fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
+fn encode_info_for_foreign_item(ecx: @encode_ctxt,
+ ebml_w: writer::Encoder,
nitem: @foreign_item,
index: @mut ~[entry<int>],
- path: ast_map::path, abi: foreign_abi) {
+ +path: ast_map::path,
+ abi: foreign_abi) {
if !reachable(ecx, nitem.id) { return; }
index.push({val: nitem.id, pos: ebml_w.writer.tell()});
ebml_w.start_tag(tag_items_data_item);
- match nitem.node {
+ match /*bad*/copy nitem.node {
foreign_item_fn(_, purity, tps) => {
encode_def_id(ebml_w, local_def(nitem.id));
encode_family(ebml_w, purity_fn_family(purity));
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
if abi == foreign_abi_rust_intrinsic {
- (ecx.encode_inlined_item)(ecx, ebml_w, path,
+ // XXX: Bad copy of `path`.
+ (ecx.encode_inlined_item)(ecx, ebml_w, copy path,
ii_foreign(nitem));
} else {
encode_symbol(ecx, ebml_w, nitem.id);
encode_info_for_mod(ecx, ebml_w, crate.node.module,
crate_node_id, ~[],
syntax::parse::token::special_idents::invalid);
- visit::visit_crate(*crate, (), visit::mk_vt(@{
+ visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor {
visit_expr: |_e, _cx, _v| { },
visit_item: |i, cx, v, copy ebml_w| {
visit::visit_item(i, cx, v);
match ecx.tcx.items.get(i.id) {
ast_map::node_item(_, pt) => {
- encode_info_for_item(ecx, ebml_w, i, index, *pt);
+ encode_info_for_item(ecx, ebml_w, i, index, /*bad*/copy *pt);
}
_ => fail ~"bad item"
}
match ecx.tcx.items.get(ni.id) {
ast_map::node_foreign_item(_, abi, pt) => {
encode_info_for_foreign_item(ecx, ebml_w, ni,
- index, *pt, abi);
+ index, /*bad*/copy *pt, abi);
}
// case for separate item and foreign-item tables
_ => fail ~"bad foreign item"
,.. *visit::default_visitor()
}));
ebml_w.end_tag();
- return *index;
+ return /*bad*/copy *index;
}
let mut buckets_frozen = ~[];
for buckets.each |bucket| {
- buckets_frozen.push(@**bucket);
+ buckets_frozen.push(@/*bad*/copy **bucket);
}
return buckets_frozen;
}
_ => {/* FIXME (#623): encode other variants */ }
}
}
- meta_list(ref name, items) => {
+ meta_list(ref name, ref items) => {
ebml_w.start_tag(tag_meta_item_list);
ebml_w.start_tag(tag_meta_item_name);
ebml_w.writer.write(str::to_bytes((*name)));
// them in anyway with default values.
fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] {
- fn synthesize_link_attr(ecx: @encode_ctxt, items: ~[@meta_item]) ->
+ fn synthesize_link_attr(ecx: @encode_ctxt, +items: ~[@meta_item]) ->
attribute {
assert (ecx.link_meta.name != ~"");
assert (ecx.link_meta.vers != ~"");
let name_item =
- attr::mk_name_value_item_str(~"name", ecx.link_meta.name);
+ attr::mk_name_value_item_str(~"name",
+ /*bad*/copy ecx.link_meta.name);
let vers_item =
- attr::mk_name_value_item_str(~"vers", ecx.link_meta.vers);
+ attr::mk_name_value_item_str(~"vers",
+ /*bad*/copy ecx.link_meta.vers);
let other_items =
{
for crate.node.attrs.each |attr| {
attrs.push(
if attr::get_attr_name(*attr) != ~"link" {
- *attr
+ /*bad*/copy *attr
} else {
- match attr.node.value.node {
+ match /*bad*/copy attr.node.value.node {
meta_list(_, l) => {
found_link_attr = true;;
synthesize_link_attr(ecx, l)
}
- _ => *attr
+ _ => /*bad*/copy *attr
}
});
}
// Pull the cnums and name,vers,hash out of cstore
let mut deps: ~[numdep] = ~[];
do cstore::iter_crate_data(cstore) |key, val| {
- let dep = {cnum: key, name: ecx.tcx.sess.ident_of(val.name),
+ let dep = {cnum: key,
+ name: ecx.tcx.sess.ident_of(/*bad*/copy val.name),
vers: decoder::get_crate_vers(val.data),
hash: decoder::get_crate_hash(val.data)};
deps.push(dep);
ebml_w.end_tag();
}
+fn encode_lang_items(ecx: @encode_ctxt, ebml_w: writer::Encoder) {
+ ebml_w.start_tag(tag_lang_items);
+
+ for ecx.tcx.lang_items.each_item |def_id, i| {
+ if def_id.crate != local_crate {
+ loop;
+ }
+
+ ebml_w.start_tag(tag_lang_items_item);
+
+ ebml_w.start_tag(tag_lang_items_item_id);
+ ebml_w.writer.write_be_u32(i as u32);
+ ebml_w.end_tag(); // tag_lang_items_item_id
+
+ ebml_w.start_tag(tag_lang_items_item_node_id);
+ ebml_w.writer.write_be_u32(def_id.node as u32);
+ ebml_w.end_tag(); // tag_lang_items_item_node_id
+
+ ebml_w.end_tag(); // tag_lang_items_item
+ }
+
+ ebml_w.end_tag(); // tag_lang_items
+}
+
fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: writer::Encoder,
dep: decoder::crate_dep) {
ebml_w.start_tag(tag_crate_dep);
{mut inline_bytes: 0,
mut attr_bytes: 0,
mut dep_bytes: 0,
+ mut lang_item_bytes: 0,
mut item_bytes: 0,
mut index_bytes: 0,
mut zero_bytes: 0,
reexports2: parms.reexports2,
item_symbols: parms.item_symbols,
discrim_symbols: parms.discrim_symbols,
- link_meta: parms.link_meta,
+ link_meta: /*bad*/copy parms.link_meta,
cstore: parms.cstore,
encode_inlined_item: parms.encode_inlined_item,
type_abbrevs: ty::new_ty_hash()
let ebml_w = writer::Encoder(wr as io::Writer);
- encode_hash(ebml_w, ecx.link_meta.extras_hash);
+ encode_hash(ebml_w, /*bad*/copy ecx.link_meta.extras_hash);
let mut i = wr.pos;
let crate_attrs = synthesize_crate_attrs(ecx, crate);
encode_crate_deps(ecx, ebml_w, ecx.cstore);
ecx.stats.dep_bytes = wr.pos - i;
+ // Encode the language items.
+ i = wr.pos;
+ encode_lang_items(ecx, ebml_w);
+ ecx.stats.lang_item_bytes = wr.pos - i;
+
// Encode and index the items.
ebml_w.start_tag(tag_items);
i = wr.pos;
io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes));
io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes));
io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes));
+ io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes));
io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes));
io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes));
// Get the encoded string for a type
fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
- let cx = @{diag: tcx.diag,
- ds: def_to_str,
- tcx: tcx,
- reachable: |_id| false,
- abbrevs: tyencode::ac_no_abbrevs};
+ let cx = @tyencode::ctxt {
+ diag: tcx.diag,
+ ds: def_to_str,
+ tcx: tcx,
+ reachable: |_id| false,
+ abbrevs: tyencode::ac_no_abbrevs};
do io::with_str_writer |wr| {
tyencode::enc_ty(wr, cx, t);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// A module for searching for libraries
// FIXME (#2658): I'm not happy how this module turned out. Should
// probably just be folded into cstore.
-use result::Result;
+use core::prelude::*;
+
+use core::option;
+use core::os;
+use core::result::Result;
+use core::result;
+use core::str;
+
export FileSearch;
export mk_filesearch;
export pick;
fn mk_filesearch(maybe_sysroot: Option<Path>,
target_triple: &str,
- addl_lib_search_paths: ~[Path]) -> FileSearch {
+ +addl_lib_search_paths: ~[Path]) -> FileSearch {
type filesearch_impl = {sysroot: Path,
addl_lib_search_paths: ~[Path],
target_triple: ~str};
impl filesearch_impl: FileSearch {
- fn sysroot() -> Path { self.sysroot }
+ fn sysroot() -> Path { /*bad*/copy self.sysroot }
fn lib_search_paths() -> ~[Path] {
- let mut paths = self.addl_lib_search_paths;
+ let mut paths = /*bad*/copy self.addl_lib_search_paths;
paths.push(
make_target_lib_path(&self.sysroot,
self.target_triple));
match get_cargo_lib_path_nearest() {
- result::Ok(ref p) => paths.push((*p)),
+ result::Ok(ref p) => paths.push((/*bad*/copy *p)),
result::Err(_) => ()
}
match get_cargo_lib_path() {
- result::Ok(ref p) => paths.push((*p)),
+ result::Ok(ref p) => paths.push((/*bad*/copy *p)),
result::Err(_) => ()
}
paths
sysroot.push_rel(&relative_target_lib_path(target_triple))
}
-fn get_default_sysroot() -> Path {
+fn get_or_default_sysroot() -> Path {
match os::self_exe_path() {
option::Some(ref p) => (*p).pop(),
option::None => fail ~"can't determine value for sysroot"
fn get_sysroot(maybe_sysroot: Option<Path>) -> Path {
match maybe_sysroot {
- option::Some(ref sr) => (*sr),
- option::None => get_default_sysroot()
+ option::Some(ref sr) => (/*bad*/copy *sr),
+ option::None => get_or_default_sysroot()
}
}
fn get_cargo_sysroot() -> Result<Path, ~str> {
- result::Ok(get_default_sysroot().push_many([libdir(), ~"cargo"]))
+ result::Ok(get_or_default_sysroot().push_many([libdir(), ~"cargo"]))
}
fn get_cargo_root() -> Result<Path, ~str> {
let cwd = os::getcwd();
let cwd_cargo = cwd.push(".cargo");
let mut par_cargo = cwd.pop().push(".cargo");
- let mut rslt = result::Ok(cwd_cargo);
+ let mut rslt = result::Ok(copy cwd_cargo); // XXX: Bad copy.
if !os::path_is_dir(&cwd_cargo) && cwd_cargo != p {
while par_cargo != p {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
//! Finds crate binaries and loads their metadata
-use syntax::diagnostic::span_handler;
-use syntax::{ast, attr};
-use syntax::print::pprust;
-use syntax::codemap::span;
+use core::prelude::*;
+
use lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
+use metadata::decoder;
+use metadata::encoder;
use metadata::filesearch::FileSearch;
-use io::WriterUtil;
+use metadata::filesearch;
+use syntax::codemap::span;
+use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
+use syntax::print::pprust;
+use syntax::{ast, attr};
+
+use core::cast;
+use core::flate;
+use core::io::WriterUtil;
+use core::io;
+use core::os::consts::{macos, freebsd, linux, android, win32};
+use core::option;
+use core::ptr;
+use core::str;
+use core::uint;
+use core::vec;
export os;
-export os_macos, os_win32, os_linux, os_freebsd;
+export os_macos, os_win32, os_linux, os_freebsd, os_android;
export ctxt;
export load_library_crate;
export list_file_metadata;
os_macos,
os_win32,
os_linux,
+ os_android,
os_freebsd
}
fn load_library_crate(cx: ctxt) -> {ident: ~str, data: @~[u8]} {
match find_library_crate(cx) {
- Some(ref t) => return (*t),
+ Some(ref t) => return (/*bad*/copy *t),
None => {
cx.diag.span_fatal(
cx.span, fmt!("can't find crate for `%s`",
}
fn find_library_crate(cx: ctxt) -> Option<{ident: ~str, data: @~[u8]}> {
- attr::require_unique_names(cx.diag, cx.metas);
+ attr::require_unique_names(cx.diag, /*bad*/copy cx.metas);
find_library_crate_aux(cx, libname(cx), cx.filesearch)
}
fn libname(cx: ctxt) -> {prefix: ~str, suffix: ~str} {
if cx.static { return {prefix: ~"lib", suffix: ~".rlib"}; }
- match cx.os {
- os_win32 => return {prefix: ~"", suffix: ~".dll"},
- os_macos => return {prefix: ~"lib", suffix: ~".dylib"},
- os_linux => return {prefix: ~"lib", suffix: ~".so"},
- os_freebsd => return {prefix: ~"lib", suffix: ~".so"}
+ let (dll_prefix, dll_suffix) = match cx.os {
+ os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
+ os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
+ os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
+ os_android => (android::DLL_PREFIX, android::DLL_SUFFIX),
+ os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
+ };
+ return {
+ prefix: str::from_slice(dll_prefix),
+ suffix: str::from_slice(dll_suffix)
}
}
nn: {prefix: ~str, suffix: ~str},
filesearch: filesearch::FileSearch) ->
Option<{ident: ~str, data: @~[u8]}> {
- let crate_name = crate_name_from_metas(cx.metas);
+ let crate_name = crate_name_from_metas(/*bad*/copy cx.metas);
let prefix: ~str = nn.prefix + crate_name + ~"-";
- let suffix: ~str = nn.suffix;
+ let suffix: ~str = /*bad*/copy nn.suffix;
let mut matches = ~[];
filesearch::search(filesearch, |path| {
if matches.is_empty() {
None
} else if matches.len() == 1u {
- Some(matches[0])
+ Some(/*bad*/copy matches[0])
} else {
cx.diag.span_err(
cx.span, fmt!("multiple matching crates for `%s`", crate_name));
}
}
-fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> ~str {
+fn crate_name_from_metas(+metas: ~[@ast::meta_item]) -> ~str {
let name_items = attr::find_meta_items_by_name(metas, ~"name");
match vec::last_opt(name_items) {
Some(i) => {
match attr::get_meta_item_value_str(i) {
- Some(ref n) => (*n),
+ Some(ref n) => (/*bad*/copy *n),
// FIXME (#2406): Probably want a warning here since the user
// is using the wrong type of meta item.
_ => fail
}
}
-fn crate_matches(crate_data: @~[u8], metas: ~[@ast::meta_item],
+fn crate_matches(crate_data: @~[u8], +metas: ~[@ast::meta_item],
hash: ~str) -> bool {
let attrs = decoder::get_crate_attributes(crate_data);
let linkage_metas = attr::find_linkage_metas(attrs);
os_macos => ~"__DATA,__note.rustc",
os_win32 => ~".note.rustc",
os_linux => ~".note.rustc",
+ os_android => ~".note.rustc",
os_freebsd => ~".note.rustc"
}
}
// except according to those terms.
#[legacy_exports];
+
export encoder;
export creader;
export cstore;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// Type decoding
// tjc note: Would be great to have a `match check` macro equivalent
// for some of these
+use core::prelude::*;
+
use middle::ty;
use middle::ty::{FnTyBase, FnMeta, FnSig};
+use core::io;
+use core::str;
+use core::uint;
+use core::vec;
use syntax::ast;
use syntax::ast::*;
use syntax::ast_util;
parse_arg(st, conv)
}
-fn parse_ret_ty(st: @pstate, conv: conv_did) -> (ast::ret_style, ty::t) {
- match peek(st) {
- '!' => { next(st); (ast::noreturn, ty::mk_bot(st.tcx)) }
- _ => (ast::return_val, parse_ty(st, conv))
- }
-}
-
fn parse_path(st: @pstate) -> @ast::path {
let mut idents: ~[ast::ident] = ~[];
fn is_last(c: char) -> bool { return c == '(' || c == ':'; }
inputs.push({mode: mode, ty: parse_ty(st, conv)});
}
st.pos += 1u; // eat the ']'
- let (ret_style, ret_ty) = parse_ret_ty(st, conv);
+ let ret_ty = parse_ty(st, conv);
return FnTyBase {
meta: FnMeta {purity: purity,
proto: proto,
onceness: onceness,
bounds: bounds,
- region: region,
- ret_style: ret_style},
+ region: region},
sig: FnSig {inputs: inputs,
output: ret_ty}
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// Type encoding
-use io::WriterUtil;
+use core::prelude::*;
+
+use middle::ty;
+use middle::ty::Vid;
+
+use core::io::WriterUtil;
+use core::io;
+use core::uint;
+use core::vec;
use std::map::HashMap;
use syntax::ast::*;
use syntax::diagnostic::span_handler;
-use middle::ty;
-use middle::ty::vid;
use syntax::print::pprust::*;
+use middle::ty::Vid;
export ctxt;
export ty_abbrev;
export enc_arg;
export enc_vstore;
-type ctxt = {
+struct ctxt {
diag: span_handler,
// Def -> str Callback:
ds: fn@(def_id) -> ~str,
tcx: ty::ctxt,
reachable: fn@(node_id) -> bool,
abbrevs: abbrev_ctxt
-};
+}
// Compact string representation for ty.t values. API ty_str & parse_from_str.
// Extra parameters are for converting to/from def_ids in the string rep.
match cx.abbrevs {
ac_no_abbrevs => {
let result_str = match cx.tcx.short_names_cache.find(t) {
- Some(s) => *s,
+ Some(s) => /*bad*/copy *s,
None => {
let s = do io::with_str_writer |wr| {
- enc_sty(wr, cx, ty::get(t).sty);
+ enc_sty(wr, cx, /*bad*/copy ty::get(t).sty);
};
- cx.tcx.short_names_cache.insert(t, @s);
+ cx.tcx.short_names_cache.insert(t, @copy s);
s
}
};
}
_ => {}
}
- enc_sty(w, cx, ty::get(t).sty);
+ enc_sty(w, cx, /*bad*/copy ty::get(t).sty);
let end = w.tell();
let len = end - pos;
fn estimate_sz(u: uint) -> uint {
w.write_char('|');
enc_bound_region(w, cx, *br);
}
+ ty::br_fresh(id) => {
+ w.write_uint(id);
+ }
}
}
}
}
-fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) {
+fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
match st {
ty::ty_nil => w.write_char('n'),
ty::ty_bot => w.write_char('z'),
enc_arg(w, cx, *arg);
}
w.write_char(']');
- match ft.meta.ret_style {
- noreturn => w.write_char('!'),
- _ => enc_ty(w, cx, ft.sig.output)
- }
+ enc_ty(w, cx, ft.sig.output);
}
fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use c = metadata::common;
use cstore = metadata::cstore;
use driver::session::Session;
use middle::typeck::{method_origin, method_map_entry, vtable_res};
use middle::typeck::{vtable_origin};
use middle::{ty, typeck};
+use middle;
use util::ppaux::ty_to_str;
-use reader = std::ebml::reader;
+use core::{dvec, io, option, vec};
use std::ebml::reader::get_doc;
+use std::ebml::reader;
use std::ebml::writer::Encoder;
use std::ebml;
use std::map::HashMap;
+use std::prettyprint;
use std::serialize;
use std::serialize::{Encodable, EncoderHelpers, DecoderHelpers};
use std::serialize::Decodable;
use syntax::parse;
use syntax::print::pprust;
use syntax::visit;
+use syntax;
use writer = std::ebml::writer;
export maps;
fn decode_inlined_item(cdata: cstore::crate_metadata,
tcx: ty::ctxt,
maps: maps,
- path: ast_map::path,
+ +path: ast_map::path,
par_doc: ebml::Doc) -> Option<ast::inlined_item> {
let dcx = @{cdata: cdata, tcx: tcx, maps: maps};
match par_doc.opt_child(c::tag_ast) {
to_id_range: to_id_range});
let raw_ii = decode_ast(ast_doc);
let ii = renumber_ast(xcx, raw_ii);
+ // XXX: Bad copy of `path`.
ast_map::map_decoded_item(tcx.sess.diagnostic(),
- dcx.tcx.items, path, ii);
+ dcx.tcx.items, copy path, ii);
debug!("Fn named: %s", tcx.sess.str_of(ii.ident()));
decode_side_tables(xcx, ast_doc);
debug!("< Decoded inlined fn: %s::%s",
// inlined items.
fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
fn drop_nested_items(blk: ast::blk_, fld: fold::ast_fold) -> ast::blk_ {
- let stmts_sans_items = do vec::filter(blk.stmts) |stmt| {
+ let stmts_sans_items = do blk.stmts.filtered |stmt| {
match stmt.node {
ast::stmt_expr(_, _) | ast::stmt_semi(_, _) |
- ast::stmt_decl(@{node: ast::decl_local(_), span: _}, _) => true,
- ast::stmt_decl(@{node: ast::decl_item(_), span: _}, _) => false,
+ ast::stmt_decl(@ast::spanned { node: ast::decl_local(_),
+ span: _}, _) => true,
+ ast::stmt_decl(@ast::spanned { node: ast::decl_item(_),
+ span: _}, _) => false,
ast::stmt_mac(*) => fail ~"unexpanded macro in astencode"
}
};
- let blk_sans_items = { stmts: stmts_sans_items,.. blk };
+ // XXX: Bad copy.
+ let blk_sans_items = { stmts: stmts_sans_items,.. copy blk };
fold::noop_fold_block(blk_sans_items, fld)
}
- let fld = fold::make_fold(@{
+ let fld = fold::make_fold(@fold::AstFoldFns {
fold_block: fold::wrap(drop_nested_items),
.. *fold::default_ast_fold()
});
ast::ii_foreign(i) => {
ast::ii_foreign(fld.fold_foreign_item(i))
}
- ast::ii_dtor(ref dtor, nm, tps, parent_id) => {
+ ast::ii_dtor(ref dtor, nm, ref tps, parent_id) => {
let dtor_body = fld.fold_block((*dtor).node.body);
- ast::ii_dtor({node: {body: dtor_body,
- .. (*dtor).node},
- .. (*dtor)}, nm, tps, parent_id)
+ ast::ii_dtor(ast::spanned { node: { body: dtor_body,
+ .. /*bad*/copy (*dtor).node },
+ .. (/*bad*/copy *dtor) },
+ nm, /*bad*/copy *tps, parent_id)
}
}
}
fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
-> ast::inlined_item {
- let fld = fold::make_fold(@{
+ let fld = fold::make_fold(@fold::AstFoldFns{
new_id: |a| xcx.tr_id(a),
new_span: |a| xcx.tr_span(a),
.. *fold::default_ast_fold()
ast::ii_foreign(i) => {
ast::ii_foreign(fld.fold_foreign_item(i))
}
- ast::ii_dtor(ref dtor, nm, tps, parent_id) => {
+ ast::ii_dtor(ref dtor, nm, ref tps, parent_id) => {
let dtor_body = fld.fold_block((*dtor).node.body);
- let dtor_attrs = fld.fold_attributes((*dtor).node.attrs);
- let new_params = fold::fold_ty_params(tps, fld);
+ let dtor_attrs = fld.fold_attributes(/*bad*/copy (*dtor).node.attrs);
+ let new_params = fold::fold_ty_params(/*bad*/copy *tps, fld);
let dtor_id = fld.new_id((*dtor).node.id);
let new_parent = xcx.tr_def_id(parent_id);
let new_self = fld.new_id((*dtor).node.self_id);
- ast::ii_dtor({node: {id: dtor_id, attrs: dtor_attrs,
- self_id: new_self, body: dtor_body},
- .. (*dtor)},
+ ast::ii_dtor(ast::spanned { node: { id: dtor_id,
+ attrs: dtor_attrs,
+ self_id: new_self,
+ body: dtor_body },
+ .. (/*bad*/copy *dtor)},
nm, new_params, new_parent)
}
}
impl ty::bound_region: tr {
fn tr(xcx: extended_decode_ctxt) -> ty::bound_region {
match self {
- ty::br_anon(_) | ty::br_named(_) | ty::br_self => self,
+ ty::br_anon(_) | ty::br_named(_) | ty::br_self |
+ ty::br_fresh(_) => self,
ty::br_cap_avoid(id, br) => ty::br_cap_avoid(xcx.tr_id(id),
@br.tr(xcx))
}
// ty::t doesn't work, and there is no way (atm) to have
// hand-written encoding routines combine with auto-generated
// ones. perhaps we should fix this.
- do ebml_w.emit_from_vec(*dr) |vtable_origin| {
+ do ebml_w.emit_from_vec(/*bad*/copy *dr) |vtable_origin| {
encode_vtable_origin(ecx, ebml_w, *vtable_origin)
}
}
ebml_w: writer::Encoder,
vtable_origin: typeck::vtable_origin) {
do ebml_w.emit_enum(~"vtable_origin") {
- match vtable_origin {
+ match /*bad*/copy vtable_origin {
typeck::vtable_static(def_id, tys, vtable_res) => {
do ebml_w.emit_enum_variant(~"vtable_static", 0u, 3u) {
do ebml_w.emit_enum_variant_arg(0u) {
ebml_w.emit_def_id(def_id)
}
do ebml_w.emit_enum_variant_arg(1u) {
- ebml_w.emit_tys(ecx, tys);
+ ebml_w.emit_tys(ecx, /*bad*/copy tys);
}
do ebml_w.emit_enum_variant_arg(2u) {
encode_vtable_res(ecx, ebml_w, vtable_res);
ebml_w.emit_def_id(def_id)
}
do ebml_w.emit_enum_variant_arg(1u) {
- ebml_w.emit_tys(ecx, tys);
+ ebml_w.emit_tys(ecx, /*bad*/copy tys);
}
}
}
impl @e::encode_ctxt: get_ty_str_ctxt {
fn ty_str_ctxt() -> @tyencode::ctxt {
- @{diag: self.tcx.sess.diagnostic(),
- ds: e::def_to_str,
- tcx: self.tcx,
- reachable: |a| encoder::reachable(self, a),
- abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)}
+ @tyencode::ctxt {diag: self.tcx.sess.diagnostic(),
+ ds: e::def_to_str,
+ tcx: self.tcx,
+ reachable: |a| encoder::reachable(self, a),
+ abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)}
}
}
}
fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]) {
- do self.emit_from_vec(tys) |ty| {
+ // XXX: Bad copy.
+ do self.emit_from_vec(copy tys) |ty| {
self.emit_ty(ecx, *ty)
}
}
fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty) {
do self.emit_rec {
do self.emit_field(~"bounds", 0u) {
- do self.emit_from_vec(*tpbt.bounds) |bs| {
+ do self.emit_from_vec(/*bad*/copy *tpbt.bounds) |bs| {
self.emit_bounds(ecx, *bs);
}
}
do ebml_w.tag(c::tag_table_node_type_subst) {
ebml_w.id(id);
do ebml_w.tag(c::tag_table_val) {
- ebml_w.emit_tys(ecx, *tys)
+ ebml_w.emit_tys(ecx, /*bad*/copy *tys)
}
}
}
do ebml_w.tag(c::tag_table_freevars) {
ebml_w.id(id);
do ebml_w.tag(c::tag_table_val) {
- do ebml_w.emit_from_vec(**fv) |fv_entry| {
+ do ebml_w.emit_from_vec(/*bad*/copy **fv) |fv_entry| {
encode_freevar_entry(ebml_w, *fv_entry)
}
}
fn cfg() -> ast::crate_cfg;
fn parse_sess() -> parse::parse_sess;
fn call_site() -> span;
- fn ident_of(st: ~str) -> ast::ident;
+ fn ident_of(+st: ~str) -> ast::ident;
}
#[cfg(test)]
expn_info: None
}
}
- fn ident_of(st: ~str) -> ast::ident {
+ fn ident_of(+st: ~str) -> ast::ident {
self.interner.intern(@st)
}
}
let out_item = decode_item_ast(ebml_doc);
let exp_str = do io::with_str_writer |w| {
- in_item.encode(&std::prettyprint::Encoder(w))
+ in_item.encode(&prettyprint::Serializer(w))
};
let out_str = do io::with_str_writer |w| {
- out_item.encode(&std::prettyprint::Encoder(w))
+ out_item.encode(&prettyprint::Serializer(w))
};
debug!("expected string: %s", exp_str);
// 1. assignments are always made to mutable locations;
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
-// 4. moves to dnot affect things loaned out in any way
+// 4. moves do not affect things loaned out in any way
-use middle::ty::{CopyValue, MoveValue, ReadValue};
+use core::prelude::*;
-use dvec::DVec;
+use middle::borrowck::{Loan, bckerr, borrowck_ctxt, cmt, inherent_mutability};
+use middle::borrowck::{req_maps, save_and_restore};
+use middle::mem_categorization::{cat_arg, cat_binding, cat_deref, cat_local};
+use middle::mem_categorization::{cat_rvalue, cat_special};
+use middle::mem_categorization::{loan_path, lp_arg, lp_comp, lp_deref};
+use middle::mem_categorization::{lp_local};
+use middle::ty::{CopyValue, MoveValue, ReadValue};
+use middle::ty;
+use util::ppaux::ty_to_str;
+
+use core::cmp;
+use core::dvec::DVec;
+use core::uint;
+use core::vec;
+use std::map::HashMap;
+use syntax::ast::{m_const, m_imm, m_mutbl};
+use syntax::ast;
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::print::pprust;
+use syntax::visit;
export check_loans;
reported: HashMap(),
mut declared_purity: ast::impure_fn,
mut fn_args: @~[]});
- let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr,
- visit_local: check_loans_in_local,
- visit_block: check_loans_in_block,
- visit_fn: check_loans_in_fn,
- .. *visit::default_visitor()});
+ let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr,
+ visit_local: check_loans_in_local,
+ visit_block: check_loans_in_block,
+ visit_fn: check_loans_in_fn,
+ .. *visit::default_visitor()});
visit::visit_crate(*crate, clcx, vt);
}
let callee_ty = ty::node_id_to_type(tcx, callee_id);
match ty::get(callee_ty).sty {
ty::ty_fn(ref fn_ty) => {
- match (*fn_ty).meta.purity {
+ match fn_ty.meta.purity {
ast::pure_fn => return, // case (c) above
ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
self.report_purity_error(
pc, callee_span,
fmt!("access to %s function",
- pprust::purity_to_str((*fn_ty).meta.purity)));
+ fn_ty.meta.purity.to_str()));
}
}
}
Some(ReadValue) | Some(CopyValue) | None => {}
}
- match expr.node {
+ match /*bad*/copy expr.node {
ast::expr_path(*) if self.bccx.last_use_map.contains_key(expr.id) => {
self.check_last_use(expr);
}
// their associated scopes. In phase two, checking loans, we will then make
// sure that all of these loans are honored.
-use middle::mem_categorization::{mem_categorization_ctxt, opt_deref_kind};
+use core::prelude::*;
+
use middle::borrowck::preserve::{preserve_condition, pc_ok, pc_if_pure};
+use middle::borrowck::{Loan, bckres, borrowck_ctxt, err_mutbl, req_maps};
+use middle::mem_categorization::{cat_binding, cat_discr, cmt, comp_variant};
+use middle::mem_categorization::{mem_categorization_ctxt};
+use middle::mem_categorization::{opt_deref_kind};
+use middle::pat_util;
use middle::ty::{ty_region};
+use middle::ty;
+use util::common::indenter;
+use util::ppaux::{expr_repr, region_to_str};
+use core::dvec;
use core::send_map::linear::LinearMap;
+use core::vec;
+use std::map::HashMap;
+use syntax::ast::{m_const, m_imm, m_mutbl};
+use syntax::ast;
+use syntax::codemap::span;
+use syntax::print::pprust;
+use syntax::visit;
export gather_loans;
mut item_ub: 0,
mut root_ub: 0,
mut ignore_adjustments: LinearMap()});
- let v = visit::mk_vt(@{visit_expr: req_loans_in_expr,
- visit_fn: req_loans_in_fn,
- .. *visit::default_visitor()});
+ let v = visit::mk_vt(@visit::Visitor {visit_expr: req_loans_in_expr,
+ visit_fn: req_loans_in_fn,
+ .. *visit::default_visitor()});
visit::visit_crate(*crate, glcx, v);
return glcx.req_maps;
}
}
// Special checks for various kinds of expressions:
- match ex.node {
+ match /*bad*/copy ex.node {
ast::expr_addr_of(mutbl, base) => {
let base_cmt = self.bccx.cat_expr(base);
discr_cmt: cmt,
root_pat: @ast::pat,
arm_id: ast::node_id,
- alt_id: ast::node_id) {
+ match_id: ast::node_id) {
do self.bccx.cat_pattern(discr_cmt, root_pat) |cmt, pat| {
match pat.node {
ast::pat_ident(bm, _, _) if self.pat_is_binding(pat) => {
ast::bind_by_value | ast::bind_by_move => {
// copying does not borrow anything, so no check
// is required
- // as for move, check::alt ensures it's from an rvalue.
+ // as for move, check::_match ensures it's from an rvalue.
}
ast::bind_by_ref(mutbl) => {
// ref x or ref x @ p --- creates a ptr which must
- // remain valid for the scope of the alt
+ // remain valid for the scope of the match
// find the region of the resulting pointer (note that
// the type of such a pattern will *always* be a
// of the function of this node in method preserve():
let arm_scope = ty::re_scope(arm_id);
if self.bccx.is_subregion_of(scope_r, arm_scope) {
- let cmt_discr = self.bccx.cat_discr(cmt, alt_id);
+ let cmt_discr = self.bccx.cat_discr(cmt, match_id);
self.guarantee_valid(cmt_discr, mutbl, scope_r);
} else {
self.guarantee_valid(cmt, mutbl, scope_r);
// Loan(Ex, M, S) = Ls holds if ToAddr(Ex) will remain valid for the entirety
// of the scope S, presuming that the returned set of loans `Ls` are honored.
+use core::prelude::*;
+
+use middle::borrowck::{Loan, bckres, borrowck_ctxt, cmt, err_mutbl};
+use middle::borrowck::{err_out_of_scope};
+use middle::mem_categorization::{cat_arg, cat_binding, cat_discr, cat_comp};
+use middle::mem_categorization::{cat_deref, cat_discr, cat_local};
+use middle::mem_categorization::{cat_special, cat_stack_upvar, comp_field};
+use middle::mem_categorization::{comp_index, comp_variant, region_ptr};
+use middle::ty;
+use util::common::indenter;
+
+use core::result::{Err, Ok, Result};
+use syntax::ast::{m_const, m_imm, m_mutbl};
+use syntax::ast;
+
export public_methods;
-use result::{Result, Ok, Err};
impl borrowck_ctxt {
fn loan(cmt: cmt,
#[legacy_exports];
+use core::prelude::*;
+
+use middle::liveness;
use middle::mem_categorization::*;
-use middle::ty::to_str;
+use middle::region;
+use middle::ty;
use util::common::indenter;
use util::ppaux::{expr_repr, note_and_explain_region};
use util::ppaux::{ty_to_str, region_to_str, explain_region};
+use core::cmp;
use core::dvec::DVec;
+use core::io;
use core::result::{Result, Ok, Err};
use std::list::{List, Cons, Nil};
use std::list;
#[legacy_exports]
pub mod preserve;
-export check_crate, root_map, mutbl_map;
-export check_loans, gather_loans, loan, preserve;
-
fn check_crate(tcx: ty::ctxt,
method_map: typeck::method_map,
last_use_map: liveness::last_use_map,
// set of ids of local vars / formal arguments that are modified / moved.
// this is used in trans for optimization purposes.
-type mutbl_map = std::map::HashMap<ast::node_id, ()>;
+type mutbl_map = HashMap<ast::node_id, ()>;
// Errors that can occur"]
enum bckerr_code {
type bckres<T> = Result<T, bckerr>;
/// a complete record of a loan that was granted
-struct Loan {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}
+pub struct Loan {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}
/// maps computed by `gather_loans` that are then used by `check_loans`
///
/// for the duration of that block/expr
/// - `pure_map`: map from block/expr that must be pure to the error message
/// that should be reported if they are not pure
-type req_maps = {
+pub type req_maps = {
req_loan_map: HashMap<ast::node_id, @DVec<Loan>>,
pure_map: HashMap<ast::node_id, bckerr>
};
cat_variant(self.tcx, self.method_map, arg, enum_did, cmt)
}
- fn cat_discr(cmt: cmt, alt_id: ast::node_id) -> cmt {
- return @{cat:cat_discr(cmt, alt_id),.. *cmt};
+ fn cat_discr(cmt: cmt, match_id: ast::node_id) -> cmt {
+ return @{cat:cat_discr(cmt, match_id),.. *cmt};
}
fn cat_pattern(cmt: cmt, pat: @ast::pat, op: fn(cmt, @ast::pat)) {
self.note_and_explain_bckerr(err);
}
- fn span_err(s: span, m: ~str) {
+ fn span_err(s: span, +m: ~str) {
self.tcx.sess.span_err(s, m);
}
- fn span_note(s: span, m: ~str) {
+ fn span_note(s: span, +m: ~str) {
self.tcx.sess.span_note(s, m);
}
// the scope S.
//
+use core::prelude::*;
+
+use middle::borrowck::{bckerr, bckerr_code, bckres, borrowck_ctxt, cmt};
+use middle::borrowck::{err_mut_uniq, err_mut_variant, err_out_of_root_scope};
+use middle::borrowck::{err_out_of_scope, err_root_not_permitted};
+use middle::mem_categorization::{cat_arg, cat_binding, cat_comp, cat_deref};
+use middle::mem_categorization::{cat_discr, cat_local, cat_special};
+use middle::mem_categorization::{cat_stack_upvar, comp_field, comp_index};
+use middle::mem_categorization::{comp_variant, region_ptr};
+use middle::ty;
+use util::common::indenter;
+
+use syntax::ast::{m_const, m_imm, m_mutbl};
+use syntax::ast;
+
export public_methods, preserve_condition, pc_ok, pc_if_pure;
enum preserve_condition {
self.attempt_root(cmt, base, derefs)
}
}
- cat_discr(base, alt_id) => {
- // Subtle: in an alt, we must ensure that each binding
+ cat_discr(base, match_id) => {
+ // Subtle: in a match, we must ensure that each binding
// variable remains valid for the duration of the arm in
// which it appears, presuming that this arm is taken.
// But it is inconvenient in trans to root something just
// for one arm. Therefore, we insert a cat_discr(),
// basically a special kind of category that says "if this
// value must be dynamically rooted, root it for the scope
- // `alt_id`.
+ // `match_id`.
//
// As an example, consider this scenario:
//
// Technically, the value `x` need only be rooted
// in the `some` arm. However, we evaluate `x` in trans
// before we know what arm will be taken, so we just
- // always root it for the duration of the alt.
+ // always root it for the duration of the match.
//
// As a second example, consider *this* scenario:
//
// found only when checking which pattern matches: but
// this check is done before entering the arm. Therefore,
// even in this case we just choose to keep the value
- // rooted for the entire alt. This means the value will be
+ // rooted for the entire match. This means the value will be
// rooted even if the none arm is taken. Oh well.
//
// At first, I tried to optimize the second case to only
// Nonetheless, if you decide to optimize this case in the
// future, you need only adjust where the cat_discr()
// node appears to draw the line between what will be rooted
- // in the *arm* vs the *alt*.
+ // in the *arm* vs the *match*.
- let alt_rooting_ctxt =
- preserve_ctxt({scope_region: ty::re_scope(alt_id),
+ let match_rooting_ctxt =
+ preserve_ctxt({scope_region: ty::re_scope(match_id),
.. **self});
- (&alt_rooting_ctxt).preserve(base)
+ (&match_rooting_ctxt).preserve(base)
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use syntax::{ast, ast_util};
-use syntax::codemap::span;
-use std::map;
+use core::prelude::*;
+
+use middle::freevars;
+use middle::ty;
+
+use core::option;
+use core::vec;
use std::map::HashMap;
+use std::map;
+use syntax::codemap::span;
+use syntax::{ast, ast_util};
export capture_mode;
export capture_var;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use middle::const_eval::{compare_const_vals, lookup_const_by_id};
-use middle::const_eval::{eval_const_expr, const_val, const_int, const_bool};
-use middle::pat_util::*;
-use middle::ty::*;
-use middle::ty;
-use middle::typeck::method_map;
-use util::ppaux::ty_to_str;
-
-use std::map::HashMap;
-use syntax::ast::*;
-use syntax::ast_util::{variant_def_ids, dummy_sp, unguarded_pat, walk_pat};
-use syntax::codemap::span;
-use syntax::print::pprust::pat_to_str;
-use syntax::visit;
-use std::sort;
-
-struct AltCheckCtxt {
- tcx: ty::ctxt,
- method_map: method_map,
-}
-
-fn check_crate(tcx: ty::ctxt, method_map: method_map, crate: @crate) {
- let cx = @AltCheckCtxt { tcx: tcx, method_map: method_map };
- visit::visit_crate(*crate, (), visit::mk_vt(@{
- visit_expr: |a,b,c| check_expr(cx, a, b, c),
- visit_local: |a,b,c| check_local(cx, a, b, c),
- visit_fn: |kind, decl, body, sp, id, e, v|
- check_fn(cx, kind, decl, body, sp, id, e, v),
- .. *visit::default_visitor::<()>()
- }));
- tcx.sess.abort_if_errors();
-}
-
-fn expr_is_non_moving_lvalue(cx: @AltCheckCtxt, expr: @expr) -> bool {
- if !ty::expr_is_lval(cx.tcx, cx.method_map, expr) {
- return false;
- }
-
- match cx.tcx.value_modes.find(expr.id) {
- Some(MoveValue) => return false,
- Some(CopyValue) | Some(ReadValue) => return true,
- None => {
- cx.tcx.sess.span_bug(expr.span, ~"no entry in value mode map");
- }
- }
-}
-
-fn check_expr(cx: @AltCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) {
- visit::visit_expr(ex, s, v);
- match ex.node {
- expr_match(scrut, ref arms) => {
- // First, check legality of move bindings.
- let is_non_moving_lvalue = expr_is_non_moving_lvalue(cx, ex);
- for arms.each |arm| {
- check_legality_of_move_bindings(cx,
- is_non_moving_lvalue,
- arm.guard.is_some(),
- arm.pats);
- }
-
- check_arms(cx, (*arms));
- /* Check for exhaustiveness */
- // Check for empty enum, because is_useful only works on inhabited
- // types.
- let pat_ty = node_id_to_type(cx.tcx, scrut.id);
- if (*arms).is_empty() {
- if !type_is_empty(cx.tcx, pat_ty) {
- // We know the type is inhabited, so this must be wrong
- cx.tcx.sess.span_err(ex.span, fmt!("non-exhaustive patterns: \
- type %s is non-empty",
- ty_to_str(cx.tcx, pat_ty)));
- }
- // If the type *is* empty, it's vacuously exhaustive
- return;
- }
- match ty::get(pat_ty).sty {
- ty_enum(did, _) => {
- if (*enum_variants(cx.tcx, did)).is_empty() &&
- (*arms).is_empty() {
-
- return;
- }
- }
- _ => { /* We assume only enum types can be uninhabited */ }
- }
- let arms = vec::concat(vec::filter_map((*arms), unguarded_pat));
- check_exhaustive(cx, ex.span, arms);
- }
- _ => ()
- }
-}
-
-// Check for unreachable patterns
-fn check_arms(cx: @AltCheckCtxt, arms: ~[arm]) {
- let mut seen = ~[];
- for arms.each |arm| {
- for arm.pats.each |pat| {
- let v = ~[*pat];
- match is_useful(cx, seen, v) {
- not_useful => {
- cx.tcx.sess.span_err(pat.span, ~"unreachable pattern");
- }
- _ => ()
- }
- if arm.guard.is_none() { seen.push(v); }
- }
- }
-}
-
-fn raw_pat(p: @pat) -> @pat {
- match p.node {
- pat_ident(_, _, Some(s)) => { raw_pat(s) }
- _ => { p }
- }
-}
-
-fn check_exhaustive(cx: @AltCheckCtxt, sp: span, pats: ~[@pat]) {
- assert(pats.is_not_empty());
- let ext = match is_useful(cx, vec::map(pats, |p| ~[*p]), ~[wild()]) {
- not_useful => return, // This is good, wildcard pattern isn't reachable
- useful_ => None,
- useful(ty, ref ctor) => {
- match ty::get(ty).sty {
- ty::ty_bool => {
- match (*ctor) {
- val(const_bool(true)) => Some(~"true"),
- val(const_bool(false)) => Some(~"false"),
- _ => None
- }
- }
- ty::ty_enum(id, _) => {
- let vid = match (*ctor) { variant(id) => id,
- _ => fail ~"check_exhaustive: non-variant ctor" };
- match vec::find(*ty::enum_variants(cx.tcx, id),
- |v| v.id == vid) {
- Some(v) => Some(cx.tcx.sess.str_of(v.name)),
- None => fail ~"check_exhaustive: bad variant in ctor"
- }
- }
- ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
- match (*ctor) {
- vec(n) => Some(fmt!("vectors of length %u", n)),
- _ => None
- }
- }
- _ => None
- }
- }
- };
- let msg = ~"non-exhaustive patterns" + match ext {
- Some(ref s) => ~": " + (*s) + ~" not covered",
- None => ~""
- };
- cx.tcx.sess.span_err(sp, msg);
-}
-
-type matrix = ~[~[@pat]];
-
-enum useful { useful(ty::t, ctor), useful_, not_useful }
-
-enum ctor {
- single,
- variant(def_id),
- val(const_val),
- range(const_val, const_val),
- vec(uint)
-}
-
-impl ctor : cmp::Eq {
- pure fn eq(&self, other: &ctor) -> bool {
- match ((*self), (*other)) {
- (single, single) => true,
- (variant(did_self), variant(did_other)) => did_self == did_other,
- (val(ref cv_self), val(ref cv_other)) =>
- (*cv_self) == (*cv_other),
- (range(ref cv0_self, ref cv1_self),
- range(ref cv0_other, ref cv1_other)) => {
- (*cv0_self) == (*cv0_other) && (*cv1_self) == (*cv1_other)
- }
- (vec(n_self), vec(n_other)) => n_self == n_other,
- (single, _) | (variant(_), _) | (val(_), _) |
- (range(*), _) | (vec(*), _) => {
- false
- }
- }
- }
- pure fn ne(&self, other: &ctor) -> bool { !(*self).eq(other) }
-}
-
-// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
-//
-// Whether a vector `v` of patterns is 'useful' in relation to a set of such
-// vectors `m` is defined as there being a set of inputs that will match `v`
-// but not any of the sets in `m`.
-//
-// This is used both for reachability checking (if a pattern isn't useful in
-// relation to preceding patterns, it is not reachable) and exhaustiveness
-// checking (if a wildcard pattern is useful in relation to a matrix, the
-// matrix isn't exhaustive).
-
-// Note: is_useful doesn't work on empty types, as the paper notes.
-// So it assumes that v is non-empty.
-fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful {
- if m.len() == 0u { return useful_; }
- if m[0].len() == 0u { return not_useful; }
- let real_pat = match vec::find(m, |r| r[0].id != 0) {
- Some(r) => r[0], None => v[0]
- };
- let left_ty = if real_pat.id == 0 { ty::mk_nil(cx.tcx) }
- else { ty::node_id_to_type(cx.tcx, real_pat.id) };
-
- match pat_ctor_id(cx, v[0]) {
- None => {
- match missing_ctor(cx, m, left_ty) {
- None => {
- match ty::get(left_ty).sty {
- ty::ty_bool => {
- match is_useful_specialized(cx, m, v,
- val(const_bool(true)),
- 0u, left_ty){
- not_useful => {
- is_useful_specialized(cx, m, v,
- val(const_bool(false)),
- 0u, left_ty)
- }
- ref u => (*u)
- }
- }
- ty::ty_enum(eid, _) => {
- for (*ty::enum_variants(cx.tcx, eid)).each |va| {
- match is_useful_specialized(cx, m, v, variant(va.id),
- va.args.len(), left_ty) {
- not_useful => (),
- ref u => return (*u)
- }
- }
- not_useful
- }
- ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
- let max_len = do m.foldr(0) |r, max_len| {
- match r[0].node {
- pat_vec(elems, _) => uint::max(elems.len(), max_len),
- _ => max_len
- }
- };
- for uint::range(0, max_len + 1) |n| {
- match is_useful_specialized(cx, m, v, vec(n), n, left_ty) {
- not_useful => (),
- ref u => return (*u)
- }
- }
- not_useful
- }
- _ => {
- let arity = ctor_arity(cx, single, left_ty);
- is_useful_specialized(cx, m, v, single, arity, left_ty)
- }
- }
- }
- Some(ref ctor) => {
- match is_useful(cx, vec::filter_map(m, |r| default(cx, *r)),
- vec::tail(v)) {
- useful_ => useful(left_ty, (*ctor)),
- ref u => (*u)
- }
- }
- }
- }
- Some(ref v0_ctor) => {
- let arity = ctor_arity(cx, (*v0_ctor), left_ty);
- is_useful_specialized(cx, m, v, (*v0_ctor), arity, left_ty)
- }
- }
-}
-
-fn is_useful_specialized(cx: @AltCheckCtxt, m: matrix, v: ~[@pat], ctor: ctor,
- arity: uint, lty: ty::t) -> useful {
- let ms = vec::filter_map(m, |r| specialize(cx, *r, ctor, arity, lty));
- let could_be_useful = is_useful(
- cx, ms, specialize(cx, v, ctor, arity, lty).get());
- match could_be_useful {
- useful_ => useful(lty, ctor),
- ref u => (*u)
- }
-}
-
-fn pat_ctor_id(cx: @AltCheckCtxt, p: @pat) -> Option<ctor> {
- let pat = raw_pat(p);
- match pat.node {
- pat_wild => { None }
- pat_ident(_, _, _) | pat_enum(_, _) => {
- match cx.tcx.def_map.find(pat.id) {
- Some(def_variant(_, id)) => Some(variant(id)),
- Some(def_const(did)) => {
- let const_expr = lookup_const_by_id(cx.tcx, did).get();
- Some(val(eval_const_expr(cx.tcx, const_expr)))
- }
- _ => None
- }
- }
- pat_lit(expr) => { Some(val(eval_const_expr(cx.tcx, expr))) }
- pat_range(lo, hi) => {
- Some(range(eval_const_expr(cx.tcx, lo), eval_const_expr(cx.tcx, hi)))
- }
- pat_struct(*) => {
- match cx.tcx.def_map.find(pat.id) {
- Some(def_variant(_, id)) => Some(variant(id)),
- _ => Some(single)
- }
- }
- pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) |
- pat_region(*) => {
- Some(single)
- }
- pat_vec(elems, tail) => {
- match tail {
- Some(_) => None,
- None => Some(vec(elems.len()))
- }
- }
- }
-}
-
-fn is_wild(cx: @AltCheckCtxt, p: @pat) -> bool {
- let pat = raw_pat(p);
- match pat.node {
- pat_wild => { true }
- pat_ident(_, _, _) => {
- match cx.tcx.def_map.find(pat.id) {
- Some(def_variant(_, _)) | Some(def_const(*)) => { false }
- _ => { true }
- }
- }
- _ => { false }
- }
-}
-
-fn missing_ctor(cx: @AltCheckCtxt,
- m: matrix,
- left_ty: ty::t)
- -> Option<ctor> {
- match ty::get(left_ty).sty {
- ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) | ty::ty_tup(_) |
- ty::ty_rec(_) | ty::ty_struct(*) => {
- for m.each |r| {
- if !is_wild(cx, r[0]) { return None; }
- }
- return Some(single);
- }
- ty::ty_enum(eid, _) => {
- let mut found = ~[];
- for m.each |r| {
- do option::iter(&pat_ctor_id(cx, r[0])) |id| {
- if !vec::contains(found, id) {
- found.push(*id);
- }
- }
- }
- let variants = ty::enum_variants(cx.tcx, eid);
- if found.len() != (*variants).len() {
- for vec::each(*variants) |v| {
- if !found.contains(&(variant(v.id))) {
- return Some(variant(v.id));
- }
- }
- fail;
- } else { None }
- }
- ty::ty_nil => None,
- ty::ty_bool => {
- let mut true_found = false, false_found = false;
- for m.each |r| {
- match pat_ctor_id(cx, r[0]) {
- None => (),
- Some(val(const_bool(true))) => true_found = true,
- Some(val(const_bool(false))) => false_found = true,
- _ => fail ~"impossible case"
- }
- }
- if true_found && false_found { None }
- else if true_found { Some(val(const_bool(false))) }
- else { Some(val(const_bool(true))) }
- }
- ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
-
- // Find the lengths and tails of all vector patterns.
- let vec_pat_lens = do m.filter_map |r| {
- match r[0].node {
- pat_vec(elems, tail) => {
- Some((elems.len(), tail.is_some()))
- }
- _ => None
- }
- };
-
- // Sort them by length such that for patterns of the same length,
- // those with a destructured tail come first.
- let mut sorted_vec_lens = sort::merge_sort(vec_pat_lens,
- |&(len1, tail1), &(len2, tail2)| {
- if len1 == len2 {
- tail1 > tail2
- } else {
- len1 <= len2
- }
- }
- );
- vec::dedup(&mut sorted_vec_lens);
-
- let mut found_tail = false;
- let mut next = 0;
- let mut missing = None;
- for sorted_vec_lens.each |&(length, tail)| {
- if length != next {
- missing = Some(next);
- break;
- }
- if tail {
- found_tail = true;
- break;
- }
- next += 1;
- }
-
- // We found patterns of all lengths within <0, next), yet there was no
- // pattern with a tail - therefore, we report vec(next) as missing.
- if !found_tail {
- missing = Some(next);
- }
- match missing {
- Some(k) => Some(vec(k)),
- None => None
- }
- }
- _ => Some(single)
- }
-}
-
-fn ctor_arity(cx: @AltCheckCtxt, ctor: ctor, ty: ty::t) -> uint {
- match ty::get(ty).sty {
- ty::ty_tup(fs) => fs.len(),
- ty::ty_rec(fs) => fs.len(),
- ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u,
- ty::ty_enum(eid, _) => {
- let id = match ctor { variant(id) => id,
- _ => fail ~"impossible case" };
- match vec::find(*ty::enum_variants(cx.tcx, eid), |v| v.id == id ) {
- Some(v) => v.args.len(),
- None => fail ~"impossible case"
- }
- }
- ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
- ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
- match ctor {
- vec(n) => n,
- _ => 0u
- }
- }
- _ => 0u
- }
-}
-
-fn wild() -> @pat {
- @{id: 0, node: pat_wild, span: syntax::ast_util::dummy_sp()}
-}
-
-fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint,
- left_ty: ty::t) -> Option<~[@pat]> {
- let r0 = raw_pat(r[0]);
- match r0.node {
- pat_wild => Some(vec::append(vec::from_elem(arity, wild()),
- vec::tail(r))),
- pat_ident(_, _, _) => {
- match cx.tcx.def_map.find(r0.id) {
- Some(def_variant(_, id)) => {
- if variant(id) == ctor_id { Some(vec::tail(r)) }
- else { None }
- }
- Some(def_const(did)) => {
- let const_expr = lookup_const_by_id(cx.tcx, did).get();
- let e_v = eval_const_expr(cx.tcx, const_expr);
- let match_ = match ctor_id {
- val(ref v) => compare_const_vals(e_v, (*v)) == 0,
- range(ref c_lo, ref c_hi) => {
- compare_const_vals((*c_lo), e_v) >= 0 &&
- compare_const_vals((*c_hi), e_v) <= 0
- }
- single => true,
- _ => fail ~"type error"
- };
- if match_ { Some(vec::tail(r)) } else { None }
- }
- _ => Some(vec::append(vec::from_elem(arity, wild()), vec::tail(r)))
- }
- }
- pat_enum(_, args) => {
- match cx.tcx.def_map.get(r0.id) {
- def_variant(_, id) if variant(id) == ctor_id => {
- let args = match args {
- Some(args) => args,
- None => vec::from_elem(arity, wild())
- };
- Some(vec::append(args, vec::tail(r)))
- }
- def_variant(_, _) => None,
- def_struct(*) => {
- // XXX: Is this right? --pcw
- let new_args;
- match args {
- Some(args) => new_args = args,
- None => new_args = vec::from_elem(arity, wild())
- }
- Some(vec::append(new_args, vec::tail(r)))
- }
- _ => None
- }
- }
- pat_rec(flds, _) => {
- let ty_flds = match ty::get(left_ty).sty {
- ty::ty_rec(flds) => flds,
- _ => fail ~"bad type for pat_rec"
- };
- let args = vec::map(ty_flds, |ty_fld| {
- match vec::find(flds, |f| f.ident == ty_fld.ident ) {
- Some(f) => f.pat,
- _ => wild()
- }
- });
- Some(vec::append(args, vec::tail(r)))
- }
- pat_struct(_, flds, _) => {
- // Is this a struct or an enum variant?
- match cx.tcx.def_map.get(r0.id) {
- def_variant(_, variant_id) => {
- if variant(variant_id) == ctor_id {
- // XXX: Is this right? --pcw
- let args = flds.map(|ty_field| {
- match vec::find(flds, |f| f.ident == ty_field.ident) {
- Some(f) => f.pat,
- _ => wild()
- }
- });
- Some(vec::append(args, vec::tail(r)))
- } else {
- None
- }
- }
- _ => {
- // Grab the class data that we care about.
- let class_fields, class_id;
- match ty::get(left_ty).sty {
- ty::ty_struct(cid, _) => {
- class_id = cid;
- class_fields = ty::lookup_struct_fields(cx.tcx,
- class_id);
- }
- _ => {
- cx.tcx.sess.span_bug(r0.span, ~"struct pattern \
- didn't resolve to a \
- struct");
- }
- }
- let args = vec::map(class_fields, |class_field| {
- match vec::find(flds, |f| f.ident == class_field.ident ) {
- Some(f) => f.pat,
- _ => wild()
- }
- });
- Some(vec::append(args, vec::tail(r)))
- }
- }
- }
- pat_tup(args) => Some(vec::append(args, vec::tail(r))),
- pat_box(a) | pat_uniq(a) | pat_region(a) =>
- Some(vec::append(~[a], vec::tail(r))),
- pat_lit(expr) => {
- let e_v = eval_const_expr(cx.tcx, expr);
- let match_ = match ctor_id {
- val(ref v) => compare_const_vals(e_v, (*v)) == 0,
- range(ref c_lo, ref c_hi) => {
- compare_const_vals((*c_lo), e_v) >= 0 &&
- compare_const_vals((*c_hi), e_v) <= 0
- }
- single => true,
- _ => fail ~"type error"
- };
- if match_ { Some(vec::tail(r)) } else { None }
- }
- pat_range(lo, hi) => {
- let (c_lo, c_hi) = match ctor_id {
- val(ref v) => ((*v), (*v)),
- range(ref lo, ref hi) => ((*lo), (*hi)),
- single => return Some(vec::tail(r)),
- _ => fail ~"type error"
- };
- let v_lo = eval_const_expr(cx.tcx, lo),
- v_hi = eval_const_expr(cx.tcx, hi);
- let match_ = compare_const_vals(c_lo, v_lo) >= 0 &&
- compare_const_vals(c_hi, v_hi) <= 0;
- if match_ { Some(vec::tail(r)) } else { None }
- }
- pat_vec(elems, tail) => {
- match ctor_id {
- vec(_) => {
- if elems.len() < arity && tail.is_some() {
- Some(vec::append(
- vec::append(elems, vec::from_elem(
- arity - elems.len(), wild()
- )),
- vec::tail(r)
- ))
- } else if elems.len() == arity {
- Some(vec::append(elems, vec::tail(r)))
- } else {
- None
- }
- }
- _ => None
- }
- }
- }
-}
-
-fn default(cx: @AltCheckCtxt, r: ~[@pat]) -> Option<~[@pat]> {
- if is_wild(cx, r[0]) { Some(vec::tail(r)) }
- else { None }
-}
-
-fn check_local(cx: @AltCheckCtxt, loc: @local, &&s: (), v: visit::vt<()>) {
- visit::visit_local(loc, s, v);
- if is_refutable(cx, loc.node.pat) {
- cx.tcx.sess.span_err(loc.node.pat.span,
- ~"refutable pattern in local binding");
- }
-
- // Check legality of move bindings.
- let is_lvalue = match loc.node.init {
- Some(init) => expr_is_non_moving_lvalue(cx, init),
- None => true
- };
- check_legality_of_move_bindings(cx, is_lvalue, false, [ loc.node.pat ]);
-}
-
-fn check_fn(cx: @AltCheckCtxt,
- kind: visit::fn_kind,
- decl: fn_decl,
- body: blk,
- sp: span,
- id: node_id,
- &&s: (),
- v: visit::vt<()>) {
- visit::visit_fn(kind, decl, body, sp, id, s, v);
- for decl.inputs.each |input| {
- if is_refutable(cx, input.pat) {
- cx.tcx.sess.span_err(input.pat.span,
- ~"refutable pattern in function argument");
- }
- }
-}
-
-fn is_refutable(cx: @AltCheckCtxt, pat: &pat) -> bool {
- match cx.tcx.def_map.find(pat.id) {
- Some(def_variant(enum_id, _)) => {
- if vec::len(*ty::enum_variants(cx.tcx, enum_id)) != 1u {
- return true;
- }
- }
- Some(def_const(*)) => return true,
- _ => ()
- }
-
- match pat.node {
- pat_box(sub) | pat_uniq(sub) | pat_region(sub) |
- pat_ident(_, _, Some(sub)) => {
- is_refutable(cx, sub)
- }
- pat_wild | pat_ident(_, _, None) => { false }
- pat_lit(@{node: expr_lit(@{node: lit_nil, _}), _}) => { false } // "()"
- pat_lit(_) | pat_range(_, _) => { true }
- pat_rec(fields, _) => {
- fields.any(|f| is_refutable(cx, f.pat))
- }
- pat_struct(_, fields, _) => {
- fields.any(|f| is_refutable(cx, f.pat))
- }
- pat_tup(elts) => {
- elts.any(|elt| is_refutable(cx, *elt))
- }
- pat_enum(_, Some(args)) => {
- args.any(|a| is_refutable(cx, *a))
- }
- pat_enum(_,_) => { false }
- pat_vec(*) => { true }
- }
-}
-
-// Legality of move bindings checking
-
-fn check_legality_of_move_bindings(cx: @AltCheckCtxt,
- is_lvalue: bool,
- has_guard: bool,
- pats: &[@pat]) {
- let tcx = cx.tcx;
- let def_map = tcx.def_map;
- let mut by_ref_span = None;
- let mut any_by_move = false;
- for pats.each |pat| {
- do pat_bindings(def_map, *pat) |bm, id, span, _path| {
- match bm {
- bind_by_ref(_) => {
- by_ref_span = Some(span);
- }
- bind_by_move => {
- any_by_move = true;
- }
- bind_by_value => {}
- bind_infer => {
- match cx.tcx.value_modes.find(id) {
- Some(MoveValue) => any_by_move = true,
- Some(CopyValue) | Some(ReadValue) => {}
- None => {
- cx.tcx.sess.span_bug(span, ~"no mode for pat \
- binding");
- }
- }
- }
- }
- }
- }
-
- let check_move: &fn(@pat, Option<@pat>) = |p, sub| {
- // check legality of moving out of the enum
- if sub.is_some() {
- tcx.sess.span_err(
- p.span,
- ~"cannot bind by-move with sub-bindings");
- } else if has_guard {
- tcx.sess.span_err(
- p.span,
- ~"cannot bind by-move into a pattern guard");
- } else if by_ref_span.is_some() {
- tcx.sess.span_err(
- p.span,
- ~"cannot bind by-move and by-ref \
- in the same pattern");
- tcx.sess.span_note(
- by_ref_span.get(),
- ~"by-ref binding occurs here");
- } else if is_lvalue {
- tcx.sess.span_err(
- p.span,
- ~"cannot bind by-move when \
- matching an lvalue");
- }
- };
-
- if !any_by_move { return; } // pointless micro-optimization
- for pats.each |pat| {
- do walk_pat(*pat) |p| {
- if pat_is_binding(def_map, p) {
- match p.node {
- pat_ident(bind_by_move, _, sub) => check_move(p, sub),
- pat_ident(bind_infer, _, sub) => {
- match tcx.value_modes.find(p.id) {
- Some(MoveValue) => check_move(p, sub),
- Some(CopyValue) | Some(ReadValue) => {}
- None => {
- cx.tcx.sess.span_bug(
- pat.span, ~"no mode for pat binding");
- }
- }
- }
- _ => {}
- }
- }
- }
-
- // Now check to ensure that any move binding is not behind an @ or &.
- // This is always illegal.
- let vt = visit::mk_vt(@{
- visit_pat: |pat, behind_bad_pointer, v| {
- let error_out = || {
- cx.tcx.sess.span_err(pat.span, ~"by-move pattern \
- bindings may not occur \
- behind @ or & bindings");
- };
- match pat.node {
- pat_ident(binding_mode, _, sub) => {
- debug!("(check legality of move) checking pat \
- ident with behind_bad_pointer %?",
- behind_bad_pointer);
- match binding_mode {
- bind_by_move if behind_bad_pointer => error_out(),
- bind_infer if behind_bad_pointer => {
- match cx.tcx.value_modes.find(pat.id) {
- Some(MoveValue) => error_out(),
- Some(CopyValue) |
- Some(ReadValue) => {}
- None => {
- cx.tcx.sess.span_bug(pat.span,
- ~"no mode for pat binding");
- }
- }
- }
- _ => {}
- }
- match sub {
- None => {}
- Some(subpat) => {
- (v.visit_pat)(subpat, behind_bad_pointer, v);
- }
- }
- }
- pat_box(subpat) | pat_region(subpat) => {
- (v.visit_pat)(subpat, true, v);
- }
- _ => visit::visit_pat(pat, behind_bad_pointer, v)
- }
- },
- .. *visit::default_visitor::<bool>()
- });
- (vt.visit_pat)(*pat, false, vt);
- }
-}
-
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use syntax::ast::*;
-use syntax::{visit, ast_util, ast_map};
+use core::prelude::*;
+
use driver::session::Session;
+use middle::resolve;
+use middle::ty;
+use middle::typeck;
+use util::ppaux;
+
+use core::dvec::DVec;
+use core::option;
use std::map::HashMap;
-use dvec::DVec;
+use syntax::ast::*;
+use syntax::{visit, ast_util, ast_map};
fn check_crate(sess: Session, crate: @crate, ast_map: ast_map::map,
def_map: resolve::DefMap,
method_map: typeck::method_map, tcx: ty::ctxt) {
- visit::visit_crate(*crate, false, visit::mk_vt(@{
+ visit::visit_crate(*crate, false, visit::mk_vt(@visit::Visitor {
visit_item: |a,b,c| check_item(sess, ast_map, def_map, a, b, c),
visit_pat: check_pat,
visit_expr: |a,b,c|
fn check_pat(p: @pat, &&_is_const: bool, v: visit::vt<bool>) {
fn is_str(e: @expr) -> bool {
match e.node {
- expr_vstore(@{node: expr_lit(@{node: lit_str(_), _}), _},
+ expr_vstore(@{node: expr_lit(@spanned { node: lit_str(_),
+ _}), _},
expr_vstore_uniq) => true,
_ => false
}
~"disallowed operator in constant expression");
return;
}
- expr_lit(@{node: lit_str(_), _}) => { }
+ expr_lit(@spanned {node: lit_str(_), _}) => { }
expr_binary(_, _, _) | expr_unary(_, _) => {
if method_map.contains_key(e.id) {
sess.span_err(e.span, ~"user-defined operators are not \
let ety = ty::expr_ty(tcx, e);
if !ty::type_is_numeric(ety) {
sess.span_err(e.span, ~"can not cast to `" +
- util::ppaux::ty_to_str(tcx, ety) +
+ ppaux::ty_to_str(tcx, ety) +
~"` in a constant expression");
}
}
expr_call(callee, _, false) => {
match def_map.find(callee.id) {
Some(def_struct(*)) => {} // OK.
+ Some(def_variant(*)) => {} // OK.
_ => {
sess.span_err(
e.span,
~"function calls in constants are limited to \
- structure constructors");
+ struct and enum constructors");
}
}
}
}
}
match e.node {
- expr_lit(@{node: lit_int(v, t), _}) => {
+ expr_lit(@spanned {node: lit_int(v, t), _}) => {
if t != ty_char {
if (v as u64) > ast_util::int_ty_max(
if t == ty_i { sess.targ_cfg.int_type } else { t }) {
}
}
}
- expr_lit(@{node: lit_uint(v, t), _}) => {
+ expr_lit(@spanned {node: lit_uint(v, t), _}) => {
if v > ast_util::uint_ty_max(
if t == ty_u { sess.targ_cfg.uint_type } else { t }) {
sess.span_err(e.span, ~"literal out of range for its type");
idstack: @DVec()
};
- let visitor = visit::mk_vt(@{
+ let visitor = visit::mk_vt(@visit::Visitor {
visit_item: visit_item,
visit_expr: visit_expr,
.. *visit::default_visitor()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
+use middle::ty;
+
use syntax::ast::*;
use syntax::visit;
fn check_crate(tcx: ty::ctxt, crate: @crate) {
visit::visit_crate(*crate,
{in_loop: false, can_ret: true},
- visit::mk_vt(@{
+ visit::mk_vt(@visit::Visitor {
visit_item: |i, _cx, v| {
visit::visit_item(i, {in_loop: false, can_ret: true}, v);
},
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::prelude::*;
+
+use middle::const_eval::{compare_const_vals, lookup_const_by_id};
+use middle::const_eval::{eval_const_expr, const_val, const_int, const_bool};
+use middle::pat_util::*;
+use middle::ty::*;
+use middle::ty;
+use middle::typeck::method_map;
+use util::ppaux::ty_to_str;
+
+use core::cmp;
+use core::option;
+use core::uint;
+use core::vec;
+use std::map::HashMap;
+use std::sort;
+use syntax::ast::*;
+use syntax::ast_util::{variant_def_ids, dummy_sp, unguarded_pat, walk_pat};
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::print::pprust::pat_to_str;
+use syntax::visit;
+
+struct MatchCheckCtxt {
+ tcx: ty::ctxt,
+ method_map: method_map,
+}
+
+fn check_crate(tcx: ty::ctxt, method_map: method_map, crate: @crate) {
+ let cx = @MatchCheckCtxt { tcx: tcx, method_map: method_map };
+ visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor {
+ visit_expr: |a,b,c| check_expr(cx, a, b, c),
+ visit_local: |a,b,c| check_local(cx, a, b, c),
+ visit_fn: |kind, decl, body, sp, id, e, v|
+ check_fn(cx, kind, decl, body, sp, id, e, v),
+ .. *visit::default_visitor::<()>()
+ }));
+ tcx.sess.abort_if_errors();
+}
+
+fn expr_is_non_moving_lvalue(cx: @MatchCheckCtxt, expr: @expr) -> bool {
+ if !ty::expr_is_lval(cx.tcx, cx.method_map, expr) {
+ return false;
+ }
+
+ match cx.tcx.value_modes.find(expr.id) {
+ Some(MoveValue) => return false,
+ Some(CopyValue) | Some(ReadValue) => return true,
+ None => {
+ cx.tcx.sess.span_bug(expr.span, ~"no entry in value mode map");
+ }
+ }
+}
+
+fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) {
+ visit::visit_expr(ex, s, v);
+ match ex.node {
+ expr_match(scrut, ref arms) => {
+ // First, check legality of move bindings.
+ let is_non_moving_lvalue = expr_is_non_moving_lvalue(cx, ex);
+ for arms.each |arm| {
+ check_legality_of_move_bindings(cx,
+ is_non_moving_lvalue,
+ arm.guard.is_some(),
+ arm.pats);
+ }
+
+ check_arms(cx, (/*bad*/copy *arms));
+ /* Check for exhaustiveness */
+ // Check for empty enum, because is_useful only works on inhabited
+ // types.
+ let pat_ty = node_id_to_type(cx.tcx, scrut.id);
+ if (*arms).is_empty() {
+ if !type_is_empty(cx.tcx, pat_ty) {
+ // We know the type is inhabited, so this must be wrong
+ cx.tcx.sess.span_err(ex.span, fmt!("non-exhaustive patterns: \
+ type %s is non-empty",
+ ty_to_str(cx.tcx, pat_ty)));
+ }
+ // If the type *is* empty, it's vacuously exhaustive
+ return;
+ }
+ match ty::get(pat_ty).sty {
+ ty_enum(did, _) => {
+ if (*enum_variants(cx.tcx, did)).is_empty() &&
+ (*arms).is_empty() {
+
+ return;
+ }
+ }
+ _ => { /* We assume only enum types can be uninhabited */ }
+ }
+ let arms = vec::concat(vec::filter_map((*arms), unguarded_pat));
+ check_exhaustive(cx, ex.span, arms);
+ }
+ _ => ()
+ }
+}
+
+// Check for unreachable patterns
+fn check_arms(cx: @MatchCheckCtxt, arms: ~[arm]) {
+ let mut seen = ~[];
+ for arms.each |arm| {
+ for arm.pats.each |pat| {
+ let v = ~[*pat];
+ match is_useful(cx, seen, v) {
+ not_useful => {
+ cx.tcx.sess.span_err(pat.span, ~"unreachable pattern");
+ }
+ _ => ()
+ }
+ if arm.guard.is_none() { seen.push(v); }
+ }
+ }
+}
+
+fn raw_pat(p: @pat) -> @pat {
+ match p.node {
+ pat_ident(_, _, Some(s)) => { raw_pat(s) }
+ _ => { p }
+ }
+}
+
+fn check_exhaustive(cx: @MatchCheckCtxt, sp: span, pats: ~[@pat]) {
+ assert(pats.is_not_empty());
+ let ext = match is_useful(cx, vec::map(pats, |p| ~[*p]), ~[wild()]) {
+ not_useful => return, // This is good, wildcard pattern isn't reachable
+ useful_ => None,
+ useful(ty, ref ctor) => {
+ match ty::get(ty).sty {
+ ty::ty_bool => {
+ match (*ctor) {
+ val(const_bool(true)) => Some(~"true"),
+ val(const_bool(false)) => Some(~"false"),
+ _ => None
+ }
+ }
+ ty::ty_enum(id, _) => {
+ let vid = match (*ctor) { variant(id) => id,
+ _ => fail ~"check_exhaustive: non-variant ctor" };
+ match vec::find(*ty::enum_variants(cx.tcx, id),
+ |v| v.id == vid) {
+ Some(v) => Some(cx.tcx.sess.str_of(v.name)),
+ None => fail ~"check_exhaustive: bad variant in ctor"
+ }
+ }
+ ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
+ match (*ctor) {
+ vec(n) => Some(fmt!("vectors of length %u", n)),
+ _ => None
+ }
+ }
+ _ => None
+ }
+ }
+ };
+ let msg = ~"non-exhaustive patterns" + match ext {
+ Some(ref s) => ~": " + (*s) + ~" not covered",
+ None => ~""
+ };
+ cx.tcx.sess.span_err(sp, msg);
+}
+
+type matrix = ~[~[@pat]];
+
+enum useful { useful(ty::t, ctor), useful_, not_useful }
+
+enum ctor {
+ single,
+ variant(def_id),
+ val(const_val),
+ range(const_val, const_val),
+ vec(uint)
+}
+
+impl ctor : cmp::Eq {
+ pure fn eq(&self, other: &ctor) -> bool {
+ match ((*self), (*other)) {
+ (single, single) => true,
+ (variant(did_self), variant(did_other)) => did_self == did_other,
+ (val(ref cv_self), val(ref cv_other)) =>
+ (*cv_self) == (*cv_other),
+ (range(ref cv0_self, ref cv1_self),
+ range(ref cv0_other, ref cv1_other)) => {
+ (*cv0_self) == (*cv0_other) && (*cv1_self) == (*cv1_other)
+ }
+ (vec(n_self), vec(n_other)) => n_self == n_other,
+ (single, _) | (variant(_), _) | (val(_), _) |
+ (range(*), _) | (vec(*), _) => {
+ false
+ }
+ }
+ }
+ pure fn ne(&self, other: &ctor) -> bool { !(*self).eq(other) }
+}
+
+// Algorithm from http://moscova.inria.fr/~maranget/papers/warn/index.html
+//
+// Whether a vector `v` of patterns is 'useful' in relation to a set of such
+// vectors `m` is defined as there being a set of inputs that will match `v`
+// but not any of the sets in `m`.
+//
+// This is used both for reachability checking (if a pattern isn't useful in
+// relation to preceding patterns, it is not reachable) and exhaustiveness
+// checking (if a wildcard pattern is useful in relation to a matrix, the
+// matrix isn't exhaustive).
+
+// Note: is_useful doesn't work on empty types, as the paper notes.
+// So it assumes that v is non-empty.
+fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: ~[@pat]) -> useful {
+ if m.len() == 0u { return useful_; }
+ if m[0].len() == 0u { return not_useful; }
+ let real_pat = match vec::find(m, |r| r[0].id != 0) {
+ Some(r) => r[0], None => v[0]
+ };
+ let left_ty = if real_pat.id == 0 { ty::mk_nil(cx.tcx) }
+ else { ty::node_id_to_type(cx.tcx, real_pat.id) };
+
+ match pat_ctor_id(cx, v[0]) {
+ None => {
+ match missing_ctor(cx, m, left_ty) {
+ None => {
+ match ty::get(left_ty).sty {
+ ty::ty_bool => {
+ match is_useful_specialized(cx, m, v,
+ val(const_bool(true)),
+ 0u, left_ty){
+ not_useful => {
+ is_useful_specialized(cx, m, v,
+ val(const_bool(false)),
+ 0u, left_ty)
+ }
+ ref u => (/*bad*/copy *u)
+ }
+ }
+ ty::ty_enum(eid, _) => {
+ for (*ty::enum_variants(cx.tcx, eid)).each |va| {
+ match is_useful_specialized(cx, m, v, variant(va.id),
+ va.args.len(), left_ty) {
+ not_useful => (),
+ ref u => return (/*bad*/copy *u)
+ }
+ }
+ not_useful
+ }
+ ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
+ let max_len = do m.foldr(0) |r, max_len| {
+ match /*bad*/copy r[0].node {
+ pat_vec(elems, _) => uint::max(elems.len(), max_len),
+ _ => max_len
+ }
+ };
+ for uint::range(0, max_len + 1) |n| {
+ match is_useful_specialized(cx, m, v, vec(n), n, left_ty) {
+ not_useful => (),
+ ref u => return (/*bad*/copy *u)
+ }
+ }
+ not_useful
+ }
+ _ => {
+ let arity = ctor_arity(cx, single, left_ty);
+ is_useful_specialized(cx, m, v, single, arity, left_ty)
+ }
+ }
+ }
+ Some(ref ctor) => {
+ match is_useful(cx, vec::filter_map(m, |r| default(cx, copy *r)),
+ vec::tail(v)) {
+ useful_ => useful(left_ty, (/*bad*/copy *ctor)),
+ ref u => (/*bad*/copy *u)
+ }
+ }
+ }
+ }
+ Some(ref v0_ctor) => {
+ let arity = ctor_arity(cx, (*v0_ctor), left_ty);
+ is_useful_specialized(cx, m, v, /*bad*/copy *v0_ctor, arity, left_ty)
+ }
+ }
+}
+
+fn is_useful_specialized(cx: @MatchCheckCtxt, m: matrix, +v: ~[@pat],
+ +ctor: ctor, arity: uint, lty: ty::t) -> useful {
+ let ms = vec::filter_map(m, |r| specialize(cx, copy *r,
+ ctor, arity, lty));
+ let could_be_useful = is_useful(
+ cx, ms, specialize(cx, v, ctor, arity, lty).get());
+ match could_be_useful {
+ useful_ => useful(lty, ctor),
+ ref u => (/*bad*/copy *u)
+ }
+}
+
+fn pat_ctor_id(cx: @MatchCheckCtxt, p: @pat) -> Option<ctor> {
+ let pat = raw_pat(p);
+ match /*bad*/copy pat.node {
+ pat_wild => { None }
+ pat_ident(_, _, _) | pat_enum(_, _) => {
+ match cx.tcx.def_map.find(pat.id) {
+ Some(def_variant(_, id)) => Some(variant(id)),
+ Some(def_const(did)) => {
+ let const_expr = lookup_const_by_id(cx.tcx, did).get();
+ Some(val(eval_const_expr(cx.tcx, const_expr)))
+ }
+ _ => None
+ }
+ }
+ pat_lit(expr) => { Some(val(eval_const_expr(cx.tcx, expr))) }
+ pat_range(lo, hi) => {
+ Some(range(eval_const_expr(cx.tcx, lo), eval_const_expr(cx.tcx, hi)))
+ }
+ pat_struct(*) => {
+ match cx.tcx.def_map.find(pat.id) {
+ Some(def_variant(_, id)) => Some(variant(id)),
+ _ => Some(single)
+ }
+ }
+ pat_box(_) | pat_uniq(_) | pat_rec(_, _) | pat_tup(_) |
+ pat_region(*) => {
+ Some(single)
+ }
+ pat_vec(elems, tail) => {
+ match tail {
+ Some(_) => None,
+ None => Some(vec(elems.len()))
+ }
+ }
+ }
+}
+
+fn is_wild(cx: @MatchCheckCtxt, p: @pat) -> bool {
+ let pat = raw_pat(p);
+ match pat.node {
+ pat_wild => { true }
+ pat_ident(_, _, _) => {
+ match cx.tcx.def_map.find(pat.id) {
+ Some(def_variant(_, _)) | Some(def_const(*)) => { false }
+ _ => { true }
+ }
+ }
+ _ => { false }
+ }
+}
+
+fn missing_ctor(cx: @MatchCheckCtxt,
+ m: matrix,
+ left_ty: ty::t)
+ -> Option<ctor> {
+ match ty::get(left_ty).sty {
+ ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) | ty::ty_tup(_) |
+ ty::ty_rec(_) | ty::ty_struct(*) => {
+ for m.each |r| {
+ if !is_wild(cx, r[0]) { return None; }
+ }
+ return Some(single);
+ }
+ ty::ty_enum(eid, _) => {
+ let mut found = ~[];
+ for m.each |r| {
+ do option::iter(&pat_ctor_id(cx, r[0])) |id| {
+ if !vec::contains(found, id) {
+ found.push(/*bad*/copy *id);
+ }
+ }
+ }
+ let variants = ty::enum_variants(cx.tcx, eid);
+ if found.len() != (*variants).len() {
+ for vec::each(*variants) |v| {
+ if !found.contains(&(variant(v.id))) {
+ return Some(variant(v.id));
+ }
+ }
+ fail;
+ } else { None }
+ }
+ ty::ty_nil => None,
+ ty::ty_bool => {
+ let mut true_found = false, false_found = false;
+ for m.each |r| {
+ match pat_ctor_id(cx, r[0]) {
+ None => (),
+ Some(val(const_bool(true))) => true_found = true,
+ Some(val(const_bool(false))) => false_found = true,
+ _ => fail ~"impossible case"
+ }
+ }
+ if true_found && false_found { None }
+ else if true_found { Some(val(const_bool(false))) }
+ else { Some(val(const_bool(true))) }
+ }
+ ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
+
+ // Find the lengths and tails of all vector patterns.
+ let vec_pat_lens = do m.filter_map |r| {
+ match /*bad*/copy r[0].node {
+ pat_vec(elems, tail) => {
+ Some((elems.len(), tail.is_some()))
+ }
+ _ => None
+ }
+ };
+
+ // Sort them by length such that for patterns of the same length,
+ // those with a destructured tail come first.
+ let mut sorted_vec_lens = sort::merge_sort(vec_pat_lens,
+ |&(len1, tail1), &(len2, tail2)| {
+ if len1 == len2 {
+ tail1 > tail2
+ } else {
+ len1 <= len2
+ }
+ }
+ );
+ vec::dedup(&mut sorted_vec_lens);
+
+ let mut found_tail = false;
+ let mut next = 0;
+ let mut missing = None;
+ for sorted_vec_lens.each |&(length, tail)| {
+ if length != next {
+ missing = Some(next);
+ break;
+ }
+ if tail {
+ found_tail = true;
+ break;
+ }
+ next += 1;
+ }
+
+ // We found patterns of all lengths within <0, next), yet there was no
+ // pattern with a tail - therefore, we report vec(next) as missing.
+ if !found_tail {
+ missing = Some(next);
+ }
+ match missing {
+ Some(k) => Some(vec(k)),
+ None => None
+ }
+ }
+ _ => Some(single)
+ }
+}
+
+fn ctor_arity(cx: @MatchCheckCtxt, ctor: ctor, ty: ty::t) -> uint {
+ match /*bad*/copy ty::get(ty).sty {
+ ty::ty_tup(fs) => fs.len(),
+ ty::ty_rec(fs) => fs.len(),
+ ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u,
+ ty::ty_enum(eid, _) => {
+ let id = match ctor { variant(id) => id,
+ _ => fail ~"impossible case" };
+ match vec::find(*ty::enum_variants(cx.tcx, eid), |v| v.id == id ) {
+ Some(v) => v.args.len(),
+ None => fail ~"impossible case"
+ }
+ }
+ ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
+ ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
+ match ctor {
+ vec(n) => n,
+ _ => 0u
+ }
+ }
+ _ => 0u
+ }
+}
+
+fn wild() -> @pat {
+ @{id: 0, node: pat_wild, span: ast_util::dummy_sp()}
+}
+
+fn specialize(cx: @MatchCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint,
+ left_ty: ty::t) -> Option<~[@pat]> {
+ let r0 = raw_pat(r[0]);
+ match /*bad*/copy r0.node {
+ pat_wild => Some(vec::append(vec::from_elem(arity, wild()),
+ vec::tail(r))),
+ pat_ident(_, _, _) => {
+ match cx.tcx.def_map.find(r0.id) {
+ Some(def_variant(_, id)) => {
+ if variant(id) == ctor_id { Some(vec::tail(r)) }
+ else { None }
+ }
+ Some(def_const(did)) => {
+ let const_expr = lookup_const_by_id(cx.tcx, did).get();
+ let e_v = eval_const_expr(cx.tcx, const_expr);
+ let match_ = match ctor_id {
+ val(ref v) => compare_const_vals(e_v, (*v)) == 0,
+ range(ref c_lo, ref c_hi) => {
+ compare_const_vals((*c_lo), e_v) >= 0 &&
+ compare_const_vals((*c_hi), e_v) <= 0
+ }
+ single => true,
+ _ => fail ~"type error"
+ };
+ if match_ { Some(vec::tail(r)) } else { None }
+ }
+ _ => Some(vec::append(vec::from_elem(arity, wild()), vec::tail(r)))
+ }
+ }
+ pat_enum(_, args) => {
+ match cx.tcx.def_map.get(r0.id) {
+ def_variant(_, id) if variant(id) == ctor_id => {
+ let args = match args {
+ Some(args) => args,
+ None => vec::from_elem(arity, wild())
+ };
+ Some(vec::append(args, vec::tail(r)))
+ }
+ def_variant(_, _) => None,
+ def_struct(*) => {
+ // XXX: Is this right? --pcw
+ let new_args;
+ match args {
+ Some(args) => new_args = args,
+ None => new_args = vec::from_elem(arity, wild())
+ }
+ Some(vec::append(new_args, vec::tail(r)))
+ }
+ _ => None
+ }
+ }
+ pat_rec(flds, _) => {
+ let ty_flds = match /*bad*/copy ty::get(left_ty).sty {
+ ty::ty_rec(flds) => flds,
+ _ => fail ~"bad type for pat_rec"
+ };
+ let args = vec::map(ty_flds, |ty_fld| {
+ match vec::find(flds, |f| f.ident == ty_fld.ident ) {
+ Some(f) => f.pat,
+ _ => wild()
+ }
+ });
+ Some(vec::append(args, vec::tail(r)))
+ }
+ pat_struct(_, flds, _) => {
+ // Is this a struct or an enum variant?
+ match cx.tcx.def_map.get(r0.id) {
+ def_variant(_, variant_id) => {
+ if variant(variant_id) == ctor_id {
+ // XXX: Is this right? --pcw
+ let args = flds.map(|ty_field| {
+ match vec::find(flds, |f| f.ident == ty_field.ident) {
+ Some(f) => f.pat,
+ _ => wild()
+ }
+ });
+ Some(vec::append(args, vec::tail(r)))
+ } else {
+ None
+ }
+ }
+ _ => {
+ // Grab the class data that we care about.
+ let class_fields, class_id;
+ match ty::get(left_ty).sty {
+ ty::ty_struct(cid, _) => {
+ class_id = cid;
+ class_fields = ty::lookup_struct_fields(cx.tcx,
+ class_id);
+ }
+ _ => {
+ cx.tcx.sess.span_bug(r0.span, ~"struct pattern \
+ didn't resolve to a \
+ struct");
+ }
+ }
+ let args = vec::map(class_fields, |class_field| {
+ match vec::find(flds, |f| f.ident == class_field.ident ) {
+ Some(f) => f.pat,
+ _ => wild()
+ }
+ });
+ Some(vec::append(args, vec::tail(r)))
+ }
+ }
+ }
+ pat_tup(args) => Some(vec::append(args, vec::tail(r))),
+ pat_box(a) | pat_uniq(a) | pat_region(a) =>
+ Some(vec::append(~[a], vec::tail(r))),
+ pat_lit(expr) => {
+ let e_v = eval_const_expr(cx.tcx, expr);
+ let match_ = match ctor_id {
+ val(ref v) => compare_const_vals(e_v, (*v)) == 0,
+ range(ref c_lo, ref c_hi) => {
+ compare_const_vals((*c_lo), e_v) >= 0 &&
+ compare_const_vals((*c_hi), e_v) <= 0
+ }
+ single => true,
+ _ => fail ~"type error"
+ };
+ if match_ { Some(vec::tail(r)) } else { None }
+ }
+ pat_range(lo, hi) => {
+ let (c_lo, c_hi) = match ctor_id {
+ val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)),
+ range(ref lo, ref hi) => ((/*bad*/copy *lo), (/*bad*/copy *hi)),
+ single => return Some(vec::tail(r)),
+ _ => fail ~"type error"
+ };
+ let v_lo = eval_const_expr(cx.tcx, lo),
+ v_hi = eval_const_expr(cx.tcx, hi);
+ let match_ = compare_const_vals(c_lo, v_lo) >= 0 &&
+ compare_const_vals(c_hi, v_hi) <= 0;
+ if match_ { Some(vec::tail(r)) } else { None }
+ }
+ pat_vec(elems, tail) => {
+ match ctor_id {
+ vec(_) => {
+ if elems.len() < arity && tail.is_some() {
+ // XXX: Bad copy.
+ Some(vec::append(
+ vec::append(copy elems, vec::from_elem(
+ arity - elems.len(), wild()
+ )),
+ vec::tail(r)
+ ))
+ } else if elems.len() == arity {
+ Some(vec::append(elems, vec::tail(r)))
+ } else {
+ None
+ }
+ }
+ _ => None
+ }
+ }
+ }
+}
+
+fn default(cx: @MatchCheckCtxt, r: ~[@pat]) -> Option<~[@pat]> {
+ if is_wild(cx, r[0]) { Some(vec::tail(r)) }
+ else { None }
+}
+
+fn check_local(cx: @MatchCheckCtxt, loc: @local, &&s: (), v: visit::vt<()>) {
+ visit::visit_local(loc, s, v);
+ if is_refutable(cx, loc.node.pat) {
+ cx.tcx.sess.span_err(loc.node.pat.span,
+ ~"refutable pattern in local binding");
+ }
+
+ // Check legality of move bindings.
+ let is_lvalue = match loc.node.init {
+ Some(init) => expr_is_non_moving_lvalue(cx, init),
+ None => true
+ };
+ check_legality_of_move_bindings(cx, is_lvalue, false, [ loc.node.pat ]);
+}
+
+fn check_fn(cx: @MatchCheckCtxt,
+ kind: visit::fn_kind,
+ decl: fn_decl,
+ body: blk,
+ sp: span,
+ id: node_id,
+ &&s: (),
+ v: visit::vt<()>) {
+ visit::visit_fn(kind, decl, body, sp, id, s, v);
+ for decl.inputs.each |input| {
+ if is_refutable(cx, input.pat) {
+ cx.tcx.sess.span_err(input.pat.span,
+ ~"refutable pattern in function argument");
+ }
+ }
+}
+
+fn is_refutable(cx: @MatchCheckCtxt, pat: &pat) -> bool {
+ match cx.tcx.def_map.find(pat.id) {
+ Some(def_variant(enum_id, _)) => {
+ if vec::len(*ty::enum_variants(cx.tcx, enum_id)) != 1u {
+ return true;
+ }
+ }
+ Some(def_const(*)) => return true,
+ _ => ()
+ }
+
+ match /*bad*/copy pat.node {
+ pat_box(sub) | pat_uniq(sub) | pat_region(sub) |
+ pat_ident(_, _, Some(sub)) => {
+ is_refutable(cx, sub)
+ }
+ pat_wild | pat_ident(_, _, None) => { false }
+ pat_lit(@{node: expr_lit(@spanned { node: lit_nil, _}), _}) => {
+ // "()"
+ false
+ }
+ pat_lit(_) | pat_range(_, _) => { true }
+ pat_rec(fields, _) => {
+ fields.any(|f| is_refutable(cx, f.pat))
+ }
+ pat_struct(_, fields, _) => {
+ fields.any(|f| is_refutable(cx, f.pat))
+ }
+ pat_tup(elts) => {
+ elts.any(|elt| is_refutable(cx, *elt))
+ }
+ pat_enum(_, Some(args)) => {
+ args.any(|a| is_refutable(cx, *a))
+ }
+ pat_enum(_,_) => { false }
+ pat_vec(*) => { true }
+ }
+}
+
+// Legality of move bindings checking
+
+fn check_legality_of_move_bindings(cx: @MatchCheckCtxt,
+ is_lvalue: bool,
+ has_guard: bool,
+ pats: &[@pat]) {
+ let tcx = cx.tcx;
+ let def_map = tcx.def_map;
+ let mut by_ref_span = None;
+ let mut any_by_move = false;
+ for pats.each |pat| {
+ do pat_bindings(def_map, *pat) |bm, id, span, _path| {
+ match bm {
+ bind_by_ref(_) => {
+ by_ref_span = Some(span);
+ }
+ bind_by_move => {
+ any_by_move = true;
+ }
+ bind_by_value => {}
+ bind_infer => {
+ match cx.tcx.value_modes.find(id) {
+ Some(MoveValue) => any_by_move = true,
+ Some(CopyValue) | Some(ReadValue) => {}
+ None => {
+ cx.tcx.sess.span_bug(span, ~"no mode for pat \
+ binding");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ let check_move: &fn(@pat, Option<@pat>) = |p, sub| {
+ // check legality of moving out of the enum
+ if sub.is_some() {
+ tcx.sess.span_err(
+ p.span,
+ ~"cannot bind by-move with sub-bindings");
+ } else if has_guard {
+ tcx.sess.span_err(
+ p.span,
+ ~"cannot bind by-move into a pattern guard");
+ } else if by_ref_span.is_some() {
+ tcx.sess.span_err(
+ p.span,
+ ~"cannot bind by-move and by-ref \
+ in the same pattern");
+ tcx.sess.span_note(
+ by_ref_span.get(),
+ ~"by-ref binding occurs here");
+ } else if is_lvalue {
+ tcx.sess.span_err(
+ p.span,
+ ~"cannot bind by-move when \
+ matching an lvalue");
+ }
+ };
+
+ if !any_by_move { return; } // pointless micro-optimization
+ for pats.each |pat| {
+ do walk_pat(*pat) |p| {
+ if pat_is_binding(def_map, p) {
+ match p.node {
+ pat_ident(bind_by_move, _, sub) => check_move(p, sub),
+ pat_ident(bind_infer, _, sub) => {
+ match tcx.value_modes.find(p.id) {
+ Some(MoveValue) => check_move(p, sub),
+ Some(CopyValue) | Some(ReadValue) => {}
+ None => {
+ cx.tcx.sess.span_bug(
+ pat.span, ~"no mode for pat binding");
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ }
+
+ // Now check to ensure that any move binding is not behind an @ or &.
+ // This is always illegal.
+ let vt = visit::mk_vt(@visit::Visitor {
+ visit_pat: |pat, behind_bad_pointer, v| {
+ let error_out = || {
+ cx.tcx.sess.span_err(pat.span, ~"by-move pattern \
+ bindings may not occur \
+ behind @ or & bindings");
+ };
+ match pat.node {
+ pat_ident(binding_mode, _, sub) => {
+ debug!("(check legality of move) checking pat \
+ ident with behind_bad_pointer %?",
+ behind_bad_pointer);
+ match binding_mode {
+ bind_by_move if behind_bad_pointer => error_out(),
+ bind_infer if behind_bad_pointer => {
+ match cx.tcx.value_modes.find(pat.id) {
+ Some(MoveValue) => error_out(),
+ Some(CopyValue) |
+ Some(ReadValue) => {}
+ None => {
+ cx.tcx.sess.span_bug(pat.span,
+ ~"no mode for pat binding");
+ }
+ }
+ }
+ _ => {}
+ }
+ match sub {
+ None => {}
+ Some(subpat) => {
+ (v.visit_pat)(subpat, behind_bad_pointer, v);
+ }
+ }
+ }
+ pat_box(subpat) | pat_region(subpat) => {
+ (v.visit_pat)(subpat, true, v);
+ }
+ _ => visit::visit_pat(pat, behind_bad_pointer, v)
+ }
+ },
+ .. *visit::default_visitor::<bool>()
+ });
+ (vt.visit_pat)(*pat, false, vt);
+ }
+}
+
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::resolve;
+use middle::ty;
+use middle;
+
+use core::cmp;
+use core::float;
+use core::vec;
use syntax::{ast, ast_map, ast_util, visit};
use syntax::ast::*;
// & and * pointers
// copies of general constants
//
-// (in theory, probably not at first: if/alt on integer-const
+// (in theory, probably not at first: if/match on integer-const
// conditions / descriminants)
//
// - Non-constants: everything else.
Some(x) => x,
None => {
let cn =
- match e.node {
+ match /*bad*/copy e.node {
ast::expr_lit(lit) => {
match lit.node {
ast::lit_str(*) |
fn process_crate(crate: @ast::crate,
def_map: resolve::DefMap,
tcx: ty::ctxt) {
- let v = visit::mk_simple_visitor(@{
+ let v = visit::mk_simple_visitor(@visit::SimpleVisitor {
visit_expr_post: |e| { classify(e, def_map, tcx); },
.. *visit::default_simple_visitor()
});
fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val {
match eval_const_expr_partial(tcx, e) {
- Ok(ref r) => (*r),
- Err(ref s) => fail (*s)
+ Ok(ref r) => (/*bad*/copy *r),
+ Err(ref s) => fail (/*bad*/copy *s)
}
}
Ok(const_uint(i)) => Ok(const_uint(-i)),
Ok(const_str(_)) => Err(~"Negate on string"),
Ok(const_bool(_)) => Err(~"Negate on boolean"),
- ref err => (*err)
+ ref err => (/*bad*/copy *err)
}
}
expr_unary(not, inner) => {
fn lit_to_const(lit: @lit) -> const_val {
match lit.node {
- lit_str(s) => const_str(*s),
+ lit_str(s) => const_str(/*bad*/copy *s),
lit_int(n, _) => const_int(n),
lit_uint(n, _) => const_uint(n),
lit_int_unsuffixed(n) => const_int(n),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// A pass that annotates for each loops and functions with the free
// variables that they contain.
-use syntax::print::pprust::path_to_str;
+use middle::resolve;
+use middle::ty;
+
+use core::int;
+use core::option::*;
+use core::vec;
use std::map::*;
-use option::*;
-use syntax::{ast, ast_util, visit};
use syntax::codemap::span;
+use syntax::print::pprust::path_to_str;
+use syntax::{ast, ast_util, visit};
export annotate_freevars;
export freevar_map;
}
};
- let v = visit::mk_vt(@{visit_item: ignore_item, visit_expr: walk_expr,
- .. *visit::default_visitor()});
+ let v = visit::mk_vt(@visit::Visitor {visit_item: ignore_item,
+ visit_expr: walk_expr,
+ .. *visit::default_visitor()});
(v.visit_block)(blk, 1, v);
- return @*refs;
+ return @/*bad*/copy *refs;
}
// Build a map from every function and for-each body to a set of the
};
let visitor =
- visit::mk_simple_visitor(@{visit_fn: walk_fn,
- .. *visit::default_simple_visitor()});
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_fn: walk_fn,
+ .. *visit::default_simple_visitor()});
visit::visit_crate(*crate, (), visitor);
return freevars;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use middle::freevars::freevar_entry;
+use middle::freevars;
use middle::lint::{non_implicitly_copyable_typarams, implicit_copies};
+use middle::liveness;
+use middle::pat_util;
use middle::ty::{CopyValue, MoveValue, ReadValue};
use middle::ty::{Kind, kind_copyable, kind_noncopyable, kind_const};
+use middle::ty;
+use middle::typeck;
+use middle;
use util::ppaux::{ty_to_str, tys_to_str};
+use core::option;
+use core::str;
+use core::vec;
use std::map::HashMap;
use syntax::ast::*;
use syntax::codemap::span;
if ty::kind_can_be_sent(k) {
kinds.push(~"owned");
} else if ty::kind_is_durable(k) {
- kinds.push(~"durable");
+ kinds.push(~"&static");
}
str::connect(kinds, ~" ")
}
-type rval_map = std::map::HashMap<node_id, ()>;
+type rval_map = HashMap<node_id, ()>;
type ctx = {tcx: ty::ctxt,
method_map: typeck::method_map,
method_map: method_map,
last_use_map: last_use_map,
current_item: -1};
- let visit = visit::mk_vt(@{
+ let visit = visit::mk_vt(@visit::Visitor {
visit_arm: check_arm,
visit_expr: check_expr,
visit_stmt: check_stmt,
}
}
- match e.node {
+ match /*bad*/copy e.node {
expr_assign(_, ex) |
expr_unary(box(_), ex) | expr_unary(uniq(_), ex) |
expr_ret(Some(ex)) => {
Some(ex) => {
// All noncopyable fields must be overridden
let t = ty::expr_ty(cx.tcx, ex);
- let ty_fields = match ty::get(t).sty {
+ let ty_fields = match /*bad*/copy ty::get(t).sty {
ty::ty_rec(f) => f,
ty::ty_struct(did, ref substs) =>
ty::struct_fields(cx.tcx, did, &(*substs)),
fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
match stmt.node {
- stmt_decl(@{node: decl_local(locals), _}, _) => {
+ stmt_decl(@spanned {node: decl_local(ref locals), _}, _) => {
for locals.each |local| {
match local.node.init {
Some(expr) =>
match ty::get(ty).sty {
ty::ty_param(*) => {
tcx.sess.span_err(sp, ~"value may contain borrowed \
- pointers; use `durable` bound");
+ pointers; use `&static` bound");
}
_ => {
tcx.sess.span_err(sp, ~"value may contain borrowed \
// worries.
let target_ty = ty::expr_ty(cx.tcx, target);
let target_substs = match ty::get(target_ty).sty {
- ty::ty_trait(_, ref substs, _) => {(*substs)}
+ ty::ty_trait(_, ref substs, _) => {(/*bad*/copy *substs)}
_ => { return; /* not a cast to a trait */ }
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
//
// * Functions called by the compiler itself.
+use core::prelude::*;
+
use driver::session::Session;
-use metadata::csearch::{each_path, get_item_attrs};
+use metadata::csearch::{each_lang_item, get_item_attrs};
use metadata::cstore::{iter_crate_data};
use metadata::decoder::{dl_def, dl_field, dl_impl};
use syntax::ast::{crate, def_fn, def_id, def_ty, lit_str, meta_item};
use syntax::ast::{meta_list, meta_name_value, meta_word};
use syntax::ast_util::{local_def};
-use syntax::visit::{default_simple_visitor, mk_simple_visitor};
+use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor};
use syntax::visit::{visit_crate, visit_item};
+use core::ptr;
use std::map::HashMap;
use str_eq = str::eq;
+pub enum LangItem {
+ ConstTraitLangItem, // 0
+ CopyTraitLangItem, // 1
+ OwnedTraitLangItem, // 2
+ DurableTraitLangItem, // 3
+
+ DropTraitLangItem, // 4
+
+ AddTraitLangItem, // 5
+ SubTraitLangItem, // 6
+ MulTraitLangItem, // 7
+ DivTraitLangItem, // 8
+ ModuloTraitLangItem, // 9
+ NegTraitLangItem, // 10
+ NotTraitLangItem, // 11
+ BitXorTraitLangItem, // 12
+ BitAndTraitLangItem, // 13
+ BitOrTraitLangItem, // 14
+ ShlTraitLangItem, // 15
+ ShrTraitLangItem, // 16
+ IndexTraitLangItem, // 17
+
+ EqTraitLangItem, // 18
+ OrdTraitLangItem, // 19
+
+ StrEqFnLangItem, // 20
+ UniqStrEqFnLangItem, // 21
+ AnnihilateFnLangItem, // 22
+ LogTypeFnLangItem, // 23
+ FailFnLangItem, // 24
+ FailBoundsCheckFnLangItem, // 25
+ ExchangeMallocFnLangItem, // 26
+ ExchangeFreeFnLangItem, // 27
+ MallocFnLangItem, // 28
+ FreeFnLangItem, // 29
+}
+
struct LanguageItems {
- mut const_trait: Option<def_id>,
- mut copy_trait: Option<def_id>,
- mut owned_trait: Option<def_id>,
- mut durable_trait: Option<def_id>,
-
- mut drop_trait: Option<def_id>,
-
- mut add_trait: Option<def_id>,
- mut sub_trait: Option<def_id>,
- mut mul_trait: Option<def_id>,
- mut div_trait: Option<def_id>,
- mut modulo_trait: Option<def_id>,
- mut neg_trait: Option<def_id>,
- mut bitxor_trait: Option<def_id>,
- mut bitand_trait: Option<def_id>,
- mut bitor_trait: Option<def_id>,
- mut shl_trait: Option<def_id>,
- mut shr_trait: Option<def_id>,
- mut index_trait: Option<def_id>,
-
- mut eq_trait: Option<def_id>,
- mut ord_trait: Option<def_id>,
-
- mut str_eq_fn: Option<def_id>,
- mut uniq_str_eq_fn: Option<def_id>,
- mut annihilate_fn: Option<def_id>,
- mut log_type_fn: Option<def_id>
+ items: [ Option<def_id> * 30 ]
}
-mod language_items {
- #[legacy_exports];
- fn make() -> LanguageItems {
+impl LanguageItems {
+ static pub fn new() -> LanguageItems {
LanguageItems {
- const_trait: None,
- copy_trait: None,
- owned_trait: None,
- durable_trait: None,
-
- drop_trait: None,
-
- add_trait: None,
- sub_trait: None,
- mul_trait: None,
- div_trait: None,
- modulo_trait: None,
- neg_trait: None,
- bitxor_trait: None,
- bitand_trait: None,
- bitor_trait: None,
- shl_trait: None,
- shr_trait: None,
- index_trait: None,
-
- eq_trait: None,
- ord_trait: None,
-
- str_eq_fn: None,
- uniq_str_eq_fn: None,
- annihilate_fn: None,
- log_type_fn: None
+ items: [ None, ..30 ]
+ }
+ }
+
+ fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) {
+ for self.items.eachi |i, &item| {
+ if !f(item.get(), i) {
+ break;
+ }
}
}
-}
-fn LanguageItemCollector(crate: @crate, session: Session,
- items: &r/LanguageItems)
- -> LanguageItemCollector/&r {
+ static pub fn item_name(index: uint) -> &static/str {
+ match index {
+ 0 => "const",
+ 1 => "copy",
+ 2 => "owned",
+ 3 => "durable",
+
+ 4 => "drop",
+
+ 5 => "add",
+ 6 => "sub",
+ 7 => "mul",
+ 8 => "div",
+ 9 => "modulo",
+ 10 => "neg",
+ 11 => "not",
+ 12 => "bitxor",
+ 13 => "bitand",
+ 14 => "bitor",
+ 15 => "shl",
+ 16 => "shr",
+ 17 => "index",
+ 18 => "eq",
+ 19 => "ord",
+
+ 20 => "str_eq",
+ 21 => "uniq_str_eq",
+ 22 => "annihilate",
+ 23 => "log_type",
+ 24 => "fail_",
+ 25 => "fail_bounds_check",
+ 26 => "exchange_malloc",
+ 27 => "exchange_free",
+ 28 => "malloc",
+ 29 => "free",
+
+ _ => "???"
+ }
+ }
+
+ // XXX: Method macros sure would be nice here.
+
+ pub fn const_trait(&const self) -> def_id {
+ self.items[ConstTraitLangItem as uint].get()
+ }
+ pub fn copy_trait(&const self) -> def_id {
+ self.items[CopyTraitLangItem as uint].get()
+ }
+ pub fn owned_trait(&const self) -> def_id {
+ self.items[OwnedTraitLangItem as uint].get()
+ }
+ pub fn durable_trait(&const self) -> def_id {
+ self.items[DurableTraitLangItem as uint].get()
+ }
+
+ pub fn drop_trait(&const self) -> def_id {
+ self.items[DropTraitLangItem as uint].get()
+ }
+
+ pub fn add_trait(&const self) -> def_id {
+ self.items[AddTraitLangItem as uint].get()
+ }
+ pub fn sub_trait(&const self) -> def_id {
+ self.items[SubTraitLangItem as uint].get()
+ }
+ pub fn mul_trait(&const self) -> def_id {
+ self.items[MulTraitLangItem as uint].get()
+ }
+ pub fn div_trait(&const self) -> def_id {
+ self.items[DivTraitLangItem as uint].get()
+ }
+ pub fn modulo_trait(&const self) -> def_id {
+ self.items[ModuloTraitLangItem as uint].get()
+ }
+ pub fn neg_trait(&const self) -> def_id {
+ self.items[NegTraitLangItem as uint].get()
+ }
+ pub fn not_trait(&const self) -> def_id {
+ self.items[NotTraitLangItem as uint].get()
+ }
+ pub fn bitxor_trait(&const self) -> def_id {
+ self.items[BitXorTraitLangItem as uint].get()
+ }
+ pub fn bitand_trait(&const self) -> def_id {
+ self.items[BitAndTraitLangItem as uint].get()
+ }
+ pub fn bitor_trait(&const self) -> def_id {
+ self.items[BitOrTraitLangItem as uint].get()
+ }
+ pub fn shl_trait(&const self) -> def_id {
+ self.items[ShlTraitLangItem as uint].get()
+ }
+ pub fn shr_trait(&const self) -> def_id {
+ self.items[ShrTraitLangItem as uint].get()
+ }
+ pub fn index_trait(&const self) -> def_id {
+ self.items[IndexTraitLangItem as uint].get()
+ }
+ pub fn eq_trait(&const self) -> def_id {
+ self.items[EqTraitLangItem as uint].get()
+ }
+ pub fn ord_trait(&const self) -> def_id {
+ self.items[OrdTraitLangItem as uint].get()
+ }
+
+ pub fn str_eq_fn(&const self) -> def_id {
+ self.items[StrEqFnLangItem as uint].get()
+ }
+ pub fn uniq_str_eq_fn(&const self) -> def_id {
+ self.items[UniqStrEqFnLangItem as uint].get()
+ }
+ pub fn annihilate_fn(&const self) -> def_id {
+ self.items[AnnihilateFnLangItem as uint].get()
+ }
+ pub fn log_type_fn(&const self) -> def_id {
+ self.items[LogTypeFnLangItem as uint].get()
+ }
+ pub fn fail_fn(&const self) -> def_id {
+ self.items[FailFnLangItem as uint].get()
+ }
+ pub fn fail_bounds_check_fn(&const self) -> def_id {
+ self.items[FailBoundsCheckFnLangItem as uint].get()
+ }
+ pub fn exchange_malloc_fn(&const self) -> def_id {
+ self.items[ExchangeMallocFnLangItem as uint].get()
+ }
+ pub fn exchange_free_fn(&const self) -> def_id {
+ self.items[ExchangeFreeFnLangItem as uint].get()
+ }
+ pub fn malloc_fn(&const self) -> def_id {
+ self.items[MallocFnLangItem as uint].get()
+ }
+ pub fn free_fn(&const self) -> def_id {
+ self.items[FreeFnLangItem as uint].get()
+ }
+}
+
+fn LanguageItemCollector(crate: @crate,
+ session: Session,
+ items: &r/mut LanguageItems)
+ -> LanguageItemCollector/&r {
let item_refs = HashMap();
- item_refs.insert(~"const", &mut items.const_trait);
- item_refs.insert(~"copy", &mut items.copy_trait);
- item_refs.insert(~"owned", &mut items.owned_trait);
- item_refs.insert(~"durable", &mut items.durable_trait);
-
- item_refs.insert(~"drop", &mut items.drop_trait);
-
- item_refs.insert(~"add", &mut items.add_trait);
- item_refs.insert(~"sub", &mut items.sub_trait);
- item_refs.insert(~"mul", &mut items.mul_trait);
- item_refs.insert(~"div", &mut items.div_trait);
- item_refs.insert(~"modulo", &mut items.modulo_trait);
- item_refs.insert(~"neg", &mut items.neg_trait);
- item_refs.insert(~"bitxor", &mut items.bitxor_trait);
- item_refs.insert(~"bitand", &mut items.bitand_trait);
- item_refs.insert(~"bitor", &mut items.bitor_trait);
- item_refs.insert(~"shl", &mut items.shl_trait);
- item_refs.insert(~"shr", &mut items.shr_trait);
- item_refs.insert(~"index", &mut items.index_trait);
-
- item_refs.insert(~"eq", &mut items.eq_trait);
- item_refs.insert(~"ord", &mut items.ord_trait);
-
- item_refs.insert(~"str_eq", &mut items.str_eq_fn);
- item_refs.insert(~"uniq_str_eq", &mut items.uniq_str_eq_fn);
- item_refs.insert(~"annihilate", &mut items.annihilate_fn);
- item_refs.insert(~"log_type", &mut items.log_type_fn);
+ item_refs.insert(~"const", ConstTraitLangItem as uint);
+ item_refs.insert(~"copy", CopyTraitLangItem as uint);
+ item_refs.insert(~"owned", OwnedTraitLangItem as uint);
+ item_refs.insert(~"durable", DurableTraitLangItem as uint);
+
+ item_refs.insert(~"drop", DropTraitLangItem as uint);
+
+ item_refs.insert(~"add", AddTraitLangItem as uint);
+ item_refs.insert(~"sub", SubTraitLangItem as uint);
+ item_refs.insert(~"mul", MulTraitLangItem as uint);
+ item_refs.insert(~"div", DivTraitLangItem as uint);
+ item_refs.insert(~"modulo", ModuloTraitLangItem as uint);
+ item_refs.insert(~"neg", NegTraitLangItem as uint);
+ item_refs.insert(~"not", NotTraitLangItem as uint);
+ item_refs.insert(~"bitxor", BitXorTraitLangItem as uint);
+ item_refs.insert(~"bitand", BitAndTraitLangItem as uint);
+ item_refs.insert(~"bitor", BitOrTraitLangItem as uint);
+ item_refs.insert(~"shl", ShlTraitLangItem as uint);
+ item_refs.insert(~"shr", ShrTraitLangItem as uint);
+ item_refs.insert(~"index", IndexTraitLangItem as uint);
+
+ item_refs.insert(~"eq", EqTraitLangItem as uint);
+ item_refs.insert(~"ord", OrdTraitLangItem as uint);
+
+ item_refs.insert(~"str_eq", StrEqFnLangItem as uint);
+ item_refs.insert(~"uniq_str_eq", UniqStrEqFnLangItem as uint);
+ item_refs.insert(~"annihilate", AnnihilateFnLangItem as uint);
+ item_refs.insert(~"log_type", LogTypeFnLangItem as uint);
+ item_refs.insert(~"fail_", FailFnLangItem as uint);
+ item_refs.insert(~"fail_bounds_check", FailBoundsCheckFnLangItem as uint);
+ item_refs.insert(~"exchange_malloc", ExchangeMallocFnLangItem as uint);
+ item_refs.insert(~"exchange_free", ExchangeFreeFnLangItem as uint);
+ item_refs.insert(~"malloc", MallocFnLangItem as uint);
+ item_refs.insert(~"free", FreeFnLangItem as uint);
LanguageItemCollector {
crate: crate,
}
struct LanguageItemCollector {
- items: &LanguageItems,
+ items: &mut LanguageItems,
crate: @crate,
session: Session,
- item_refs: HashMap<~str,&mut Option<def_id>>,
+ item_refs: HashMap<~str,uint>,
}
impl LanguageItemCollector {
-
fn match_and_collect_meta_item(item_def_id: def_id,
meta_item: meta_item) {
match meta_item.node {
match literal.node {
lit_str(value) => {
self.match_and_collect_item(item_def_id,
- (*key),
- *value);
+ (/*bad*/copy *key),
+ /*bad*/copy *value);
}
_ => {} // Skip.
}
}
}
+ fn collect_item(item_index: uint, item_def_id: def_id) {
+ // Check for duplicates.
+ match self.items.items[item_index] {
+ Some(original_def_id) if original_def_id != item_def_id => {
+ self.session.err(fmt!("duplicate entry for `%s`",
+ LanguageItems::item_name(item_index)));
+ }
+ Some(_) | None => {
+ // OK.
+ }
+ }
+
+ // Matched.
+ self.items.items[item_index] = Some(item_def_id);
+ }
+
fn match_and_collect_item(item_def_id: def_id, key: ~str, value: ~str) {
if key != ~"lang" {
return; // Didn't match.
None => {
// Didn't match.
}
- Some(item_ref) => {
- // Check for duplicates.
- match copy *item_ref {
- Some(original_def_id)
- if original_def_id != item_def_id => {
-
- self.session.err(fmt!("duplicate entry for `%s`",
- value));
- }
- Some(_) | None => {
- // OK.
- }
- }
-
- // Matched.
- *item_ref = Some(item_def_id);
+ Some(item_index) => {
+ self.collect_item(item_index, item_def_id)
}
}
}
fn collect_local_language_items() {
let this = unsafe { ptr::addr_of(&self) };
- visit_crate(*self.crate, (), mk_simple_visitor(@{
+ visit_crate(*self.crate, (), mk_simple_visitor(@SimpleVisitor {
visit_item: |item| {
for item.attrs.each |attribute| {
unsafe {
fn collect_external_language_items() {
let crate_store = self.session.cstore;
do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
- for each_path(crate_store, crate_number) |path_entry| {
- let def_id;
- match path_entry.def_like {
- dl_def(def_ty(did)) | dl_def(def_fn(did, _)) => {
- def_id = did;
- }
- dl_def(_) | dl_impl(_) | dl_field => {
- // Skip this.
- loop;
- }
- }
-
- do get_item_attrs(crate_store, def_id) |meta_items| {
- for meta_items.each |meta_item| {
- self.match_and_collect_meta_item(def_id, **meta_item);
- }
- }
+ for each_lang_item(crate_store, crate_number)
+ |node_id, item_index| {
+ let def_id = { crate: crate_number, node: node_id };
+ self.collect_item(item_index, def_id);
}
}
}
fn check_completeness() {
for self.item_refs.each |key, item_ref| {
- match *item_ref {
+ match self.items.items[item_ref] {
None => {
self.session.err(fmt!("no item found for `%s`", key));
}
}
fn collect_language_items(crate: @crate, session: Session) -> LanguageItems {
- let items = language_items::make();
- let collector = LanguageItemCollector(crate, session, &items);
+ let mut items = LanguageItems::new();
+ let collector = LanguageItemCollector(crate, session, &mut items);
collector.collect();
copy items
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use driver::session;
+use core::prelude::*;
+
use driver::session::Session;
+use driver::session;
+use middle::pat_util::{pat_bindings};
use middle::ty;
-use syntax::{ast, ast_util, visit};
-use syntax::attr;
-use syntax::codemap::span;
-use std::map::{Map,HashMap};
-use std::smallintmap::{Map,SmallIntMap};
-use io::WriterUtil;
use util::ppaux::{ty_to_str};
-use middle::pat_util::{pat_bindings};
+
+use core::char;
+use core::cmp;
+use core::either;
+use core::i8;
+use core::i16;
+use core::i32;
+use core::i64;
+use core::int;
+use core::io::WriterUtil;
+use core::str;
+use core::u8;
+use core::u16;
+use core::u32;
+use core::u64;
+use core::uint;
+use core::vec;
+use std::map::{Map, HashMap};
+use std::map;
+use std::smallintmap::{Map, SmallIntMap};
+use std::smallintmap;
use syntax::ast_util::{path_to_ident};
+use syntax::attr;
+use syntax::codemap::span;
use syntax::print::pprust::{expr_to_str, mode_to_str, pat_to_str};
+use syntax::{ast, ast_util, visit};
+
export lint, ctypes, unused_imports, while_true, path_statement, old_vecs;
export unrecognized_lint, non_implicitly_copyable_typarams;
export vecs_implicitly_copyable, implicit_copies, legacy_modes;
pure fn ne(&self, other: &lint) -> bool { !(*self).eq(other) }
}
-fn level_to_str(lv: level) -> ~str {
+fn level_to_str(lv: level) -> &static/str {
match lv {
- allow => ~"allow",
- warn => ~"warn",
- deny => ~"deny",
- forbid => ~"forbid"
+ allow => "allow",
+ warn => "warn",
+ deny => "deny",
+ forbid => "forbid"
}
}
}
type lint_spec = @{lint: lint,
- desc: ~str,
+ desc: &static/str,
default: level};
type lint_dict = HashMap<~str,lint_spec>;
let v = ~[
(~"ctypes",
@{lint: ctypes,
- desc: ~"proper use of core::libc types in foreign modules",
+ desc: "proper use of core::libc types in foreign modules",
default: warn}),
(~"unused_imports",
@{lint: unused_imports,
- desc: ~"imports that are never used",
+ desc: "imports that are never used",
default: allow}),
(~"while_true",
@{lint: while_true,
- desc: ~"suggest using loop { } instead of while(true) { }",
+ desc: "suggest using loop { } instead of while(true) { }",
default: warn}),
(~"path_statement",
@{lint: path_statement,
- desc: ~"path statements with no effect",
+ desc: "path statements with no effect",
default: warn}),
(~"unrecognized_lint",
@{lint: unrecognized_lint,
- desc: ~"unrecognized lint attribute",
+ desc: "unrecognized lint attribute",
default: warn}),
(~"non_implicitly_copyable_typarams",
@{lint: non_implicitly_copyable_typarams,
- desc: ~"passing non implicitly copyable types as copy type params",
+ desc: "passing non implicitly copyable types as copy type params",
default: warn}),
(~"vecs_implicitly_copyable",
@{lint: vecs_implicitly_copyable,
- desc: ~"make vecs and strs not implicitly copyable \
+ desc: "make vecs and strs not implicitly copyable \
(only checked at top level)",
default: warn}),
(~"implicit_copies",
@{lint: implicit_copies,
- desc: ~"implicit copies of non implicitly copyable data",
+ desc: "implicit copies of non implicitly copyable data",
default: warn}),
(~"deprecated_mode",
@{lint: deprecated_mode,
- desc: ~"warn about deprecated uses of modes",
+ desc: "warn about deprecated uses of modes",
default: warn}),
(~"deprecated_pattern",
@{lint: deprecated_pattern,
- desc: ~"warn about deprecated uses of pattern bindings",
+ desc: "warn about deprecated uses of pattern bindings",
default: allow}),
(~"non_camel_case_types",
@{lint: non_camel_case_types,
- desc: ~"types, variants and traits should have camel case names",
+ desc: "types, variants and traits should have camel case names",
default: allow}),
(~"managed_heap_memory",
@{lint: managed_heap_memory,
- desc: ~"use of managed (@ type) heap memory",
+ desc: "use of managed (@ type) heap memory",
default: allow}),
(~"owned_heap_memory",
@{lint: owned_heap_memory,
- desc: ~"use of owned (~ type) heap memory",
+ desc: "use of owned (~ type) heap memory",
default: allow}),
(~"heap_memory",
@{lint: heap_memory,
- desc: ~"use of any (~ type or @ type) heap memory",
+ desc: "use of any (~ type or @ type) heap memory",
default: allow}),
(~"structural_records",
@{lint: structural_records,
- desc: ~"use of any structural records",
+ desc: "use of any structural records",
default: allow}),
(~"legacy modes",
@{lint: legacy_modes,
- desc: ~"allow legacy modes",
+ desc: "allow legacy modes",
default: forbid}),
(~"type_limits",
@{lint: type_limits,
- desc: ~"comparisons made useless by limits of the types involved",
+ desc: "comparisons made useless by limits of the types involved",
default: warn}),
(~"default_methods",
@{lint: default_methods,
- desc: ~"allow default methods",
+ desc: "allow default methods",
default: deny}),
(~"deprecated_self",
@{lint: deprecated_self,
- desc: ~"warn about deprecated uses of `self`",
+ desc: "warn about deprecated uses of `self`",
default: allow}),
/* FIXME(#3266)--make liveness warnings lintable
(~"unused_variable",
@{lint: unused_variable,
- desc: ~"detect variables which are not used in any way",
+ desc: "detect variables which are not used in any way",
default: warn}),
(~"dead_assignment",
@{lint: dead_assignment,
- desc: ~"detect assignments that will never be read",
+ desc: "detect assignments that will never be read",
default: warn}),
*/
];
- std::map::hash_from_vec(v)
+ map::hash_from_vec(v)
}
// This is a highly not-optimal set of data structure decisions.
};
fn mk_lint_settings() -> lint_settings {
- {default_settings: std::smallintmap::mk(),
+ {default_settings: smallintmap::mk(),
settings_map: HashMap()}
}
// This is kind of unfortunate. It should be somewhere else, or we should use
// a persistent data structure...
fn clone_lint_modes(modes: lint_modes) -> lint_modes {
- std::smallintmap::SmallIntMap_(@{v: copy modes.v})
+ smallintmap::SmallIntMap_(@{v: copy modes.v})
}
type ctxt_ = {dict: lint_dict,
}
}
- fn span_lint(level: level, span: span, msg: ~str) {
+ fn span_lint(level: level, span: span, +msg: ~str) {
self.sess.span_lint_level(level, span, msg);
}
for [allow, warn, deny, forbid].each |level| {
let level_name = level_to_str(*level);
let metas =
- attr::attr_metas(attr::find_attrs_by_name(attrs,
- level_name));
+ attr::attr_metas(attr::find_attrs_by_name(attrs, level_name));
for metas.each |meta| {
- match meta.node {
+ match /*bad*/copy meta.node {
ast::meta_list(_, metas) => {
for metas.each |meta| {
match meta.node {
ast::meta_word(ref lintname) => {
- triples.push((*meta, *level, *lintname));
+ triples.push((*meta,
+ *level,
+ /*bad*/copy *lintname));
}
_ => {
self.sess.span_err(
}
for triples.each |pair| {
- let (meta, level, lintname) = *pair;
+ let (meta, level, lintname) = /*bad*/copy *pair;
match self.dict.find(lintname) {
None => {
self.span_lint(
fn build_settings_item(i: @ast::item, &&cx: ctxt, v: visit::vt<ctxt>) {
- do cx.with_lint_attrs(i.attrs) |cx| {
+ do cx.with_lint_attrs(/*bad*/copy i.attrs) |cx| {
if !cx.is_default {
cx.sess.lint_settings.settings_map.insert(i.id, cx.curr);
}
fn build_settings_crate(sess: session::Session, crate: @ast::crate) {
let cx = ctxt_({dict: get_lint_dict(),
- curr: std::smallintmap::mk(),
+ curr: smallintmap::mk(),
is_default: true,
sess: sess});
cx.set_level(lint, level);
}
- do cx.with_lint_attrs(crate.node.attrs) |cx| {
+ do cx.with_lint_attrs(/*bad*/copy crate.node.attrs) |cx| {
// Copy out the default settings
for cx.curr.each |k, v| {
sess.lint_settings.default_settings.insert(k, v);
let cx = ctxt_({is_default: true,.. *cx});
- let visit = visit::mk_vt(@{
+ let visit = visit::mk_vt(@visit::Visitor {
visit_item: build_settings_item,
.. *visit::default_visitor()
});
// not traverse into subitems, since that is handled by the outer
// lint visitor.
fn item_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
- visit::mk_vt(@{visit_item: |_i, _e, _v| { },.. **v})
+ visit::mk_vt(@visit::Visitor {visit_item: |_i, _e, _v| { },.. **v})
}
fn check_item_while_true(cx: ty::ctxt, it: @ast::item) {
- let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
- visit_expr: fn@(e: @ast::expr) {
- match e.node {
- ast::expr_while(cond, _) => {
- match cond.node {
- ast::expr_lit(@{node: ast::lit_bool(true),_}) => {
- cx.sess.span_lint(
- while_true, e.id, it.id,
- e.span,
- ~"denote infinite loops with loop { ... }");
+ let visit = item_stopping_visitor(
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_expr: |e: @ast::expr| {
+ match e.node {
+ ast::expr_while(cond, _) => {
+ match cond.node {
+ ast::expr_lit(@ast::spanned {
+ node: ast::lit_bool(true), _}) =>
+ {
+ cx.sess.span_lint(
+ while_true, e.id, it.id,
+ e.span,
+ ~"denote infinite loops \
+ with loop { ... }");
+ }
+ _ => ()
+ }
}
_ => ()
}
- }
- _ => ()
- }
- },
- .. *visit::default_simple_visitor()
- }));
+ },
+ .. *visit::default_simple_visitor()
+ }));
visit::visit_item(it, (), visit);
}
} else {
binop
};
- match ty::get(ty::expr_ty(cx, @*expr)).sty {
+ match ty::get(ty::expr_ty(cx, @/*bad*/copy *expr)).sty {
ty::ty_int(int_ty) => {
let (min, max) = int_ty_range(int_ty);
let lit_val: i64 = match lit.node {
}
}
- let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
- visit_expr: fn@(e: @ast::expr) {
- match e.node {
- ast::expr_binary(ref binop, @ref l, @ref r) => {
- if is_comparison(*binop)
- && !check_limits(cx, *binop, l, r) {
- cx.sess.span_lint(
- type_limits, e.id, it.id, e.span,
- ~"comparison is useless due to type limits");
- }
+ let visit_expr: @fn(@ast::expr) = |e| {
+ match e.node {
+ ast::expr_binary(ref binop, @ref l, @ref r) => {
+ if is_comparison(*binop)
+ && !check_limits(cx, *binop, l, r) {
+ cx.sess.span_lint(
+ type_limits, e.id, it.id, e.span,
+ ~"comparison is useless due to type limits");
}
- _ => ()
}
- },
- .. *visit::default_simple_visitor()
- }));
+ _ => ()
+ }
+ };
+
+ let visit = item_stopping_visitor(
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_expr: visit_expr,
+ .. *visit::default_simple_visitor()
+ }));
visit::visit_item(it, (), visit);
}
fn check_item_default_methods(cx: ty::ctxt, item: @ast::item) {
- match item.node {
+ match /*bad*/copy item.node {
ast::item_trait(_, _, methods) => {
for methods.each |method| {
match *method {
parameter or mark the method as static");
}
- match item.node {
+ match /*bad*/copy item.node {
ast::item_trait(_, _, methods) => {
for methods.each |method| {
- match *method {
+ match /*bad*/copy *method {
ast::required(ty_method) => {
maybe_warn(cx, item, ty_method.self_ty);
}
}
fn check_item_structural_records(cx: ty::ctxt, it: @ast::item) {
- let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
- visit_expr: fn@(e: @ast::expr) {
- match e.node {
- ast::expr_rec(*) =>
- cx.sess.span_lint(
- structural_records, e.id, it.id,
- e.span,
- ~"structural records are deprecated"),
- _ => ()
- }
- },
- .. *visit::default_simple_visitor()
- }));
+ let visit = item_stopping_visitor(
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_expr: |e: @ast::expr| {
+ match e.node {
+ ast::expr_rec(*) =>
+ cx.sess.span_lint(
+ structural_records, e.id, it.id,
+ e.span,
+ ~"structural records are deprecated"),
+ _ => ()
+ }
+ },
+ .. *visit::default_simple_visitor()
+ }));
visit::visit_item(it, (), visit);
}
}
match it.node {
- ast::item_foreign_mod(nmod) if attr::foreign_abi(it.attrs) !=
- either::Right(ast::foreign_abi_rust_intrinsic) => {
+ ast::item_foreign_mod(ref nmod)
+ if attr::foreign_abi(it.attrs) !=
+ either::Right(ast::foreign_abi_rust_intrinsic) => {
for nmod.items.each |ni| {
- match ni.node {
+ match /*bad*/copy ni.node {
ast::foreign_item_fn(decl, _, _) => {
check_foreign_fn(cx, it.id, decl);
}
_ => ()
}
- let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
- visit_expr: fn@(e: @ast::expr) {
- let ty = ty::expr_ty(cx, e);
- check_type(cx, e.id, it.id, e.span, ty);
- },
- .. *visit::default_simple_visitor()
- }));
+ let visit = item_stopping_visitor(
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_expr: |e: @ast::expr| {
+ let ty = ty::expr_ty(cx, e);
+ check_type(cx, e.id, it.id, e.span, ty);
+ },
+ .. *visit::default_simple_visitor()
+ }));
visit::visit_item(it, (), visit);
}
fn check_item_path_statement(cx: ty::ctxt, it: @ast::item) {
- let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
- visit_stmt: fn@(s: @ast::stmt) {
- match s.node {
- ast::stmt_semi(@{id: id,
- callee_id: _,
- node: ast::expr_path(_),
- span: _}, _) => {
- cx.sess.span_lint(
- path_statement, id, it.id,
- s.span,
- ~"path statement with no effect");
- }
- _ => ()
- }
- },
- .. *visit::default_simple_visitor()
- }));
+ let visit = item_stopping_visitor(
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_stmt: |s: @ast::stmt| {
+ match s.node {
+ ast::stmt_semi(@{id: id,
+ callee_id: _,
+ node: ast::expr_path(_),
+ span: _}, _) => {
+ cx.sess.span_lint(
+ path_statement, id, it.id,
+ s.span,
+ ~"path statement with no effect");
+ }
+ _ => ()
+ }
+ },
+ .. *visit::default_simple_visitor()
+ }));
visit::visit_item(it, (), visit);
}
!ident.contains_char('_')
}
- fn ident_without_trailing_underscores(ident: ~str) -> ~str {
+ fn ident_without_trailing_underscores(+ident: ~str) -> ~str {
match str::rfind(ident, |c| c != '_') {
Some(idx) => (ident).slice(0, idx + 1),
None => { ident } // all underscores
}
}
- fn ident_without_leading_underscores(ident: ~str) -> ~str {
+ fn ident_without_leading_underscores(+ident: ~str) -> ~str {
match str::find(ident, |c| c != '_') {
Some(idx) => ident.slice(idx, ident.len()),
None => {
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
- let v = visit::mk_simple_visitor(@{
+ let v = visit::mk_simple_visitor(@visit::SimpleVisitor {
visit_item: |it|
check_item(it, tcx),
visit_fn: |fk, decl, body, span, id|
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
/*!
* A classic liveness analysis based on dataflow over the AST. Computes,
* for each local variable in a function, whether that variable is live
* to return explicitly.
*/
+use core::prelude::*;
+
use middle::capture::{cap_move, cap_drop, cap_copy, cap_ref};
+use middle::capture;
+use middle::pat_util;
use middle::ty::MoveValue;
+use middle::ty;
+use middle::typeck;
+use core::cmp;
use core::dvec::DVec;
use core::io::WriterUtil;
+use core::io;
+use core::ptr;
+use core::to_str;
+use core::uint;
+use core::vec;
use std::map::HashMap;
use syntax::ast::*;
use syntax::codemap::span;
fn check_crate(tcx: ty::ctxt,
method_map: typeck::method_map,
crate: @crate) -> last_use_map {
- let visitor = visit::mk_vt(@{
+ let visitor = visit::mk_vt(@visit::Visitor {
visit_fn: visit_fn,
visit_local: visit_local,
visit_expr: visit_expr,
fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
sp: span, id: node_id, &&self: @IrMaps, v: vt<@IrMaps>) {
debug!("visit_fn: id=%d", id);
- let _i = util::common::indenter();
+ let _i = ::util::common::indenter();
// swap in a new set of IR maps for this function body:
let fn_maps = @IrMaps(self.tcx, self.method_map,
let entry_ln = (*lsets).compute(decl, body);
// check for various error conditions
- let check_vt = visit::mk_vt(@{
+ let check_vt = visit::mk_vt(@visit::Visitor {
visit_fn: check_fn,
visit_local: check_local,
visit_expr: check_expr,
}
fn propagate_through_decl(decl: @decl, succ: LiveNode) -> LiveNode {
- match decl.node {
+ match /*bad*/copy decl.node {
decl_local(locals) => {
do locals.foldr(succ) |local, succ| {
self.propagate_through_local(*local, succ)
debug!("propagate_through_expr: %s",
expr_to_str(expr, self.tcx.sess.intr()));
- match expr.node {
+ match /*bad*/copy expr.node {
// Interesting cases with control flow or which gen/kill
expr_path(_) => {
}
fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
- match expr.node {
+ match /*bad*/copy expr.node {
expr_path(_) => {
for self.variable_from_def_map(expr.id, expr.span).each |var| {
let ln = self.live_node(expr.id, expr.span);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
/*!
* # Categorization
*
* then an index to jump forward to the relevant item.
*/
-use syntax::ast;
+use core::prelude::*;
+
+use middle::ty;
+use middle::typeck;
+use util::ppaux::{ty_to_str, region_to_str};
+use util::common::indenter;
+
+use core::cmp;
+use core::to_bytes;
+use core::uint;
use syntax::ast::{m_imm, m_const, m_mutbl};
+use syntax::ast;
use syntax::codemap::span;
use syntax::print::pprust;
-use util::ppaux::{ty_to_str, region_to_str};
-use util::common::indenter;
enum categorization {
cat_rvalue, // result of eval'ing some misc expr
}
// different kinds of pointers:
-enum ptr_kind {
+pub enum ptr_kind {
uniq_ptr,
gc_ptr,
region_ptr(ty::Region),
// I am coining the term "components" to mean "pieces of a data
// structure accessible without a dereference":
-enum comp_kind {
+pub enum comp_kind {
comp_tuple, // elt in a tuple
comp_anon_field, // anonymous field (in e.g.
// struct Foo(int, int);
// a loan path is like a category, but it exists only when the data is
// interior to the stack frame. loan paths are used as the key to a
// map indicating what is borrowed at any point in time.
-enum loan_path {
+pub enum loan_path {
lp_local(ast::node_id),
lp_arg(ast::node_id),
lp_deref(@loan_path, ptr_kind),
// local(x)->@->@
//
// where the id of `local(x)` is the id of the `x` that appears
- // in the alt, the id of `local(x)->@` is the `@y` pattern,
+ // in the match, the id of `local(x)->@` is the `@y` pattern,
// and the id of `local(x)->@->@` is the id of the `y` pattern.
pat.id, pprust::pat_to_str(pat, tcx.sess.intr()),
self.cmt_to_repr(cmt));
- match pat.node {
+ match /*bad*/copy pat.node {
ast::pat_wild => {
// _
}
f_name: ast::ident,
node_id: ast::node_id) -> Option<ast::mutability> {
// Need to refactor so that records/class fields can be treated uniformly.
- match ty::get(base_ty).sty {
+ match /*bad*/copy ty::get(base_ty).sty {
ty::ty_rec(fields) => {
for fields.each |f| {
if f.ident == f_name {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use middle::pat_util;
use middle::ty;
use middle::ty::{CopyValue, MoveValue, ReadValue, ValueMode, ctxt};
use syntax::ast::{expr_match, expr_method_call, expr_paren, expr_path};
use syntax::ast::{expr_swap, expr_unary, neg, node_id, not, pat, pat_ident};
use syntax::ast::{sty_uniq, sty_value, uniq};
+use syntax::ast::{fn_decl, blk};
use syntax::visit;
-use syntax::visit::vt;
+use syntax::visit::{fn_kind, vt};
+use syntax::print::pprust;
+use syntax::codemap::span;
struct VisitContext {
tcx: ctxt,
mode: ValueMode,
}
+fn compute_modes_for_fn(fk: fn_kind,
+ decl: fn_decl,
+ body: blk,
+ sp: span,
+ id: node_id,
+ &&cx: VisitContext,
+ v: vt<VisitContext>) {
+ let body_cx = VisitContext { mode: MoveValue, ..cx };
+ visit::visit_fn(fk, decl, body, sp, id, body_cx, v);
+}
+
fn compute_modes_for_fn_args(callee_id: node_id,
args: &[@expr],
last_arg_is_block: bool,
fn compute_modes_for_expr(expr: @expr,
&&cx: VisitContext,
v: vt<VisitContext>) {
+ debug!("compute_modes_for_expr(expr=%?/%s, mode=%?)",
+ expr.id, pprust::expr_to_str(expr, cx.tcx.sess.intr()),
+ cx.mode);
+
// Adjust the mode if there was an implicit reference here.
let cx = match cx.tcx.adjustments.find(expr.id) {
None => cx,
}
};
- match expr.node {
+ match copy expr.node {
expr_call(callee, args, is_block) => {
let callee_cx = VisitContext { mode: ReadValue, ..cx };
compute_modes_for_expr(callee, callee_cx, v);
}
pub fn compute_modes(tcx: ctxt, method_map: method_map, crate: @crate) {
- let visitor = visit::mk_vt(@{
+ let visitor = visit::mk_vt(@visit::Visitor {
+ visit_fn: compute_modes_for_fn,
visit_expr: compute_modes_for_expr,
visit_pat: compute_modes_for_pat,
.. *visit::default_visitor()
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::resolve;
use middle::ty::{CopyValue, MoveValue, ReadValue};
+use middle::ty;
use syntax::ast::*;
use syntax::ast_util;
export pat_is_const;
export arms_have_by_move_bindings;
-type PatIdMap = std::map::HashMap<ident, node_id>;
+type PatIdMap = HashMap<ident, node_id>;
// This is used because same-named variables in alternative patterns need to
// use the node_id of their namesake in the first pattern.
fn pat_id_map(dm: resolve::DefMap, pat: @pat) -> PatIdMap {
- let map = std::map::HashMap();
+ let map = HashMap();
do pat_bindings(dm, pat) |_bm, p_id, _s, n| {
map.insert(path_to_ident(n), p_id);
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
// A pass that checks to make sure private fields and methods aren't used
// outside their scopes.
+use core::prelude::*;
+
use middle::ty::{ty_struct, ty_enum};
+use middle::ty;
use middle::typeck::{method_map, method_origin, method_param, method_self};
use middle::typeck::{method_static, method_trait};
-use /*mod*/ syntax::ast;
-use /*mod*/ syntax::visit;
-use syntax::ast_map;
+
+use core::dvec::DVec;
+use core::util::ignore;
use syntax::ast::{def_variant, expr_field, expr_method_call, expr_struct};
use syntax::ast::{expr_unary, ident, item_struct, item_enum, item_impl};
use syntax::ast::{item_trait, local_crate, node_id, pat_struct, private};
use syntax::ast::{provided, required};
+use syntax::ast;
use syntax::ast_map::{node_item, node_method};
+use syntax::ast_map;
use syntax::ast_util::{Private, Public, has_legacy_export_attr, is_local};
use syntax::ast_util::{visibility_to_privacy};
-
-use core::util::ignore;
-use dvec::DVec;
+use syntax::visit;
fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) {
let privileged_items = @DVec();
}
};
- let visitor = visit::mk_vt(@{
+ let visitor = visit::mk_vt(@visit::Visitor {
visit_mod: |the_module, span, node_id, method_map, visitor| {
let n_added = add_privileged_items(the_module.items);
visit::visit_expr(expr, method_map, visitor);
},
visit_pat: |pattern, method_map, visitor| {
- match pattern.node {
+ match /*bad*/copy pattern.node {
pat_struct(_, fields, _) => {
match ty::get(ty::pat_ty(tcx, pattern)).sty {
ty_struct(id, _) => {
*/
+use core::prelude::*;
+
use driver::session::Session;
use metadata::csearch;
+use middle::resolve;
use middle::ty::{region_variance, rv_covariant, rv_invariant};
use middle::ty::{rv_contravariant};
use middle::ty;
+use core::cmp;
use core::dvec::DVec;
+use core::vec;
use std::list;
use std::list::list;
use std::map::HashMap;
// that when we visit it we can view it as a parent.
root_exprs: HashMap<ast::node_id, ()>,
- // The parent scope is the innermost block, statement, call, or alt
+ // The parent scope is the innermost block, statement, call, or match
// expression during the execution of which the current expression
// will be evaluated. Generally speaking, the innermost parent
// scope is also the closest suitable ancestor in the AST tree.
region_map: HashMap(),
root_exprs: HashMap(),
parent: None};
- let visitor = visit::mk_vt(@{
+ let visitor = visit::mk_vt(@visit::Visitor {
visit_block: resolve_block,
visit_item: resolve_item,
visit_fn: resolve_fn,
self.item_id = item_id;
self.anon_implies_rp = anon_implies_rp;
debug!("with_item_id(%d, %b)", item_id, anon_implies_rp);
- let _i = util::common::indenter();
+ let _i = ::util::common::indenter();
f();
self.item_id = old_item_id;
self.anon_implies_rp = old_anon_implies_rp;
mut ambient_variance: rv_covariant});
// Gather up the base set, worklist and dep_map
- let visitor = visit::mk_vt(@{
+ let visitor = visit::mk_vt(@visit::Visitor {
visit_fn: determine_rp_in_fn,
visit_item: determine_rp_in_item,
visit_ty: determine_rp_in_ty,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use driver::session::Session;
use metadata::csearch::{each_path, get_method_names_if_trait};
use metadata::csearch::{get_static_methods_if_impl, get_type_name_if_impl};
use middle::lang_items::LanguageItems;
use middle::lint::{deny, allow, forbid, level, unused_imports, warn};
use middle::pat_util::{pat_bindings};
-use syntax::ast::{_mod, add, arm, binding_mode, bitand, bitor, bitxor, blk};
-use syntax::ast::{capture_clause};
+
+use core::cmp;
+use core::str;
+use core::vec;
+use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm};
+use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk, capture_clause};
use syntax::ast::{crate, crate_num, decl_item, def, def_arg, def_binding};
use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label};
use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self};
use syntax::ast::{gt, ident, impure_fn, inherited, item, item_struct};
use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod};
use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le};
-use syntax::ast::{local, local_crate, lt, method, mode, module_ns, mul, ne};
-use syntax::ast::{neg, node_id, pat, pat_enum, pat_ident, path, prim_ty};
-use syntax::ast::{pat_box, pat_lit, pat_range, pat_rec, pat_struct};
-use syntax::ast::{pat_tup, pat_uniq, pat_wild, private, provided, public};
-use syntax::ast::{required, rem, self_ty_, shl, shr, stmt_decl, struct_dtor};
-use syntax::ast::{struct_field, struct_variant_kind, sty_by_ref, sty_static};
-use syntax::ast::{subtract, trait_ref, tuple_variant_kind, Ty, ty_bool};
-use syntax::ast::{ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16};
-use syntax::ast::{ty_i32, ty_i64, ty_i8, ty_int, ty_param, ty_path, ty_str};
-use syntax::ast::{ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint};
+use syntax::ast::{local, local_crate, lt, method, mode, module_ns, mul};
+use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident};
+use syntax::ast::{path, pat_box, pat_lit, pat_range, pat_rec, pat_struct};
+use syntax::ast::{pat_tup, pat_uniq, pat_wild, prim_ty, private, provided};
+use syntax::ast::{public, required, rem, self_ty_, shl, shr, stmt_decl};
+use syntax::ast::{struct_dtor, struct_field, struct_variant_kind, sty_by_ref};
+use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty};
+use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
+use syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, ty_param, ty_path};
+use syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint};
use syntax::ast::{type_value_ns, ty_param_bound, unnamed_field};
use syntax::ast::{variant, view_item, view_item_export, view_item_import};
use syntax::ast::{view_item_use, view_path_glob, view_path_list};
-use syntax::ast::{view_path_simple, visibility, anonymous, named};
+use syntax::ast::{view_path_simple, visibility, anonymous, named, not};
use syntax::ast_util::{def_id_of_def, dummy_sp, local_def};
use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
use syntax::ast_util::{Privacy, Public, Private, visibility_to_privacy};
use syntax::ast_util::has_legacy_export_attr;
use syntax::attr::{attr_metas, contains_name};
+use syntax::parse::token::ident_interner;
+use syntax::parse::token::special_idents;
use syntax::print::pprust::{pat_to_str, path_to_str};
use syntax::codemap::span;
-use syntax::visit::{default_visitor, fk_method, mk_vt, visit_block};
+use syntax::visit::{default_visitor, fk_method, mk_vt, Visitor, visit_block};
use syntax::visit::{visit_crate, visit_expr, visit_expr_opt, visit_fn};
use syntax::visit::{visit_foreign_item, visit_item, visit_method_helper};
use syntax::visit::{visit_mod, visit_ty, vt};
use option::{Some, get, is_some, is_none};
use str::{connect, split_str};
use vec::pop;
-use syntax::parse::token::ident_interner;
use std::list::{Cons, List, Nil};
use std::map::HashMap;
UseLexicalScope
}
-struct ModulePrefixResult {
- result: ResolveResult<@Module>,
- prefix_len: uint
+enum SearchThroughModulesFlag {
+ DontSearchThroughModules,
+ SearchThroughModules
+}
+
+enum ModulePrefixResult {
+ NoPrefixFound,
+ PrefixFound(@Module, uint)
}
impl XrayFlag : cmp::Eq {
BlockParentLink(@Module, node_id)
}
+/// The type of module this is.
+enum ModuleKind {
+ NormalModuleKind,
+ ExternModuleKind,
+ TraitModuleKind,
+ AnonymousModuleKind,
+}
+
/// One node in the tree of modules.
struct Module {
parent_link: ParentLink,
mut def_id: Option<def_id>,
+ kind: ModuleKind,
children: HashMap<ident,@NameBindings>,
imports: DVec<@ImportDirective>,
fn Module(parent_link: ParentLink,
def_id: Option<def_id>,
+ kind: ModuleKind,
legacy_exports: bool) -> Module {
Module {
parent_link: parent_link,
def_id: def_id,
+ kind: kind,
children: HashMap(),
imports: DVec(),
anonymous_children: HashMap(),
fn define_module(privacy: Privacy,
parent_link: ParentLink,
def_id: Option<def_id>,
+ kind: ModuleKind,
legacy_exports: bool,
sp: span) {
// Merges the module with the existing type def or creates a new one.
- let module_ = @Module(parent_link, def_id, legacy_exports);
+ let module_ = @Module(parent_link, def_id, kind, legacy_exports);
match self.type_def {
None => {
self.type_def = Some(TypeNsDef {
(*graph_root).define_module(Public,
NoParentLink,
Some({ crate: 0, node: 0 }),
+ NormalModuleKind,
has_legacy_export_attr(crate.node.attrs),
crate.span);
xray_context: NoXray,
current_trait_refs: None,
- self_ident: syntax::parse::token::special_idents::self_,
+ self_ident: special_idents::self_,
+ type_self_ident: special_idents::type_self,
+
primitive_type_table: @PrimitiveTypeTable(session.
parse_sess.interner),
// The ident for the keyword "self".
self_ident: ident,
+ // The ident for the non-keyword "Self".
+ type_self_ident: ident,
// The idents for the primitive types.
primitive_type_table: @PrimitiveTypeTable,
fn build_reduced_graph(this: @Resolver) {
let initial_parent =
ModuleReducedGraphParent((*self.graph_root).get_module());
- visit_crate(*self.crate, initial_parent, mk_vt(@{
+ visit_crate(*self.crate, initial_parent, mk_vt(@Visitor {
visit_item: |item, context, visitor|
(*this).build_reduced_graph_for_item(item, context, visitor),
};
let privacy = visibility_to_privacy(item.vis, legacy);
- match item.node {
+ match /*bad*/copy item.node {
item_mod(module_) => {
let legacy = has_legacy_export_attr(item.attrs);
let (name_bindings, new_parent) =
let parent_link = self.get_parent_link(new_parent, ident);
let def_id = { crate: 0, node: item.id };
- (*name_bindings).define_module(privacy, parent_link,
- Some(def_id), legacy, sp);
+ (*name_bindings).define_module(privacy,
+ parent_link,
+ Some(def_id),
+ NormalModuleKind,
+ legacy,
+ sp);
let new_parent =
ModuleReducedGraphParent((*name_bindings).get_module());
(*name_bindings).define_module(privacy,
parent_link,
Some(def_id),
+ ExternModuleKind,
legacy,
sp);
let parent_link = self.get_parent_link(new_parent,
ident);
let def_id = local_def(item.id);
- name_bindings.define_module(privacy, parent_link,
- Some(def_id), false, sp);
+ name_bindings.define_module(privacy,
+ parent_link,
+ Some(def_id),
+ TraitModuleKind,
+ false,
+ sp);
let new_parent = ModuleReducedGraphParent(
name_bindings.get_module());
name_bindings.define_module(privacy,
parent_link,
Some(local_def(item.id)),
+ TraitModuleKind,
false,
sp);
module_parent_opt = Some(ModuleReducedGraphParent(
ModuleReducedGraphParent(m) => m.legacy_exports
};
let privacy = visibility_to_privacy(view_item.vis, legacy);
- match view_item.node {
+ match /*bad*/copy view_item.node {
view_item_import(view_paths) => {
for view_paths.each |view_path| {
// Extract and intern the module part of the path. For
(*child_name_bindings).define_module(privacy,
parent_link,
Some(def_id),
+ NormalModuleKind,
false,
view_item.span);
self.build_reduced_graph_for_external_crate
self.add_child(name, parent, ForbidDuplicateValues,
foreign_item.span);
- match foreign_item.node {
+ match /*bad*/copy foreign_item.node {
foreign_item_fn(_, purity, type_parameters) => {
let def = def_fn(local_def(foreign_item.id), purity);
(*name_bindings).define_value(Public, def, foreign_item.span);
let parent_module = self.get_module_from_parent(parent);
let new_module = @Module(BlockParentLink(parent_module, block_id),
- None, false);
+ None,
+ AnonymousModuleKind,
+ false);
parent_module.anonymous_children.insert(block_id, new_module);
new_parent = ModuleReducedGraphParent(new_module);
} else {
child_name_bindings.define_module(Public,
parent_link,
Some(def_id),
+ NormalModuleKind,
false,
dummy_sp());
modules.insert(def_id,
let mut current_module = root;
for pieces.each |ident_str| {
- let ident = self.session.ident_of(*ident_str);
+ let ident = self.session.ident_of(/*bad*/copy *ident_str);
// Create or reuse a graph node for the child.
let (child_name_bindings, new_parent) =
self.add_child(ident,
(*child_name_bindings).define_module(Public,
parent_link,
None,
+ NormalModuleKind,
false,
dummy_sp());
}
(*child_name_bindings).define_module(Public,
parent_link,
None,
+ NormalModuleKind,
false,
dummy_sp());
}
}
dl_impl(def) => {
// We only process static methods of impls here.
- debug!("(building reduced graph for external crate) \
- processing impl %s", final_ident_str);
-
match get_type_name_if_impl(self.session.cstore, def) {
None => {}
Some(final_ident) => {
get_static_methods_if_impl(
self.session.cstore, def);
match static_methods_opt {
- Some(static_methods) if
+ Some(ref static_methods) if
static_methods.len() >= 1 => {
debug!("(building reduced graph for \
external crate) processing \
Public,
parent_link,
Some(def),
+ NormalModuleKind,
false,
dummy_sp());
type_module =
}
dl_field => {
debug!("(building reduced graph for external crate) \
- ignoring field %s", final_ident_str);
+ ignoring field");
}
}
}
match self.resolve_import_for_module(module_, import_directive) {
Failed => {
// We presumably emitted an error. Continue.
- self.session.span_err(import_directive.span,
- ~"failed to resolve import");
+ let idents = import_directive.module_path.get();
+ let msg = fmt!("failed to resolve import: %s",
+ self.import_path_to_str(idents,
+ *import_directive.subclass));
+ self.session.span_err(import_directive.span, msg);
}
Indeterminate => {
// Bail out. We'll come around next time.
}
fn idents_to_str(idents: ~[ident]) -> ~str {
- // XXX: str::connect should do this.
- let mut result = ~"";
- let mut first = true;
- for idents.each() |ident| {
- if first {
- first = false;
- } else {
- result += ~"::";
- }
- result += self.session.str_of(*ident);
- }
- // XXX: Shouldn't copy here. We need string builder functionality.
- return result;
+ let ident_strs = idents.map(|&ident| self.session.str_of(ident));
+ return str::connect(ident_strs, "::");
+ }
+
+ fn import_directive_subclass_to_str(subclass: ImportDirectiveSubclass)
+ -> ~str {
+ match subclass {
+ SingleImport(_target, source, _ns) => self.session.str_of(source),
+ GlobImport => ~"*"
+ }
}
+
+ fn import_path_to_str(idents: ~[ident], subclass: ImportDirectiveSubclass)
+ -> ~str {
+ if idents.is_empty() {
+ self.import_directive_subclass_to_str(subclass)
+ } else {
+ fmt!("%s::%s",
+ self.idents_to_str(idents),
+ self.import_directive_subclass_to_str(subclass))
+ }
+ }
+
/**
* Attempts to resolve the given import. The return value indicates
* failure if we're certain the name does not exist, indeterminate if we
self.idents_to_str((*module_path).get()),
self.module_to_str(module_));
- // The first element of the module path must be in the current scope
- // chain.
-
- let resolve_result = match use_lexical_scope {
- DontUseLexicalScope => {
- self.resolve_module_prefix(module_, module_path)
- }
- UseLexicalScope => {
- let result = self.resolve_module_in_lexical_scope(
- module_,
- module_path.get_elt(0));
- ModulePrefixResult { result: result, prefix_len: 1 }
- }
- };
+ // Resolve the module prefix, if any.
+ let module_prefix_result = self.resolve_module_prefix(module_,
+ module_path);
let mut search_module;
- match resolve_result.result {
+ let mut start_index;
+ match module_prefix_result {
Failed => {
self.session.span_err(span, ~"unresolved name");
return Failed;
bailing");
return Indeterminate;
}
- Success(resulting_module) => {
- search_module = resulting_module;
+ Success(NoPrefixFound) => {
+ // There was no prefix, so we're considering the first element
+ // of the path. How we handle this depends on whether we were
+ // instructed to use lexical scope or not.
+ match use_lexical_scope {
+ DontUseLexicalScope => {
+ // This is a crate-relative path. We will start the
+ // resolution process at index zero.
+ search_module = self.graph_root.get_module();
+ start_index = 0;
+ }
+ UseLexicalScope => {
+ // This is not a crate-relative path. We resolve the
+ // first component of the path in the current lexical
+ // scope and then proceed to resolve below that.
+ let result = self.resolve_module_in_lexical_scope(
+ module_,
+ module_path.get_elt(0));
+ match result {
+ Failed => {
+ self.session.span_err(span,
+ ~"unresolved name");
+ return Failed;
+ }
+ Indeterminate => {
+ debug!("(resolving module path for import) \
+ indeterminate; bailing");
+ return Indeterminate;
+ }
+ Success(containing_module) => {
+ search_module = containing_module;
+ start_index = 1;
+ }
+ }
+ }
+ }
+ }
+ Success(PrefixFound(containing_module, index)) => {
+ search_module = containing_module;
+ start_index = index;
}
}
return self.resolve_module_path_from_root(search_module,
module_path,
- resolve_result.prefix_len,
+ start_index,
xray,
span);
}
fn resolve_item_in_lexical_scope(module_: @Module,
name: ident,
- namespace: Namespace)
+ namespace: Namespace,
+ search_through_modules:
+ SearchThroughModulesFlag)
-> ResolveResult<Target> {
debug!("(resolving item in lexical scope) resolving `%s` in \
module");
return Failed;
}
- ModuleParentLink(parent_module_node, _) |
+ ModuleParentLink(parent_module_node, _) => {
+ match search_through_modules {
+ DontSearchThroughModules => {
+ match search_module.kind {
+ NormalModuleKind => {
+ // We stop the search here.
+ debug!("(resolving item in lexical \
+ scope) unresolved module: not \
+ searching through module \
+ parents");
+ return Failed;
+ }
+ ExternModuleKind |
+ TraitModuleKind |
+ AnonymousModuleKind => {
+ search_module = parent_module_node;
+ }
+ }
+ }
+ SearchThroughModules => {
+ search_module = parent_module_node;
+ }
+ }
+ }
BlockParentLink(parent_module_node, _) => {
search_module = parent_module_node;
}
-> ResolveResult<@Module> {
// If this module is an anonymous module, resolve the item in the
// lexical scope. Otherwise, resolve the item from the crate root.
- let resolve_result = self.resolve_item_in_lexical_scope(module_,
- name,
- TypeNS);
+ let resolve_result = self.resolve_item_in_lexical_scope(
+ module_, name, TypeNS, DontSearchThroughModules);
match resolve_result {
Success(target) => {
match target.bindings.type_def {
}
/**
- * Resolves a "module prefix". A module prefix is one of (a) the name of a
- * module; (b) "self::"; (c) some chain of "super::".
+ * Returns the nearest normal module parent of the given module.
*/
- fn resolve_module_prefix(module_: @Module,
- module_path: @DVec<ident>)
- -> ModulePrefixResult {
- let interner = self.session.parse_sess.interner;
-
- let mut containing_module = self.graph_root.get_module();
- let mut i = 0;
+ fn get_nearest_normal_module_parent(module_: @Module) -> Option<@Module> {
+ let mut module_ = module_;
loop {
- if *interner.get(module_path.get_elt(i)) == ~"self" {
- containing_module = module_;
- i += 1;
- break;
- }
- if *interner.get(module_path.get_elt(i)) == ~"super" {
- match containing_module.parent_link {
- NoParentLink => {
- return ModulePrefixResult {
- result: Failed,
- prefix_len: i
- };
- }
- BlockParentLink(new_module, _) |
- ModuleParentLink(new_module, _) => {
- containing_module = new_module;
+ match module_.parent_link {
+ NoParentLink => return None,
+ ModuleParentLink(new_module, _) |
+ BlockParentLink(new_module, _) => {
+ match new_module.kind {
+ NormalModuleKind => return Some(new_module),
+ ExternModuleKind |
+ TraitModuleKind |
+ AnonymousModuleKind => module_ = new_module,
}
}
- i += 1;
- } else {
- break;
}
}
+ }
- // Is the containing module the current module? If so, we allow
- // globs to be unresolved.
- let allow_globs = core::managed::ptr_eq(containing_module, module_);
-
- let name = module_path.get_elt(i);
- let resolve_result = self.resolve_name_in_module(containing_module,
- name,
- TypeNS,
- Xray,
- allow_globs);
- match resolve_result {
- Success(target) => {
- match target.bindings.type_def {
- Some(ref type_def) => {
- match (*type_def).module_def {
- None => {
- error!("!!! (resolving crate-relative \
- module) module wasn't actually a \
- module!");
- return ModulePrefixResult {
- result: Failed,
- prefix_len: i + 1
- };
- }
- Some(module_def) => {
- return ModulePrefixResult {
- result: Success(module_def),
- prefix_len: i + 1
- };
- }
- }
- }
- None => {
- error!("!!! (resolving crate-relative module) module
- wasn't actually a module!");
- return ModulePrefixResult {
- result: Failed,
- prefix_len: i + 1
- };
- }
+ /**
+ * Returns the nearest normal module parent of the given module, or the
+ * module itself if it is a normal module.
+ */
+ fn get_nearest_normal_module_parent_or_self(module_: @Module) -> @Module {
+ match module_.kind {
+ NormalModuleKind => return module_,
+ ExternModuleKind | TraitModuleKind | AnonymousModuleKind => {
+ match self.get_nearest_normal_module_parent(module_) {
+ None => module_,
+ Some(new_module) => new_module
}
}
- Indeterminate => {
- debug!("(resolving crate-relative module) indeterminate; \
- bailing");
- return ModulePrefixResult {
- result: Indeterminate,
- prefix_len: i + 1
- };
- }
- Failed => {
- debug!("(resolving crate-relative module) failed to resolve");
- return ModulePrefixResult {
- result: Failed,
- prefix_len: i + 1
- };
+ }
+ }
+
+ /**
+ * Resolves a "module prefix". A module prefix is one of (a) `self::`;
+ * (b) some chain of `super::`.
+ */
+ fn resolve_module_prefix(module_: @Module,
+ module_path: @DVec<ident>)
+ -> ResolveResult<ModulePrefixResult> {
+ let interner = self.session.parse_sess.interner;
+
+ // Start at the current module if we see `self` or `super`, or at the
+ // top of the crate otherwise.
+ let mut containing_module;
+ let mut i;
+ if *interner.get(module_path.get_elt(0)) == ~"self" {
+ containing_module =
+ self.get_nearest_normal_module_parent_or_self(module_);
+ i = 1;
+ } else if *interner.get(module_path.get_elt(0)) == ~"super" {
+ containing_module =
+ self.get_nearest_normal_module_parent_or_self(module_);
+ i = 0; // We'll handle `super` below.
+ } else {
+ return Success(NoPrefixFound);
+ }
+
+ // Now loop through all the `super`s we find.
+ while i < module_path.len() &&
+ *interner.get(module_path.get_elt(i)) == ~"super" {
+ debug!("(resolving module prefix) resolving `super` at %s",
+ self.module_to_str(containing_module));
+ match self.get_nearest_normal_module_parent(containing_module) {
+ None => return Failed,
+ Some(new_module) => {
+ containing_module = new_module;
+ i += 1;
+ }
}
}
+
+ debug!("(resolving module prefix) finished resolving prefix at %s",
+ self.module_to_str(containing_module));
+
+ return Success(PrefixFound(containing_module, i));
}
fn name_is_exported(module_: @Module, name: ident) -> bool {
xray: XrayFlag,
allow_globs: bool)
-> ResolveResult<Target> {
-
debug!("(resolving name in module) resolving `%s` in `%s`",
self.session.str_of(name),
self.module_to_str(module_));
debug!("(resolving one-level naming result) searching for module");
match self.resolve_item_in_lexical_scope(module_,
source_name,
- TypeNS) {
+ TypeNS,
+ SearchThroughModules) {
Failed => {
debug!("(resolving one-level renaming import) didn't find \
module result");
} else {
debug!("(resolving one-level naming result) searching for value");
match self.resolve_item_in_lexical_scope(module_,
- source_name,
- ValueNS) {
+ source_name,
+ ValueNS,
+ SearchThroughModules) {
Failed => {
debug!("(resolving one-level renaming import) didn't \
debug!("(resolving one-level naming result) searching for type");
match self.resolve_item_in_lexical_scope(module_,
- source_name,
- TypeNS) {
+ source_name,
+ TypeNS,
+ SearchThroughModules) {
Failed => {
debug!("(resolving one-level renaming import) didn't \
fn resolve_crate(@self) {
debug!("(resolving crate) starting");
- visit_crate(*self.crate, (), mk_vt(@{
+ visit_crate(*self.crate, (), mk_vt(@Visitor {
visit_item: |item, _context, visitor|
self.resolve_item(item, visitor),
visit_arm: |arm, _context, visitor|
// Items with the !resolve_unexported attribute are X-ray contexts.
// This is used to allow the test runner to run unexported tests.
let orig_xray_flag = self.xray_context;
- if contains_name(attr_metas(item.attrs), ~"!resolve_unexported") {
+ if contains_name(attr_metas(/*bad*/copy item.attrs),
+ ~"!resolve_unexported") {
self.xray_context = Xray;
}
- match item.node {
+ match /*bad*/copy item.node {
// enum item: resolve all the variants' discrs,
// then resolve the ty params
- item_enum(ref enum_def, type_parameters) => {
+ item_enum(ref enum_def, ref type_parameters) => {
for (*enum_def).variants.each() |variant| {
do variant.node.disr_expr.iter() |dis_expr| {
// n.b. the discr expr gets visted twice.
// but maybe it's okay since the first time will signal an
// error if there is one? -- tjc
- do self.with_type_parameter_rib
- (HasTypeParameters(&type_parameters, item.id, 0,
- NormalRibKind))
- || {
-
+ do self.with_type_parameter_rib(
+ HasTypeParameters(
+ type_parameters, item.id, 0, NormalRibKind)) {
visit_item(item, (), visitor);
}
}
visitor);
}
- item_trait(type_parameters, traits, ref methods) => {
+ item_trait(ref type_parameters, ref traits, ref methods) => {
// Create a new rib for the self type.
let self_type_rib = @Rib(NormalRibKind);
(*self.type_ribs).push(self_type_rib);
self_type_rib.bindings.insert(self.self_ident,
dl_def(def_self_ty(item.id)));
+ self_type_rib.bindings.insert(self.type_self_ident,
+ dl_def(def_self_ty(item.id)));
// Create a new rib for the trait-wide type parameters.
do self.with_type_parameter_rib
- (HasTypeParameters(&type_parameters, item.id, 0,
+ (HasTypeParameters(type_parameters, item.id, 0,
NormalRibKind)) {
- self.resolve_type_parameters(type_parameters, visitor);
+ self.resolve_type_parameters(/*bad*/copy *type_parameters,
+ visitor);
// Resolve derived traits.
for traits.each |trt| {
// Resolve the method-specific type
// parameters.
- self.resolve_type_parameters((*ty_m).tps,
- visitor);
+ self.resolve_type_parameters(
+ /*bad*/copy (*ty_m).tps,
+ visitor);
for (*ty_m).decl.inputs.each |argument| {
self.resolve_type(argument.ty, visitor);
item_struct(struct_def, ty_params) => {
self.resolve_struct(item.id,
@copy ty_params,
- struct_def.fields,
+ /*bad*/copy struct_def.fields,
struct_def.dtor,
visitor);
}
item_foreign_mod(foreign_module) => {
do self.with_scope(Some(item.ident)) {
for foreign_module.items.each |foreign_item| {
- match foreign_item.node {
+ match /*bad*/copy foreign_item.node {
foreign_item_fn(_, _, type_parameters) => {
do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters,
}
}
- item_fn(fn_decl, _, ty_params, ref block) => {
+ item_fn(ref fn_decl, _, ref ty_params, ref block) => {
// If this is the main function, we must record it in the
// session.
//
if !self.session.building_library &&
is_none(&self.session.main_fn) &&
- item.ident == syntax::parse::token::special_idents::main {
+ item.ident == special_idents::main {
self.session.main_fn = Some((item.id, item.span));
}
self.resolve_function(OpaqueFunctionRibKind,
- Some(@fn_decl),
+ Some(@/*bad*/copy *fn_decl),
HasTypeParameters
- (&ty_params,
+ (ty_params,
item.id,
0,
OpaqueFunctionRibKind),
// Continue.
}
HasTypeParameters(type_parameters, _, _, _) => {
- self.resolve_type_parameters(*type_parameters, visitor);
+ self.resolve_type_parameters(/*bad*/copy *type_parameters,
+ visitor);
}
}
fn resolve_type_parameters(type_parameters: ~[ty_param],
visitor: ResolveVisitor) {
for type_parameters.each |type_parameter| {
- for type_parameter.bounds.each |bound| {
- self.resolve_type(**bound, visitor);
+ for type_parameter.bounds.each |&bound| {
+ match bound {
+ TraitTyParamBound(ty) => self.resolve_type(ty, visitor),
+ RegionTyParamBound => {}
+ }
}
}
}
OpaqueFunctionRibKind)) {
// Resolve the type parameters.
- self.resolve_type_parameters(*type_parameters, visitor);
+ self.resolve_type_parameters(/*bad*/copy *type_parameters,
+ visitor);
// Resolve fields.
for fields.each |field| {
};
self.resolve_function(rib_kind,
- Some(@method.decl),
+ Some(@/*bad*/copy method.decl),
type_parameters,
method.body,
self_binding,
(borrowed_type_parameters, id, 0,
NormalRibKind)) {
// Resolve the type parameters.
- self.resolve_type_parameters(type_parameters, visitor);
+ self.resolve_type_parameters(/*bad*/copy type_parameters,
+ visitor);
// Resolve the trait reference, if necessary.
let original_trait_refs = self.current_trait_refs;
// Write the result into the def map.
debug!("(resolving type) writing resolution for `%s` \
(id %d)",
- connect(path.idents.map(
- |x| self.session.str_of(*x)), ~"::"),
+ self.idents_to_str(path.idents),
path_id);
self.record_def(path_id, def);
}
None => {
self.session.span_err
(ty.span, fmt!("use of undeclared type name `%s`",
- connect(path.idents.map(
- |x| self.session.str_of(*x)),
- ~"::")));
+ self.idents_to_str(path.idents)));
}
}
}
self.session.span_err(
path.span,
fmt!("`%s` does not name a structure",
- connect(path.idents.map(
- |x| self.session.str_of(*x)),
- ~"::")));
+ self.idents_to_str(path.idents)));
}
}
}
-> BareIdentifierPatternResolution {
match self.resolve_item_in_lexical_scope(self.current_module,
name,
- ValueNS) {
+ ValueNS,
+ SearchThroughModules) {
Success(target) => {
match target.bindings.value_def {
None => {
* If `check_ribs` is true, checks the local definitions first; i.e.
* doesn't skip straight to the containing module.
*/
- fn resolve_path(path: @path, namespace: Namespace, check_ribs: bool,
+ fn resolve_path(path: @path,
+ namespace: Namespace,
+ check_ribs: bool,
visitor: ResolveVisitor)
-> Option<def> {
-
// First, resolve the types.
for path.types.each |ty| {
self.resolve_type(*ty, visitor);
if path.idents.len() > 1 {
return self.resolve_module_relative_path(path,
- self.xray_context,
- namespace);
+ self.xray_context,
+ namespace);
}
return self.resolve_identifier(path.idents.last(),
}
return self.resolve_item_by_identifier_in_lexical_scope(identifier,
- namespace);
+ namespace);
}
// XXX: Merge me with resolve_name_in_module?
let mut containing_module;
match self.resolve_module_path_from_root(root_module,
- module_path_idents,
- 0,
- xray,
- path.span) {
+ module_path_idents,
+ 0,
+ xray,
+ path.span) {
Failed => {
self.session.span_err(path.span,
let name = path.idents.last();
match self.resolve_definition_of_name_in_module(containing_module,
- name,
- namespace,
- xray) {
+ name,
+ namespace,
+ xray) {
NoNameDefinition => {
// We failed to resolve the name. Report an error.
return None;
-> Option<def> {
// Check the items.
match self.resolve_item_in_lexical_scope(self.current_module,
- ident,
- namespace) {
+ ident,
+ namespace,
+ DontSearchThroughModules) {
Success(target) => {
match (*target.bindings).def_for_namespace(namespace) {
None => {
item_struct(class_def, _) => {
for vec::each(class_def.fields) |field| {
match field.node.kind {
- syntax::ast::unnamed_field
- => {},
- syntax::ast::named_field(ident, _, _)
- => {
+ unnamed_field => {},
+ named_field(ident, _, _) => {
if str::eq_slice(self.session.str_of(ident),
name) {
return true
Some(def) => {
// Write the result into the def map.
debug!("(resolving expr) resolved `%s`",
- connect(path.idents.map(
- |x| self.session.str_of(*x)), ~"::"));
+ self.idents_to_str(path.idents));
self.record_def(expr.id, def);
}
None => {
- let wrong_name =
- connect(path.idents.map(
- |x| self.session.str_of(*x)), ~"::") ;
+ let wrong_name = self.idents_to_str(
+ /*bad*/copy path.idents);
if self.name_exists_in_scope_struct(wrong_name) {
self.session.span_err(expr.span,
fmt!("unresolved name: `%s`. \
visit_expr(expr, (), visitor);
}
- expr_fn(_, fn_decl, ref block, capture_clause) |
- expr_fn_block(fn_decl, ref block, capture_clause) => {
+ expr_fn(_, ref fn_decl, ref block, capture_clause) |
+ expr_fn_block(ref fn_decl, ref block, capture_clause) => {
self.resolve_function(FunctionRibKind(expr.id, block.node.id),
- Some(@fn_decl),
+ Some(@/*bad*/copy *fn_decl),
NoTypeParameters,
(*block),
NoSelfBinding,
self.session.span_err(
path.span,
fmt!("`%s` does not name a structure",
- connect(path.idents.map(
- |x| self.session.str_of(*x)),
- ~"::")));
+ self.idents_to_str(path.idents)));
}
}
}
expr_binary(add, _, _) | expr_assign_op(add, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.add_trait);
+ self.lang_items.add_trait());
}
expr_binary(subtract, _, _) | expr_assign_op(subtract, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.sub_trait);
+ self.lang_items.sub_trait());
}
expr_binary(mul, _, _) | expr_assign_op(mul, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.mul_trait);
+ self.lang_items.mul_trait());
}
expr_binary(div, _, _) | expr_assign_op(div, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.div_trait);
+ self.lang_items.div_trait());
}
expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.modulo_trait);
+ self.lang_items.modulo_trait());
}
expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.bitxor_trait);
+ self.lang_items.bitxor_trait());
}
expr_binary(bitand, _, _) | expr_assign_op(bitand, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.bitand_trait);
+ self.lang_items.bitand_trait());
}
expr_binary(bitor, _, _) | expr_assign_op(bitor, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.bitor_trait);
+ self.lang_items.bitor_trait());
}
expr_binary(shl, _, _) | expr_assign_op(shl, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.shl_trait);
+ self.lang_items.shl_trait());
}
expr_binary(shr, _, _) | expr_assign_op(shr, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.shr_trait);
+ self.lang_items.shr_trait());
}
expr_binary(lt, _, _) | expr_binary(le, _, _) |
expr_binary(ge, _, _) | expr_binary(gt, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.ord_trait);
+ self.lang_items.ord_trait());
}
expr_binary(eq, _, _) | expr_binary(ne, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.eq_trait);
+ self.lang_items.eq_trait());
}
expr_unary(neg, _) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.neg_trait);
+ self.lang_items.neg_trait());
+ }
+ expr_unary(not, _) => {
+ self.add_fixed_trait_for_expr(expr.id,
+ self.lang_items.not_trait());
}
expr_index(*) => {
self.add_fixed_trait_for_expr(expr.id,
- self.lang_items.index_trait);
+ self.lang_items.index_trait());
}
_ => {
// Nothing to do.
}
}
- fn add_fixed_trait_for_expr(expr_id: node_id, +trait_id: Option<def_id>) {
+ fn add_fixed_trait_for_expr(expr_id: node_id, +trait_id: def_id) {
let traits = @DVec();
- traits.push(trait_id.get());
+ traits.push(trait_id);
self.trait_map.insert(expr_id, traits);
}
// hit.
//
- /// A somewhat inefficient routine to print out the name of a module.
+ /// A somewhat inefficient routine to obtain the name of a module.
fn module_to_str(module_: @Module) -> ~str {
let idents = DVec();
let mut current_module = module_;
current_module = module_;
}
BlockParentLink(module_, _) => {
- idents.push(syntax::parse::token::special_idents::opaque);
+ idents.push(special_idents::opaque);
current_module = module_;
}
}
if idents.len() == 0 {
return ~"???";
}
-
- let mut string = ~"";
- let mut i = idents.len() - 1;
- loop {
- if i < idents.len() - 1 {
- string += ~"::";
- }
- string += self.session.str_of(idents.get_elt(i));
-
- if i == 0 {
- break;
- }
- i -= 1;
- }
-
- return string;
+ return self.idents_to_str(vec::reversed(idents.get()));
}
fn dump_module(module_: @Module) {
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ *
+ * # Compilation of match statements
+ *
+ * I will endeavor to explain the code as best I can. I have only a loose
+ * understanding of some parts of it.
+ *
+ * ## Matching
+ *
+ * The basic state of the code is maintained in an array `m` of `@Match`
+ * objects. Each `@Match` describes some list of patterns, all of which must
+ * match against the current list of values. If those patterns match, then
+ * the arm listed in the match is the correct arm. A given arm may have
+ * multiple corresponding match entries, one for each alternative that
+ * remains. As we proceed these sets of matches are adjusted by the various
+ * `enter_XXX()` functions, each of which adjusts the set of options given
+ * some information about the value which has been matched.
+ *
+ * So, initially, there is one value and N matches, each of which have one
+ * constituent pattern. N here is usually the number of arms but may be
+ * greater, if some arms have multiple alternatives. For example, here:
+ *
+ * enum Foo { A, B(int), C(uint, uint) }
+ * match foo {
+ * A => ...,
+ * B(x) => ...,
+ * C(1u, 2) => ...,
+ * C(_) => ...
+ * }
+ *
+ * The value would be `foo`. There would be four matches, each of which
+ * contains one pattern (and, in one case, a guard). We could collect the
+ * various options and then compile the code for the case where `foo` is an
+ * `A`, a `B`, and a `C`. When we generate the code for `C`, we would (1)
+ * drop the two matches that do not match a `C` and (2) expand the other two
+ * into two patterns each. In the first case, the two patterns would be `1u`
+ * and `2`, and the in the second case the _ pattern would be expanded into
+ * `_` and `_`. The two values are of course the arguments to `C`.
+ *
+ * Here is a quick guide to the various functions:
+ *
+ * - `compile_submatch()`: The main workhouse. It takes a list of values and
+ * a list of matches and finds the various possibilities that could occur.
+ *
+ * - `enter_XXX()`: modifies the list of matches based on some information
+ * about the value that has been matched. For example,
+ * `enter_rec_or_struct()` adjusts the values given that a record or struct
+ * has been matched. This is an infallible pattern, so *all* of the matches
+ * must be either wildcards or record/struct patterns. `enter_opt()`
+ * handles the fallible cases, and it is correspondingly more complex.
+ *
+ * ## Bindings
+ *
+ * We store information about the bound variables for each arm as part of the
+ * per-arm `ArmData` struct. There is a mapping from identifiers to
+ * `BindingInfo` structs. These structs contain the mode/id/type of the
+ * binding, but they also contain up to two LLVM values, called `llmatch` and
+ * `llbinding` respectively (the `llbinding`, as will be described shortly, is
+ * optional and only present for by-value bindings---therefore it is bundled
+ * up as part of the `TransBindingMode` type). Both point at allocas.
+ *
+ * The `llmatch` binding always stores a pointer into the value being matched
+ * which points at the data for the binding. If the value being matched has
+ * type `T`, then, `llmatch` will point at an alloca of type `T*` (and hence
+ * `llmatch` has type `T**`). So, if you have a pattern like:
+ *
+ * let a: A = ...;
+ * let b: B = ...;
+ * match (a, b) { (ref c, copy d) => { ... } }
+ *
+ * For `c` and `d`, we would generate allocas of type `C*` and `D*`
+ * respectively. These are called the `llmatch`. As we match, when we come
+ * up against an identifier, we store the current pointer into the
+ * corresponding alloca.
+ *
+ * In addition, for each by-value binding (copy or move), we will create a
+ * second alloca (`llbinding`) that will hold the final value. In this
+ * example, that means that `d` would have this second alloca of type `D` (and
+ * hence `llbinding` has type `D*`).
+ *
+ * Once a pattern is completely matched, and assuming that there is no guard
+ * pattern, we will branch to a block that leads to the body itself. For any
+ * by-value bindings, this block will first load the ptr from `llmatch` (the
+ * one of type `D*`) and copy/move the value into `llbinding` (the one of type
+ * `D`). The second alloca then becomes the value of the local variable. For
+ * by ref bindings, the value of the local variable is simply the first
+ * alloca.
+ *
+ * So, for the example above, we would generate a setup kind of like this:
+ *
+ * +-------+
+ * | Entry |
+ * +-------+
+ * |
+ * +-------------------------------------------+
+ * | llmatch_c = (addr of first half of tuple) |
+ * | llmatch_d = (addr of first half of tuple) |
+ * +-------------------------------------------+
+ * |
+ * +--------------------------------------+
+ * | *llbinding_d = **llmatch_dlbinding_d |
+ * +--------------------------------------+
+ *
+ * If there is a guard, the situation is slightly different, because we must
+ * execute the guard code. Moreover, we need to do so once for each of the
+ * alternatives that lead to the arm, because if the guard fails, they may
+ * have different points from which to continue the search. Therefore, in that
+ * case, we generate code that looks more like:
+ *
+ * +-------+
+ * | Entry |
+ * +-------+
+ * |
+ * +-------------------------------------------+
+ * | llmatch_c = (addr of first half of tuple) |
+ * | llmatch_d = (addr of first half of tuple) |
+ * +-------------------------------------------+
+ * |
+ * +-------------------------------------------------+
+ * | *llbinding_d = **llmatch_dlbinding_d |
+ * | check condition |
+ * | if false { free *llbinding_d, goto next case } |
+ * | if true { goto body } |
+ * +-------------------------------------------------+
+ *
+ * The handling for the cleanups is a bit... sensitive. Basically, the body
+ * is the one that invokes `add_clean()` for each binding. During the guard
+ * evaluation, we add temporary cleanups and revoke them after the guard is
+ * evaluated (it could fail, after all). Presuming the guard fails, we drop
+ * the various values we copied explicitly. Note that guards and moves are
+ * just plain incompatible.
+ *
+ */
+
+use core::prelude::*;
+
+use back::abi;
+use lib::llvm::llvm;
+use lib::llvm::{ValueRef, BasicBlockRef};
+use middle::const_eval;
+use middle::pat_util::*;
+use middle::resolve::DefMap;
+use middle::trans::base::*;
+use middle::trans::build::*;
+use middle::trans::callee;
+use middle::trans::common::*;
+use middle::trans::consts;
+use middle::trans::controlflow;
+use middle::trans::datum::*;
+use middle::trans::expr::Dest;
+use middle::trans::expr;
+use middle::trans::glue;
+use middle::ty::{CopyValue, MoveValue, ReadValue};
+use util::common::indenter;
+
+use core::dvec::DVec;
+use core::dvec;
+use std::map::HashMap;
+use syntax::ast::def_id;
+use syntax::ast;
+use syntax::ast_util::{dummy_sp, path_to_ident};
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::print::pprust::pat_to_str;
+
+fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export.
+
+// An option identifying a literal: either a unit-like struct or an
+// expression.
+enum Lit {
+ UnitLikeStructLit(ast::node_id), // the node ID of the pattern
+ ExprLit(@ast::expr),
+ ConstLit(ast::def_id), // the def ID of the constant
+}
+
+// An option identifying a branch (either a literal, a enum variant or a
+// range)
+enum Opt {
+ lit(Lit),
+ var(/* disr val */int, /* variant dids */{enm: def_id, var: def_id}),
+ range(@ast::expr, @ast::expr),
+ vec_len_eq(uint),
+ vec_len_ge(uint)
+}
+
+fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
+ match (*a, *b) {
+ (lit(a), lit(b)) => {
+ match (a, b) {
+ (UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
+ _ => {
+ let a_expr;
+ match a {
+ ExprLit(existing_a_expr) => a_expr = existing_a_expr,
+ ConstLit(a_const) => {
+ let e = const_eval::lookup_const_by_id(tcx, a_const);
+ a_expr = e.get();
+ }
+ UnitLikeStructLit(_) => {
+ fail ~"UnitLikeStructLit should have been handled \
+ above"
+ }
+ }
+
+ let b_expr;
+ match b {
+ ExprLit(existing_b_expr) => b_expr = existing_b_expr,
+ ConstLit(b_const) => {
+ let e = const_eval::lookup_const_by_id(tcx, b_const);
+ b_expr = e.get();
+ }
+ UnitLikeStructLit(_) => {
+ fail ~"UnitLikeStructLit should have been handled \
+ above"
+ }
+ }
+
+ const_eval::compare_lit_exprs(tcx, a_expr, b_expr) == 0
+ }
+ }
+ }
+ (range(a1, a2), range(b1, b2)) => {
+ const_eval::compare_lit_exprs(tcx, a1, b1) == 0 &&
+ const_eval::compare_lit_exprs(tcx, a2, b2) == 0
+ }
+ (var(a, _), var(b, _)) => a == b,
+ (vec_len_eq(a), vec_len_eq(b)) => a == b,
+ (vec_len_ge(a), vec_len_ge(b)) => a == b,
+ _ => false
+ }
+}
+
+enum opt_result {
+ single_result(Result),
+ lower_bound(Result),
+ range_result(Result, Result),
+}
+fn trans_opt(bcx: block, o: &Opt) -> opt_result {
+ let _icx = bcx.insn_ctxt("match::trans_opt");
+ let ccx = bcx.ccx();
+ let mut bcx = bcx;
+ match *o {
+ lit(ExprLit(lit_expr)) => {
+ let datumblock = expr::trans_to_datum(bcx, lit_expr);
+ return single_result(datumblock.to_result());
+ }
+ lit(UnitLikeStructLit(pat_id)) => {
+ let struct_ty = ty::node_id_to_type(bcx.tcx(), pat_id);
+ let datumblock = datum::scratch_datum(bcx, struct_ty, true);
+ return single_result(datumblock.to_result(bcx));
+ }
+ lit(ConstLit(lit_id)) => {
+ let llval = consts::get_const_val(bcx.ccx(), lit_id);
+ return single_result(rslt(bcx, llval));
+ }
+ var(disr_val, _) => {
+ return single_result(rslt(bcx, C_int(ccx, disr_val)));
+ }
+ range(l1, l2) => {
+ return range_result(rslt(bcx, consts::const_expr(ccx, l1)),
+ rslt(bcx, consts::const_expr(ccx, l2)));
+ }
+ vec_len_eq(n) => {
+ return single_result(rslt(bcx, C_int(ccx, n as int)));
+ }
+ vec_len_ge(n) => {
+ return lower_bound(rslt(bcx, C_int(ccx, n as int)));
+ }
+ }
+}
+
+fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> Opt {
+ match tcx.def_map.get(pat_id) {
+ ast::def_variant(enum_id, var_id) => {
+ let variants = ty::enum_variants(tcx, enum_id);
+ for vec::each(*variants) |v| {
+ if var_id == v.id {
+ return var(v.disr_val, {enm: enum_id, var: var_id});
+ }
+ }
+ ::core::util::unreachable();
+ }
+ ast::def_struct(_) => {
+ return lit(UnitLikeStructLit(pat_id));
+ }
+ _ => {
+ tcx.sess.bug(~"non-variant or struct in variant_opt()");
+ }
+ }
+}
+
+enum TransBindingMode {
+ TrByValue(/*ismove:*/ bool, /*llbinding:*/ ValueRef),
+ TrByRef,
+ TrByImplicitRef
+}
+
+/**
+ * Information about a pattern binding:
+ * - `llmatch` is a pointer to a stack slot. The stack slot contains a
+ * pointer into the value being matched. Hence, llmatch has type `T**`
+ * where `T` is the value being matched.
+ * - `trmode` is the trans binding mode
+ * - `id` is the node id of the binding
+ * - `ty` is the Rust type of the binding */
+struct BindingInfo {
+ llmatch: ValueRef,
+ trmode: TransBindingMode,
+ id: ast::node_id,
+ ty: ty::t,
+}
+
+type BindingsMap = HashMap<ident, BindingInfo>;
+
+struct ArmData {
+ bodycx: block,
+ arm: &ast::arm,
+ bindings_map: BindingsMap
+}
+
+struct Match {
+ pats: ~[@ast::pat],
+ data: @ArmData
+}
+
+fn match_to_str(bcx: block, m: &Match) -> ~str {
+ if bcx.sess().verbose() {
+ // for many programs, this just take too long to serialize
+ fmt!("%?", m.pats.map(|p| pat_to_str(*p, bcx.sess().intr())))
+ } else {
+ fmt!("%u pats", m.pats.len())
+ }
+}
+
+fn matches_to_str(bcx: block, m: &[@Match]) -> ~str {
+ fmt!("%?", m.map(|n| match_to_str(bcx, *n)))
+}
+
+fn has_nested_bindings(m: &[@Match], col: uint) -> bool {
+ for vec::each(m) |br| {
+ match br.pats[col].node {
+ ast::pat_ident(_, _, Some(_)) => return true,
+ _ => ()
+ }
+ }
+ return false;
+}
+
+fn expand_nested_bindings(bcx: block, m: &[@Match/&r],
+ col: uint, val: ValueRef)
+ -> ~[@Match/&r]
+{
+ debug!("expand_nested_bindings(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ do m.map |br| {
+ match br.pats[col].node {
+ ast::pat_ident(_, path, Some(inner)) => {
+ let pats = vec::append(
+ vec::slice(br.pats, 0u, col),
+ vec::append(~[inner],
+ vec::view(br.pats, col + 1u, br.pats.len())));
+
+ let binding_info =
+ br.data.bindings_map.get(path_to_ident(path));
+
+ Store(bcx, val, binding_info.llmatch);
+ @Match {pats: pats, data: br.data}
+ }
+ _ => {
+ *br
+ }
+ }
+ }
+}
+
+type enter_pat = fn(@ast::pat) -> Option<~[@ast::pat]>;
+
+fn assert_is_binding_or_wild(bcx: block, p: @ast::pat) {
+ if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
+ bcx.sess().span_bug(
+ p.span,
+ fmt!("Expected an identifier pattern but found p: %s",
+ pat_to_str(p, bcx.sess().intr())));
+ }
+}
+
+fn enter_match(bcx: block, dm: DefMap, m: &[@Match/&r],
+ col: uint, val: ValueRef, e: enter_pat)
+ -> ~[@Match/&r]
+{
+ debug!("enter_match(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let mut result = ~[];
+ for vec::each(m) |br| {
+ match e(br.pats[col]) {
+ Some(sub) => {
+ let pats =
+ vec::append(
+ vec::append(sub, vec::view(br.pats, 0u, col)),
+ vec::view(br.pats, col + 1u, br.pats.len()));
+
+ let self = br.pats[col];
+ match self.node {
+ ast::pat_ident(_, path, None) => {
+ if pat_is_binding(dm, self) {
+ let binding_info =
+ br.data.bindings_map.get(path_to_ident(path));
+ Store(bcx, val, binding_info.llmatch);
+ }
+ }
+ _ => {}
+ }
+
+ result.push(@Match {pats: pats, data: br.data});
+ }
+ None => ()
+ }
+ }
+
+ debug!("result=%s", matches_to_str(bcx, result));
+
+ return result;
+}
+
+fn enter_default(bcx: block, dm: DefMap, m: &[@Match/&r],
+ col: uint, val: ValueRef)
+ -> ~[@Match/&r]
+{
+ debug!("enter_default(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match p.node {
+ ast::pat_wild | ast::pat_rec(_, _) | ast::pat_tup(_) |
+ ast::pat_struct(*) => Some(~[]),
+ ast::pat_ident(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
+ _ => None
+ }
+ }
+}
+
+// <pcwalton> nmatsakis: what does enter_opt do?
+// <pcwalton> in trans/match
+// <pcwalton> trans/match.rs is like stumbling around in a dark cave
+// <nmatsakis> pcwalton: the enter family of functions adjust the set of
+// patterns as needed
+// <nmatsakis> yeah, at some point I kind of achieved some level of
+// understanding
+// <nmatsakis> anyhow, they adjust the patterns given that something of that
+// kind has been found
+// <nmatsakis> pcwalton: ok, right, so enter_XXX() adjusts the patterns, as I
+// said
+// <nmatsakis> enter_match() kind of embodies the generic code
+// <nmatsakis> it is provided with a function that tests each pattern to see
+// if it might possibly apply and so forth
+// <nmatsakis> so, if you have a pattern like {a: _, b: _, _} and one like _
+// <nmatsakis> then _ would be expanded to (_, _)
+// <nmatsakis> one spot for each of the sub-patterns
+// <nmatsakis> enter_opt() is one of the more complex; it covers the fallible
+// cases
+// <nmatsakis> enter_rec_or_struct() or enter_tuple() are simpler, since they
+// are infallible patterns
+// <nmatsakis> so all patterns must either be records (resp. tuples) or
+// wildcards
+
+fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
+ variant_size: uint, val: ValueRef)
+ -> ~[@Match/&r]
+{
+ debug!("enter_opt(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let tcx = bcx.tcx();
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, tcx.def_map, m, col, val) |p| {
+ match /*bad*/copy p.node {
+ ast::pat_enum(_, subpats) => {
+ if opt_eq(tcx, &variant_opt(tcx, p.id), opt) {
+ Some(option::get_or_default(subpats,
+ vec::from_elem(variant_size,
+ dummy)))
+ } else {
+ None
+ }
+ }
+ ast::pat_ident(_, _, None)
+ if pat_is_variant_or_struct(tcx.def_map, p) => {
+ if opt_eq(tcx, &variant_opt(tcx, p.id), opt) {
+ Some(~[])
+ } else {
+ None
+ }
+ }
+ ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
+ let const_def = tcx.def_map.get(p.id);
+ let const_def_id = ast_util::def_id_of_def(const_def);
+ if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
+ Some(~[])
+ } else {
+ None
+ }
+ }
+ ast::pat_lit(l) => {
+ if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(~[])} else {None}
+ }
+ ast::pat_range(l1, l2) => {
+ if opt_eq(tcx, &range(l1, l2), opt) {Some(~[])} else {None}
+ }
+ ast::pat_struct(_, field_pats, _) => {
+ if opt_eq(tcx, &variant_opt(tcx, p.id), opt) {
+ // Look up the struct variant ID.
+ let struct_id;
+ match tcx.def_map.get(p.id) {
+ ast::def_variant(_, found_struct_id) => {
+ struct_id = found_struct_id;
+ }
+ _ => {
+ tcx.sess.span_bug(p.span, ~"expected enum \
+ variant def");
+ }
+ }
+
+ // Reorder the patterns into the same order they were
+ // specified in the struct definition. Also fill in
+ // unspecified fields with dummy.
+ let reordered_patterns = dvec::DVec();
+ for ty::lookup_struct_fields(tcx, struct_id).each
+ |field| {
+ match field_pats.find(|p|
+ p.ident == field.ident) {
+ None => reordered_patterns.push(dummy),
+ Some(fp) => reordered_patterns.push(fp.pat)
+ }
+ }
+ Some(dvec::unwrap(move reordered_patterns))
+ } else {
+ None
+ }
+ }
+ ast::pat_vec(elems, tail) => {
+ match tail {
+ Some(_) => {
+ if opt_eq(tcx, &vec_len_ge(elems.len()), opt) {
+ Some(vec::append_one(elems, tail.get()))
+ } else {
+ None
+ }
+ }
+ None => {
+ if opt_eq(tcx, &vec_len_eq(elems.len()), opt) {
+ Some(copy elems)
+ } else {
+ None
+ }
+ }
+ }
+ }
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(vec::from_elem(variant_size, dummy))
+ }
+ }
+ }
+}
+
+fn enter_rec_or_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint,
+ fields: ~[ast::ident], val: ValueRef) -> ~[@Match/&r] {
+ debug!("enter_rec_or_struct(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match /*bad*/copy p.node {
+ ast::pat_rec(fpats, _) | ast::pat_struct(_, fpats, _) => {
+ let mut pats = ~[];
+ for vec::each(fields) |fname| {
+ match fpats.find(|p| p.ident == *fname) {
+ None => pats.push(dummy),
+ Some(pat) => pats.push(pat.pat)
+ }
+ }
+ Some(pats)
+ }
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(vec::from_elem(fields.len(), dummy))
+ }
+ }
+ }
+}
+
+fn enter_tup(bcx: block, dm: DefMap, m: &[@Match/&r],
+ col: uint, val: ValueRef, n_elts: uint)
+ -> ~[@Match/&r]
+{
+ debug!("enter_tup(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match /*bad*/copy p.node {
+ ast::pat_tup(elts) => {
+ Some(elts)
+ }
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(vec::from_elem(n_elts, dummy))
+ }
+ }
+ }
+}
+
+fn enter_tuple_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint,
+ val: ValueRef, n_elts: uint)
+ -> ~[@Match/&r]
+{
+ debug!("enter_tuple_struct(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match /*bad*/copy p.node {
+ ast::pat_enum(_, Some(elts)) => Some(elts),
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(vec::from_elem(n_elts, dummy))
+ }
+ }
+ }
+}
+
+fn enter_box(bcx: block, dm: DefMap, m: &[@Match/&r],
+ col: uint, val: ValueRef)
+ -> ~[@Match/&r]
+{
+ debug!("enter_box(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match p.node {
+ ast::pat_box(sub) => {
+ Some(~[sub])
+ }
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(~[dummy])
+ }
+ }
+ }
+}
+
+fn enter_uniq(bcx: block, dm: DefMap, m: &[@Match/&r],
+ col: uint, val: ValueRef)
+ -> ~[@Match/&r]
+{
+ debug!("enter_uniq(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match p.node {
+ ast::pat_uniq(sub) => {
+ Some(~[sub])
+ }
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(~[dummy])
+ }
+ }
+ }
+}
+
+fn enter_region(bcx: block, dm: DefMap, m: &[@Match/&r],
+ col: uint, val: ValueRef)
+ -> ~[@Match/&r]
+{
+ debug!("enter_region(bcx=%s, m=%s, col=%u, val=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ col,
+ bcx.val_str(val));
+ let _indenter = indenter();
+
+ let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
+ do enter_match(bcx, dm, m, col, val) |p| {
+ match p.node {
+ ast::pat_region(sub) => {
+ Some(~[sub])
+ }
+ _ => {
+ assert_is_binding_or_wild(bcx, p);
+ Some(~[dummy])
+ }
+ }
+ }
+}
+
+// Returns the options in one column of matches. An option is something that
+// needs to be conditionally matched at runtime; for example, the discriminant
+// on a set of enum variants or a literal.
+fn get_options(ccx: @crate_ctxt, m: &[@Match], col: uint) -> ~[Opt] {
+ fn add_to_set(tcx: ty::ctxt, set: &DVec<Opt>, val: Opt) {
+ if set.any(|l| opt_eq(tcx, l, &val)) {return;}
+ set.push(val);
+ }
+
+ let found = DVec();
+ for vec::each(m) |br| {
+ let cur = br.pats[col];
+ match /*bad*/copy cur.node {
+ ast::pat_lit(l) => {
+ add_to_set(ccx.tcx, &found, lit(ExprLit(l)));
+ }
+ ast::pat_ident(*) => {
+ // This is one of: an enum variant, a unit-like struct, or a
+ // variable binding.
+ match ccx.tcx.def_map.find(cur.id) {
+ Some(ast::def_variant(*)) => {
+ add_to_set(ccx.tcx, &found,
+ variant_opt(ccx.tcx, cur.id));
+ }
+ Some(ast::def_struct(*)) => {
+ add_to_set(ccx.tcx, &found,
+ lit(UnitLikeStructLit(cur.id)));
+ }
+ Some(ast::def_const(const_did)) => {
+ add_to_set(ccx.tcx, &found,
+ lit(ConstLit(const_did)));
+ }
+ _ => {}
+ }
+ }
+ ast::pat_enum(*) | ast::pat_struct(*) => {
+ // This could be one of: a tuple-like enum variant, a
+ // struct-like enum variant, or a struct.
+ match ccx.tcx.def_map.find(cur.id) {
+ Some(ast::def_variant(*)) => {
+ add_to_set(ccx.tcx, &found,
+ variant_opt(ccx.tcx, cur.id));
+ }
+ _ => {}
+ }
+ }
+ ast::pat_range(l1, l2) => {
+ add_to_set(ccx.tcx, &found, range(l1, l2));
+ }
+ ast::pat_vec(elems, tail) => {
+ let opt = match tail {
+ None => vec_len_eq(elems.len()),
+ Some(_) => vec_len_ge(elems.len())
+ };
+ add_to_set(ccx.tcx, &found, opt);
+ }
+ _ => {}
+ }
+ }
+ return dvec::unwrap(move found);
+}
+
+fn extract_variant_args(bcx: block, pat_id: ast::node_id,
+ vdefs: {enm: def_id, var: def_id},
+ val: ValueRef)
+ -> {vals: ~[ValueRef], bcx: block}
+{
+ let _icx = bcx.insn_ctxt("match::extract_variant_args");
+ let ccx = bcx.fcx.ccx;
+ let enum_ty_substs = match ty::get(node_id_type(bcx, pat_id)).sty {
+ ty::ty_enum(id, ref substs) => {
+ assert id == vdefs.enm;
+ /*bad*/copy (*substs).tps
+ }
+ _ => bcx.sess().bug(~"extract_variant_args: pattern has non-enum type")
+ };
+ let mut blobptr = val;
+ let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
+ let size = ty::enum_variant_with_id(ccx.tcx, vdefs.enm,
+ vdefs.var).args.len();
+ if size > 0u && (*variants).len() != 1u {
+ let enumptr =
+ PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
+ blobptr = GEPi(bcx, enumptr, [0u, 1u]);
+ }
+ let vdefs_tg = vdefs.enm;
+ let vdefs_var = vdefs.var;
+ let args = do vec::from_fn(size) |i| {
+ GEP_enum(bcx, blobptr, vdefs_tg, vdefs_var,
+ /*bad*/copy enum_ty_substs, i)
+ };
+ return {vals: args, bcx: bcx};
+}
+
+fn extract_vec_elems(bcx: block, pat_id: ast::node_id,
+ elem_count: uint, tail: bool, val: ValueRef)
+ -> {vals: ~[ValueRef], bcx: block}
+{
+ let _icx = bcx.insn_ctxt("match::extract_vec_elems");
+ let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
+ let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
+ let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
+
+ let mut elems = do vec::from_fn(elem_count) |i| {
+ GEPi(bcx, base, ~[i])
+ };
+ if tail {
+ let tail_offset = Mul(bcx, vt.llunit_size,
+ C_int(bcx.ccx(), elem_count as int)
+ );
+ let tail_begin = tvec::pointer_add(bcx, base, tail_offset);
+ let tail_len = Sub(bcx, len, tail_offset);
+ let tail_ty = ty::mk_evec(bcx.tcx(),
+ {ty: vt.unit_ty, mutbl: ast::m_imm},
+ ty::vstore_slice(ty::re_static)
+ );
+ let scratch = scratch_datum(bcx, tail_ty, false);
+ Store(bcx, tail_begin,
+ GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
+ );
+ Store(bcx, tail_len,
+ GEPi(bcx, scratch.val, [0u, abi::slice_elt_len])
+ );
+ elems.push(scratch.val);
+ scratch.add_clean(bcx);
+ }
+ return {vals: elems, bcx: bcx};
+}
+
+// NB: This function does not collect fields from struct-like enum variants.
+fn collect_record_or_struct_fields(bcx: block, m: &[@Match], col: uint) ->
+ ~[ast::ident] {
+ let mut fields: ~[ast::ident] = ~[];
+ for vec::each(m) |br| {
+ match /*bad*/copy br.pats[col].node {
+ ast::pat_rec(fs, _) => extend(&mut fields, fs),
+ ast::pat_struct(_, fs, _) => {
+ match ty::get(node_id_type(bcx, br.pats[col].id)).sty {
+ ty::ty_struct(*) => extend(&mut fields, fs),
+ _ => ()
+ }
+ }
+ _ => ()
+ }
+ }
+ return fields;
+
+ fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
+ for field_pats.each |field_pat| {
+ let field_ident = field_pat.ident;
+ if !vec::any(*idents, |x| *x == field_ident) {
+ idents.push(field_ident);
+ }
+ }
+ }
+}
+
+fn root_pats_as_necessary(bcx: block, m: &[@Match],
+ col: uint, val: ValueRef)
+{
+ for vec::each(m) |br| {
+ let pat_id = br.pats[col].id;
+
+ match bcx.ccx().maps.root_map.find({id:pat_id, derefs:0u}) {
+ None => (),
+ Some(scope_id) => {
+ // Note: the scope_id will always be the id of the match. See
+ // the extended comment in rustc::middle::borrowck::preserve()
+ // for details (look for the case covering cat_discr).
+
+ let datum = Datum {val: val, ty: node_id_type(bcx, pat_id),
+ mode: ByRef, source: FromLvalue};
+ datum.root(bcx, scope_id);
+ return; // if we kept going, we'd only re-root the same value
+ }
+ }
+ }
+}
+
+// Macro for deciding whether any of the remaining matches fit a given kind of
+// pattern. Note that, because the macro is well-typed, either ALL of the
+// matches should fit that sort of pattern or NONE (however, some of the
+// matches may be wildcards like _ or identifiers).
+macro_rules! any_pat (
+ ($m:expr, $pattern:pat) => (
+ vec::any($m, |br| {
+ match br.pats[col].node {
+ $pattern => true,
+ _ => false
+ }
+ })
+ )
+)
+
+fn any_box_pat(m: &[@Match], col: uint) -> bool {
+ any_pat!(m, ast::pat_box(_))
+}
+
+fn any_uniq_pat(m: &[@Match], col: uint) -> bool {
+ any_pat!(m, ast::pat_uniq(_))
+}
+
+fn any_region_pat(m: &[@Match], col: uint) -> bool {
+ any_pat!(m, ast::pat_region(_))
+}
+
+fn any_tup_pat(m: &[@Match], col: uint) -> bool {
+ any_pat!(m, ast::pat_tup(_))
+}
+
+fn any_tuple_struct_pat(bcx: block, m: &[@Match], col: uint) -> bool {
+ vec::any(m, |br| {
+ let pat = br.pats[col];
+ match pat.node {
+ ast::pat_enum(_, Some(_)) => {
+ match bcx.tcx().def_map.find(pat.id) {
+ Some(ast::def_struct(*)) => true,
+ _ => false
+ }
+ }
+ _ => false
+ }
+ })
+}
+
+type mk_fail = fn@() -> BasicBlockRef;
+
+fn pick_col(m: &[@Match]) -> uint {
+ fn score(p: @ast::pat) -> uint {
+ match p.node {
+ ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) => 1u,
+ ast::pat_ident(_, _, Some(p)) => score(p),
+ _ => 0u
+ }
+ }
+ let scores = vec::to_mut(vec::from_elem(m[0].pats.len(), 0u));
+ for vec::each(m) |br| {
+ let mut i = 0u;
+ for vec::each(br.pats) |p| { scores[i] += score(*p); i += 1u; }
+ }
+ let mut max_score = 0u;
+ let mut best_col = 0u;
+ let mut i = 0u;
+ for vec::each(scores) |score| {
+ let score = *score;
+
+ // Irrefutable columns always go first, they'd only be duplicated in
+ // the branches.
+ if score == 0u { return i; }
+ // If no irrefutable ones are found, we pick the one with the biggest
+ // branching factor.
+ if score > max_score { max_score = score; best_col = i; }
+ i += 1u;
+ }
+ return best_col;
+}
+
+enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
+
+impl branch_kind : cmp::Eq {
+ pure fn eq(&self, other: &branch_kind) -> bool {
+ ((*self) as uint) == ((*other) as uint)
+ }
+ pure fn ne(&self, other: &branch_kind) -> bool { !(*self).eq(other) }
+}
+
+// Compiles a comparison between two things.
+fn compare_values(cx: block, lhs: ValueRef, rhs: ValueRef, rhs_t: ty::t) ->
+ Result {
+ let _icx = cx.insn_ctxt("compare_values");
+ if ty::type_is_scalar(rhs_t) {
+ let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::eq);
+ return rslt(rs.bcx, rs.val);
+ }
+
+ match ty::get(rhs_t).sty {
+ ty::ty_estr(ty::vstore_uniq) => {
+ let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()),
+ false);
+ let scratch_lhs = alloca(cx, val_ty(lhs));
+ Store(cx, lhs, scratch_lhs);
+ let scratch_rhs = alloca(cx, val_ty(rhs));
+ Store(cx, rhs, scratch_rhs);
+ let did = cx.tcx().lang_items.uniq_str_eq_fn();
+ let bcx = callee::trans_rtcall_or_lang_call(cx, did,
+ ~[scratch_lhs,
+ scratch_rhs],
+ expr::SaveIn(
+ scratch_result.val));
+ return scratch_result.to_result(bcx);
+ }
+ ty::ty_estr(_) => {
+ let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()),
+ false);
+ let did = cx.tcx().lang_items.str_eq_fn();
+ let bcx = callee::trans_rtcall_or_lang_call(cx, did,
+ ~[lhs, rhs],
+ expr::SaveIn(
+ scratch_result.val));
+ return scratch_result.to_result(bcx);
+ }
+ _ => {
+ cx.tcx().sess.bug(~"only scalars and strings supported in \
+ compare_values");
+ }
+ }
+}
+
+fn store_non_ref_bindings(bcx: block,
+ data: &ArmData,
+ opt_temp_cleanups: Option<&DVec<ValueRef>>)
+ -> block
+{
+ /*!
+ *
+ * For each copy/move binding, copy the value from the value
+ * being matched into its final home. This code executes once
+ * one of the patterns for a given arm has completely matched.
+ * It adds temporary cleanups to the `temp_cleanups` array,
+ * if one is provided.
+ */
+
+ let mut bcx = bcx;
+ for data.bindings_map.each_value |binding_info| {
+ match binding_info.trmode {
+ TrByValue(is_move, lldest) => {
+ let llval = Load(bcx, binding_info.llmatch); // get a T*
+ let datum = Datum {val: llval, ty: binding_info.ty,
+ mode: ByRef, source: FromLvalue};
+ bcx = {
+ if is_move {
+ datum.move_to(bcx, INIT, lldest)
+ } else {
+ datum.copy_to(bcx, INIT, lldest)
+ }
+ };
+
+ for opt_temp_cleanups.each |temp_cleanups| {
+ add_clean_temp_mem(bcx, lldest, binding_info.ty);
+ temp_cleanups.push(lldest);
+ }
+ }
+ TrByRef | TrByImplicitRef => {}
+ }
+ }
+ return bcx;
+}
+
+fn insert_lllocals(bcx: block,
+ data: &ArmData,
+ add_cleans: bool) -> block {
+ /*!
+ *
+ * For each binding in `data.bindings_map`, adds an appropriate entry into
+ * the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for
+ * the bindings. */
+
+ for data.bindings_map.each_value |binding_info| {
+ let llval = match binding_info.trmode {
+ // By value bindings: use the stack slot that we
+ // copied/moved the value into
+ TrByValue(_, lldest) => {
+ if add_cleans {
+ add_clean(bcx, lldest, binding_info.ty);
+ }
+
+ lldest
+ }
+
+ // By ref binding: use the ptr into the matched value
+ TrByRef => {
+ binding_info.llmatch
+ }
+
+ // Ugly: for implicit ref, we actually want a T*, but
+ // we have a T**, so we had to load. This will go away
+ // once implicit refs go away.
+ TrByImplicitRef => {
+ Load(bcx, binding_info.llmatch)
+ }
+ };
+
+ bcx.fcx.lllocals.insert(binding_info.id,
+ local_mem(llval));
+ }
+ return bcx;
+}
+
+fn compile_guard(bcx: block,
+ guard_expr: @ast::expr,
+ data: &ArmData,
+ m: &[@Match],
+ vals: &[ValueRef],
+ chk: Option<mk_fail>)
+ -> block
+{
+ debug!("compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%?)",
+ bcx.to_str(),
+ bcx.expr_to_str(guard_expr),
+ matches_to_str(bcx, m),
+ vals.map(|v| bcx.val_str(*v)));
+ let _indenter = indenter();
+
+ let mut bcx = bcx;
+ let temp_cleanups = DVec();
+ bcx = store_non_ref_bindings(bcx, data, Some(&temp_cleanups));
+ bcx = insert_lllocals(bcx, data, false);
+
+ let val = unpack_result!(bcx, {
+ do with_scope_result(bcx, guard_expr.info(),
+ ~"guard") |bcx| {
+ expr::trans_to_datum(bcx, guard_expr).to_result()
+ }
+ });
+
+ // Revoke the temp cleanups now that the guard successfully executed.
+ for temp_cleanups.each |llval| {
+ revoke_clean(bcx, *llval);
+ }
+
+ return do with_cond(bcx, Not(bcx, val)) |bcx| {
+ // Guard does not match: free the values we copied,
+ // and remove all bindings from the lllocals table
+ let bcx = drop_bindings(bcx, data);
+ compile_submatch(bcx, m, vals, chk);
+ bcx
+ };
+
+ fn drop_bindings(bcx: block, data: &ArmData) -> block {
+ let mut bcx = bcx;
+ for data.bindings_map.each_value |binding_info| {
+ match binding_info.trmode {
+ TrByValue(_, llval) => {
+ bcx = glue::drop_ty(bcx, llval, binding_info.ty);
+ }
+ TrByRef | TrByImplicitRef => {}
+ }
+ bcx.fcx.lllocals.remove(binding_info.id);
+ }
+ return bcx;
+ }
+}
+
+fn compile_submatch(bcx: block,
+ m: &[@Match],
+ vals: &[ValueRef],
+ chk: Option<mk_fail>)
+{
+ debug!("compile_submatch(bcx=%s, m=%s, vals=%?)",
+ bcx.to_str(),
+ matches_to_str(bcx, m),
+ vals.map(|v| bcx.val_str(*v)));
+ let _indenter = indenter();
+
+ /*
+ For an empty match, a fall-through case must exist
+ */
+ assert(m.len() > 0u || chk.is_some());
+ let _icx = bcx.insn_ctxt("match::compile_submatch");
+ let mut bcx = bcx;
+ let tcx = bcx.tcx(), dm = tcx.def_map;
+ if m.len() == 0u {
+ Br(bcx, chk.get()());
+ return;
+ }
+ if m[0].pats.len() == 0u {
+ let data = m[0].data;
+ match data.arm.guard {
+ Some(guard_expr) => {
+ bcx = compile_guard(bcx, guard_expr, m[0].data,
+ vec::view(m, 1, m.len()),
+ vals, chk);
+ }
+ _ => ()
+ }
+ Br(bcx, data.bodycx.llbb);
+ return;
+ }
+
+ let col = pick_col(m);
+ let val = vals[col];
+ let m = {
+ if has_nested_bindings(m, col) {
+ expand_nested_bindings(bcx, m, col, val)
+ } else {
+ m.to_vec()
+ }
+ };
+
+ let vals_left = vec::append(vec::slice(vals, 0u, col),
+ vec::view(vals, col + 1u, vals.len()));
+ let ccx = bcx.fcx.ccx;
+ let mut pat_id = 0;
+ for vec::each(m) |br| {
+ // Find a real id (we're adding placeholder wildcard patterns, but
+ // each column is guaranteed to have at least one real pattern)
+ if pat_id == 0 { pat_id = br.pats[col].id; }
+ }
+
+ root_pats_as_necessary(bcx, m, col, val);
+
+ let rec_fields = collect_record_or_struct_fields(bcx, m, col);
+ if rec_fields.len() > 0 {
+ let pat_ty = node_id_type(bcx, pat_id);
+ do expr::with_field_tys(tcx, pat_ty, None) |_has_dtor, field_tys| {
+ let rec_vals = rec_fields.map(|field_name| {
+ let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
+ GEPi(bcx, val, struct_field(ix))
+ });
+ compile_submatch(
+ bcx,
+ enter_rec_or_struct(bcx, dm, m, col, rec_fields, val),
+ vec::append(rec_vals, vals_left),
+ chk);
+ }
+ return;
+ }
+
+ if any_tup_pat(m, col) {
+ let tup_ty = node_id_type(bcx, pat_id);
+ let n_tup_elts = match /*bad*/copy ty::get(tup_ty).sty {
+ ty::ty_tup(elts) => elts.len(),
+ _ => ccx.sess.bug(~"non-tuple type in tuple pattern")
+ };
+ let tup_vals = vec::from_fn(n_tup_elts, |i| GEPi(bcx, val, [0u, i]));
+ compile_submatch(bcx, enter_tup(bcx, dm, m, col, val, n_tup_elts),
+ vec::append(tup_vals, vals_left), chk);
+ return;
+ }
+
+ if any_tuple_struct_pat(bcx, m, col) {
+ let struct_ty = node_id_type(bcx, pat_id);
+ let struct_element_count;
+ match ty::get(struct_ty).sty {
+ ty::ty_struct(struct_id, _) => {
+ struct_element_count =
+ ty::lookup_struct_fields(tcx, struct_id).len();
+ }
+ _ => {
+ ccx.sess.bug(~"non-struct type in tuple struct pattern");
+ }
+ }
+
+ let llstructvals = vec::from_fn(
+ struct_element_count, |i| GEPi(bcx, val, struct_field(i)));
+ compile_submatch(bcx,
+ enter_tuple_struct(bcx, dm, m, col, val,
+ struct_element_count),
+ vec::append(llstructvals, vals_left),
+ chk);
+ return;
+ }
+
+ // Unbox in case of a box field
+ if any_box_pat(m, col) {
+ let llbox = Load(bcx, val);
+ let box_no_addrspace = non_gc_box_cast(bcx, llbox);
+ let unboxed =
+ GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
+ compile_submatch(bcx, enter_box(bcx, dm, m, col, val),
+ vec::append(~[unboxed], vals_left), chk);
+ return;
+ }
+
+ if any_uniq_pat(m, col) {
+ let llbox = Load(bcx, val);
+ let box_no_addrspace = non_gc_box_cast(bcx, llbox);
+ let unboxed =
+ GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
+ compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
+ vec::append(~[unboxed], vals_left), chk);
+ return;
+ }
+
+ if any_region_pat(m, col) {
+ let loaded_val = Load(bcx, val);
+ compile_submatch(bcx, enter_region(bcx, dm, m, col, val),
+ vec::append(~[loaded_val], vals_left), chk);
+ return;
+ }
+
+ // Decide what kind of branch we need
+ let opts = get_options(ccx, m, col);
+ let mut kind = no_branch;
+ let mut test_val = val;
+ if opts.len() > 0u {
+ match opts[0] {
+ var(_, vdef) => {
+ if (*ty::enum_variants(tcx, vdef.enm)).len() == 1u {
+ kind = single;
+ } else {
+ let enumptr =
+ PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
+ let discrimptr = GEPi(bcx, enumptr, [0u, 0u]);
+ test_val = Load(bcx, discrimptr);
+ kind = switch;
+ }
+ }
+ lit(_) => {
+ let pty = node_id_type(bcx, pat_id);
+ test_val = load_if_immediate(bcx, val, pty);
+ kind = if ty::type_is_integral(pty) { switch }
+ else { compare };
+ }
+ range(_, _) => {
+ test_val = Load(bcx, val);
+ kind = compare;
+ },
+ vec_len_eq(_) | vec_len_ge(_) => {
+ let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
+ let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
+ let (_, len) = tvec::get_base_and_len(
+ bcx, unboxed, vt.vec_ty
+ );
+ test_val = SDiv(bcx, len, vt.llunit_size);
+ kind = compare_vec_len;
+ }
+ }
+ }
+ for vec::each(opts) |o| {
+ match *o {
+ range(_, _) => { kind = compare; break }
+ _ => ()
+ }
+ }
+ let else_cx = match kind {
+ no_branch | single => bcx,
+ _ => sub_block(bcx, ~"match_else")
+ };
+ let sw = if kind == switch {
+ Switch(bcx, test_val, else_cx.llbb, opts.len())
+ } else {
+ C_int(ccx, 0) // Placeholder for when not using a switch
+ };
+
+ let defaults = enter_default(else_cx, dm, m, col, val);
+ let exhaustive = chk.is_none() && defaults.len() == 0u;
+ let len = opts.len();
+ let mut i = 0u;
+
+ // Compile subtrees for each option
+ for vec::each(opts) |opt| {
+ i += 1u;
+ let mut opt_cx = else_cx;
+ if !exhaustive || i < len {
+ opt_cx = sub_block(bcx, ~"match_case");
+ match kind {
+ single => Br(bcx, opt_cx.llbb),
+ switch => {
+ match trans_opt(bcx, opt) {
+ single_result(r) => {
+ unsafe {
+ llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
+ bcx = r.bcx;
+ }
+ }
+ _ => {
+ bcx.sess().bug(
+ ~"in compile_submatch, expected \
+ trans_opt to return a single_result")
+ }
+ }
+ }
+ compare => {
+ let t = node_id_type(bcx, pat_id);
+ let Result {bcx: after_cx, val: matches} = {
+ do with_scope_result(bcx, None,
+ ~"compare_scope") |bcx| {
+ match trans_opt(bcx, opt) {
+ single_result(
+ Result {bcx, val}) => {
+ compare_values(bcx, test_val, val, t)
+ }
+ lower_bound(
+ Result {bcx, val}) => {
+ compare_scalar_types(
+ bcx, test_val, val,
+ t, ast::ge)
+ }
+ range_result(
+ Result {val: vbegin, _},
+ Result {bcx, val: vend}) => {
+ let Result {bcx, val: llge} =
+ compare_scalar_types(
+ bcx, test_val,
+ vbegin, t, ast::ge);
+ let Result {bcx, val: llle} =
+ compare_scalar_types(
+ bcx, test_val, vend,
+ t, ast::le);
+ rslt(bcx, And(bcx, llge, llle))
+ }
+ }
+ }
+ };
+ bcx = sub_block(after_cx, ~"compare_next");
+ CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
+ }
+ compare_vec_len => {
+ let Result {bcx: after_cx, val: matches} = {
+ do with_scope_result(bcx, None,
+ ~"compare_vec_len_scope") |bcx| {
+ match trans_opt(bcx, opt) {
+ single_result(
+ Result {bcx, val}) => {
+ let value = compare_scalar_values(
+ bcx, test_val, val,
+ signed_int, ast::eq);
+ rslt(bcx, value)
+ }
+ lower_bound(
+ Result {bcx, val: val}) => {
+ let value = compare_scalar_values(
+ bcx, test_val, val,
+ signed_int, ast::ge);
+ rslt(bcx, value)
+ }
+ range_result(
+ Result {val: vbegin, _},
+ Result {bcx, val: vend}) => {
+ let llge =
+ compare_scalar_values(
+ bcx, test_val,
+ vbegin, signed_int, ast::ge);
+ let llle =
+ compare_scalar_values(
+ bcx, test_val, vend,
+ signed_int, ast::le);
+ rslt(bcx, And(bcx, llge, llle))
+ }
+ }
+ }
+ };
+ bcx = sub_block(after_cx, ~"compare_vec_len_next");
+ CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
+ }
+ _ => ()
+ }
+ } else if kind == compare || kind == compare_vec_len {
+ Br(bcx, else_cx.llbb);
+ }
+
+ let mut size = 0u;
+ let mut unpacked = ~[];
+ match *opt {
+ var(_, vdef) => {
+ let args = extract_variant_args(opt_cx, pat_id, vdef, val);
+ size = args.vals.len();
+ unpacked = /*bad*/copy args.vals;
+ opt_cx = args.bcx;
+ }
+ vec_len_eq(n) | vec_len_ge(n) => {
+ let tail = match *opt {
+ vec_len_ge(_) => true,
+ _ => false
+ };
+ let args = extract_vec_elems(opt_cx, pat_id, n, tail, val);
+ size = args.vals.len();
+ unpacked = /*bad*/copy args.vals;
+ opt_cx = args.bcx;
+ }
+ lit(_) | range(_, _) => ()
+ }
+ let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
+ let opt_vals = vec::append(unpacked, vals_left);
+ compile_submatch(opt_cx, opt_ms, opt_vals, chk);
+ }
+
+ // Compile the fall-through case, if any
+ if !exhaustive {
+ if kind == compare || kind == compare_vec_len {
+ Br(bcx, else_cx.llbb);
+ }
+ if kind != single {
+ compile_submatch(else_cx, defaults, vals_left, chk);
+ }
+ }
+}
+
+fn trans_match(bcx: block,
+ match_expr: @ast::expr,
+ discr_expr: @ast::expr,
+ arms: ~[ast::arm],
+ dest: Dest) -> block {
+ let _icx = bcx.insn_ctxt("match::trans_match");
+ do with_scope(bcx, match_expr.info(), ~"match") |bcx| {
+ trans_match_inner(bcx, discr_expr, arms, dest)
+ }
+}
+
+fn trans_match_inner(scope_cx: block,
+ discr_expr: @ast::expr,
+ arms: &[ast::arm],
+ dest: Dest) -> block {
+ let _icx = scope_cx.insn_ctxt("match::trans_match_inner");
+ let mut bcx = scope_cx;
+ let tcx = bcx.tcx();
+
+ let discr_datum = unpack_datum!(bcx, {
+ expr::trans_to_datum(bcx, discr_expr)
+ });
+ if bcx.unreachable {
+ return bcx;
+ }
+
+ let mut arm_datas = ~[], matches = ~[];
+ for vec::each(arms) |arm| {
+ let body = scope_block(bcx, arm.body.info(), ~"case_body");
+
+ // Create the bindings map, which is a mapping from each binding name
+ // to an alloca() that will be the value for that local variable.
+ // Note that we use the names because each binding will have many ids
+ // from the various alternatives.
+ let bindings_map = HashMap();
+ do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, s, path| {
+ let ident = path_to_ident(path);
+ let variable_ty = node_id_type(bcx, p_id);
+ let llvariable_ty = type_of::type_of(bcx.ccx(), variable_ty);
+
+ let llmatch, trmode;
+ match bm {
+ ast::bind_by_value | ast::bind_by_move => {
+ // in this case, the type of the variable will be T,
+ // but we need to store a *T
+ let is_move = (bm == ast::bind_by_move);
+ llmatch = alloca(bcx, T_ptr(llvariable_ty));
+ trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
+ }
+ ast::bind_infer => {
+ // in this case also, the type of the variable will be T,
+ // but we need to store a *T
+ let is_move = match tcx.value_modes.find(p_id) {
+ None => {
+ tcx.sess.span_bug(s, ~"no value mode");
+ }
+ Some(MoveValue) => true,
+ Some(CopyValue) | Some(ReadValue) => false
+ };
+ llmatch = alloca(bcx, T_ptr(llvariable_ty));
+ trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
+ }
+ ast::bind_by_ref(_) => {
+ llmatch = alloca(bcx, llvariable_ty);
+ trmode = TrByRef;
+ }
+ };
+ bindings_map.insert(ident, BindingInfo {
+ llmatch: llmatch, trmode: trmode,
+ id: p_id, ty: variable_ty
+ });
+ }
+
+ let arm_data = @ArmData {bodycx: body,
+ arm: arm,
+ bindings_map: bindings_map};
+ arm_datas.push(arm_data);
+ for vec::each(arm.pats) |p| {
+ matches.push(@Match {pats: ~[*p], data: arm_data});
+ }
+ }
+
+ let t = node_id_type(bcx, discr_expr.id);
+ let chk = {
+ if ty::type_is_empty(tcx, t) {
+ // Special case for empty types
+ let fail_cx = @mut None;
+ Some(|| mk_fail(scope_cx, discr_expr.span,
+ ~"scrutinizing value that can't exist", fail_cx))
+ } else {
+ None
+ }
+ };
+ let lldiscr = discr_datum.to_ref_llval(bcx);
+ compile_submatch(bcx, matches, ~[lldiscr], chk);
+
+ let arm_cxs = DVec();
+ for arm_datas.each |arm_data| {
+ let mut bcx = arm_data.bodycx;
+
+ // If this arm has a guard, then the various by-value bindings have
+ // already been copied into their homes. If not, we do it here. This
+ // is just to reduce code space. See extensive comment at the start
+ // of the file for more details.
+ if arm_data.arm.guard.is_none() {
+ bcx = store_non_ref_bindings(bcx, *arm_data, None);
+ }
+
+ // insert bindings into the lllocals map and add cleanups
+ bcx = insert_lllocals(bcx, *arm_data, true);
+
+ bcx = controlflow::trans_block(bcx, arm_data.arm.body, dest);
+ bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
+ arm_cxs.push(bcx);
+ }
+
+ return controlflow::join_blocks(scope_cx, dvec::unwrap(move arm_cxs));
+
+ fn mk_fail(bcx: block, sp: span, +msg: ~str,
+ finished: @mut Option<BasicBlockRef>) -> BasicBlockRef {
+ match *finished { Some(bb) => return bb, _ => () }
+ let fail_cx = sub_block(bcx, ~"case_fallthrough");
+ controlflow::trans_fail(fail_cx, Some(sp), msg);
+ *finished = Some(fail_cx.llbb);
+ return fail_cx.llbb;
+ }
+}
+
+enum IrrefutablePatternBindingMode {
+ // Stores the association between node ID and LLVM value in `lllocals`.
+ BindLocal,
+ // Stores the association between node ID and LLVM value in `llargs`.
+ BindArgument
+}
+
+// Not match-related, but similar to the pattern-munging code above
+fn bind_irrefutable_pat(bcx: block,
+ pat: @ast::pat,
+ val: ValueRef,
+ make_copy: bool,
+ binding_mode: IrrefutablePatternBindingMode)
+ -> block {
+ let _icx = bcx.insn_ctxt("match::bind_irrefutable_pat");
+ let ccx = bcx.fcx.ccx;
+ let mut bcx = bcx;
+
+ // Necessary since bind_irrefutable_pat is called outside trans_match
+ match /*bad*/copy pat.node {
+ ast::pat_ident(_, _,inner) => {
+ if pat_is_variant_or_struct(bcx.tcx().def_map, pat) {
+ return bcx;
+ }
+
+ if make_copy {
+ let binding_ty = node_id_type(bcx, pat.id);
+ let datum = Datum {val: val, ty: binding_ty,
+ mode: ByRef, source: FromRvalue};
+ let scratch = scratch_datum(bcx, binding_ty, false);
+ datum.copy_to_datum(bcx, INIT, scratch);
+ match binding_mode {
+ BindLocal => {
+ bcx.fcx.lllocals.insert(pat.id,
+ local_mem(scratch.val));
+ }
+ BindArgument => {
+ bcx.fcx.llargs.insert(pat.id,
+ local_mem(scratch.val));
+ }
+ }
+ add_clean(bcx, scratch.val, binding_ty);
+ } else {
+ match binding_mode {
+ BindLocal => {
+ bcx.fcx.lllocals.insert(pat.id, local_mem(val));
+ }
+ BindArgument => {
+ bcx.fcx.llargs.insert(pat.id, local_mem(val));
+ }
+ }
+ }
+
+ for inner.each |inner_pat| {
+ bcx = bind_irrefutable_pat(
+ bcx, *inner_pat, val, true, binding_mode);
+ }
+ }
+ ast::pat_enum(_, sub_pats) => {
+ match bcx.tcx().def_map.find(pat.id) {
+ Some(ast::def_variant(*)) => {
+ let pat_def = ccx.tcx.def_map.get(pat.id);
+ let vdefs = ast_util::variant_def_ids(pat_def);
+ let args = extract_variant_args(bcx, pat.id, vdefs, val);
+ for sub_pats.each |sub_pat| {
+ for vec::eachi(args.vals) |i, argval| {
+ bcx = bind_irrefutable_pat(bcx,
+ sub_pat[i],
+ *argval,
+ make_copy,
+ binding_mode);
+ }
+ }
+ }
+ Some(ast::def_struct(*)) => {
+ match sub_pats {
+ None => {
+ // This is a unit-like struct. Nothing to do here.
+ }
+ Some(elems) => {
+ // This is the tuple variant case.
+ for vec::eachi(elems) |i, elem| {
+ let fldptr = GEPi(bcx, val, struct_field(i));
+ bcx = bind_irrefutable_pat(bcx,
+ *elem,
+ fldptr,
+ make_copy,
+ binding_mode);
+ }
+ }
+ }
+ }
+ _ => {
+ // Nothing to do here.
+ }
+ }
+ }
+ ast::pat_rec(fields, _) | ast::pat_struct(_, fields, _) => {
+ let tcx = bcx.tcx();
+ let pat_ty = node_id_type(bcx, pat.id);
+ do expr::with_field_tys(tcx, pat_ty, None) |_hd, field_tys| {
+ for vec::each(fields) |f| {
+ let ix = ty::field_idx_strict(tcx, f.ident, field_tys);
+ let fldptr = GEPi(bcx, val, struct_field(ix));
+ bcx = bind_irrefutable_pat(bcx,
+ f.pat,
+ fldptr,
+ make_copy,
+ binding_mode);
+ }
+ }
+ }
+ ast::pat_tup(elems) => {
+ for vec::eachi(elems) |i, elem| {
+ let fldptr = GEPi(bcx, val, [0u, i]);
+ bcx = bind_irrefutable_pat(bcx,
+ *elem,
+ fldptr,
+ make_copy,
+ binding_mode);
+ }
+ }
+ ast::pat_box(inner) | ast::pat_uniq(inner) => {
+ let llbox = Load(bcx, val);
+ let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
+ bcx = bind_irrefutable_pat(bcx,
+ inner,
+ unboxed,
+ true,
+ binding_mode);
+ }
+ ast::pat_region(inner) => {
+ let loaded_val = Load(bcx, val);
+ bcx = bind_irrefutable_pat(bcx,
+ inner,
+ loaded_val,
+ true,
+ binding_mode);
+ }
+ ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) |
+ ast::pat_vec(*) => ()
+ }
+ return bcx;
+}
+
+// Local Variables:
+// mode: rust
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// End:
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- *
- * # Compilation of match statements
- *
- * I will endeavor to explain the code as best I can. I have only a loose
- * understanding of some parts of it.
- *
- * ## Matching
- *
- * The basic state of the code is maintained in an array `m` of `@Match`
- * objects. Each `@Match` describes some list of patterns, all of which must
- * match against the current list of values. If those patterns match, then
- * the arm listed in the match is the correct arm. A given arm may have
- * multiple corresponding match entries, one for each alternative that
- * remains. As we proceed these sets of matches are adjusted by the various
- * `enter_XXX()` functions, each of which adjusts the set of options given
- * some information about the value which has been matched.
- *
- * So, initially, there is one value and N matches, each of which have one
- * constituent pattern. N here is usually the number of arms but may be
- * greater, if some arms have multiple alternatives. For example, here:
- *
- * enum Foo { A, B(int), C(uint, uint) }
- * match foo {
- * A => ...,
- * B(x) => ...,
- * C(1u, 2) => ...,
- * C(_) => ...
- * }
- *
- * The value would be `foo`. There would be four matches, each of which
- * contains one pattern (and, in one case, a guard). We could collect the
- * various options and then compile the code for the case where `foo` is an
- * `A`, a `B`, and a `C`. When we generate the code for `C`, we would (1)
- * drop the two matches that do not match a `C` and (2) expand the other two
- * into two patterns each. In the first case, the two patterns would be `1u`
- * and `2`, and the in the second case the _ pattern would be expanded into
- * `_` and `_`. The two values are of course the arguments to `C`.
- *
- * Here is a quick guide to the various functions:
- *
- * - `compile_submatch()`: The main workhouse. It takes a list of values and
- * a list of matches and finds the various possibilities that could occur.
- *
- * - `enter_XXX()`: modifies the list of matches based on some information
- * about the value that has been matched. For example,
- * `enter_rec_or_struct()` adjusts the values given that a record or struct
- * has been matched. This is an infallible pattern, so *all* of the matches
- * must be either wildcards or record/struct patterns. `enter_opt()`
- * handles the fallible cases, and it is correspondingly more complex.
- *
- * ## Bindings
- *
- * We store information about the bound variables for each arm as part of the
- * per-arm `ArmData` struct. There is a mapping from identifiers to
- * `BindingInfo` structs. These structs contain the mode/id/type of the
- * binding, but they also contain up to two LLVM values, called `llmatch` and
- * `llbinding` respectively (the `llbinding`, as will be described shortly, is
- * optional and only present for by-value bindings---therefore it is bundled
- * up as part of the `TransBindingMode` type). Both point at allocas.
- *
- * The `llmatch` binding always stores a pointer into the value being matched
- * which points at the data for the binding. If the value being matched has
- * type `T`, then, `llmatch` will point at an alloca of type `T*` (and hence
- * `llmatch` has type `T**`). So, if you have a pattern like:
- *
- * let a: A = ...;
- * let b: B = ...;
- * match (a, b) { (ref c, copy d) => { ... } }
- *
- * For `c` and `d`, we would generate allocas of type `C*` and `D*`
- * respectively. These are called the `llmatch`. As we match, when we come
- * up against an identifier, we store the current pointer into the
- * corresponding alloca.
- *
- * In addition, for each by-value binding (copy or move), we will create a
- * second alloca (`llbinding`) that will hold the final value. In this
- * example, that means that `d` would have this second alloca of type `D` (and
- * hence `llbinding` has type `D*`).
- *
- * Once a pattern is completely matched, and assuming that there is no guard
- * pattern, we will branch to a block that leads to the body itself. For any
- * by-value bindings, this block will first load the ptr from `llmatch` (the
- * one of type `D*`) and copy/move the value into `llbinding` (the one of type
- * `D`). The second alloca then becomes the value of the local variable. For
- * by ref bindings, the value of the local variable is simply the first
- * alloca.
- *
- * So, for the example above, we would generate a setup kind of like this:
- *
- * +-------+
- * | Entry |
- * +-------+
- * |
- * +-------------------------------------------+
- * | llmatch_c = (addr of first half of tuple) |
- * | llmatch_d = (addr of first half of tuple) |
- * +-------------------------------------------+
- * |
- * +--------------------------------------+
- * | *llbinding_d = **llmatch_dlbinding_d |
- * +--------------------------------------+
- *
- * If there is a guard, the situation is slightly different, because we must
- * execute the guard code. Moreover, we need to do so once for each of the
- * alternatives that lead to the arm, because if the guard fails, they may
- * have different points from which to continue the search. Therefore, in that
- * case, we generate code that looks more like:
- *
- * +-------+
- * | Entry |
- * +-------+
- * |
- * +-------------------------------------------+
- * | llmatch_c = (addr of first half of tuple) |
- * | llmatch_d = (addr of first half of tuple) |
- * +-------------------------------------------+
- * |
- * +-------------------------------------------------+
- * | *llbinding_d = **llmatch_dlbinding_d |
- * | check condition |
- * | if false { free *llbinding_d, goto next case } |
- * | if true { goto body } |
- * +-------------------------------------------------+
- *
- * The handling for the cleanups is a bit... sensitive. Basically, the body
- * is the one that invokes `add_clean()` for each binding. During the guard
- * evaluation, we add temporary cleanups and revoke them after the guard is
- * evaluated (it could fail, after all). Presuming the guard fails, we drop
- * the various values we copied explicitly. Note that guards and moves are
- * just plain incompatible.
- *
- */
-
-use back::abi;
-use lib::llvm::llvm;
-use lib::llvm::{ValueRef, BasicBlockRef};
-use middle::pat_util::*;
-use middle::resolve::DefMap;
-use middle::trans::base::*;
-use middle::trans::build::*;
-use middle::trans::common::*;
-use middle::trans::datum::*;
-use middle::trans::expr::Dest;
-use middle::ty::{CopyValue, MoveValue, ReadValue};
-use util::common::indenter;
-
-use core::dvec::DVec;
-use std::map::HashMap;
-use syntax::ast::def_id;
-use syntax::ast;
-use syntax::ast_util::{dummy_sp, path_to_ident};
-use syntax::ast_util;
-use syntax::codemap::span;
-use syntax::print::pprust::pat_to_str;
-
-fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export.
-
-// An option identifying a literal: either a unit-like struct or an
-// expression.
-enum Lit {
- UnitLikeStructLit(ast::node_id), // the node ID of the pattern
- ExprLit(@ast::expr),
- ConstLit(ast::def_id), // the def ID of the constant
-}
-
-// An option identifying a branch (either a literal, a enum variant or a
-// range)
-enum Opt {
- lit(Lit),
- var(/* disr val */int, /* variant dids */{enm: def_id, var: def_id}),
- range(@ast::expr, @ast::expr),
- vec_len_eq(uint),
- vec_len_ge(uint)
-}
-
-fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
- match (*a, *b) {
- (lit(a), lit(b)) => {
- match (a, b) {
- (UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
- _ => {
- let a_expr;
- match a {
- ExprLit(existing_a_expr) => a_expr = existing_a_expr,
- ConstLit(a_const) => {
- let e = const_eval::lookup_const_by_id(tcx, a_const);
- a_expr = e.get();
- }
- UnitLikeStructLit(_) => {
- fail ~"UnitLikeStructLit should have been handled \
- above"
- }
- }
-
- let b_expr;
- match b {
- ExprLit(existing_b_expr) => b_expr = existing_b_expr,
- ConstLit(b_const) => {
- let e = const_eval::lookup_const_by_id(tcx, b_const);
- b_expr = e.get();
- }
- UnitLikeStructLit(_) => {
- fail ~"UnitLikeStructLit should have been handled \
- above"
- }
- }
-
- const_eval::compare_lit_exprs(tcx, a_expr, b_expr) == 0
- }
- }
- }
- (range(a1, a2), range(b1, b2)) => {
- const_eval::compare_lit_exprs(tcx, a1, b1) == 0 &&
- const_eval::compare_lit_exprs(tcx, a2, b2) == 0
- }
- (var(a, _), var(b, _)) => a == b,
- (vec_len_eq(a), vec_len_eq(b)) => a == b,
- (vec_len_ge(a), vec_len_ge(b)) => a == b,
- _ => false
- }
-}
-
-enum opt_result {
- single_result(Result),
- lower_bound(Result),
- range_result(Result, Result),
-}
-fn trans_opt(bcx: block, o: &Opt) -> opt_result {
- let _icx = bcx.insn_ctxt("alt::trans_opt");
- let ccx = bcx.ccx();
- let mut bcx = bcx;
- match *o {
- lit(ExprLit(lit_expr)) => {
- let datumblock = expr::trans_to_datum(bcx, lit_expr);
- return single_result(datumblock.to_result());
- }
- lit(UnitLikeStructLit(pat_id)) => {
- let struct_ty = ty::node_id_to_type(bcx.tcx(), pat_id);
- let datumblock = datum::scratch_datum(bcx, struct_ty, true);
- return single_result(datumblock.to_result(bcx));
- }
- lit(ConstLit(lit_id)) => {
- let llval = consts::get_const_val(bcx.ccx(), lit_id);
- return single_result(rslt(bcx, llval));
- }
- var(disr_val, _) => {
- return single_result(rslt(bcx, C_int(ccx, disr_val)));
- }
- range(l1, l2) => {
- return range_result(rslt(bcx, consts::const_expr(ccx, l1)),
- rslt(bcx, consts::const_expr(ccx, l2)));
- }
- vec_len_eq(n) => {
- return single_result(rslt(bcx, C_int(ccx, n as int)));
- }
- vec_len_ge(n) => {
- return lower_bound(rslt(bcx, C_int(ccx, n as int)));
- }
- }
-}
-
-fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> Opt {
- match tcx.def_map.get(pat_id) {
- ast::def_variant(enum_id, var_id) => {
- let variants = ty::enum_variants(tcx, enum_id);
- for vec::each(*variants) |v| {
- if var_id == v.id {
- return var(v.disr_val, {enm: enum_id, var: var_id});
- }
- }
- core::util::unreachable();
- }
- ast::def_struct(_) => {
- return lit(UnitLikeStructLit(pat_id));
- }
- _ => {
- tcx.sess.bug(~"non-variant or struct in variant_opt()");
- }
- }
-}
-
-enum TransBindingMode {
- TrByValue(/*ismove:*/ bool, /*llbinding:*/ ValueRef),
- TrByRef,
- TrByImplicitRef
-}
-
-/**
- * Information about a pattern binding:
- * - `llmatch` is a pointer to a stack slot. The stack slot contains a
- * pointer into the value being matched. Hence, llmatch has type `T**`
- * where `T` is the value being matched.
- * - `trmode` is the trans binding mode
- * - `id` is the node id of the binding
- * - `ty` is the Rust type of the binding */
-struct BindingInfo {
- llmatch: ValueRef,
- trmode: TransBindingMode,
- id: ast::node_id,
- ty: ty::t,
-}
-
-type BindingsMap = HashMap<ident, BindingInfo>;
-
-struct ArmData {
- bodycx: block,
- arm: &ast::arm,
- bindings_map: BindingsMap
-}
-
-struct Match {
- pats: ~[@ast::pat],
- data: @ArmData
-}
-
-fn match_to_str(bcx: block, m: &Match) -> ~str {
- if bcx.sess().verbose() {
- // for many programs, this just take too long to serialize
- fmt!("%?", m.pats.map(|p| pat_to_str(*p, bcx.sess().intr())))
- } else {
- fmt!("%u pats", m.pats.len())
- }
-}
-
-fn matches_to_str(bcx: block, m: &[@Match]) -> ~str {
- fmt!("%?", m.map(|n| match_to_str(bcx, *n)))
-}
-
-fn has_nested_bindings(m: &[@Match], col: uint) -> bool {
- for vec::each(m) |br| {
- match br.pats[col].node {
- ast::pat_ident(_, _, Some(_)) => return true,
- _ => ()
- }
- }
- return false;
-}
-
-fn expand_nested_bindings(bcx: block, m: &[@Match/&r],
- col: uint, val: ValueRef)
- -> ~[@Match/&r]
-{
- debug!("expand_nested_bindings(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- do m.map |br| {
- match br.pats[col].node {
- ast::pat_ident(_, path, Some(inner)) => {
- let pats = vec::append(
- vec::slice(br.pats, 0u, col),
- vec::append(~[inner],
- vec::view(br.pats, col + 1u, br.pats.len())));
-
- let binding_info =
- br.data.bindings_map.get(path_to_ident(path));
-
- Store(bcx, val, binding_info.llmatch);
- @Match {pats: pats, data: br.data}
- }
- _ => {
- *br
- }
- }
- }
-}
-
-type enter_pat = fn(@ast::pat) -> Option<~[@ast::pat]>;
-
-fn assert_is_binding_or_wild(bcx: block, p: @ast::pat) {
- if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
- bcx.sess().span_bug(
- p.span,
- fmt!("Expected an identifier pattern but found p: %s",
- pat_to_str(p, bcx.sess().intr())));
- }
-}
-
-fn enter_match(bcx: block, dm: DefMap, m: &[@Match/&r],
- col: uint, val: ValueRef, e: enter_pat)
- -> ~[@Match/&r]
-{
- debug!("enter_match(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let mut result = ~[];
- for vec::each(m) |br| {
- match e(br.pats[col]) {
- Some(sub) => {
- let pats =
- vec::append(
- vec::append(sub, vec::view(br.pats, 0u, col)),
- vec::view(br.pats, col + 1u, br.pats.len()));
-
- let self = br.pats[col];
- match self.node {
- ast::pat_ident(_, path, None) => {
- if pat_is_binding(dm, self) {
- let binding_info =
- br.data.bindings_map.get(path_to_ident(path));
- Store(bcx, val, binding_info.llmatch);
- }
- }
- _ => {}
- }
-
- result.push(@Match {pats: pats, data: br.data});
- }
- None => ()
- }
- }
-
- debug!("result=%s", matches_to_str(bcx, result));
-
- return result;
-}
-
-fn enter_default(bcx: block, dm: DefMap, m: &[@Match/&r],
- col: uint, val: ValueRef)
- -> ~[@Match/&r]
-{
- debug!("enter_default(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_wild | ast::pat_rec(_, _) | ast::pat_tup(_) |
- ast::pat_struct(*) => Some(~[]),
- ast::pat_ident(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
- _ => None
- }
- }
-}
-
-// <pcwalton> nmatsakis: what does enter_opt do?
-// <pcwalton> in trans/alt
-// <pcwalton> trans/alt.rs is like stumbling around in a dark cave
-// <nmatsakis> pcwalton: the enter family of functions adjust the set of
-// patterns as needed
-// <nmatsakis> yeah, at some point I kind of achieved some level of
-// understanding
-// <nmatsakis> anyhow, they adjust the patterns given that something of that
-// kind has been found
-// <nmatsakis> pcwalton: ok, right, so enter_XXX() adjusts the patterns, as I
-// said
-// <nmatsakis> enter_match() kind of embodies the generic code
-// <nmatsakis> it is provided with a function that tests each pattern to see
-// if it might possibly apply and so forth
-// <nmatsakis> so, if you have a pattern like {a: _, b: _, _} and one like _
-// <nmatsakis> then _ would be expanded to (_, _)
-// <nmatsakis> one spot for each of the sub-patterns
-// <nmatsakis> enter_opt() is one of the more complex; it covers the fallible
-// cases
-// <nmatsakis> enter_rec_or_struct() or enter_tuple() are simpler, since they
-// are infallible patterns
-// <nmatsakis> so all patterns must either be records (resp. tuples) or
-// wildcards
-
-fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint,
- variant_size: uint, val: ValueRef)
- -> ~[@Match/&r]
-{
- debug!("enter_opt(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let tcx = bcx.tcx();
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, tcx.def_map, m, col, val) |p| {
- match p.node {
- ast::pat_enum(_, subpats) => {
- if opt_eq(tcx, &variant_opt(tcx, p.id), opt) {
- Some(option::get_default(subpats,
- vec::from_elem(variant_size,
- dummy)))
- } else {
- None
- }
- }
- ast::pat_ident(_, _, None)
- if pat_is_variant_or_struct(tcx.def_map, p) => {
- if opt_eq(tcx, &variant_opt(tcx, p.id), opt) {
- Some(~[])
- } else {
- None
- }
- }
- ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
- let const_def = tcx.def_map.get(p.id);
- let const_def_id = ast_util::def_id_of_def(const_def);
- if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
- Some(~[])
- } else {
- None
- }
- }
- ast::pat_lit(l) => {
- if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(~[])} else {None}
- }
- ast::pat_range(l1, l2) => {
- if opt_eq(tcx, &range(l1, l2), opt) {Some(~[])} else {None}
- }
- ast::pat_struct(_, field_pats, _) => {
- if opt_eq(tcx, &variant_opt(tcx, p.id), opt) {
- // Look up the struct variant ID.
- let struct_id;
- match tcx.def_map.get(p.id) {
- ast::def_variant(_, found_struct_id) => {
- struct_id = found_struct_id;
- }
- _ => {
- tcx.sess.span_bug(p.span, ~"expected enum \
- variant def");
- }
- }
-
- // Reorder the patterns into the same order they were
- // specified in the struct definition. Also fill in
- // unspecified fields with dummy.
- let reordered_patterns = dvec::DVec();
- for ty::lookup_struct_fields(tcx, struct_id).each
- |field| {
- match field_pats.find(|p|
- p.ident == field.ident) {
- None => reordered_patterns.push(dummy),
- Some(fp) => reordered_patterns.push(fp.pat)
- }
- }
- Some(dvec::unwrap(move reordered_patterns))
- } else {
- None
- }
- }
- ast::pat_vec(elems, tail) => {
- match tail {
- Some(_) => {
- if opt_eq(tcx, &vec_len_ge(elems.len()), opt) {
- Some(vec::append_one(elems, tail.get()))
- } else {
- None
- }
- }
- None => {
- if opt_eq(tcx, &vec_len_eq(elems.len()), opt) {
- Some(copy elems)
- } else {
- None
- }
- }
- }
- }
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(vec::from_elem(variant_size, dummy))
- }
- }
- }
-}
-
-fn enter_rec_or_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint,
- fields: ~[ast::ident], val: ValueRef) -> ~[@Match/&r] {
- debug!("enter_rec_or_struct(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_rec(fpats, _) | ast::pat_struct(_, fpats, _) => {
- let mut pats = ~[];
- for vec::each(fields) |fname| {
- match fpats.find(|p| p.ident == *fname) {
- None => pats.push(dummy),
- Some(pat) => pats.push(pat.pat)
- }
- }
- Some(pats)
- }
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(vec::from_elem(fields.len(), dummy))
- }
- }
- }
-}
-
-fn enter_tup(bcx: block, dm: DefMap, m: &[@Match/&r],
- col: uint, val: ValueRef, n_elts: uint)
- -> ~[@Match/&r]
-{
- debug!("enter_tup(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_tup(elts) => {
- Some(elts)
- }
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(vec::from_elem(n_elts, dummy))
- }
- }
- }
-}
-
-fn enter_tuple_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint,
- val: ValueRef, n_elts: uint)
- -> ~[@Match/&r]
-{
- debug!("enter_tuple_struct(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_enum(_, Some(elts)) => Some(elts),
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(vec::from_elem(n_elts, dummy))
- }
- }
- }
-}
-
-fn enter_box(bcx: block, dm: DefMap, m: &[@Match/&r],
- col: uint, val: ValueRef)
- -> ~[@Match/&r]
-{
- debug!("enter_box(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_box(sub) => {
- Some(~[sub])
- }
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(~[dummy])
- }
- }
- }
-}
-
-fn enter_uniq(bcx: block, dm: DefMap, m: &[@Match/&r],
- col: uint, val: ValueRef)
- -> ~[@Match/&r]
-{
- debug!("enter_uniq(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_uniq(sub) => {
- Some(~[sub])
- }
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(~[dummy])
- }
- }
- }
-}
-
-fn enter_region(bcx: block, dm: DefMap, m: &[@Match/&r],
- col: uint, val: ValueRef)
- -> ~[@Match/&r]
-{
- debug!("enter_region(bcx=%s, m=%s, col=%u, val=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- col,
- bcx.val_str(val));
- let _indenter = indenter();
-
- let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()};
- do enter_match(bcx, dm, m, col, val) |p| {
- match p.node {
- ast::pat_region(sub) => {
- Some(~[sub])
- }
- _ => {
- assert_is_binding_or_wild(bcx, p);
- Some(~[dummy])
- }
- }
- }
-}
-
-// Returns the options in one column of matches. An option is something that
-// needs to be conditionally matched at runtime; for example, the discriminant
-// on a set of enum variants or a literal.
-fn get_options(ccx: @crate_ctxt, m: &[@Match], col: uint) -> ~[Opt] {
- fn add_to_set(tcx: ty::ctxt, set: &DVec<Opt>, val: Opt) {
- if set.any(|l| opt_eq(tcx, l, &val)) {return;}
- set.push(val);
- }
-
- let found = DVec();
- for vec::each(m) |br| {
- let cur = br.pats[col];
- match cur.node {
- ast::pat_lit(l) => {
- add_to_set(ccx.tcx, &found, lit(ExprLit(l)));
- }
- ast::pat_ident(*) => {
- // This is one of: an enum variant, a unit-like struct, or a
- // variable binding.
- match ccx.tcx.def_map.find(cur.id) {
- Some(ast::def_variant(*)) => {
- add_to_set(ccx.tcx, &found,
- variant_opt(ccx.tcx, cur.id));
- }
- Some(ast::def_struct(*)) => {
- add_to_set(ccx.tcx, &found,
- lit(UnitLikeStructLit(cur.id)));
- }
- Some(ast::def_const(const_did)) => {
- add_to_set(ccx.tcx, &found,
- lit(ConstLit(const_did)));
- }
- _ => {}
- }
- }
- ast::pat_enum(*) | ast::pat_struct(*) => {
- // This could be one of: a tuple-like enum variant, a
- // struct-like enum variant, or a struct.
- match ccx.tcx.def_map.find(cur.id) {
- Some(ast::def_variant(*)) => {
- add_to_set(ccx.tcx, &found,
- variant_opt(ccx.tcx, cur.id));
- }
- _ => {}
- }
- }
- ast::pat_range(l1, l2) => {
- add_to_set(ccx.tcx, &found, range(l1, l2));
- }
- ast::pat_vec(elems, tail) => {
- let opt = match tail {
- None => vec_len_eq(elems.len()),
- Some(_) => vec_len_ge(elems.len())
- };
- add_to_set(ccx.tcx, &found, opt);
- }
- _ => {}
- }
- }
- return dvec::unwrap(move found);
-}
-
-fn extract_variant_args(bcx: block, pat_id: ast::node_id,
- vdefs: {enm: def_id, var: def_id},
- val: ValueRef)
- -> {vals: ~[ValueRef], bcx: block}
-{
- let _icx = bcx.insn_ctxt("alt::extract_variant_args");
- let ccx = bcx.fcx.ccx;
- let enum_ty_substs = match ty::get(node_id_type(bcx, pat_id)).sty {
- ty::ty_enum(id, ref substs) => { assert id == vdefs.enm; (*substs).tps }
- _ => bcx.sess().bug(~"extract_variant_args: pattern has non-enum type")
- };
- let mut blobptr = val;
- let variants = ty::enum_variants(ccx.tcx, vdefs.enm);
- let size = ty::enum_variant_with_id(ccx.tcx, vdefs.enm,
- vdefs.var).args.len();
- if size > 0u && (*variants).len() != 1u {
- let enumptr =
- PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
- blobptr = GEPi(bcx, enumptr, [0u, 1u]);
- }
- let vdefs_tg = vdefs.enm;
- let vdefs_var = vdefs.var;
- let args = do vec::from_fn(size) |i| {
- GEP_enum(bcx, blobptr, vdefs_tg, vdefs_var,
- enum_ty_substs, i)
- };
- return {vals: args, bcx: bcx};
-}
-
-fn extract_vec_elems(bcx: block, pat_id: ast::node_id,
- elem_count: uint, tail: bool, val: ValueRef)
- -> {vals: ~[ValueRef], bcx: block}
-{
- let _icx = bcx.insn_ctxt("alt::extract_vec_elems");
- let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
- let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
- let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty);
-
- let mut elems = do vec::from_fn(elem_count) |i| {
- GEPi(bcx, base, ~[i])
- };
- if tail {
- let tail_offset = Mul(bcx, vt.llunit_size,
- C_int(bcx.ccx(), elem_count as int)
- );
- let tail_begin = tvec::pointer_add(bcx, base, tail_offset);
- let tail_len = Sub(bcx, len, tail_offset);
- let tail_ty = ty::mk_evec(bcx.tcx(),
- {ty: vt.unit_ty, mutbl: ast::m_imm},
- ty::vstore_slice(ty::re_static)
- );
- let scratch = scratch_datum(bcx, tail_ty, false);
- Store(bcx, tail_begin,
- GEPi(bcx, scratch.val, [0u, abi::slice_elt_base])
- );
- Store(bcx, tail_len,
- GEPi(bcx, scratch.val, [0u, abi::slice_elt_len])
- );
- elems.push(scratch.val);
- scratch.add_clean(bcx);
- }
- return {vals: elems, bcx: bcx};
-}
-
-// NB: This function does not collect fields from struct-like enum variants.
-fn collect_record_or_struct_fields(bcx: block, m: &[@Match], col: uint) ->
- ~[ast::ident] {
- let mut fields: ~[ast::ident] = ~[];
- for vec::each(m) |br| {
- match br.pats[col].node {
- ast::pat_rec(fs, _) => extend(&mut fields, fs),
- ast::pat_struct(_, fs, _) => {
- match ty::get(node_id_type(bcx, br.pats[col].id)).sty {
- ty::ty_struct(*) => extend(&mut fields, fs),
- _ => ()
- }
- }
- _ => ()
- }
- }
- return fields;
-
- fn extend(idents: &mut ~[ast::ident], field_pats: &[ast::field_pat]) {
- for field_pats.each |field_pat| {
- let field_ident = field_pat.ident;
- if !vec::any(*idents, |x| *x == field_ident) {
- idents.push(field_ident);
- }
- }
- }
-}
-
-fn root_pats_as_necessary(bcx: block, m: &[@Match],
- col: uint, val: ValueRef)
-{
- for vec::each(m) |br| {
- let pat_id = br.pats[col].id;
-
- match bcx.ccx().maps.root_map.find({id:pat_id, derefs:0u}) {
- None => (),
- Some(scope_id) => {
- // Note: the scope_id will always be the id of the alt. See
- // the extended comment in rustc::middle::borrowck::preserve()
- // for details (look for the case covering cat_discr).
-
- let datum = Datum {val: val, ty: node_id_type(bcx, pat_id),
- mode: ByRef, source: FromLvalue};
- datum.root(bcx, scope_id);
- return; // if we kept going, we'd only re-root the same value
- }
- }
- }
-}
-
-// Macro for deciding whether any of the remaining matches fit a given kind of
-// pattern. Note that, because the macro is well-typed, either ALL of the
-// matches should fit that sort of pattern or NONE (however, some of the
-// matches may be wildcards like _ or identifiers).
-macro_rules! any_pat (
- ($m:expr, $pattern:pat) => (
- vec::any($m, |br| {
- match br.pats[col].node {
- $pattern => true,
- _ => false
- }
- })
- )
-)
-
-fn any_box_pat(m: &[@Match], col: uint) -> bool {
- any_pat!(m, ast::pat_box(_))
-}
-
-fn any_uniq_pat(m: &[@Match], col: uint) -> bool {
- any_pat!(m, ast::pat_uniq(_))
-}
-
-fn any_region_pat(m: &[@Match], col: uint) -> bool {
- any_pat!(m, ast::pat_region(_))
-}
-
-fn any_tup_pat(m: &[@Match], col: uint) -> bool {
- any_pat!(m, ast::pat_tup(_))
-}
-
-fn any_tuple_struct_pat(bcx: block, m: &[@Match], col: uint) -> bool {
- vec::any(m, |br| {
- let pat = br.pats[col];
- match pat.node {
- ast::pat_enum(_, Some(_)) => {
- match bcx.tcx().def_map.find(pat.id) {
- Some(ast::def_struct(*)) => true,
- _ => false
- }
- }
- _ => false
- }
- })
-}
-
-type mk_fail = fn@() -> BasicBlockRef;
-
-fn pick_col(m: &[@Match]) -> uint {
- fn score(p: @ast::pat) -> uint {
- match p.node {
- ast::pat_lit(_) | ast::pat_enum(_, _) | ast::pat_range(_, _) => 1u,
- ast::pat_ident(_, _, Some(p)) => score(p),
- _ => 0u
- }
- }
- let scores = vec::to_mut(vec::from_elem(m[0].pats.len(), 0u));
- for vec::each(m) |br| {
- let mut i = 0u;
- for vec::each(br.pats) |p| { scores[i] += score(*p); i += 1u; }
- }
- let mut max_score = 0u;
- let mut best_col = 0u;
- let mut i = 0u;
- for vec::each(scores) |score| {
- let score = *score;
-
- // Irrefutable columns always go first, they'd only be duplicated in
- // the branches.
- if score == 0u { return i; }
- // If no irrefutable ones are found, we pick the one with the biggest
- // branching factor.
- if score > max_score { max_score = score; best_col = i; }
- i += 1u;
- }
- return best_col;
-}
-
-enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
-
-impl branch_kind : cmp::Eq {
- pure fn eq(&self, other: &branch_kind) -> bool {
- ((*self) as uint) == ((*other) as uint)
- }
- pure fn ne(&self, other: &branch_kind) -> bool { !(*self).eq(other) }
-}
-
-// Compiles a comparison between two things.
-fn compare_values(cx: block, lhs: ValueRef, rhs: ValueRef, rhs_t: ty::t) ->
- Result {
- let _icx = cx.insn_ctxt("compare_values");
- if ty::type_is_scalar(rhs_t) {
- let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::eq);
- return rslt(rs.bcx, rs.val);
- }
-
- match ty::get(rhs_t).sty {
- ty::ty_estr(ty::vstore_uniq) => {
- let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()),
- false);
- let scratch_lhs = alloca(cx, val_ty(lhs));
- Store(cx, lhs, scratch_lhs);
- let scratch_rhs = alloca(cx, val_ty(rhs));
- Store(cx, rhs, scratch_rhs);
- let did = cx.tcx().lang_items.uniq_str_eq_fn.get();
- let bcx = callee::trans_rtcall_or_lang_call(cx, did,
- ~[scratch_lhs,
- scratch_rhs],
- expr::SaveIn(
- scratch_result.val));
- return scratch_result.to_result(bcx);
- }
- ty::ty_estr(_) => {
- let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()),
- false);
- let did = cx.tcx().lang_items.str_eq_fn.get();
- let bcx = callee::trans_rtcall_or_lang_call(cx, did,
- ~[lhs, rhs],
- expr::SaveIn(
- scratch_result.val));
- return scratch_result.to_result(bcx);
- }
- _ => {
- cx.tcx().sess.bug(~"only scalars and strings supported in \
- compare_values");
- }
- }
-}
-
-fn store_non_ref_bindings(bcx: block,
- data: &ArmData,
- opt_temp_cleanups: Option<&DVec<ValueRef>>)
- -> block
-{
- /*!
- *
- * For each copy/move binding, copy the value from the value
- * being matched into its final home. This code executes once
- * one of the patterns for a given arm has completely matched.
- * It adds temporary cleanups to the `temp_cleanups` array,
- * if one is provided.
- */
-
- let mut bcx = bcx;
- for data.bindings_map.each_value |binding_info| {
- match binding_info.trmode {
- TrByValue(is_move, lldest) => {
- let llval = Load(bcx, binding_info.llmatch); // get a T*
- let datum = Datum {val: llval, ty: binding_info.ty,
- mode: ByRef, source: FromLvalue};
- bcx = {
- if is_move {
- datum.move_to(bcx, INIT, lldest)
- } else {
- datum.copy_to(bcx, INIT, lldest)
- }
- };
-
- for opt_temp_cleanups.each |temp_cleanups| {
- add_clean_temp_mem(bcx, lldest, binding_info.ty);
- temp_cleanups.push(lldest);
- }
- }
- TrByRef | TrByImplicitRef => {}
- }
- }
- return bcx;
-}
-
-fn insert_lllocals(bcx: block,
- data: &ArmData,
- add_cleans: bool) -> block {
- /*!
- *
- * For each binding in `data.bindings_map`, adds an appropriate entry into
- * the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for
- * the bindings. */
-
- for data.bindings_map.each_value |binding_info| {
- let llval = match binding_info.trmode {
- // By value bindings: use the stack slot that we
- // copied/moved the value into
- TrByValue(_, lldest) => {
- if add_cleans {
- add_clean(bcx, lldest, binding_info.ty);
- }
-
- lldest
- }
-
- // By ref binding: use the ptr into the matched value
- TrByRef => {
- binding_info.llmatch
- }
-
- // Ugly: for implicit ref, we actually want a T*, but
- // we have a T**, so we had to load. This will go away
- // once implicit refs go away.
- TrByImplicitRef => {
- Load(bcx, binding_info.llmatch)
- }
- };
-
- bcx.fcx.lllocals.insert(binding_info.id,
- local_mem(llval));
- }
- return bcx;
-}
-
-fn compile_guard(bcx: block,
- guard_expr: @ast::expr,
- data: &ArmData,
- m: &[@Match],
- vals: &[ValueRef],
- chk: Option<mk_fail>)
- -> block
-{
- debug!("compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%?)",
- bcx.to_str(),
- bcx.expr_to_str(guard_expr),
- matches_to_str(bcx, m),
- vals.map(|v| bcx.val_str(*v)));
- let _indenter = indenter();
-
- let mut bcx = bcx;
- let temp_cleanups = DVec();
- bcx = store_non_ref_bindings(bcx, data, Some(&temp_cleanups));
- bcx = insert_lllocals(bcx, data, false);
-
- let val = unpack_result!(bcx, {
- do with_scope_result(bcx, guard_expr.info(),
- ~"guard") |bcx| {
- expr::trans_to_datum(bcx, guard_expr).to_result()
- }
- });
-
- // Revoke the temp cleanups now that the guard successfully executed.
- for temp_cleanups.each |llval| {
- revoke_clean(bcx, *llval);
- }
-
- return do with_cond(bcx, Not(bcx, val)) |bcx| {
- // Guard does not match: free the values we copied,
- // and remove all bindings from the lllocals table
- let bcx = drop_bindings(bcx, data);
- compile_submatch(bcx, m, vals, chk);
- bcx
- };
-
- fn drop_bindings(bcx: block, data: &ArmData) -> block {
- let mut bcx = bcx;
- for data.bindings_map.each_value |binding_info| {
- match binding_info.trmode {
- TrByValue(_, llval) => {
- bcx = glue::drop_ty(bcx, llval, binding_info.ty);
- }
- TrByRef | TrByImplicitRef => {}
- }
- bcx.fcx.lllocals.remove(binding_info.id);
- }
- return bcx;
- }
-}
-
-fn compile_submatch(bcx: block,
- m: &[@Match],
- vals: &[ValueRef],
- chk: Option<mk_fail>)
-{
- debug!("compile_submatch(bcx=%s, m=%s, vals=%?)",
- bcx.to_str(),
- matches_to_str(bcx, m),
- vals.map(|v| bcx.val_str(*v)));
- let _indenter = indenter();
-
- /*
- For an empty match, a fall-through case must exist
- */
- assert(m.len() > 0u || chk.is_some());
- let _icx = bcx.insn_ctxt("alt::compile_submatch");
- let mut bcx = bcx;
- let tcx = bcx.tcx(), dm = tcx.def_map;
- if m.len() == 0u {
- Br(bcx, chk.get()());
- return;
- }
- if m[0].pats.len() == 0u {
- let data = m[0].data;
- match data.arm.guard {
- Some(guard_expr) => {
- bcx = compile_guard(bcx, guard_expr, m[0].data,
- vec::view(m, 1, m.len()),
- vals, chk);
- }
- _ => ()
- }
- Br(bcx, data.bodycx.llbb);
- return;
- }
-
- let col = pick_col(m);
- let val = vals[col];
- let m = {
- if has_nested_bindings(m, col) {
- expand_nested_bindings(bcx, m, col, val)
- } else {
- m.to_vec()
- }
- };
-
- let vals_left = vec::append(vec::slice(vals, 0u, col),
- vec::view(vals, col + 1u, vals.len()));
- let ccx = bcx.fcx.ccx;
- let mut pat_id = 0;
- for vec::each(m) |br| {
- // Find a real id (we're adding placeholder wildcard patterns, but
- // each column is guaranteed to have at least one real pattern)
- if pat_id == 0 { pat_id = br.pats[col].id; }
- }
-
- root_pats_as_necessary(bcx, m, col, val);
-
- let rec_fields = collect_record_or_struct_fields(bcx, m, col);
- if rec_fields.len() > 0 {
- let pat_ty = node_id_type(bcx, pat_id);
- do expr::with_field_tys(tcx, pat_ty, None) |_has_dtor, field_tys| {
- let rec_vals = rec_fields.map(|field_name| {
- let ix = ty::field_idx_strict(tcx, *field_name, field_tys);
- GEPi(bcx, val, struct_field(ix))
- });
- compile_submatch(
- bcx,
- enter_rec_or_struct(bcx, dm, m, col, rec_fields, val),
- vec::append(rec_vals, vals_left),
- chk);
- }
- return;
- }
-
- if any_tup_pat(m, col) {
- let tup_ty = node_id_type(bcx, pat_id);
- let n_tup_elts = match ty::get(tup_ty).sty {
- ty::ty_tup(elts) => elts.len(),
- _ => ccx.sess.bug(~"non-tuple type in tuple pattern")
- };
- let tup_vals = vec::from_fn(n_tup_elts, |i| GEPi(bcx, val, [0u, i]));
- compile_submatch(bcx, enter_tup(bcx, dm, m, col, val, n_tup_elts),
- vec::append(tup_vals, vals_left), chk);
- return;
- }
-
- if any_tuple_struct_pat(bcx, m, col) {
- let struct_ty = node_id_type(bcx, pat_id);
- let struct_element_count;
- match ty::get(struct_ty).sty {
- ty::ty_struct(struct_id, _) => {
- struct_element_count =
- ty::lookup_struct_fields(tcx, struct_id).len();
- }
- _ => {
- ccx.sess.bug(~"non-struct type in tuple struct pattern");
- }
- }
-
- let llstructvals = vec::from_fn(
- struct_element_count, |i| GEPi(bcx, val, struct_field(i)));
- compile_submatch(bcx,
- enter_tuple_struct(bcx, dm, m, col, val,
- struct_element_count),
- vec::append(llstructvals, vals_left),
- chk);
- return;
- }
-
- // Unbox in case of a box field
- if any_box_pat(m, col) {
- let llbox = Load(bcx, val);
- let box_no_addrspace = non_gc_box_cast(bcx, llbox);
- let unboxed =
- GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
- compile_submatch(bcx, enter_box(bcx, dm, m, col, val),
- vec::append(~[unboxed], vals_left), chk);
- return;
- }
-
- if any_uniq_pat(m, col) {
- let llbox = Load(bcx, val);
- let box_no_addrspace = non_gc_box_cast(bcx, llbox);
- let unboxed =
- GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
- compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
- vec::append(~[unboxed], vals_left), chk);
- return;
- }
-
- if any_region_pat(m, col) {
- let loaded_val = Load(bcx, val);
- compile_submatch(bcx, enter_region(bcx, dm, m, col, val),
- vec::append(~[loaded_val], vals_left), chk);
- return;
- }
-
- // Decide what kind of branch we need
- let opts = get_options(ccx, m, col);
- let mut kind = no_branch;
- let mut test_val = val;
- if opts.len() > 0u {
- match opts[0] {
- var(_, vdef) => {
- if (*ty::enum_variants(tcx, vdef.enm)).len() == 1u {
- kind = single;
- } else {
- let enumptr =
- PointerCast(bcx, val, T_opaque_enum_ptr(ccx));
- let discrimptr = GEPi(bcx, enumptr, [0u, 0u]);
- test_val = Load(bcx, discrimptr);
- kind = switch;
- }
- }
- lit(_) => {
- let pty = node_id_type(bcx, pat_id);
- test_val = load_if_immediate(bcx, val, pty);
- kind = if ty::type_is_integral(pty) { switch }
- else { compare };
- }
- range(_, _) => {
- test_val = Load(bcx, val);
- kind = compare;
- },
- vec_len_eq(_) | vec_len_ge(_) => {
- let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
- let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
- let (_, len) = tvec::get_base_and_len(
- bcx, unboxed, vt.vec_ty
- );
- test_val = SDiv(bcx, len, vt.llunit_size);
- kind = compare_vec_len;
- }
- }
- }
- for vec::each(opts) |o| {
- match *o {
- range(_, _) => { kind = compare; break }
- _ => ()
- }
- }
- let else_cx = match kind {
- no_branch | single => bcx,
- _ => sub_block(bcx, ~"match_else")
- };
- let sw = if kind == switch {
- Switch(bcx, test_val, else_cx.llbb, opts.len())
- } else {
- C_int(ccx, 0) // Placeholder for when not using a switch
- };
-
- let defaults = enter_default(else_cx, dm, m, col, val);
- let exhaustive = chk.is_none() && defaults.len() == 0u;
- let len = opts.len();
- let mut i = 0u;
-
- // Compile subtrees for each option
- for vec::each(opts) |opt| {
- i += 1u;
- let mut opt_cx = else_cx;
- if !exhaustive || i < len {
- opt_cx = sub_block(bcx, ~"match_case");
- match kind {
- single => Br(bcx, opt_cx.llbb),
- switch => {
- match trans_opt(bcx, opt) {
- single_result(r) => {
- llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
- bcx = r.bcx;
- }
- _ => {
- bcx.sess().bug(
- ~"in compile_submatch, expected \
- trans_opt to return a single_result")
- }
- }
- }
- compare => {
- let t = node_id_type(bcx, pat_id);
- let Result {bcx: after_cx, val: matches} = {
- do with_scope_result(bcx, None,
- ~"compare_scope") |bcx| {
- match trans_opt(bcx, opt) {
- single_result(
- Result {bcx, val}) => {
- compare_values(bcx, test_val, val, t)
- }
- lower_bound(
- Result {bcx, val}) => {
- compare_scalar_types(
- bcx, test_val, val,
- t, ast::ge)
- }
- range_result(
- Result {val: vbegin, _},
- Result {bcx, val: vend}) => {
- let Result {bcx, val: llge} =
- compare_scalar_types(
- bcx, test_val,
- vbegin, t, ast::ge);
- let Result {bcx, val: llle} =
- compare_scalar_types(
- bcx, test_val, vend,
- t, ast::le);
- rslt(bcx, And(bcx, llge, llle))
- }
- }
- }
- };
- bcx = sub_block(after_cx, ~"compare_next");
- CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
- }
- compare_vec_len => {
- let Result {bcx: after_cx, val: matches} = {
- do with_scope_result(bcx, None,
- ~"compare_vec_len_scope") |bcx| {
- match trans_opt(bcx, opt) {
- single_result(
- Result {bcx, val}) => {
- let value = compare_scalar_values(
- bcx, test_val, val,
- signed_int, ast::eq);
- rslt(bcx, value)
- }
- lower_bound(
- Result {bcx, val: val}) => {
- let value = compare_scalar_values(
- bcx, test_val, val,
- signed_int, ast::ge);
- rslt(bcx, value)
- }
- range_result(
- Result {val: vbegin, _},
- Result {bcx, val: vend}) => {
- let llge =
- compare_scalar_values(
- bcx, test_val,
- vbegin, signed_int, ast::ge);
- let llle =
- compare_scalar_values(
- bcx, test_val, vend,
- signed_int, ast::le);
- rslt(bcx, And(bcx, llge, llle))
- }
- }
- }
- };
- bcx = sub_block(after_cx, ~"compare_vec_len_next");
- CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
- }
- _ => ()
- }
- } else if kind == compare || kind == compare_vec_len {
- Br(bcx, else_cx.llbb);
- }
-
- let mut size = 0u;
- let mut unpacked = ~[];
- match *opt {
- var(_, vdef) => {
- let args = extract_variant_args(opt_cx, pat_id, vdef, val);
- size = args.vals.len();
- unpacked = args.vals;
- opt_cx = args.bcx;
- }
- vec_len_eq(n) | vec_len_ge(n) => {
- let tail = match *opt {
- vec_len_ge(_) => true,
- _ => false
- };
- let args = extract_vec_elems(opt_cx, pat_id, n, tail, val);
- size = args.vals.len();
- unpacked = args.vals;
- opt_cx = args.bcx;
- }
- lit(_) | range(_, _) => ()
- }
- let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
- let opt_vals = vec::append(unpacked, vals_left);
- compile_submatch(opt_cx, opt_ms, opt_vals, chk);
- }
-
- // Compile the fall-through case, if any
- if !exhaustive {
- if kind == compare || kind == compare_vec_len {
- Br(bcx, else_cx.llbb);
- }
- if kind != single {
- compile_submatch(else_cx, defaults, vals_left, chk);
- }
- }
-}
-
-fn trans_alt(bcx: block,
- alt_expr: @ast::expr,
- discr_expr: @ast::expr,
- arms: ~[ast::arm],
- dest: Dest) -> block {
- let _icx = bcx.insn_ctxt("alt::trans_alt");
- do with_scope(bcx, alt_expr.info(), ~"alt") |bcx| {
- trans_alt_inner(bcx, discr_expr, arms, dest)
- }
-}
-
-fn trans_alt_inner(scope_cx: block,
- discr_expr: @ast::expr,
- arms: &[ast::arm],
- dest: Dest) -> block {
- let _icx = scope_cx.insn_ctxt("alt::trans_alt_inner");
- let mut bcx = scope_cx;
- let tcx = bcx.tcx();
-
- let discr_datum = unpack_datum!(bcx, {
- expr::trans_to_datum(bcx, discr_expr)
- });
- if bcx.unreachable {
- return bcx;
- }
-
- let mut arm_datas = ~[], matches = ~[];
- for vec::each(arms) |arm| {
- let body = scope_block(bcx, arm.body.info(), ~"case_body");
-
- // Create the bindings map, which is a mapping from each binding name
- // to an alloca() that will be the value for that local variable.
- // Note that we use the names because each binding will have many ids
- // from the various alternatives.
- let bindings_map = std::map::HashMap();
- do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, s, path| {
- let ident = path_to_ident(path);
- let variable_ty = node_id_type(bcx, p_id);
- let llvariable_ty = type_of::type_of(bcx.ccx(), variable_ty);
-
- let llmatch, trmode;
- match bm {
- ast::bind_by_value | ast::bind_by_move => {
- // in this case, the type of the variable will be T,
- // but we need to store a *T
- let is_move = (bm == ast::bind_by_move);
- llmatch = alloca(bcx, T_ptr(llvariable_ty));
- trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
- }
- ast::bind_infer => {
- // in this case also, the type of the variable will be T,
- // but we need to store a *T
- let is_move = match tcx.value_modes.find(p_id) {
- None => {
- tcx.sess.span_bug(s, ~"no value mode");
- }
- Some(MoveValue) => true,
- Some(CopyValue) | Some(ReadValue) => false
- };
- llmatch = alloca(bcx, T_ptr(llvariable_ty));
- trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
- }
- ast::bind_by_ref(_) => {
- llmatch = alloca(bcx, llvariable_ty);
- trmode = TrByRef;
- }
- };
- bindings_map.insert(ident, BindingInfo {
- llmatch: llmatch, trmode: trmode,
- id: p_id, ty: variable_ty
- });
- }
-
- let arm_data = @ArmData {bodycx: body,
- arm: arm,
- bindings_map: bindings_map};
- arm_datas.push(arm_data);
- for vec::each(arm.pats) |p| {
- matches.push(@Match {pats: ~[*p], data: arm_data});
- }
- }
-
- let t = node_id_type(bcx, discr_expr.id);
- let chk = {
- if ty::type_is_empty(tcx, t) {
- // Special case for empty types
- let fail_cx = @mut None;
- Some(|| mk_fail(scope_cx, discr_expr.span,
- ~"scrutinizing value that can't exist", fail_cx))
- } else {
- None
- }
- };
- let lldiscr = discr_datum.to_ref_llval(bcx);
- compile_submatch(bcx, matches, ~[lldiscr], chk);
-
- let arm_cxs = DVec();
- for arm_datas.each |arm_data| {
- let mut bcx = arm_data.bodycx;
-
- // If this arm has a guard, then the various by-value bindings have
- // already been copied into their homes. If not, we do it here. This
- // is just to reduce code space. See extensive comment at the start
- // of the file for more details.
- if arm_data.arm.guard.is_none() {
- bcx = store_non_ref_bindings(bcx, *arm_data, None);
- }
-
- // insert bindings into the lllocals map and add cleanups
- bcx = insert_lllocals(bcx, *arm_data, true);
-
- bcx = controlflow::trans_block(bcx, arm_data.arm.body, dest);
- bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
- arm_cxs.push(bcx);
- }
-
- return controlflow::join_blocks(scope_cx, dvec::unwrap(move arm_cxs));
-
- fn mk_fail(bcx: block, sp: span, msg: ~str,
- finished: @mut Option<BasicBlockRef>) -> BasicBlockRef {
- match *finished { Some(bb) => return bb, _ => () }
- let fail_cx = sub_block(bcx, ~"case_fallthrough");
- controlflow::trans_fail(fail_cx, Some(sp), msg);
- *finished = Some(fail_cx.llbb);
- return fail_cx.llbb;
- }
-}
-
-enum IrrefutablePatternBindingMode {
- // Stores the association between node ID and LLVM value in `lllocals`.
- BindLocal,
- // Stores the association between node ID and LLVM value in `llargs`.
- BindArgument
-}
-
-// Not alt-related, but similar to the pattern-munging code above
-fn bind_irrefutable_pat(bcx: block,
- pat: @ast::pat,
- val: ValueRef,
- make_copy: bool,
- binding_mode: IrrefutablePatternBindingMode)
- -> block {
- let _icx = bcx.insn_ctxt("alt::bind_irrefutable_pat");
- let ccx = bcx.fcx.ccx;
- let mut bcx = bcx;
-
- // Necessary since bind_irrefutable_pat is called outside trans_alt
- match pat.node {
- ast::pat_ident(_, _,inner) => {
- if pat_is_variant_or_struct(bcx.tcx().def_map, pat) {
- return bcx;
- }
-
- if make_copy {
- let binding_ty = node_id_type(bcx, pat.id);
- let datum = Datum {val: val, ty: binding_ty,
- mode: ByRef, source: FromRvalue};
- let scratch = scratch_datum(bcx, binding_ty, false);
- datum.copy_to_datum(bcx, INIT, scratch);
- match binding_mode {
- BindLocal => {
- bcx.fcx.lllocals.insert(pat.id,
- local_mem(scratch.val));
- }
- BindArgument => {
- bcx.fcx.llargs.insert(pat.id,
- local_mem(scratch.val));
- }
- }
- add_clean(bcx, scratch.val, binding_ty);
- } else {
- match binding_mode {
- BindLocal => {
- bcx.fcx.lllocals.insert(pat.id, local_mem(val));
- }
- BindArgument => {
- bcx.fcx.llargs.insert(pat.id, local_mem(val));
- }
- }
- }
-
- for inner.each |inner_pat| {
- bcx = bind_irrefutable_pat(
- bcx, *inner_pat, val, true, binding_mode);
- }
- }
- ast::pat_enum(_, sub_pats) => {
- match bcx.tcx().def_map.find(pat.id) {
- Some(ast::def_variant(*)) => {
- let pat_def = ccx.tcx.def_map.get(pat.id);
- let vdefs = ast_util::variant_def_ids(pat_def);
- let args = extract_variant_args(bcx, pat.id, vdefs, val);
- for sub_pats.each |sub_pat| {
- for vec::eachi(args.vals) |i, argval| {
- bcx = bind_irrefutable_pat(bcx,
- sub_pat[i],
- *argval,
- make_copy,
- binding_mode);
- }
- }
- }
- Some(ast::def_struct(*)) => {
- match sub_pats {
- None => {
- // This is a unit-like struct. Nothing to do here.
- }
- Some(elems) => {
- // This is the tuple variant case.
- for vec::eachi(elems) |i, elem| {
- let fldptr = GEPi(bcx, val, struct_field(i));
- bcx = bind_irrefutable_pat(bcx,
- *elem,
- fldptr,
- make_copy,
- binding_mode);
- }
- }
- }
- }
- _ => {
- // Nothing to do here.
- }
- }
- }
- ast::pat_rec(fields, _) | ast::pat_struct(_, fields, _) => {
- let tcx = bcx.tcx();
- let pat_ty = node_id_type(bcx, pat.id);
- do expr::with_field_tys(tcx, pat_ty, None) |_hd, field_tys| {
- for vec::each(fields) |f| {
- let ix = ty::field_idx_strict(tcx, f.ident, field_tys);
- let fldptr = GEPi(bcx, val, struct_field(ix));
- bcx = bind_irrefutable_pat(bcx,
- f.pat,
- fldptr,
- make_copy,
- binding_mode);
- }
- }
- }
- ast::pat_tup(elems) => {
- for vec::eachi(elems) |i, elem| {
- let fldptr = GEPi(bcx, val, [0u, i]);
- bcx = bind_irrefutable_pat(bcx,
- *elem,
- fldptr,
- make_copy,
- binding_mode);
- }
- }
- ast::pat_box(inner) | ast::pat_uniq(inner) => {
- let llbox = Load(bcx, val);
- let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
- bcx = bind_irrefutable_pat(bcx,
- inner,
- unboxed,
- true,
- binding_mode);
- }
- ast::pat_region(inner) => {
- let loaded_val = Load(bcx, val);
- bcx = bind_irrefutable_pat(bcx,
- inner,
- loaded_val,
- true,
- binding_mode);
- }
- ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) |
- ast::pat_vec(*) => ()
- }
- return bcx;
-}
-
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
// but many TypeRefs correspond to one ty::t; for instance, tup(int, int,
// int) and rec(x=int, y=int, z=int) will have the same TypeRef.
+use core::prelude::*;
+
use back::link::{mangle_exported_name};
use back::link::{mangle_internal_name_by_path_and_seq};
use back::link::{mangle_internal_name_by_path};
use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
use lib::llvm::{True, False};
use lib::llvm::{llvm, mk_target_data, mk_type_names};
+use lib;
use metadata::common::link_meta;
use metadata::{csearch, cstore, decoder, encoder};
+use middle::astencode;
use middle::pat_util::*;
+use middle::resolve;
+use middle::trans::_match;
use middle::trans::build::*;
+use middle::trans::callee;
use middle::trans::common::*;
+use middle::trans::consts;
+use middle::trans::controlflow;
+use middle::trans::datum;
+use middle::trans::debuginfo;
+use middle::trans::expr;
+use middle::trans::foreign;
+use middle::trans::glue;
+use middle::trans::inline;
+use middle::trans::meth;
+use middle::trans::monomorphize;
+use middle::trans::reachable;
use middle::trans::shape::*;
+use middle::trans::tvec;
use middle::trans::type_of::*;
use util::common::indenter;
use util::common::is_main_name;
use util::ppaux::{ty_to_str, ty_to_short_str};
use util::ppaux;
+use core::either;
+use core::hash;
+use core::int;
+use core::io;
use core::libc::{c_uint, c_ulonglong};
use core::option::{is_none, is_some};
+use core::option;
+use core::uint;
use std::map::HashMap;
use std::smallintmap;
use std::{map, time, list};
-use syntax::ast_map::{path, path_mod, path_name};
+use syntax::ast_map::{path, path_elt_to_str, path_mod, path_name};
use syntax::ast_util::{def_id_of_def, local_def, path_to_ident};
use syntax::attr;
use syntax::codemap::span;
}
}
-fn log_fn_time(ccx: @crate_ctxt, name: ~str, start: time::Timespec,
+fn log_fn_time(ccx: @crate_ctxt, +name: ~str, start: time::Timespec,
end: time::Timespec) {
let elapsed = 1000 * ((end.sec - start.sec) as int) +
((end.nsec as int) - (start.nsec as int)) / 1000000;
fn decl_fn(llmod: ModuleRef, name: ~str, cc: lib::llvm::CallConv,
llty: TypeRef) -> ValueRef {
let llfn: ValueRef = str::as_c_str(name, |buf| {
- llvm::LLVMGetOrInsertFunction(llmod, buf, llty)
+ unsafe {
+ llvm::LLVMGetOrInsertFunction(llmod, buf, llty)
+ }
});
- lib::llvm::SetFunctionCallConv(llfn, cc);
+ unsafe {
+ lib::llvm::SetFunctionCallConv(llfn, cc);
+ }
return llfn;
}
-fn decl_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) -> ValueRef {
+fn decl_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) -> ValueRef {
return decl_fn(llmod, name, lib::llvm::CCallConv, llty);
}
// Only use this if you are going to actually define the function. It's
// not valid to simply declare a function as internal.
-fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) ->
+fn decl_internal_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) ->
ValueRef {
let llfn = decl_cdecl_fn(llmod, name, llty);
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
}
fn get_extern_fn(externs: HashMap<~str, ValueRef>,
- llmod: ModuleRef, name: ~str,
- cc: lib::llvm::CallConv, ty: TypeRef) -> ValueRef {
- if externs.contains_key(name) { return externs.get(name); }
- let f = decl_fn(llmod, name, cc, ty);
+ llmod: ModuleRef,
+ +name: ~str,
+ cc: lib::llvm::CallConv,
+ ty: TypeRef) -> ValueRef {
+ // XXX: Bad copy.
+ if externs.contains_key(copy name) { return externs.get(name); }
+ // XXX: Bad copy.
+ let f = decl_fn(llmod, copy name, cc, ty);
externs.insert(name, f);
return f;
}
fn get_extern_const(externs: HashMap<~str, ValueRef>, llmod: ModuleRef,
- name: ~str, ty: TypeRef) -> ValueRef {
- if externs.contains_key(name) { return externs.get(name); }
- let c = str::as_c_str(name, |buf| llvm::LLVMAddGlobal(llmod, ty, buf));
- externs.insert(name, c);
- return c;
+ +name: ~str, ty: TypeRef) -> ValueRef {
+ unsafe {
+ // XXX: Bad copy.
+ if externs.contains_key(copy name) { return externs.get(name); }
+ let c = str::as_c_str(name, |buf| {
+ llvm::LLVMAddGlobal(llmod, ty, buf)
+ });
+ externs.insert(name, c);
+ return c;
+ }
}
fn get_simple_extern_fn(cx: block,
externs: HashMap<~str, ValueRef>,
llmod: ModuleRef,
- name: ~str, n_args: int) -> ValueRef {
+ +name: ~str,
+ n_args: int) -> ValueRef {
let _icx = cx.insn_ctxt("get_simple_extern_fn");
let ccx = cx.fcx.ccx;
let inputs = vec::from_elem(n_args as uint, ccx.int_type);
}
fn trans_foreign_call(cx: block, externs: HashMap<~str, ValueRef>,
- llmod: ModuleRef, name: ~str, args: ~[ValueRef]) ->
+ llmod: ModuleRef, +name: ~str, args: ~[ValueRef]) ->
ValueRef {
let _icx = cx.insn_ctxt("trans_foreign_call");
let n = args.len() as int;
// malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size.
-fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
+fn malloc_raw_dyn(bcx: block,
+ t: ty::t,
+ heap: heap,
size: ValueRef) -> Result {
let _icx = bcx.insn_ctxt("malloc_raw");
let ccx = bcx.ccx();
- let (mk_fn, rtcall) = match heap {
- heap_shared => (ty::mk_imm_box, ~"malloc"),
- heap_exchange => (ty::mk_imm_uniq, ~"exchange_malloc")
+ let (mk_fn, langcall) = match heap {
+ heap_shared => {
+ (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
+ }
+ heap_exchange => {
+ (ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn())
+ }
};
// Grab the TypeRef type of box_ptr_ty.
// Allocate space:
let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8()));
let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
- let bcx = callee::trans_rtcall(bcx, rtcall, ~[tydesc, size],
- expr::SaveIn(rval));
+ let bcx = callee::trans_rtcall_or_lang_call(
+ bcx,
+ langcall,
+ ~[tydesc, size],
+ expr::SaveIn(rval));
return rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
}
* wrong address space and thus be the wrong type.
*/
fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef {
- debug!("non_gc_box_cast");
- add_comment(bcx, ~"non_gc_box_cast");
- assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace
- || bcx.unreachable);
- let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val)));
- PointerCast(bcx, val, non_gc_t)
+ unsafe {
+ debug!("non_gc_box_cast");
+ add_comment(bcx, ~"non_gc_box_cast");
+ assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) ==
+ gc_box_addrspace || bcx.unreachable);
+ let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val)));
+ PointerCast(bcx, val, non_gc_t)
+ }
}
// malloc_raw: expects an unboxed type and returns a pointer to
}
fn set_no_inline(f: ValueRef) {
- llvm::LLVMAddFunctionAttr(f, lib::llvm::NoInlineAttribute as c_ulonglong,
- 0u as c_ulonglong);
+ unsafe {
+ llvm::LLVMAddFunctionAttr(f,
+ lib::llvm::NoInlineAttribute as c_ulonglong,
+ 0u as c_ulonglong);
+ }
}
fn set_no_unwind(f: ValueRef) {
- llvm::LLVMAddFunctionAttr(f, lib::llvm::NoUnwindAttribute as c_ulonglong,
- 0u as c_ulonglong);
+ unsafe {
+ llvm::LLVMAddFunctionAttr(f,
+ lib::llvm::NoUnwindAttribute as c_ulonglong,
+ 0u as c_ulonglong);
+ }
}
// Tell LLVM to emit the information necessary to unwind the stack for the
// function f.
fn set_uwtable(f: ValueRef) {
- llvm::LLVMAddFunctionAttr(f, lib::llvm::UWTableAttribute as c_ulonglong,
- 0u as c_ulonglong);
+ unsafe {
+ llvm::LLVMAddFunctionAttr(f,
+ lib::llvm::UWTableAttribute as c_ulonglong,
+ 0u as c_ulonglong);
+ }
}
fn set_inline_hint(f: ValueRef) {
- llvm::LLVMAddFunctionAttr(f, lib::llvm::InlineHintAttribute
- as c_ulonglong, 0u as c_ulonglong);
+ unsafe {
+ llvm::LLVMAddFunctionAttr(f, lib::llvm::InlineHintAttribute
+ as c_ulonglong, 0u as c_ulonglong);
+ }
}
fn set_inline_hint_if_appr(attrs: ~[ast::attribute],
}
fn set_always_inline(f: ValueRef) {
- llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute
- as c_ulonglong, 0u as c_ulonglong);
+ unsafe {
+ llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute
+ as c_ulonglong, 0u as c_ulonglong);
+ }
}
fn set_custom_stack_growth_fn(f: ValueRef) {
- llvm::LLVMAddFunctionAttr(f, 0u as c_ulonglong, 1u as c_ulonglong);
+ unsafe {
+ llvm::LLVMAddFunctionAttr(f, 0u as c_ulonglong, 1u as c_ulonglong);
+ }
}
fn set_glue_inlining(f: ValueRef, t: ty::t) {
// Double-check that we never ask LLVM to declare the same symbol twice. It
// silently mangles such symbols, breaking our linkage model.
-fn note_unique_llvm_symbol(ccx: @crate_ctxt, sym: ~str) {
- if ccx.all_llvm_symbols.contains_key(sym) {
+fn note_unique_llvm_symbol(ccx: @crate_ctxt, +sym: ~str) {
+ // XXX: Bad copy.
+ if ccx.all_llvm_symbols.contains_key(copy sym) {
ccx.sess.bug(~"duplicate LLVM symbol: " + sym);
}
ccx.all_llvm_symbols.insert(sym, ());
// Structural comparison: a rather involved form of glue.
fn maybe_name_value(cx: @crate_ctxt, v: ValueRef, s: ~str) {
if cx.sess.opts.save_temps {
- let _: () = str::as_c_str(s, |buf| llvm::LLVMSetValueName(v, buf));
+ let _: () = str::as_c_str(s, |buf| {
+ unsafe {
+ llvm::LLVMSetValueName(v, buf)
+ }
+ });
}
}
fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
nt: scalar_type, op: ast::binop) -> ValueRef {
let _icx = cx.insn_ctxt("compare_scalar_values");
- fn die_(cx: block) -> ! {
+ fn die(cx: block) -> ! {
cx.tcx().sess.bug(~"compare_scalar_values: must be a\
comparison operator");
}
- let die = fn@() -> ! { die_(cx) };
match nt {
nil_type => {
// We don't need to do actual comparisons for nil.
ast::eq | ast::le | ast::ge => return C_bool(true),
ast::ne | ast::lt | ast::gt => return C_bool(false),
// refinements would be nice
- _ => die()
+ _ => die(cx)
}
}
floating_point => {
ast::le => lib::llvm::RealOLE,
ast::gt => lib::llvm::RealOGT,
ast::ge => lib::llvm::RealOGE,
- _ => die()
+ _ => die(cx)
};
return FCmp(cx, cmp, lhs, rhs);
}
ast::le => lib::llvm::IntSLE,
ast::gt => lib::llvm::IntSGT,
ast::ge => lib::llvm::IntSGE,
- _ => die()
+ _ => die(cx)
};
return ICmp(cx, cmp, lhs, rhs);
}
ast::le => lib::llvm::IntULE,
ast::gt => lib::llvm::IntUGT,
ast::ge => lib::llvm::IntUGE,
- _ => die()
+ _ => die(cx)
};
return ICmp(cx, cmp, lhs, rhs);
}
let mut j = 0u;
let v_id = variant.id;
for vec::each(fn_ty.sig.inputs) |a| {
- let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j);
+ let llfldp_a = GEP_enum(cx, a_tup, tid, v_id,
+ /*bad*/copy tps, j);
// XXX: Is "None" right here?
let ty_subst = ty::subst_tps(ccx.tcx, tps, None, a.ty);
cx = f(cx, llfldp_a, ty_subst);
j += 1u;
}
}
- _ => cx.tcx().sess.bug(~"iter_variant: not a function type")
+ _ => cx.tcx().sess.bug(fmt!("iter_variant: not a function type: \
+ %s (variant name = %s)",
+ cx.ty_to_str(fn_ty),
+ cx.sess().str_of(variant.name)))
}
return cx;
}
- /*
- Typestate constraint that shows the unimpl case doesn't happen?
- */
let mut cx = cx;
- match ty::get(t).sty {
+ match /*bad*/copy ty::get(t).sty {
ty::ty_rec(*) | ty::ty_struct(*) => {
do expr::with_field_tys(cx.tcx(), t, None) |_has_dtor, field_tys| {
for vec::eachi(field_tys) |i, field_ty| {
// Cast the enums to types we can GEP into.
if n_variants == 1u {
- return iter_variant(cx, av, variants[0],
- (*substs).tps, tid, f);
+ return iter_variant(cx,
+ av,
+ variants[0],
+ /*bad*/copy substs.tps,
+ tid,
+ f);
}
let ccx = cx.ccx();
AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb);
let variant_cx =
iter_variant(variant_cx, llunion_a_ptr, *variant,
- (*substs).tps, tid, f);
+ /*bad*/copy (*substs).tps, tid, f);
Br(variant_cx, next_cx.llbb);
}
return next_cx;
fn cast_shift_const_rhs(op: ast::binop,
lhs: ValueRef, rhs: ValueRef) -> ValueRef {
- cast_shift_rhs(op, lhs, rhs,
- llvm::LLVMConstTrunc, llvm::LLVMConstZExt)
+ unsafe {
+ cast_shift_rhs(op, lhs, rhs,
+ |a, b| unsafe { llvm::LLVMConstTrunc(a, b) },
+ |a, b| unsafe { llvm::LLVMConstZExt(a, b) })
+ }
}
fn cast_shift_rhs(op: ast::binop,
zext: fn(ValueRef, TypeRef) -> ValueRef
) -> ValueRef {
// Shifts may have any size int on the rhs
- if ast_util::is_shift_binop(op) {
- let rhs_llty = val_ty(rhs);
- let lhs_llty = val_ty(lhs);
- let rhs_sz = llvm::LLVMGetIntTypeWidth(rhs_llty);
- let lhs_sz = llvm::LLVMGetIntTypeWidth(lhs_llty);
- if lhs_sz < rhs_sz {
- trunc(rhs, lhs_llty)
- } else if lhs_sz > rhs_sz {
- // FIXME (#1877: If shifting by negative
- // values becomes not undefined then this is wrong.
- zext(rhs, lhs_llty)
+ unsafe {
+ if ast_util::is_shift_binop(op) {
+ let rhs_llty = val_ty(rhs);
+ let lhs_llty = val_ty(lhs);
+ let rhs_sz = llvm::LLVMGetIntTypeWidth(rhs_llty);
+ let lhs_sz = llvm::LLVMGetIntTypeWidth(lhs_llty);
+ if lhs_sz < rhs_sz {
+ trunc(rhs, lhs_llty)
+ } else if lhs_sz > rhs_sz {
+ // FIXME (#1877: If shifting by negative
+ // values becomes not undefined then this is wrong.
+ zext(rhs, lhs_llty)
+ } else {
+ rhs
+ }
} else {
rhs
}
- } else {
- rhs
}
}
}
};
do with_cond(cx, is_zero) |bcx| {
- controlflow::trans_fail(bcx, Some(span), text)
+ controlflow::trans_fail(bcx, Some(span), /*bad*/copy text)
}
}
};
}
+fn get_discrim_val(cx: @crate_ctxt, span: span, enum_did: ast::def_id,
+ variant_did: ast::def_id) -> ValueRef {
+ // Can't use `discrims` from the crate context here because
+ // those discriminants have an extra level of indirection,
+ // and there's no LLVM constant load instruction.
+ let mut lldiscrim_opt = None;
+ for ty::enum_variants(cx.tcx, enum_did).each |variant_info| {
+ if variant_info.id == variant_did {
+ lldiscrim_opt = Some(C_int(cx,
+ variant_info.disr_val));
+ break;
+ }
+ }
+
+ match lldiscrim_opt {
+ None => {
+ cx.tcx.sess.span_bug(span, ~"didn't find discriminant?!");
+ }
+ Some(found_lldiscrim) => {
+ found_lldiscrim
+ }
+ }
+}
+
fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
- let _icx = ccx.insn_ctxt("lookup_discriminant");
- match ccx.discrims.find(vid) {
- None => {
- // It's an external discriminant that we haven't seen yet.
- assert (vid.crate != ast::local_crate);
- let sym = csearch::get_symbol(ccx.sess.cstore, vid);
- let gvar = str::as_c_str(sym, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
- });
- lib::llvm::SetLinkage(gvar, lib::llvm::ExternalLinkage);
- llvm::LLVMSetGlobalConstant(gvar, True);
- ccx.discrims.insert(vid, gvar);
- return gvar;
- }
- Some(llval) => return llval,
+ unsafe {
+ let _icx = ccx.insn_ctxt("lookup_discriminant");
+ match ccx.discrims.find(vid) {
+ None => {
+ // It's an external discriminant that we haven't seen yet.
+ assert (vid.crate != ast::local_crate);
+ let sym = csearch::get_symbol(ccx.sess.cstore, vid);
+ let gvar = str::as_c_str(sym, |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+ });
+ lib::llvm::SetLinkage(gvar, lib::llvm::ExternalLinkage);
+ llvm::LLVMSetGlobalConstant(gvar, True);
+ ccx.discrims.insert(vid, gvar);
+ return gvar;
+ }
+ Some(llval) => return llval,
+ }
}
}
-fn invoke(bcx: block, llfn: ValueRef, llargs: ~[ValueRef]) -> block {
+fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block {
let _icx = bcx.insn_ctxt("invoke_");
if bcx.unreachable { return bcx; }
if need_invoke(bcx) {
return v;
}
-fn trans_trace(bcx: block, sp_opt: Option<span>, trace_str: ~str) {
+fn trans_trace(bcx: block, sp_opt: Option<span>, +trace_str: ~str) {
if !bcx.sess().trace() { return; }
let _icx = bcx.insn_ctxt("trans_trace");
- add_comment(bcx, trace_str);
+ // XXX: Bad copy.
+ add_comment(bcx, copy trace_str);
let V_trace_str = C_cstr(bcx.ccx(), trace_str);
let {V_filename, V_line} = match sp_opt {
Some(sp) => {
let sess = bcx.sess();
let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo);
- {V_filename: C_cstr(bcx.ccx(), loc.file.name),
+ {V_filename: C_cstr(bcx.ccx(), /*bad*/copy loc.file.name),
V_line: loc.line as int}
}
None => {
bcx.to_str());
add_clean(bcx, llptr, ty);
- return alt::bind_irrefutable_pat(bcx,
- local.node.pat,
- llptr,
- false,
- alt::BindLocal);
+ return _match::bind_irrefutable_pat(bcx,
+ local.node.pat,
+ llptr,
+ false,
+ _match::BindLocal);
}
fn trans_stmt(cx: block, s: ast::stmt) -> block {
bcx = expr::trans_into(cx, e, expr::Ignore);
}
ast::stmt_decl(d, _) => {
- match d.node {
+ match /*bad*/copy d.node {
ast::decl_local(locals) => {
for vec::each(locals) |local| {
bcx = init_local(bcx, *local);
// You probably don't want to use this one. See the
// next three functions instead.
fn new_block(cx: fn_ctxt, parent: Option<block>, +kind: block_kind,
- is_lpad: bool, name: ~str, opt_node_info: Option<node_info>)
+ is_lpad: bool, +name: ~str, opt_node_info: Option<node_info>)
-> block {
let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
(cx.ccx.names)(name)
- } else { special_idents::invalid };
- let llbb: BasicBlockRef = str::as_c_str(cx.ccx.sess.str_of(s), |buf| {
- llvm::LLVMAppendBasicBlock(cx.llfn, buf)
- });
- let bcx = mk_block(llbb, parent, move kind, is_lpad, opt_node_info, cx);
- do option::iter(&parent) |cx| {
- if cx.unreachable { Unreachable(bcx); }
+ } else {
+ special_idents::invalid
};
- return bcx;
+ unsafe {
+ let llbb: BasicBlockRef = str::as_c_str(cx.ccx.sess.str_of(s), |buf| {
+ llvm::LLVMAppendBasicBlock(cx.llfn, buf)
+ });
+ let bcx = mk_block(llbb,
+ parent,
+ move kind,
+ is_lpad,
+ opt_node_info,
+ cx);
+ do option::iter(&parent) |cx| {
+ if cx.unreachable { Unreachable(bcx); }
+ };
+ return bcx;
+ }
}
fn simple_block_scope() -> block_kind {
- block_scope({loop_break: None, loop_label: None, mut cleanups: ~[],
- mut cleanup_paths: ~[], mut landing_pad: None})
+ block_scope(scope_info {
+ loop_break: None,
+ loop_label: None,
+ mut cleanups: ~[],
+ mut cleanup_paths: ~[],
+ mut landing_pad: None
+ })
}
// Use this when you're at the top block of a function or the like.
fn scope_block(bcx: block,
opt_node_info: Option<node_info>,
- n: ~str) -> block {
+ +n: ~str) -> block {
return new_block(bcx.fcx, Some(bcx), simple_block_scope(), bcx.is_lpad,
n, opt_node_info);
}
fn loop_scope_block(bcx: block, loop_break: block, loop_label: Option<ident>,
- n: ~str, opt_node_info: Option<node_info>) -> block {
- return new_block(bcx.fcx, Some(bcx), block_scope({
+ +n: ~str, opt_node_info: Option<node_info>) -> block {
+ return new_block(bcx.fcx, Some(bcx), block_scope(scope_info {
loop_break: Some(loop_break),
loop_label: loop_label,
mut cleanups: ~[],
}
// Use this when creating a block for the inside of a landing pad.
-fn lpad_block(bcx: block, n: ~str) -> block {
+fn lpad_block(bcx: block, +n: ~str) -> block {
new_block(bcx.fcx, Some(bcx), block_non_scope, true, n, None)
}
// Use this when you're making a general CFG BB within a scope.
-fn sub_block(bcx: block, n: ~str) -> block {
+fn sub_block(bcx: block, +n: ~str) -> block {
new_block(bcx.fcx, Some(bcx), block_non_scope, bcx.is_lpad, n, None)
}
}
fn with_scope(bcx: block, opt_node_info: Option<node_info>,
- name: ~str, f: fn(block) -> block) -> block {
+ +name: ~str, f: fn(block) -> block) -> block {
let _icx = bcx.insn_ctxt("with_scope");
debug!("with_scope(bcx=%s, opt_node_info=%?, name=%s)",
leave_block(f(scope_cx), scope_cx)
}
-fn with_scope_result(bcx: block, opt_node_info: Option<node_info>,
- name: ~str, f: fn(block) -> Result)
- -> Result
-{
+fn with_scope_result(bcx: block,
+ opt_node_info: Option<node_info>,
+ +name: ~str,
+ f: fn(block) -> Result)
+ -> Result {
let _icx = bcx.insn_ctxt("with_scope_result");
let scope_cx = scope_block(bcx, opt_node_info, name);
Br(bcx, scope_cx.llbb);
}
fn with_scope_datumblock(bcx: block, opt_node_info: Option<node_info>,
- name: ~str, f: fn(block) -> datum::DatumBlock)
+ +name: ~str, f: fn(block) -> datum::DatumBlock)
-> datum::DatumBlock
{
use middle::trans::datum::DatumBlock;
for vec::each(b.node.stmts) |s| {
match s.node {
ast::stmt_decl(d, _) => {
- match d.node {
+ match /*bad*/copy d.node {
ast::decl_local(locals) => {
for vec::each(locals) |local| {
it(*local);
if cx.sess().opts.debuginfo {
do option::iter(&simple_name) |name| {
str::as_c_str(cx.ccx().sess.str_of(*name), |buf| {
- llvm::LLVMSetValueName(val, buf)
+ unsafe {
+ llvm::LLVMSetValueName(val, buf)
+ }
});
}
}
fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
let _icx = cx.insn_ctxt("alloca");
- if cx.unreachable { return llvm::LLVMGetUndef(t); }
+ if cx.unreachable {
+ unsafe {
+ return llvm::LLVMGetUndef(t);
+ }
+ }
let initcx = base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
let p = Alloca(initcx, t);
if zero { memzero(initcx, p, t); }
fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
let _icx = cx.insn_ctxt("arrayalloca");
- if cx.unreachable { return llvm::LLVMGetUndef(t); }
+ if cx.unreachable {
+ unsafe {
+ return llvm::LLVMGetUndef(t);
+ }
+ }
return ArrayAlloca(
base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), t, v);
}
// Creates the standard set of basic blocks for a function
fn mk_standard_basic_blocks(llfn: ValueRef) ->
{sa: BasicBlockRef, rt: BasicBlockRef} {
- {sa: str::as_c_str(~"static_allocas",
- |buf| llvm::LLVMAppendBasicBlock(llfn, buf)),
- rt: str::as_c_str(~"return",
- |buf| llvm::LLVMAppendBasicBlock(llfn, buf))}
+ unsafe {
+ {sa: str::as_c_str(~"static_allocas",
+ |buf| llvm::LLVMAppendBasicBlock(llfn, buf)),
+ rt: str::as_c_str(~"return",
+ |buf| llvm::LLVMAppendBasicBlock(llfn, buf))}
+ }
}
// - new_fn_ctxt
// - trans_args
fn new_fn_ctxt_w_id(ccx: @crate_ctxt,
- path: path,
+ +path: path,
llfndecl: ValueRef,
id: ast::node_id,
impl_id: Option<ast::def_id>,
- param_substs: Option<param_substs>,
+ +param_substs: Option<param_substs>,
sp: Option<span>) -> fn_ctxt {
let llbbs = mk_standard_basic_blocks(llfndecl);
- return @{llfn: llfndecl,
- llenv: llvm::LLVMGetParam(llfndecl, 1u as c_uint),
- llretptr: llvm::LLVMGetParam(llfndecl, 0u as c_uint),
+ return @fn_ctxt_ {
+ llfn: llfndecl,
+ llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) },
+ llretptr: unsafe { llvm::LLVMGetParam(llfndecl, 0u as c_uint) },
mut llstaticallocas: llbbs.sa,
mut llloadenv: None,
mut llreturn: llbbs.rt,
param_substs: param_substs,
span: sp,
path: path,
- ccx: ccx};
+ ccx: ccx
+ };
}
-fn new_fn_ctxt(ccx: @crate_ctxt, path: path, llfndecl: ValueRef,
- sp: Option<span>) -> fn_ctxt {
+fn new_fn_ctxt(ccx: @crate_ctxt,
+ +path: path,
+ llfndecl: ValueRef,
+ sp: Option<span>)
+ -> fn_ctxt {
return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp);
}
// Return an array containing the ValueRefs that we get from
// llvm::LLVMGetParam for each argument.
vec::from_fn(args.len(), |i| {
- let arg_n = first_real_arg + i;
- llvm::LLVMGetParam(cx.llfn, arg_n as c_uint)
+ unsafe {
+ let arg_n = first_real_arg + i;
+ llvm::LLVMGetParam(cx.llfn, arg_n as c_uint)
+ }
})
}
}
}
- bcx = alt::bind_irrefutable_pat(bcx,
- args[arg_n].pat,
- llarg,
- false,
- alt::BindArgument);
+ bcx = _match::bind_irrefutable_pat(bcx,
+ args[arg_n].pat,
+ llarg,
+ false,
+ _match::BindArgument);
fcx.llargs.insert(arg_id, local_mem(llarg));
// trans_closure: Builds an LLVM function out of a source function.
// If the function closes over its environment a closure will be
// returned.
-fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
- body: ast::blk, llfndecl: ValueRef,
+fn trans_closure(ccx: @crate_ctxt,
+ +path: path,
+ decl: ast::fn_decl,
+ body: ast::blk,
+ llfndecl: ValueRef,
ty_self: self_arg,
- param_substs: Option<param_substs>,
+ +param_substs: Option<param_substs>,
id: ast::node_id,
impl_id: Option<ast::def_id>,
maybe_load_env: fn(fn_ctxt),
// Set up arguments to the function.
let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs,
Some(body.span));
- let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs);
+ let raw_llargs = create_llargs_for_fn_args(fcx, ty_self,
+ /*bad*/copy decl.inputs);
// Set GC for function.
if ccx.sess.opts.gc {
do str::as_c_str("generic") |strategy| {
- llvm::LLVMSetGC(fcx.llfn, strategy);
+ unsafe {
+ llvm::LLVMSetGC(fcx.llfn, strategy);
+ }
}
ccx.uses_gc = true;
}
// trans_fn: creates an LLVM function corresponding to a source language
// function.
fn trans_fn(ccx: @crate_ctxt,
- path: path,
+ +path: path,
decl: ast::fn_decl,
body: ast::blk,
llfndecl: ValueRef,
ty_self: self_arg,
- param_substs: Option<param_substs>,
+ +param_substs: Option<param_substs>,
id: ast::node_id,
impl_id: Option<ast::def_id>) {
let do_time = ccx.sess.trans_stats();
debug!("trans_fn(ty_self=%?)", ty_self);
let _icx = ccx.insn_ctxt("trans_fn");
ccx.stats.n_fns += 1;
- trans_closure(ccx, path, decl, body, llfndecl, ty_self,
+ // XXX: Bad copy of `path`.
+ trans_closure(ccx, copy path, decl, body, llfndecl, ty_self,
param_substs, id, impl_id,
|fcx| {
if ccx.sess.opts.extra_debuginfo {
args: ~[ast::variant_arg],
disr: int,
is_degen: bool,
- param_substs: Option<param_substs>,
+ +param_substs: Option<param_substs>,
llfndecl: ValueRef) {
let _icx = ccx.insn_ctxt("trans_enum_variant");
// Translate variant arguments to function arguments.
ast_util::dummy_sp(),
special_idents::arg),
id: varg.id});
+ // XXX: Bad copy of `param_substs`.
let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None,
- param_substs, None);
- let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
+ copy param_substs, None);
+ // XXX: Bad copy.
+ let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args);
let ty_param_substs = match param_substs {
- Some(substs) => substs.tys,
+ Some(ref substs) => /*bad*/copy substs.tys,
None => ~[]
};
let bcx = top_scope_block(fcx, None), lltop = bcx.llbb;
let v_id = local_def(variant.node.id);
for vec::eachi(args) |i, va| {
let lldestptr = GEP_enum(bcx, llblobptr, t_id, v_id,
- ty_param_substs, i);
+ /*bad*/copy ty_param_substs, i);
// If this argument to this function is a enum, it'll have come in to
// this function as an opaque blob due to the way that type_of()
// works. So we have to cast to the destination's view of the type.
fn trans_tuple_struct(ccx: @crate_ctxt,
fields: ~[@ast::struct_field],
ctor_id: ast::node_id,
- param_substs: Option<param_substs>,
+ +param_substs: Option<param_substs>,
llfndecl: ValueRef) {
let _icx = ccx.insn_ctxt("trans_tuple_struct");
let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, None,
param_substs, None);
- let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
+
+ // XXX: Bad copy.
+ let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args);
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
finish_fn(fcx, lltop);
}
-fn trans_struct_dtor(ccx: @crate_ctxt, path: path,
- body: ast::blk, dtor_id: ast::node_id,
- psubsts: Option<param_substs>,
- hash_id: Option<mono_id>, parent_id: ast::def_id)
- -> ValueRef {
+fn trans_struct_dtor(ccx: @crate_ctxt,
+ +path: path,
+ body: ast::blk,
+ dtor_id: ast::node_id,
+ +psubsts: Option<param_substs>,
+ hash_id: Option<mono_id>,
+ parent_id: ast::def_id)
+ -> ValueRef {
let tcx = ccx.tcx;
/* Look up the parent class's def_id */
let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty;
and returns () */
let lldty = type_of_dtor(ccx, class_ty);
- let s = get_dtor_symbol(ccx, path, dtor_id, psubsts);
+ // XXX: Bad copies.
+ let s = get_dtor_symbol(ccx, copy path, dtor_id, copy psubsts);
/* Register the dtor as a function. It has external linkage */
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
*i += 1;
match variant.node.kind {
- ast::tuple_variant_kind(args) if args.len() > 0 => {
+ ast::tuple_variant_kind(ref args) if args.len() > 0 => {
let llfn = get_item_val(ccx, variant.node.id);
- trans_enum_variant(ccx, id, *variant, args, disr_val,
- degen, None, llfn);
+ trans_enum_variant(ccx, id, *variant, /*bad*/copy *args,
+ disr_val, degen, None, llfn);
}
ast::tuple_variant_kind(_) => {
// Nothing to do.
}
ast::struct_variant_kind(struct_def) => {
- trans_struct_def(ccx, struct_def, tps, path,
+ trans_struct_def(ccx, struct_def, /*bad*/copy tps, path,
variant.node.id);
}
ast::enum_variant_kind(ref enum_definition) => {
trans_enum_def(ccx,
*enum_definition,
id,
- tps,
+ /*bad*/copy tps,
degen,
path,
vi,
// tjc: ?
_ => fail ~"trans_item",
};
- match item.node {
- ast::item_fn(decl, purity, tps, ref body) => {
+ match /*bad*/copy item.node {
+ // XXX: Bad copies.
+ ast::item_fn(copy decl, purity, copy tps, ref body) => {
if purity == ast::extern_fn {
let llfndecl = get_item_val(ccx, item.id);
foreign::trans_foreign_fn(ccx,
vec::append(
- *path,
+ /*bad*/copy *path,
~[path_name(item.ident)]),
decl, (*body), llfndecl, item.id);
} else if tps.is_empty() {
let llfndecl = get_item_val(ccx, item.id);
trans_fn(ccx,
- vec::append(*path, ~[path_name(item.ident)]),
+ vec::append(/*bad*/copy *path, ~[path_name(item.ident)]),
decl, (*body), llfndecl, no_self, None, item.id, None);
} else {
for vec::each((*body).node.stmts) |stmt| {
match stmt.node {
- ast::stmt_decl(@{node: ast::decl_item(i), _}, _) => {
+ ast::stmt_decl(@ast::spanned { node: ast::decl_item(i),
+ _ }, _) => {
trans_item(ccx, *i);
}
_ => ()
}
}
ast::item_impl(tps, _, _, ms) => {
- meth::trans_impl(ccx, *path, item.ident, ms, tps, None,
+ meth::trans_impl(ccx, /*bad*/copy *path, item.ident, ms, tps, None,
item.id);
}
ast::item_mod(m) => {
trans_mod(ccx, m);
}
- ast::item_enum(ref enum_definition, tps) => {
+ ast::item_enum(ref enum_definition, ref tps) => {
if tps.len() == 0u {
let degen = (*enum_definition).variants.len() == 1u;
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
let mut i = 0;
- trans_enum_def(ccx, (*enum_definition), item.id, tps, degen, path,
- vi, &mut i);
+ trans_enum_def(ccx, (*enum_definition), item.id, /*bad*/copy *tps,
+ degen, path, vi, &mut i);
}
}
ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id),
ast::item_foreign_mod(foreign_mod) => {
let abi = match attr::foreign_abi(item.attrs) {
either::Right(abi_) => abi_,
- either::Left(ref msg) => ccx.sess.span_fatal(item.span, (*msg))
+ either::Left(ref msg) => ccx.sess.span_fatal(item.span,
+ /*bad*/copy *msg)
};
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
}
if tps.len() == 0u {
// Translate the destructor.
do option::iter(&struct_def.dtor) |dtor| {
- trans_struct_dtor(ccx, *path, dtor.node.body,
+ trans_struct_dtor(ccx, /*bad*/copy *path, dtor.node.body,
dtor.node.id, None, None, local_def(id));
};
// otherwise this is a unit-like struct.
Some(ctor_id) if struct_def.fields.len() > 0 => {
let llfndecl = get_item_val(ccx, ctor_id);
- trans_tuple_struct(ccx, struct_def.fields, ctor_id, None,
- llfndecl);
+ trans_tuple_struct(ccx, /*bad*/copy struct_def.fields,
+ ctor_id, None, llfndecl);
}
Some(_) | None => {}
}
return struct_elt(llpairty, 0u);
}
-fn register_fn(ccx: @crate_ctxt, sp: span, path: path,
- node_id: ast::node_id) -> ValueRef {
+fn register_fn(ccx: @crate_ctxt,
+ sp: span,
+ +path: path,
+ node_id: ast::node_id,
+ attrs: &[ast::attribute])
+ -> ValueRef {
let t = ty::node_id_to_type(ccx.tcx, node_id);
- register_fn_full(ccx, sp, path, node_id, t)
+ register_fn_full(ccx, sp, path, node_id, attrs, t)
}
-fn register_fn_full(ccx: @crate_ctxt, sp: span, path: path,
- node_id: ast::node_id, node_type: ty::t) -> ValueRef {
+fn register_fn_full(ccx: @crate_ctxt,
+ sp: span,
+ +path: path,
+ node_id: ast::node_id,
+ attrs: &[ast::attribute],
+ node_type: ty::t)
+ -> ValueRef {
let llfty = type_of_fn_from_ty(ccx, node_type);
- register_fn_fuller(ccx, sp, path, node_id, node_type,
+ register_fn_fuller(ccx, sp, path, node_id, attrs, node_type,
lib::llvm::CCallConv, llfty)
}
-fn register_fn_fuller(ccx: @crate_ctxt, sp: span, path: path,
- node_id: ast::node_id, node_type: ty::t,
- cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef {
- let ps: ~str = mangle_exported_name(ccx, path, node_type);
- let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty);
- ccx.item_symbols.insert(node_id, ps);
-
- debug!("register_fn_fuller created fn %s for item %d with path %s",
- val_str(ccx.tn, llfn), node_id,
+fn register_fn_fuller(ccx: @crate_ctxt,
+ sp: span,
+ +path: path,
+ node_id: ast::node_id,
+ attrs: &[ast::attribute],
+ node_type: ty::t,
+ cc: lib::llvm::CallConv,
+ llfty: TypeRef)
+ -> ValueRef {
+ debug!("register_fn_fuller creating fn for item %d with path %s",
+ node_id,
ast_map::path_to_str(path, ccx.sess.parse_sess.interner));
- let is_main = is_main_name(path) && !ccx.sess.building_library;
+ let ps = if attr::attrs_contains_name(attrs, "no_mangle") {
+ path_elt_to_str(path.last(), ccx.sess.parse_sess.interner)
+ } else {
+ mangle_exported_name(ccx, /*bad*/copy path, node_type)
+ };
+
+ // XXX: Bad copy.
+ let llfn: ValueRef = decl_fn(ccx.llmod, copy ps, cc, llfty);
+ ccx.item_symbols.insert(node_id, ps);
+
+ // FIXME #4404 android JNI hacks
+ let is_main = is_main_name(path) && (!ccx.sess.building_library ||
+ (ccx.sess.building_library &&
+ ccx.sess.targ_cfg.os == session::os_android));
if is_main { create_main_wrapper(ccx, sp, llfn); }
llfn
}
let lltop = bcx.llbb;
// Call main.
- let lloutputarg = llvm::LLVMGetParam(llfdecl, 0 as c_uint);
- let llenvarg = llvm::LLVMGetParam(llfdecl, 1 as c_uint);
+ let lloutputarg = unsafe { llvm::LLVMGetParam(llfdecl, 0 as c_uint) };
+ let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) };
let mut args = ~[lloutputarg, llenvarg];
Call(bcx, main_llfn, args);
#[cfg(unix)]
fn main_name() -> ~str { return ~"main"; }
let llfty = T_fn(~[ccx.int_type, ccx.int_type], ccx.int_type);
- let llfn = decl_cdecl_fn(ccx.llmod, main_name(), llfty);
+
+ // FIXME #4404 android JNI hacks
+ let llfn = if ccx.sess.building_library {
+ decl_cdecl_fn(ccx.llmod, ~"amain", llfty)
+ } else {
+ decl_cdecl_fn(ccx.llmod, main_name(), llfty)
+ };
let llbb = str::as_c_str(~"top", |buf| {
- llvm::LLVMAppendBasicBlock(llfn, buf)
+ unsafe {
+ llvm::LLVMAppendBasicBlock(llfn, buf)
+ }
});
let bld = ccx.builder.B;
- llvm::LLVMPositionBuilderAtEnd(bld, llbb);
+ unsafe {
+ llvm::LLVMPositionBuilderAtEnd(bld, llbb);
+ }
let crate_map = ccx.crate_map;
let start_ty = T_fn(~[val_ty(rust_main), ccx.int_type, ccx.int_type,
val_ty(crate_map)], ccx.int_type);
let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty);
- let args = ~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint),
- llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map];
+ let args = if ccx.sess.building_library unsafe {
+ ~[rust_main,
+ llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False),
+ llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False),
+ crate_map]
+ } else unsafe {
+ ~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint),
+ llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map]
+ };
+
let result = unsafe {
llvm::LLVMBuildCall(bld, start, vec::raw::to_ptr(args),
args.len() as c_uint, noname())
};
- llvm::LLVMBuildRet(bld, result);
+ unsafe {
+ llvm::LLVMBuildRet(bld, result);
+ }
}
}
fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
vec::append(
- *match ccx.tcx.items.get(i.id) {
+ /*bad*/copy *match ccx.tcx.items.get(i.id) {
ast_map::node_item(_, p) => p,
// separate map for paths?
_ => fail ~"item_path"
/* If there's already a symbol for the dtor with <id> and substs <substs>,
return it; otherwise, create one and register it, returning it as well */
-fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id,
- substs: Option<param_substs>) -> ~str {
+fn get_dtor_symbol(ccx: @crate_ctxt,
+ +path: path,
+ id: ast::node_id,
+ +substs: Option<param_substs>)
+ -> ~str {
let t = ty::node_id_to_type(ccx.tcx, id);
match ccx.item_symbols.find(id) {
- Some(ref s) => (*s),
+ Some(ref s) => (/*bad*/copy *s),
None if substs.is_none() => {
let s = mangle_exported_name(
ccx,
vec::append(path, ~[path_name((ccx.names)(~"dtor"))]),
t);
- ccx.item_symbols.insert(id, s);
+ // XXX: Bad copy, use `@str`?
+ ccx.item_symbols.insert(id, copy s);
s
}
None => {
let mut exprt = false;
let val = match ccx.tcx.items.get(id) {
ast_map::node_item(i, pth) => {
- let my_path = vec::append(*pth, ~[path_name(i.ident)]);
+ let my_path = vec::append(/*bad*/copy *pth,
+ ~[path_name(i.ident)]);
match i.node {
- ast::item_const(_, _) => {
+ ast::item_const(_, expr) => {
let typ = ty::node_id_to_type(ccx.tcx, i.id);
let s = mangle_exported_name(ccx, my_path, typ);
- let g = str::as_c_str(s, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf)
- });
- ccx.item_symbols.insert(i.id, s);
- g
+ // We need the translated value here, because for enums the
+ // LLVM type is not fully determined by the Rust type.
+ let v = consts::const_expr(ccx, expr);
+ ccx.const_values.insert(id, v);
+ unsafe {
+ let llty = llvm::LLVMTypeOf(v);
+ let g = str::as_c_str(s, |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
+ });
+ ccx.item_symbols.insert(i.id, s);
+ g
+ }
}
ast::item_fn(_, purity, _, _) => {
let llfn = if purity != ast::extern_fn {
- register_fn(ccx, i.span, my_path, i.id)
+ register_fn(ccx, i.span, my_path, i.id, i.attrs)
} else {
- foreign::register_foreign_fn(ccx, i.span, my_path, i.id)
+ foreign::register_foreign_fn(ccx,
+ i.span,
+ my_path,
+ i.id,
+ i.attrs)
};
- set_inline_hint_if_appr(i.attrs, llfn);
+ set_inline_hint_if_appr(/*bad*/copy i.attrs, llfn);
llfn
}
_ => fail ~"get_item_val: weird result in table"
match ni.node {
ast::foreign_item_fn(*) => {
register_fn(ccx, ni.span,
- vec::append(*pth, ~[path_name(ni.ident)]),
- ni.id)
+ vec::append(/*bad*/copy *pth,
+ ~[path_name(ni.ident)]),
+ ni.id,
+ ni.attrs)
}
ast::foreign_item_const(*) => {
let typ = ty::node_id_to_type(ccx.tcx, ni.id);
let ident = ccx.sess.parse_sess.interner.get(ni.ident);
let g = do str::as_c_str(*ident) |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf)
+ unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod,
+ type_of(ccx, typ),
+ buf)
+ }
};
g
}
let class_ty = ty::lookup_item_type(tcx, parent_id).ty;
// This code shouldn't be reached if the class is generic
assert !ty::type_has_params(class_ty);
- let lldty = T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(tcx))),
- T_ptr(type_of(ccx, class_ty))],
- llvm::LLVMVoidType());
- let s = get_dtor_symbol(ccx, *pt, dt.node.id, None);
+ let lldty = unsafe {
+ T_fn(~[
+ T_ptr(type_of(ccx, ty::mk_nil(tcx))),
+ T_ptr(type_of(ccx, class_ty))
+ ],
+ llvm::LLVMVoidType())
+ };
+ let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None);
/* Make the declaration for the dtor */
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
ast_map::node_variant(ref v, enm, pth) => {
let llfn;
- match (*v).node.kind {
+ match /*bad*/copy (*v).node.kind {
ast::tuple_variant_kind(args) => {
assert args.len() != 0u;
- let pth = vec::append(*pth,
+ let pth = vec::append(/*bad*/copy *pth,
~[path_name(enm.ident),
path_name((*v).node.name)]);
llfn = match enm.node {
ast::item_enum(_, _) => {
- register_fn(ccx, (*v).span, pth, id)
+ register_fn(ccx, (*v).span, pth, id, enm.attrs)
}
_ => fail ~"node_variant, shouldn't happen"
};
a non-tuple-like struct")
}
Some(ctor_id) => {
- let llfn = register_fn(ccx, struct_item.span,
- *struct_path, ctor_id);
+ let llfn = register_fn(ccx,
+ struct_item.span,
+ /*bad*/copy *struct_path,
+ ctor_id,
+ struct_item.attrs);
set_inline_hint(llfn);
llfn
}
fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
m: @ast::method) -> ValueRef {
let mty = ty::node_id_to_type(ccx.tcx, id);
- let pth = vec::append(*pth, ~[path_name((ccx.names)(~"meth")),
+ let pth = vec::append(/*bad*/copy *pth, ~[path_name((ccx.names)(~"meth")),
path_name(m.ident)]);
- let llfn = register_fn_full(ccx, m.span, pth, id, mty);
- set_inline_hint_if_appr(m.attrs, llfn);
+ let llfn = register_fn_full(ccx, m.span, pth, id, m.attrs, mty);
+ set_inline_hint_if_appr(/*bad*/copy m.attrs, llfn);
llfn
}
let mut i = 0;
let path = item_path(ccx, it);
for vec::each((*enum_definition).variants) |variant| {
- let p = vec::append(path, ~[path_name(variant.node.name),
- path_name(special_idents::descrim)]);
+ let p = vec::append(/*bad*/copy path, ~[
+ path_name(variant.node.name),
+ path_name(special_idents::descrim)
+ ]);
let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
let disr_val = vi[i].disr_val;
- note_unique_llvm_symbol(ccx, s);
+ // XXX: Bad copy.
+ note_unique_llvm_symbol(ccx, copy s);
let discrim_gvar = str::as_c_str(s, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+ unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+ }
});
- llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
- llvm::LLVMSetGlobalConstant(discrim_gvar, True);
+ unsafe {
+ llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
+ llvm::LLVMSetGlobalConstant(discrim_gvar, True);
+ }
ccx.discrims.insert(
local_def(variant.node.id), discrim_gvar);
ccx.discrim_symbols.insert(variant.node.id, s);
}
fn trans_constants(ccx: @crate_ctxt, crate: @ast::crate) {
- visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
- visit_item: |a| trans_constant(ccx, a),
- ..*visit::default_simple_visitor()
- }));
+ visit::visit_crate(
+ *crate, (),
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_item: |a| trans_constant(ccx, a),
+ ..*visit::default_simple_visitor()
+ }));
}
fn vp2i(cx: block, v: ValueRef) -> ValueRef {
}
fn p2i(ccx: @crate_ctxt, v: ValueRef) -> ValueRef {
- return llvm::LLVMConstPtrToInt(v, ccx.int_type);
+ unsafe {
+ return llvm::LLVMConstPtrToInt(v, ccx.int_type);
+ }
}
fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
T_fn(~[T_i32(), T_i1()], T_i32()));
let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64",
T_fn(~[T_i64(), T_i1()], T_i64()));
+ let bswap16 = decl_cdecl_fn(llmod, ~"llvm.bswap.i16",
+ T_fn(~[T_i16()], T_i16()));
+ let bswap32 = decl_cdecl_fn(llmod, ~"llvm.bswap.i32",
+ T_fn(~[T_i32()], T_i32()));
+ let bswap64 = decl_cdecl_fn(llmod, ~"llvm.bswap.i64",
+ T_fn(~[T_i64()], T_i64()));
let intrinsics = HashMap();
intrinsics.insert(~"llvm.gcroot", gcroot);
intrinsics.insert(~"llvm.cttz.i16", cttz16);
intrinsics.insert(~"llvm.cttz.i32", cttz32);
intrinsics.insert(~"llvm.cttz.i64", cttz64);
+ intrinsics.insert(~"llvm.bswap.i16", bswap16);
+ intrinsics.insert(~"llvm.bswap.i32", bswap32);
+ intrinsics.insert(~"llvm.bswap.i64", bswap64);
return intrinsics;
}
}
}
-fn push_rtcall(ccx: @crate_ctxt, name: ~str, did: ast::def_id) {
- match ccx.rtcalls.find(name) {
- Some(existing_did) if did != existing_did => {
- ccx.sess.fatal(fmt!("multiple definitions for runtime call %s",
- name));
- }
- Some(_) | None => {
- ccx.rtcalls.insert(name, did);
- }
- }
-}
-
-fn gather_local_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
- visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
- visit_item: |item| match item.node {
- ast::item_fn(*) => {
- let attr_metas = attr::attr_metas(
- attr::find_attrs_by_name(item.attrs, ~"rt"));
- for vec::each(attr_metas) |attr_meta| {
- match attr::get_meta_item_list(*attr_meta) {
- Some(list) => {
- let head = vec::head(list);
- let name = attr::get_meta_item_name(head);
- push_rtcall(ccx, name, {crate: ast::local_crate,
- node: item.id});
- }
- None => ()
- }
- }
- }
- _ => ()
- },
- ..*visit::default_simple_visitor()
- }));
-}
-
-fn gather_external_rtcalls(ccx: @crate_ctxt) {
- do cstore::iter_crate_data(ccx.sess.cstore) |_cnum, cmeta| {
- let get_crate_data: decoder::GetCrateDataCb = |cnum| {
- cstore::get_crate_data(ccx.sess.cstore, cnum)
- };
- do decoder::each_path(ccx.sess.intr(), cmeta, get_crate_data) |path| {
- let pathname = path.path_string;
- match path.def_like {
- decoder::dl_def(d) => {
- match d {
- ast::def_fn(did, _) => {
- // FIXME (#2861): This should really iterate attributes
- // like gather_local_rtcalls, but we'll need to
- // export attributes in metadata/encoder before we can do
- // that.
- let sentinel = ~"rt::rt_";
- let slen = str::len(sentinel);
- if str::starts_with(pathname, sentinel) {
- let name = str::substr(pathname,
- slen, str::len(pathname)-slen);
- push_rtcall(ccx, name, did);
- }
- }
- _ => ()
- }
- }
- _ => ()
- }
- true
- }
- }
-}
-
-fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
- gather_local_rtcalls(ccx, crate);
- gather_external_rtcalls(ccx);
-
- // FIXME (#2861): Check for other rtcalls too, once they are
- // supported. Also probably want to check type signature so we don't crash
- // in some obscure place in LLVM if the user provides the wrong signature
- // for an rtcall.
- let expected_rtcalls =
- ~[~"exchange_free", ~"exchange_malloc", ~"fail_", ~"free", ~"malloc"];
- for vec::each(expected_rtcalls) |name| {
- if !ccx.rtcalls.contains_key(*name) {
- fail fmt!("no definition for runtime call %s", *name);
- }
- }
-}
-
fn decl_gc_metadata(ccx: @crate_ctxt, llmod_id: ~str) {
if !ccx.sess.opts.gc || !ccx.uses_gc {
return;
let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
let gc_metadata = do str::as_c_str(gc_metadata_name) |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
+ unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
+ }
};
- llvm::LLVMSetGlobalConstant(gc_metadata, True);
- lib::llvm::SetLinkage(gc_metadata, lib::llvm::ExternalLinkage);
- ccx.module_data.insert(~"_gc_module_metadata", gc_metadata);
+ unsafe {
+ llvm::LLVMSetGlobalConstant(gc_metadata, True);
+ lib::llvm::SetLinkage(gc_metadata, lib::llvm::ExternalLinkage);
+ ccx.module_data.insert(~"_gc_module_metadata", gc_metadata);
+ }
}
fn create_module_map(ccx: @crate_ctxt) -> ValueRef {
let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
let maptype = T_array(elttype, ccx.module_data.size() + 1u);
let map = str::as_c_str(~"_rust_mod_map", |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, maptype, buf)
+ unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod, maptype, buf)
+ }
});
- lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
+ unsafe {
+ lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
+ }
let mut elts: ~[ValueRef] = ~[];
for ccx.module_data.each |key, val| {
let elt = C_struct(~[p2i(ccx, C_cstr(ccx, key)),
}
let term = C_struct(~[C_int(ccx, 0), C_int(ccx, 0)]);
elts.push(term);
- llvm::LLVMSetInitializer(map, C_array(elttype, elts));
+ unsafe {
+ llvm::LLVMSetInitializer(map, C_array(elttype, elts));
+ }
return map;
}
let arrtype = T_array(int_type, n_subcrates as uint);
let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype]);
let map = str::as_c_str(sym_name, |buf| {
- llvm::LLVMAddGlobal(llmod, maptype, buf)
+ unsafe {
+ llvm::LLVMAddGlobal(llmod, maptype, buf)
+ }
});
lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
return map;
~"_" + cstore::get_crate_vers(cstore, i) +
~"_" + cstore::get_crate_hash(cstore, i);
let cr = str::as_c_str(nm, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+ unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
+ }
});
subcrates.push(p2i(ccx, cr));
i += 1;
subcrates.push(C_int(ccx, 0));
let llannihilatefn;
- let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn.get();
+ let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn();
if annihilate_def_id.crate == ast::local_crate {
llannihilatefn = get_item_val(ccx, annihilate_def_id.node);
} else {
annihilate_fn_type);
}
- llvm::LLVMSetInitializer(map, C_struct(
- ~[C_i32(1),
- lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn,
- T_ptr(T_i8())),
- p2i(ccx, create_module_map(ccx)),
- C_array(ccx.int_type, subcrates)]));
+ unsafe {
+ llvm::LLVMSetInitializer(map, C_struct(
+ ~[C_i32(1),
+ lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn,
+ T_ptr(T_i8())),
+ p2i(ccx, create_module_map(ccx)),
+ C_array(ccx.int_type, subcrates)]));
+ }
}
-fn crate_ctxt_to_encode_parms(cx: @crate_ctxt)
- -> encoder::encode_parms {
-
+fn crate_ctxt_to_encode_parms(cx: @crate_ctxt) -> encoder::encode_parms {
+ // XXX: Bad copy of `c`, whatever it is.
let encode_inlined_item =
- |a,b,c,d| astencode::encode_inlined_item(a, b, c, d, cx.maps);
+ |a,b,c,d| astencode::encode_inlined_item(a, b, copy c, d, cx.maps);
return {
diag: cx.sess.diagnostic(),
reexports2: cx.exp_map2,
item_symbols: cx.item_symbols,
discrim_symbols: cx.discrim_symbols,
- link_meta: cx.link_meta,
+ link_meta: /*bad*/copy cx.link_meta,
cstore: cx.sess.cstore,
encode_inlined_item: encode_inlined_item
};
let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
let llconst = C_struct(~[llmeta]);
let mut llglobal = str::as_c_str(~"rust_metadata", |buf| {
- llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst), buf)
- });
- llvm::LLVMSetInitializer(llglobal, llconst);
- str::as_c_str(cx.sess.targ_cfg.target_strs.meta_sect_name, |buf| {
- llvm::LLVMSetSection(llglobal, buf)
+ unsafe {
+ llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst), buf)
+ }
});
- lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
+ unsafe {
+ llvm::LLVMSetInitializer(llglobal, llconst);
+ str::as_c_str(cx.sess.targ_cfg.target_strs.meta_sect_name, |buf| {
+ llvm::LLVMSetSection(llglobal, buf)
+ });
+ lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
- let t_ptr_i8 = T_ptr(T_i8());
- llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8);
- let llvm_used = str::as_c_str(~"llvm.used", |buf| {
- llvm::LLVMAddGlobal(cx.llmod, T_array(t_ptr_i8, 1u), buf)
- });
- lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
- llvm::LLVMSetInitializer(llvm_used, C_array(t_ptr_i8, ~[llglobal]));
+ let t_ptr_i8 = T_ptr(T_i8());
+ llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8);
+ let llvm_used = str::as_c_str(~"llvm.used", |buf| {
+ llvm::LLVMAddGlobal(cx.llmod, T_array(t_ptr_i8, 1u), buf)
+ });
+ lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
+ llvm::LLVMSetInitializer(llvm_used, C_array(t_ptr_i8, ~[llglobal]));
+ }
}
// Writes the current ABI version into the crate.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
let llmod_id = link_meta.name + ~".rc";
- let llmod = str::as_c_str(llmod_id, |buf| {
- llvm::LLVMModuleCreateWithNameInContext
- (buf, llvm::LLVMGetGlobalContext())
- });
- let data_layout = sess.targ_cfg.target_strs.data_layout;
- let targ_triple = sess.targ_cfg.target_strs.target_triple;
- let _: () =
- str::as_c_str(data_layout,
- |buf| llvm::LLVMSetDataLayout(llmod, buf));
- let _: () =
- str::as_c_str(targ_triple,
- |buf| llvm::LLVMSetTarget(llmod, buf));
- let targ_cfg = sess.targ_cfg;
- let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
- let tn = mk_type_names();
- let intrinsics = declare_intrinsics(llmod);
- if sess.opts.extra_debuginfo {
- declare_dbg_intrinsics(llmod, intrinsics);
- }
- let int_type = T_int(targ_cfg);
- let float_type = T_float(targ_cfg);
- let task_type = T_task(targ_cfg);
- let taskptr_type = T_ptr(task_type);
- lib::llvm::associate_type(tn, ~"taskptr", taskptr_type);
- let tydesc_type = T_tydesc(targ_cfg);
- lib::llvm::associate_type(tn, ~"tydesc", tydesc_type);
- let crate_map = decl_crate_map(sess, link_meta, llmod);
- let dbg_cx = if sess.opts.debuginfo {
- option::Some(debuginfo::mk_ctxt(llmod_id, sess.parse_sess.interner))
- } else {
- option::None
- };
+ unsafe {
+ let llmod = str::as_c_str(llmod_id, |buf| {
+ llvm::LLVMModuleCreateWithNameInContext
+ (buf, llvm::LLVMGetGlobalContext())
+ });
+ let data_layout = /*bad*/copy sess.targ_cfg.target_strs.data_layout;
+ let targ_triple = /*bad*/copy sess.targ_cfg.target_strs.target_triple;
+ let _: () =
+ str::as_c_str(data_layout,
+ |buf| llvm::LLVMSetDataLayout(llmod, buf));
+ let _: () =
+ str::as_c_str(targ_triple,
+ |buf| llvm::LLVMSetTarget(llmod, buf));
+ let targ_cfg = sess.targ_cfg;
+ let td = mk_target_data(
+ /*bad*/copy sess.targ_cfg.target_strs.data_layout);
+ let tn = mk_type_names();
+ let intrinsics = declare_intrinsics(llmod);
+ if sess.opts.extra_debuginfo {
+ declare_dbg_intrinsics(llmod, intrinsics);
+ }
+ let int_type = T_int(targ_cfg);
+ let float_type = T_float(targ_cfg);
+ let task_type = T_task(targ_cfg);
+ let taskptr_type = T_ptr(task_type);
+ lib::llvm::associate_type(tn, ~"taskptr", taskptr_type);
+ let tydesc_type = T_tydesc(targ_cfg);
+ lib::llvm::associate_type(tn, ~"tydesc", tydesc_type);
+ let crate_map = decl_crate_map(sess, link_meta, llmod);
+ let dbg_cx = if sess.opts.debuginfo {
+ Some(debuginfo::mk_ctxt(copy llmod_id, sess.parse_sess.interner))
+ } else {
+ None
+ };
- let ccx =
- @{sess: sess,
- llmod: llmod,
- td: td,
- tn: tn,
- externs: HashMap(),
- intrinsics: intrinsics,
- item_vals: HashMap(),
- exp_map2: emap2,
- reachable: reachable,
- item_symbols: HashMap(),
- mut main_fn: None::<ValueRef>,
- link_meta: link_meta,
- enum_sizes: ty::new_ty_hash(),
- discrims: HashMap(),
- discrim_symbols: HashMap(),
- tydescs: ty::new_ty_hash(),
- mut finished_tydescs: false,
- external: HashMap(),
- monomorphized: HashMap(),
- monomorphizing: HashMap(),
- type_use_cache: HashMap(),
- vtables: map::HashMap(),
- const_cstr_cache: HashMap(),
- const_globals: HashMap(),
- const_values: HashMap(),
- module_data: HashMap(),
- lltypes: ty::new_ty_hash(),
- names: new_namegen(sess.parse_sess.interner),
- next_addrspace: new_addrspace_gen(),
- symbol_hasher: symbol_hasher,
- type_hashcodes: ty::new_ty_hash(),
- type_short_names: ty::new_ty_hash(),
- all_llvm_symbols: HashMap(),
- tcx: tcx,
- maps: maps,
- stats:
- {mut n_static_tydescs: 0u,
- mut n_glues_created: 0u,
- mut n_null_glues: 0u,
- mut n_real_glues: 0u,
- mut n_fns: 0u,
- mut n_monos: 0u,
- mut n_inlines: 0u,
- mut n_closures: 0u,
- llvm_insn_ctxt: @mut ~[],
- llvm_insns: HashMap(),
- fn_times: @mut ~[]},
- upcalls:
- upcall::declare_upcalls(targ_cfg, llmod),
- rtcalls: HashMap(),
- tydesc_type: tydesc_type,
- int_type: int_type,
- float_type: float_type,
- task_type: task_type,
- opaque_vec_type: T_opaque_vec(targ_cfg),
- builder: BuilderRef_res(llvm::LLVMCreateBuilder()),
- shape_cx: mk_ctxt(llmod),
- crate_map: crate_map,
- mut uses_gc: false,
- dbg_cx: dbg_cx,
- mut do_not_commit_warning_issued: false};
-
-
- gather_rtcalls(ccx, crate);
+ let ccx = @crate_ctxt {
+ sess: sess,
+ llmod: llmod,
+ td: td,
+ tn: tn,
+ externs: HashMap(),
+ intrinsics: intrinsics,
+ item_vals: HashMap(),
+ exp_map2: emap2,
+ reachable: reachable,
+ item_symbols: HashMap(),
+ mut main_fn: None::<ValueRef>,
+ link_meta: copy link_meta, // XXX: Bad copy.
+ enum_sizes: ty::new_ty_hash(),
+ discrims: HashMap(),
+ discrim_symbols: HashMap(),
+ tydescs: ty::new_ty_hash(),
+ mut finished_tydescs: false,
+ external: HashMap(),
+ monomorphized: HashMap(),
+ monomorphizing: HashMap(),
+ type_use_cache: HashMap(),
+ vtables: map::HashMap(),
+ const_cstr_cache: HashMap(),
+ const_globals: HashMap(),
+ const_values: HashMap(),
+ module_data: HashMap(),
+ lltypes: ty::new_ty_hash(),
+ names: new_namegen(sess.parse_sess.interner),
+ next_addrspace: new_addrspace_gen(),
+ symbol_hasher: symbol_hasher,
+ type_hashcodes: ty::new_ty_hash(),
+ type_short_names: ty::new_ty_hash(),
+ all_llvm_symbols: HashMap(),
+ tcx: tcx,
+ maps: maps,
+ stats:
+ {mut n_static_tydescs: 0u,
+ mut n_glues_created: 0u,
+ mut n_null_glues: 0u,
+ mut n_real_glues: 0u,
+ mut n_fns: 0u,
+ mut n_monos: 0u,
+ mut n_inlines: 0u,
+ mut n_closures: 0u,
+ llvm_insn_ctxt: @mut ~[],
+ llvm_insns: HashMap(),
+ fn_times: @mut ~[]},
+ upcalls: upcall::declare_upcalls(targ_cfg, llmod),
+ tydesc_type: tydesc_type,
+ int_type: int_type,
+ float_type: float_type,
+ task_type: task_type,
+ opaque_vec_type: T_opaque_vec(targ_cfg),
+ builder: BuilderRef_res(unsafe { llvm::LLVMCreateBuilder() }),
+ shape_cx: mk_ctxt(llmod),
+ crate_map: crate_map,
+ mut uses_gc: false,
+ dbg_cx: dbg_cx,
+ mut do_not_commit_warning_issued: false
+ };
- {
- let _icx = ccx.insn_ctxt("data");
- trans_constants(ccx, crate);
- }
+ {
+ let _icx = ccx.insn_ctxt("data");
+ trans_constants(ccx, crate);
+ }
- {
- let _icx = ccx.insn_ctxt("text");
- trans_mod(ccx, crate.node.module);
- }
-
- decl_gc_metadata(ccx, llmod_id);
- fill_crate_map(ccx, crate_map);
- glue::emit_tydescs(ccx);
- write_abi_version(ccx);
-
- // Translate the metadata.
- write_metadata(ccx, crate);
- if ccx.sess.trans_stats() {
- io::println(~"--- trans stats ---");
- io::println(fmt!("n_static_tydescs: %u",
- ccx.stats.n_static_tydescs));
- io::println(fmt!("n_glues_created: %u",
- ccx.stats.n_glues_created));
- io::println(fmt!("n_null_glues: %u", ccx.stats.n_null_glues));
- io::println(fmt!("n_real_glues: %u", ccx.stats.n_real_glues));
-
- io::println(fmt!("n_fns: %u", ccx.stats.n_fns));
- io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
- io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
- io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
- }
-
- if ccx.sess.count_llvm_insns() {
- for ccx.stats.llvm_insns.each |k, v| {
- io::println(fmt!("%-7u %s", v, k));
+ {
+ let _icx = ccx.insn_ctxt("text");
+ trans_mod(ccx, crate.node.module);
+ }
+
+ decl_gc_metadata(ccx, llmod_id);
+ fill_crate_map(ccx, crate_map);
+ glue::emit_tydescs(ccx);
+ write_abi_version(ccx);
+
+ // Translate the metadata.
+ write_metadata(ccx, crate);
+ if ccx.sess.trans_stats() {
+ io::println(~"--- trans stats ---");
+ io::println(fmt!("n_static_tydescs: %u",
+ ccx.stats.n_static_tydescs));
+ io::println(fmt!("n_glues_created: %u",
+ ccx.stats.n_glues_created));
+ io::println(fmt!("n_null_glues: %u", ccx.stats.n_null_glues));
+ io::println(fmt!("n_real_glues: %u", ccx.stats.n_real_glues));
+
+ io::println(fmt!("n_fns: %u", ccx.stats.n_fns));
+ io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
+ io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
+ io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
+ }
+
+ if ccx.sess.count_llvm_insns() {
+ for ccx.stats.llvm_insns.each |k, v| {
+ io::println(fmt!("%-7u %s", v, k));
+ }
}
+ return (llmod, link_meta);
}
- return (llmod, link_meta);
}
//
// Local Variables:
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
use codemap::span;
use lib::llvm::llvm;
use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering};
use libc::{c_uint, c_int};
use middle::trans::common::*;
+use core::cast;
+use core::libc;
+use core::str;
+use core::vec;
use std::map::HashMap;
use syntax::codemap;
fn B(cx: block) -> BuilderRef {
- let b = cx.fcx.ccx.builder.B;
- llvm::LLVMPositionBuilderAtEnd(b, cx.llbb);
- return b;
+ unsafe {
+ let b = cx.fcx.ccx.builder.B;
+ llvm::LLVMPositionBuilderAtEnd(b, cx.llbb);
+ return b;
+ }
}
fn count_insn(cx: block, category: &str) {
let mut s = ~".";
i = 0u;
while i < len {
- let e = v[i];
- i = mm.get(e);
+ let e = /*bad*/copy v[i];
+ i = mm.get(/*bad*/ copy e);
s += ~"/";
s += e;
i += 1u;
// further instructions to the block should simply be ignored.
fn RetVoid(cx: block) {
- if cx.unreachable { return; }
- assert (!cx.terminated);
- cx.terminated = true;
- count_insn(cx, "retvoid");
- llvm::LLVMBuildRetVoid(B(cx));
+ unsafe {
+ if cx.unreachable { return; }
+ assert (!cx.terminated);
+ cx.terminated = true;
+ count_insn(cx, "retvoid");
+ llvm::LLVMBuildRetVoid(B(cx));
+ }
}
fn Ret(cx: block, V: ValueRef) {
- if cx.unreachable { return; }
- assert (!cx.terminated);
- cx.terminated = true;
- count_insn(cx, "ret");
- llvm::LLVMBuildRet(B(cx), V);
+ unsafe {
+ if cx.unreachable { return; }
+ assert (!cx.terminated);
+ cx.terminated = true;
+ count_insn(cx, "ret");
+ llvm::LLVMBuildRet(B(cx), V);
+ }
}
fn AggregateRet(cx: block, RetVals: ~[ValueRef]) {
}
fn Br(cx: block, Dest: BasicBlockRef) {
- if cx.unreachable { return; }
- assert (!cx.terminated);
- cx.terminated = true;
- count_insn(cx, "br");
- llvm::LLVMBuildBr(B(cx), Dest);
+ unsafe {
+ if cx.unreachable { return; }
+ assert (!cx.terminated);
+ cx.terminated = true;
+ count_insn(cx, "br");
+ llvm::LLVMBuildBr(B(cx), Dest);
+ }
}
fn CondBr(cx: block, If: ValueRef, Then: BasicBlockRef,
Else: BasicBlockRef) {
- if cx.unreachable { return; }
- assert (!cx.terminated);
- cx.terminated = true;
- count_insn(cx, "condbr");
- llvm::LLVMBuildCondBr(B(cx), If, Then, Else);
+ unsafe {
+ if cx.unreachable { return; }
+ assert (!cx.terminated);
+ cx.terminated = true;
+ count_insn(cx, "condbr");
+ llvm::LLVMBuildCondBr(B(cx), If, Then, Else);
+ }
}
fn Switch(cx: block, V: ValueRef, Else: BasicBlockRef, NumCases: uint)
-> ValueRef {
- if cx.unreachable { return _Undef(V); }
- assert !cx.terminated;
- cx.terminated = true;
- return llvm::LLVMBuildSwitch(B(cx), V, Else, NumCases as c_uint);
+ unsafe {
+ if cx.unreachable { return _Undef(V); }
+ assert !cx.terminated;
+ cx.terminated = true;
+ return llvm::LLVMBuildSwitch(B(cx), V, Else, NumCases as c_uint);
+ }
}
fn AddCase(S: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef) {
- if llvm::LLVMIsUndef(S) == lib::llvm::True { return; }
- llvm::LLVMAddCase(S, OnVal, Dest);
+ unsafe {
+ if llvm::LLVMIsUndef(S) == lib::llvm::True { return; }
+ llvm::LLVMAddCase(S, OnVal, Dest);
+ }
}
fn IndirectBr(cx: block, Addr: ValueRef, NumDests: uint) {
- if cx.unreachable { return; }
- assert (!cx.terminated);
- cx.terminated = true;
- count_insn(cx, "indirectbr");
- llvm::LLVMBuildIndirectBr(B(cx), Addr, NumDests as c_uint);
+ unsafe {
+ if cx.unreachable { return; }
+ assert (!cx.terminated);
+ cx.terminated = true;
+ count_insn(cx, "indirectbr");
+ llvm::LLVMBuildIndirectBr(B(cx), Addr, NumDests as c_uint);
+ }
}
// This is a really awful way to get a zero-length c-string, but better (and a
}
fn Unreachable(cx: block) {
- if cx.unreachable { return; }
- cx.unreachable = true;
- if !cx.terminated {
- count_insn(cx, "unreachable");
- llvm::LLVMBuildUnreachable(B(cx));
+ unsafe {
+ if cx.unreachable { return; }
+ cx.unreachable = true;
+ if !cx.terminated {
+ count_insn(cx, "unreachable");
+ llvm::LLVMBuildUnreachable(B(cx));
+ }
}
}
fn _Undef(val: ValueRef) -> ValueRef {
- return llvm::LLVMGetUndef(val_ty(val));
+ unsafe {
+ return llvm::LLVMGetUndef(val_ty(val));
+ }
}
/* Arithmetic */
fn Add(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "add");
- return llvm::LLVMBuildAdd(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "add");
+ return llvm::LLVMBuildAdd(B(cx), LHS, RHS, noname());
+ }
}
fn NSWAdd(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "nswadd");
- return llvm::LLVMBuildNSWAdd(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "nswadd");
+ return llvm::LLVMBuildNSWAdd(B(cx), LHS, RHS, noname());
+ }
}
fn NUWAdd(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "nuwadd");
- return llvm::LLVMBuildNUWAdd(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "nuwadd");
+ return llvm::LLVMBuildNUWAdd(B(cx), LHS, RHS, noname());
+ }
}
fn FAdd(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "fadd");
- return llvm::LLVMBuildFAdd(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "fadd");
+ return llvm::LLVMBuildFAdd(B(cx), LHS, RHS, noname());
+ }
}
fn Sub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "sub");
- return llvm::LLVMBuildSub(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "sub");
+ return llvm::LLVMBuildSub(B(cx), LHS, RHS, noname());
+ }
}
fn NSWSub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "nwsub");
- return llvm::LLVMBuildNSWSub(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "nwsub");
+ return llvm::LLVMBuildNSWSub(B(cx), LHS, RHS, noname());
+ }
}
fn NUWSub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "nuwsub");
- return llvm::LLVMBuildNUWSub(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "nuwsub");
+ return llvm::LLVMBuildNUWSub(B(cx), LHS, RHS, noname());
+ }
}
fn FSub(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "sub");
- return llvm::LLVMBuildFSub(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "sub");
+ return llvm::LLVMBuildFSub(B(cx), LHS, RHS, noname());
+ }
}
fn Mul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "mul");
- return llvm::LLVMBuildMul(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "mul");
+ return llvm::LLVMBuildMul(B(cx), LHS, RHS, noname());
+ }
}
fn NSWMul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "nswmul");
- return llvm::LLVMBuildNSWMul(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "nswmul");
+ return llvm::LLVMBuildNSWMul(B(cx), LHS, RHS, noname());
+ }
}
fn NUWMul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "nuwmul");
- return llvm::LLVMBuildNUWMul(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "nuwmul");
+ return llvm::LLVMBuildNUWMul(B(cx), LHS, RHS, noname());
+ }
}
fn FMul(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "fmul");
- return llvm::LLVMBuildFMul(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "fmul");
+ return llvm::LLVMBuildFMul(B(cx), LHS, RHS, noname());
+ }
}
fn UDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "udiv");
- return llvm::LLVMBuildUDiv(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "udiv");
+ return llvm::LLVMBuildUDiv(B(cx), LHS, RHS, noname());
+ }
}
fn SDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "sdiv");
- return llvm::LLVMBuildSDiv(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "sdiv");
+ return llvm::LLVMBuildSDiv(B(cx), LHS, RHS, noname());
+ }
}
fn ExactSDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "extractsdiv");
- return llvm::LLVMBuildExactSDiv(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "extractsdiv");
+ return llvm::LLVMBuildExactSDiv(B(cx), LHS, RHS, noname());
+ }
}
fn FDiv(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "fdiv");
- return llvm::LLVMBuildFDiv(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "fdiv");
+ return llvm::LLVMBuildFDiv(B(cx), LHS, RHS, noname());
+ }
}
fn URem(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "urem");
- return llvm::LLVMBuildURem(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "urem");
+ return llvm::LLVMBuildURem(B(cx), LHS, RHS, noname());
+ }
}
fn SRem(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "srem");
- return llvm::LLVMBuildSRem(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "srem");
+ return llvm::LLVMBuildSRem(B(cx), LHS, RHS, noname());
+ }
}
fn FRem(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "frem");
- return llvm::LLVMBuildFRem(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "frem");
+ return llvm::LLVMBuildFRem(B(cx), LHS, RHS, noname());
+ }
}
fn Shl(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "shl");
- return llvm::LLVMBuildShl(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "shl");
+ return llvm::LLVMBuildShl(B(cx), LHS, RHS, noname());
+ }
}
fn LShr(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "lshr");
- return llvm::LLVMBuildLShr(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "lshr");
+ return llvm::LLVMBuildLShr(B(cx), LHS, RHS, noname());
+ }
}
fn AShr(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "ashr");
- return llvm::LLVMBuildAShr(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "ashr");
+ return llvm::LLVMBuildAShr(B(cx), LHS, RHS, noname());
+ }
}
fn And(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "and");
- return llvm::LLVMBuildAnd(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "and");
+ return llvm::LLVMBuildAnd(B(cx), LHS, RHS, noname());
+ }
}
fn Or(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "or");
- return llvm::LLVMBuildOr(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "or");
+ return llvm::LLVMBuildOr(B(cx), LHS, RHS, noname());
+ }
}
fn Xor(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "xor");
- return llvm::LLVMBuildXor(B(cx), LHS, RHS, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "xor");
+ return llvm::LLVMBuildXor(B(cx), LHS, RHS, noname());
+ }
}
-fn BinOp(cx: block, Op: Opcode, LHS: ValueRef, RHS: ValueRef) ->
- ValueRef {
- if cx.unreachable { return _Undef(LHS); }
- count_insn(cx, "binop");
- return llvm::LLVMBuildBinOp(B(cx), Op, LHS, RHS, noname());
+fn BinOp(cx: block, Op: Opcode, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
+ unsafe {
+ if cx.unreachable { return _Undef(LHS); }
+ count_insn(cx, "binop");
+ return llvm::LLVMBuildBinOp(B(cx), Op, LHS, RHS, noname());
+ }
}
fn Neg(cx: block, V: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(V); }
- count_insn(cx, "neg");
- return llvm::LLVMBuildNeg(B(cx), V, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(V); }
+ count_insn(cx, "neg");
+ return llvm::LLVMBuildNeg(B(cx), V, noname());
+ }
}
fn NSWNeg(cx: block, V: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(V); }
- count_insn(cx, "nswneg");
- return llvm::LLVMBuildNSWNeg(B(cx), V, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(V); }
+ count_insn(cx, "nswneg");
+ return llvm::LLVMBuildNSWNeg(B(cx), V, noname());
+ }
}
fn NUWNeg(cx: block, V: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(V); }
- count_insn(cx, "nuwneg");
- return llvm::LLVMBuildNUWNeg(B(cx), V, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(V); }
+ count_insn(cx, "nuwneg");
+ return llvm::LLVMBuildNUWNeg(B(cx), V, noname());
+ }
}
fn FNeg(cx: block, V: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(V); }
- count_insn(cx, "fneg");
- return llvm::LLVMBuildFNeg(B(cx), V, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(V); }
+ count_insn(cx, "fneg");
+ return llvm::LLVMBuildFNeg(B(cx), V, noname());
+ }
}
fn Not(cx: block, V: ValueRef) -> ValueRef {
- if cx.unreachable { return _Undef(V); }
- count_insn(cx, "not");
- return llvm::LLVMBuildNot(B(cx), V, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(V); }
+ count_insn(cx, "not");
+ return llvm::LLVMBuildNot(B(cx), V, noname());
+ }
}
/* Memory */
fn Malloc(cx: block, Ty: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
- count_insn(cx, "malloc");
- return llvm::LLVMBuildMalloc(B(cx), Ty, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
+ count_insn(cx, "malloc");
+ return llvm::LLVMBuildMalloc(B(cx), Ty, noname());
+ }
}
fn ArrayMalloc(cx: block, Ty: TypeRef, Val: ValueRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
- count_insn(cx, "arraymalloc");
- return llvm::LLVMBuildArrayMalloc(B(cx), Ty, Val, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
+ count_insn(cx, "arraymalloc");
+ return llvm::LLVMBuildArrayMalloc(B(cx), Ty, Val, noname());
+ }
}
fn Alloca(cx: block, Ty: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
- count_insn(cx, "alloca");
- return llvm::LLVMBuildAlloca(B(cx), Ty, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
+ count_insn(cx, "alloca");
+ return llvm::LLVMBuildAlloca(B(cx), Ty, noname());
+ }
}
fn ArrayAlloca(cx: block, Ty: TypeRef, Val: ValueRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
- count_insn(cx, "arrayalloca");
- return llvm::LLVMBuildArrayAlloca(B(cx), Ty, Val, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
+ count_insn(cx, "arrayalloca");
+ return llvm::LLVMBuildArrayAlloca(B(cx), Ty, Val, noname());
+ }
}
fn Free(cx: block, PointerVal: ValueRef) {
- if cx.unreachable { return; }
- count_insn(cx, "free");
- llvm::LLVMBuildFree(B(cx), PointerVal);
+ unsafe {
+ if cx.unreachable { return; }
+ count_insn(cx, "free");
+ llvm::LLVMBuildFree(B(cx), PointerVal);
+ }
}
fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
- let ccx = cx.fcx.ccx;
- if cx.unreachable {
- let ty = val_ty(PointerVal);
- let eltty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Array {
- llvm::LLVMGetElementType(ty) } else { ccx.int_type };
- return llvm::LLVMGetUndef(eltty);
+ unsafe {
+ let ccx = cx.fcx.ccx;
+ if cx.unreachable {
+ let ty = val_ty(PointerVal);
+ let eltty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Array {
+ llvm::LLVMGetElementType(ty) } else { ccx.int_type };
+ return llvm::LLVMGetUndef(eltty);
+ }
+ count_insn(cx, "load");
+ return llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
}
- count_insn(cx, "load");
- return llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
}
fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
- if cx.unreachable { return; }
- debug!("Store %s -> %s",
- val_str(cx.ccx().tn, Val),
- val_str(cx.ccx().tn, Ptr));
- count_insn(cx, "store");
- llvm::LLVMBuildStore(B(cx), Val, Ptr);
+ unsafe {
+ if cx.unreachable { return; }
+ debug!("Store %s -> %s",
+ val_str(cx.ccx().tn, Val),
+ val_str(cx.ccx().tn, Ptr));
+ count_insn(cx, "store");
+ llvm::LLVMBuildStore(B(cx), Val, Ptr);
+ }
}
fn GEP(cx: block, Pointer: ValueRef, Indices: ~[ValueRef]) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
unsafe {
- count_insn(cx, "gep");
- return llvm::LLVMBuildGEP(B(cx), Pointer, vec::raw::to_ptr(Indices),
- Indices.len() as c_uint, noname());
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
+ count_insn(cx, "gep");
+ return llvm::LLVMBuildGEP(B(cx), Pointer, vec::raw::to_ptr(Indices),
+ Indices.len() as c_uint, noname());
}
}
fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) ->
ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
unsafe {
- count_insn(cx, "inboundsgep");
- return llvm::LLVMBuildInBoundsGEP(B(cx), Pointer,
- vec::raw::to_ptr(Indices),
- Indices.len() as c_uint,
- noname());
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
+ unsafe {
+ count_insn(cx, "inboundsgep");
+ return llvm::LLVMBuildInBoundsGEP(B(cx), Pointer,
+ vec::raw::to_ptr(Indices),
+ Indices.len() as c_uint,
+ noname());
+ }
}
}
fn StructGEP(cx: block, Pointer: ValueRef, Idx: uint) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
- count_insn(cx, "structgep");
- return llvm::LLVMBuildStructGEP(B(cx), Pointer, Idx as c_uint, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
+ count_insn(cx, "structgep");
+ return llvm::LLVMBuildStructGEP(B(cx),
+ Pointer,
+ Idx as c_uint,
+ noname());
+ }
}
fn GlobalString(cx: block, _Str: *libc::c_char) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
- count_insn(cx, "globalstring");
- return llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
+ count_insn(cx, "globalstring");
+ return llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
+ }
}
fn GlobalStringPtr(cx: block, _Str: *libc::c_char) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
- count_insn(cx, "globalstringptr");
- return llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
+ count_insn(cx, "globalstringptr");
+ return llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
+ }
}
/* Casts */
fn Trunc(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "trunc");
- return llvm::LLVMBuildTrunc(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "trunc");
+ return llvm::LLVMBuildTrunc(B(cx), Val, DestTy, noname());
+ }
}
fn ZExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "zext");
- return llvm::LLVMBuildZExt(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "zext");
+ return llvm::LLVMBuildZExt(B(cx), Val, DestTy, noname());
+ }
}
fn SExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "sext");
- return llvm::LLVMBuildSExt(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "sext");
+ return llvm::LLVMBuildSExt(B(cx), Val, DestTy, noname());
+ }
}
fn FPToUI(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "fptoui");
- return llvm::LLVMBuildFPToUI(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "fptoui");
+ return llvm::LLVMBuildFPToUI(B(cx), Val, DestTy, noname());
+ }
}
fn FPToSI(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "fptosi");
- return llvm::LLVMBuildFPToSI(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "fptosi");
+ return llvm::LLVMBuildFPToSI(B(cx), Val, DestTy, noname());
+ }
}
fn UIToFP(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "uitofp");
- return llvm::LLVMBuildUIToFP(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "uitofp");
+ return llvm::LLVMBuildUIToFP(B(cx), Val, DestTy, noname());
+ }
}
fn SIToFP(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "sitofp");
- return llvm::LLVMBuildSIToFP(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "sitofp");
+ return llvm::LLVMBuildSIToFP(B(cx), Val, DestTy, noname());
+ }
}
fn FPTrunc(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "fptrunc");
- return llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "fptrunc");
+ return llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy, noname());
+ }
}
fn FPExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "fpext");
- return llvm::LLVMBuildFPExt(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "fpext");
+ return llvm::LLVMBuildFPExt(B(cx), Val, DestTy, noname());
+ }
}
fn PtrToInt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "ptrtoint");
- return llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "ptrtoint");
+ return llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy, noname());
+ }
}
fn IntToPtr(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "inttoptr");
- return llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "inttoptr");
+ return llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy, noname());
+ }
}
fn BitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "bitcast");
- return llvm::LLVMBuildBitCast(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "bitcast");
+ return llvm::LLVMBuildBitCast(B(cx), Val, DestTy, noname());
+ }
}
-fn ZExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) ->
- ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "zextorbitcast");
- return llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy, noname());
+fn ZExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "zextorbitcast");
+ return llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy, noname());
+ }
}
-fn SExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) ->
- ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "sextorbitcast");
- return llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy, noname());
+fn SExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "sextorbitcast");
+ return llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy, noname());
+ }
}
-fn TruncOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) ->
- ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "truncorbitcast");
- return llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy, noname());
+fn TruncOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "truncorbitcast");
+ return llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy, noname());
+ }
}
-fn Cast(cx: block, Op: Opcode, Val: ValueRef, DestTy: TypeRef,
- _Name: *u8) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "cast");
- return llvm::LLVMBuildCast(B(cx), Op, Val, DestTy, noname());
+fn Cast(cx: block, Op: Opcode, Val: ValueRef, DestTy: TypeRef, _: *u8)
+ -> ValueRef {
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "cast");
+ return llvm::LLVMBuildCast(B(cx), Op, Val, DestTy, noname());
+ }
}
fn PointerCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "pointercast");
- return llvm::LLVMBuildPointerCast(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "pointercast");
+ return llvm::LLVMBuildPointerCast(B(cx), Val, DestTy, noname());
+ }
}
fn IntCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "intcast");
- return llvm::LLVMBuildIntCast(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "intcast");
+ return llvm::LLVMBuildIntCast(B(cx), Val, DestTy, noname());
+ }
}
fn FPCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
- count_insn(cx, "fpcast");
- return llvm::LLVMBuildFPCast(B(cx), Val, DestTy, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
+ count_insn(cx, "fpcast");
+ return llvm::LLVMBuildFPCast(B(cx), Val, DestTy, noname());
+ }
}
/* Comparisons */
fn ICmp(cx: block, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef)
- -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
- count_insn(cx, "icmp");
- return llvm::LLVMBuildICmp(B(cx), Op as c_uint, LHS, RHS, noname());
+ -> ValueRef {
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
+ count_insn(cx, "icmp");
+ return llvm::LLVMBuildICmp(B(cx), Op as c_uint, LHS, RHS, noname());
+ }
}
fn FCmp(cx: block, Op: RealPredicate, LHS: ValueRef, RHS: ValueRef)
- -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
- count_insn(cx, "fcmp");
- return llvm::LLVMBuildFCmp(B(cx), Op as c_uint, LHS, RHS, noname());
+ -> ValueRef {
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
+ count_insn(cx, "fcmp");
+ return llvm::LLVMBuildFCmp(B(cx), Op as c_uint, LHS, RHS, noname());
+ }
}
/* Miscellaneous instructions */
fn EmptyPhi(cx: block, Ty: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
- count_insn(cx, "emptyphi");
- return llvm::LLVMBuildPhi(B(cx), Ty, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
+ count_insn(cx, "emptyphi");
+ return llvm::LLVMBuildPhi(B(cx), Ty, noname());
+ }
}
fn Phi(cx: block, Ty: TypeRef, vals: ~[ValueRef], bbs: ~[BasicBlockRef])
- -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
- assert vals.len() == bbs.len();
- let phi = EmptyPhi(cx, Ty);
+ -> ValueRef {
unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
+ assert vals.len() == bbs.len();
+ let phi = EmptyPhi(cx, Ty);
count_insn(cx, "addincoming");
llvm::LLVMAddIncoming(phi, vec::raw::to_ptr(vals),
vec::raw::to_ptr(bbs),
}
fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
- if llvm::LLVMIsUndef(phi) == lib::llvm::True { return; }
unsafe {
+ if llvm::LLVMIsUndef(phi) == lib::llvm::True { return; }
let valptr = cast::reinterpret_cast(&ptr::addr_of(&val));
let bbptr = cast::reinterpret_cast(&ptr::addr_of(&bb));
llvm::LLVMAddIncoming(phi, valptr, bbptr, 1 as c_uint);
}
fn _UndefReturn(cx: block, Fn: ValueRef) -> ValueRef {
- let ccx = cx.fcx.ccx;
- let ty = val_ty(Fn);
- let retty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Integer {
- llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
- count_insn(cx, ~"");
- return llvm::LLVMGetUndef(retty);
+ unsafe {
+ let ccx = cx.fcx.ccx;
+ let ty = val_ty(Fn);
+ let retty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Integer {
+ llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
+ count_insn(cx, ~"");
+ return llvm::LLVMGetUndef(retty);
+ }
}
fn add_span_comment(bcx: block, sp: span, text: ~str) {
if !ccx.sess.no_asm_comments() {
let s = text + ~" (" + ccx.sess.codemap.span_to_str(sp)
+ ~")";
- log(debug, s);
+ log(debug, copy s);
add_comment(bcx, s);
}
}
fn add_comment(bcx: block, text: ~str) {
- let ccx = bcx.ccx();
- if !ccx.sess.no_asm_comments() {
- let sanitized = str::replace(text, ~"$", ~"");
- let comment_text = ~"# " + str::replace(sanitized, ~"\n", ~"\n\t# ");
- let asm = str::as_c_str(comment_text, |c| {
- str::as_c_str(~"", |e| {
- count_insn(bcx, ~"inlineasm");
- llvm::LLVMConstInlineAsm(T_fn(~[], T_void()), c, e,
- False, False)
- })
- });
- Call(bcx, asm, ~[]);
+ unsafe {
+ let ccx = bcx.ccx();
+ if !ccx.sess.no_asm_comments() {
+ let sanitized = str::replace(text, ~"$", ~"");
+ let comment_text = ~"# " +
+ str::replace(sanitized, ~"\n", ~"\n\t# ");
+ let asm = str::as_c_str(comment_text, |c| {
+ str::as_c_str(~"", |e| {
+ count_insn(bcx, ~"inlineasm");
+ llvm::LLVMConstInlineAsm(T_fn(~[], T_void()), c, e,
+ False, False)
+ })
+ });
+ Call(bcx, asm, ~[]);
+ }
}
}
fn Select(cx: block, If: ValueRef, Then: ValueRef, Else: ValueRef) ->
ValueRef {
- if cx.unreachable { return _Undef(Then); }
- count_insn(cx, "select");
- return llvm::LLVMBuildSelect(B(cx), If, Then, Else, noname());
+ unsafe {
+ if cx.unreachable { return _Undef(Then); }
+ count_insn(cx, "select");
+ return llvm::LLVMBuildSelect(B(cx), If, Then, Else, noname());
+ }
}
fn VAArg(cx: block, list: ValueRef, Ty: TypeRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
- count_insn(cx, "vaarg");
- return llvm::LLVMBuildVAArg(B(cx), list, Ty, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
+ count_insn(cx, "vaarg");
+ return llvm::LLVMBuildVAArg(B(cx), list, Ty, noname());
+ }
}
fn ExtractElement(cx: block, VecVal: ValueRef, Index: ValueRef) ->
ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
- count_insn(cx, "extractelement");
- return llvm::LLVMBuildExtractElement(B(cx), VecVal, Index, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
+ count_insn(cx, "extractelement");
+ return llvm::LLVMBuildExtractElement(B(cx), VecVal, Index, noname());
+ }
}
fn InsertElement(cx: block, VecVal: ValueRef, EltVal: ValueRef,
Index: ValueRef) {
- if cx.unreachable { return; }
- count_insn(cx, "insertelement");
- llvm::LLVMBuildInsertElement(B(cx), VecVal, EltVal, Index, noname());
+ unsafe {
+ if cx.unreachable { return; }
+ count_insn(cx, "insertelement");
+ llvm::LLVMBuildInsertElement(B(cx), VecVal, EltVal, Index, noname());
+ }
}
fn ShuffleVector(cx: block, V1: ValueRef, V2: ValueRef,
Mask: ValueRef) {
- if cx.unreachable { return; }
- count_insn(cx, "shufflevector");
- llvm::LLVMBuildShuffleVector(B(cx), V1, V2, Mask, noname());
+ unsafe {
+ if cx.unreachable { return; }
+ count_insn(cx, "shufflevector");
+ llvm::LLVMBuildShuffleVector(B(cx), V1, V2, Mask, noname());
+ }
}
fn ExtractValue(cx: block, AggVal: ValueRef, Index: uint) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
- count_insn(cx, "extractvalue");
- return llvm::LLVMBuildExtractValue(
- B(cx), AggVal, Index as c_uint, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
+ count_insn(cx, "extractvalue");
+ return llvm::LLVMBuildExtractValue(
+ B(cx), AggVal, Index as c_uint, noname());
+ }
}
fn InsertValue(cx: block, AggVal: ValueRef, EltVal: ValueRef,
Index: uint) {
- if cx.unreachable { return; }
- count_insn(cx, "insertvalue");
- llvm::LLVMBuildInsertValue(B(cx), AggVal, EltVal, Index as c_uint,
- noname());
+ unsafe {
+ if cx.unreachable { return; }
+ count_insn(cx, "insertvalue");
+ llvm::LLVMBuildInsertValue(B(cx), AggVal, EltVal, Index as c_uint,
+ noname());
+ }
}
fn IsNull(cx: block, Val: ValueRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
- count_insn(cx, "isnull");
- return llvm::LLVMBuildIsNull(B(cx), Val, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
+ count_insn(cx, "isnull");
+ return llvm::LLVMBuildIsNull(B(cx), Val, noname());
+ }
}
fn IsNotNull(cx: block, Val: ValueRef) -> ValueRef {
- if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
- count_insn(cx, "isnotnull");
- return llvm::LLVMBuildIsNotNull(B(cx), Val, noname());
+ unsafe {
+ if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
+ count_insn(cx, "isnotnull");
+ return llvm::LLVMBuildIsNotNull(B(cx), Val, noname());
+ }
}
fn PtrDiff(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
- let ccx = cx.fcx.ccx;
- if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type); }
- count_insn(cx, "ptrdiff");
- return llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
+ unsafe {
+ let ccx = cx.fcx.ccx;
+ if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type); }
+ count_insn(cx, "ptrdiff");
+ return llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
+ }
}
fn Trap(cx: block) {
- if cx.unreachable { return; }
- let b = B(cx);
- let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(b);
- let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB);
- let M: ModuleRef = llvm::LLVMGetGlobalParent(FN);
- let T: ValueRef = str::as_c_str(~"llvm.trap", |buf| {
- llvm::LLVMGetNamedFunction(M, buf)
- });
- assert (T as int != 0);
- let Args: ~[ValueRef] = ~[];
unsafe {
- count_insn(cx, "trap");
- llvm::LLVMBuildCall(b, T, vec::raw::to_ptr(Args),
- Args.len() as c_uint, noname());
+ if cx.unreachable { return; }
+ let b = B(cx);
+ let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(b);
+ let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB);
+ let M: ModuleRef = llvm::LLVMGetGlobalParent(FN);
+ let T: ValueRef = str::as_c_str(~"llvm.trap", |buf| {
+ llvm::LLVMGetNamedFunction(M, buf)
+ });
+ assert (T as int != 0);
+ let Args: ~[ValueRef] = ~[];
+ unsafe {
+ count_insn(cx, "trap");
+ llvm::LLVMBuildCall(b, T, vec::raw::to_ptr(Args),
+ Args.len() as c_uint, noname());
+ }
}
}
fn LandingPad(cx: block, Ty: TypeRef, PersFn: ValueRef,
NumClauses: uint) -> ValueRef {
- assert !cx.terminated && !cx.unreachable;
- count_insn(cx, "landingpad");
- return llvm::LLVMBuildLandingPad(B(cx), Ty, PersFn,
- NumClauses as c_uint, noname());
+ unsafe {
+ assert !cx.terminated && !cx.unreachable;
+ count_insn(cx, "landingpad");
+ return llvm::LLVMBuildLandingPad(B(cx), Ty, PersFn,
+ NumClauses as c_uint, noname());
+ }
}
fn SetCleanup(cx: block, LandingPad: ValueRef) {
- count_insn(cx, "setcleanup");
- llvm::LLVMSetCleanup(LandingPad, lib::llvm::True);
+ unsafe {
+ count_insn(cx, "setcleanup");
+ llvm::LLVMSetCleanup(LandingPad, lib::llvm::True);
+ }
}
fn Resume(cx: block, Exn: ValueRef) -> ValueRef {
- assert (!cx.terminated);
- cx.terminated = true;
- count_insn(cx, "resume");
- return llvm::LLVMBuildResume(B(cx), Exn);
+ unsafe {
+ assert (!cx.terminated);
+ cx.terminated = true;
+ count_insn(cx, "resume");
+ return llvm::LLVMBuildResume(B(cx), Exn);
+ }
}
// Atomic Operations
fn AtomicCmpXchg(cx: block, dst: ValueRef,
cmp: ValueRef, src: ValueRef,
order: AtomicOrdering) -> ValueRef {
- llvm::LLVMBuildAtomicCmpXchg(B(cx), dst, cmp, src, order)
+ unsafe {
+ llvm::LLVMBuildAtomicCmpXchg(B(cx), dst, cmp, src, order)
+ }
}
fn AtomicRMW(cx: block, op: AtomicBinOp,
dst: ValueRef, src: ValueRef,
order: AtomicOrdering) -> ValueRef {
- llvm::LLVMBuildAtomicRMW(B(cx), op, dst, src, order)
+ unsafe {
+ llvm::LLVMBuildAtomicRMW(B(cx), op, dst, src, order)
+ }
}
//
// and methods are represented as just a fn ptr and not a full
// closure.
+use core::prelude::*;
+
use lib::llvm::ValueRef;
use middle::trans::base::{get_item_val, trans_external_path};
use middle::trans::build::*;
+use middle::trans::callee;
+use middle::trans::closure;
use middle::trans::common::{block, node_id_type_params};
use middle::trans::datum::*;
use middle::trans::datum::Datum;
+use middle::trans::inline;
+use middle::trans::meth;
+use middle::trans::monomorphize;
+use middle::typeck;
use util::common::indenter;
use syntax::ast;
fn trans_fn_ref_with_vtables_to_callee(bcx: block,
def_id: ast::def_id,
ref_id: ast::node_id,
- type_params: ~[ty::t],
+ +type_params: ~[ty::t],
vtables: Option<typeck::vtable_res>)
-> Callee
{
bcx: block, //
def_id: ast::def_id, // def id of fn
ref_id: ast::node_id, // node id of use of fn; may be zero if N/A
- type_params: ~[ty::t], // values for fn's ty params
+ +type_params: ~[ty::t], // values for fn's ty params
vtables: Option<typeck::vtable_res>)
-> FnData
{
DontAutorefArg)
}
-fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: expr::Dest)
- -> block
-{
- let did = bcx.ccx().rtcalls[name];
- return trans_rtcall_or_lang_call(bcx, did, args, dest);
-}
-
fn trans_rtcall_or_lang_call(bcx: block, did: ast::def_id, args: ~[ValueRef],
dest: expr::Dest) -> block {
let fty = if did.crate == ast::local_crate {
bcx, None, fty, rty,
|bcx| {
let callee =
- trans_fn_ref_with_vtables_to_callee(bcx, did, 0, type_params,
+ trans_fn_ref_with_vtables_to_callee(bcx, did, 0,
+ copy type_params,
None);
let new_llval;
fn body_contains_ret(body: ast::blk) -> bool {
let cx = {mut found: false};
- visit::visit_block(body, cx, visit::mk_vt(@{
+ visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor {
visit_item: |_i, _cx, _v| { },
visit_expr: |e: @ast::expr, cx: {mut found: bool}, v| {
if !cx.found {
autoref_arg: AutorefArg) -> block
{
do base::with_scope(in_cx, call_info, ~"call") |cx| {
- let ret_in_loop = match args {
+ let ret_in_loop = match /*bad*/copy args {
ArgExprs(args) => {
args.len() > 0u && match vec::last(args).node {
ast::expr_loop_body(@{
Some(flag)
} else { None };
- let (llfn, llenv) = match callee.data {
- Fn(d) => {
- (d.llfn, llvm::LLVMGetUndef(T_opaque_box_ptr(ccx)))
- }
- Method(d) => {
- // Weird but true: we pass self in the *environment* slot!
- let llself = PointerCast(bcx, d.llself,
- T_opaque_box_ptr(ccx));
- (d.llfn, llself)
- }
- Closure(d) => {
- // Closures are represented as (llfn, llclosure) pair:
- // load the requisite values out.
- let pair = d.to_ref_llval(bcx);
- let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
- let llfn = Load(bcx, llfn);
- let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
- let llenv = Load(bcx, llenv);
- (llfn, llenv)
+ let (llfn, llenv) = unsafe {
+ match callee.data {
+ Fn(d) => {
+ (d.llfn, llvm::LLVMGetUndef(T_opaque_box_ptr(ccx)))
+ }
+ Method(d) => {
+ // Weird but true: we pass self in the *environment* slot!
+ let llself = PointerCast(bcx, d.llself,
+ T_opaque_box_ptr(ccx));
+ (d.llfn, llself)
+ }
+ Closure(d) => {
+ // Closures are represented as (llfn, llclosure) pair:
+ // load the requisite values out.
+ let pair = d.to_ref_llval(bcx);
+ let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
+ let llfn = Load(bcx, llfn);
+ let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
+ let llenv = Load(bcx, llenv);
+ (llfn, llenv)
+ }
}
};
- let args_res = trans_args(bcx, llenv, args, fn_expr_ty,
+ let args_res = trans_args(bcx, llenv, /*bad*/copy args, fn_expr_ty,
dest, ret_flag, autoref_arg);
bcx = args_res.bcx;
- let mut llargs = args_res.args;
+ let mut llargs = /*bad*/copy args_res.args;
let llretslot = args_res.retslot;
bcx = base::invoke(bcx, llfn, llargs);
match dest { // drop the value if it is not being saved.
expr::Ignore => {
- if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
- bcx = glue::drop_ty(bcx, llretslot, ret_ty);
+ unsafe {
+ if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
+ bcx = glue::drop_ty(bcx, llretslot, ret_ty);
+ }
}
}
expr::SaveIn(_) => { }
ArgVals(~[ValueRef])
}
-fn trans_args(cx: block, llenv: ValueRef, args: CallArgs, fn_ty: ty::t,
- dest: expr::Dest, ret_flag: Option<ValueRef>,
+fn trans_args(cx: block,
+ llenv: ValueRef,
+ +args: CallArgs,
+ fn_ty: ty::t,
+ dest: expr::Dest,
+ ret_flag: Option<ValueRef>,
+autoref_arg: AutorefArg)
-> {bcx: block, args: ~[ValueRef], retslot: ValueRef}
{
expr::SaveIn(dst) => dst,
expr::Ignore => {
if ty::type_is_nil(retty) {
- llvm::LLVMGetUndef(T_ptr(T_nil()))
+ unsafe {
+ llvm::LLVMGetUndef(T_ptr(T_nil()))
+ }
} else {
alloc_ty(bcx, retty)
}
Some(_) => {
match arg_expr.node {
ast::expr_loop_body(
- blk@@{node:ast::expr_fn_block(decl, ref body, cap), _}) =>
+ // XXX: Bad copy.
+ blk@@{
+ node: ast::expr_fn_block(copy decl, ref body, cap),
+ _
+ }) =>
{
- let scratch_ty = expr_ty(bcx, blk);
+ let scratch_ty = expr_ty(bcx, arg_expr);
let scratch = alloc_ty(bcx, scratch_ty);
let arg_ty = expr_ty(bcx, arg_expr);
let proto = ty::ty_fn_proto(arg_ty);
let bcx = closure::trans_expr_fn(
- bcx, proto, decl, (*body), blk.id, cap,
- Some(ret_flag), expr::SaveIn(scratch));
+ bcx, proto, decl, /*bad*/copy *body, arg_expr.id,
+ blk.id, cap, Some(ret_flag), expr::SaveIn(scratch));
DatumBlock {bcx: bcx,
datum: Datum {val: scratch,
ty: scratch_ty,
// be inspected. It's important for the value
// to have type lldestty (the callee's expected type).
let llformal_ty = type_of::type_of(ccx, formal_ty.ty);
- val = llvm::LLVMGetUndef(llformal_ty);
+ unsafe {
+ val = llvm::LLVMGetUndef(llformal_ty);
+ }
} else {
// FIXME(#3548) use the adjustments table
match autoref_arg {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use back::abi;
use back::link::{mangle_internal_name_by_path_and_seq};
use back::link::{mangle_internal_name_by_path};
use lib::llvm::llvm;
use lib::llvm::{ValueRef, TypeRef};
+use middle::capture;
use middle::trans::base::*;
use middle::trans::build::*;
+use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::datum::{Datum, INIT, ByRef, ByValue, FromLvalue};
+use middle::trans::expr;
+use middle::trans::glue;
use middle::trans::type_of::*;
use util::ppaux::ty_to_str;
let ccx = bcx.ccx(), tcx = ccx.tcx;
// compute the shape of the closure
- let cdata_ty = mk_closure_tys(tcx, bound_values);
+ // XXX: Bad copy.
+ let cdata_ty = mk_closure_tys(tcx, copy bound_values);
// allocate closure in the heap
let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty);
let ll =
str::as_c_str(~"load_env",
|buf|
- llvm::LLVMAppendBasicBlock(fcx.llfn, buf));
+ unsafe {
+ llvm::LLVMAppendBasicBlock(fcx.llfn, buf)
+ });
fcx.llloadenv = Some(ll);
ll
}
fn trans_expr_fn(bcx: block,
proto: ast::Proto,
- decl: ast::fn_decl,
- body: ast::blk,
- id: ast::node_id,
+ +decl: ast::fn_decl,
+ +body: ast::blk,
+ outer_id: ast::node_id,
+ user_id: ast::node_id,
cap_clause: ast::capture_clause,
is_loop_body: Option<Option<ValueRef>>,
- dest: expr::Dest) -> block {
+ dest: expr::Dest) -> block
+{
+ /*!
+ *
+ * Translates the body of a closure expression.
+ *
+ * - `proto`
+ * - `decl`
+ * - `body`
+ * - `outer_id`: The id of the closure expression with the correct
+ * type. This is usually the same as as `user_id`, but in the
+ * case of a `for` loop, the `outer_id` will have the return
+ * type of boolean, and the `user_id` will have the return type
+ * of `nil`.
+ * - `user_id`: The id of the closure as the user expressed it.
+ Generally the same as `outer_id`
+ * - `cap_clause`: information about captured variables, if any.
+ * - `is_loop_body`: `Some()` if this is part of a `for` loop.
+ * - `dest`: where to write the closure value, which must be a
+ (fn ptr, env) pair
+ */
+
let _icx = bcx.insn_ctxt("closure::trans_expr_fn");
let dest_addr = match dest {
};
let ccx = bcx.ccx();
- let fty = node_id_type(bcx, id);
+ let fty = node_id_type(bcx, outer_id);
let llfnty = type_of_fn_from_ty(ccx, fty);
- let sub_path = vec::append_one(bcx.fcx.path,
+ let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path,
path_name(special_idents::anon));
- let s = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"expr_fn");
+ // XXX: Bad copy.
+ let s = mangle_internal_name_by_path_and_seq(ccx,
+ copy sub_path,
+ ~"expr_fn");
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
- let trans_closure_env = fn@(proto: ast::Proto) -> Result {
- let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto,
+ // XXX: Bad copies.
+ let trans_closure_env = |proto, copy body, copy sub_path, copy decl| {
+ let cap_vars = capture::compute_capture_vars(ccx.tcx, user_id, proto,
cap_clause);
let ret_handle = match is_loop_body { Some(x) => x, None => None };
- let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, proto,
+ // XXX: Bad copy.
+ let {llbox, cdata_ty, bcx} = build_closure(bcx, copy cap_vars, proto,
ret_handle);
- trans_closure(ccx, sub_path, decl, body, llfn, no_self,
- bcx.fcx.param_substs, id, None, |fcx| {
- load_environment(fcx, cdata_ty, cap_vars,
+ trans_closure(ccx, /*bad*/copy sub_path, decl, body, llfn, no_self,
+ /*bad*/copy bcx.fcx.param_substs, user_id, None,
+ |fcx| {
+ load_environment(fcx, cdata_ty, copy cap_vars,
ret_handle.is_some(), proto);
}, |bcx| {
if is_loop_body.is_some() {
}
ast::ProtoBare => {
trans_closure(ccx, sub_path, decl, body, llfn, no_self, None,
- id, None, |_fcx| { }, |_bcx| { });
+ user_id, None, |_fcx| { }, |_bcx| { });
rslt(bcx, C_null(T_opaque_box_ptr(ccx)))
}
};
let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx)));
// Allocate memory, update original ptr, and copy existing data
- let malloc = ~"exchange_malloc";
let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8()));
let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
- let bcx = callee::trans_rtcall(bcx, malloc, ~[opaque_tydesc, sz],
- expr::SaveIn(rval));
+ let bcx = callee::trans_rtcall_or_lang_call(
+ bcx,
+ bcx.tcx().lang_items.exchange_malloc_fn(),
+ ~[opaque_tydesc, sz],
+ expr::SaveIn(rval));
let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
call_memcpy(bcx, cbox_out, cbox_in, sz);
Store(bcx, cbox_out, cboxptr);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
/**
Code that is useful in various trans modules.
*/
-use libc::c_uint;
-use vec::raw::to_ptr;
-use std::map::{HashMap,Set};
-use syntax::{ast, ast_map};
-use driver::session;
-use session::Session;
-use middle::ty;
+use core::prelude::*;
+
use back::{link, abi, upcall};
-use syntax::codemap::span;
-use lib::llvm::{llvm, target_data, type_names, associate_type,
- name_has_type};
+use driver::session;
+use driver::session::Session;
use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
use lib::llvm::{True, False, Bool};
-use metadata::{csearch};
+use lib::llvm::{llvm, target_data, type_names, associate_type, name_has_type};
+use lib;
use metadata::common::link_meta;
+use metadata::{csearch};
+use middle::astencode;
+use middle::resolve;
+use middle::trans::base;
+use middle::trans::build;
+use middle::trans::callee;
+use middle::trans::datum;
+use middle::trans::debuginfo;
+use middle::trans::glue;
+use middle::trans::meth;
+use middle::trans::reachable;
+use middle::trans::shape;
+use middle::trans::type_of;
+use middle::trans::type_use;
+use middle::ty;
+use middle::typeck;
+use util::ppaux::{expr_repr, ty_to_str};
+
+use core::cast;
+use core::cmp;
+use core::hash;
+use core::libc::c_uint;
+use core::ptr;
+use core::str;
+use core::to_bytes;
+use core::vec::raw::to_ptr;
+use core::vec;
+use std::map::{HashMap, Set};
+use syntax::ast::ident;
use syntax::ast_map::path;
-use util::ppaux::ty_to_str;
-use syntax::print::pprust::expr_to_str;
+use syntax::codemap::span;
use syntax::parse::token::ident_interner;
-use syntax::ast::ident;
+use syntax::print::pprust::expr_to_str;
+use syntax::{ast, ast_map};
type namegen = fn@(~str) -> ident;
fn new_namegen(intr: @ident_interner) -> namegen {
return fn@(prefix: ~str) -> ident {
- return intr.gensym(@fmt!("%s_%u", prefix, intr.gensym(@prefix).repr))
+ // XXX: Bad copies.
+ return intr.gensym(@fmt!("%s_%u",
+ prefix,
+ intr.gensym(@copy prefix).repr))
};
}
struct BuilderRef_res {
B: BuilderRef,
- drop { llvm::LLVMDisposeBuilder(self.B); }
+ drop {
+ unsafe {
+ llvm::LLVMDisposeBuilder(self.B);
+ }
+ }
}
fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
}
// Crate context. Every crate we compile has one of these.
-type crate_ctxt = {
+struct crate_ctxt {
sess: session::Session,
llmod: ModuleRef,
td: target_data,
maps: astencode::maps,
stats: stats,
upcalls: @upcall::upcalls,
- rtcalls: HashMap<~str, ast::def_id>,
tydesc_type: TypeRef,
int_type: TypeRef,
float_type: TypeRef,
// is not emitted by LLVM's GC pass when no functions use GC.
mut uses_gc: bool,
dbg_cx: Option<debuginfo::debug_ctxt>,
- mut do_not_commit_warning_issued: bool};
+ mut do_not_commit_warning_issued: bool
+}
// Types used for llself.
struct ValSelfData {
// Here `self_ty` is the real type of the self parameter to this method. It
// will only be set in the case of default methods.
-type param_substs = {tys: ~[ty::t],
- vtables: Option<typeck::vtable_res>,
- bounds: @~[ty::param_bounds],
- self_ty: Option<ty::t>};
+struct param_substs {
+ tys: ~[ty::t],
+ vtables: Option<typeck::vtable_res>,
+ bounds: @~[ty::param_bounds],
+ self_ty: Option<ty::t>
+}
fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str {
fmt!("param_substs {tys:%?, vtables:%?, bounds:%?}",
// Function context. Every LLVM function we create will have one of
// these.
-type fn_ctxt = @{
+struct fn_ctxt_ {
// The ValueRef returned from a call to llvm::LLVMAddFunction; the
// address of the first instruction in the sequence of
// instructions for this function that will go in the .text
// This function's enclosing crate context.
ccx: @crate_ctxt
-};
+}
+
+pub type fn_ctxt = @fn_ctxt_;
fn warn_not_to_commit(ccx: @crate_ctxt, msg: ~str) {
if !ccx.do_not_commit_warning_issued {
fn block_cleanups(bcx: block) -> ~[cleanup] {
match bcx.kind {
block_non_scope => ~[],
- block_scope(ref inf) => (*inf).cleanups
+ block_scope(ref inf) => /*bad*/copy inf.cleanups
}
}
block_non_scope,
}
-type scope_info = {
+struct scope_info {
loop_break: Option<block>,
loop_label: Option<ident>,
// A list of functions that must be run at when leaving this
mut cleanup_paths: ~[cleanup_path],
// Unwinding landing pad. Also cleared when cleanups change.
mut landing_pad: Option<BasicBlockRef>,
-};
+}
trait get_node_info {
fn info() -> Option<node_info>;
return lib::llvm::type_to_str(tn, t);
}
-fn val_ty(v: ValueRef) -> TypeRef { return llvm::LLVMTypeOf(v); }
+fn val_ty(v: ValueRef) -> TypeRef {
+ unsafe {
+ return llvm::LLVMTypeOf(v);
+ }
+}
fn val_str(tn: type_names, v: ValueRef) -> ~str {
return ty_str(tn, val_ty(v));
// Returns the nth element of the given LLVM structure type.
fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
- let elt_count = llvm::LLVMCountStructElementTypes(llstructty) as uint;
- assert (n < elt_count);
- let mut elt_tys = vec::from_elem(elt_count, T_nil());
- llvm::LLVMGetStructElementTypes(llstructty,
- ptr::to_mut_unsafe_ptr(&mut elt_tys[0]));
- return llvm::LLVMGetElementType(elt_tys[n]);
+ unsafe {
+ let elt_count = llvm::LLVMCountStructElementTypes(llstructty) as uint;
+ assert (n < elt_count);
+ let mut elt_tys = vec::from_elem(elt_count, T_nil());
+ llvm::LLVMGetStructElementTypes(
+ llstructty,
+ ptr::to_mut_unsafe_ptr(&mut elt_tys[0]));
+ return llvm::LLVMGetElementType(elt_tys[n]);
+ }
}
fn in_scope_cx(cx: block, f: fn(scope_info)) {
}
fn expr_to_str(e: @ast::expr) -> ~str {
- util::ppaux::expr_repr(self.tcx(), e)
+ expr_repr(self.tcx(), e)
}
fn expr_is_lval(e: @ast::expr) -> bool {
// LLVM type constructors.
fn T_void() -> TypeRef {
- // Note: For the time being llvm is kinda busted here, it has the notion
- // of a 'void' type that can only occur as part of the signature of a
- // function, but no general unit type of 0-sized value. This is, afaict,
- // vestigial from its C heritage, and we'll be attempting to submit a
- // patch upstream to fix it. In the mean time we only model function
- // outputs (Rust functions and C functions) using T_void, and model the
- // Rust general purpose nil type you can construct as 1-bit (always
- // zero). This makes the result incorrect for now -- things like a tuple
- // of 10 nil values will have 10-bit size -- but it doesn't seem like we
- // have any other options until it's fixed upstream.
-
- return llvm::LLVMVoidType();
+ unsafe {
+ return llvm::LLVMVoidType();
+ }
}
fn T_nil() -> TypeRef {
- // NB: See above in T_void().
-
- return llvm::LLVMInt1Type();
+ return T_struct(~[])
}
-fn T_metadata() -> TypeRef { return llvm::LLVMMetadataType(); }
+fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
-fn T_i1() -> TypeRef { return llvm::LLVMInt1Type(); }
+fn T_i1() -> TypeRef { unsafe { return llvm::LLVMInt1Type(); } }
-fn T_i8() -> TypeRef { return llvm::LLVMInt8Type(); }
+fn T_i8() -> TypeRef { unsafe { return llvm::LLVMInt8Type(); } }
-fn T_i16() -> TypeRef { return llvm::LLVMInt16Type(); }
+fn T_i16() -> TypeRef { unsafe { return llvm::LLVMInt16Type(); } }
-fn T_i32() -> TypeRef { return llvm::LLVMInt32Type(); }
+fn T_i32() -> TypeRef { unsafe { return llvm::LLVMInt32Type(); } }
-fn T_i64() -> TypeRef { return llvm::LLVMInt64Type(); }
+fn T_i64() -> TypeRef { unsafe { return llvm::LLVMInt64Type(); } }
-fn T_f32() -> TypeRef { return llvm::LLVMFloatType(); }
+fn T_f32() -> TypeRef { unsafe { return llvm::LLVMFloatType(); } }
-fn T_f64() -> TypeRef { return llvm::LLVMDoubleType(); }
+fn T_f64() -> TypeRef { unsafe { return llvm::LLVMDoubleType(); } }
fn T_bool() -> TypeRef { return T_i1(); }
}
fn T_ptr(t: TypeRef) -> TypeRef {
- return llvm::LLVMPointerType(t, default_addrspace);
+ unsafe {
+ return llvm::LLVMPointerType(t, default_addrspace);
+ }
}
fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
- return llvm::LLVMPointerType(t, addrspace);
+ unsafe {
+ return llvm::LLVMPointerType(t, addrspace);
+ }
}
fn T_struct(elts: ~[TypeRef]) -> TypeRef unsafe {
- return llvm::LLVMStructType(to_ptr(elts), elts.len() as c_uint, False);
+ unsafe {
+ return llvm::LLVMStructType(to_ptr(elts),
+ elts.len() as c_uint,
+ False);
+ }
}
fn T_named_struct(name: ~str) -> TypeRef {
- let c = llvm::LLVMGetGlobalContext();
- return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf));
+ unsafe {
+ let c = llvm::LLVMGetGlobalContext();
+ return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf));
+ }
}
fn set_struct_body(t: TypeRef, elts: ~[TypeRef]) unsafe {
- llvm::LLVMStructSetBody(t, to_ptr(elts),
- elts.len() as c_uint, False);
+ unsafe {
+ llvm::LLVMStructSetBody(t,
+ to_ptr(elts),
+ elts.len() as c_uint,
+ False);
+ }
}
fn T_empty_struct() -> TypeRef { return T_struct(~[]); }
fn T_tydesc_field(cx: @crate_ctxt, field: uint) -> TypeRef unsafe {
// Bit of a kludge: pick the fn typeref out of the tydesc..
- let mut tydesc_elts: ~[TypeRef] =
- vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
- T_nil());
- llvm::LLVMGetStructElementTypes(
- cx.tydesc_type,
- ptr::to_mut_unsafe_ptr(&mut tydesc_elts[0]));
- let t = llvm::LLVMGetElementType(tydesc_elts[field]);
- return t;
+ unsafe {
+ let mut tydesc_elts: ~[TypeRef] =
+ vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
+ T_nil());
+ llvm::LLVMGetStructElementTypes(
+ cx.tydesc_type,
+ ptr::to_mut_unsafe_ptr(&mut tydesc_elts[0]));
+ let t = llvm::LLVMGetElementType(tydesc_elts[field]);
+ return t;
+ }
}
fn T_generic_glue_fn(cx: @crate_ctxt) -> TypeRef {
}
fn T_array(t: TypeRef, n: uint) -> TypeRef {
- return llvm::LLVMArrayType(t, n as c_uint);
+ unsafe {
+ return llvm::LLVMArrayType(t, n as c_uint);
+ }
}
// Interior vector.
}
fn T_box_ptr(t: TypeRef) -> TypeRef {
- return llvm::LLVMPointerType(t, gc_box_addrspace);
+ unsafe {
+ return llvm::LLVMPointerType(t, gc_box_addrspace);
+ }
}
fn T_opaque_box(cx: @crate_ctxt) -> TypeRef {
}
fn T_unique_ptr(t: TypeRef) -> TypeRef {
- return llvm::LLVMPointerType(t, gc_box_addrspace);
+ unsafe {
+ return llvm::LLVMPointerType(t, gc_box_addrspace);
+ }
}
fn T_port(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {
// LLVM constant constructors.
-fn C_null(t: TypeRef) -> ValueRef { return llvm::LLVMConstNull(t); }
+fn C_null(t: TypeRef) -> ValueRef {
+ unsafe {
+ return llvm::LLVMConstNull(t);
+ }
+}
fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
- return llvm::LLVMConstInt(t, u, sign_extend);
+ unsafe {
+ return llvm::LLVMConstInt(t, u, sign_extend);
+ }
}
fn C_floating(s: ~str, t: TypeRef) -> ValueRef {
- return str::as_c_str(s, |buf| llvm::LLVMConstRealOfString(t, buf));
+ unsafe {
+ return str::as_c_str(s, |buf| llvm::LLVMConstRealOfString(t, buf));
+ }
}
fn C_nil() -> ValueRef {
- // NB: See comment above in T_void().
-
- return C_integral(T_i1(), 0u64, False);
+ return C_struct(~[]);
}
fn C_bool(b: bool) -> ValueRef {
// This is a 'c-like' raw string, which differs from
// our boxed-and-length-annotated strings.
-fn C_cstr(cx: @crate_ctxt, s: ~str) -> ValueRef {
- match cx.const_cstr_cache.find(s) {
- Some(llval) => return llval,
- None => ()
- }
+fn C_cstr(cx: @crate_ctxt, +s: ~str) -> ValueRef {
+ unsafe {
+ match cx.const_cstr_cache.find(s) {
+ Some(llval) => return llval,
+ None => ()
+ }
- let sc = do str::as_c_str(s) |buf| {
- llvm::LLVMConstString(buf, str::len(s) as c_uint, False)
- };
- let g =
- str::as_c_str(fmt!("str%u", (cx.names)(~"str").repr),
- |buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf));
- llvm::LLVMSetInitializer(g, sc);
- llvm::LLVMSetGlobalConstant(g, True);
- lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
+ let sc = do str::as_c_str(s) |buf| {
+ llvm::LLVMConstString(buf, str::len(s) as c_uint, False)
+ };
+ let g =
+ str::as_c_str(fmt!("str%u", (cx.names)(~"str").repr),
+ |buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf));
+ llvm::LLVMSetInitializer(g, sc);
+ llvm::LLVMSetGlobalConstant(g, True);
+ lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
- cx.const_cstr_cache.insert(s, g);
+ cx.const_cstr_cache.insert(s, g);
- return g;
+ return g;
+ }
}
-fn C_estr_slice(cx: @crate_ctxt, s: ~str) -> ValueRef {
- let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
- C_struct(~[cs, C_uint(cx, str::len(s) + 1u /* +1 for null */)])
+// NB: Do not use `do_spill_noroot` to make this into a constant string, or
+// you will be kicked off fast isel. See issue #4352 for an example of this.
+fn C_estr_slice(cx: @crate_ctxt, +s: ~str) -> ValueRef {
+ unsafe {
+ let len = str::len(s);
+ let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
+ C_struct(~[cs, C_uint(cx, len + 1u /* +1 for null */)])
+ }
}
// Returns a Plain Old LLVM String:
fn C_postr(s: ~str) -> ValueRef {
- return do str::as_c_str(s) |buf| {
- llvm::LLVMConstString(buf, str::len(s) as c_uint, False)
- };
+ unsafe {
+ return do str::as_c_str(s) |buf| {
+ llvm::LLVMConstString(buf, str::len(s) as c_uint, False)
+ };
+ }
}
fn C_zero_byte_arr(size: uint) -> ValueRef unsafe {
- let mut i = 0u;
- let mut elts: ~[ValueRef] = ~[];
- while i < size { elts.push(C_u8(0u)); i += 1u; }
- return llvm::LLVMConstArray(T_i8(), vec::raw::to_ptr(elts),
- elts.len() as c_uint);
+ unsafe {
+ let mut i = 0u;
+ let mut elts: ~[ValueRef] = ~[];
+ while i < size { elts.push(C_u8(0u)); i += 1u; }
+ return llvm::LLVMConstArray(T_i8(),
+ vec::raw::to_ptr(elts),
+ elts.len() as c_uint);
+ }
}
fn C_struct(elts: &[ValueRef]) -> ValueRef {
- do vec::as_imm_buf(elts) |ptr, len| {
- llvm::LLVMConstStruct(ptr, len as c_uint, False)
+ unsafe {
+ do vec::as_imm_buf(elts) |ptr, len| {
+ llvm::LLVMConstStruct(ptr, len as c_uint, False)
+ }
}
}
fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
- do vec::as_imm_buf(elts) |ptr, len| {
- llvm::LLVMConstNamedStruct(T, ptr, len as c_uint)
+ unsafe {
+ do vec::as_imm_buf(elts) |ptr, len| {
+ llvm::LLVMConstNamedStruct(T, ptr, len as c_uint)
+ }
}
}
fn C_array(ty: TypeRef, elts: ~[ValueRef]) -> ValueRef unsafe {
- return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
- elts.len() as c_uint);
+ unsafe {
+ return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
+ elts.len() as c_uint);
+ }
}
fn C_bytes(bytes: ~[u8]) -> ValueRef unsafe {
- return llvm::LLVMConstString(
- cast::reinterpret_cast(&vec::raw::to_ptr(bytes)),
- bytes.len() as c_uint, True);
+ unsafe {
+ return llvm::LLVMConstString(
+ cast::reinterpret_cast(&vec::raw::to_ptr(bytes)),
+ bytes.len() as c_uint, True);
+ }
}
fn C_bytes_plus_null(bytes: ~[u8]) -> ValueRef unsafe {
- return llvm::LLVMConstString(
- cast::reinterpret_cast(&vec::raw::to_ptr(bytes)),
- bytes.len() as c_uint, False);
+ unsafe {
+ return llvm::LLVMConstString(
+ cast::reinterpret_cast(&vec::raw::to_ptr(bytes)),
+ bytes.len() as c_uint, False);
+ }
}
-fn C_shape(ccx: @crate_ctxt, bytes: ~[u8]) -> ValueRef {
- let llshape = C_bytes_plus_null(bytes);
- let name = fmt!("shape%u", (ccx.names)(~"shape").repr);
- let llglobal = str::as_c_str(name, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
- });
- llvm::LLVMSetInitializer(llglobal, llshape);
- llvm::LLVMSetGlobalConstant(llglobal, True);
- lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
- return llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
+fn C_shape(ccx: @crate_ctxt, +bytes: ~[u8]) -> ValueRef {
+ unsafe {
+ let llshape = C_bytes_plus_null(bytes);
+ let name = fmt!("shape%u", (ccx.names)(~"shape").repr);
+ let llglobal = str::as_c_str(name, |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
+ });
+ llvm::LLVMSetInitializer(llglobal, llshape);
+ llvm::LLVMSetGlobalConstant(llglobal, True);
+ lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
+ return llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
+ }
}
fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
- llvm::LLVMGetParam(fndecl, param as c_uint)
+ unsafe {
+ llvm::LLVMGetParam(fndecl, param as c_uint)
+ }
}
// Used to identify cached monomorphized functions and vtables
datum::DatumMode),
}
-type mono_id_ = {
+struct mono_id_ {
def: ast::def_id,
params: ~[mono_param_id],
impl_did_opt: Option<ast::def_id>
-};
+}
type mono_id = @mono_id_;
impl mono_param_id : cmp::Eq {
pure fn eq(&self, other: &mono_param_id) -> bool {
- match ((*self), (*other)) {
- (mono_precise(ty_a, ids_a), mono_precise(ty_b, ids_b)) => {
+ match (self, other) {
+ (&mono_precise(ty_a, ref ids_a),
+ &mono_precise(ty_b, ref ids_b)) => {
ty_a == ty_b && ids_a == ids_b
}
- (mono_any, mono_any) => true,
- (mono_repr(size_a, align_a, is_float_a, mode_a),
- mono_repr(size_b, align_b, is_float_b, mode_b)) => {
+ (&mono_any, &mono_any) => true,
+ (&mono_repr(size_a, align_a, is_float_a, mode_a),
+ &mono_repr(size_b, align_b, is_float_b, mode_b)) => {
size_a == size_b && align_a == align_b &&
is_float_a == is_float_b && mode_a == mode_b
}
- (mono_precise(*), _) => false,
- (mono_any, _) => false,
- (mono_repr(*), _) => false
+ (&mono_precise(*), _) => false,
+ (&mono_any, _) => false,
+ (&mono_repr(*), _) => false
}
}
pure fn ne(&self, other: &mono_param_id) -> bool { !(*self).eq(other) }
impl mono_param_id : to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
- match *self {
+ match /*bad*/copy *self {
mono_precise(t, mids) =>
to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), &mids, lsb0, f),
}
}
-impl mono_id_ : core::to_bytes::IterBytes {
+impl mono_id_ : to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f);
}
}
fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
- match bcx.fcx.param_substs {
+ match /*bad*/copy bcx.fcx.param_substs {
Some(substs) => {
ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
}
fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
let tcx = bcx.tcx();
let params = ty::node_id_to_type_params(tcx, id);
- match bcx.fcx.param_substs {
+ match /*bad*/copy bcx.fcx.param_substs {
Some(substs) => {
do vec::map(params) |t| {
ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
-> typeck::vtable_res
{
- @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, *d))
+ @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d))
}
// Apply the typaram substitutions in the fn_ctxt to a vtable. This should
// eliminate any vtable_params.
-fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
+fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin)
-> typeck::vtable_origin
{
let tcx = fcx.ccx.tcx;
match vt {
typeck::vtable_static(trait_id, tys, sub) => {
- let tys = match fcx.param_substs {
+ let tys = match /*bad*/copy fcx.param_substs {
Some(substs) => {
do vec::map(tys) |t| {
ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
}
_ => {
tcx.sess.bug(fmt!(
- "resolve_vtable_in_fn_ctxt: asked to lookup %? but \
- no vtables in the fn_ctxt!", vt))
+ "resolve_vtable_in_fn_ctxt: asked to lookup but \
+ no vtables in the fn_ctxt!"))
}
}
}
- _ => vt
+ vt => vt
}
}
let vtables_to_skip =
ty::count_traits_and_supertraits(tcx, first_n_bounds);
let vtable_off = vtables_to_skip + n_bound;
- ps.vtables.get()[vtable_off]
+ /*bad*/ copy ps.vtables.get()[vtable_off]
}
-fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
+fn dummy_substs(+tps: ~[ty::t]) -> ty::substs {
{self_r: Some(ty::re_bound(ty::br_self)),
self_ty: None,
tps: tps}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::const_eval;
use middle::trans::base::get_insn_ctxt;
use middle::trans::common::*;
+use middle::trans::consts;
+use middle::trans::expr;
+use middle::ty;
use syntax::{ast, ast_util, codemap, ast_map};
~"integer literal doesn't have a type")
}
}
- ast::lit_float(fs, t) => C_floating(*fs, T_float_ty(cx, t)),
+ ast::lit_float(fs, t) => C_floating(/*bad*/copy *fs, T_float_ty(cx, t)),
ast::lit_float_unsuffixed(fs) => {
let lit_float_ty = ty::node_id_to_type(cx.tcx, e.id);
match ty::get(lit_float_ty).sty {
ty::ty_float(t) => {
- C_floating(*fs, T_float_ty(cx, t))
+ C_floating(/*bad*/copy *fs, T_float_ty(cx, t))
}
_ => {
cx.sess.span_bug(lit.span,
}
ast::lit_bool(b) => C_bool(b),
ast::lit_nil => C_nil(),
- ast::lit_str(s) => C_estr_slice(cx, *s)
+ ast::lit_str(s) => C_estr_slice(cx, /*bad*/copy *s)
}
}
fn const_ptrcast(cx: @crate_ctxt, a: ValueRef, t: TypeRef) -> ValueRef {
- let b = llvm::LLVMConstPointerCast(a, T_ptr(t));
- assert cx.const_globals.insert(b as int, a);
- b
+ unsafe {
+ let b = llvm::LLVMConstPointerCast(a, T_ptr(t));
+ assert cx.const_globals.insert(b as int, a);
+ b
+ }
}
fn const_vec(cx: @crate_ctxt, e: @ast::expr, es: &[@ast::expr])
-> (ValueRef, ValueRef, TypeRef) {
- let vec_ty = ty::expr_ty(cx.tcx, e);
- let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
- let llunitty = type_of::type_of(cx, unit_ty);
- let v = C_array(llunitty, es.map(|e| const_expr(cx, *e)));
- let unit_sz = shape::llsize_of(cx, llunitty);
- let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz);
- return (v, sz, llunitty);
+ unsafe {
+ let vec_ty = ty::expr_ty(cx.tcx, e);
+ let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
+ let llunitty = type_of::type_of(cx, unit_ty);
+ let v = C_array(llunitty, es.map(|e| const_expr(cx, *e)));
+ let unit_sz = shape::llsize_of(cx, llunitty);
+ let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz);
+ return (v, sz, llunitty);
+ }
}
fn const_deref(cx: @crate_ctxt, v: ValueRef) -> ValueRef {
- let v = match cx.const_globals.find(v as int) {
- Some(v) => v,
- None => v
- };
- assert llvm::LLVMIsGlobalConstant(v) == True;
- let v = llvm::LLVMGetInitializer(v);
- v
+ unsafe {
+ let v = match cx.const_globals.find(v as int) {
+ Some(v) => v,
+ None => v
+ };
+ assert llvm::LLVMIsGlobalConstant(v) == True;
+ let v = llvm::LLVMGetInitializer(v);
+ v
+ }
}
fn const_get_elt(cx: @crate_ctxt, v: ValueRef, us: &[c_uint]) -> ValueRef {
- let r = do vec::as_imm_buf(us) |p, len| {
- llvm::LLVMConstExtractValue(v, p, len as c_uint)
- };
+ unsafe {
+ let r = do vec::as_imm_buf(us) |p, len| {
+ llvm::LLVMConstExtractValue(v, p, len as c_uint)
+ };
- debug!("const_get_elt(v=%s, us=%?, r=%s)",
- val_str(cx.tn, v), us, val_str(cx.tn, r));
+ debug!("const_get_elt(v=%s, us=%?, r=%s)",
+ val_str(cx.tn, v), us, val_str(cx.tn, r));
- return r;
+ return r;
+ }
}
fn const_autoderef(cx: @crate_ctxt, ty: ty::t, v: ValueRef)
}
fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
- let _icx = cx.insn_ctxt("const_expr");
- return match e.node {
- ast::expr_lit(lit) => consts::const_lit(cx, e, *lit),
- ast::expr_binary(b, e1, e2) => {
- let te1 = const_expr(cx, e1);
- let te2 = const_expr(cx, e2);
+ unsafe {
+ let _icx = cx.insn_ctxt("const_expr");
+ return match /*bad*/copy e.node {
+ ast::expr_lit(lit) => consts::const_lit(cx, e, *lit),
+ ast::expr_binary(b, e1, e2) => {
+ let te1 = const_expr(cx, e1);
+ let te2 = const_expr(cx, e2);
- let te2 = base::cast_shift_const_rhs(b, te1, te2);
+ let te2 = base::cast_shift_const_rhs(b, te1, te2);
- /* Neither type is bottom, and we expect them to be unified already,
- * so the following is safe. */
- let ty = ty::expr_ty(cx.tcx, e1);
- let is_float = ty::type_is_fp(ty);
- let signed = ty::type_is_signed(ty);
- return match b {
- ast::add => {
- if is_float { llvm::LLVMConstFAdd(te1, te2) }
- else { llvm::LLVMConstAdd(te1, te2) }
- }
- ast::subtract => {
- if is_float { llvm::LLVMConstFSub(te1, te2) }
- else { llvm::LLVMConstSub(te1, te2) }
- }
- ast::mul => {
- if is_float { llvm::LLVMConstFMul(te1, te2) }
- else { llvm::LLVMConstMul(te1, te2) }
- }
- ast::div => {
- if is_float { llvm::LLVMConstFDiv(te1, te2) }
- else if signed { llvm::LLVMConstSDiv(te1, te2) }
- else { llvm::LLVMConstUDiv(te1, te2) }
- }
- ast::rem => {
- if is_float { llvm::LLVMConstFRem(te1, te2) }
- else if signed { llvm::LLVMConstSRem(te1, te2) }
- else { llvm::LLVMConstURem(te1, te2) }
- }
- ast::and |
- ast::or => cx.sess.span_unimpl(e.span, ~"binop logic"),
- ast::bitxor => llvm::LLVMConstXor(te1, te2),
- ast::bitand => llvm::LLVMConstAnd(te1, te2),
- ast::bitor => llvm::LLVMConstOr(te1, te2),
- ast::shl => llvm::LLVMConstShl(te1, te2),
- ast::shr => {
- if signed { llvm::LLVMConstAShr(te1, te2) }
- else { llvm::LLVMConstLShr(te1, te2) }
+ /* Neither type is bottom, and we expect them to be unified
+ * already, so the following is safe. */
+ let ty = ty::expr_ty(cx.tcx, e1);
+ let is_float = ty::type_is_fp(ty);
+ let signed = ty::type_is_signed(ty);
+ return match b {
+ ast::add => {
+ if is_float { llvm::LLVMConstFAdd(te1, te2) }
+ else { llvm::LLVMConstAdd(te1, te2) }
+ }
+ ast::subtract => {
+ if is_float { llvm::LLVMConstFSub(te1, te2) }
+ else { llvm::LLVMConstSub(te1, te2) }
+ }
+ ast::mul => {
+ if is_float { llvm::LLVMConstFMul(te1, te2) }
+ else { llvm::LLVMConstMul(te1, te2) }
+ }
+ ast::div => {
+ if is_float { llvm::LLVMConstFDiv(te1, te2) }
+ else if signed { llvm::LLVMConstSDiv(te1, te2) }
+ else { llvm::LLVMConstUDiv(te1, te2) }
+ }
+ ast::rem => {
+ if is_float { llvm::LLVMConstFRem(te1, te2) }
+ else if signed { llvm::LLVMConstSRem(te1, te2) }
+ else { llvm::LLVMConstURem(te1, te2) }
+ }
+ ast::and |
+ ast::or => cx.sess.span_unimpl(e.span, ~"binop logic"),
+ ast::bitxor => llvm::LLVMConstXor(te1, te2),
+ ast::bitand => llvm::LLVMConstAnd(te1, te2),
+ ast::bitor => llvm::LLVMConstOr(te1, te2),
+ ast::shl => llvm::LLVMConstShl(te1, te2),
+ ast::shr => {
+ if signed { llvm::LLVMConstAShr(te1, te2) }
+ else { llvm::LLVMConstLShr(te1, te2) }
+ }
+ ast::eq |
+ ast::lt |
+ ast::le |
+ ast::ne |
+ ast::ge |
+ ast::gt => cx.sess.span_unimpl(e.span, ~"binop comparator")
+ }
}
- ast::eq |
- ast::lt |
- ast::le |
- ast::ne |
- ast::ge |
- ast::gt => cx.sess.span_unimpl(e.span, ~"binop comparator")
- }
- }
- ast::expr_unary(u, e) => {
- let te = const_expr(cx, e);
- let ty = ty::expr_ty(cx.tcx, e);
- let is_float = ty::type_is_fp(ty);
- return match u {
- ast::box(_) |
- ast::uniq(_) |
- ast::deref => const_deref(cx, te),
- ast::not => llvm::LLVMConstNot(te),
- ast::neg => {
- if is_float { llvm::LLVMConstFNeg(te) }
- else { llvm::LLVMConstNeg(te) }
+ ast::expr_unary(u, e) => {
+ let te = const_expr(cx, e);
+ let ty = ty::expr_ty(cx.tcx, e);
+ let is_float = ty::type_is_fp(ty);
+ return match u {
+ ast::box(_) |
+ ast::uniq(_) |
+ ast::deref => const_deref(cx, te),
+ ast::not => llvm::LLVMConstNot(te),
+ ast::neg => {
+ if is_float { llvm::LLVMConstFNeg(te) }
+ else { llvm::LLVMConstNeg(te) }
+ }
+ }
}
- }
- }
- ast::expr_field(base, field, _) => {
- let bt = ty::expr_ty(cx.tcx, base);
- let bv = const_expr(cx, base);
- let (bt, bv) = const_autoderef(cx, bt, bv);
- do expr::with_field_tys(cx.tcx, bt, None) |_has_dtor, field_tys| {
- let ix = ty::field_idx_strict(cx.tcx, field, field_tys);
+ ast::expr_field(base, field, _) => {
+ let bt = ty::expr_ty(cx.tcx, base);
+ let bv = const_expr(cx, base);
+ let (bt, bv) = const_autoderef(cx, bt, bv);
+ do expr::with_field_tys(cx.tcx, bt, None) |_, field_tys| {
+ let ix = ty::field_idx_strict(cx.tcx, field, field_tys);
- // Note: ideally, we'd use `struct_field()` here instead
- // of hardcoding [0, ix], but we can't because it yields
- // the wrong type and also inserts an extra 0 that is
- // not needed in the constant variety:
- const_get_elt(cx, bv, [0, ix as c_uint])
+ // Note: ideally, we'd use `struct_field()` here instead
+ // of hardcoding [0, ix], but we can't because it yields
+ // the wrong type and also inserts an extra 0 that is
+ // not needed in the constant variety:
+ const_get_elt(cx, bv, [0, ix as c_uint])
+ }
}
- }
- ast::expr_index(base, index) => {
- let bt = ty::expr_ty(cx.tcx, base);
- let bv = const_expr(cx, base);
- let (bt, bv) = const_autoderef(cx, bt, bv);
- let iv = match const_eval::eval_const_expr(cx.tcx, index) {
- const_eval::const_int(i) => i as u64,
- const_eval::const_uint(u) => u,
- _ => cx.sess.span_bug(index.span,
- ~"index is not an integer-constant \
- expression")
- };
- let (arr, _len) = match ty::get(bt).sty {
- ty::ty_evec(_, vstore) | ty::ty_estr(vstore) =>
- match vstore {
- ty::vstore_fixed(u) =>
- (bv, C_uint(cx, u)),
+ ast::expr_index(base, index) => {
+ let bt = ty::expr_ty(cx.tcx, base);
+ let bv = const_expr(cx, base);
+ let (bt, bv) = const_autoderef(cx, bt, bv);
+ let iv = match const_eval::eval_const_expr(cx.tcx, index) {
+ const_eval::const_int(i) => i as u64,
+ const_eval::const_uint(u) => u,
+ _ => cx.sess.span_bug(index.span,
+ ~"index is not an integer-constant \
+ expression")
+ };
+ let (arr, _len) = match ty::get(bt).sty {
+ ty::ty_evec(_, vstore) | ty::ty_estr(vstore) =>
+ match vstore {
+ ty::vstore_fixed(u) =>
+ (bv, C_uint(cx, u)),
- ty::vstore_slice(_) => {
- let unit_ty = ty::sequence_element_type(cx.tcx, bt);
- let llunitty = type_of::type_of(cx, unit_ty);
- let unit_sz = shape::llsize_of(cx, llunitty);
+ ty::vstore_slice(_) => {
+ let unit_ty = ty::sequence_element_type(cx.tcx, bt);
+ let llunitty = type_of::type_of(cx, unit_ty);
+ let unit_sz = shape::llsize_of(cx, llunitty);
- (const_deref(cx, const_get_elt(cx, bv, [0])),
- llvm::LLVMConstUDiv(const_get_elt(cx, bv, [1]),
- unit_sz))
+ (const_deref(cx, const_get_elt(cx, bv, [0])),
+ llvm::LLVMConstUDiv(const_get_elt(cx, bv, [1]),
+ unit_sz))
+ },
+ _ => cx.sess.span_bug(base.span,
+ ~"index-expr base must be \
+ fixed-size or slice")
},
- _ => cx.sess.span_bug(base.span,
- ~"index-expr base must be \
- fixed-size or slice")
- },
- _ => cx.sess.span_bug(base.span,
- ~"index-expr base must be \
- a vector or string type")
- };
+ _ => cx.sess.span_bug(base.span,
+ ~"index-expr base must be \
+ a vector or string type")
+ };
- // FIXME #3169: This is a little odd but it arises due to a weird
- // wrinkle in LLVM: it doesn't appear willing to let us call
- // LLVMConstIntGetZExtValue on the size element of the slice, or
- // seemingly any integer-const involving a sizeof() call. Despite
- // that being "a const", it's not the kind of const you can ask
- // for the integer-value of, evidently. This might be an LLVM
- // bug, not sure. In any case, to work around this we drop down
- // to the array-type level here and just ask how long the
- // array-type itself is, ignoring the length we pulled out of the
- // slice. This in turn only works because we picked out the
- // original globalvar via const_deref and so can recover the
- // array-size of the underlying array, and all this will hold
- // together exactly as long as we _don't_ support const
- // sub-slices (that is, slices that represent something other
- // than a whole array). At that point we'll have more and uglier
- // work to do here, but for now this should work.
- //
- // In the future, what we should be doing here is the
- // moral equivalent of:
- //
- // let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
- //
- // but we might have to do substantially more magic to
- // make it work. Or figure out what is causing LLVM to
- // not want to consider sizeof() a constant expression
- // we can get the value (as a number) out of.
+ // FIXME #3169: This is a little odd but it arises due to a
+ // weird wrinkle in LLVM: it doesn't appear willing to let us
+ // call LLVMConstIntGetZExtValue on the size element of the
+ // slice, or seemingly any integer-const involving a sizeof()
+ // call. Despite that being "a const", it's not the kind of
+ // const you can ask for the integer-value of, evidently. This
+ // might be an LLVM bug, not sure. In any case, to work around
+ // this we drop down to the array-type level here and just ask
+ // how long the array-type itself is, ignoring the length we
+ // pulled out of the slice. This in turn only works because we
+ // picked out the original globalvar via const_deref and so can
+ // recover the array-size of the underlying array, and all this
+ // will hold together exactly as long as we _don't_ support
+ // const sub-slices (that is, slices that represent something
+ // other than a whole array). At that point we'll have more and
+ // uglier work to do here, but for now this should work.
+ //
+ // In the future, what we should be doing here is the
+ // moral equivalent of:
+ //
+ // let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
+ //
+ // but we might have to do substantially more magic to
+ // make it work. Or figure out what is causing LLVM to
+ // not want to consider sizeof() a constant expression
+ // we can get the value (as a number) out of.
- let len = llvm::LLVMGetArrayLength(val_ty(arr)) as u64;
- let len = match ty::get(bt).sty {
- ty::ty_estr(*) => {assert len > 0; len - 1},
- _ => len
- };
- if iv >= len {
- // FIXME #3170: report this earlier on in the const-eval
- // pass. Reporting here is a bit late.
- cx.sess.span_err(e.span,
- ~"const index-expr is out of bounds");
+ let len = llvm::LLVMGetArrayLength(val_ty(arr)) as u64;
+ let len = match ty::get(bt).sty {
+ ty::ty_estr(*) => {assert len > 0; len - 1},
+ _ => len
+ };
+ if iv >= len {
+ // FIXME #3170: report this earlier on in the const-eval
+ // pass. Reporting here is a bit late.
+ cx.sess.span_err(e.span,
+ ~"const index-expr is out of bounds");
+ }
+ const_get_elt(cx, arr, [iv as c_uint])
}
- const_get_elt(cx, arr, [iv as c_uint])
- }
- ast::expr_cast(base, _) => {
- let ety = ty::expr_ty(cx.tcx, e), llty = type_of::type_of(cx, ety);
- let basety = ty::expr_ty(cx.tcx, base);
- let v = const_expr(cx, base);
- match (expr::cast_type_kind(basety),
- expr::cast_type_kind(ety)) {
+ ast::expr_cast(base, _) => {
+ let ety = ty::expr_ty(cx.tcx, e);
+ let llty = type_of::type_of(cx, ety);
+ let basety = ty::expr_ty(cx.tcx, base);
+ let v = const_expr(cx, base);
+ match (expr::cast_type_kind(basety),
+ expr::cast_type_kind(ety)) {
- (expr::cast_integral, expr::cast_integral) => {
- let s = if ty::type_is_signed(basety) { True } else { False };
- llvm::LLVMConstIntCast(v, llty, s)
- }
- (expr::cast_integral, expr::cast_float) => {
- if ty::type_is_signed(basety) { llvm::LLVMConstSIToFP(v, llty) }
- else { llvm::LLVMConstUIToFP(v, llty) }
- }
- (expr::cast_float, expr::cast_float) => {
- llvm::LLVMConstFPCast(v, llty)
- }
- (expr::cast_float, expr::cast_integral) => {
- if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty) }
- else { llvm::LLVMConstFPToUI(v, llty) }
- }
- _ => cx.sess.impossible_case(e.span,
- ~"bad combination of types for cast")
- }
- }
- ast::expr_addr_of(ast::m_imm, sub) => {
- let cv = const_expr(cx, sub);
- let subty = ty::expr_ty(cx.tcx, sub),
- llty = type_of::type_of(cx, subty);
- let gv = do str::as_c_str("const") |name| {
- llvm::LLVMAddGlobal(cx.llmod, llty, name)
- };
- llvm::LLVMSetInitializer(gv, cv);
- llvm::LLVMSetGlobalConstant(gv, True);
- gv
- }
- ast::expr_tup(es) => {
- C_struct(es.map(|e| const_expr(cx, *e)))
- }
- ast::expr_rec(ref fs, None) => {
- C_struct([C_struct(
- (*fs).map(|f| const_expr(cx, f.node.expr)))])
- }
- ast::expr_struct(_, ref fs, _) => {
- let ety = ty::expr_ty(cx.tcx, e);
- let cs = do expr::with_field_tys(cx.tcx,
- ety,
- None) |_hd, field_tys| {
- field_tys.map(|field_ty| {
- match fs.find(|f| field_ty.ident == f.node.ident) {
- Some(ref f) => const_expr(cx, (*f).node.expr),
- None => {
- cx.tcx.sess.span_bug(
- e.span, ~"missing struct field");
- }
- }
- })
- };
- let llty = type_of::type_of(cx, ety);
- C_named_struct(llty, [C_struct(cs)])
- }
- ast::expr_vec(es, ast::m_imm) => {
- let (v, _, _) = const_vec(cx, e, es);
- v
- }
- ast::expr_vstore(e, ast::expr_vstore_fixed(_)) => {
- const_expr(cx, e)
- }
- ast::expr_vstore(sub, ast::expr_vstore_slice) => {
- match sub.node {
- ast::expr_lit(lit) => {
- match lit.node {
- ast::lit_str(*) => { const_expr(cx, sub) }
- _ => { cx.sess.span_bug(e.span,
- ~"bad const-slice lit") }
+ (expr::cast_integral, expr::cast_integral) => {
+ let s = if ty::type_is_signed(basety) { True } else { False };
+ llvm::LLVMConstIntCast(v, llty, s)
+ }
+ (expr::cast_integral, expr::cast_float) => {
+ if ty::type_is_signed(basety) {
+ llvm::LLVMConstSIToFP(v, llty)
+ } else {
+ llvm::LLVMConstUIToFP(v, llty)
+ }
+ }
+ (expr::cast_float, expr::cast_float) => {
+ llvm::LLVMConstFPCast(v, llty)
+ }
+ (expr::cast_float, expr::cast_integral) => {
+ if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty) }
+ else { llvm::LLVMConstFPToUI(v, llty) }
+ }
+ _ => {
+ cx.sess.impossible_case(e.span,
+ ~"bad combination of types for cast")
+ }
}
}
- ast::expr_vec(es, ast::m_imm) => {
- let (cv, sz, llunitty) = const_vec(cx, e, es);
- let llty = val_ty(cv);
+ ast::expr_addr_of(ast::m_imm, sub) => {
+ let cv = const_expr(cx, sub);
+ let subty = ty::expr_ty(cx.tcx, sub),
+ llty = type_of::type_of(cx, subty);
let gv = do str::as_c_str("const") |name| {
llvm::LLVMAddGlobal(cx.llmod, llty, name)
};
llvm::LLVMSetInitializer(gv, cv);
llvm::LLVMSetGlobalConstant(gv, True);
- let p = const_ptrcast(cx, gv, llunitty);
- C_struct(~[p, sz])
+ gv
}
- _ => cx.sess.span_bug(e.span,
- ~"bad const-slice expr")
- }
- }
- ast::expr_path(pth) => {
- assert pth.types.len() == 0;
- match cx.tcx.def_map.find(e.id) {
- Some(ast::def_fn(def_id, _)) => {
- assert ast_util::is_local(def_id);
- let f = base::get_item_val(cx, def_id.node);
- C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
+ ast::expr_tup(es) => {
+ C_struct(es.map(|e| const_expr(cx, *e)))
+ }
+ ast::expr_rec(ref fs, None) => {
+ C_struct([C_struct(
+ (*fs).map(|f| const_expr(cx, f.node.expr)))])
+ }
+ ast::expr_struct(_, ref fs, _) => {
+ let ety = ty::expr_ty(cx.tcx, e);
+ let cs = do expr::with_field_tys(cx.tcx,
+ ety,
+ None) |_hd, field_tys| {
+ field_tys.map(|field_ty| {
+ match fs.find(|f| field_ty.ident == f.node.ident) {
+ Some(ref f) => const_expr(cx, (*f).node.expr),
+ None => {
+ cx.tcx.sess.span_bug(
+ e.span, ~"missing struct field");
+ }
+ }
+ })
+ };
+ let llty = type_of::type_of(cx, ety);
+ C_named_struct(llty, [C_struct(cs)])
+ }
+ ast::expr_vec(es, ast::m_imm) => {
+ let (v, _, _) = const_vec(cx, e, es);
+ v
+ }
+ ast::expr_vstore(e, ast::expr_vstore_fixed(_)) => {
+ const_expr(cx, e)
+ }
+ ast::expr_vstore(sub, ast::expr_vstore_slice) => {
+ match /*bad*/copy sub.node {
+ ast::expr_lit(lit) => {
+ match lit.node {
+ ast::lit_str(*) => { const_expr(cx, sub) }
+ _ => { cx.sess.span_bug(e.span,
+ ~"bad const-slice lit") }
+ }
+ }
+ ast::expr_vec(es, ast::m_imm) => {
+ let (cv, sz, llunitty) = const_vec(cx, e, es);
+ let llty = val_ty(cv);
+ let gv = do str::as_c_str("const") |name| {
+ llvm::LLVMAddGlobal(cx.llmod, llty, name)
+ };
+ llvm::LLVMSetInitializer(gv, cv);
+ llvm::LLVMSetGlobalConstant(gv, True);
+ let p = const_ptrcast(cx, gv, llunitty);
+ C_struct(~[p, sz])
+ }
+ _ => cx.sess.span_bug(e.span,
+ ~"bad const-slice expr")
}
- Some(ast::def_const(def_id)) => {
- get_const_val(cx, def_id)
+ }
+ ast::expr_path(pth) => {
+ assert pth.types.len() == 0;
+ match cx.tcx.def_map.find(e.id) {
+ Some(ast::def_fn(def_id, _)) => {
+ assert ast_util::is_local(def_id);
+ let f = base::get_item_val(cx, def_id.node);
+ C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
+ }
+ Some(ast::def_const(def_id)) => {
+ get_const_val(cx, def_id)
+ }
+ Some(ast::def_variant(enum_did, variant_did)) => {
+ // Note that we know this is a C-like (nullary) enum
+ // variant or we wouldn't have gotten here -- the constant
+ // checker forbids paths that don't map to C-like enum
+ // variants.
+ let lldiscrim = base::get_discrim_val(cx, e.span,
+ enum_did,
+ variant_did);
+ C_struct(~[lldiscrim])
+ }
+ Some(ast::def_struct(_)) => {
+ let ety = ty::expr_ty(cx.tcx, e);
+ let llty = type_of::type_of(cx, ety);
+ C_null(llty)
+ }
+ _ => {
+ cx.sess.span_bug(e.span,
+ ~"expected a const, fn, or variant def")
+ }
}
- Some(ast::def_variant(enum_did, variant_did)) => {
- // Note that we know this is a C-like (nullary) enum variant,
- // or we wouldn't have gotten here -- the constant checker
- // forbids paths that don't map to C-like enum variants.
- let ety = ty::expr_ty(cx.tcx, e);
- let llty = type_of::type_of(cx, ety);
- let llstructtys = lib::llvm::struct_element_types(llty);
-
- // Can't use `discrims` from the crate context here because
- // those discriminants have an extra level of indirection,
- // and there's no LLVM constant load instruction.
- let mut lldiscrim_opt = None;
- for ty::enum_variants(cx.tcx, enum_did).each |variant_info| {
- if variant_info.id == variant_did {
- lldiscrim_opt = Some(C_int(cx,
- variant_info.disr_val));
- break;
+ }
+ ast::expr_call(callee, args, _) => {
+ match cx.tcx.def_map.find(callee.id) {
+ Some(ast::def_struct(def_id)) => {
+ let ety = ty::expr_ty(cx.tcx, e);
+ let llty = type_of::type_of(cx, ety);
+ let llstructbody =
+ C_struct(args.map(|a| const_expr(cx, *a)));
+ if ty::ty_dtor(cx.tcx, def_id).is_present() {
+ C_named_struct(llty, ~[ llstructbody, C_u8(0) ])
+ } else {
+ C_named_struct(llty, ~[ llstructbody ])
}
}
+ Some(ast::def_variant(tid, vid)) => {
+ let ety = ty::expr_ty(cx.tcx, e);
+ let degen = ty::enum_is_univariant(cx.tcx, tid);
+ let size = shape::static_size_of_enum(cx, ety);
- let lldiscrim;
- match lldiscrim_opt {
- None => {
- cx.tcx.sess.span_bug(e.span,
- ~"didn't find discriminant?!");
- }
- Some(found_lldiscrim) => {
- lldiscrim = found_lldiscrim;
- }
- }
+ let discrim = base::get_discrim_val(cx, e.span, tid, vid);
+ let c_args = C_struct(args.map(|a| const_expr(cx, *a)));
- C_named_struct(llty, ~[ lldiscrim, C_null(llstructtys[1]) ])
- }
- Some(ast::def_struct(_)) => {
- let ety = ty::expr_ty(cx.tcx, e);
- let llty = type_of::type_of(cx, ety);
- C_null(llty)
- }
- _ => {
- cx.sess.span_bug(e.span,
- ~"expected a const, fn, or variant def")
- }
- }
- }
- ast::expr_call(callee, args, _) => {
- match cx.tcx.def_map.find(callee.id) {
- Some(ast::def_struct(def_id)) => {
- let ety = ty::expr_ty(cx.tcx, e);
- let llty = type_of::type_of(cx, ety);
- let llstructbody = C_struct(args.map(|a| const_expr(cx, *a)));
- if ty::ty_dtor(cx.tcx, def_id).is_present() {
- C_named_struct(llty, ~[ llstructbody, C_u8(0) ])
+ let fields = if !degen {
+ ~[discrim, c_args]
+ } else if size == 0 {
+ ~[discrim]
} else {
- C_named_struct(llty, ~[ llstructbody ])
- }
+ ~[c_args]
+ };
+
+ C_struct(fields)
}
- _ => cx.sess.span_bug(e.span, ~"expected a struct def")
- }
- }
- ast::expr_paren(e) => { return const_expr(cx, e); }
- _ => cx.sess.span_bug(e.span,
- ~"bad constant expression type in consts::const_expr")
- };
+ _ => cx.sess.span_bug(e.span, ~"expected a struct def")
+ }
+ }
+ ast::expr_paren(e) => { return const_expr(cx, e); }
+ _ => cx.sess.span_bug(e.span,
+ ~"bad constant expression type in consts::const_expr")
+ };
+ }
}
-fn trans_const(ccx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
- let _icx = ccx.insn_ctxt("trans_const");
- let g = base::get_item_val(ccx, id);
- let v = const_expr(ccx, e);
- ccx.const_values.insert(id, v);
- llvm::LLVMSetInitializer(g, v);
- llvm::LLVMSetGlobalConstant(g, True);
+fn trans_const(ccx: @crate_ctxt, _e: @ast::expr, id: ast::node_id) {
+ unsafe {
+ let _icx = ccx.insn_ctxt("trans_const");
+ let g = base::get_item_val(ccx, id);
+ // At this point, get_item_val has already translated the
+ // constant's initializer to determine its LLVM type.
+ let v = ccx.const_values.get(id);
+ llvm::LLVMSetInitializer(g, v);
+ llvm::LLVMSetGlobalConstant(g, True);
+ }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use lib::llvm::ValueRef;
use middle::trans::base::*;
+use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::datum::*;
+use core::str;
+
fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export.
fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block {
}
let modpath = vec::append(
- ~[path_mod(ccx.sess.ident_of(ccx.link_meta.name))],
- vec::filter(bcx.fcx.path, |e|
+ ~[path_mod(ccx.sess.ident_of(/*bad*/copy ccx.link_meta.name))],
+ bcx.fcx.path.filtered(|e|
match *e { path_mod(_) => true, _ => false }
));
- let modname = path_str(ccx.sess, modpath);
+ // XXX: Bad copy.
+ let modname = path_str(ccx.sess, copy modpath);
- let global = if ccx.module_data.contains_key(modname) {
+ // XXX: Bad copy.
+ let global = if ccx.module_data.contains_key(copy modname) {
ccx.module_data.get(modname)
} else {
let s = link::mangle_internal_name_by_path_and_seq(
ccx, modpath, ~"loglevel");
- let global = str::as_c_str(s, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
- });
- llvm::LLVMSetGlobalConstant(global, False);
- llvm::LLVMSetInitializer(global, C_null(T_i32()));
- lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
+ let global;
+ unsafe {
+ global = str::as_c_str(s, |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
+ });
+ llvm::LLVMSetGlobalConstant(global, False);
+ llvm::LLVMSetInitializer(global, C_null(T_i32()));
+ lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
+ }
ccx.module_data.insert(modname, global);
global
};
// Call the polymorphic log function
let val = val_datum.to_ref_llval(bcx);
- let did = bcx.tcx().lang_items.log_type_fn.get();
+ let did = bcx.tcx().lang_items.log_type_fn();
let bcx = callee::trans_rtcall_or_lang_call_with_type_params(
bcx, did, ~[level, val], ~[val_datum.ty], expr::Ignore);
bcx
let mut target;
loop {
match unwind.kind {
- block_scope({loop_break: Some(brk), loop_label: l, _}) => {
+ block_scope(scope_info {
+ loop_break: Some(brk),
+ loop_label: l,
+ _
+ }) => {
// If we're looking for a labeled loop, check the label...
target = if to_end {
brk
}
};
do with_cond(bcx, Not(bcx, val)) |bcx| {
- trans_fail(bcx, Some(pred_expr.span), expr_str)
+ trans_fail(bcx, Some(pred_expr.span), /*bad*/copy expr_str)
}
}
}
}
-fn trans_fail(bcx: block, sp_opt: Option<span>, fail_str: ~str)
+fn trans_fail(bcx: block, sp_opt: Option<span>, +fail_str: ~str)
-> block
{
let _icx = bcx.insn_ctxt("trans_fail");
Some(sp) => {
let sess = bcx.sess();
let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo);
- {V_filename: C_cstr(bcx.ccx(), loc.file.name),
+ {V_filename: C_cstr(bcx.ccx(), /*bad*/copy loc.file.name),
V_line: loc.line as int}
}
None => {
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
- let bcx = callee::trans_rtcall(bcx, ~"fail_", args, expr::Ignore);
+ let bcx = callee::trans_rtcall_or_lang_call(
+ bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
Unreachable(bcx);
return bcx;
}
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(sp.lo);
let line = C_int(ccx, loc.line as int);
- let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
+ let filename_cstr = C_cstr(bcx.ccx(), /*bad*/copy loc.file.name);
let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
let args = ~[filename, line, index, len];
- let bcx = callee::trans_rtcall(bcx, ~"fail_bounds_check", args,
- expr::Ignore);
+ let bcx = callee::trans_rtcall_or_lang_call(
+ bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);
Unreachable(bcx);
return bcx;
}
* methods themselves. Most are only suitable for some types of
* values. */
+use core::prelude::*;
+
use lib::llvm::ValueRef;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
+use middle::trans::common;
+use middle::trans::tvec;
+use middle::typeck;
use util::common::indenter;
use util::ppaux::ty_to_str;
+use core::cmp;
+use core::option;
+use core::uint;
+use core::vec;
+use syntax::parse::token::special_idents;
+
enum CopyAction {
INIT,
DROP_EXISTING
// Check whether this struct is a newtype struct.
let fields = ty::struct_fields(ccx.tcx, did, substs);
if fields.len() != 1 || fields[0].ident !=
- syntax::parse::token::special_idents::unnamed_field {
+ special_idents::unnamed_field {
return None;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use driver::session;
use lib::llvm::ValueRef;
use lib::llvm::llvm;
use middle::trans::base;
use middle::trans::build::B;
use middle::trans::common::*;
+use middle::trans::shape;
+use middle::trans::type_of;
+use middle::trans;
use middle::ty;
use util::ppaux::ty_to_str;
+use core::libc;
+use core::option;
+use core::sys;
use std::map::HashMap;
use std::map;
use syntax::ast::Ty;
fn llstr(s: ~str) -> ValueRef {
str::as_c_str(s, |sbuf| {
- llvm::LLVMMDString(sbuf, str::len(s) as libc::c_uint)
+ unsafe {
+ llvm::LLVMMDString(sbuf, str::len(s) as libc::c_uint)
+ }
})
}
fn lltag(lltag: int) -> ValueRef {
C_bool(bval)
}
fn llmdnode(elems: ~[ValueRef]) -> ValueRef unsafe {
- llvm::LLVMMDNode(vec::raw::to_ptr(elems),
- vec::len(elems) as libc::c_uint)
+ unsafe {
+ llvm::LLVMMDNode(vec::raw::to_ptr(elems),
+ vec::len(elems) as libc::c_uint)
+ }
}
fn llunused() -> ValueRef {
lli32(0x0)
fn add_named_metadata(cx: @crate_ctxt, name: ~str, val: ValueRef) {
str::as_c_str(name, |sbuf| {
- llvm::LLVMAddNamedMetadataOperand(cx.llmod, sbuf, val)
+ unsafe {
+ llvm::LLVMAddNamedMetadataOperand(cx.llmod, sbuf, val)
+ }
})
}
crate_file: ~str
};
-fn mk_ctxt(crate: ~str, intr: @ident_interner) -> debug_ctxt {
+fn mk_ctxt(+crate: ~str, intr: @ident_interner) -> debug_ctxt {
{llmetadata: map::HashMap(),
names: new_namegen(intr),
crate_file: crate}
fn create_compile_unit(cx: @crate_ctxt)
-> @metadata<compile_unit_md> unsafe {
let cache = get_cache(cx);
- let crate_name = cx.dbg_cx.get().crate_file;
+ let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
let tg = CompileUnitTag;
match cached_metadata::<@metadata<compile_unit_md>>(cache, tg,
|md| md.data.name == crate_name) {
let unit_metadata = ~[lltag(tg),
llunused(),
lli32(DW_LANG_RUST),
- llstr(crate_name),
+ llstr(copy crate_name),
llstr(work_dir),
llstr(env!("CFG_VERSION")),
lli1(true), // deprecated: main compile unit
}
fn get_cache(cx: @crate_ctxt) -> metadata_cache {
- cx.dbg_cx.get().llmetadata
+ (/*bad*/copy cx.dbg_cx).get().llmetadata
}
fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
}, str::from_slice(work_dir))
}
-fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> {
+fn create_file(cx: @crate_ctxt, +full_path: ~str) -> @metadata<file_md> {
let cache = get_cache(cx);;
let tg = FileDescriptorTag;
match cached_metadata::<@metadata<file_md>>(
let sp = cx.node_info.get().span;
let start = cx.sess().codemap.lookup_char_pos(sp.lo);
- let fname = start.file.name;
+ let fname = /*bad*/copy start.file.name;
let end = cx.sess().codemap.lookup_char_pos(sp.hi);
let tg = LexicalBlockTag;
- /*alt cached_metadata::<@metadata<block_md>>(
+ /*match cached_metadata::<@metadata<block_md>>(
cache, tg,
{|md| start == md.data.start && end == md.data.end}) {
option::Some(md) { return md; }
};
fn finish_structure(cx: @struct_ctxt) -> ValueRef {
- return create_composite_type(StructureTypeTag, cx.name, cx.file, cx.line,
- cx.total_size, cx.align, 0, option::None,
- option::Some(cx.members));
-}
-
-fn create_structure(file: @metadata<file_md>, name: ~str, line: int)
+ return create_composite_type(StructureTypeTag,
+ /*bad*/copy cx.name,
+ cx.file,
+ cx.line,
+ cx.total_size,
+ cx.align,
+ 0,
+ option::None,
+ option::Some(/*bad*/copy cx.members));
+}
+
+fn create_structure(file: @metadata<file_md>, +name: ~str, line: int)
-> @struct_ctxt {
let cx = @{file: file.node,
name: name,
return cx;
}
-fn create_derived_type(type_tag: int, file: ValueRef, name: ~str, line: int,
+fn create_derived_type(type_tag: int, file: ValueRef, +name: ~str, line: int,
size: int, align: int, offset: int, ty: ValueRef)
-> ValueRef {
let lldata = ~[lltag(type_tag),
return llmdnode(lldata);
}
-fn add_member(cx: @struct_ctxt, name: ~str, line: int, size: int, align: int,
+fn add_member(cx: @struct_ctxt, +name: ~str, line: int, size: int, align: int,
ty: ValueRef) {
cx.members.push(create_derived_type(MemberTag, cx.file, name, line,
size * 8, align * 8, cx.total_size,
let file_node = create_file(cx, fname);
let scx = create_structure(file_node,
cx.sess.str_of(
- (cx.dbg_cx.get().names)(~"rec")),
+ ((/*bad*/copy cx.dbg_cx).get().names)
+ (~"rec")),
line_from_span(cx.sess.codemap,
span) as int);
for fields.each |field| {
return mdval;
}
-fn create_composite_type(type_tag: int, name: ~str, file: ValueRef, line: int,
- size: int, align: int, offset: int,
+fn create_composite_type(type_tag: int, +name: ~str, file: ValueRef,
+ line: int, size: int, align: int, offset: int,
derived: Option<ValueRef>,
- members: Option<~[ValueRef]>)
+ +members: Option<~[ValueRef]>)
-> ValueRef {
let lldata = ~[lltag(type_tag),
file,
}
fn filename_from_span(cx: @crate_ctxt, sp: codemap::span) -> ~str {
- cx.sess.codemap.lookup_char_pos(sp.lo).file.name
+ /*bad*/copy cx.sess.codemap.lookup_char_pos(sp.lo).file.name
}
-fn create_var(type_tag: int, context: ValueRef, name: ~str, file: ValueRef,
+fn create_var(type_tag: int, context: ValueRef, +name: ~str, file: ValueRef,
line: int, ret_ty: ValueRef) -> ValueRef {
let lldata = ~[lltag(type_tag),
context,
let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
let ty = node_id_type(bcx, local.node.id);
let tymd = create_ty(cx, ty, local.node.ty);
- let filemd = create_file(cx, loc.file.name);
+ let filemd = create_file(cx, /*bad*/copy loc.file.name);
let context = match bcx.parent {
None => create_function(bcx.fcx).node,
Some(_) => create_block(bcx).node
let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
let ty = node_id_type(bcx, arg.id);
let tymd = create_ty(cx, ty, arg.ty);
- let filemd = create_file(cx, loc.file.name);
+ let filemd = create_file(cx, /*bad*/copy loc.file.name);
let context = create_function(bcx.fcx);
match arg.pat.node {
blockmd.node,
llnull()];
let dbgscope = llmdnode(scopedata);
- llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope);
+ unsafe {
+ llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope);
+ }
}
fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
let cx = fcx.ccx;
- let dbg_cx = cx.dbg_cx.get();
+ let dbg_cx = (/*bad*/copy cx.dbg_cx).get();
debug!("~~");
log(debug, fcx.id);
let (ident, ret_ty, id) = match cx.tcx.items.get(fcx.id) {
ast_map::node_item(item, _) => {
- match item.node {
+ match /*bad*/copy item.node {
ast::item_fn(decl, _, _, _) => {
(item.ident, decl.output, item.id)
}
(method.ident, method.decl.output, method.id)
}
ast_map::node_expr(expr) => {
- match expr.node {
+ match /*bad*/copy expr.node {
ast::expr_fn(_, decl, _, _) => {
((dbg_cx.names)(~"fn"), decl.output, expr.id)
}
*/
+use core::prelude::*;
+
use lib::llvm::ValueRef;
+use middle::resolve;
use middle::trans::base::*;
use middle::trans::callee::{AutorefArg, DoAutorefArg, DontAutorefArg};
+use middle::trans::callee;
+use middle::trans::closure;
use middle::trans::common::*;
+use middle::trans::consts;
+use middle::trans::controlflow;
use middle::trans::datum::*;
+use middle::trans::machine;
+use middle::trans::meth;
+use middle::trans::tvec;
use middle::ty::MoveValue;
use middle::ty::struct_mutable_fields;
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
use util::ppaux::ty_to_str;
use syntax::print::pprust::{expr_to_str};
+use syntax::ast;
+use syntax::ast::spanned;
// The primary two functions for translating expressions:
export trans_to_datum, trans_into;
trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr)));
- match expr.node {
+ // XXX: This copy is really bad.
+ match /*bad*/copy expr.node {
ast::expr_paren(e) => {
return trans_rvalue_dps_unadjusted(bcx, e, dest);
}
return controlflow::trans_if(bcx, cond, (*thn), els, dest);
}
ast::expr_match(discr, ref arms) => {
- return alt::trans_alt(bcx, expr, discr, (*arms), dest);
+ return _match::trans_match(bcx, expr, discr, /*bad*/copy *arms,
+ dest);
}
ast::expr_block(ref blk) => {
return do base::with_scope(bcx, (*blk).info(),
ast::expr_tup(args) => {
return trans_tup(bcx, args, dest);
}
- ast::expr_lit(@{node: ast::lit_str(s), _}) => {
+ ast::expr_lit(@ast::spanned {node: ast::lit_str(s), _}) => {
return tvec::trans_lit_str(bcx, expr, s, dest);
}
ast::expr_vstore(contents, ast::expr_vstore_slice) |
ast::expr_vec(*) | ast::expr_repeat(*) => {
return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
}
- ast::expr_fn(proto, decl, ref body, cap_clause) => {
+ // XXX: Bad copy.
+ ast::expr_fn(proto, copy decl, ref body, cap_clause) => {
// Don't use this function for anything real. Use the one in
// astconv instead.
- return closure::trans_expr_fn(bcx, proto, decl, *body, expr.id,
+ return closure::trans_expr_fn(bcx, proto, decl,
+ /*bad*/copy *body,
+ expr.id, expr.id,
cap_clause, None, dest);
}
- ast::expr_fn_block(decl, ref body, cap_clause) => {
+ ast::expr_fn_block(ref decl, ref body, cap_clause) => {
let expr_ty = expr_ty(bcx, expr);
match ty::get(expr_ty).sty {
ty::ty_fn(ref fn_ty) => {
expr_to_str(expr, tcx.sess.intr()),
ty_to_str(tcx, expr_ty));
return closure::trans_expr_fn(
- bcx, fn_ty.meta.proto, decl, *body, expr.id,
+ bcx, fn_ty.meta.proto, /*bad*/copy *decl,
+ /*bad*/copy *body, expr.id, expr.id,
cap_clause, None, dest);
}
_ => {
match ty::get(expr_ty(bcx, expr)).sty {
ty::ty_fn(ref fn_ty) => {
match blk.node {
- ast::expr_fn_block(decl, ref body, cap) => {
+ ast::expr_fn_block(copy decl, ref body, cap) => {
return closure::trans_expr_fn(
- bcx, fn_ty.meta.proto, decl, *body, blk.id,
- cap, Some(None), dest);
+ bcx,
+ fn_ty.meta.proto,
+ decl,
+ /*bad*/copy *body,
+ expr.id,
+ blk.id,
+ cap,
+ Some(None),
+ dest);
}
_ => {
bcx.sess().impossible_case(
ast::def_const(did) => {
let const_ty = expr_ty(bcx, ref_expr);
let val = if did.crate == ast::local_crate {
- base::get_item_val(ccx, did.node)
+ // The LLVM global has the type of its initializer,
+ // which may not be equal to the enum's type for
+ // non-C-like enums.
+ PointerCast(bcx, base::get_item_val(ccx, did.node),
+ T_ptr(type_of(bcx.ccx(), const_ty)))
} else {
base::trans_external_path(ccx, did, const_ty)
};
fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
llsrc: ValueRef, signed: bool) -> ValueRef {
let _icx = bcx.insn_ctxt("int_cast");
- let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype);
- let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype);
- return if dstsz == srcsz {
- BitCast(bcx, llsrc, lldsttype)
- } else if srcsz > dstsz {
- TruncOrBitCast(bcx, llsrc, lldsttype)
- } else if signed {
- SExtOrBitCast(bcx, llsrc, lldsttype)
- } else { ZExtOrBitCast(bcx, llsrc, lldsttype) };
+ unsafe {
+ let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype);
+ let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype);
+ return if dstsz == srcsz {
+ BitCast(bcx, llsrc, lldsttype)
+ } else if srcsz > dstsz {
+ TruncOrBitCast(bcx, llsrc, lldsttype)
+ } else if signed {
+ SExtOrBitCast(bcx, llsrc, lldsttype)
+ } else {
+ ZExtOrBitCast(bcx, llsrc, lldsttype)
+ };
+ }
}
fn float_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
// The classification code for the x86_64 ABI is taken from the clay language
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
+use core::prelude::*;
+
use back::{link, abi};
use driver::session::arch_x86_64;
+use driver::session::arch_arm;
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
use lib::llvm::{Struct, Array, ModuleRef, CallConv, Attribute};
use lib::llvm::{StructRetAttribute, ByValAttribute};
use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double};
+use lib;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::callee::*;
use middle::trans::common::*;
use middle::trans::datum::*;
use middle::trans::expr::{Dest, Ignore};
+use middle::trans::glue;
+use middle::trans::machine;
+use middle::trans::shape;
use middle::trans::type_of::*;
+use middle::trans::type_of;
use middle::ty::{FnTyBase, FnMeta, FnSig};
use util::ppaux::ty_to_str;
use core::libc::c_uint;
-use std::map::HashMap;
use syntax::codemap::span;
use syntax::{ast, ast_util};
use syntax::{attr, ast_map};
+use syntax::parse::token::special_idents;
export link_name, trans_foreign_mod, register_foreign_fn, trans_foreign_fn,
trans_intrinsic;
}
fn struct_tys(ty: TypeRef) -> ~[TypeRef] {
- let n = llvm::LLVMCountStructElementTypes(ty);
- let mut elts = vec::from_elem(n as uint, ptr::null());
- llvm::LLVMGetStructElementTypes(ty,
- ptr::to_mut_unsafe_ptr(&mut elts[0]));
- return elts;
+ unsafe {
+ let n = llvm::LLVMCountStructElementTypes(ty);
+ if (n == 0) {
+ return ~[];
+ }
+ let mut elts = vec::from_elem(n as uint, ptr::null());
+ llvm::LLVMGetStructElementTypes(ty,
+ ptr::to_mut_unsafe_ptr(&mut elts[0]));
+ return elts;
+ }
}
fn ty_align(ty: TypeRef) -> uint {
- return match llvm::LLVMGetTypeKind(ty) {
- Integer => {
- ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
- }
- Pointer => 8,
- Float => 4,
- Double => 8,
- Struct => {
- do vec::foldl(0, struct_tys(ty)) |a, t| {
- uint::max(a, ty_align(*t))
- }
- }
- Array => {
- let elt = llvm::LLVMGetElementType(ty);
- ty_align(elt)
- }
- _ => fail ~"ty_size: unhandled type"
- };
+ unsafe {
+ return match llvm::LLVMGetTypeKind(ty) {
+ Integer => {
+ ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
+ }
+ Pointer => 8,
+ Float => 4,
+ Double => 8,
+ Struct => {
+ do vec::foldl(1, struct_tys(ty)) |a, t| {
+ uint::max(a, ty_align(*t))
+ }
+ }
+ Array => {
+ let elt = llvm::LLVMGetElementType(ty);
+ ty_align(elt)
+ }
+ _ => fail ~"ty_size: unhandled type"
+ };
+ }
}
fn ty_size(ty: TypeRef) -> uint {
- return match llvm::LLVMGetTypeKind(ty) {
- Integer => {
- ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
- }
- Pointer => 8,
- Float => 4,
- Double => 8,
- Struct => {
- let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
- align(s, *t) + ty_size(*t)
- };
- align(size, ty)
- }
- Array => {
- let len = llvm::LLVMGetArrayLength(ty) as uint;
- let elt = llvm::LLVMGetElementType(ty);
- let eltsz = ty_size(elt);
- len * eltsz
- }
- _ => fail ~"ty_size: unhandled type"
- };
+ unsafe {
+ return match llvm::LLVMGetTypeKind(ty) {
+ Integer => {
+ ((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
+ }
+ Pointer => 8,
+ Float => 4,
+ Double => 8,
+ Struct => {
+ let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
+ align(s, *t) + ty_size(*t)
+ };
+ align(size, ty)
+ }
+ Array => {
+ let len = llvm::LLVMGetArrayLength(ty) as uint;
+ let elt = llvm::LLVMGetElementType(ty);
+ let eltsz = ty_size(elt);
+ len * eltsz
+ }
+ _ => fail ~"ty_size: unhandled type"
+ };
+ }
}
fn all_mem(cls: &[mut x86_64_reg_class]) {
fn classify_struct(tys: &[TypeRef],
cls: &[mut x86_64_reg_class], i: uint,
off: uint) {
- if vec::is_empty(tys) {
- classify(T_i64(), cls, i, off);
- } else {
- let mut field_off = off;
- for vec::each(tys) |ty| {
- field_off = align(field_off, *ty);
- classify(*ty, cls, i, field_off);
- field_off += ty_size(*ty);
- }
+ let mut field_off = off;
+ for vec::each(tys) |ty| {
+ field_off = align(field_off, *ty);
+ classify(*ty, cls, i, field_off);
+ field_off += ty_size(*ty);
}
}
fn classify(ty: TypeRef,
cls: &[mut x86_64_reg_class], ix: uint,
off: uint) {
- let t_align = ty_align(ty);
- let t_size = ty_size(ty);
-
- let misalign = off % t_align;
- if misalign != 0u {
- let mut i = off / 8u;
- let e = (off + t_size + 7u) / 8u;
- while i < e {
- unify(cls, ix + i, memory_class);
- i += 1u;
+ unsafe {
+ let t_align = ty_align(ty);
+ let t_size = ty_size(ty);
+
+ let misalign = off % t_align;
+ if misalign != 0u {
+ let mut i = off / 8u;
+ let e = (off + t_size + 7u) / 8u;
+ while i < e {
+ unify(cls, ix + i, memory_class);
+ i += 1u;
+ }
+ return;
}
- return;
- }
- match llvm::LLVMGetTypeKind(ty) as int {
- 8 /* integer */ |
- 12 /* pointer */ => {
- unify(cls, ix + off / 8u, integer_class);
- }
- 2 /* float */ => {
- if off % 8u == 4u {
- unify(cls, ix + off / 8u, sse_fv_class);
- } else {
- unify(cls, ix + off / 8u, sse_fs_class);
+ match llvm::LLVMGetTypeKind(ty) as int {
+ 8 /* integer */ |
+ 12 /* pointer */ => {
+ unify(cls, ix + off / 8u, integer_class);
}
- }
- 3 /* double */ => {
- unify(cls, ix + off / 8u, sse_ds_class);
- }
- 10 /* struct */ => {
- classify_struct(struct_tys(ty), cls, ix, off);
- }
- 11 /* array */ => {
- let elt = llvm::LLVMGetElementType(ty);
- let eltsz = ty_size(elt);
- let len = llvm::LLVMGetArrayLength(ty) as uint;
- let mut i = 0u;
- while i < len {
- classify(elt, cls, ix, off + i * eltsz);
- i += 1u;
+ 2 /* float */ => {
+ if off % 8u == 4u {
+ unify(cls, ix + off / 8u, sse_fv_class);
+ } else {
+ unify(cls, ix + off / 8u, sse_fs_class);
+ }
+ }
+ 3 /* double */ => {
+ unify(cls, ix + off / 8u, sse_ds_class);
}
+ 10 /* struct */ => {
+ classify_struct(struct_tys(ty), cls, ix, off);
+ }
+ 11 /* array */ => {
+ let elt = llvm::LLVMGetElementType(ty);
+ let eltsz = ty_size(elt);
+ let len = llvm::LLVMGetArrayLength(ty) as uint;
+ let mut i = 0u;
+ while i < len {
+ classify(elt, cls, ix, off + i * eltsz);
+ i += 1u;
+ }
+ }
+ _ => fail ~"classify: unhandled type"
}
- _ => fail ~"classify: unhandled type"
}
}
fn fixup(ty: TypeRef, cls: &[mut x86_64_reg_class]) {
- let mut i = 0u;
- let llty = llvm::LLVMGetTypeKind(ty) as int;
- let e = vec::len(cls);
- if vec::len(cls) > 2u &&
- (llty == 10 /* struct */ ||
- llty == 11 /* array */) {
- if is_sse(cls[i]) {
- i += 1u;
+ unsafe {
+ let mut i = 0u;
+ let llty = llvm::LLVMGetTypeKind(ty) as int;
+ let e = vec::len(cls);
+ if vec::len(cls) > 2u &&
+ (llty == 10 /* struct */ ||
+ llty == 11 /* array */) {
+ if is_sse(cls[i]) {
+ i += 1u;
+ while i < e {
+ if cls[i] != sseup_class {
+ all_mem(cls);
+ return;
+ }
+ i += 1u;
+ }
+ } else {
+ all_mem(cls);
+ return
+ }
+ } else {
while i < e {
- if cls[i] != sseup_class {
+ if cls[i] == memory_class {
all_mem(cls);
return;
}
- i += 1u;
- }
- } else {
- all_mem(cls);
- return
- }
- } else {
- while i < e {
- if cls[i] == memory_class {
- all_mem(cls);
- return;
- }
- if cls[i] == x87up_class {
- // for darwin
- // cls[i] = sse_ds_class;
- all_mem(cls);
- return;
- }
- if cls[i] == sseup_class {
- cls[i] = sse_int_class;
- } else if is_sse(cls[i]) {
- i += 1;
- while cls[i] == sseup_class { i += 1u; }
- } else if cls[i] == x87_class {
- i += 1;
- while cls[i] == x87up_class { i += 1u; }
- } else {
- i += 1;
+ if cls[i] == x87up_class {
+ // for darwin
+ // cls[i] = sse_ds_class;
+ all_mem(cls);
+ return;
+ }
+ if cls[i] == sseup_class {
+ cls[i] = sse_int_class;
+ } else if is_sse(cls[i]) {
+ i += 1;
+ while cls[i] == sseup_class { i += 1u; }
+ } else if cls[i] == x87_class {
+ i += 1;
+ while cls[i] == x87up_class { i += 1u; }
+ } else {
+ i += 1;
+ }
}
}
}
return len;
}
- let mut tys = ~[];
- let mut i = 0u;
- let e = vec::len(cls);
- while i < e {
- match cls[i] {
- integer_class => {
- tys.push(T_i64());
- }
- sse_fv_class => {
- let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
- let vec_ty = llvm::LLVMVectorType(T_f32(),
- vec_len as c_uint);
- tys.push(vec_ty);
- i += vec_len;
- loop;
- }
- sse_fs_class => {
- tys.push(T_f32());
- }
- sse_ds_class => {
- tys.push(T_f64());
+ unsafe {
+ let mut tys = ~[];
+ let mut i = 0u;
+ let e = vec::len(cls);
+ while i < e {
+ match cls[i] {
+ integer_class => {
+ tys.push(T_i64());
+ }
+ sse_fv_class => {
+ let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
+ let vec_ty = llvm::LLVMVectorType(T_f32(),
+ vec_len as c_uint);
+ tys.push(vec_ty);
+ i += vec_len;
+ loop;
+ }
+ sse_fs_class => {
+ tys.push(T_f32());
+ }
+ sse_ds_class => {
+ tys.push(T_f64());
+ }
+ _ => fail ~"llregtype: unhandled class"
}
- _ => fail ~"llregtype: unhandled class"
+ i += 1u;
}
- i += 1u;
+ return T_struct(tys);
}
- return T_struct(tys);
}
type x86_64_llty = {
rty: TypeRef,
ret_def: bool) -> x86_64_tys {
fn is_reg_ty(ty: TypeRef) -> bool {
- return match llvm::LLVMGetTypeKind(ty) as int {
- 8 /* integer */ |
- 12 /* pointer */ |
- 2 /* float */ |
- 3 /* double */ => true,
- _ => false
- };
+ unsafe {
+ return match llvm::LLVMGetTypeKind(ty) as int {
+ 8 /* integer */ |
+ 12 /* pointer */ |
+ 2 /* float */ |
+ 3 /* double */ => true,
+ _ => false
+ };
+ }
}
fn is_pass_byval(cls: &[x86_64_reg_class]) -> bool {
- return cls[0] == memory_class ||
- cls[0] == x87_class ||
- cls[0] == complex_x87_class;
+ return cls.len() > 0 &&
+ (cls[0] == memory_class ||
+ cls[0] == x87_class ||
+ cls[0] == complex_x87_class);
}
fn is_ret_bysret(cls: &[x86_64_reg_class]) -> bool {
- return cls[0] == memory_class;
+ return cls.len() > 0 && cls[0] == memory_class;
}
fn x86_64_ty(ty: TypeRef,
for vec::eachi(tys.attrs) |i, a| {
match *a {
option::Some(attr) => {
- let llarg = get_param(llfn, i);
- llvm::LLVMAddAttribute(llarg, attr as c_uint);
+ unsafe {
+ let llarg = get_param(llfn, i);
+ llvm::LLVMAddAttribute(llarg, attr as c_uint);
+ }
}
_ => ()
}
fn link_name(ccx: @crate_ctxt, i: @ast::foreign_item) -> ~str {
match attr::first_attr_value_str_by_name(i.attrs, ~"link_name") {
None => ccx.sess.str_of(i.ident),
- option::Some(ref ln) => (*ln)
+ option::Some(ref ln) => (/*bad*/copy *ln)
}
}
id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) {
match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
ty::ty_fn(ref fn_ty) => {
- let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs);
+ let llargtys = type_of_explicit_args(
+ ccx,
+ /*bad*/copy fn_ty.sig.inputs);
let llretty = type_of::type_of(ccx, fn_ty.sig.output);
(llargtys, llretty, fn_ty.sig.output)
}
fn c_stack_tys(ccx: @crate_ctxt,
id: ast::node_id) -> @c_stack_tys {
let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, id);
- let bundle_ty = T_struct(vec::append_one(llargtys, T_ptr(llretty)));
+ // XXX: Bad copy.
+ let bundle_ty = T_struct(vec::append_one(copy llargtys, T_ptr(llretty)));
let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty);
let x86_64 = if ccx.sess.targ_cfg.arch == arch_x86_64 {
option::Some(x86_64_tys(llargtys, llretty, ret_def))
+ } else if ccx.sess.targ_cfg.arch == arch_arm {
+ option::Some(x86_64_tys(llargtys, llretty, ret_def))
} else {
option::None
};
llargbundle: ValueRef, llretval: ValueRef);
fn build_shim_fn_(ccx: @crate_ctxt,
- shim_name: ~str,
+ +shim_name: ~str,
llbasefn: ValueRef,
tys: @c_stack_tys,
cc: lib::llvm::CallConv,
match tys.x86_64_tys {
Some(ref x86_64) => {
- let mut atys = (*x86_64).arg_tys;
- let mut attrs = (*x86_64).attrs;
+ let mut atys = /*bad*/copy (*x86_64).arg_tys;
+ let mut attrs = /*bad*/copy (*x86_64).attrs;
if (*x86_64).sret {
let llretptr = GEPi(bcx, llargbundle, [0u, n]);
let llretloc = Load(bcx, llretptr);
for vec::eachi((*x86_64).attrs) |i, a| {
match *a {
Some(attr) => {
- llvm::LLVMAddInstrAttribute(
- llretval, (i + 1u) as c_uint,
- attr as c_uint);
+ unsafe {
+ llvm::LLVMAddInstrAttribute(
+ llretval, (i + 1u) as c_uint,
+ attr as c_uint);
+ }
}
_ => ()
}
}
let lname = link_name(ccx, foreign_item);
- let llbasefn = base_fn(ccx, lname, tys, cc);
+ let llbasefn = base_fn(ccx, copy lname, tys, cc);
// Name the shim function
let shim_name = lname + ~"__c_stack_shim";
return build_shim_fn_(ccx, shim_name, llbasefn, tys, cc,
build_args, build_ret);
}
- fn base_fn(ccx: @crate_ctxt, lname: ~str, tys: @c_stack_tys,
+ fn base_fn(ccx: @crate_ctxt, +lname: ~str, tys: @c_stack_tys,
cc: lib::llvm::CallConv) -> ValueRef {
// Declare the "prototype" for the base function F:
match tys.x86_64_tys {
Some(ref x86_64) => {
do decl_x86_64_fn((*x86_64)) |fnty| {
- decl_fn(ccx.llmod, lname, cc, fnty)
+ decl_fn(ccx.llmod, /*bad*/copy lname, cc, fnty)
}
}
_ => {
- let llbasefnty = T_fn(tys.arg_tys, tys.ret_ty);
+ let llbasefnty = T_fn(/*bad*/copy tys.arg_tys, tys.ret_ty);
decl_fn(ccx.llmod, lname, cc, llbasefnty)
}
}
if abi != ast::foreign_abi_rust_intrinsic {
let llwrapfn = get_item_val(ccx, id);
let tys = c_stack_tys(ccx, id);
- if attr::attrs_contains_name(foreign_item.attrs,
- ~"rust_stack") {
+ if attr::attrs_contains_name(foreign_item.attrs, "rust_stack") {
build_direct_fn(ccx, llwrapfn, *foreign_item, tys, cc);
} else {
let llshimfn = build_shim_fn(ccx, *foreign_item, tys, cc);
}
fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
- path: ast_map::path, substs: param_substs,
+ +path: ast_map::path, +substs: param_substs,
ref_id: Option<ast::node_id>)
{
debug!("trans_intrinsic(item.ident=%s)", ccx.sess.str_of(item.ident));
+ // XXX: Bad copy.
let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, None,
- Some(substs), Some(item.span));
+ Some(copy substs), Some(item.span));
let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb;
match ccx.sess.str_of(item.ident) {
~"atomic_cxchg" => {
proto: ast::ProtoBorrowed,
onceness: ast::Many,
region: ty::re_bound(ty::br_anon(0)),
- bounds: @~[],
- ret_style: ast::return_val},
+ bounds: @~[]},
sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val),
ty: star_u8}],
output: ty::mk_nil(bcx.tcx())}
let cttz = ccx.intrinsics.get(~"llvm.cttz.i64");
Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr)
}
+ ~"bswap16" => {
+ let x = get_param(decl, first_real_arg);
+ let cttz = ccx.intrinsics.get(~"llvm.bswap.i16");
+ Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr)
+ }
+ ~"bswap32" => {
+ let x = get_param(decl, first_real_arg);
+ let cttz = ccx.intrinsics.get(~"llvm.bswap.i32");
+ Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr)
+ }
+ ~"bswap64" => {
+ let x = get_param(decl, first_real_arg);
+ let cttz = ccx.intrinsics.get(~"llvm.bswap.i64");
+ Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr)
+ }
_ => {
// Could we make this an enum rather than a string? does it get
// checked earlier?
finish_fn(fcx, lltop);
}
-fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl,
- body: ast::blk, llwrapfn: ValueRef, id: ast::node_id) {
-
+fn trans_foreign_fn(ccx: @crate_ctxt, +path: ast_map::path,
+ decl: ast::fn_decl, body: ast::blk, llwrapfn: ValueRef,
+ id: ast::node_id) {
let _icx = ccx.insn_ctxt("foreign::build_foreign_fn");
- fn build_rust_fn(ccx: @crate_ctxt, path: ast_map::path,
+ fn build_rust_fn(ccx: @crate_ctxt, +path: ast_map::path,
decl: ast::fn_decl, body: ast::blk,
id: ast::node_id) -> ValueRef {
let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn");
let t = ty::node_id_to_type(ccx.tcx, id);
+ // XXX: Bad copy.
let ps = link::mangle_internal_name_by_path(
- ccx, vec::append_one(path, ast_map::path_name(
- syntax::parse::token::special_idents::clownshoe_abi
+ ccx, vec::append_one(copy path, ast_map::path_name(
+ special_idents::clownshoe_abi
)));
let llty = type_of_fn_from_ty(ccx, t);
let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty);
return llfndecl;
}
- fn build_shim_fn(ccx: @crate_ctxt, path: ast_map::path,
+ fn build_shim_fn(ccx: @crate_ctxt, +path: ast_map::path,
llrustfn: ValueRef, tys: @c_stack_tys) -> ValueRef {
-
let _icx = ccx.insn_ctxt("foreign::foreign::build_shim_fn");
fn build_args(bcx: block, tys: @c_stack_tys,
let shim_name = link::mangle_internal_name_by_path(
ccx, vec::append_one(path, ast_map::path_name(
- syntax::parse::token::special_idents::clownshoe_stack_shim
+ special_idents::clownshoe_stack_shim
)));
return build_shim_fn_(ccx, shim_name, llrustfn, tys,
lib::llvm::CCallConv,
let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args");
match tys.x86_64_tys {
option::Some(ref x86_64) => {
- let mut atys = (*x86_64).arg_tys;
- let mut attrs = (*x86_64).attrs;
+ let mut atys = /*bad*/copy (*x86_64).arg_tys;
+ let mut attrs = /*bad*/copy (*x86_64).attrs;
let mut j = 0u;
let llretptr = if (*x86_64).sret {
atys = vec::tail(atys);
let tys = c_stack_tys(ccx, id);
// The internal Rust ABI function - runs on the Rust stack
- let llrustfn = build_rust_fn(ccx, path, decl, body, id);
+ // XXX: Bad copy.
+ let llrustfn = build_rust_fn(ccx, copy path, decl, body, id);
// The internal shim function - runs on the Rust stack
let llshimfn = build_shim_fn(ccx, path, llrustfn, tys);
// The foreign C function - runs on the C stack
build_wrap_fn(ccx, llshimfn, llwrapfn, tys)
}
-fn register_foreign_fn(ccx: @crate_ctxt, sp: span,
- path: ast_map::path, node_id: ast::node_id)
- -> ValueRef {
+fn register_foreign_fn(ccx: @crate_ctxt,
+ sp: span,
+ +path: ast_map::path,
+ node_id: ast::node_id,
+ attrs: &[ast::attribute])
+ -> ValueRef {
let _icx = ccx.insn_ctxt("foreign::register_foreign_fn");
let t = ty::node_id_to_type(ccx.tcx, node_id);
let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, node_id);
let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty);
let x86_64 = x86_64_tys(llargtys, llretty, ret_def);
do decl_x86_64_fn(x86_64) |fnty| {
- register_fn_fuller(ccx, sp, path, node_id,
+ register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs,
+ t, lib::llvm::CCallConv, fnty)
+ }
+ } else if ccx.sess.targ_cfg.arch == arch_arm {
+ let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty);
+ let x86_64 = x86_64_tys(llargtys, llretty, ret_def);
+ do decl_x86_64_fn(x86_64) |fnty| {
+ register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, attrs,
t, lib::llvm::CCallConv, fnty)
}
+
} else {
let llfty = T_fn(llargtys, llretty);
- register_fn_fuller(ccx, sp, path, node_id,
+ register_fn_fuller(ccx, sp, path, node_id, attrs,
t, lib::llvm::CCallConv, llfty)
}
}
},
Some(_) => match attr::foreign_abi(i.attrs) {
either::Right(abi) => abi,
- either::Left(ref msg) => ccx.sess.span_fatal(i.span, (*msg))
+ either::Left(ref msg) => {
+ ccx.sess.span_fatal(i.span, (/*bad*/copy *msg))
+ }
}
}
}
//
// Code relating to taking, dropping, etc as well as type descriptors.
+use core::prelude::*;
+
use lib::llvm::{ValueRef, TypeRef};
use middle::trans::base::*;
+use middle::trans::callee;
+use middle::trans::closure;
use middle::trans::common::*;
use middle::trans::build::*;
+use middle::trans::reflect;
+use middle::trans::tvec;
use middle::trans::type_of::type_of;
+use middle::trans::uniq;
+
+use core::io;
+use core::str;
fn trans_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt("trans_free");
- callee::trans_rtcall(cx, ~"free", ~[PointerCast(cx, v, T_ptr(T_i8()))],
- expr::Ignore)
+ callee::trans_rtcall_or_lang_call(
+ cx,
+ cx.tcx().lang_items.free_fn(),
+ ~[PointerCast(cx, v, T_ptr(T_i8()))],
+ expr::Ignore)
}
fn trans_unique_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt("trans_unique_free");
- callee::trans_rtcall(
- cx, ~"exchange_free", ~[PointerCast(cx, v, T_ptr(T_i8()))],
+ callee::trans_rtcall_or_lang_call(
+ cx,
+ cx.tcx().lang_items.exchange_free_fn(),
+ ~[PointerCast(cx, v, T_ptr(T_i8()))],
expr::Ignore)
}
// Find and call the actual destructor
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
- class_did, substs.tps);
+ class_did, /*bad*/copy substs.tps);
// The second argument is the "self" argument for drop
- let params = lib::llvm::fn_ty_param_tys(
- llvm::LLVMGetElementType(llvm::LLVMTypeOf(dtor_addr)));
+ let params = unsafe {
+ lib::llvm::fn_ty_param_tys(
+ llvm::LLVMGetElementType(llvm::LLVMTypeOf(dtor_addr)))
+ };
// Class dtors have no explicit args, so the params should
// just consist of the output pointer and the environment
} else {
mangle_internal_name_by_seq(ccx, ~"tydesc")
};
- note_unique_llvm_symbol(ccx, name);
+ // XXX: Bad copy.
+ note_unique_llvm_symbol(ccx, copy name);
log(debug, fmt!("+++ declare_tydesc %s %s", ty_to_str(ccx.tcx, t), name));
let gvar = str::as_c_str(name, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
+ unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
+ }
});
let inf =
@{ty: t,
type glue_helper = fn@(block, ValueRef, ty::t);
fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef,
- name: ~str) -> ValueRef {
+ +name: ~str) -> ValueRef {
let _icx = ccx.insn_ctxt("declare_generic_glue");
let name = name;
let mut fn_nm;
fn_nm = mangle_internal_name_by_seq(ccx, (~"glue_" + name));
}
debug!("%s is for type %s", fn_nm, ty_to_str(ccx.tcx, t));
- note_unique_llvm_symbol(ccx, fn_nm);
+ // XXX: Bad copy.
+ note_unique_llvm_symbol(ccx, copy fn_nm);
let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
set_glue_inlining(llfn, t);
return llfn;
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
- let llrawptr0 = llvm::LLVMGetParam(llfn, 3u as c_uint);
+ let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, 3u as c_uint) };
helper(bcx, llrawptr0, t);
finish_fn(fcx, lltop);
return llfn;
match copy ti.take_glue {
None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) }
Some(v) => {
- ccx.stats.n_real_glues += 1u;
- llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ unsafe {
+ ccx.stats.n_real_glues += 1u;
+ llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ }
}
};
let drop_glue =
match copy ti.drop_glue {
None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) }
Some(v) => {
- ccx.stats.n_real_glues += 1u;
- llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ unsafe {
+ ccx.stats.n_real_glues += 1u;
+ llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ }
}
};
let free_glue =
match copy ti.free_glue {
None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) }
Some(v) => {
- ccx.stats.n_real_glues += 1u;
- llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ unsafe {
+ ccx.stats.n_real_glues += 1u;
+ llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ }
}
};
let visit_glue =
match copy ti.visit_glue {
None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) }
Some(v) => {
- ccx.stats.n_real_glues += 1u;
- llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ unsafe {
+ ccx.stats.n_real_glues += 1u;
+ llvm::LLVMConstPointerCast(v, glue_fn_ty)
+ }
}
};
shape, // shape
shape_tables]); // shape_tables
- let gvar = ti.tydesc;
- llvm::LLVMSetInitializer(gvar, tydesc);
- llvm::LLVMSetGlobalConstant(gvar, True);
- lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
-
- // Index tydesc by addrspace.
- if ti.addrspace > gc_box_addrspace {
- let llty = T_ptr(ccx.tydesc_type);
- let addrspace_name = fmt!("_gc_addrspace_metadata_%u",
- ti.addrspace as uint);
- let addrspace_gvar = str::as_c_str(addrspace_name, |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
- });
- lib::llvm::SetLinkage(addrspace_gvar, lib::llvm::InternalLinkage);
- llvm::LLVMSetInitializer(addrspace_gvar, gvar);
+ unsafe {
+ let gvar = ti.tydesc;
+ llvm::LLVMSetInitializer(gvar, tydesc);
+ llvm::LLVMSetGlobalConstant(gvar, True);
+ lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
+
+ // Index tydesc by addrspace.
+ if ti.addrspace > gc_box_addrspace {
+ let llty = T_ptr(ccx.tydesc_type);
+ let addrspace_name = fmt!("_gc_addrspace_metadata_%u",
+ ti.addrspace as uint);
+ let addrspace_gvar = str::as_c_str(addrspace_name, |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
+ });
+ lib::llvm::SetLinkage(addrspace_gvar,
+ lib::llvm::InternalLinkage);
+ llvm::LLVMSetInitializer(addrspace_gvar, gvar);
+ }
}
};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::astencode;
use middle::trans::base::{get_insn_ctxt};
use middle::trans::base::{impl_owned_self, impl_self, no_self};
use middle::trans::base::{trans_item, get_item_val, self_arg, trans_fn};
use middle::trans::common::*;
+use middle::trans::common;
+use middle::trans::inline;
+use middle::trans::monomorphize;
+use core::vec;
use syntax::ast;
use syntax::ast_map::{path, path_mod, path_name};
use syntax::ast_util::local_def;
match csearch::maybe_get_item_ast(
ccx.tcx, fn_id,
|a,b,c,d| {
- astencode::decode_inlined_item(a, b, ccx.maps, c, d)
+ astencode::decode_inlined_item(a, b, ccx.maps,
+ /*bad*/ copy c, d)
}) {
csearch::not_found => {
// Information concerning the machine representation of various types.
+
use middle::trans::common::*;
+use middle::trans::type_of;
+use middle::ty;
+
+use syntax::parse::token::special_idents;
// Creates a simpler, size-equivalent type. The resulting type is guaranteed
// to have (a) the same size as the type that was passed in; (b) to be non-
ty::ty_struct(did, ref substs) => {
let simpl_fields = (if ty::ty_dtor(tcx, did).is_present() {
// remember the drop flag
- ~[{ident: syntax::parse::token::special_idents::dtor,
+ ~[{ident: special_idents::dtor,
mt: {ty: ty::mk_u8(tcx),
mutbl: ast::m_mutbl}}] }
else { ~[] }) +
// Returns the number of bytes clobbered by a Store to this type.
pub fn llsize_of_store(cx: @crate_ctxt, t: TypeRef) -> uint {
- return llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
+ unsafe {
+ return llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
+ }
}
// Returns the number of bytes between successive elements of type T in an
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
pub fn llsize_of_alloc(cx: @crate_ctxt, t: TypeRef) -> uint {
- return llvm::LLVMABISizeOfType(cx.td.lltd, t) as uint;
+ unsafe {
+ return llvm::LLVMABISizeOfType(cx.td.lltd, t) as uint;
+ }
}
// Returns, as near as we can figure, the "real" size of a type. As in, the
// at the codegen level! In general you should prefer `llbitsize_of_real`
// below.
pub fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
- let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint;
- if nbits & 7u != 0u {
- // Not an even number of bytes, spills into "next" byte.
- 1u + (nbits >> 3)
- } else {
- nbits >> 3
+ unsafe {
+ let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint;
+ if nbits & 7u != 0u {
+ // Not an even number of bytes, spills into "next" byte.
+ 1u + (nbits >> 3)
+ } else {
+ nbits >> 3
+ }
}
}
/// Returns the "real" size of the type in bits.
pub fn llbitsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
- llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint
+ unsafe {
+ llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint
+ }
}
// Returns the "default" size of t, which is calculated by casting null to a
// (i.e. including alignment-padding), but goodness knows which alignment it
// winds up using. Probably the ABI one? Not recommended.
pub fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
- return llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t), cx.int_type,
- False);
+ unsafe {
+ return llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t),
+ cx.int_type,
+ False);
+ }
+}
+
+// Returns the "default" size of t (see above), or 1 if the size would
+// be zero. This is important for things like vectors that expect
+// space to be consumed.
+pub fn nonzero_llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
+ if llbitsize_of_real(cx, t) == 0 {
+ unsafe { llvm::LLVMConstInt(cx.int_type, 1, False) }
+ } else {
+ llsize_of(cx, t)
+ }
}
// Returns the preferred alignment of the given type for the current target.
// packing the type into structs. This will be used for things like
// allocations inside a stack frame, which LLVM has a free hand in.
pub fn llalign_of_pref(cx: @crate_ctxt, t: TypeRef) -> uint {
- return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
+ unsafe {
+ return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
+ }
}
// Returns the minimum alignment of a type required by the plattform.
// This is the alignment that will be used for struct fields, arrays,
// and similar ABI-mandated things.
pub fn llalign_of_min(cx: @crate_ctxt, t: TypeRef) -> uint {
- return llvm::LLVMABIAlignmentOfType(cx.td.lltd, t) as uint;
+ unsafe {
+ return llvm::LLVMABIAlignmentOfType(cx.td.lltd, t) as uint;
+ }
}
// Returns the "default" alignment of t, which is calculated by casting
// null to a record containing a single-bit followed by a t value, then
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
pub fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
- return llvm::LLVMConstIntCast(
- lib::llvm::llvm::LLVMAlignOf(t), cx.int_type, False);
+ unsafe {
+ return llvm::LLVMConstIntCast(
+ lib::llvm::llvm::LLVMAlignOf(t), cx.int_type, False);
+ }
}
// Computes the size of the data part of an enum.
let mut max_size = 0u;
let variants = ty::enum_variants(cx.tcx, tid);
for vec::each(*variants) |variant| {
- let tup_ty = simplify_type(cx.tcx,
- ty::mk_tup(cx.tcx, variant.args));
+ let tup_ty = simplify_type(
+ cx.tcx,
+ ty::mk_tup(cx.tcx, /*bad*/copy variant.args));
// Perform any type parameter substitutions.
let tup_ty = ty::subst(cx.tcx, substs, tup_ty);
// Here we possibly do a recursive call.
)
);
-}
\ No newline at end of file
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use back::{link, abi};
+use driver;
use lib::llvm::llvm::LLVMGetParam;
use lib::llvm::llvm;
use lib::llvm::{ValueRef, TypeRef};
+use lib;
use metadata::csearch;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::callee::*;
+use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::expr::{SaveIn, Ignore};
+use middle::trans::expr;
+use middle::trans::glue;
+use middle::trans::inline;
+use middle::trans::monomorphize;
use middle::trans::type_of::*;
+use middle::typeck;
use util::ppaux::{ty_to_str, tys_to_str};
use core::libc::c_uint;
be generated once they are invoked with specific type parameters,
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
*/
-fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident,
+fn trans_impl(ccx: @crate_ctxt, +path: path, name: ast::ident,
methods: ~[@ast::method], tps: ~[ast::ty_param],
self_ty: Option<ty::t>, id: ast::node_id) {
let _icx = ccx.insn_ctxt("impl::trans_impl");
for vec::each(methods) |method| {
if method.tps.len() == 0u {
let llfn = get_item_val(ccx, method.id);
- let path = vec::append_one(sub_path, path_name(method.ident));
+ let path = vec::append_one(/*bad*/copy sub_path,
+ path_name(method.ident));
let param_substs_opt;
match self_ty {
None => param_substs_opt = None,
Some(self_ty) => {
- param_substs_opt = Some({
+ param_substs_opt = Some(param_substs {
tys: ~[],
vtables: None,
bounds: @~[],
- `impl_id`: the node ID of the impl this method is inside
*/
fn trans_method(ccx: @crate_ctxt,
- path: path,
+ +path: path,
method: &ast::method,
- param_substs: Option<param_substs>,
+ +param_substs: Option<param_substs>,
base_self_ty: Option<ty::t>,
llfn: ValueRef,
impl_id: ast::def_id) {
-
// figure out how self is being passed
let self_arg = match method.self_ty.node {
ast::sty_static => {
}
let self_ty = match param_substs {
None => self_ty,
- Some({tys: ref tys, _}) => {
+ Some(param_substs {tys: ref tys, _}) => {
ty::subst_tps(ccx.tcx, *tys, None, self_ty)
}
};
let vtbls = resolve_vtables_in_fn_ctxt(
bcx.fcx, ccx.maps.vtable_map.get(callee_id));
- match vtbls[bound_index] {
+ match /*bad*/copy vtbls[bound_index] {
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
match ccx.tcx.items.get(impl_id.node) {
- ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
- method_from_methods(ms, name).get()
+ ast_map::node_item(@{
+ node: ast::item_impl(_, _, _, ref ms),
+ _
+ }, _) => {
+ method_from_methods(/*bad*/copy *ms, name).get()
}
_ => fail ~"method_with_name"
}
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
match ccx.tcx.items.get(impl_id.node) {
- ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => {
- let did = method_from_methods(ms, name);
+ ast_map::node_item(@{
+ node: ast::item_impl(_, _, _, ref ms), _
+ }, _) => {
+ let did = method_from_methods(/*bad*/copy *ms, name);
if did.is_some() {
return did.get();
} else {
mentry: typeck::method_map_entry,
trait_id: ast::def_id,
n_method: uint,
- vtbl: typeck::vtable_origin)
+ +vtbl: typeck::vtable_origin)
-> Callee
{
let _icx = bcx.insn_ctxt("impl::trans_monomorphized_callee");
mth_did: ast::def_id,
impl_did: ast::def_id,
callee_id: ast::node_id,
- rcvr_substs: ~[ty::t])
+ +rcvr_substs: ~[ty::t])
-> ~[ty::t]
{
/*!
let ccx = bcx.ccx();
let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did);
let node_substs = node_id_type_params(bcx, callee_id);
+ debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t)));
let ty_substs
= vec::append(rcvr_substs,
vec::tailn(node_substs,
node_substs.len() - n_m_tps));
debug!("n_m_tps=%?", n_m_tps);
- debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t)));
debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t)));
debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t)));
let m_origins = vec::tailn(*r_m_origins, r_m_origins.len() - m_vtables);
// Combine rcvr + method to find the final result:
- @vec::append(*rcvr_origins, m_origins)
+ @vec::append(/*bad*/copy *rcvr_origins, m_origins)
}
};
}
-fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id {
+fn vtable_id(ccx: @crate_ctxt, +origin: typeck::vtable_origin) -> mono_id {
match origin {
typeck::vtable_static(impl_id, substs, sub_vtables) => {
monomorphize::make_mono_id(
None)
}
typeck::vtable_trait(trait_id, substs) => {
- @{def: trait_id,
- params: vec::map(substs, |t| mono_precise(*t, None)),
- impl_did_opt: None}
+ @mono_id_ {
+ def: trait_id,
+ params: vec::map(substs, |t| mono_precise(*t, None)),
+ impl_did_opt: None
+ }
}
// can't this be checked at the callee?
_ => fail ~"vtable_id"
}
}
-fn get_vtable(ccx: @crate_ctxt, origin: typeck::vtable_origin)
- -> ValueRef {
- let hash_id = vtable_id(ccx, origin);
+fn get_vtable(ccx: @crate_ctxt, +origin: typeck::vtable_origin) -> ValueRef {
+ // XXX: Bad copy.
+ let hash_id = vtable_id(ccx, copy origin);
match ccx.vtables.find(hash_id) {
Some(val) => val,
None => match origin {
}
fn make_vtable(ccx: @crate_ctxt, ptrs: ~[ValueRef]) -> ValueRef {
- let _icx = ccx.insn_ctxt("impl::make_vtable");
- let tbl = C_struct(ptrs);
- let vt_gvar =
- str::as_c_str(ccx.sess.str_of((ccx.names)(~"vtable")), |buf| {
- llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
- });
- llvm::LLVMSetInitializer(vt_gvar, tbl);
- llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
- lib::llvm::SetLinkage(vt_gvar, lib::llvm::InternalLinkage);
- vt_gvar
+ unsafe {
+ let _icx = ccx.insn_ctxt("impl::make_vtable");
+ let tbl = C_struct(ptrs);
+ let vt_gvar =
+ str::as_c_str(ccx.sess.str_of((ccx.names)(~"vtable")), |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
+ });
+ llvm::LLVMSetInitializer(vt_gvar, tbl);
+ llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
+ lib::llvm::SetLinkage(vt_gvar, lib::llvm::InternalLinkage);
+ vt_gvar
+ }
}
fn make_impl_vtable(ccx: @crate_ctxt, impl_id: ast::def_id, substs: ~[ty::t],
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
- let fty = ty::subst_tps(tcx, substs, None, ty::mk_fn(tcx, im.fty));
+ let fty = ty::subst_tps(tcx, substs, None,
+ ty::mk_fn(tcx, copy im.fty));
if (*im.tps).len() > 0u || ty::type_has_self(fty) {
debug!("(making impl vtable) method has self or type params: %s",
tcx.sess.str_of(im.ident));
}
// Store the vtable into the pair or triple.
- let orig = ccx.maps.vtable_map.get(id)[0];
+ let orig = /*bad*/copy ccx.maps.vtable_map.get(id)[0];
let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig);
let vtable = get_vtable(bcx.ccx(), orig);
Store(bcx, vtable, PointerCast(bcx,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use back::link::mangle_exported_name;
use middle::trans::base::{get_insn_ctxt};
use middle::trans::base::{set_inline_hint_if_appr, set_inline_hint};
use middle::trans::base::{trans_enum_variant, trans_struct_dtor};
use middle::trans::base::{trans_fn, impl_self, decl_internal_cdecl_fn};
use middle::trans::base::{trans_item, get_item_val, no_self, self_arg};
+use middle::trans::base;
use middle::trans::common::*;
+use middle::trans::datum;
+use middle::trans::foreign;
+use middle::trans::machine;
+use middle::trans::meth;
+use middle::trans::shape;
use middle::trans::type_of::type_of_fn_from_ty;
+use middle::trans::type_of;
+use middle::trans::type_use;
use middle::ty::{FnTyBase, FnMeta, FnSig};
+use middle::typeck;
+use core::option;
+use core::vec;
use syntax::ast;
use syntax::ast_map::{path, path_mod, path_name};
use syntax::ast_util::local_def;
for real_substs.each() |s| { assert !ty::type_has_params(*s); }
for substs.each() |s| { assert !ty::type_has_params(*s); }
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
- let hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt,
+ // XXX: Bad copy.
+ let hash_id = make_mono_id(ccx, fn_id, copy substs, vtables, impl_did_opt,
Some(param_uses));
if vec::any(hash_id.params,
|p| match *p { mono_precise(_, _) => false, _ => true }) {
ccx.stats.n_monos += 1;
- let depth = option::get_default(ccx.monomorphizing.find(fn_id), 0u);
+ let depth = option::get_or_default(ccx.monomorphizing.find(fn_id), 0u);
// Random cut-off -- code that needs to instantiate the same function
// recursively more than ten times can probably safely be assumed to be
// causing an infinite expansion.
}
ccx.monomorphizing.insert(fn_id, depth + 1);
- let pt = vec::append(*pt,
+ let pt = vec::append(/*bad*/copy *pt,
~[path_name((ccx.names)(ccx.sess.str_of(name)))]);
- let s = mangle_exported_name(ccx, pt, mono_ty);
+ let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty);
- let mk_lldecl = || {
- let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty);
+ let mk_lldecl = |/*bad*/copy s| {
+ let lldecl = decl_internal_cdecl_fn(ccx.llmod, /*bad*/copy s, llfty);
ccx.monomorphized.insert(hash_id, lldecl);
lldecl
};
- let psubsts = Some({
+ let psubsts = Some(param_substs {
tys: substs,
vtables: vtables,
bounds: tpt.bounds,
let lldecl = match map_node {
ast_map::node_item(i@@{
- node: ast::item_fn(decl, _, _, ref body),
+ // XXX: Bad copy.
+ node: ast::item_fn(copy decl, _, _, ref body),
_
}, _) => {
let d = mk_lldecl();
- set_inline_hint_if_appr(i.attrs, d);
+ set_inline_hint_if_appr(/*bad*/copy i.attrs, d);
trans_fn(ccx, pt, decl, *body, d, no_self, psubsts, fn_id.node, None);
d
}
let d = mk_lldecl();
set_inline_hint(d);
match (*v).node.kind {
- ast::tuple_variant_kind(args) => {
- trans_enum_variant(ccx, enum_item.id, (*v), args,
- this_tv.disr_val, (*tvs).len() == 1u,
+ ast::tuple_variant_kind(ref args) => {
+ trans_enum_variant(ccx, enum_item.id, *v, /*bad*/copy *args,
+ this_tv.disr_val, tvs.len() == 1u,
psubsts, d);
}
ast::struct_variant_kind(_) =>
ast_map::node_method(mth, supplied_impl_did, _) => {
// XXX: What should the self type be here?
let d = mk_lldecl();
- set_inline_hint_if_appr(mth.attrs, d);
+ set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
// Override the impl def ID if necessary.
let impl_did;
None => ccx.sess.span_bug(dtor.span, ~"Bad self ty in \
dtor")
};
- trans_struct_dtor(ccx, *pt, dtor.node.body,
+ trans_struct_dtor(ccx, /*bad*/copy *pt, dtor.node.body,
dtor.node.id, psubsts, Some(hash_id), parent_id)
}
ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
let d = mk_lldecl();
- set_inline_hint_if_appr(mth.attrs, d);
+ set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
debug!("monomorphic_fn impl_did_opt is %?", impl_did_opt);
- meth::trans_method(ccx, *pt, mth, psubsts, None, d,
+ meth::trans_method(ccx, /*bad*/copy *pt, mth, psubsts, None, d,
impl_did_opt.get());
d
}
let d = mk_lldecl();
set_inline_hint(d);
base::trans_tuple_struct(ccx,
- struct_def.fields,
+ /*bad*/copy struct_def.fields,
option::expect(struct_def.ctor_id,
~"ast-mapped tuple struct \
didn't have a ctor id"),
proto: fty.meta.proto,
onceness: ast::Many,
region: ty::re_static,
- bounds: @~[],
- ret_style: ast::return_val},
+ bounds: @~[]},
sig: FnSig {inputs: ~[],
output: ty::mk_nil(tcx)}}))
}
proto: ast::ProtoBox,
onceness: ast::Many,
region: ty::re_static,
- bounds: @~[],
- ret_style: ast::return_val},
+ bounds: @~[]},
sig: FnSig {inputs: ~[],
output: ty::mk_nil(tcx)}}))
}
for bounds.each |bound| {
match *bound {
ty::bound_trait(_) => {
- v.push(meth::vtable_id(ccx, vts[i]));
+ v.push(meth::vtable_id(ccx, /*bad*/copy vts[i]));
i += 1u;
}
_ => ()
}
};
let param_ids = match param_uses {
- Some(uses) => {
- vec::map2(precise_param_ids, uses, |id, uses| {
+ Some(ref uses) => {
+ vec::map2(precise_param_ids, *uses, |id, uses| {
if ccx.sess.no_monomorphic_collapse() {
- match *id {
+ match copy *id {
(a, b) => mono_precise(a, b)
}
} else {
match *id {
- (a, b@Some(_)) => mono_precise(a, b),
+ // XXX: Bad copy.
+ (a, copy b@Some(_)) => mono_precise(a, b),
(subst, None) => {
if *uses == 0u {
mono_any
}
None => {
precise_param_ids.map(|x| {
- let (a, b) = *x;
+ let (a, b) = copy *x;
mono_precise(a, b)
})
}
};
- @{def: item, params: param_ids, impl_did_opt: impl_did_opt}
+ @mono_id_ {def: item, params: param_ids, impl_did_opt: impl_did_opt}
}
// makes all other generics or inline functions that it references
// reachable as well.
+
+use driver::session::*;
+use middle::resolve;
+use middle::ty;
+use middle::typeck;
+
+use core::vec;
+use std::map::HashMap;
use syntax::ast::*;
-use syntax::{visit, ast_util, ast_map};
use syntax::ast_util::def_id_of_def;
use syntax::attr;
use syntax::print::pprust::expr_to_str;
-use std::map::HashMap;
-use driver::session::*;
+use syntax::{visit, ast_util, ast_map};
export map, find_reachable;
-type map = std::map::HashMap<node_id, ()>;
+type map = HashMap<node_id, ()>;
-type ctx = {exp_map2: resolve::ExportMap2,
- tcx: ty::ctxt,
- method_map: typeck::method_map,
- rmap: map};
+struct ctx {
+ exp_map2: resolve::ExportMap2,
+ tcx: ty::ctxt,
+ method_map: typeck::method_map,
+ rmap: map
+}
fn find_reachable(crate_mod: _mod, exp_map2: resolve::ExportMap2,
tcx: ty::ctxt, method_map: typeck::method_map) -> map {
- let rmap = std::map::HashMap();
- let cx = {exp_map2: exp_map2, tcx: tcx,
- method_map: method_map, rmap: rmap};
+ let rmap = HashMap();
+ let cx = ctx {
+ exp_map2: exp_map2,
+ tcx: tcx,
+ method_map: method_map,
+ rmap: rmap
+ };
traverse_public_mod(cx, ast::crate_node_id, crate_mod);
traverse_all_resources_and_impls(cx, crate_mod);
rmap
if did.crate != local_crate { return; }
let n = match cx.tcx.items.find(did.node) {
None => return, // This can happen for self, for example
- Some(ref n) => (*n)
+ Some(ref n) => (/*bad*/copy *n)
};
match n {
ast_map::node_item(item, _) => traverse_public_item(cx, item),
fn traverse_public_item(cx: ctx, item: @item) {
if cx.rmap.contains_key(item.id) { return; }
cx.rmap.insert(item.id, ());
- match item.node {
+ match /*bad*/copy item.node {
item_mod(m) => traverse_public_mod(cx, item.id, m),
item_foreign_mod(nm) => {
if !traverse_exports(cx, item.id) {
}
}
}
- item_fn(_, _, tps, ref blk) => {
+ item_fn(_, _, ref tps, ref blk) => {
if tps.len() > 0u ||
attr::find_inline_attr(item.attrs) != attr::ia_none {
traverse_inline_body(cx, (*blk));
}
fn mk_ty_visitor() -> visit::vt<ctx> {
- visit::mk_vt(@{visit_ty: traverse_ty, ..*visit::default_visitor()})
+ visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty,
+ ..*visit::default_visitor()})
}
fn traverse_ty(ty: @Ty, cx: ctx, v: visit::vt<ctx>) {
fn traverse_item(i: @item, cx: ctx, _v: visit::vt<ctx>) {
traverse_public_item(cx, i);
}
- visit::visit_block(body, cx, visit::mk_vt(@{
+ visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor {
visit_expr: traverse_expr,
visit_item: traverse_item,
..*visit::default_visitor()
}
fn traverse_all_resources_and_impls(cx: ctx, crate_mod: _mod) {
- visit::visit_mod(crate_mod, ast_util::dummy_sp(), 0, cx, visit::mk_vt(@{
- visit_expr: |_e, _cx, _v| { },
- visit_item: |i, cx, v| {
- visit::visit_item(i, cx, v);
- match i.node {
- item_struct(struct_def, _) if struct_def.dtor.is_some() => {
- traverse_public_item(cx, i);
- }
- item_impl(*) => {
- traverse_public_item(cx, i);
- }
- _ => ()
- }
- },
- ..*visit::default_visitor()
- }));
+ visit::visit_mod(
+ crate_mod, ast_util::dummy_sp(), 0, cx,
+ visit::mk_vt(@visit::Visitor {
+ visit_expr: |_e, _cx, _v| { },
+ visit_item: |i, cx, v| {
+ visit::visit_item(i, cx, v);
+ match i.node {
+ item_struct(sdef, _) if sdef.dtor.is_some() => {
+ traverse_public_item(cx, i);
+ }
+ item_impl(*) => {
+ traverse_public_item(cx, i);
+ }
+ _ => ()
+ }
+ },
+ ..*visit::default_visitor()
+ }));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
use back::abi;
use lib::llvm::{TypeRef, ValueRef};
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::callee::{ArgVals, DontAutorefArg};
+use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::datum::*;
use middle::trans::expr::SaveIn;
+use middle::trans::glue;
+use middle::trans::meth;
+use middle::trans::shape;
use middle::trans::type_of::*;
use util::ppaux::ty_to_str;
C_int(self.bcx.ccx(), i)
}
- fn c_slice(s: ~str) -> ValueRef {
- let ss = C_estr_slice(self.bcx.ccx(), s);
- do_spill_noroot(self.bcx, ss)
+ fn c_slice(+s: ~str) -> ValueRef {
+ // We're careful to not use first class aggregates here because that
+ // will kick us off fast isel. (Issue #4352.)
+ let bcx = self.bcx;
+ let str_vstore = ty::vstore_slice(ty::re_static);
+ let str_ty = ty::mk_estr(bcx.tcx(), str_vstore);
+ let scratch = scratch_datum(bcx, str_ty, false);
+ let len = C_uint(bcx.ccx(), s.len() + 1);
+ let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), T_ptr(T_i8()));
+ Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
+ Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
+ scratch.val
}
fn c_size_and_align(t: ty::t) -> ~[ValueRef] {
tcx.sess.ident_of(~"visit_" + ty_name),
*self.visitor_methods).expect(fmt!("Couldn't find visit method \
for %s", ty_name));
- let mth_ty = ty::mk_fn(tcx, self.visitor_methods[mth_idx].fty);
+ let mth_ty = ty::mk_fn(
+ tcx,
+ /*bad*/copy self.visitor_methods[mth_idx].fty);
let v = self.visitor_val;
debug!("passing %u args:", vec::len(args));
let bcx = self.bcx;
self.bcx = next_bcx
}
- fn bracketed(bracket_name: ~str, extra: ~[ValueRef],
+ fn bracketed(bracket_name: ~str, +extra: ~[ValueRef],
inner: fn()) {
- self.visit(~"enter_" + bracket_name, extra);
+ // XXX: Bad copy.
+ self.visit(~"enter_" + bracket_name, copy extra);
inner();
self.visit(~"leave_" + bracket_name, extra);
}
fn vstore_name_and_extra(t: ty::t,
vstore: ty::vstore,
- f: fn(~str,~[ValueRef])) {
+ f: fn(+s: ~str,+v: ~[ValueRef])) {
match vstore {
ty::vstore_fixed(n) => {
let extra = vec::append(~[self.c_uint(n)],
}
}
- fn leaf(name: ~str) {
+ fn leaf(+name: ~str) {
self.visit(name, ~[]);
}
debug!("reflect::visit_ty %s",
ty_to_str(bcx.ccx().tcx, t));
- match ty::get(t).sty {
+ match /*bad*/copy ty::get(t).sty {
ty::ty_bot => self.leaf(~"bot"),
ty::ty_nil => self.leaf(~"nil"),
ty::ty_bool => self.leaf(~"bool"),
ast::extern_fn => 3u
};
let protoval = ast_proto_constant(fty.meta.proto);
- let retval = match fty.meta.ret_style {
- ast::noreturn => 0u,
- ast::return_val => 1u
- };
+ let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
let extra = ~[self.c_uint(pureval),
self.c_uint(protoval),
self.c_uint(vec::len(fty.sig.inputs)),
self.c_uint(retval)];
- self.visit(~"enter_fn", extra);
+ self.visit(~"enter_fn", copy extra); // XXX: Bad copy.
for fty.sig.inputs.eachi |i, arg| {
let modeval = match arg.mode {
ast::infer(_) => 0u,
// A "shape" is a compact encoding of a type that is used by interpreted glue.
// This substitutes for the runtime tags used by e.g. MLs.
+
use back::abi;
use lib::llvm::llvm;
use lib::llvm::{True, False, ModuleRef, TypeRef, ValueRef};
use middle::trans::base;
use middle::trans::common::*;
use middle::trans::machine::*;
+use middle::trans;
use middle::ty::field;
use middle::ty;
use util::ppaux::ty_to_str;
use core::dvec::DVec;
use core::option::is_some;
+use core::vec;
use std::map::HashMap;
use syntax::ast;
use syntax::ast_util::dummy_sp;
fn mk_global(ccx: @crate_ctxt, name: ~str, llval: ValueRef, internal: bool) ->
ValueRef {
- let llglobal = do str::as_c_str(name) |buf| {
- lib::llvm::llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf)
- };
- lib::llvm::llvm::LLVMSetInitializer(llglobal, llval);
- lib::llvm::llvm::LLVMSetGlobalConstant(llglobal, True);
+ unsafe {
+ let llglobal = do str::as_c_str(name) |buf| {
+ llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf)
+ };
+ llvm::LLVMSetInitializer(llglobal, llval);
+ llvm::LLVMSetGlobalConstant(llglobal, True);
- if internal {
- lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
- }
+ if internal {
+ ::lib::llvm::SetLinkage(llglobal,
+ ::lib::llvm::InternalLinkage);
+ }
- return llglobal;
+ return llglobal;
+ }
}
fn mk_ctxt(llmod: ModuleRef) -> ctxt {
- let llshapetablesty = trans::common::T_named_struct(~"shapes");
- let _llshapetables = str::as_c_str(~"shapes", |buf| {
- lib::llvm::llvm::LLVMAddGlobal(llmod, llshapetablesty, buf)
- });
+ unsafe {
+ let llshapetablesty = trans::common::T_named_struct(~"shapes");
+ let _llshapetables = str::as_c_str(~"shapes", |buf| {
+ llvm::LLVMAddGlobal(llmod, llshapetablesty, buf)
+ });
- return {mut next_tag_id: 0u16, pad: 0u16, pad2: 0u32};
+ return {mut next_tag_id: 0u16, pad: 0u16, pad2: 0u32};
+ }
}
/*
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
use back::abi;
use lib::llvm::{ValueRef, TypeRef};
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::datum::*;
use middle::trans::expr::{Dest, Ignore, SaveIn};
-use middle::trans::shape::llsize_of;
+use middle::trans::expr;
+use middle::trans::glue;
+use middle::trans::shape::{llsize_of, nonzero_llsize_of};
+use middle::trans::type_of;
+use middle::ty;
use util::common::indenter;
use util::ppaux::ty_to_str;
let _icx = bcx.insn_ctxt("tvec::alloc_uniq");
let ccx = bcx.ccx();
let llunitty = type_of::type_of(ccx, unit_ty);
- let unit_sz = llsize_of(ccx, llunitty);
+ let unit_sz = nonzero_llsize_of(ccx, llunitty);
let fill = Mul(bcx, C_uint(ccx, elts), unit_sz);
let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) }
// Handle the &"..." case:
match content_expr.node {
- ast::expr_lit(@{node: ast::lit_str(s), span: _}) => {
+ ast::expr_lit(@ast::spanned {node: ast::lit_str(s), span: _}) => {
return trans_lit_str(bcx, content_expr, s, dest);
}
_ => {}
match dest {
Ignore => bcx,
SaveIn(lldest) => {
- let bytes = lit_str.len() + 1; // count null-terminator too
- let llbytes = C_uint(bcx.ccx(), bytes);
- let llcstr = C_cstr(bcx.ccx(), *lit_str);
- let llcstr = llvm::LLVMConstPointerCast(llcstr, T_ptr(T_i8()));
- Store(bcx, llcstr, GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
- Store(bcx, llbytes, GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
- bcx
+ unsafe {
+ let bytes = lit_str.len() + 1; // count null-terminator too
+ let llbytes = C_uint(bcx.ccx(), bytes);
+ let llcstr = C_cstr(bcx.ccx(), /*bad*/copy *lit_str);
+ let llcstr = llvm::LLVMConstPointerCast(llcstr,
+ T_ptr(T_i8()));
+ Store(bcx,
+ llcstr,
+ GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
+ Store(bcx,
+ llbytes,
+ GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
+ bcx
+ }
}
}
}
bcx.expr_to_str(vstore_expr));
let _indenter = indenter();
- match content_expr.node {
- ast::expr_lit(@{node: ast::lit_str(s), span: _}) => {
+ match /*bad*/copy content_expr.node {
+ ast::expr_lit(@ast::spanned { node: ast::lit_str(s), _ }) => {
match dest {
Ignore => {
return bcx;
SaveIn(lldest) => {
let bytes = s.len() + 1; // copy null-terminator too
let llbytes = C_uint(bcx.ccx(), bytes);
- let llcstr = C_cstr(bcx.ccx(), *s);
+ let llcstr = C_cstr(bcx.ccx(), /*bad*/copy *s);
base::call_memcpy(bcx, lldest, llcstr, llbytes);
return bcx;
}
let ccx = bcx.ccx();
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunit_ty = type_of::type_of(ccx, unit_ty);
- let llunit_size = llsize_of(ccx, llunit_ty);
+ let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
+
VecTypes {vec_ty: vec_ty,
unit_ty: unit_ty,
llunit_ty: llunit_ty,
fn elements_required(bcx: block, content_expr: @ast::expr) -> uint {
//! Figure out the number of elements we need to store this content
- match content_expr.node {
- ast::expr_lit(@{node: ast::lit_str(s), span: _}) => s.len() + 1,
+ match /*bad*/copy content_expr.node {
+ ast::expr_lit(@ast::spanned { node: ast::lit_str(s), _ }) => {
+ s.len() + 1
+ },
ast::expr_vec(es, _) => es.len(),
ast::expr_repeat(_, count_expr, _) => {
ty::eval_repeat_count(bcx.tcx(), count_expr, content_expr.span)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
use lib::llvm::llvm;
use lib::llvm::{TypeRef};
use middle::trans::common::*;
+use middle::trans::common;
+use middle::trans::expr;
+use util::ppaux;
use std::map::HashMap;
use syntax::ast;
fn type_of_fn(cx: @crate_ctxt, inputs: ~[ty::arg],
output: ty::t) -> TypeRef {
- let mut atys: ~[TypeRef] = ~[];
+ unsafe {
+ let mut atys: ~[TypeRef] = ~[];
- // Arg 0: Output pointer.
- atys.push(T_ptr(type_of(cx, output)));
+ // Arg 0: Output pointer.
+ atys.push(T_ptr(type_of(cx, output)));
- // Arg 1: Environment
- atys.push(T_opaque_box_ptr(cx));
+ // Arg 1: Environment
+ atys.push(T_opaque_box_ptr(cx));
- // ... then explicit args.
- atys.push_all(type_of_explicit_args(cx, inputs));
- return T_fn(atys, llvm::LLVMVoidType());
+ // ... then explicit args.
+ atys.push_all(type_of_explicit_args(cx, inputs));
+ return T_fn(atys, llvm::LLVMVoidType());
+ }
}
// Given a function type and a count of ty params, construct an llvm type
return llty;
}
- let llty = match ty::get(t).sty {
+ // XXX: This is a terrible terrible copy.
+ let llty = match /*bad*/copy ty::get(t).sty {
ty::ty_nil | ty::ty_bot => T_nil(),
ty::ty_bool => T_bool(),
ty::ty_int(t) => T_int_ty(cx, t),
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
- common::T_named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
+ common::T_named_struct(llvm_type_name(cx,
+ an_enum,
+ did,
+ /*bad*/copy substs.tps))
}
ty::ty_estr(ty::vstore_box) => {
T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive struct types.
- common::T_named_struct(llvm_type_name(cx, a_struct, did, substs.tps))
+ common::T_named_struct(llvm_type_name(cx,
+ a_struct,
+ did,
+ /*bad*/ copy substs.tps))
}
ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"),
debug!("type_of_enum %?: %?", t, ty::get(t));
let lltys = {
- let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
+ let degen = ty::enum_is_univariant(cx.tcx, did);
let size = shape::static_size_of_enum(cx, t);
if !degen {
~[T_enum_discrim(cx), T_array(T_i8(), size)]
return fmt!(
"%s %s[#%d]",
name,
- util::ppaux::parameterized(
+ ppaux::parameterized(
cx.tcx,
ty::item_path_str(cx.tcx, did),
None,
}
fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
- T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer
- T_ptr(type_of(ccx, self_ty))], // self arg
- llvm::LLVMVoidType())
+ unsafe {
+ T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer
+ T_ptr(type_of(ccx, self_ty))], // self arg
+ llvm::LLVMVoidType())
+ }
}
fn type_of_rooted(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
// much information, but have the disadvantage of being very
// invasive.)
+
use metadata::csearch;
+use middle::freevars;
use middle::trans::common::*;
+use middle::trans::inline;
+use core::option;
+use core::uint;
+use core::vec;
use std::list::{List, Cons, Nil};
use std::list;
use std::map::HashMap;
if fn_id_loc.crate != local_crate {
let uses = vec::from_mut(copy cx.uses);
- ccx.type_use_cache.insert(fn_id, uses);
+ ccx.type_use_cache.insert(fn_id, copy uses);
return uses;
}
let map_node = match ccx.tcx.items.find(fn_id_loc.node) {
- Some(ref x) => (*x),
+ Some(ref x) => (/*bad*/copy *x),
None => ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?",
fn_id_loc))
};
~"ctlz8" | ~"ctlz16" | ~"ctlz32" | ~"ctlz64" => 0,
~"cttz8" | ~"cttz16" | ~"cttz32" | ~"cttz64" => 0,
+ ~"bswap16" | ~"bswap32" | ~"bswap64" => 0,
+
// would be cool to make these an enum instead of strings!
_ => fail ~"unknown intrinsic in type_use"
};
}
}
let uses = vec::from_mut(copy cx.uses);
- ccx.type_use_cache.insert(fn_id, uses);
+ // XXX: Bad copy, use @vec instead?
+ ccx.type_use_cache.insert(fn_id, copy uses);
uses
}
}
fn handle_body(cx: ctx, body: blk) {
- let v = visit::mk_vt(@{
+ let v = visit::mk_vt(@visit::Visitor {
visit_expr: |e, cx, v| {
visit::visit_expr(e, cx, v);
mark_for_expr(cx, e);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
+use back;
use lib::llvm::ValueRef;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::datum::immediate_rvalue;
+use middle::trans::datum;
+use middle::trans::glue;
use syntax::ast;
#[warn(deprecated_pattern)];
-use core::dvec::DVec;
-use std::{map, smallintmap};
-use result::Result;
-use std::map::HashMap;
+use core::prelude::*;
+
use driver::session;
-use session::Session;
-use syntax::{ast, ast_map};
-use syntax::ast_util;
-use syntax::ast_util::{is_local, local_def};
-use syntax::codemap::span;
use metadata::csearch;
-use util::ppaux::{region_to_str, explain_region, vstore_to_str,
- note_and_explain_region, bound_region_to_str};
-use middle::lint;
+use metadata;
+use middle::const_eval;
+use middle::freevars;
use middle::lint::{get_lint_level, allow};
-use syntax::ast::*;
-use syntax::print::pprust::*;
-use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
+use middle::lint;
use middle::resolve::{Impl, MethodInfo};
+use middle::resolve;
+use middle::ty;
+use middle::typeck;
+use middle;
+use session::Session;
+use util::ppaux::{note_and_explain_region, bound_region_to_str};
+use util::ppaux::{region_to_str, explain_region, vstore_to_str};
+use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
+
+use core::cast;
+use core::cmp;
+use core::dvec::DVec;
+use core::dvec;
+use core::ops;
+use core::option;
+use core::ptr::to_unsafe_ptr;
+use core::result::Result;
+use core::result;
+use core::to_bytes;
+use core::uint;
+use core::vec;
+use std::map::HashMap;
+use std::{map, smallintmap};
+use syntax::ast::*;
+use syntax::ast_util::{is_local, local_def};
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::print::pprust;
+use syntax::{ast, ast_map};
+use syntax;
export ProvidedMethodSource;
export ProvidedMethodInfo;
export ProvidedMethodsMap;
export InstantiatedTraitRef;
-export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid;
+export TyVid, IntVid, FloatVid, FnVid, RegionVid, Vid;
export br_hashmap;
export is_instantiable;
export node_id_to_type;
export expr_is_lval, expr_kind;
export ExprKind, LvalueExpr, RvalueDatumExpr, RvalueDpsExpr, RvalueStmtExpr;
export field_ty;
-export fold_ty, fold_sty_to_ty, fold_region, fold_regions;
+export fold_ty, fold_sty_to_ty, fold_region, fold_regions, fold_sig;
export apply_op_on_t_to_ty_fn;
export fold_regions_and_ty, walk_regions_and_ty;
export field;
export ty_opaque_box, mk_opaque_box;
export ty_float, mk_float, mk_mach_float, type_is_fp;
export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn;
-export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
+export ty_fn_proto, ty_fn_purity, ty_fn_ret, tys_in_fn_sig;
+export replace_fn_return_type;
export ty_int, mk_int, mk_mach_int, mk_char;
export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
export mk_f32, mk_f64;
export ty_type, mk_type;
export ty_uint, mk_uint, mk_mach_uint;
export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
-export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var, mk_float_var;
+export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var;
+export mk_float_var;
export InferTy, TyVar, IntVar, FloatVar;
export ValueMode, ReadValue, CopyValue, MoveValue;
export ty_self, mk_self, type_has_self;
export Region, bound_region, encl_region;
export re_bound, re_free, re_scope, re_static, re_infer;
export ReVar, ReSkolemized;
-export br_self, br_anon, br_named, br_cap_avoid;
+export br_self, br_anon, br_named, br_cap_avoid, br_fresh;
export get, type_has_params, type_needs_infer, type_has_regions;
-export type_is_region_ptr;
+export type_contains_err, type_is_region_ptr;
export type_id;
export tbox_has_flag;
export ty_var_id;
export meta_kind, kind_lteq, type_kind, type_kind_ext;
export operators;
export type_err, terr_vstore_kind;
-export terr_mismatch, terr_onceness_mismatch;
+export terr_integer_as_char, terr_mismatch, terr_onceness_mismatch;
export type_err_to_str, note_and_explain_type_err;
export expected_found;
export type_needs_drop;
+export type_is_char;
export type_is_empty;
export type_is_integral;
export type_is_numeric;
export terr_regions_insufficiently_polymorphic;
export terr_regions_overly_polymorphic;
export terr_proto_mismatch;
-export terr_ret_style_mismatch;
export terr_fn, terr_trait;
-export purity_to_str;
export onceness_to_str;
export param_tys_in_type;
export eval_repeat_count;
}
}
-type intern_key = {sty: sty, o_def_id: Option<ast::def_id>};
+type intern_key = {sty: *sty, o_def_id: Option<ast::def_id>};
impl intern_key : cmp::Eq {
pure fn eq(&self, other: &intern_key) -> bool {
- (*self).sty == (*other).sty && (*self).o_def_id == (*other).o_def_id
+ unsafe {
+ *self.sty == *other.sty && self.o_def_id == other.o_def_id
+ }
}
pure fn ne(&self, other: &intern_key) -> bool { !(*self).eq(other) }
}
impl intern_key : to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
- to_bytes::iter_bytes_2(&self.sty, &self.o_def_id, lsb0, f);
+ unsafe {
+ to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f);
+ }
}
}
has_self = 2,
needs_infer = 4,
has_regions = 8,
+ has_ty_err = 16,
// a meta-flag: subst may be required if the type has parameters, a self
// type, or references bound regions
pure fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
pure fn type_needs_infer(t: t) -> bool { tbox_has_flag(get(t), needs_infer) }
pure fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) }
+pure fn type_contains_err(t: t) -> bool { tbox_has_flag(get(t), has_ty_err) }
pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
pure fn type_id(t: t) -> uint { get(t).id }
* - `onceness` indicates whether the function can be called one time or many
* times.
* - `region` is the region bound on the function's upvars (often &static).
- * - `bounds` is the parameter bounds on the function's upvars.
- * - `ret_style` indicates whether the function returns a value or fails. */
+ * - `bounds` is the parameter bounds on the function's upvars. */
+#[deriving_eq]
struct FnMeta {
purity: ast::purity,
proto: ast::Proto,
onceness: ast::Onceness,
region: Region,
- bounds: @~[param_bound],
- ret_style: ret_style
+ bounds: @~[param_bound]
}
/**
*
* - `inputs` is the list of arguments and their modes.
* - `output` is the return type. */
+#[deriving_eq]
struct FnSig {
inputs: ~[arg],
output: t
* type signature. This particular type is parameterized
* by the meta information because, in some cases, the
* meta information is inferred. */
+#[deriving_eq]
struct FnTyBase<M: cmp::Eq> {
- meta: M,
- sig: FnSig
+ meta: M, // Either FnMeta or FnVid
+ sig: FnSig // Types of arguments/return type
+}
+
+impl<M: to_bytes::IterBytes> FnTyBase<M> : to_bytes::IterBytes {
+ pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+ to_bytes::iter_bytes_2(&self.meta, &self.sig, lsb0, f)
+ }
}
type FnTy = FnTyBase<FnMeta>;
/// Named region parameters for functions (a in &a/T)
br_named(ast::ident),
+ /// Fresh bound identifiers created during GLB computations.
+ br_fresh(uint),
+
/**
* Handles capture-avoiding substitution in a rather subtle case. If you
* have a closure whose argument types are being inferred based on the
ty_param(param_ty), // type parameter
ty_self, // special, implicit `self` type parameter
- ty_infer(InferTy), // soething used only during inference/typeck
+ ty_infer(InferTy), // something used only during inference/typeck
ty_err, // Also only used during inference/typeck, to represent
// the type of an erroneous expression (helps cut down
// on non-useful type error messages)
// Data structures used in type unification
enum type_err {
terr_mismatch,
- terr_ret_style_mismatch(expected_found<ast::ret_style>),
terr_purity_mismatch(expected_found<purity>),
terr_onceness_mismatch(expected_found<Onceness>),
terr_mutability,
terr_in_field(@type_err, ast::ident),
terr_sorts(expected_found<t>),
terr_self_substs,
+ terr_integer_as_char,
terr_no_integral_type,
terr_no_floating_point_type,
}
#[auto_decode]
enum RegionVid = uint;
+#[deriving_eq]
enum InferTy {
TyVar(TyVid),
IntVar(IntVid),
match *self {
TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
- FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f)
+ FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f),
}
}
}
}
}
-trait vid {
+trait Vid {
pure fn to_uint() -> uint;
- pure fn to_str() -> ~str;
}
-impl TyVid: vid {
+impl TyVid: Vid {
pure fn to_uint() -> uint { *self }
+}
+
+impl TyVid: ToStr {
pure fn to_str() -> ~str { fmt!("<V%u>", self.to_uint()) }
}
-impl IntVid: vid {
+impl IntVid: Vid {
pure fn to_uint() -> uint { *self }
+}
+
+impl IntVid: ToStr {
pure fn to_str() -> ~str { fmt!("<VI%u>", self.to_uint()) }
}
-impl FloatVid: vid {
+impl FloatVid: Vid {
pure fn to_uint() -> uint { *self }
+}
+
+impl FloatVid: ToStr {
pure fn to_str() -> ~str { fmt!("<VF%u>", self.to_uint()) }
}
-impl FnVid: vid {
+impl FnVid: Vid {
pure fn to_uint() -> uint { *self }
+}
+
+impl FnVid: ToStr {
pure fn to_str() -> ~str { fmt!("<F%u>", self.to_uint()) }
}
-impl RegionVid: vid {
+impl RegionVid: Vid {
pure fn to_uint() -> uint { *self }
- pure fn to_str() -> ~str { fmt!("%?", self) }
}
-impl InferTy {
- pure fn to_hash() -> uint {
- match self {
- TyVar(v) => v.to_uint() << 1,
- IntVar(v) => (v.to_uint() << 1) + 1,
- FloatVar(v) => (v.to_uint() << 1) + 2
- }
- }
+impl RegionVid: ToStr {
+ pure fn to_str() -> ~str { fmt!("%?", self) }
+}
+impl FnSig : ToStr {
pure fn to_str() -> ~str {
- match self {
- TyVar(v) => v.to_str(),
- IntVar(v) => v.to_str(),
- FloatVar(v) => v.to_str()
- }
+ // grr, without tcx not much we can do.
+ return ~"(...)";
}
}
-trait purity_to_str {
- pure fn to_str() -> ~str;
-}
-
-impl purity: purity_to_str {
+impl InferTy: ToStr {
pure fn to_str() -> ~str {
- purity_to_str(self)
+ match self {
+ TyVar(ref v) => v.to_str(),
+ IntVar(ref v) => v.to_str(),
+ FloatVar(ref v) => v.to_str()
+ }
}
}
// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for t above).
fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
- let key = {sty: st, o_def_id: o_def_id};
+ let key = {sty: to_unsafe_ptr(&st), o_def_id: o_def_id};
match cx.interner.find(key) {
Some(t) => unsafe { return cast::reinterpret_cast(&t); },
_ => ()
}
+
let mut flags = 0u;
fn rflags(r: Region) -> uint {
(has_regions as uint) | {
substs.self_r.iter(|r| f |= rflags(*r));
return f;
}
- match st {
- ty_estr(vstore_slice(r)) => {
+ match &st {
+ &ty_estr(vstore_slice(r)) => {
flags |= rflags(r);
}
- ty_evec(mt, vstore_slice(r)) => {
+ &ty_evec(ref mt, vstore_slice(r)) => {
flags |= rflags(r);
flags |= get(mt.ty).flags;
}
- ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
- ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
- ty_opaque_box | ty_err => (),
- ty_param(_) => flags |= has_params as uint,
- ty_infer(_) => flags |= needs_infer as uint,
- ty_self => flags |= has_self as uint,
- ty_enum(_, ref substs) | ty_struct(_, ref substs)
- | ty_trait(_, ref substs, _) => {
+ &ty_nil | &ty_bot | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
+ &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
+ &ty_opaque_box => (),
+ &ty_err => flags |= has_ty_err as uint,
+ &ty_param(_) => flags |= has_params as uint,
+ &ty_infer(_) => flags |= needs_infer as uint,
+ &ty_self => flags |= has_self as uint,
+ &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
+ &ty_trait(_, ref substs, _) => {
flags |= sflags(substs);
}
- ty_box(m) | ty_uniq(m) | ty_evec(m, _) |
- ty_ptr(m) | ty_unboxed_vec(m) => {
+ &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
+ &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
flags |= get(m.ty).flags;
}
- ty_rptr(r, m) => {
+ &ty_rptr(r, ref m) => {
flags |= rflags(r);
flags |= get(m.ty).flags;
}
- ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
- ty_tup(ts) => for ts.each |tt| { flags |= get(*tt).flags; },
- ty_fn(ref f) => {
+ &ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
+ &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
+ &ty_fn(ref f) => {
flags |= rflags(f.meta.region);
for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
flags |= get(f.sig.output).flags;
}
}
- let t = @{sty: st, id: cx.next_id, flags: flags, o_def_id: o_def_id};
- cx.interner.insert(key, t);
+
+ let t = @{sty: move st, id: cx.next_id, flags: flags, o_def_id: o_def_id};
+
+ let key = {sty: to_unsafe_ptr(&t.sty), o_def_id: o_def_id};
+ cx.interner.insert(move key, t);
+
cx.next_id += 1u;
unsafe { cast::reinterpret_cast(&t) }
}
mk_t(cx, ty_unboxed_vec({ty: ty, mutbl: ast::m_imm}))
}
-fn mk_rec(cx: ctxt, fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
+fn mk_rec(cx: ctxt, +fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
-fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
+fn mk_tup(cx: ctxt, +ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
// take a copy because we want to own the various vectors inside
fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) }
fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
-fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
+fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) }
fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t {
- mk_t_with_id(cx, get(base).sty, Some(def_id))
+ mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id))
}
// Converts s to its machine type equivalent
ty_int(ast::ty_i) => ty_int(cfg.int_type),
ty_uint(ast::ty_u) => ty_uint(cfg.uint_type),
ty_float(ast::ty_f) => ty_float(cfg.float_type),
- ref s => (*s)
+ ref s => (/*bad*/copy *s)
}
}
fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
if !f(ty) { return; }
- match get(ty).sty {
+ match /*bad*/copy get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_box | ty_self |
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
mk_t(tcx, fold_sty(sty, foldop))
}
+fn fold_sig(sig: &FnSig, fldop: fn(t) -> t) -> FnSig {
+ let args = do sig.inputs.map |arg| {
+ { mode: arg.mode, ty: fldop(arg.ty) }
+ };
+
+ FnSig {
+ inputs: move args,
+ output: fldop(sig.output)
+ }
+}
+
fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
fn fold_substs(substs: &substs, fldop: fn(t) -> t) -> substs {
{self_r: substs.self_r,
tps: substs.tps.map(|t| fldop(*t))}
}
- match *sty {
+ match /*bad*/copy *sty {
ty_box(tm) => {
ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl})
}
ty_tup(new_ts)
}
ty_fn(ref f) => {
- let new_args = f.sig.inputs.map(|a| {
- let new_ty = fldop(a.ty);
- {mode: a.mode, ty: new_ty}
- });
- let new_output = fldop(f.sig.output);
- ty_fn(FnTyBase {
- meta: f.meta,
- sig: FnSig {inputs: new_args, output: new_output}
- })
+ let sig = fold_sig(&f.sig, fldop);
+ ty_fn(FnTyBase {meta: f.meta, sig: sig})
}
ty_rptr(r, tm) => {
ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl})
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
- *sty
+ /*bad*/copy *sty
}
}
}
fn fold_substs(
substs: &substs,
fldr: fn(r: Region) -> Region,
- fldt: fn(t: t) -> t) -> substs {
-
+ fldt: fn(t: t) -> t) -> substs
+ {
{self_r: substs.self_r.map(|r| fldr(*r)),
self_ty: substs.self_ty.map(|t| fldt(*t)),
tps: substs.tps.map(|t| fldt(*t))}
ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
}
ty_fn(ref f) => {
- let new_region = fldr(f.meta.region);
- let new_args = vec::map(f.sig.inputs, |a| {
- let new_ty = fldfnt(a.ty);
- {mode: a.mode, ty: new_ty}
- });
- let new_output = fldfnt(f.sig.output);
- ty::mk_fn(cx, FnTyBase {
- meta: FnMeta {region: new_region,
- ..f.meta},
- sig: FnSig {inputs: new_args,
- output: new_output}
- })
+ ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region),
+ ..f.meta},
+ sig: fold_sig(&f.sig, fldfnt)})
}
ref sty => {
fold_sty_to_ty(cx, sty, |t| fldt(t))
f: &FnTy,
t_op: fn(t) -> t) -> FnTy
{
- let t0 = ty::mk_fn(cx, *f);
+ let t0 = ty::mk_fn(cx, /*bad*/copy *f);
let t1 = t_op(t0);
match ty::get(t1).sty {
ty::ty_fn(copy f) => {
fn fold_regions(
cx: ctxt,
ty: t,
- fldr: fn(r: Region, in_fn: bool) -> Region) -> t {
-
+ fldr: fn(r: Region, in_fn: bool) -> Region) -> t
+{
fn do_fold(cx: ctxt, ty: t, in_fn: bool,
fldr: fn(Region, bool) -> Region) -> t {
+ debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
if !type_has_regions(ty) { return ty; }
fold_regions_and_ty(
cx, ty,
fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
fmt!("substs(self_r=%s, self_ty=%s, tps=%?)",
substs.self_r.map_default(~"none", |r| region_to_str(cx, *r)),
- substs.self_ty.map_default(~"none", |t| ty_to_str(cx, *t)),
+ substs.self_ty.map_default(~"none",
+ |t| ::util::ppaux::ty_to_str(cx, *t)),
tys_to_str(cx, substs.tps))
}
fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str {
match *pb {
bound_copy => ~"copy",
- bound_durable => ~"durable",
+ bound_durable => ~"&static",
bound_owned => ~"owned",
bound_const => ~"const",
- bound_trait(t) => ty_to_str(cx, t)
+ bound_trait(t) => ::util::ppaux::ty_to_str(cx, t)
}
}
debug!("subst(substs=%s, typ=%s)",
substs_to_str(cx, substs),
- ty_to_str(cx, typ));
+ ::util::ppaux::ty_to_str(cx, typ));
if substs_is_noop(substs) { return typ; }
let r = do_subst(cx, substs, typ);
- debug!(" r = %s", ty_to_str(cx, r));
+ debug!(" r = %s", ::util::ppaux::ty_to_str(cx, r));
return r;
fn do_subst(cx: ctxt,
fold_regions_and_ty(
cx, typ,
|r| match r {
- re_bound(br_self) => substs.self_r.expect(
- fmt!("ty::subst: \
- Reference to self region when given substs with no \
- self region, ty = %s", ty_to_str(cx, typ))),
+ re_bound(br_self) => {
+ match substs.self_r {
+ None => {
+ cx.sess.bug(
+ fmt!("ty::subst: \
+ Reference to self region when given substs \
+ with no self region, ty = %s",
+ ::util::ppaux::ty_to_str(cx, typ)))
+ }
+ Some(self_r) => self_r
+ }
+ }
_ => r
},
|t| do_subst(cx, substs, t),
}
fn get_element_type(ty: t, i: uint) -> t {
- match get(ty).sty {
+ match /*bad*/copy get(ty).sty {
ty_rec(flds) => return flds[i].mt.ty,
ty_tup(ts) => return ts[i],
_ => fail ~"get_element_type called on invalid type"
}
let mut accum = false;
- let result = match get(ty).sty {
+ let result = match /*bad*/copy get(ty).sty {
// scalar types
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_type | ty_ptr(_) | ty_rptr(_, _) |
// Insert a default in case we loop back on self recursively.
cx.kind_cache.insert(ty, kind_top());
- let mut result = match get(ty).sty {
+ let mut result = match /*bad*/copy get(ty).sty {
// Scalar and unique types are sendable, constant, and owned
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_ptr(_) => {
/// gives a rough estimate of how much space it takes to represent
/// an instance of `ty`. Used for the mode transition.
fn type_size(cx: ctxt, ty: t) -> uint {
- match get(ty).sty {
+ match /*bad*/copy get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_ptr(_) | ty_box(_) | ty_uniq(_) | ty_estr(vstore_uniq) |
ty_trait(*) | ty_rptr(*) | ty_evec(_, vstore_uniq) |
fn type_requires(cx: ctxt, seen: @mut ~[def_id],
r_ty: t, ty: t) -> bool {
debug!("type_requires(%s, %s)?",
- ty_to_str(cx, r_ty),
- ty_to_str(cx, ty));
+ ::util::ppaux::ty_to_str(cx, r_ty),
+ ::util::ppaux::ty_to_str(cx, ty));
let r = {
get(r_ty).sty == get(ty).sty ||
};
debug!("type_requires(%s, %s)? %b",
- ty_to_str(cx, r_ty),
- ty_to_str(cx, ty),
+ ::util::ppaux::ty_to_str(cx, r_ty),
+ ::util::ppaux::ty_to_str(cx, ty),
r);
return r;
}
fn subtypes_require(cx: ctxt, seen: @mut ~[def_id],
r_ty: t, ty: t) -> bool {
debug!("subtypes_require(%s, %s)?",
- ty_to_str(cx, r_ty),
- ty_to_str(cx, ty));
+ ::util::ppaux::ty_to_str(cx, r_ty),
+ ::util::ppaux::ty_to_str(cx, ty));
- let r = match get(ty).sty {
+ let r = match /*bad*/copy get(ty).sty {
ty_nil |
ty_bot |
ty_bool |
};
debug!("subtypes_require(%s, %s)? %b",
- ty_to_str(cx, r_ty),
- ty_to_str(cx, ty),
+ ::util::ppaux::ty_to_str(cx, r_ty),
+ ::util::ppaux::ty_to_str(cx, ty),
r);
return r;
fn type_structurally_contains(cx: ctxt, ty: t, test: fn(x: &sty) -> bool) ->
bool {
let sty = &get(ty).sty;
- debug!("type_structurally_contains: %s", ty_to_str(cx, ty));
+ debug!("type_structurally_contains: %s",
+ ::util::ppaux::ty_to_str(cx, ty));
if test(sty) { return true; }
- match *sty {
+ match /*bad*/copy *sty {
ty_enum(did, ref substs) => {
for vec::each(*enum_variants(cx, did)) |variant| {
for variant.args.each |aty| {
}
}
+fn type_is_char(ty: t) -> bool {
+ match get(ty).sty {
+ ty_int(ty_char) => true,
+ _ => false
+ }
+}
+
fn type_is_fp(ty: t) -> bool {
match get(ty).sty {
ty_infer(FloatVar(_)) | ty_float(_) => true,
// that the cycle collector might care about.
fn type_is_pod(cx: ctxt, ty: t) -> bool {
let mut result = true;
- match get(ty).sty {
+ match /*bad*/copy get(ty).sty {
// Scalar types
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_type | ty_ptr(_) => result = true,
ty_enum(did, ref substs) => {
let variants = enum_variants(cx, did);
for vec::each(*variants) |variant| {
- let tup_ty = mk_tup(cx, variant.args);
+ let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
// Perform any type parameter substitutions.
let tup_ty = subst(cx, substs, tup_ty);
to_bytes::iter_bytes_2(&2u8, ident, lsb0, f),
ty::br_cap_avoid(ref id, ref br) =>
- to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f)
+ to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f),
+
+ ty::br_fresh(ref x) =>
+ to_bytes::iter_bytes_2(&4u8, x, lsb0, f)
}
}
}
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_5(&self.purity,
&self.proto,
+ &self.onceness,
&self.region,
&self.bounds,
- &self.ret_style,
lsb0, f);
}
}
to_bytes::iter_bytes_2(&11u8, fs, lsb0, f),
ty_fn(ref ft) =>
- to_bytes::iter_bytes_3(&12u8,
- &ft.meta,
- &ft.sig,
- lsb0, f),
+ to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
ty_self => 13u8.iter_bytes(lsb0, f),
// Type accessors for substructures of types
fn ty_fn_args(fty: t) -> ~[arg] {
match get(fty).sty {
- ty_fn(ref f) => f.sig.inputs,
+ ty_fn(ref f) => /*bad*/copy f.sig.inputs,
_ => fail ~"ty_fn_args() called on non-fn type"
}
}
pure fn ty_fn_ret(fty: t) -> t {
match get(fty).sty {
- ty_fn(ref f) => f.sig.output,
- _ => fail ~"ty_fn_ret() called on non-fn type"
- }
-}
-
-fn ty_fn_ret_style(fty: t) -> ast::ret_style {
- match get(fty).sty {
- ty_fn(ref f) => f.meta.ret_style,
- _ => fail ~"ty_fn_ret_style() called on non-fn type"
+ ty_fn(ref f) => f.sig.output,
+ _ => fail ~"ty_fn_ret() called on non-fn type"
}
}
}
}
+fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
+ /*!
+ *
+ * Returns a new function type based on `fn_type` but returning a value of
+ * type `ret_type` instead. */
+
+ match ty::get(fn_type).sty {
+ ty::ty_fn(ref fty) => {
+ ty::mk_fn(tcx, FnTyBase {
+ meta: fty.meta,
+ sig: FnSig {output: ret_type, ..copy fty.sig}
+ })
+ }
+ _ => {
+ tcx.sess.bug(fmt!(
+ "replace_fn_ret() invoked with non-fn-type: %s",
+ ty_to_str(tcx, fn_type)));
+ }
+ }
+}
+
// Returns a vec of all the input and output types of fty.
-fn tys_in_fn_ty(fty: &FnTy) -> ~[t] {
- vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output)
+fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
+ vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
}
// Just checks whether it's a fn that returns bool,
// trait itself. This ought to be harmonized.
let trt_bounds =
ty::lookup_item_type(tcx, trt_id).bounds;
- let mth = ty::trait_methods(tcx, trt_id)[n_mth];
- @(vec::append(*trt_bounds, *mth.tps))
+ let mth = /*bad*/copy ty::trait_methods(tcx, trt_id)[n_mth];
+ @(vec::append(/*bad*/copy *trt_bounds, *mth.tps))
}
}
}
ast::expr_copy(*) |
ast::expr_unary_move(*) |
ast::expr_repeat(*) |
- ast::expr_lit(@{node: lit_str(_), _}) |
+ ast::expr_lit(@ast::spanned {node: lit_str(_), _}) |
ast::expr_vstore(_, ast::expr_vstore_slice) |
ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
ast::expr_vstore(_, ast::expr_vstore_fixed(_)) |
}
fn get_fields(rec_ty:t) -> ~[field] {
- match get(rec_ty).sty {
+ match /*bad*/copy get(rec_ty).sty {
ty_rec(fields) => fields,
// Can we check at the caller?
_ => fail ~"get_fields: not a record type"
tcx.sess.span_fatal
(sp, ~"type inference failed because I \
could not find a type\n that's both of the form "
- + ty_to_str(tcx, mk_var(tcx, vid)) +
- ~" and of the form " + ty_to_str(tcx, rt) +
+ + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
+ ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
~" - such a type would have to be infinitely large.");
}
}
ty_nil | ty_bot | ty_bool | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_estr(_) |
ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
- ty_to_str(cx, t)
+ ::util::ppaux::ty_to_str(cx, t)
}
ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
match *err {
terr_mismatch => ~"types differ",
- terr_ret_style_mismatch(values) => {
- fn to_str(s: ast::ret_style) -> ~str {
- match s {
- ast::noreturn => ~"non-returning",
- ast::return_val => ~"return-by-value"
- }
- }
- fmt!("expected %s function, found %s function",
- to_str(values.expected),
- to_str(values.expected))
- }
terr_purity_mismatch(values) => {
fmt!("expected %s fn but found %s fn",
- purity_to_str(values.expected),
- purity_to_str(values.found))
+ values.expected.to_str(), values.found.to_str())
}
terr_onceness_mismatch(values) => {
fmt!("expected %s fn but found %s fn",
- onceness_to_str(values.expected),
- onceness_to_str(values.found))
+ values.expected.to_str(), values.found.to_str())
}
terr_proto_mismatch(values) => {
fmt!("expected %s closure, found %s closure",
- proto_ty_to_str(cx, values.expected),
- proto_ty_to_str(cx, values.found))
+ proto_ty_to_str(cx, values.expected, false),
+ proto_ty_to_str(cx, values.found, false))
}
terr_mutability => ~"values differ in mutability",
terr_box_mutability => ~"boxed values differ in mutability",
terr_arg_count => ~"incorrect number of function parameters",
terr_mode_mismatch(values) => {
fmt!("expected argument mode %s, but found %s",
- mode_to_str(values.expected), mode_to_str(values.found))
+ pprust::mode_to_str(values.expected),
+ pprust::mode_to_str(values.found))
}
terr_regions_does_not_outlive(*) => {
fmt!("lifetime mismatch")
~"couldn't determine an appropriate integral type for integer \
literal"
}
+ terr_integer_as_char => {
+ ~"integer literals can't be inferred to char type \
+ (try an explicit cast)"
+ }
terr_no_floating_point_type => {
~"couldn't determine an appropriate floating point type for \
floating point literal"
node: item_trait(_, _, ref ms),
_
}, _)) =>
- match ast_util::split_trait_methods((*ms)) {
+ match ast_util::split_trait_methods((/*bad*/copy *ms)) {
(_, p) => p.map(|method| method.ident)
},
_ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
ty_trait(def_id, ref substs, _) => {
result.push(InstantiatedTraitRef {
def_id: def_id,
- tpt: { substs: (*substs), ty: *trait_type }
+ tpt: { substs: (/*bad*/copy *substs), ty: *trait_type }
});
}
_ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
match ty::get(ty).sty {
ty::ty_trait(_, _, trait_vstore) if vstore == trait_vstore => ty,
ty::ty_trait(did, ref substs, _) => {
- mk_trait(cx, did, (*substs), vstore)
+ mk_trait(cx, did, (/*bad*/copy *substs), vstore)
}
_ => cx.sess.bug(~"impl_traits: not a trait")
}
let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
@VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
- ..**variant_info}
+ ../*bad*/copy **variant_info}
}
}
ast_map::path_name(item.ident)
}
};
- vec::append_one(*path, item_elt)
+ vec::append_one(/*bad*/copy *path, item_elt)
}
ast_map::node_foreign_item(nitem, _, path) => {
- vec::append_one(*path, ast_map::path_name(nitem.ident))
+ vec::append_one(/*bad*/copy *path,
+ ast_map::path_name(nitem.ident))
}
ast_map::node_method(method, _, path) => {
- vec::append_one(*path, ast_map::path_name(method.ident))
+ vec::append_one(/*bad*/copy *path,
+ ast_map::path_name(method.ident))
}
ast_map::node_trait_method(trait_method, _, path) => {
let method = ast_util::trait_method_to_ty_method(*trait_method);
- vec::append_one(*path, ast_map::path_name(method.ident))
+ vec::append_one(/*bad*/copy *path,
+ ast_map::path_name(method.ident))
}
ast_map::node_variant(ref variant, _, path) => {
}
ast_map::node_dtor(_, _, _, path) => {
- vec::append_one(*path, ast_map::path_name(
+ vec::append_one(/*bad*/copy *path, ast_map::path_name(
syntax::parse::token::special_idents::literally_dtor))
}
ast_map::node_struct_ctor(_, item, path) => {
- vec::append_one(*path, ast_map::path_name(item.ident))
+ vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
}
ast_map::node_stmt(*) | ast_map::node_expr(*) |
node: ast::item_enum(ref enum_definition, _),
_
}, _) => {
- let variants = (*enum_definition).variants;
+ let variants = /*bad*/copy (*enum_definition).variants;
let mut disr_val = -1;
@vec::map(variants, |variant| {
match variant.node.kind {
- ast::tuple_variant_kind(args) => {
+ ast::tuple_variant_kind(ref args) => {
let ctor_ty = node_id_to_type(cx, variant.node.id);
let arg_tys = {
- if vec::len(args) > 0u {
+ if args.len() > 0u {
ty_fn_args(ctor_ty).map(|a| a.ty)
} else {
~[]
Some(ast_map::node_item(i,_)) => {
match i.node {
ast::item_struct(struct_def, _) => {
- struct_field_tys(struct_def.fields)
+ struct_field_tys(/*bad*/copy struct_def.fields)
}
_ => cx.sess.bug(~"struct ID bound to non-struct")
}
Some(ast_map::node_variant(ref variant, _, _)) => {
match (*variant).node.kind {
ast::struct_variant_kind(struct_def) => {
- struct_field_tys(struct_def.fields)
+ struct_field_tys(/*bad*/copy struct_def.fields)
}
_ => {
cx.sess.bug(~"struct ID bound to enum variant that isn't \
region: ty::re_static,
..fn_ty.meta
},
- sig: fn_ty.sig
+ sig: /*bad*/copy fn_ty.sig
})
}
mk_enum(cx, did,
{self_r: Some(ty::re_static),
self_ty: None,
- tps: (*r).tps}),
+ tps: /*bad*/copy (*r).tps}),
None =>
t
},
// Ditto.
mk_struct(cx, did, {self_r: Some(ty::re_static),
self_ty: None,
- tps: (*r).tps}),
+ tps: /*bad*/copy (*r).tps}),
None =>
t
},
pure fn ne(&self, other: &vstore) -> bool { !(*self).eq(other) }
}
-impl FnMeta : cmp::Eq {
- pure fn eq(&self, other: &FnMeta) -> bool {
- (*self).purity == (*other).purity &&
- (*self).proto == (*other).proto &&
- (*self).bounds == (*other).bounds &&
- (*self).ret_style == (*other).ret_style
- }
- pure fn ne(&self, other: &FnMeta) -> bool { !(*self).eq(other) }
-}
-
-impl FnSig : cmp::Eq {
- pure fn eq(&self, other: &FnSig) -> bool {
- (*self).inputs == (*other).inputs &&
- (*self).output == (*other).output
- }
- pure fn ne(&self, other: &FnSig) -> bool { !(*self).eq(other) }
-}
-
-impl<M: cmp::Eq> FnTyBase<M> : cmp::Eq {
- pure fn eq(&self, other: &FnTyBase<M>) -> bool {
- (*self).meta == (*other).meta && (*self).sig == (*other).sig
- }
- pure fn ne(&self, other: &FnTyBase<M>) -> bool { !(*self).eq(other) }
-}
-
impl TyVid : cmp::Eq {
pure fn eq(&self, other: &TyVid) -> bool { *(*self) == *(*other) }
pure fn ne(&self, other: &TyVid) -> bool { *(*self) != *(*other) }
_ => false
}
}
+ br_fresh(e0a) => {
+ match (*other) {
+ br_fresh(e0b) => e0a == e0b,
+ _ => false
+ }
+ }
}
}
pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
pure fn ne(&self, other: &substs) -> bool { !(*self).eq(other) }
}
-impl InferTy : cmp::Eq {
- pure fn eq(&self, other: &InferTy) -> bool {
- (*self).to_hash() == (*other).to_hash()
- }
- pure fn ne(&self, other: &InferTy) -> bool { !(*self).eq(other) }
-}
-
impl sty : cmp::Eq {
pure fn eq(&self, other: &sty) -> bool {
- match (*self) {
+ match (/*bad*/copy *self) {
ty_nil => {
match (*other) {
ty_nil => true,
}
}
ty_rec(e0a) => {
- match (*other) {
+ match (/*bad*/copy *other) {
ty_rec(e0b) => e0a == e0b,
_ => false
}
}
}
ty_tup(e0a) => {
- match (*other) {
+ match (/*bad*/copy *other) {
ty_tup(e0b) => e0a == e0b,
_ => false
}
}
- ty_infer(e0a) => {
+ ty_infer(ref e0a) => {
match (*other) {
- ty_infer(e0b) => e0a == e0b,
+ ty_infer(ref e0b) => *e0a == *e0b,
_ => false
}
}
* an rptr (`&r.T`) use the region `r` that appears in the rptr.
*/
-use middle::ty::{FnTyBase, FnMeta, FnSig};
+use core::prelude::*;
+
+use middle::pat_util::pat_id_map;
+use middle::ty::{FnTyBase, FnMeta, FnSig, ty_param_substs_and_ty};
+use middle::ty;
use middle::typeck::check::fn_ctxt;
+use middle::typeck::collect;
use middle::typeck::rscope::{anon_rscope, binding_rscope, empty_rscope};
use middle::typeck::rscope::{in_anon_rscope, in_binding_rscope};
use middle::typeck::rscope::{region_scope, type_rscope};
+use middle::typeck::{crate_ctxt, write_substs_to_tcx, write_ty_to_tcx};
+
+use core::result;
+use core::vec;
+use syntax::ast;
+use syntax::codemap::span;
+use syntax::print::pprust::path_to_str;
+use util::common::indent;
pub trait ast_conv {
fn tcx() -> ty::ctxt;
match res {
result::Ok(r) => r,
result::Err(ref e) => {
- tcx.sess.span_err(span, (*e));
+ tcx.sess.span_err(span, (/*bad*/copy *e));
ty::re_static
}
}
let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t));
let substs = {self_r:self_r, self_ty:None, tps:tps};
- {substs: substs, ty: ty::subst(tcx, &substs, decl_ty)}
+ let ty = ty::subst(tcx, &substs, decl_ty);
+ {substs: substs, ty: ty}
}
pub fn ast_path_to_ty<AC: ast_conv, RS: region_scope Copy Durable>(
let {substs: substs, ty: ty} =
ast_path_to_substs_and_ty(self, rscope, did, path);
write_ty_to_tcx(tcx, path_id, ty);
- write_substs_to_tcx(tcx, path_id, substs.tps);
+ write_substs_to_tcx(tcx, path_id, /*bad*/copy substs.tps);
return {substs: substs, ty: ty};
}
}
}
return ty::mk_trait(tcx, trait_def_id,
- (*substs), vst);
+ /*bad*/copy *substs, vst);
}
_ => {}
}
tcx.ast_ty_to_ty_cache.insert(ast_ty, ty::atttce_unresolved);
- let typ = match ast_ty.node {
+ let typ = match /*bad*/copy ast_ty.node {
ast::ty_nil => ty::mk_nil(tcx),
ast::ty_bot => ty::mk_bot(tcx),
ast::ty_box(mt) => {
proto: ast_proto,
onceness: onceness,
region: bound_region,
- bounds: bounds,
- ret_style: decl.cf},
+ bounds: bounds},
sig: FnSig {inputs: input_tys,
output: output_ty}
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::prelude::*;
+
+use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const};
+use middle::pat_util::{pat_is_variant_or_struct};
+use middle::ty;
+use middle::typeck::check::demand;
+use middle::typeck::check::{check_block, check_expr_with, fn_ctxt};
+use middle::typeck::check::{instantiate_path, lookup_def, lookup_local};
+use middle::typeck::check::{structure_of, valid_range_bounds};
+use middle::typeck::require_same_types;
+
+use core::vec;
+use std::map::HashMap;
+use syntax::ast;
+use syntax::ast_util::walk_pat;
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::print::pprust;
+
+fn check_match(fcx: @fn_ctxt,
+ expr: @ast::expr,
+ discrim: @ast::expr,
+ arms: ~[ast::arm]) -> bool {
+ let tcx = fcx.ccx.tcx;
+ let mut bot;
+
+ let pattern_ty = fcx.infcx().next_ty_var();
+ bot = check_expr_with(fcx, discrim, pattern_ty);
+
+ // Typecheck the patterns first, so that we get types for all the
+ // bindings.
+ for arms.each |arm| {
+ let pcx = pat_ctxt {
+ fcx: fcx,
+ map: pat_id_map(tcx.def_map, arm.pats[0]),
+ match_region: ty::re_scope(expr.id),
+ block_region: ty::re_scope(arm.body.node.id)
+ };
+
+ for arm.pats.each |p| { check_pat(pcx, *p, pattern_ty);}
+ }
+
+ // Now typecheck the blocks.
+ let mut result_ty = fcx.infcx().next_ty_var();
+ let mut arm_non_bot = false;
+ for arms.each |arm| {
+ match arm.guard {
+ Some(e) => { check_expr_with(fcx, e, ty::mk_bool(tcx)); },
+ None => ()
+ }
+ if !check_block(fcx, arm.body) { arm_non_bot = true; }
+ let bty = fcx.node_ty(arm.body.node.id);
+ demand::suptype(fcx, arm.body.span, result_ty, bty);
+ }
+ bot |= !arm_non_bot;
+ if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
+ fcx.write_ty(expr.id, result_ty);
+ return bot;
+}
+
+struct pat_ctxt {
+ fcx: @fn_ctxt,
+ map: PatIdMap,
+ match_region: ty::Region, // Region for the match as a whole
+ block_region: ty::Region, // Region for the block of the arm
+}
+
+fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
+ +subpats: Option<~[@ast::pat]>, expected: ty::t) {
+
+ // Typecheck the path.
+ let fcx = pcx.fcx;
+ let tcx = pcx.fcx.ccx.tcx;
+
+ let arg_types, kind_name;
+
+ // structure_of requires type variables to be resolved.
+ // So when we pass in <expected>, it's an error if it
+ // contains type variables.
+
+ // Check to see whether this is an enum or a struct.
+ match structure_of(pcx.fcx, pat.span, expected) {
+ ty::ty_enum(_, ref expected_substs) => {
+ // Lookup the enum and variant def ids:
+ let v_def = lookup_def(pcx.fcx, path.span, pat.id);
+ let v_def_ids = ast_util::variant_def_ids(v_def);
+
+ // Assign the pattern the type of the *enum*, not the variant.
+ let enum_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
+ instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id,
+ pcx.block_region);
+
+ // check that the type of the value being matched is a subtype
+ // of the type of the pattern:
+ let pat_ty = fcx.node_ty(pat.id);
+ demand::suptype(fcx, pat.span, pat_ty, expected);
+
+ // Get the expected types of the arguments.
+ arg_types = {
+ let vinfo =
+ ty::enum_variant_with_id(
+ tcx, v_def_ids.enm, v_def_ids.var);
+ let var_tpt = ty::lookup_item_type(tcx, v_def_ids.var);
+ vinfo.args.map(|t| {
+ if var_tpt.bounds.len() == expected_substs.tps.len() {
+ ty::subst(tcx, expected_substs, *t)
+ }
+ else {
+ *t // In this case, an error was already signaled
+ // anyway
+ }
+ })
+ };
+
+ kind_name = "variant";
+ }
+ ty::ty_struct(struct_def_id, ref expected_substs) => {
+ // Assign the pattern the type of the struct.
+ let struct_tpt = ty::lookup_item_type(tcx, struct_def_id);
+ instantiate_path(pcx.fcx, path, struct_tpt, pat.span, pat.id,
+ pcx.block_region);
+
+ // Check that the type of the value being matched is a subtype of
+ // the type of the pattern.
+ let pat_ty = fcx.node_ty(pat.id);
+ demand::suptype(fcx, pat.span, pat_ty, expected);
+
+ // Get the expected types of the arguments.
+ let class_fields = ty::struct_fields(
+ tcx, struct_def_id, expected_substs);
+ arg_types = class_fields.map(|field| field.mt.ty);
+
+ kind_name = "structure";
+ }
+ _ => {
+ tcx.sess.span_fatal(
+ pat.span,
+ fmt!("mismatched types: expected enum or structure but \
+ found `%s`",
+ fcx.infcx().ty_to_str(expected)));
+ }
+ }
+
+ let arg_len = arg_types.len();
+
+ // Count the number of subpatterns.
+ let subpats_len;
+ match subpats {
+ None => subpats_len = arg_len,
+ Some(ref subpats) => subpats_len = subpats.len()
+ }
+
+ if arg_len > 0u {
+ // N-ary variant.
+ if arg_len != subpats_len {
+ let s = fmt!("this pattern has %u field%s, but the corresponding \
+ %s has %u field%s",
+ subpats_len,
+ if subpats_len == 1u { ~"" } else { ~"s" },
+ kind_name,
+ arg_len,
+ if arg_len == 1u { ~"" } else { ~"s" });
+ // XXX: This should not be fatal.
+ tcx.sess.span_fatal(pat.span, s);
+ }
+
+ do subpats.iter() |pats| {
+ for vec::each2(*pats, arg_types) |subpat, arg_ty| {
+ check_pat(pcx, *subpat, *arg_ty);
+ }
+ };
+ } else if subpats_len > 0u {
+ tcx.sess.span_fatal
+ (pat.span, fmt!("this pattern has %u field%s, but the \
+ corresponding %s has no fields",
+ subpats_len,
+ if subpats_len == 1u { ~"" }
+ else { ~"s" },
+ kind_name));
+ }
+}
+
+/// `path` is the AST path item naming the type of this struct.
+/// `fields` is the field patterns of the struct pattern.
+/// `class_fields` describes the type of each field of the struct.
+/// `class_id` is the ID of the struct.
+/// `substitutions` are the type substitutions applied to this struct type
+/// (e.g. K,V in HashMap<K,V>).
+/// `etc` is true if the pattern said '...' and false otherwise.
+fn check_struct_pat_fields(pcx: pat_ctxt,
+ span: span,
+ path: @ast::path,
+ fields: ~[ast::field_pat],
+ class_fields: ~[ty::field_ty],
+ class_id: ast::def_id,
+ substitutions: &ty::substs,
+ etc: bool) {
+ let tcx = pcx.fcx.ccx.tcx;
+
+ // Index the class fields.
+ let field_map = HashMap();
+ for class_fields.eachi |i, class_field| {
+ field_map.insert(class_field.ident, i);
+ }
+
+ // Typecheck each field.
+ let found_fields = HashMap();
+ for fields.each |field| {
+ match field_map.find(field.ident) {
+ Some(index) => {
+ let class_field = class_fields[index];
+ let field_type = ty::lookup_field_type(tcx,
+ class_id,
+ class_field.id,
+ substitutions);
+ check_pat(pcx, field.pat, field_type);
+ found_fields.insert(index, ());
+ }
+ None => {
+ let name = pprust::path_to_str(path, tcx.sess.intr());
+ tcx.sess.span_err(span,
+ fmt!("struct `%s` does not have a field
+ named `%s`", name,
+ tcx.sess.str_of(field.ident)));
+ }
+ }
+ }
+
+ // Report an error if not all the fields were specified.
+ if !etc {
+ for class_fields.eachi |i, field| {
+ if found_fields.contains_key(i) {
+ loop;
+ }
+ tcx.sess.span_err(span,
+ fmt!("pattern does not mention field `%s`",
+ tcx.sess.str_of(field.ident)));
+ }
+ }
+}
+
+fn check_struct_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span,
+ expected: ty::t, path: @ast::path,
+ +fields: ~[ast::field_pat], etc: bool,
+ class_id: ast::def_id, substitutions: &ty::substs) {
+ let fcx = pcx.fcx;
+ let tcx = pcx.fcx.ccx.tcx;
+
+ let class_fields = ty::lookup_struct_fields(tcx, class_id);
+
+ // Check to ensure that the struct is the one specified.
+ match tcx.def_map.find(pat_id) {
+ Some(ast::def_struct(supplied_def_id))
+ if supplied_def_id == class_id => {
+ // OK.
+ }
+ Some(ast::def_struct(*)) | Some(ast::def_variant(*)) => {
+ let name = pprust::path_to_str(path, tcx.sess.intr());
+ tcx.sess.span_err(span,
+ fmt!("mismatched types: expected `%s` but \
+ found `%s`",
+ fcx.infcx().ty_to_str(expected),
+ name));
+ }
+ _ => {
+ tcx.sess.span_bug(span, ~"resolve didn't write in class");
+ }
+ }
+
+ // Forbid pattern-matching structs with destructors.
+ if ty::has_dtor(tcx, class_id) {
+ tcx.sess.span_err(span, ~"deconstructing struct not allowed in \
+ pattern (it has a destructor)");
+ }
+
+ check_struct_pat_fields(pcx, span, path, fields, class_fields, class_id,
+ substitutions, etc);
+}
+
+fn check_struct_like_enum_variant_pat(pcx: pat_ctxt,
+ pat_id: ast::node_id,
+ span: span,
+ expected: ty::t,
+ path: @ast::path,
+ +fields: ~[ast::field_pat],
+ etc: bool,
+ enum_id: ast::def_id,
+ substitutions: &ty::substs) {
+ let fcx = pcx.fcx;
+ let tcx = pcx.fcx.ccx.tcx;
+
+ // Find the variant that was specified.
+ match tcx.def_map.find(pat_id) {
+ Some(ast::def_variant(found_enum_id, variant_id))
+ if found_enum_id == enum_id => {
+ // Get the struct fields from this struct-like enum variant.
+ let class_fields = ty::lookup_struct_fields(tcx, variant_id);
+
+ check_struct_pat_fields(pcx, span, path, fields, class_fields,
+ variant_id, substitutions, etc);
+ }
+ Some(ast::def_struct(*)) | Some(ast::def_variant(*)) => {
+ let name = pprust::path_to_str(path, tcx.sess.intr());
+ tcx.sess.span_err(span,
+ fmt!("mismatched types: expected `%s` but \
+ found `%s`",
+ fcx.infcx().ty_to_str(expected),
+ name));
+ }
+ _ => {
+ tcx.sess.span_bug(span, ~"resolve didn't write in variant");
+ }
+ }
+}
+
+// Pattern checking is top-down rather than bottom-up so that bindings get
+// their types immediately.
+fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
+ let fcx = pcx.fcx;
+ let tcx = pcx.fcx.ccx.tcx;
+
+ match /*bad*/copy pat.node {
+ ast::pat_wild => {
+ fcx.write_ty(pat.id, expected);
+ }
+ ast::pat_lit(lt) => {
+ check_expr_with(fcx, lt, expected);
+ fcx.write_ty(pat.id, fcx.expr_ty(lt));
+ }
+ ast::pat_range(begin, end) => {
+ check_expr_with(fcx, begin, expected);
+ check_expr_with(fcx, end, expected);
+ let b_ty =
+ fcx.infcx().resolve_type_vars_if_possible(fcx.expr_ty(begin));
+ let e_ty =
+ fcx.infcx().resolve_type_vars_if_possible(fcx.expr_ty(end));
+ debug!("pat_range beginning type: %?", b_ty);
+ debug!("pat_range ending type: %?", e_ty);
+ if !require_same_types(
+ tcx, Some(fcx.infcx()), false, pat.span, b_ty, e_ty,
+ || ~"mismatched types in range")
+ {
+ // no-op
+ } else if !ty::type_is_numeric(b_ty) {
+ tcx.sess.span_err(pat.span, ~"non-numeric type used in range");
+ } else if !valid_range_bounds(fcx.ccx, begin, end) {
+ tcx.sess.span_err(begin.span, ~"lower range bound must be less \
+ than upper");
+ }
+ fcx.write_ty(pat.id, b_ty);
+ }
+ ast::pat_ident(*) if pat_is_const(tcx.def_map, pat) => {
+ let const_did = ast_util::def_id_of_def(tcx.def_map.get(pat.id));
+ let const_tpt = ty::lookup_item_type(tcx, const_did);
+ fcx.write_ty(pat.id, const_tpt.ty);
+ }
+ ast::pat_ident(bm, name, sub) if pat_is_binding(tcx.def_map, pat) => {
+ let vid = lookup_local(fcx, pat.span, pat.id);
+ let mut typ = ty::mk_var(tcx, vid);
+
+ match bm {
+ ast::bind_by_ref(mutbl) => {
+ // if the binding is like
+ // ref x | ref const x | ref mut x
+ // then the type of x is &M T where M is the mutability
+ // and T is the expected type
+ let region_var =
+ fcx.infcx().next_region_var_with_lb(
+ pat.span, pcx.block_region);
+ let mt = {ty: expected, mutbl: mutbl};
+ let region_ty = ty::mk_rptr(tcx, region_var, mt);
+ demand::eqtype(fcx, pat.span, region_ty, typ);
+ }
+ // otherwise the type of x is the expected type T
+ ast::bind_by_value | ast::bind_by_move | ast::bind_infer => {
+ demand::eqtype(fcx, pat.span, expected, typ);
+ }
+ }
+
+ let canon_id = pcx.map.get(ast_util::path_to_ident(name));
+ if canon_id != pat.id {
+ let tv_id = lookup_local(fcx, pat.span, canon_id);
+ let ct = ty::mk_var(tcx, tv_id);
+ demand::eqtype(fcx, pat.span, ct, typ);
+ }
+ fcx.write_ty(pat.id, typ);
+
+ debug!("(checking match) writing type for pat id %d", pat.id);
+
+ match sub {
+ Some(p) => check_pat(pcx, p, expected),
+ _ => ()
+ }
+ }
+ ast::pat_ident(_, path, _) => {
+ check_pat_variant(pcx, pat, path, Some(~[]), expected);
+ }
+ ast::pat_enum(path, subpats) => {
+ check_pat_variant(pcx, pat, path, subpats, expected);
+ }
+ ast::pat_rec(fields, etc) => {
+ let ex_fields = match structure_of(fcx, pat.span, expected) {
+ ty::ty_rec(fields) => fields,
+ _ => {
+ tcx.sess.span_fatal
+ (pat.span,
+ fmt!("mismatched types: expected `%s` but found record",
+ fcx.infcx().ty_to_str(expected)));
+ }
+ };
+ let f_count = vec::len(fields);
+ let ex_f_count = vec::len(ex_fields);
+ if ex_f_count < f_count || !etc && ex_f_count > f_count {
+ tcx.sess.span_fatal
+ (pat.span, fmt!("mismatched types: expected a record \
+ with %u fields, found one with %u \
+ fields",
+ ex_f_count, f_count));
+ }
+
+ for fields.each |f| {
+ match vec::find(ex_fields, |a| f.ident == a.ident) {
+ Some(field) => {
+ check_pat(pcx, f.pat, field.mt.ty);
+ }
+ None => {
+ tcx.sess.span_fatal(pat.span,
+ fmt!("mismatched types: did not \
+ expect a record with a field `%s`",
+ tcx.sess.str_of(f.ident)));
+ }
+ }
+ }
+ fcx.write_ty(pat.id, expected);
+ }
+ ast::pat_struct(path, fields, etc) => {
+ // Grab the class data that we care about.
+ let structure = structure_of(fcx, pat.span, expected);
+ match structure {
+ ty::ty_struct(cid, ref substs) => {
+ check_struct_pat(pcx, pat.id, pat.span, expected, path,
+ fields, etc, cid, substs);
+ }
+ ty::ty_enum(eid, ref substs) => {
+ check_struct_like_enum_variant_pat(
+ pcx, pat.id, pat.span, expected, path, fields, etc, eid,
+ substs);
+ }
+ _ => {
+ // XXX: This should not be fatal.
+ tcx.sess.span_fatal(pat.span,
+ fmt!("mismatched types: expected `%s` \
+ but found struct",
+ fcx.infcx().ty_to_str(expected)));
+ }
+ }
+
+ // Finally, write in the type.
+ fcx.write_ty(pat.id, expected);
+ }
+ ast::pat_tup(elts) => {
+ let ex_elts = match structure_of(fcx, pat.span, expected) {
+ ty::ty_tup(elts) => elts,
+ _ => {
+ tcx.sess.span_fatal
+ (pat.span,
+ fmt!("mismatched types: expected `%s`, found tuple",
+ fcx.infcx().ty_to_str(expected)));
+ }
+ };
+ let e_count = vec::len(elts);
+ if e_count != vec::len(ex_elts) {
+ tcx.sess.span_fatal
+ (pat.span, fmt!("mismatched types: expected a tuple \
+ with %u fields, found one with %u \
+ fields", vec::len(ex_elts), e_count));
+ }
+ let mut i = 0u;
+ for elts.each |elt| {
+ check_pat(pcx, *elt, ex_elts[i]);
+ i += 1u;
+ }
+
+ fcx.write_ty(pat.id, expected);
+ }
+ ast::pat_box(inner) => {
+ match structure_of(fcx, pat.span, expected) {
+ ty::ty_box(e_inner) => {
+ check_pat(pcx, inner, e_inner.ty);
+ fcx.write_ty(pat.id, expected);
+ }
+ _ => {
+ tcx.sess.span_fatal(
+ pat.span,
+ ~"mismatched types: expected `" +
+ fcx.infcx().ty_to_str(expected) +
+ ~"` found box");
+ }
+ }
+ }
+ ast::pat_uniq(inner) => {
+ match structure_of(fcx, pat.span, expected) {
+ ty::ty_uniq(e_inner) => {
+ check_pat(pcx, inner, e_inner.ty);
+ fcx.write_ty(pat.id, expected);
+ }
+ _ => {
+ tcx.sess.span_fatal(
+ pat.span,
+ ~"mismatched types: expected `" +
+ fcx.infcx().ty_to_str(expected) +
+ ~"` found uniq");
+ }
+ }
+ }
+ ast::pat_region(inner) => {
+ match structure_of(fcx, pat.span, expected) {
+ ty::ty_rptr(_, e_inner) => {
+ check_pat(pcx, inner, e_inner.ty);
+ fcx.write_ty(pat.id, expected);
+ }
+ _ => {
+ tcx.sess.span_fatal(
+ pat.span,
+ ~"mismatched types: expected `" +
+ fcx.infcx().ty_to_str(expected) +
+ ~"` found borrowed pointer");
+ }
+ }
+ }
+ ast::pat_vec(elts, tail) => {
+ let default_region_var =
+ fcx.infcx().next_region_var_with_lb(
+ pat.span, pcx.block_region
+ );
+
+ let (elt_type, region_var) = match structure_of(
+ fcx, pat.span, expected
+ ) {
+ ty::ty_evec(mt, vstore) => {
+ let region_var = match vstore {
+ ty::vstore_slice(r) => r,
+ ty::vstore_box | ty::vstore_uniq | ty::vstore_fixed(_) => {
+ default_region_var
+ }
+ };
+ (mt, region_var)
+ }
+ ty::ty_unboxed_vec(mt) => {
+ (mt, default_region_var)
+ },
+ _ => {
+ tcx.sess.span_fatal(
+ pat.span,
+ fmt!("mismatched type: expected `%s` but found vector",
+ fcx.infcx().ty_to_str(expected))
+ );
+ }
+ };
+ for elts.each |elt| {
+ check_pat(pcx, *elt, elt_type.ty);
+ }
+ fcx.write_ty(pat.id, expected);
+
+ match tail {
+ Some(tail_pat) => {
+ let slice_ty = ty::mk_evec(tcx,
+ {ty: elt_type.ty, mutbl: elt_type.mutbl},
+ ty::vstore_slice(region_var)
+ );
+ check_pat(pcx, tail_pat, slice_ty);
+ }
+ None => ()
+ }
+ }
+ }
+}
+
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use middle::pat_util::{pat_is_binding, pat_is_const};
-use middle::pat_util::{pat_is_variant_or_struct};
-
-use syntax::ast_util::walk_pat;
-use syntax::print::pprust;
-
-fn check_alt(fcx: @fn_ctxt,
- expr: @ast::expr,
- discrim: @ast::expr,
- arms: ~[ast::arm]) -> bool {
- let tcx = fcx.ccx.tcx;
- let mut bot;
-
- let pattern_ty = fcx.infcx().next_ty_var();
- bot = check_expr_with(fcx, discrim, pattern_ty);
-
- // Typecheck the patterns first, so that we get types for all the
- // bindings.
- for arms.each |arm| {
- let pcx = {
- fcx: fcx,
- map: pat_id_map(tcx.def_map, arm.pats[0]),
- alt_region: ty::re_scope(expr.id),
- block_region: ty::re_scope(arm.body.node.id)
- };
-
- for arm.pats.each |p| { check_pat(pcx, *p, pattern_ty);}
- }
-
- // Now typecheck the blocks.
- let mut result_ty = fcx.infcx().next_ty_var();
- let mut arm_non_bot = false;
- for arms.each |arm| {
- match arm.guard {
- Some(e) => { check_expr_with(fcx, e, ty::mk_bool(tcx)); },
- None => ()
- }
- if !check_block(fcx, arm.body) { arm_non_bot = true; }
- let bty = fcx.node_ty(arm.body.node.id);
- demand::suptype(fcx, arm.body.span, result_ty, bty);
- }
- bot |= !arm_non_bot;
- if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
- fcx.write_ty(expr.id, result_ty);
- return bot;
-}
-
-type pat_ctxt = {
- fcx: @fn_ctxt,
- map: PatIdMap,
- alt_region: ty::Region, // Region for the alt as a whole
- block_region: ty::Region, // Region for the block of the arm
-};
-
-fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
- subpats: Option<~[@ast::pat]>, expected: ty::t) {
-
- // Typecheck the path.
- let fcx = pcx.fcx;
- let tcx = pcx.fcx.ccx.tcx;
-
- let arg_types, kind_name;
-
- // structure_of requires type variables to be resolved.
- // So when we pass in <expected>, it's an error if it
- // contains type variables.
-
- // Check to see whether this is an enum or a struct.
- match structure_of(pcx.fcx, pat.span, expected) {
- ty::ty_enum(_, ref expected_substs) => {
- // Lookup the enum and variant def ids:
- let v_def = lookup_def(pcx.fcx, path.span, pat.id);
- let v_def_ids = ast_util::variant_def_ids(v_def);
-
- // Assign the pattern the type of the *enum*, not the variant.
- let enum_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
- instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id,
- pcx.block_region);
-
- // check that the type of the value being matched is a subtype
- // of the type of the pattern:
- let pat_ty = fcx.node_ty(pat.id);
- demand::suptype(fcx, pat.span, pat_ty, expected);
-
- // Get the expected types of the arguments.
- arg_types = {
- let vinfo =
- ty::enum_variant_with_id(
- tcx, v_def_ids.enm, v_def_ids.var);
- let var_tpt = ty::lookup_item_type(tcx, v_def_ids.var);
- vinfo.args.map(|t| {
- if var_tpt.bounds.len() == expected_substs.tps.len() {
- ty::subst(tcx, expected_substs, *t)
- }
- else {
- *t // In this case, an error was already signaled
- // anyway
- }
- })
- };
-
- kind_name = "variant";
- }
- ty::ty_struct(struct_def_id, ref expected_substs) => {
- // Assign the pattern the type of the struct.
- let struct_tpt = ty::lookup_item_type(tcx, struct_def_id);
- instantiate_path(pcx.fcx, path, struct_tpt, pat.span, pat.id,
- pcx.block_region);
-
- // Check that the type of the value being matched is a subtype of
- // the type of the pattern.
- let pat_ty = fcx.node_ty(pat.id);
- demand::suptype(fcx, pat.span, pat_ty, expected);
-
- // Get the expected types of the arguments.
- let class_fields = ty::struct_fields(
- tcx, struct_def_id, expected_substs);
- arg_types = class_fields.map(|field| field.mt.ty);
-
- kind_name = "structure";
- }
- _ => {
- tcx.sess.span_fatal(
- pat.span,
- fmt!("mismatched types: expected enum or structure but \
- found `%s`",
- fcx.infcx().ty_to_str(expected)));
- }
- }
-
- let arg_len = arg_types.len();
-
- // Count the number of subpatterns.
- let subpats_len;
- match subpats {
- None => subpats_len = arg_len,
- Some(subpats) => subpats_len = subpats.len()
- }
-
- if arg_len > 0u {
- // N-ary variant.
- if arg_len != subpats_len {
- let s = fmt!("this pattern has %u field%s, but the corresponding \
- %s has %u field%s",
- subpats_len,
- if subpats_len == 1u { ~"" } else { ~"s" },
- kind_name,
- arg_len,
- if arg_len == 1u { ~"" } else { ~"s" });
- // XXX: This should not be fatal.
- tcx.sess.span_fatal(pat.span, s);
- }
-
- do subpats.iter() |pats| {
- for vec::each2(*pats, arg_types) |subpat, arg_ty| {
- check_pat(pcx, *subpat, *arg_ty);
- }
- };
- } else if subpats_len > 0u {
- tcx.sess.span_fatal
- (pat.span, fmt!("this pattern has %u field%s, but the \
- corresponding %s has no fields",
- subpats_len,
- if subpats_len == 1u { ~"" }
- else { ~"s" },
- kind_name));
- }
-}
-
-/// `path` is the AST path item naming the type of this struct.
-/// `fields` is the field patterns of the struct pattern.
-/// `class_fields` describes the type of each field of the struct.
-/// `class_id` is the ID of the struct.
-/// `substitutions` are the type substitutions applied to this struct type
-/// (e.g. K,V in HashMap<K,V>).
-/// `etc` is true if the pattern said '...' and false otherwise.
-fn check_struct_pat_fields(pcx: pat_ctxt,
- span: span,
- path: @ast::path,
- fields: ~[ast::field_pat],
- class_fields: ~[ty::field_ty],
- class_id: ast::def_id,
- substitutions: &ty::substs,
- etc: bool) {
- let tcx = pcx.fcx.ccx.tcx;
-
- // Index the class fields.
- let field_map = std::map::HashMap();
- for class_fields.eachi |i, class_field| {
- field_map.insert(class_field.ident, i);
- }
-
- // Typecheck each field.
- let found_fields = std::map::HashMap();
- for fields.each |field| {
- match field_map.find(field.ident) {
- Some(index) => {
- let class_field = class_fields[index];
- let field_type = ty::lookup_field_type(tcx,
- class_id,
- class_field.id,
- substitutions);
- check_pat(pcx, field.pat, field_type);
- found_fields.insert(index, ());
- }
- None => {
- let name = pprust::path_to_str(path, tcx.sess.intr());
- tcx.sess.span_err(span,
- fmt!("struct `%s` does not have a field
- named `%s`", name,
- tcx.sess.str_of(field.ident)));
- }
- }
- }
-
- // Report an error if not all the fields were specified.
- if !etc {
- for class_fields.eachi |i, field| {
- if found_fields.contains_key(i) {
- loop;
- }
- tcx.sess.span_err(span,
- fmt!("pattern does not mention field `%s`",
- tcx.sess.str_of(field.ident)));
- }
- }
-}
-
-fn check_struct_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span,
- expected: ty::t, path: @ast::path,
- fields: ~[ast::field_pat], etc: bool,
- class_id: ast::def_id, substitutions: &ty::substs) {
- let fcx = pcx.fcx;
- let tcx = pcx.fcx.ccx.tcx;
-
- let class_fields = ty::lookup_struct_fields(tcx, class_id);
-
- // Check to ensure that the struct is the one specified.
- match tcx.def_map.find(pat_id) {
- Some(ast::def_struct(supplied_def_id))
- if supplied_def_id == class_id => {
- // OK.
- }
- Some(ast::def_struct(*)) | Some(ast::def_variant(*)) => {
- let name = pprust::path_to_str(path, tcx.sess.intr());
- tcx.sess.span_err(span,
- fmt!("mismatched types: expected `%s` but \
- found `%s`",
- fcx.infcx().ty_to_str(expected),
- name));
- }
- _ => {
- tcx.sess.span_bug(span, ~"resolve didn't write in class");
- }
- }
-
- // Forbid pattern-matching structs with destructors.
- if ty::has_dtor(tcx, class_id) {
- tcx.sess.span_err(span, ~"deconstructing struct not allowed in \
- pattern (it has a destructor)");
- }
-
- check_struct_pat_fields(pcx, span, path, fields, class_fields, class_id,
- substitutions, etc);
-}
-
-fn check_struct_like_enum_variant_pat(pcx: pat_ctxt,
- pat_id: ast::node_id,
- span: span,
- expected: ty::t,
- path: @ast::path,
- fields: ~[ast::field_pat],
- etc: bool,
- enum_id: ast::def_id,
- substitutions: &ty::substs) {
- let fcx = pcx.fcx;
- let tcx = pcx.fcx.ccx.tcx;
-
- // Find the variant that was specified.
- match tcx.def_map.find(pat_id) {
- Some(ast::def_variant(found_enum_id, variant_id))
- if found_enum_id == enum_id => {
- // Get the struct fields from this struct-like enum variant.
- let class_fields = ty::lookup_struct_fields(tcx, variant_id);
-
- check_struct_pat_fields(pcx, span, path, fields, class_fields,
- variant_id, substitutions, etc);
- }
- Some(ast::def_struct(*)) | Some(ast::def_variant(*)) => {
- let name = pprust::path_to_str(path, tcx.sess.intr());
- tcx.sess.span_err(span,
- fmt!("mismatched types: expected `%s` but \
- found `%s`",
- fcx.infcx().ty_to_str(expected),
- name));
- }
- _ => {
- tcx.sess.span_bug(span, ~"resolve didn't write in variant");
- }
- }
-}
-
-// Pattern checking is top-down rather than bottom-up so that bindings get
-// their types immediately.
-fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
- let fcx = pcx.fcx;
- let tcx = pcx.fcx.ccx.tcx;
-
- match pat.node {
- ast::pat_wild => {
- fcx.write_ty(pat.id, expected);
- }
- ast::pat_lit(lt) => {
- check_expr_with(fcx, lt, expected);
- fcx.write_ty(pat.id, fcx.expr_ty(lt));
- }
- ast::pat_range(begin, end) => {
- check_expr_with(fcx, begin, expected);
- check_expr_with(fcx, end, expected);
- let b_ty =
- fcx.infcx().resolve_type_vars_if_possible(fcx.expr_ty(begin));
- let e_ty =
- fcx.infcx().resolve_type_vars_if_possible(fcx.expr_ty(end));
- debug!("pat_range beginning type: %?", b_ty);
- debug!("pat_range ending type: %?", e_ty);
- if !require_same_types(
- tcx, Some(fcx.infcx()), false, pat.span, b_ty, e_ty,
- || ~"mismatched types in range")
- {
- // no-op
- } else if !ty::type_is_numeric(b_ty) {
- tcx.sess.span_err(pat.span, ~"non-numeric type used in range");
- } else if !valid_range_bounds(fcx.ccx, begin, end) {
- tcx.sess.span_err(begin.span, ~"lower range bound must be less \
- than upper");
- }
- fcx.write_ty(pat.id, b_ty);
- }
- ast::pat_ident(*) if pat_is_const(tcx.def_map, pat) => {
- let const_did = ast_util::def_id_of_def(tcx.def_map.get(pat.id));
- let const_tpt = ty::lookup_item_type(tcx, const_did);
- fcx.write_ty(pat.id, const_tpt.ty);
- }
- ast::pat_ident(bm, name, sub) if pat_is_binding(tcx.def_map, pat) => {
- let vid = lookup_local(fcx, pat.span, pat.id);
- let mut typ = ty::mk_var(tcx, vid);
-
- match bm {
- ast::bind_by_ref(mutbl) => {
- // if the binding is like
- // ref x | ref const x | ref mut x
- // then the type of x is &M T where M is the mutability
- // and T is the expected type
- let region_var =
- fcx.infcx().next_region_var_with_lb(
- pat.span, pcx.block_region);
- let mt = {ty: expected, mutbl: mutbl};
- let region_ty = ty::mk_rptr(tcx, region_var, mt);
- demand::eqtype(fcx, pat.span, region_ty, typ);
- }
- // otherwise the type of x is the expected type T
- ast::bind_by_value | ast::bind_by_move | ast::bind_infer => {
- demand::eqtype(fcx, pat.span, expected, typ);
- }
- }
-
- let canon_id = pcx.map.get(ast_util::path_to_ident(name));
- if canon_id != pat.id {
- let tv_id = lookup_local(fcx, pat.span, canon_id);
- let ct = ty::mk_var(tcx, tv_id);
- demand::eqtype(fcx, pat.span, ct, typ);
- }
- fcx.write_ty(pat.id, typ);
-
- debug!("(checking alt) writing type for pat id %d", pat.id);
-
- match sub {
- Some(p) => check_pat(pcx, p, expected),
- _ => ()
- }
- }
- ast::pat_ident(_, path, _) => {
- check_pat_variant(pcx, pat, path, Some(~[]), expected);
- }
- ast::pat_enum(path, subpats) => {
- check_pat_variant(pcx, pat, path, subpats, expected);
- }
- ast::pat_rec(fields, etc) => {
- let ex_fields = match structure_of(fcx, pat.span, expected) {
- ty::ty_rec(fields) => fields,
- _ => {
- tcx.sess.span_fatal
- (pat.span,
- fmt!("mismatched types: expected `%s` but found record",
- fcx.infcx().ty_to_str(expected)));
- }
- };
- let f_count = vec::len(fields);
- let ex_f_count = vec::len(ex_fields);
- if ex_f_count < f_count || !etc && ex_f_count > f_count {
- tcx.sess.span_fatal
- (pat.span, fmt!("mismatched types: expected a record \
- with %u fields, found one with %u \
- fields",
- ex_f_count, f_count));
- }
-
- for fields.each |f| {
- match vec::find(ex_fields, |a| f.ident == a.ident) {
- Some(field) => {
- check_pat(pcx, f.pat, field.mt.ty);
- }
- None => {
- tcx.sess.span_fatal(pat.span,
- fmt!("mismatched types: did not \
- expect a record with a field `%s`",
- tcx.sess.str_of(f.ident)));
- }
- }
- }
- fcx.write_ty(pat.id, expected);
- }
- ast::pat_struct(path, fields, etc) => {
- // Grab the class data that we care about.
- let structure = structure_of(fcx, pat.span, expected);
- match structure {
- ty::ty_struct(cid, ref substs) => {
- check_struct_pat(pcx, pat.id, pat.span, expected, path,
- fields, etc, cid, substs);
- }
- ty::ty_enum(eid, ref substs) => {
- check_struct_like_enum_variant_pat(
- pcx, pat.id, pat.span, expected, path, fields, etc, eid,
- substs);
- }
- _ => {
- // XXX: This should not be fatal.
- tcx.sess.span_fatal(pat.span,
- fmt!("mismatched types: expected `%s` \
- but found struct",
- fcx.infcx().ty_to_str(expected)));
- }
- }
-
- // Finally, write in the type.
- fcx.write_ty(pat.id, expected);
- }
- ast::pat_tup(elts) => {
- let ex_elts = match structure_of(fcx, pat.span, expected) {
- ty::ty_tup(elts) => elts,
- _ => {
- tcx.sess.span_fatal
- (pat.span,
- fmt!("mismatched types: expected `%s`, found tuple",
- fcx.infcx().ty_to_str(expected)));
- }
- };
- let e_count = vec::len(elts);
- if e_count != vec::len(ex_elts) {
- tcx.sess.span_fatal
- (pat.span, fmt!("mismatched types: expected a tuple \
- with %u fields, found one with %u \
- fields", vec::len(ex_elts), e_count));
- }
- let mut i = 0u;
- for elts.each |elt| {
- check_pat(pcx, *elt, ex_elts[i]);
- i += 1u;
- }
-
- fcx.write_ty(pat.id, expected);
- }
- ast::pat_box(inner) => {
- match structure_of(fcx, pat.span, expected) {
- ty::ty_box(e_inner) => {
- check_pat(pcx, inner, e_inner.ty);
- fcx.write_ty(pat.id, expected);
- }
- _ => {
- tcx.sess.span_fatal(
- pat.span,
- ~"mismatched types: expected `" +
- fcx.infcx().ty_to_str(expected) +
- ~"` found box");
- }
- }
- }
- ast::pat_uniq(inner) => {
- match structure_of(fcx, pat.span, expected) {
- ty::ty_uniq(e_inner) => {
- check_pat(pcx, inner, e_inner.ty);
- fcx.write_ty(pat.id, expected);
- }
- _ => {
- tcx.sess.span_fatal(
- pat.span,
- ~"mismatched types: expected `" +
- fcx.infcx().ty_to_str(expected) +
- ~"` found uniq");
- }
- }
- }
- ast::pat_region(inner) => {
- match structure_of(fcx, pat.span, expected) {
- ty::ty_rptr(_, e_inner) => {
- check_pat(pcx, inner, e_inner.ty);
- fcx.write_ty(pat.id, expected);
- }
- _ => {
- tcx.sess.span_fatal(
- pat.span,
- ~"mismatched types: expected `" +
- fcx.infcx().ty_to_str(expected) +
- ~"` found borrowed pointer");
- }
- }
- }
- ast::pat_vec(elts, tail) => {
- let default_region_var =
- fcx.infcx().next_region_var_with_lb(
- pat.span, pcx.block_region
- );
-
- let (elt_type, region_var) = match structure_of(
- fcx, pat.span, expected
- ) {
- ty::ty_evec(mt, vstore) => {
- let region_var = match vstore {
- ty::vstore_slice(r) => r,
- ty::vstore_box | ty::vstore_uniq | ty::vstore_fixed(_) => {
- default_region_var
- }
- };
- (mt, region_var)
- }
- ty::ty_unboxed_vec(mt) => {
- (mt, default_region_var)
- },
- _ => {
- tcx.sess.span_fatal(
- pat.span,
- fmt!("mismatched type: expected `%s` but found vector",
- fcx.infcx().ty_to_str(expected))
- );
- }
- };
- for elts.each |elt| {
- check_pat(pcx, *elt, elt_type.ty);
- }
- fcx.write_ty(pat.id, expected);
-
- match tail {
- Some(tail_pat) => {
- let slice_ty = ty::mk_evec(tcx,
- {ty: elt_type.ty, mutbl: elt_type.mutbl},
- ty::vstore_slice(region_var)
- );
- check_pat(pcx, tail_pat, slice_ty);
- }
- None => ()
- }
- }
- }
-}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
+use middle::ty;
use middle::typeck::check::fn_ctxt;
+use middle::typeck::infer;
+
+use core::result::{Err, Ok};
+use core::result;
+use syntax::ast;
+use syntax::codemap::span;
// Requires that the two types unify, and prints an error message if they
// don't.
*/
+use core::prelude::*;
+
use middle::resolve::{Impl, MethodInfo};
+use middle::resolve;
use middle::ty::*;
+use middle::ty;
+use middle::typeck::check::{fn_ctxt, impl_self_ty};
+use middle::typeck::check::{structurally_resolved_type};
+use middle::typeck::check::vtable::VtableContext;
+use middle::typeck::check::vtable;
use middle::typeck::check;
use middle::typeck::coherence::get_base_type_def_id;
+use middle::typeck::infer;
+use middle::typeck::{method_map_entry, method_origin, method_param};
+use middle::typeck::{method_self, method_static, method_trait};
+use util::common::indenter;
+use util::ppaux::expr_repr;
use core::dvec::DVec;
+use core::result;
+use core::uint;
+use core::vec;
+use std::map::HashMap;
use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box};
use syntax::ast::{sty_uniq, sty_static, node_id, by_copy, by_ref};
use syntax::ast::{m_const, m_mutbl, m_imm};
+use syntax::ast;
use syntax::ast_map;
use syntax::ast_map::node_id_to_str;
use syntax::ast_util::dummy_sp;
+use syntax::codemap::span;
fn lookup(
fcx: @fn_ctxt,
ty_self => {
// Call is of the form "self.foo()" and appears in one
// of a trait's default method implementations.
- let self_did = self.fcx.self_impl_def_id.expect(
- ~"unexpected `none` for self_impl_def_id");
+ let self_did = self.fcx.self_info.expect(
+ ~"self_impl_def_id is undefined (`self` may not \
+ be in scope here").def_id;
let substs = {self_r: None, self_ty: None, tps: ~[]};
self.push_inherent_candidates_from_self(
self_ty, self_did, &substs);
let bound_substs = match ty::get(bound_trait_ty).sty {
- ty::ty_trait(_, ref substs, _) => (*substs),
+ ty::ty_trait(_, ref substs, _) => (/*bad*/copy *substs),
_ => {
self.bug(fmt!("add_candidates_from_param: \
non-trait bound %s",
let mut i = 0;
while i < worklist.len() {
- let (init_trait_ty, init_substs) = worklist[i];
+ let (init_trait_ty, init_substs) = /*bad*/copy worklist[i];
i += 1;
let init_trait_id = ty::ty_to_def_id(init_trait_ty).get();
// `trait_ty` for `self` here, because it allows the compiler
// to soldier on. An error will be reported should this
// candidate be selected if the method refers to `self`.
- let rcvr_substs = {self_ty: Some(self_ty), ..*substs};
+ let rcvr_substs = {self_ty: Some(self_ty), ../*bad*/copy *substs};
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(method.self_ty,
}
let method = &methods[index];
- let rcvr_substs = { self_ty: Some(self_ty), ..*substs };
+ let rcvr_substs = { self_ty: Some(self_ty), ../*bad*/copy *substs };
let (rcvr_ty, rcvr_substs) =
self.create_rcvr_ty_and_substs_for_method(
method.self_ty,
let mut merged = ~[];
let mut i = 0;
while i < candidates.len() {
- let candidate_a = candidates[i];
+ let candidate_a = /*bad*/copy candidates[i];
let mut skip = false;
let mut j = i + 1;
while j < candidates.len() {
- let candidate_b = candidates[j];
+ let candidate_b = /*bad*/copy candidates[j];
debug!("attempting to merge %? and %?",
candidate_a, candidate_b);
let candidates_same = match (&candidate_a.origin,
// Construct the full set of type parameters for the method,
// which is equal to the class tps + the method tps.
- let all_substs = {tps: vec::append(candidate.rcvr_substs.tps,
- m_substs),
- ..candidate.rcvr_substs};
+ let all_substs = {
+ tps: vec::append(/*bad*/copy candidate.rcvr_substs.tps,
+ m_substs),
+ ../*bad*/copy candidate.rcvr_substs
+ };
self.fcx.write_ty_substs(self.callee_id, fty, all_substs);
return {self_arg: {mode: ast::expl(candidate.self_mode),
trait_did: def_id,
method_num: uint) -> ty::t {
let trait_methods = ty::trait_methods(tcx, trait_did);
- ty::mk_fn(tcx, trait_methods[method_num].fty)
+ ty::mk_fn(tcx, /*bad*/copy trait_methods[method_num].fty)
}
}
ty::item_path_str(self.tcx(), did)));
}
- fn infcx(&self) -> infer::infer_ctxt {
+ fn infcx(&self) -> @infer::InferCtxt {
self.fcx.inh.infcx
}
ty::item_path_str(self.tcx(), did)
}
- fn bug(&self, s: ~str) -> ! {
+ fn bug(&self, +s: ~str) -> ! {
self.tcx().sess.bug(s)
}
}
*/
-use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig, VariantInfo_};
+use core::prelude::*;
+
+use middle::capture;
+use middle::const_eval;
+use middle::pat_util::pat_id_map;
+use middle::pat_util;
+use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_, field};
+use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
+use middle::ty::{re_bound, br_cap_avoid};
+use middle::ty;
use middle::typeck::astconv::{ast_conv, ast_path_to_ty};
use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
+use middle::typeck::astconv;
+use middle::typeck::check::_match::pat_ctxt;
use middle::typeck::check::method::TransformTypeNormally;
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_ty;
+use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
use middle::typeck::check::vtable::{LocationInfo, VtableContext};
+use middle::typeck::crate_ctxt;
use middle::typeck::infer::{resolve_type, force_tvar};
+use middle::typeck::infer;
use middle::typeck::rscope::{anon_rscope, binding_rscope, bound_self_region};
use middle::typeck::rscope::{empty_rscope, in_anon_rscope};
use middle::typeck::rscope::{in_binding_rscope, region_scope, type_rscope};
+use middle::typeck::rscope;
+use middle::typeck::{isr_alist, lookup_def_ccx, method_map_entry};
+use middle::typeck::{method_origin, method_self, method_trait, no_params};
+use middle::typeck::{require_same_types};
+use util::common::{block_query, indenter, loop_query};
+use util::ppaux::{bound_region_to_str, expr_repr};
use util::ppaux;
+use core::either;
+use core::option;
+use core::ptr;
use core::result::{Result, Ok, Err};
+use core::result;
+use core::str;
+use core::vec;
+use std::list::Nil;
use std::map::HashMap;
-use syntax::ast::ty_i;
-use syntax::ast_util::{is_local, visibility_to_privacy, Private, Public};
+use std::map;
+use syntax::ast::{provided, required, spanned, ty_i};
+use syntax::ast;
+use syntax::ast_map;
+use syntax::ast_util::{Private, Public, is_local, local_def, respan};
+use syntax::ast_util::{visibility_to_privacy};
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::codemap;
use syntax::parse::token::special_idents;
+use syntax::print::pprust::{expr_to_str, pat_to_str};
use syntax::print::pprust;
+use syntax::visit;
+use syntax;
-export alt;
+export _match;
export vtable;
export writeback;
export regionmanip;
export DontDerefArgs;
export DoDerefArgs;
export check_item_types;
+export check_block;
+export check_expr_with;
+export fn_ctxt;
+export lookup_def;
+export structure_of;
+export self_info;
+export structurally_resolved_type;
+export instantiate_path;
+export valid_range_bounds;
#[legacy_exports]
-pub mod alt;
+pub mod _match;
#[legacy_exports]
pub mod vtable;
#[legacy_exports]
/// `bar()` will each have their own `fn_ctxt`, but they will
/// share the inherited fields.
struct inherited {
- infcx: infer::infer_ctxt,
+ infcx: @infer::InferCtxt,
locals: HashMap<ast::node_id, TyVid>,
node_types: HashMap<ast::node_id, ty::t>,
node_type_substs: HashMap<ast::node_id, ty::substs>,
// var_bindings, locals and next_var_id are shared
// with any nested functions that capture the environment
// (and with any functions whose environment is being captured).
- self_impl_def_id: Option<ast::def_id>,
+
+ // Refers to whichever `self` is in scope, even this fn_ctxt is
+ // for a nested closure that captures `self`
+ self_info: Option<self_info>,
ret_ty: ty::t,
// Used by loop bodies that return from the outer function
indirect_ret_ty: Option<ty::t>,
// It's kind of a kludge to manufacture a fake function context
// and statement context, but we might as well do write the code only once
@fn_ctxt {
- self_impl_def_id: None,
+ self_info: None,
ret_ty: rty,
indirect_ret_ty: None,
purity: ast::pure_fn,
}
fn check_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
- let visit = visit::mk_simple_visitor(@{
+ let visit = visit::mk_simple_visitor(@visit::SimpleVisitor {
visit_item: |a| check_item(ccx, a),
.. *visit::default_simple_visitor()
});
}
fn check_bare_fn(ccx: @crate_ctxt,
- decl: ast::fn_decl,
+ decl: &ast::fn_decl,
body: ast::blk,
id: ast::node_id,
self_info: Option<self_info>) {
fn check_fn(ccx: @crate_ctxt,
self_info: Option<self_info>,
fn_ty: &ty::FnTy,
- decl: ast::fn_decl,
+ decl: &ast::fn_decl,
body: ast::blk,
fn_kind: FnKind,
old_fcx: Option<@fn_ctxt>) {
// types with free ones. The free region references will be bound
// the node_id of the body block.
- let {isr: isr, self_info: self_info, fn_ty: fn_ty} = {
+ let {isr, self_info, fn_sig} = {
let old_isr = option::map_default(&old_fcx, @Nil,
- |fcx| fcx.in_scope_regions);
- replace_bound_regions_in_fn_ty(tcx, old_isr, self_info, fn_ty,
- |br| ty::re_free(body.node.id, br))
+ |fcx| fcx.in_scope_regions);
+ replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, &fn_ty.sig,
+ |br| ty::re_free(body.node.id, br))
};
- let arg_tys = fn_ty.sig.inputs.map(|a| a.ty);
- let ret_ty = fn_ty.sig.output;
+ let arg_tys = fn_sig.inputs.map(|a| a.ty);
+ let ret_ty = fn_sig.output;
debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)",
arg_tys.map(|a| ppaux::ty_to_str(tcx, *a)),
} else { None };
@fn_ctxt {
- self_impl_def_id: self_info.map(|self_info| self_info.def_id),
+ self_info: self_info,
ret_ty: ret_ty,
indirect_ret_ty: indirect_ret_ty,
purity: purity,
}
};
- gather_locals(fcx, decl, body, arg_tys, self_info);
+ // XXX: Bad copy.
+ gather_locals(fcx, decl, body, copy arg_tys, self_info);
check_block(fcx, body);
// We unify the tail expr's type with the
// resolved when the enclosing scope finishes up.
if old_fcx.is_none() {
vtable::resolve_in_block(fcx, body);
- regionck::regionck_fn(fcx, decl, body);
+ regionck::regionck_fn(fcx, body);
writeback::resolve_type_vars_in_fn(fcx, decl, body, self_info);
}
fn gather_locals(fcx: @fn_ctxt,
- decl: ast::fn_decl,
+ decl: &ast::fn_decl,
body: ast::blk,
arg_tys: ~[ty::t],
self_info: Option<self_info>) {
// Check the pattern.
let region = fcx.block_region();
- let pcx = {
+ let pcx = pat_ctxt {
fcx: fcx,
map: pat_id_map(tcx.def_map, input.pat),
- alt_region: region,
+ match_region: region,
block_region: region,
};
- alt::check_pat(pcx, input.pat, *arg_ty);
+ _match::check_pat(pcx, input.pat, *arg_ty);
}
// Add explicitly-declared locals.
}
fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { }
- let visit = visit::mk_vt(@{visit_local: visit_local,
- visit_pat: visit_pat,
- visit_fn: visit_fn,
- visit_item: visit_item,
- visit_block: visit_block,
- .. *visit::default_visitor()});
+ let visit = visit::mk_vt(
+ @visit::Visitor {visit_local: visit_local,
+ visit_pat: visit_pat,
+ visit_fn: visit_fn,
+ visit_item: visit_item,
+ visit_block: visit_block,
+ ..*visit::default_visitor()});
(visit.visit_block)(body, (), visit);
}
self_id: method.self_id,
def_id: self_impl_def_id,
explicit_self: method.self_ty };
- check_bare_fn(ccx, method.decl, method.body, method.id, Some(self_info));
+ check_bare_fn(ccx, &method.decl, method.body, method.id, Some(self_info));
}
fn check_no_duplicate_fields(tcx: ty::ctxt, fields:
let self_ty = ty::node_id_to_type(tcx, id);
do struct_def.dtor.iter() |dtor| {
- let class_t = {self_ty: self_ty,
- self_id: dtor.node.self_id,
- def_id: local_def(id),
- explicit_self: {node: ast::sty_by_ref,
- span: ast_util::dummy_sp()}};
+ let class_t = { self_ty: self_ty,
+ self_id: dtor.node.self_id,
+ def_id: local_def(id),
+ explicit_self:
+ spanned { node: ast::sty_by_ref,
+ span: ast_util::dummy_sp() } };
// typecheck the dtor
- check_bare_fn(ccx, ast_util::dtor_dec(),
+ let dtor_dec = ast_util::dtor_dec();
+ check_bare_fn(ccx, &dtor_dec,
dtor.node.body, dtor.node.id,
Some(class_t));
};
ty::item_path_str(ccx.tcx, local_def(it.id)));
let _indenter = indenter();
- match it.node {
+ match /*bad*/copy it.node {
ast::item_const(_, e) => check_const(ccx, it.span, e, it.id),
ast::item_enum(ref enum_definition, _) => {
- check_enum_variants(ccx, it.span, (*enum_definition).variants, it.id);
+ check_enum_variants(ccx,
+ it.span,
+ /*bad*/copy (*enum_definition).variants,
+ it.id);
}
- ast::item_fn(decl, _, _, ref body) => {
+ ast::item_fn(ref decl, _, _, ref body) => {
check_bare_fn(ccx, decl, (*body), it.id, None);
}
ast::item_impl(_, _, ty, ms) => {
}
impl @fn_ctxt {
- fn infcx() -> infer::infer_ctxt { self.inh.infcx }
+ fn infcx() -> @infer::InferCtxt { self.inh.infcx }
fn search_in_scope_regions(br: ty::bound_region)
-> Result<ty::Region, ~str>
{
}
fn node_ty_substs(id: ast::node_id) -> ty::substs {
match self.inh.node_type_substs.find(id) {
- Some(ref ts) => (*ts),
+ Some(ref ts) => (/*bad*/copy *ts),
None => {
self.tcx().sess.bug(
fmt!("no type substs for node %d: %s in fcx %s",
let {n_tps, region_param, raw_ty} = if did.crate == ast::local_crate {
let region_param = tcx.region_paramd_items.find(did.node);
match tcx.items.find(did.node) {
- Some(ast_map::node_item(@{node: ast::item_impl(ts, _, st, _),
+ Some(ast_map::node_item(@{node: ast::item_impl(ref ts, _, st, _),
_}, _)) => {
{n_tps: ts.len(),
region_param: region_param,
raw_ty: vcx.ccx.to_ty(rscope::type_rscope(region_param), st)}
}
- Some(ast_map::node_item(@{node: ast::item_struct(_, ts),
+ Some(ast_map::node_item(@{node: ast::item_struct(_, ref ts),
id: class_id, _},_)) => {
/* If the impl is a class, the self ty is just the class ty
(doing a no-op subst for the ty params; in the next step,
raw_ty: ty::mk_struct(tcx, local_def(class_id),
{self_r: rscope::bound_self_region(region_param),
self_ty: None,
- tps: ty::ty_params_to_tys(tcx, ts)})}
+ tps: ty::ty_params_to_tys(tcx, /*bad*/copy *ts)})}
}
_ => { tcx.sess.bug(~"impl_self_ty: unbound item or item that \
doesn't have a self_ty"); }
DoDerefArgs
}
+fn break_here() {
+ debug!("break here!");
+}
+
fn check_expr_with_unifier(fcx: @fn_ctxt,
expr: @ast::expr,
expected: Option<ty::t>,
let fty =
match structure_of(fcx, sp, in_fty) {
ty::ty_fn(ref fn_ty) => {
- let fn_ty = replace_bound_regions_in_fn_ty(tcx, @Nil,
+ let fn_ty =
+ /*bad*/copy replace_bound_regions_in_fn_ty(tcx, @Nil,
None, fn_ty, |_br| fcx.infcx().next_region_var(sp,
call_expr_id)).fn_ty;
let supplied_arg_count = args.len();
+ bot |= ty::type_is_bot(fn_ty.sig.output);
+
// Grab the argument types, supplying fresh type variables
// if the wrong number of arguments were supplied
let expected_arg_count = fn_ty.sig.inputs.len();
call_expr_id: ast::node_id,
fn_ty: ty::t,
expr: @ast::expr,
- args: ~[@ast::expr],
+ +args: ~[@ast::expr],
bot: bool)
-> bool {
let mut bot = bot;
// Pull the return type out of the type of the function.
match structure_of(fcx, sp, fty) {
ty::ty_fn(ref f) => {
- bot |= (f.meta.ret_style == ast::noreturn);
fcx.write_ty(call_expr_id, f.sig.output);
return bot;
}
// A generic function for doing all of the checking for call expressions
fn check_call(fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id,
- f: @ast::expr, args: ~[@ast::expr]) -> bool {
-
+ f: @ast::expr, +args: ~[@ast::expr]) -> bool {
// Index expressions need to be handled separately, to inform them
// that they appear in call position.
- let mut bot = match f.node {
+ let mut bot = match /*bad*/copy f.node {
ast::expr_field(base, field, tys) => {
check_field(fcx, f, true, base, field, tys)
}
expr: @ast::expr,
rcvr: @ast::expr,
method_name: ast::ident,
- args: ~[@ast::expr],
+ +args: ~[@ast::expr],
tps: ~[@ast::Ty])
-> bool {
let bot = check_expr(fcx, rcvr, None);
fn lookup_op_method(fcx: @fn_ctxt, op_ex: @ast::expr,
self_ex: @ast::expr, self_t: ty::t,
- opname: ast::ident, args: ~[@ast::expr],
+ opname: ast::ident, +args: ~[@ast::expr],
+deref_args: DerefArgs)
-> Option<(ty::t, bool)>
{
// resolution is not possible (e.g., no constraints yet present), just
// returns `none`.
fn unpack_expected<O: Copy>(fcx: @fn_ctxt, expected: Option<ty::t>,
- unpack: fn(ty::sty) -> Option<O>)
+ unpack: fn(&ty::sty) -> Option<O>)
-> Option<O> {
match expected {
Some(t) => {
match resolve_type(fcx.infcx(), t, force_tvar) {
- Ok(t) => unpack(ty::get(t).sty),
+ Ok(t) => unpack(&ty::get(t).sty),
_ => None
}
}
fn check_expr_fn(fcx: @fn_ctxt,
expr: @ast::expr,
ast_proto_opt: Option<ast::Proto>,
- decl: ast::fn_decl,
+ decl: &ast::fn_decl,
body: ast::blk,
fn_kind: FnKind,
expected: Option<ty::t>) {
// to impure and block. Note that we only will use those for
// block syntax lambdas; that is, lambdas without explicit
// protos.
- let expected_sty = unpack_expected(fcx, expected, |x| Some(x));
+ let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
let (expected_tys,
expected_purity,
expected_proto,
replace_bound_regions_in_fn_ty(
tcx, @Nil, None, fn_ty,
|br| ty::re_bound(ty::br_cap_avoid(id, @br)));
- (Some({inputs: fn_ty.sig.inputs,
+ (Some({inputs: /*bad*/copy fn_ty.sig.inputs,
output: fn_ty.sig.output}),
fn_ty.meta.purity,
fn_ty.meta.proto,
fcx, fcx,
proto, purity, expected_onceness,
/*bounds:*/ @~[], /*opt_region:*/ None,
- decl, expected_tys, expr.span);
+ *decl, expected_tys, expr.span);
- let fty = ty::mk_fn(tcx, fn_ty);
+ // XXX: Bad copy.
+ let fty = ty::mk_fn(tcx, copy fn_ty);
debug!("check_expr_fn_with_unifier %s fty=%s",
expr_to_str(expr, tcx.sess.intr()),
fcx.write_ty(expr.id, fty);
- check_fn(fcx.ccx, None, &fn_ty, decl, body,
+ // We inherit the same self info as the enclosing scope,
+ // since the function we're checking might capture `self`
+ check_fn(fcx.ccx, fcx.self_info, &fn_ty, decl, body,
fn_kind, Some(fcx));
}
let expected_field_type =
ty::lookup_field_type(
tcx, class_id, field_id, substitutions);
- bot |= check_expr(fcx,
- field.node.expr,
- Some(expected_field_type));
+ bot |=
+ check_expr_with_assignability(
+ fcx,
+ field.node.expr,
+ expected_field_type);
class_field_map.insert(
field.node.ident, (field_id, true));
fields_found += 1;
fn check_struct_constructor(fcx: @fn_ctxt,
id: ast::node_id,
- span: syntax::codemap::span,
+ span: codemap::span,
class_id: ast::def_id,
fields: ~[ast::field],
base_expr: Option<@ast::expr>) -> bool {
tcx.region_paramd_items.find(class_id.node);
match tcx.items.find(class_id.node) {
Some(ast_map::node_item(@{
- node: ast::item_struct(_, type_parameters),
+ node: ast::item_struct(_, ref type_parameters),
_
}, _)) => {
raw_type = ty::mk_struct(tcx, class_id, {
self_r: self_region,
self_ty: None,
- tps: ty::ty_params_to_tys(tcx, type_parameters)
+ tps: ty::ty_params_to_tys(
+ tcx,
+ /*bad*/copy *type_parameters)
});
}
_ => {
fn check_struct_enum_variant(fcx: @fn_ctxt,
id: ast::node_id,
- span: syntax::codemap::span,
+ span: codemap::span,
enum_id: ast::def_id,
variant_id: ast::def_id,
fields: ~[ast::field]) -> bool {
tcx.region_paramd_items.find(enum_id.node);
match tcx.items.find(enum_id.node) {
Some(ast_map::node_item(@{
- node: ast::item_enum(_, type_parameters),
+ node: ast::item_enum(_, ref type_parameters),
_
}, _)) => {
raw_type = ty::mk_enum(tcx, enum_id, {
self_r: self_region,
self_ty: None,
- tps: ty::ty_params_to_tys(tcx, type_parameters)
+ tps: ty::ty_params_to_tys(
+ tcx,
+ /*bad*/copy *type_parameters)
});
}
_ => {
let tcx = fcx.ccx.tcx;
let id = expr.id;
let mut bot = false;
- match expr.node {
+ match /*bad*/copy expr.node {
ast::expr_vstore(ev, vst) => {
- let typ = match ev.node {
- ast::expr_lit(@{node: ast::lit_str(s), span:_}) => {
+ let typ = match /*bad*/copy ev.node {
+ ast::expr_lit(@ast::spanned { node: ast::lit_str(s), _ }) => {
let tt = ast_expr_vstore_to_vstore(fcx, ev, str::len(*s), vst);
ty::mk_estr(tcx, tt)
}
ast::expr_unary(unop, oprnd) => {
let exp_inner = do unpack_expected(fcx, expected) |sty| {
match unop {
- ast::box(_) | ast::uniq(_) => match sty {
- ty::ty_box(mt) | ty::ty_uniq(mt) => Some(mt.ty),
+ ast::box(_) | ast::uniq(_) => match *sty {
+ ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => Some(mt.ty),
_ => None
},
ast::not | ast::neg => expected,
fcx.write_ty(id, oprnd_t);
}
ast::expr_addr_of(mutbl, oprnd) => {
- bot = check_expr(fcx, oprnd, unpack_expected(fcx, expected, |ty|
- match ty { ty::ty_rptr(_, mt) => Some(mt.ty), _ => None }
+ bot = check_expr(fcx, oprnd, unpack_expected(fcx, expected, |sty|
+ match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty), _ => None }
));
// Note: at this point, we cannot say what the best lifetime
bot = !may_break(tcx, expr.id, (*body));
}
ast::expr_match(discrim, ref arms) => {
- bot = alt::check_alt(fcx, expr, discrim, (*arms));
+ bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms));
}
- ast::expr_fn(proto, decl, ref body, cap_clause) => {
+ ast::expr_fn(proto, ref decl, ref body, cap_clause) => {
check_expr_fn(fcx, expr, Some(proto),
decl, (*body), Vanilla, expected);
capture::check_capture_clause(tcx, expr.id, cap_clause);
}
- ast::expr_fn_block(decl, ref body, cap_clause) => {
+ ast::expr_fn_block(ref decl, ref body, cap_clause) => {
check_expr_fn(fcx, expr, None,
decl, (*body), Vanilla, expected);
capture::check_capture_clause(tcx, expr.id, cap_clause);
// 1. a closure that returns a bool is expected
// 2. the closure that was given returns unit
let mut err_happened = false;
- let expected_sty = unpack_expected(fcx, expected, |x| Some(x));
+ let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
let inner_ty = match expected_sty {
Some(ty::ty_fn(ref fty)) => {
match fcx.mk_subty(false, expr.span,
ty::mk_fn(tcx, FnTyBase {
meta: (*fty).meta,
sig: FnSig {output: ty::mk_nil(tcx),
- ..(*fty).sig}
+ ../*bad*/copy (*fty).sig}
})
}
_ =>
}
};
match b.node {
- ast::expr_fn_block(decl, ref body, cap_clause) => {
+ ast::expr_fn_block(ref decl, ref body, cap_clause) => {
check_expr_fn(fcx, b, None,
- decl, (*body), ForLoop, Some(inner_ty));
+ decl, *body, ForLoop, Some(inner_ty));
demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
capture::check_capture_clause(tcx, b.id, cap_clause);
}
}
let block_ty = structurally_resolved_type(
fcx, expr.span, fcx.node_ty(b.id));
- match ty::get(block_ty).sty {
- ty::ty_fn(ref fty) => {
- if !err_happened {
- fcx.write_ty(expr.id, ty::mk_fn(tcx, FnTyBase {
- meta: (*fty).meta,
- sig: FnSig {output: ty::mk_bool(tcx),
- ..(*fty).sig}
- }));
- }
- else {
- fcx.write_ty(expr.id, ty::mk_err(fcx.tcx()));
- }
- }
- _ => fail ~"expected fn type"
+ if err_happened {
+ fcx.write_ty(expr.id, ty::mk_err(fcx.tcx()));
+ } else {
+ let loop_body_ty = ty::replace_fn_return_type(tcx, block_ty,
+ ty::mk_bool(tcx));
+ fcx.write_ty(expr.id, loop_body_ty);
}
}
ast::expr_do_body(b) => {
- let expected_sty = unpack_expected(fcx, expected, |x| Some(x));
+ let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
let inner_ty = match expected_sty {
Some(ty::ty_fn(ref fty)) => {
- ty::mk_fn(tcx, (*fty))
+ ty::mk_fn(tcx, (/*bad*/copy *fty))
}
_ => match expected {
Some(expected_t) => {
}
};
match b.node {
- ast::expr_fn_block(decl, ref body, cap_clause) => {
+ ast::expr_fn_block(ref decl, ref body, cap_clause) => {
check_expr_fn(fcx, b, None,
- decl, (*body), DoBlock, Some(inner_ty));
+ decl, *body, DoBlock, Some(inner_ty));
demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
capture::check_capture_clause(tcx, b.id, cap_clause);
}
// argh
_ => fail ~"expected fn ty"
}
- let block_ty = structurally_resolved_type(
- fcx, expr.span, fcx.node_ty(b.id));
- match ty::get(block_ty).sty {
- ty::ty_fn(ref fty) => {
- fcx.write_ty(expr.id, ty::mk_fn(tcx, (*fty)));
- }
- _ => fail ~"expected fn ty"
- }
+ fcx.write_ty(expr.id, fcx.node_ty(b.id));
}
ast::expr_block(ref b) => {
// If this is an unchecked block, turn off purity-checking
}
ast::expr_tup(elts) => {
let flds = unpack_expected(fcx, expected, |sty| {
- match sty { ty::ty_tup(flds) => Some(flds), _ => None }
+ match *sty { ty::ty_tup(ref flds) => Some(copy *flds), _ => None }
});
let elt_ts = do elts.mapi |i, e| {
check_expr(fcx, *e, flds.map(|fs| fs[i]));
Some(fcx.expr_ty(base.get()))
} else { expected };
let flds = unpack_expected(fcx, expected, |sty|
- match sty { ty::ty_rec(flds) => Some(flds), _ => None }
+ match *sty {
+ ty::ty_rec(ref flds) => Some(copy *flds),
+ _ => None
+ }
);
let fields_t = vec::map((*fields), |f| {
bot |= check_expr(fcx, f.node.expr, flds.chain_ref(|flds|
match tcx.def_map.find(id) {
Some(ast::def_struct(type_def_id)) => {
check_struct_constructor(fcx, id, expr.span, type_def_id,
- (*fields), base_expr);
+ (/*bad*/copy *fields), base_expr);
}
Some(ast::def_variant(enum_id, variant_id)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
- variant_id, (*fields));
+ variant_id, (/*bad*/copy *fields));
}
_ => {
tcx.sess.span_bug(path.span, ~"structure constructor does \
}
if bot { fcx.write_bot(expr.id); }
- debug!("type of expr %s is %s, expected is %s",
- syntax::print::pprust::expr_to_str(expr, tcx.sess.intr()),
+ debug!("type of expr %s is...",
+ syntax::print::pprust::expr_to_str(expr, tcx.sess.intr()));
+ debug!("... %s, expected is %s",
ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
match expected {
Some(t) => ppaux::ty_to_str(tcx, t),
let region =
ty::re_scope(tcx.region_map.get(local.node.id));
- let pcx = {
+ let pcx = pat_ctxt {
fcx: fcx,
map: pat_id_map(tcx.def_map, local.node.pat),
- alt_region: region,
+ match_region: region,
block_region: region,
};
- alt::check_pat(pcx, local.node.pat, t);
+ _match::check_pat(pcx, local.node.pat, t);
return bot;
}
match stmt.node {
ast::stmt_decl(decl, id) => {
node_id = id;
- match decl.node {
+ match /*bad*/copy decl.node {
ast::decl_local(ls) => for ls.each |l| {
bot |= check_decl_local(fcx, *l);
},
for blk.node.stmts.each |s| {
if bot && !warned &&
match s.node {
- ast::stmt_decl(@{node: ast::decl_local(_), _}, _) |
+ ast::stmt_decl(@ast::spanned { node: ast::decl_local(_),
+ _}, _) |
ast::stmt_expr(_, _) | ast::stmt_semi(_, _) => {
true
}
fn check_enum_variants(ccx: @crate_ctxt,
sp: span,
- vs: ~[ast::variant],
+ +vs: ~[ast::variant],
id: ast::node_id) {
fn do_check(ccx: @crate_ctxt, sp: span, vs: ~[ast::variant],
id: ast::node_id, disr_vals: &mut ~[int], disr_val: &mut int,
*disr_val += 1;
match v.node.kind {
- ast::tuple_variant_kind(args) if args.len() > 0u => {
+ ast::tuple_variant_kind(ref args) if args.len() > 0u => {
arg_tys = Some(ty::ty_fn_args(ctor_ty).map(|a| a.ty));
}
ast::tuple_variant_kind(_) => {
}
ast::enum_variant_kind(_) => {
arg_tys = None;
- do_check(ccx, sp, vs, id, disr_vals, disr_val, variants);
+ do_check(ccx,
+ sp,
+ /*bad*/copy vs,
+ id,
+ disr_vals,
+ disr_val,
+ variants);
}
}
span: span,
node_id: ast::node_id,
region_lb: ty::Region) {
+ debug!(">>> instantiate_path");
+
let ty_param_count = vec::len(*tpt.bounds);
let ty_substs_len = vec::len(pth.types);
let substs = {self_r: self_r, self_ty: None, tps: tps};
fcx.write_ty_substs(node_id, tpt.ty, substs);
+
+ debug!("<<<");
}
// Resolves `typ` by a single level if `typ` is a type variable. If no
// Returns the one-level-deep structure of the given type.
fn structure_of(fcx: @fn_ctxt, sp: span, typ: ty::t) -> ty::sty {
- ty::get(structurally_resolved_type(fcx, sp, typ)).sty
+ /*bad*/copy ty::get(structurally_resolved_type(fcx, sp, typ)).sty
}
fn type_is_integral(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
(1u, ~[], ty::mk_nil_ptr(tcx))
}
~"visit_tydesc" => {
- let tydesc_name = syntax::parse::token::special_idents::tydesc;
+ let tydesc_name = special_idents::tydesc;
let ty_visitor_name = tcx.sess.ident_of(~"TyVisitor");
assert tcx.intrinsic_defs.contains_key(tydesc_name);
assert ccx.tcx.intrinsic_defs.contains_key(ty_visitor_name);
proto: ast::ProtoBorrowed,
onceness: ast::Once,
region: ty::re_bound(ty::br_anon(0)),
- bounds: @~[],
- ret_style: ast::return_val},
+ bounds: @~[]},
sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val),
ty: ty::mk_imm_ptr(
ccx.tcx,
(0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
ty::mk_i64(tcx))
}
+ ~"bswap16" => {
+ (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))],
+ ty::mk_i16(tcx))
+ }
+ ~"bswap32" => {
+ (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))],
+ ty::mk_i32(tcx))
+ }
+ ~"bswap64" => {
+ (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))],
+ ty::mk_i64(tcx))
+ }
ref other => {
tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" +
(*other) + ~"`");
proto: ast::ProtoBare,
onceness: ast::Many,
region: ty::re_static,
- bounds: @~[],
- ret_style: ast::return_val},
+ bounds: @~[]},
sig: FnSig {inputs: inputs,
output: output}
});
*/
+use core::prelude::*;
+
use middle::freevars::get_freevars;
use middle::pat_util::pat_bindings;
use middle::ty::{encl_region, re_scope};
use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice};
use middle::ty::{vstore_uniq};
-use middle::typeck::infer::{resolve_and_force_all_but_regions, fres};
+use middle::ty;
+use middle::typeck::check::fn_ctxt;
+use middle::typeck::check::lookup_def;
+use middle::typeck::infer::{fres, resolve_and_force_all_but_regions};
+use middle::typeck::infer::{resolve_type};
use util::ppaux::{note_and_explain_region, ty_to_str};
+use core::result;
use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed};
use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar};
+use syntax::ast;
+use syntax::codemap::span;
use syntax::print::pprust;
+use syntax::visit;
enum rcx { rcx_({fcx: @fn_ctxt, mut errors_reported: uint}) }
type rvt = visit::vt<@rcx>;
}
fn regionck_fn(fcx: @fn_ctxt,
- _decl: ast::fn_decl,
blk: ast::blk) {
let rcx = rcx_({fcx:fcx, mut errors_reported: 0});
let v = regionck_visitor();
}
fn regionck_visitor() -> rvt {
- visit::mk_vt(@{visit_item: visit_item,
- visit_stmt: visit_stmt,
- visit_expr: visit_expr,
- visit_block: visit_block,
- visit_local: visit_local,
- .. *visit::default_visitor()})
+ visit::mk_vt(@visit::Visitor {visit_item: visit_item,
+ visit_stmt: visit_stmt,
+ visit_expr: visit_expr,
+ visit_block: visit_block,
+ visit_local: visit_local,
+ .. *visit::default_visitor()})
}
fn visit_item(_item: @ast::item, &&_rcx: @rcx, _v: rvt) {
debug!("visit_expr(e=%s)",
pprust::expr_to_str(expr, rcx.fcx.tcx().sess.intr()));
- match expr.node {
+ match /*bad*/copy expr.node {
ast::expr_path(*) => {
// Avoid checking the use of local variables, as we
// already check their definitions. The def'n always
// except according to those terms.
// #[warn(deprecated_mode)];
-// #[warn(deprecated_pattern)];
+use core::prelude::*;
+
+use middle::ty::{FnTyBase};
+use middle::ty;
+use middle::typeck::check::self_info;
+use middle::typeck::isr_alist;
+use util::common::indenter;
+use util::ppaux::region_to_str;
use util::ppaux;
+use std::list::Cons;
+use syntax::ast;
use syntax::print::pprust::{expr_to_str};
// Helper functions related to manipulating region types.
-fn replace_bound_regions_in_fn_ty(
+pub fn replace_bound_regions_in_fn_ty(
tcx: ty::ctxt,
isr: isr_alist,
self_info: Option<self_info>,
fn_ty: &ty::FnTy,
mapf: fn(ty::bound_region) -> ty::Region) ->
- {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy} {
+ {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy}
+{
+ let {isr, self_info, fn_sig} =
+ replace_bound_regions_in_fn_sig(
+ tcx, isr, self_info, &fn_ty.sig, mapf);
+ {isr: isr,
+ self_info: self_info,
+ fn_ty: FnTyBase {meta: fn_ty.meta,
+ sig: fn_sig}}
+}
+pub fn replace_bound_regions_in_fn_sig(
+ tcx: ty::ctxt,
+ isr: isr_alist,
+ self_info: Option<self_info>,
+ fn_sig: &ty::FnSig,
+ mapf: fn(ty::bound_region) -> ty::Region) ->
+ {isr: isr_alist, self_info: Option<self_info>, fn_sig: ty::FnSig}
+{
// Take self_info apart; the self_ty part is the only one we want
// to update here.
- let (self_ty, rebuild_self_info) = match self_info {
- Some(copy s) => (Some(s.self_ty), |t| Some({self_ty: t,.. s})),
- None => (None, |_t| None)
- };
+ let self_ty = self_info.map(|s| s.self_ty);
+ let rebuild_self_info = |t| self_info.map(|s| {self_ty: t, ..*s});
- let mut all_tys = ty::tys_in_fn_ty(fn_ty);
+ let mut all_tys = ty::tys_in_fn_sig(fn_sig);
match self_info {
- Some({explicit_self: {node: ast::sty_region(m), _}, _}) => {
+ Some({explicit_self: ast::spanned { node: ast::sty_region(m),
+ _}, _}) => {
let region = ty::re_bound(ty::br_self);
let ty = ty::mk_rptr(tcx, region,
{ ty: ty::mk_self(tcx), mutbl: m });
for self_ty.each |t| { all_tys.push(*t) }
- debug!("replace_bound_regions_in_fn_ty(self_info.self_ty=%?, fn_ty=%s, \
- all_tys=%?)",
+ debug!("replace_bound_regions_in_fn_sig(self_info.self_ty=%?, fn_sig=%s, \
+ all_tys=%?)",
self_ty.map(|t| ppaux::ty_to_str(tcx, *t)),
- ppaux::ty_to_str(tcx, ty::mk_fn(tcx, *fn_ty)),
+ ppaux::fn_sig_to_str(tcx, fn_sig),
all_tys.map(|t| ppaux::ty_to_str(tcx, *t)));
let _i = indenter();
debug!("br=%?", br);
mapf(br)
};
- let ty_fn = ty::ty_fn(*fn_ty);
- let t_fn = ty::fold_sty_to_ty(tcx, &ty_fn, |t| {
+ let new_fn_sig = ty::fold_sig(fn_sig, |t| {
replace_bound_regions(tcx, isr, t)
});
let t_self = self_ty.map(|t| replace_bound_regions(tcx, isr, *t));
- debug!("result of replace_bound_regions_in_fn_ty: self_info.self_ty=%?, \
- fn_ty=%s",
+ debug!("result of replace_bound_regions_in_fn_sig: self_info.self_ty=%?, \
+ fn_sig=%s",
t_self.map(|t| ppaux::ty_to_str(tcx, *t)),
- ppaux::ty_to_str(tcx, t_fn));
-
+ ppaux::fn_sig_to_str(tcx, &new_fn_sig));
// Glue updated self_ty back together with its original def_id.
let new_self_info: Option<self_info> = match t_self {
};
return {isr: isr,
- self_info: new_self_info,
- fn_ty: match ty::get(t_fn).sty { ty::ty_fn(ref o) => (*o),
- _ => tcx.sess.bug(~"replace_bound_regions_in_fn_ty: impossible")}};
-
+ self_info: new_self_info,
+ fn_sig: new_fn_sig};
// Takes `isr`, a (possibly empty) mapping from in-scope region
// names ("isr"s) to their corresponding regions; `tys`, a list of
ty: ty::t) -> ty::t {
do ty::fold_regions(tcx, ty) |r, in_fn| {
- match r {
+ let r1 = match r {
// As long as we are not within a fn() type, `&T` is
// mapped to the free region anon_r. But within a fn
// type, it remains bound.
ty::re_scope(_) |
ty::re_free(_, _) |
ty::re_infer(_) => r
- }
+ };
+ r1
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::resolve;
+use middle::ty;
use middle::typeck::check::{fn_ctxt, impl_self_ty};
-use middle::typeck::infer::{fixup_err_to_str, infer_ctxt};
+use middle::typeck::check::{structurally_resolved_type};
+use middle::typeck::infer::{fixup_err_to_str, InferCtxt};
use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
+use middle::typeck::infer;
+use middle::typeck::{crate_ctxt, vtable_origin, vtable_param, vtable_res};
+use middle::typeck::{vtable_static, vtable_trait};
use util::common::indenter;
+use util::ppaux::tys_to_str;
use util::ppaux;
+use core::result;
+use core::uint;
+use core::vec;
use result::{Result, Ok, Err};
+use std::map::HashMap;
+use syntax::ast;
+use syntax::ast_util;
use syntax::codemap::span;
+use syntax::print::pprust::expr_to_str;
use syntax::print::pprust;
+use syntax::visit;
// vtable resolution looks for places where trait bounds are
// subsituted in and figures out which vtable is used. There is some
/// callback function to call in case of type error.
struct VtableContext {
ccx: @crate_ctxt,
- infcx: infer::infer_ctxt
+ infcx: @infer::InferCtxt
}
impl VtableContext {
ppaux::ty_to_str(tcx, trait_ty),
ty::substs_to_str(tcx, substs));
- let new_substs = {self_ty: Some(*ty), ..*substs};
+ let new_substs = {self_ty: Some(*ty), ../*bad*/copy *substs};
let trait_ty = ty::subst(tcx, &new_substs, trait_ty);
debug!("after subst: %?",
}
fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
- id: ast::def_id, substs: ty::substs,
+ id: ast::def_id, +substs: ty::substs,
is_early: bool) -> Option<ty::substs> {
let tcx = vcx.tcx();
// use a dummy type just to package up the substs that need fixing up
let t = ty::mk_trait(tcx, id, substs, ty::vstore_slice(ty::re_static));
do fixup_ty(vcx, location_info, t, is_early).map |t_f| {
match ty::get(*t_f).sty {
- ty::ty_trait(_, ref substs_f, _) => (*substs_f),
+ ty::ty_trait(_, ref substs_f, _) => (/*bad*/copy *substs_f),
_ => fail ~"t_f should be a trait"
}
}
let tcx = vcx.tcx();
let (trait_id, trait_substs, trait_vstore) = match ty::get(trait_ty).sty {
- ty::ty_trait(did, ref substs, vstore) => (did, (*substs), vstore),
+ ty::ty_trait(did, ref substs, vstore) =>
+ (did, (/*bad*/copy *substs), vstore),
_ => tcx.sess.impossible_case(location_info.span,
"lookup_vtable: \
don't know how to handle a non-trait")
relate_trait_tys(vcx, location_info, trait_ty, ty);
if !allow_unsafe && !is_early {
for vec::each(*ty::trait_methods(tcx, did)) |m| {
- if ty::type_has_self(ty::mk_fn(tcx, m.fty)) {
+ if ty::type_has_self(ty::mk_fn(tcx, /*bad*/copy m.fty)) {
tcx.sess.span_err(
location_info.span,
~"a boxed trait with self types may not be \
}
}
}
- return Some(vtable_trait(did, (*substs).tps));
+ return Some(vtable_trait(did, /*bad*/copy (*substs).tps));
}
_ => {
// trait_substs. Now we extract out the
// types themselves from trait_substs.
- let trait_tps = trait_substs.tps;
+ let trait_tps = /*bad*/copy trait_substs.tps;
debug!("Casting to a trait ty whose substs \
(trait_tps) are %s",
trait_id,
substs,
is_early) {
- Some(ref substs) => (*substs),
+ Some(ref substs) => (/*bad*/copy *substs),
None => {
assert is_early;
// Bail out with a bogus answer
im.did).bounds;
connect_trait_tps(vcx,
location_info,
- substs_f.tps,
+ /*bad*/copy substs_f.tps,
trait_tps,
im.did,
trait_vstore);
// of type substitutions for the target
// trait.
found.push(
- vtable_static(im.did, substs_f.tps,
+ vtable_static(im.did,
+ /*bad*/copy substs_f.tps,
subres));
}
}
match found.len() {
0 => { /* fallthrough */ }
- 1 => { return Some(found[0]); }
+ 1 => { return Some(/*bad*/copy found[0]); }
_ => {
if !is_early {
vcx.tcx().sess.span_err(
location_info.span,
~"multiple applicable methods in scope");
}
- return Some(found[0]);
+ return Some(/*bad*/copy found[0]);
}
}
}
let item_ty = ty::lookup_item_type(cx.tcx, did);
debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def,
fcx.infcx().ty_to_str(item_ty.ty));
- if has_trait_bounds(*item_ty.bounds) {
+ if has_trait_bounds(/*bad*/copy *item_ty.bounds) {
for item_ty.bounds.each |bounds| {
debug!("early_resolve_expr: looking up vtables for bound \
%s",
ast::expr_index(*) | ast::expr_method_call(*) => {
match ty::method_call_bounds(cx.tcx, cx.method_map, ex.id) {
Some(bounds) => {
- if has_trait_bounds(*bounds) {
+ if has_trait_bounds(/*bad*/copy *bounds) {
let callee_id = match ex.node {
ast::expr_field(_, _, _) => ex.id,
_ => ex.callee_id
ex.span,
fmt!("failed to find an implementation of trait \
%s for %s",
- ppaux::ty_to_str(fcx.tcx(), target_ty),
- ppaux::ty_to_str(fcx.tcx(), ty)));
+ fcx.infcx().ty_to_str(target_ty),
+ fcx.infcx().ty_to_str(ty)));
}
}
Some(vtable) => {
// Detect points where a trait-bounded type parameter is
// instantiated, resolve the impls for the parameters.
fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) {
- visit::visit_block(bl, fcx, visit::mk_vt(@{
+ visit::visit_block(bl, fcx, visit::mk_vt(@visit::Visitor {
visit_expr: resolve_expr,
visit_item: fn@(_i: @ast::item, &&_e: @fn_ctxt,
_v: visit::vt<@fn_ctxt>) {},
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
-use middle::typeck::check::{fn_ctxt, lookup_local};
+use core::prelude::*;
+
+use middle::pat_util;
+use middle::ty;
+use middle::typeck::check::{fn_ctxt, lookup_local, self_info};
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::{resolve_type};
+use middle::typeck::infer;
+use middle::typeck::{vtable_param, vtable_trait, write_substs_to_tcx};
+use middle::typeck::{write_ty_to_tcx};
use util::ppaux;
-use result::{Result, Ok, Err};
+use core::result::{Result, Ok, Err};
+use core::vec;
+use std::map::HashMap;
+use syntax::ast;
+use syntax::codemap::span;
+use syntax::print::pprust::pat_to_str;
+use syntax::visit;
export resolve_type_vars_in_fn;
export resolve_type_vars_in_expr;
resolve_method_map_entry(wbcx.fcx, e.span, e.id);
resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id);
match e.node {
- ast::expr_fn(_, decl, _, _) |
- ast::expr_fn_block(decl, _, _) => {
+ ast::expr_fn_block(ref decl, _, _) => {
for vec::each(decl.inputs) |input| {
let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id);
}
fn mk_visitor() -> visit::vt<wb_ctxt> {
- visit::mk_vt(@{visit_item: visit_item,
- visit_stmt: visit_stmt,
- visit_expr: visit_expr,
- visit_block: visit_block,
- visit_pat: visit_pat,
- visit_local: visit_local,
- .. *visit::default_visitor()})
+ visit::mk_vt(@visit::Visitor {visit_item: visit_item,
+ visit_stmt: visit_stmt,
+ visit_expr: visit_expr,
+ visit_block: visit_block,
+ visit_pat: visit_pat,
+ visit_local: visit_local,
+ .. *visit::default_visitor()})
}
fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool {
}
fn resolve_type_vars_in_fn(fcx: @fn_ctxt,
- decl: ast::fn_decl,
+ decl: &ast::fn_decl,
blk: ast::blk,
self_info: Option<self_info>) -> bool {
let wbcx = {fcx: fcx, mut success: true};
// has at most one implementation for each type. Then we build a mapping from
// each trait in the system to its implementations.
+use core::prelude::*;
+
+use driver;
use metadata::csearch::{ProvidedTraitMethodInfo, each_path, get_impl_traits};
use metadata::csearch::{get_impls_for_mod};
+use metadata::csearch;
use metadata::cstore::{CStore, iter_crate_data};
use metadata::decoder::{dl_def, dl_field, dl_impl};
use middle::resolve::{Impl, MethodInfo};
use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst};
use middle::ty::{t, ty_bool, ty_bot, ty_box, ty_enum, ty_err, ty_estr};
-use middle::ty::{ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil, ty_ptr};
-use middle::ty::{ty_rec, ty_rptr, ty_struct, ty_trait, ty_tup, ty_uint};
-use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box, ty_uniq};
+use middle::ty::{ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil};
+use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
+use middle::ty::{ty_rec, ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
+use middle::ty::{ty_type, ty_uint, ty_uniq};
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext};
use middle::ty::{type_is_ty_var};
-use middle::typeck::infer::{infer_ctxt, can_mk_subty};
+use middle::ty;
+use middle::typeck::crate_ctxt;
+use middle::typeck::infer::{InferCtxt, can_mk_subty};
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
use syntax::ast::{crate, def_id, def_mod, def_ty};
use syntax::ast::{item_foreign_mod, item_impl, item_mac, item_mod};
use syntax::ast::{item_trait, item_ty, local_crate, method, node_id};
use syntax::ast::{trait_ref};
+use syntax::ast;
use syntax::ast_map::node_item;
-use syntax::ast_util::{def_id_of_def, dummy_sp};
+use syntax::ast_map;
+use syntax::ast_util::{def_id_of_def, dummy_sp, local_def};
use syntax::attr;
use syntax::codemap::span;
+use syntax::parse;
use syntax::visit::{default_simple_visitor, default_visitor};
use syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item};
+use syntax::visit::{Visitor, SimpleVisitor};
use syntax::visit::{visit_mod};
use util::ppaux::ty_to_str;
use core::dvec::DVec;
use core::result::Ok;
-use std::map::HashMap;
+use core::send_map;
use core::uint::range;
+use core::uint;
use core::vec::{len, push};
+use core::vec;
+use std::map::HashMap;
struct UniversalQuantificationResult {
monotype: t,
bounds: @~[param_bounds]
}
-fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t)
+fn get_base_type(inference_context: @InferCtxt, span: span, original_type: t)
-> Option<t> {
let resolved_type;
}
// Returns the def ID of the base type, if there is one.
-fn get_base_type_def_id(inference_context: infer_ctxt,
+fn get_base_type_def_id(inference_context: @InferCtxt,
span: span,
original_type: t)
-> Option<def_id> {
struct CoherenceChecker {
crate_context: @crate_ctxt,
- inference_context: infer_ctxt,
+ inference_context: @InferCtxt,
// A mapping from implementations to the corresponding base type
// definition ID.
// Check implementations and traits. This populates the tables
// containing the inherent methods and extension methods. It also
// builds up the trait inheritance table.
- visit_crate(*crate, (), mk_simple_visitor(@{
+ visit_crate(*crate, (), mk_simple_visitor(@SimpleVisitor {
visit_item: |item| {
debug!("(checking coherence) item '%s'",
self.crate_context.tcx.sess.str_of(item.ident));
for self.each_provided_trait_method(trait_did) |trait_method| {
// Synthesize an ID.
let tcx = self.crate_context.tcx;
- let new_id = syntax::parse::next_node_id(tcx.sess.parse_sess);
+ let new_id = parse::next_node_id(tcx.sess.parse_sess);
let new_did = local_def(new_id);
// XXX: Perform substitutions.
self_ty: None,
tps: type_parameters
};
-
let monotype = subst(self.crate_context.tcx,
&substitutions,
polytype.ty);
+
+ // Get our type parameters back.
+ let { self_r: _, self_ty: _, tps: type_parameters } = substitutions;
+
UniversalQuantificationResult {
monotype: monotype,
type_variables: move type_parameters,
// Privileged scope checking
fn check_privileged_scopes(crate: @crate) {
- visit_crate(*crate, (), mk_vt(@{
+ visit_crate(*crate, (), mk_vt(@Visitor {
visit_item: |item, _context, visitor| {
- match item.node {
+ match /*bad*/copy item.node {
item_mod(module_) => {
// Then visit the module items.
visit_mod(module_, item.span, item.id, (), visitor);
}
}
- match item.node {
+ match /*bad*/copy item.node {
item_impl(_, trait_refs, _, ast_methods) => {
let mut methods = ~[];
for ast_methods.each |ast_method| {
// Create a new def ID for this provided method.
let parse_sess = &self.crate_context.tcx.sess.parse_sess;
- let new_did = local_def(syntax::parse::next_node_id(*parse_sess));
+ let new_did = local_def(parse::next_node_id(*parse_sess));
let provided_method_info =
@ProvidedMethodInfo {
fn populate_destructor_table() {
let coherence_info = &self.crate_context.coherence_info;
let tcx = self.crate_context.tcx;
- let drop_trait = tcx.lang_items.drop_trait.get();
+ let drop_trait = tcx.lang_items.drop_trait();
let impls_opt = coherence_info.extension_methods.find(drop_trait);
let impls;
*/
+use core::prelude::*;
+
+use metadata::csearch;
use middle::ty::{FnMeta, FnSig, FnTyBase, InstantiatedTraitRef};
+use middle::ty::{ty_param_substs_and_ty};
+use middle::ty;
use middle::typeck::astconv::{ast_conv, ty_of_fn_decl, ty_of_arg};
use middle::typeck::astconv::{ast_ty_to_ty};
+use middle::typeck::astconv;
+use middle::typeck::infer;
use middle::typeck::rscope::*;
-use util::common::pluralize;
+use middle::typeck::rscope;
+use middle::typeck::{crate_ctxt, lookup_def_tcx, no_params, write_ty_to_tcx};
+use util::common::{indenter, pluralize};
use util::ppaux;
use util::ppaux::bound_to_str;
-use syntax::ast_util::trait_method_to_ty_method;
+use core::dvec;
+use core::option;
+use core::vec;
+use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
+use syntax::ast;
+use syntax::ast_map;
+use syntax::ast_util::{local_def, split_trait_methods};
+use syntax::ast_util::{trait_method_to_ty_method};
+use syntax::ast_util;
+use syntax::codemap::span;
+use syntax::codemap;
+use syntax::print::pprust::path_to_str;
+use syntax::visit;
fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
for crate.node.module.items.each |crate_item| {
if crate_item.ident
- == syntax::parse::token::special_idents::intrinsic {
+ == ::syntax::parse::token::special_idents::intrinsic {
- match crate_item.node {
+ match /*bad*/copy crate_item.node {
ast::item_mod(m) => {
for m.items.each |intrinsic_item| {
let def_id = { crate: ast::local_crate,
}
}
- visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
- visit_item: |a|convert(ccx, a),
- visit_foreign_item: |a|convert_foreign(ccx, a),
- .. *visit::default_simple_visitor()
- }));
+ visit::visit_crate(
+ *crate, (),
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_item: |a|convert(ccx, a),
+ visit_foreign_item: |a|convert_foreign(ccx, a),
+ .. *visit::default_simple_visitor()
+ }));
}
impl @crate_ctxt {
// constructors get turned into functions.
let result_ty;
match variant.node.kind {
- ast::tuple_variant_kind(args) if args.len() > 0 => {
+ ast::tuple_variant_kind(ref args) if args.len() > 0 => {
let rs = type_rscope(rp);
let args = args.map(|va| {
let arg_ty = ccx.to_ty(rs, va.ty);
proto: ast::ProtoBare,
onceness: ast::Many,
bounds: @~[],
- region: ty::re_static,
- ret_style: ast::return_val},
+ region: ty::re_static},
sig: FnSig {inputs: args,
output: enum_ty}
}));
result_ty = Some(enum_ty);
}
ast::struct_variant_kind(struct_def) => {
- result_ty = Some(enum_ty);
// XXX: Merge with computation of the the same value below?
- let tpt = {bounds: ty_param_bounds(ccx, ty_params),
- region_param: rp,
- ty: enum_ty};
+ let tpt = {
+ bounds: ty_param_bounds(ccx, /*bad*/copy ty_params),
+ region_param: rp,
+ ty: enum_ty
+ };
convert_struct(
- ccx, rp, struct_def, ty_params, tpt, variant.node.id);
+ ccx,
+ rp,
+ struct_def,
+ /*bad*/copy ty_params,
+ tpt,
+ variant.node.id);
+ // Compute the ctor arg types from the struct fields
+ let struct_fields = do struct_def.fields.map |struct_field| {
+ {mode: ast::expl(ast::by_val),
+ ty: ty::node_id_to_type(ccx.tcx, (*struct_field).node.id)
+ }
+ };
+ result_ty = Some(ty::mk_fn(tcx, FnTyBase {
+ meta: FnMeta {purity: ast::pure_fn,
+ proto: ast::ProtoBare,
+ onceness: ast::Many,
+ bounds: @~[],
+ region: ty::re_static},
+ sig: FnSig {inputs: struct_fields, output: enum_ty }}));
}
ast::enum_variant_kind(ref enum_definition) => {
get_enum_variant_types(ccx,
enum_ty,
- enum_definition.variants,
- ty_params,
+ /*bad*/copy enum_definition.variants,
+ /*bad*/copy ty_params,
rp);
result_ty = None;
}
match result_ty {
None => {}
Some(result_ty) => {
- let tpt = {bounds: ty_param_bounds(ccx, ty_params),
- region_param: rp,
- ty: result_ty};
+ let tpt = {
+ bounds: ty_param_bounds(ccx, /*bad*/copy ty_params),
+ region_param: rp,
+ ty: result_ty
+ };
tcx.tcache.insert(local_def(variant.node.id), tpt);
write_ty_to_tcx(tcx, variant.node.id, result_ty);
}
fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) {
fn store_methods<T>(ccx: @crate_ctxt, id: ast::node_id,
- stuff: ~[T], f: fn@(v: &T) -> ty::method) {
+ stuff: ~[T], f: &fn(v: &T) -> ty::method) {
ty::store_trait_methods(ccx.tcx, id, @vec::map(stuff, f));
}
let substs = { self_r: None, self_ty: Some(self_param),
tps: non_shifted_trait_tps + shifted_method_tps };
- let ty = ty::subst(ccx.tcx, &substs, ty::mk_fn(ccx.tcx, m.fty));
+ let ty = ty::subst(ccx.tcx,
+ &substs,
+ ty::mk_fn(ccx.tcx, /*bad*/copy m.fty));
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
+ *m.tps);
ccx.tcx.tcache.insert(local_def(am.id),
let region_paramd = tcx.region_paramd_items.find(id);
match tcx.items.get(id) {
ast_map::node_item(@{
- node: ast::item_trait(params, _, ref ms),
+ node: ast::item_trait(ref params, _, ref ms),
_
}, _) => {
- store_methods::<ast::trait_method>(ccx, id, (*ms), |m| {
+ store_methods::<ast::trait_method>(ccx, id, (/*bad*/copy *ms), |m| {
let def_id;
match *m {
ast::required(ref ty_method) => {
ast::provided(method) => def_id = local_def(method.id)
}
- let trait_bounds = ty_param_bounds(ccx, params);
+ let trait_bounds = ty_param_bounds(ccx, copy *params);
let ty_m = trait_method_to_ty_method(*m);
let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id);
if ty_m.self_ty.node == ast::sty_static {
// that correspond to the parameters we will find on the impl
// - replace self region with a fresh, dummy region
let impl_fty = {
- let impl_fty = ty::mk_fn(tcx, impl_m.fty);
+ let impl_fty = ty::mk_fn(tcx, /*bad*/copy impl_m.fty);
debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty));
replace_bound_self(tcx, impl_fty, dummy_self_r)
};
self_ty: Some(self_ty),
tps: vec::append(trait_tps, dummy_tps)
};
- let trait_fty = ty::mk_fn(tcx, trait_m.fty);
+ let trait_fty = ty::mk_fn(tcx, /*bad*/copy trait_m.fty);
debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty));
ty::subst(tcx, &substs, trait_fty)
};
let tcx = ccx.tcx;
do vec::map(ms) |m| {
- let bounds = ty_param_bounds(ccx, m.tps);
+ let bounds = ty_param_bounds(ccx, /*bad*/copy m.tps);
let mty = ty_of_method(ccx, *m, rp);
- let fty = ty::mk_fn(tcx, mty.fty);
+ let fty = ty::mk_fn(tcx, /*bad*/copy mty.fty);
tcx.tcache.insert(
local_def(m.id),
// n.b.: the type of a method is parameterized by both
// the tps on the receiver and those on the method itself
- {bounds: @(vec::append(*rcvr_bounds, *bounds)),
+ {bounds: @(vec::append(/*bad*/copy *rcvr_bounds, *bounds)),
region_param: rp,
ty: fty});
write_ty_to_tcx(tcx, m.id, fty);
let rp = tcx.region_paramd_items.find(it.id);
debug!("convert: item %s with id %d rp %?",
tcx.sess.str_of(it.ident), it.id, rp);
- match it.node {
+ match /*bad*/copy it.node {
// These don't define types.
ast::item_foreign_mod(_) | ast::item_mod(_) => {}
- ast::item_enum(ref enum_definition, ty_params) => {
+ ast::item_enum(ref enum_definition, ref ty_params) => {
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
- get_enum_variant_types(ccx, tpt.ty, (*enum_definition).variants,
- ty_params, rp);
+ get_enum_variant_types(ccx,
+ tpt.ty,
+ /*bad*/copy (*enum_definition).variants,
+ /*bad*/copy *ty_params, rp);
}
- ast::item_impl(tps, trait_ref, selfty, ms) => {
- let i_bounds = ty_param_bounds(ccx, tps);
+ ast::item_impl(ref tps, trait_ref, selfty, ref ms) => {
+ let i_bounds = ty_param_bounds(ccx, /*bad*/copy *tps);
let selfty = ccx.to_ty(type_rscope(rp), selfty);
write_ty_to_tcx(tcx, it.id, selfty);
tcx.tcache.insert(local_def(it.id),
region_param: rp,
ty: selfty});
- let cms = convert_methods(ccx, ms, rp, i_bounds);
+ // XXX: Bad copy of `ms` below.
+ let cms = convert_methods(ccx, /*bad*/copy *ms, rp, i_bounds);
for trait_ref.each |t| {
- check_methods_against_trait(ccx, tps, rp, selfty, *t, cms);
+ check_methods_against_trait(ccx, /*bad*/copy *tps, rp, selfty,
+ *t, /*bad*/copy cms);
}
}
- ast::item_trait(tps, supertraits, ref trait_methods) => {
+ ast::item_trait(ref tps, ref supertraits, ref trait_methods) => {
let tpt = ty_of_item(ccx, it);
debug!("item_trait(it.id=%d, tpt.ty=%s)",
it.id, ppaux::ty_to_str(tcx, tpt.ty));
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id, tpt.ty);
- ensure_supertraits(ccx, it.id, it.span, rp, supertraits);
+ ensure_supertraits(ccx, it.id, it.span, rp, *supertraits);
- let (_, provided_methods) = split_trait_methods((*trait_methods));
- let {bounds, _} = mk_substs(ccx, tps, rp);
+ let (_, provided_methods) =
+ split_trait_methods(/*bad*/copy *trait_methods);
+ let {bounds, _} = mk_substs(ccx, /*bad*/copy *tps, rp);
let _cms = convert_methods(ccx, provided_methods, rp, bounds);
// FIXME (#2616): something like this, when we start having
// trait inheritance?
fn convert_struct(ccx: @crate_ctxt,
rp: Option<ty::region_variance>,
struct_def: @ast::struct_def,
- tps: ~[ast::ty_param],
+ +tps: ~[ast::ty_param],
tpt: ty::ty_param_bounds_and_ty,
id: ast::node_id) {
let tcx = ccx.tcx;
proto: ast::ProtoBare,
onceness: ast::Many,
bounds: @~[],
- region: ty::re_static,
- ret_style: ast::return_val,
+ region: ty::re_static
},
sig: FnSig {
inputs: do struct_def.fields.map |field| {
m: @ast::method,
rp: Option<ty::region_variance>) -> ty::method {
{ident: m.ident,
- tps: ty_param_bounds(ccx, m.tps),
+ tps: ty_param_bounds(ccx, /*bad*/copy m.tps),
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare,
m.purity, ast::Many,
/*bounds:*/ @~[], /*opt_region:*/ None,
rp: Option<ty::region_variance>,
id: ast::def_id) -> ty::method {
{ident: m.ident,
- tps: ty_param_bounds(self, m.tps),
+ tps: ty_param_bounds(self, /*bad*/copy m.tps),
fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare,
m.purity, ast::Many,
/*bounds:*/ @~[], /*opt_region:*/ None,
_ => {}
}
let rp = tcx.region_paramd_items.find(it.id);
- match it.node {
+ match /*bad*/copy it.node {
ast::item_const(t, _) => {
let typ = ccx.to_ty(empty_rscope, t);
let tpt = no_params(typ);
fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item)
-> ty::ty_param_bounds_and_ty {
- match it.node {
+ match /*bad*/copy it.node {
ast::foreign_item_fn(fn_decl, purity, params) => {
return ty_of_foreign_fn_decl(ccx, fn_decl, purity, params,
local_def(it.id));
}
}
-// Translate the AST's notion of ty param bounds (which are just newtyped Tys)
-// to ty's notion of ty param bounds, which can either be user-defined traits,
-// or one of the four built-in traits (formerly known as kinds): Const, Copy,
-// Durable, and Send.
+// Translate the AST's notion of ty param bounds (which are an enum consisting
+// of a newtyped Ty or a region) to ty's notion of ty param bounds, which can
+// either be user-defined traits, or one of the four built-in traits (formerly
+// known as kinds): Const, Copy, Durable, and Send.
fn compute_bounds(ccx: @crate_ctxt,
- ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds {
+ ast_bounds: @~[ast::ty_param_bound])
+ -> ty::param_bounds {
@do vec::flat_map(*ast_bounds) |b| {
- let li = &ccx.tcx.lang_items;
- let ity = ast_ty_to_ty(ccx, empty_rscope, **b);
- match ty::get(ity).sty {
- ty::ty_trait(did, _, _) => {
- let d = Some(did);
- if d == li.owned_trait {
- ~[ty::bound_owned]
- }
- else if d == li.copy_trait {
- ~[ty::bound_copy]
- }
- else if d == li.const_trait {
- ~[ty::bound_const]
- }
- else if d == li.durable_trait {
- ~[ty::bound_durable]
- }
- else {
- // Must be a user-defined trait
- ~[ty::bound_trait(ity)]
+ match b {
+ &TraitTyParamBound(b) => {
+ let li = &ccx.tcx.lang_items;
+ let ity = ast_ty_to_ty(ccx, empty_rscope, b);
+ match ty::get(ity).sty {
+ ty::ty_trait(did, _, _) => {
+ if did == li.owned_trait() {
+ ~[ty::bound_owned]
+ } else if did == li.copy_trait() {
+ ~[ty::bound_copy]
+ } else if did == li.const_trait() {
+ ~[ty::bound_const]
+ } else if did == li.durable_trait() {
+ ~[ty::bound_durable]
+ } else {
+ // Must be a user-defined trait
+ ~[ty::bound_trait(ity)]
+ }
+ }
+ _ => {
+ ccx.tcx.sess.span_err(
+ (*b).span, ~"type parameter bounds must be \
+ trait types");
+ ~[]
+ }
}
}
- _ => {
- ccx.tcx.sess.span_err(
- (*b).span, ~"type parameter bounds must be \
- trait types");
- ~[]
- }
+ &RegionTyParamBound => ~[ty::bound_durable]
}
}
}
fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
decl: ast::fn_decl,
purity: ast::purity,
- ty_params: ~[ast::ty_param],
+ +ty_params: ~[ast::ty_param],
def_id: ast::def_id) -> ty::ty_param_bounds_and_ty {
-
let bounds = ty_param_bounds(ccx, ty_params);
let rb = in_binding_rscope(empty_rscope);
let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, *a, None) );
onceness: ast::Many,
proto: ast::ProtoBare,
bounds: @~[],
- region: ty::re_static,
- ret_style: ast::return_val},
+ region: ty::re_static},
sig: FnSig {inputs: input_tys,
output: output_ty}
});
-> {bounds: @~[ty::param_bounds], params: ~[ty::t]} {
let mut i = 0u;
- let bounds = ty_param_bounds(ccx, atps);
+ // XXX: Bad copy.
+ let bounds = ty_param_bounds(ccx, copy atps);
{bounds: bounds,
params: vec::map(atps, |atp| {
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
})}
}
-fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param],
+fn mk_substs(ccx: @crate_ctxt,
+ +atps: ~[ast::ty_param],
rp: Option<ty::region_variance>)
- -> {bounds: @~[ty::param_bounds], substs: ty::substs} {
-
+ -> {bounds: @~[ty::param_bounds], substs: ty::substs} {
let {bounds, params} = mk_ty_params(ccx, atps);
let self_r = rscope::bound_self_region(rp);
{bounds: bounds, substs: {self_r: self_r, self_ty: None, tps: params}}
// A. But this upper-bound might be stricter than what is truly
// needed.
-use middle::typeck::infer::combine::combine_fields;
-use middle::typeck::infer::to_str::ToStr;
+use core::prelude::*;
-fn to_ares(+c: cres<ty::t>) -> ares {
+use middle::ty::TyVar;
+use middle::ty;
+use middle::typeck::infer::{ares, cres};
+use middle::typeck::infer::combine::CombineFields;
+use middle::typeck::infer::sub::Sub;
+use middle::typeck::infer::to_str::InferStr;
+use util::common::{indent, indenter};
+
+use core::option;
+use syntax::ast::{m_const, m_imm, m_mutbl};
+use syntax::ast;
+
+fn to_ares<T>(+c: cres<T>) -> ares {
match c {
Ok(_) => Ok(None),
Err(ref e) => Err((*e))
// Note: Assign is not actually a combiner, in that it does not
// conform to the same interface, though it performs a similar
// function.
-enum Assign = combine_fields;
+enum Assign = CombineFields;
impl Assign {
fn tys(a: ty::t, b: ty::t) -> ares {
- debug!("Assign.tys(%s -> %s)",
- a.to_str(self.infcx),
- b.to_str(self.infcx));
+ debug!("Assign.tys(%s => %s)",
+ a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
let _r = indenter();
- match (ty::get(a).sty, ty::get(b).sty) {
+ debug!("Assign.tys: copying first type");
+ let copy_a = copy ty::get(a).sty;
+ debug!("Assign.tys: copying second type");
+ let copy_b = copy ty::get(b).sty;
+ debug!("Assign.tys: performing match");
+
+ let r = match (copy_a, copy_b) {
(ty::ty_bot, _) => {
Ok(None)
}
(_, _) => {
self.assign_tys_or_sub(a, b, Some(a), Some(b))
}
- }
+ };
+
+ debug!("Assign.tys end");
+
+ move r
}
}
a: ty::t, b: ty::t,
+a_bnd: Option<ty::t>, +b_bnd: Option<ty::t>) -> ares {
- debug!("Assign.assign_tys_or_sub(%s -> %s, %s -> %s)",
- a.to_str(self.infcx), b.to_str(self.infcx),
- a_bnd.to_str(self.infcx), b_bnd.to_str(self.infcx));
+ debug!("Assign.assign_tys_or_sub(%s => %s, %s => %s)",
+ a.inf_str(self.infcx), b.inf_str(self.infcx),
+ a_bnd.inf_str(self.infcx), b_bnd.inf_str(self.infcx));
let _r = indenter();
fn is_borrowable(v: ty::vstore) -> bool {
match (a_bnd, b_bnd) {
(Some(a_bnd), Some(b_bnd)) => {
- match (ty::get(a_bnd).sty, ty::get(b_bnd).sty) {
+ match (/*bad*/copy ty::get(a_bnd).sty,
+ /*bad*/copy ty::get(b_bnd).sty) {
// check for a case where a non-region pointer (@, ~) is
// being assigned to a region pointer:
(ty::ty_box(_), ty::ty_rptr(r_b, mt_b)) => {
let nr_b = ty::mk_fn(self.infcx.tcx, ty::FnTyBase {
meta: ty::FnMeta {proto: a_f.meta.proto,
..b_f.meta},
- sig: b_f.sig
+ sig: copy b_f.sig
});
self.try_assign(0, ty::AutoBorrowFn,
a, nr_b, m_imm, b_f.meta.region)
}
+ (ty::ty_fn(ref a_f), ty::ty_fn(ref b_f))
+ if a_f.meta.proto == ast::ProtoBare => {
+ let b1_f = ty::FnTyBase {
+ meta: ty::FnMeta {proto: ast::ProtoBare,
+ ..b_f.meta},
+ sig: copy b_f.sig
+ };
+ // Eventually we will need to add some sort of
+ // adjustment here so that trans can add an
+ // extra NULL env pointer:
+ to_ares(Sub(*self).fns(a_f, &b1_f))
+ }
+
// check for &T being assigned to *T:
(ty::ty_rptr(_, ref a_t), ty::ty_ptr(ref b_t)) => {
- match Sub(*self).mts(*a_t, *b_t) {
- Ok(_) => Ok(None),
- Err(ref e) => Err((*e))
- }
+ to_ares(Sub(*self).mts(*a_t, *b_t))
}
// otherwise, assignment follows normal subtype rules:
r_b: ty::Region) -> ares {
debug!("try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)",
- a.to_str(self.infcx),
- nr_b.to_str(self.infcx),
+ a.inf_str(self.infcx),
+ nr_b.inf_str(self.infcx),
m,
- r_b.to_str(self.infcx));
+ r_b.inf_str(self.infcx));
do indent {
let sub = Sub(*self);
// terms of error reporting, although we do not do that properly right
// now.
-use middle::ty::{FnTyBase, FnMeta, FnSig};
-use middle::typeck::infer::to_str::ToStr;
-
-use syntax::ast::Onceness;
+use core::prelude::*;
+
+use middle::ty::{FloatVar, FnTyBase, FnMeta, FnSig, IntVar, TyVar};
+use middle::ty;
+use middle::typeck::infer::glb::Glb;
+use middle::typeck::infer::lub::Lub;
+use middle::typeck::infer::sub::Sub;
+use middle::typeck::infer::to_str::InferStr;
+use middle::typeck::infer::{cres, InferCtxt, ures, IntType, UintType};
+use util::common::indent;
+
+use core::result::{iter_vec2, map_vec2};
+use core::vec;
+use syntax::ast::{Onceness, purity, ret_style};
+use syntax::ast;
+use syntax::codemap::span;
fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export.
-trait combine {
- fn infcx() -> infer_ctxt;
+trait Combine {
+ fn infcx() -> @InferCtxt;
fn tag() -> ~str;
fn a_is_expected() -> bool;
+ fn span() -> span;
fn sub() -> Sub;
fn lub() -> Lub;
fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>;
fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto>;
- fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
fn purities(a: purity, b: purity) -> cres<purity>;
fn oncenesses(a: Onceness, b: Onceness) -> cres<Onceness>;
fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region>;
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore>;
}
-pub struct combine_fields {
- infcx: infer_ctxt,
+pub struct CombineFields {
+ infcx: @InferCtxt,
a_is_expected: bool,
span: span,
}
-fn expected_found<C: combine,T>(
+fn expected_found<C:Combine,T>(
self: &C, +a: T, +b: T) -> ty::expected_found<T> {
if self.a_is_expected() {
}
}
-pub fn eq_tys<C: combine>(self: &C, a: ty::t, b: ty::t) -> ures {
+pub fn eq_tys<C:Combine>(self: &C, a: ty::t, b: ty::t) -> ures {
let suber = self.sub();
do self.infcx().try {
do suber.tys(a, b).chain |_ok| {
}
}
-fn eq_regions<C: combine>(self: &C, a: ty::Region, b: ty::Region) -> ures {
+fn eq_regions<C:Combine>(self: &C, a: ty::Region, b: ty::Region) -> ures {
debug!("eq_regions(%s, %s)",
- a.to_str(self.infcx()),
- b.to_str(self.infcx()));
+ a.inf_str(self.infcx()),
+ b.inf_str(self.infcx()));
let sub = self.sub();
do indent {
self.infcx().try(|| {
}
}
-fn eq_opt_regions<C:combine>(
+fn eq_opt_regions<C:Combine>(
self: &C,
a: Option<ty::Region>,
b: Option<ty::Region>) -> cres<Option<ty::Region>> {
self.infcx().tcx.sess.bug(
fmt!("substitution a had opt_region %s and \
b had opt_region %s",
- a.to_str(self.infcx()),
- b.to_str(self.infcx())));
+ a.inf_str(self.infcx()),
+ b.inf_str(self.infcx())));
}
}
}
-fn super_substs<C:combine>(
+fn super_substs<C:Combine>(
self: &C, did: ast::def_id,
a: &ty::substs, b: &ty::substs) -> cres<ty::substs> {
- fn relate_region_param<C:combine>(
+ fn relate_region_param<C:Combine>(
self: &C,
did: ast::def_id,
a: Option<ty::Region>,
self.infcx().tcx.sess.bug(
fmt!("substitution a had opt_region %s and \
b had opt_region %s with variance %?",
- a.to_str(self.infcx()),
- b.to_str(self.infcx()),
+ a.inf_str(self.infcx()),
+ b.inf_str(self.infcx()),
polyty.region_param));
}
}
do relate_region_param(self, did,
a.self_r, b.self_r).chain |self_r|
{
- Ok({self_r: self_r, self_ty: self_ty, tps: tps})
+ Ok({self_r: self_r, self_ty: self_ty, tps: /*bad*/copy tps})
}
}
}
}
-fn super_tps<C:combine>(
+fn super_tps<C:Combine>(
self: &C, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
// Note: type parameters are always treated as *invariant*
}
}
-fn super_self_tys<C:combine>(
+fn super_self_tys<C:Combine>(
self: &C, a: Option<ty::t>, b: Option<ty::t>) -> cres<Option<ty::t>> {
// Note: the self type parameter is (currently) always treated as
}
}
-fn super_flds<C:combine>(
+fn super_protos<C: Combine>(
+ self: &C, p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto>
+{
+ if p1 == p2 {
+ Ok(p1)
+ } else {
+ Err(ty::terr_proto_mismatch(expected_found(self, p1, p2)))
+ }
+}
+
+fn super_flds<C:Combine>(
self: &C, a: ty::field, b: ty::field) -> cres<ty::field> {
if a.ident == b.ident {
}
}
-fn super_modes<C:combine>(
+fn super_modes<C:Combine>(
self: &C, a: ast::mode, b: ast::mode)
-> cres<ast::mode> {
ty::unify_mode(tcx, expected_found(self, a, b))
}
-fn super_args<C:combine>(
+fn super_args<C:Combine>(
self: &C, a: ty::arg, b: ty::arg)
-> cres<ty::arg> {
}
}
-fn super_vstores<C:combine>(
+fn super_vstores<C:Combine>(
self: &C, vk: ty::terr_vstore_kind,
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore>
{
}
}
-fn super_fn_metas<C:combine>(
+fn super_fn_metas<C:Combine>(
self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres<ty::FnMeta>
{
let p = if_ok!(self.protos(a_f.proto, b_f.proto));
let r = if_ok!(self.contraregions(a_f.region, b_f.region));
- let rs = if_ok!(self.ret_styles(a_f.ret_style, b_f.ret_style));
let purity = if_ok!(self.purities(a_f.purity, b_f.purity));
let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness));
Ok(FnMeta {purity: purity,
proto: p,
- region: r,
onceness: onceness,
- bounds: a_f.bounds, // XXX: This is wrong!
- ret_style: rs})
+ region: r,
+ bounds: a_f.bounds}) // XXX: This is wrong!
}
-fn super_fn_sigs<C:combine>(
+fn super_fn_sigs<C:Combine>(
self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig>
{
- fn argvecs<C:combine>(self: &C, a_args: ~[ty::arg],
- b_args: ~[ty::arg]) -> cres<~[ty::arg]> {
-
+ fn argvecs<C:Combine>(self: &C,
+ +a_args: ~[ty::arg],
+ +b_args: ~[ty::arg]) -> cres<~[ty::arg]>
+ {
if vec::same_length(a_args, b_args) {
map_vec2(a_args, b_args, |a, b| self.args(*a, *b))
} else {
}
}
- do argvecs(self, a_f.inputs, b_f.inputs).chain |inputs| {
+ do argvecs(self, /*bad*/copy a_f.inputs, /*bad*/copy b_f.inputs)
+ .chain |inputs| {
do self.tys(a_f.output, b_f.output).chain |output| {
- Ok(FnSig {inputs: inputs, output: output})
+ Ok(FnSig {inputs: /*bad*/copy inputs, output: output})
}
}
}
-fn super_fns<C:combine>(
+fn super_fns<C:Combine>(
self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres<ty::FnTy>
{
- do self.fn_metas(&a_f.meta, &b_f.meta).chain |m| {
- do self.fn_sigs(&a_f.sig, &b_f.sig).chain |s| {
- Ok(FnTyBase {meta: m, sig: s})
- }
- }
+ let m = if_ok!(self.fn_metas(&a_f.meta, &b_f.meta));
+ let s = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig));
+ Ok(FnTyBase {meta: m, sig: s})
}
-fn super_tys<C:combine>(
- self: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
-
+fn super_tys<C:Combine>(
+ self: &C, a: ty::t, b: ty::t) -> cres<ty::t>
+{
let tcx = self.infcx().tcx;
- match (ty::get(a).sty, ty::get(b).sty) {
+ match (/*bad*/copy ty::get(a).sty, /*bad*/copy ty::get(b).sty) {
// The "subtype" ought to be handling cases involving bot or var:
(ty::ty_bot, _) |
(_, ty::ty_bot) |
tcx.sess.bug(
fmt!("%s: bot and var types should have been handled (%s,%s)",
self.tag(),
- a.to_str(self.infcx()),
- b.to_str(self.infcx())));
+ a.inf_str(self.infcx()),
+ b.inf_str(self.infcx())));
}
// Relate integral variables to other types
(ty::ty_infer(IntVar(a_id)), ty::ty_infer(IntVar(b_id))) => {
- self.infcx().int_vars(a_id, b_id).then(|| Ok(a) )
+ if_ok!(self.infcx().simple_vars(&self.infcx().int_var_bindings,
+ ty::terr_no_integral_type,
+ a_id, b_id));
+ Ok(a)
}
- (ty::ty_infer(IntVar(a_id)), ty::ty_int(_)) |
- (ty::ty_infer(IntVar(a_id)), ty::ty_uint(_)) => {
- self.infcx().int_var_sub_t(a_id, b).then(|| Ok(a) )
+ (ty::ty_infer(IntVar(v_id)), ty::ty_int(v)) |
+ (ty::ty_int(v), ty::ty_infer(IntVar(v_id))) => {
+ if v == ast::ty_char {
+ Err(ty::terr_integer_as_char)
+ } else {
+ if_ok!(self.infcx().simple_var_t(&self.infcx().int_var_bindings,
+ ty::terr_no_integral_type,
+ v_id, IntType(v)));
+ Ok(ty::mk_mach_int(tcx, v))
+ }
}
- (ty::ty_int(_), ty::ty_infer(IntVar(b_id))) |
- (ty::ty_uint(_), ty::ty_infer(IntVar(b_id))) => {
- self.infcx().t_sub_int_var(a, b_id).then(|| Ok(a) )
+ (ty::ty_infer(IntVar(v_id)), ty::ty_uint(v)) |
+ (ty::ty_uint(v), ty::ty_infer(IntVar(v_id))) => {
+ if_ok!(self.infcx().simple_var_t(&self.infcx().int_var_bindings,
+ ty::terr_no_integral_type,
+ v_id, UintType(v)));
+ Ok(ty::mk_mach_uint(tcx, v))
}
// Relate floating-point variables to other types
(ty::ty_infer(FloatVar(a_id)), ty::ty_infer(FloatVar(b_id))) => {
- self.infcx().float_vars(a_id, b_id).then(|| Ok(a) )
- }
- (ty::ty_infer(FloatVar(a_id)), ty::ty_float(_)) => {
- self.infcx().float_var_sub_t(a_id, b).then(|| Ok(a) )
+ if_ok!(self.infcx().simple_vars(&self.infcx().float_var_bindings,
+ ty::terr_no_floating_point_type,
+ a_id, b_id));
+ Ok(a)
}
- (ty::ty_float(_), ty::ty_infer(FloatVar(b_id))) => {
- self.infcx().t_sub_float_var(a, b_id).then(|| Ok(a) )
+ (ty::ty_infer(FloatVar(v_id)), ty::ty_float(v)) |
+ (ty::ty_float(v), ty::ty_infer(FloatVar(v_id))) => {
+ if_ok!(self.infcx().simple_var_t(&self.infcx().float_var_bindings,
+ ty::terr_no_floating_point_type,
+ v_id, v));
+ Ok(ty::mk_mach_float(tcx, v))
}
(ty::ty_int(_), _) |
(ty::ty_uint(_), _) |
(ty::ty_float(_), _) => {
- let as_ = ty::get(a).sty;
- let bs = ty::get(b).sty;
+ let as_ = /*bad*/copy ty::get(a).sty;
+ let bs = /*bad*/copy ty::get(b).sty;
if as_ == bs {
Ok(a)
} else {
if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| {
do self.vstores(ty::terr_trait, a_vstore, b_vstore).chain |vs| {
- Ok(ty::mk_trait(tcx, a_id, substs, vs))
+ Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, vs))
}
}
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Code related to floating-point type inference.
-
-*/
-
-use middle::ty::ty_float;
-use middle::typeck::infer::to_str::ToStr;
-
-// Bitvector to represent sets of floating-point types.
-pub enum float_ty_set = uint;
-
-// Constants representing singleton sets containing each of the floating-point
-// types.
-pub const FLOAT_TY_SET_EMPTY: uint = 0b000u;
-pub const FLOAT_TY_SET_FLOAT: uint = 0b001u;
-pub const FLOAT_TY_SET_F32: uint = 0b010u;
-pub const FLOAT_TY_SET_F64: uint = 0b100u;
-
-pub fn float_ty_set_all() -> float_ty_set {
- float_ty_set(FLOAT_TY_SET_FLOAT | FLOAT_TY_SET_F32 | FLOAT_TY_SET_F64)
-}
-
-pub fn intersection(a: float_ty_set, b: float_ty_set) -> float_ty_set {
- float_ty_set(*a & *b)
-}
-
-pub fn single_type_contained_in(tcx: ty::ctxt, a: float_ty_set)
- -> Option<ty::t> {
- debug!("single_type_contained_in(a=%s)", uint::to_str(*a, 10));
-
- if *a == FLOAT_TY_SET_FLOAT { return Some(ty::mk_float(tcx)); }
- if *a == FLOAT_TY_SET_F32 { return Some(ty::mk_f32(tcx)); }
- if *a == FLOAT_TY_SET_F64 { return Some(ty::mk_f64(tcx)); }
- return None;
-}
-
-pub fn convert_floating_point_ty_to_float_ty_set(tcx: ty::ctxt, t: ty::t)
- -> float_ty_set {
- match get(t).sty {
- ty::ty_float(ast::ty_f) => float_ty_set(FLOAT_TY_SET_FLOAT),
- ty::ty_float(ast::ty_f32) => float_ty_set(FLOAT_TY_SET_F32),
- ty::ty_float(ast::ty_f64) => float_ty_set(FLOAT_TY_SET_F64),
- _ => tcx.sess.bug(~"non-floating-point type passed to \
- convert_floating_point_ty_to_float_ty_set()")
- }
-}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::ty::RegionVid;
+use middle::ty;
use middle::typeck::infer::combine::*;
+use middle::typeck::infer::glb::Glb;
use middle::typeck::infer::lattice::*;
-use middle::typeck::infer::to_str::ToStr;
+use middle::typeck::infer::lub::Lub;
+use middle::typeck::infer::sub::Sub;
+use middle::typeck::infer::to_str::InferStr;
+use middle::typeck::isr_alist;
+use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl};
+use syntax::ast::{noreturn, pure_fn, ret_style, return_val, unsafe_fn};
+use util::ppaux::mt_to_str;
-use syntax::ast::{Many, Once};
+use std::list;
-enum Glb = combine_fields; // "greatest lower bound" (common subtype)
+enum Glb = CombineFields; // "greatest lower bound" (common subtype)
-impl Glb: combine {
- fn infcx() -> infer_ctxt { self.infcx }
+impl Glb: Combine {
+ fn infcx() -> @InferCtxt { self.infcx }
fn tag() -> ~str { ~"glb" }
fn a_is_expected() -> bool { self.a_is_expected }
+ fn span() -> span { self.span }
fn sub() -> Sub { Sub(*self) }
fn lub() -> Lub { Lub(*self) }
Lub(*self).tys(a, b)
}
- fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
- if p1 == p2 {Ok(p1)} else {Ok(ast::ProtoBare)}
- }
-
fn purities(a: purity, b: purity) -> cres<purity> {
match (a, b) {
(pure_fn, _) | (_, pure_fn) => Ok(pure_fn),
}
}
- fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
- match (r1, r2) {
- (ast::return_val, ast::return_val) => {
- Ok(ast::return_val)
- }
- (ast::noreturn, _) |
- (_, ast::noreturn) => {
- Ok(ast::noreturn)
- }
- }
- }
-
fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
debug!("%s.regions(%?, %?)",
self.tag(),
- a.to_str(self.infcx),
- b.to_str(self.infcx));
+ a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
do indent {
self.infcx.region_vars.glb_regions(self.span, a, b)
}
fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
- lattice_tys(&self, a, b)
+ super_lattice_tys(&self, a, b)
}
// Traits please (FIXME: #2794):
super_args(&self, a, b)
}
+ fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
+ // Note: this is a subtle algorithm. For a full explanation,
+ // please see the large comment in `region_inference.rs`.
+
+ debug!("%s.fn_sigs(%?, %?)",
+ self.tag(), a.inf_str(self.infcx), b.inf_str(self.infcx));
+ let _indenter = indenter();
+
+ // Take a snapshot. We'll never roll this back, but in later
+ // phases we do want to be able to examine "all bindings that
+ // were created as part of this type comparison", and making a
+ // snapshot is a convenient way to do that.
+ let snapshot = self.infcx.region_vars.start_snapshot();
+
+ // Instantiate each bound region with a fresh region variable.
+ let (a_with_fresh, a_isr) =
+ self.infcx.replace_bound_regions_with_fresh_regions(
+ self.span, a);
+ let a_vars = var_ids(&self, a_isr);
+ let (b_with_fresh, b_isr) =
+ self.infcx.replace_bound_regions_with_fresh_regions(
+ self.span, b);
+ let b_vars = var_ids(&self, b_isr);
+
+ // Collect constraints.
+ let sig0 = if_ok!(super_fn_sigs(&self, &a_with_fresh, &b_with_fresh));
+ debug!("sig0 = %s", sig0.inf_str(self.infcx));
+
+ // Generalize the regions appearing in fn_ty0 if possible
+ let new_vars =
+ self.infcx.region_vars.vars_created_since_snapshot(snapshot);
+ let sig1 =
+ self.infcx.fold_regions_in_sig(
+ &sig0,
+ |r, _in_fn| generalize_region(&self, snapshot,
+ new_vars, a_isr, a_vars, b_vars,
+ r));
+ debug!("sig1 = %s", sig1.inf_str(self.infcx));
+ return Ok(move sig1);
+
+ fn generalize_region(self: &Glb,
+ snapshot: uint,
+ new_vars: &[RegionVid],
+ a_isr: isr_alist,
+ a_vars: &[RegionVid],
+ b_vars: &[RegionVid],
+ r0: ty::Region) -> ty::Region {
+ if !is_var_in_set(new_vars, r0) {
+ return r0;
+ }
+
+ let tainted = self.infcx.region_vars.tainted(snapshot, r0);
+
+ let mut a_r = None, b_r = None, only_new_vars = true;
+ for tainted.each |r| {
+ if is_var_in_set(a_vars, *r) {
+ if a_r.is_some() {
+ return fresh_bound_variable(self);
+ } else {
+ a_r = Some(*r);
+ }
+ } else if is_var_in_set(b_vars, *r) {
+ if b_r.is_some() {
+ return fresh_bound_variable(self);
+ } else {
+ b_r = Some(*r);
+ }
+ } else if !is_var_in_set(new_vars, *r) {
+ only_new_vars = false;
+ }
+ }
+
+ // NB---I do not believe this algorithm computes
+ // (necessarily) the GLB. As written it can
+ // spuriously fail. In particular, if there is a case
+ // like: fn(fn(&a)) and fn(fn(&b)), where a and b are
+ // free, it will return fn(&c) where c = GLB(a,b). If
+ // however this GLB is not defined, then the result is
+ // an error, even though something like
+ // "fn<X>(fn(&X))" where X is bound would be a
+ // subtype of both of those.
+ //
+ // The problem is that if we were to return a bound
+ // variable, we'd be computing a lower-bound, but not
+ // necessarily the *greatest* lower-bound.
+
+ if a_r.is_some() && b_r.is_some() && only_new_vars {
+ // Related to exactly one bound variable from each fn:
+ return rev_lookup(self, a_isr, a_r.get());
+ } else if a_r.is_none() && b_r.is_none() {
+ // Not related to bound variables from either fn:
+ return r0;
+ } else {
+ // Other:
+ return fresh_bound_variable(self);
+ }
+ }
+
+ fn rev_lookup(self: &Glb,
+ a_isr: isr_alist,
+ r: ty::Region) -> ty::Region
+ {
+ for list::each(a_isr) |pair| {
+ let (a_br, a_r) = *pair;
+ if a_r == r {
+ return ty::re_bound(a_br);
+ }
+ }
+
+ self.infcx.tcx.sess.span_bug(
+ self.span,
+ fmt!("could not find original bound region for %?", r));
+ }
+
+ fn fresh_bound_variable(self: &Glb) -> ty::Region {
+ self.infcx.region_vars.new_bound()
+ }
+ }
+
+ fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
+ super_protos(&self, p1, p2)
+ }
+
fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
super_fns(&self, a, b)
}
super_fn_metas(&self, a, b)
}
- fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
- super_fn_sigs(&self, a, b)
- }
-
fn substs(did: ast::def_id,
as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> {
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Code related to integral type inference.
-
-*/
-
-use middle::typeck::infer::to_str::ToStr;
-
-// Bitvector to represent sets of integral types
-enum int_ty_set = uint;
-
-// Constants representing singleton sets containing each of the
-// integral types
-const INT_TY_SET_EMPTY : uint = 0b00_0000_0000u;
-const INT_TY_SET_i8 : uint = 0b00_0000_0001u;
-const INT_TY_SET_u8 : uint = 0b00_0000_0010u;
-const INT_TY_SET_i16 : uint = 0b00_0000_0100u;
-const INT_TY_SET_u16 : uint = 0b00_0000_1000u;
-const INT_TY_SET_i32 : uint = 0b00_0001_0000u;
-const INT_TY_SET_u32 : uint = 0b00_0010_0000u;
-const INT_TY_SET_i64 : uint = 0b00_0100_0000u;
-const INT_TY_SET_u64 : uint = 0b00_1000_0000u;
-const INT_TY_SET_i : uint = 0b01_0000_0000u;
-const INT_TY_SET_u : uint = 0b10_0000_0000u;
-
-fn int_ty_set_all() -> int_ty_set {
- int_ty_set(INT_TY_SET_i8 | INT_TY_SET_u8 |
- INT_TY_SET_i16 | INT_TY_SET_u16 |
- INT_TY_SET_i32 | INT_TY_SET_u32 |
- INT_TY_SET_i64 | INT_TY_SET_u64 |
- INT_TY_SET_i | INT_TY_SET_u)
-}
-
-fn intersection(a: int_ty_set, b: int_ty_set) -> int_ty_set {
- int_ty_set(*a & *b)
-}
-
-fn single_type_contained_in(tcx: ty::ctxt, a: int_ty_set) ->
- Option<ty::t> {
- debug!("single_type_contained_in(a=%s)", uint::to_str(*a, 10u));
-
- if *a == INT_TY_SET_i8 { return Some(ty::mk_i8(tcx)); }
- if *a == INT_TY_SET_u8 { return Some(ty::mk_u8(tcx)); }
- if *a == INT_TY_SET_i16 { return Some(ty::mk_i16(tcx)); }
- if *a == INT_TY_SET_u16 { return Some(ty::mk_u16(tcx)); }
- if *a == INT_TY_SET_i32 { return Some(ty::mk_i32(tcx)); }
- if *a == INT_TY_SET_u32 { return Some(ty::mk_u32(tcx)); }
- if *a == INT_TY_SET_i64 { return Some(ty::mk_i64(tcx)); }
- if *a == INT_TY_SET_u64 { return Some(ty::mk_u64(tcx)); }
- if *a == INT_TY_SET_i { return Some(ty::mk_int(tcx)); }
- if *a == INT_TY_SET_u { return Some(ty::mk_uint(tcx)); }
- return None;
-}
-
-fn convert_integral_ty_to_int_ty_set(tcx: ty::ctxt, t: ty::t)
- -> int_ty_set {
-
- match get(t).sty {
- ty_int(int_ty) => match int_ty {
- ast::ty_i8 => int_ty_set(INT_TY_SET_i8),
- ast::ty_i16 => int_ty_set(INT_TY_SET_i16),
- ast::ty_i32 => int_ty_set(INT_TY_SET_i32),
- ast::ty_i64 => int_ty_set(INT_TY_SET_i64),
- ast::ty_i => int_ty_set(INT_TY_SET_i),
- ast::ty_char => tcx.sess.bug(
- ~"char type passed to convert_integral_ty_to_int_ty_set()")
- },
- ty_uint(uint_ty) => match uint_ty {
- ast::ty_u8 => int_ty_set(INT_TY_SET_u8),
- ast::ty_u16 => int_ty_set(INT_TY_SET_u16),
- ast::ty_u32 => int_ty_set(INT_TY_SET_u32),
- ast::ty_u64 => int_ty_set(INT_TY_SET_u64),
- ast::ty_u => int_ty_set(INT_TY_SET_u)
- },
- _ => tcx.sess.bug(~"non-integral type passed to \
- convert_integral_ty_to_int_ty_set()")
- }
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+/*!
+ *
+ * # Lattice Variables
+ *
+ * This file contains generic code for operating on inference variables
+ * that are characterized by an upper- and lower-bound. The logic and
+ * reasoning is explained in detail in the large comment in `infer.rs`.
+ *
+ * The code in here is defined quite generically so that it can be
+ * applied both to type variables, which represent types being inferred,
+ * and fn variables, which represent function types being inferred.
+ * It may eventually be applied to ther types as well, who knows.
+ * In some cases, the functions are also generic with respect to the
+ * operation on the lattice (GLB vs LUB).
+ *
+ * Although all the functions are generic, we generally write the
+ * comments in a way that is specific to type variables and the LUB
+ * operation. It's just easier that way.
+ *
+ * In general all of the functions are defined parametrically
+ * over a `LatticeValue`, which is a value defined with respect to
+ * a lattice.
+ */
+
+use core::prelude::*;
+
+use middle::ty::{RegionVid, TyVar};
+use middle::ty;
+use middle::typeck::isr_alist;
+use middle::typeck::infer::*;
use middle::typeck::infer::combine::*;
+use middle::typeck::infer::glb::Glb;
+use middle::typeck::infer::lub::Lub;
use middle::typeck::infer::unify::*;
-use middle::typeck::infer::to_str::ToStr;
+use middle::typeck::infer::sub::Sub;
+use middle::typeck::infer::lub::Lub;
+use middle::typeck::infer::glb::Glb;
+use middle::typeck::infer::to_str::InferStr;
+
+use std::list;
+
+trait LatticeValue {
+ static fn sub(cf: &CombineFields, a: &self, b: &self) -> ures;
+ static fn lub(cf: &CombineFields, a: &self, b: &self) -> cres<self>;
+ static fn glb(cf: &CombineFields, a: &self, b: &self) -> cres<self>;
+}
+
+type LatticeOp<T> = &fn(cf: &CombineFields, a: &T, b: &T) -> cres<T>;
+
+impl ty::t: LatticeValue {
+ static fn sub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> ures {
+ Sub(*cf).tys(*a, *b).to_ures()
+ }
+
+ static fn lub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
+ Lub(*cf).tys(*a, *b)
+ }
+
+ static fn glb(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
+ Glb(*cf).tys(*a, *b)
+ }
+}
+
+impl FnMeta: LatticeValue {
+ static fn sub(cf: &CombineFields,
+ a: &FnMeta, b: &FnMeta) -> ures {
+ Sub(*cf).fn_metas(a, b).to_ures()
+ }
+
+ static fn lub(cf: &CombineFields,
+ a: &FnMeta, b: &FnMeta) -> cres<FnMeta> {
+ Lub(*cf).fn_metas(a, b)
+ }
+
+ static fn glb(cf: &CombineFields,
+ a: &FnMeta, b: &FnMeta) -> cres<FnMeta> {
+ Glb(*cf).fn_metas(a, b)
+ }
+}
+
+impl CombineFields {
+ fn var_sub_var<V:Copy Eq Vid ToStr, T:Copy InferStr LatticeValue>(
+ &self,
+ vb: &ValsAndBindings<V, Bounds<T>>,
+ +a_id: V,
+ +b_id: V) -> ures
+ {
+ /*!
+ *
+ * Make one variable a subtype of another variable. This is a
+ * subtle and tricky process, as described in detail at the
+ * top of infer.rs*/
+
+ // Need to make sub_id a subtype of sup_id.
+ let node_a = self.infcx.get(vb, a_id);
+ let node_b = self.infcx.get(vb, b_id);
+ let a_id = node_a.root;
+ let b_id = node_b.root;
+ let a_bounds = node_a.possible_types;
+ let b_bounds = node_b.possible_types;
+
+ debug!("vars(%s=%s <: %s=%s)",
+ a_id.to_str(), a_bounds.inf_str(self.infcx),
+ b_id.to_str(), b_bounds.inf_str(self.infcx));
+
+ if a_id == b_id { return uok(); }
+
+ // If both A's UB and B's LB have already been bound to types,
+ // see if we can make those types subtypes.
+ match (a_bounds.ub, b_bounds.lb) {
+ (Some(ref a_ub), Some(ref b_lb)) => {
+ let r = self.infcx.try(
+ || LatticeValue::sub(self, a_ub, b_lb));
+ match r {
+ Ok(()) => {
+ return Ok(());
+ }
+ Err(_) => { /*fallthrough */ }
+ }
+ }
+ _ => { /*fallthrough*/ }
+ }
+
+ // Otherwise, we need to merge A and B so as to guarantee that
+ // A remains a subtype of B. Actually, there are other options,
+ // but that's the route we choose to take.
+
+ self.infcx.unify(vb, &node_a, &node_b, |new_root, new_rank| {
+ self.set_var_to_merged_bounds(vb, new_root,
+ &a_bounds, &b_bounds,
+ new_rank)
+ })
+ }
+
+ /// make variable a subtype of T
+ fn var_sub_t<V:Copy Eq Vid ToStr, T:Copy InferStr LatticeValue>(
+ &self,
+ vb: &ValsAndBindings<V, Bounds<T>>,
+ +a_id: V,
+ +b: T) -> ures
+ {
+ /*!
+ *
+ * Make a variable (`a_id`) a subtype of the concrete type `b` */
+
+ let node_a = self.infcx.get(vb, a_id);
+ let a_id = node_a.root;
+ let a_bounds = &node_a.possible_types;
+ let b_bounds = &{lb: None, ub: Some(b)};
+
+ debug!("var_sub_t(%s=%s <: %s)",
+ a_id.to_str(),
+ a_bounds.inf_str(self.infcx),
+ b.inf_str(self.infcx));
+
+ self.set_var_to_merged_bounds(
+ vb, a_id, a_bounds, b_bounds, node_a.rank)
+ }
+
+ fn t_sub_var<V:Copy Eq Vid ToStr, T:Copy InferStr LatticeValue>(
+ &self,
+ vb: &ValsAndBindings<V, Bounds<T>>,
+ +a: T,
+ +b_id: V) -> ures
+ {
+ /*!
+ *
+ * Make a concrete type (`a`) a subtype of the variable `b_id` */
+
+ let a_bounds = &{lb: Some(a), ub: None};
+ let node_b = self.infcx.get(vb, b_id);
+ let b_id = node_b.root;
+ let b_bounds = &node_b.possible_types;
+
+ debug!("t_sub_var(%s <: %s=%s)",
+ a.inf_str(self.infcx),
+ b_id.to_str(),
+ b_bounds.inf_str(self.infcx));
+
+ self.set_var_to_merged_bounds(
+ vb, b_id, a_bounds, b_bounds, node_b.rank)
+ }
+
+ fn merge_bnd<T:Copy InferStr LatticeValue>(
+ &self,
+ a: &Bound<T>,
+ b: &Bound<T>,
+ lattice_op: LatticeOp<T>)
+ -> cres<Bound<T>>
+ {
+ /*!
+ *
+ * Combines two bounds into a more general bound. */
+
+ debug!("merge_bnd(%s,%s)",
+ a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
+ let _r = indenter();
+
+ match (*a, *b) {
+ (None, None) => Ok(None),
+ (Some(_), None) => Ok(*a),
+ (None, Some(_)) => Ok(*b),
+ (Some(ref v_a), Some(ref v_b)) => {
+ do lattice_op(self, v_a, v_b).chain |v| {
+ Ok(Some(v))
+ }
+ }
+ }
+ }
+
+ fn set_var_to_merged_bounds<V:Copy Eq Vid ToStr,
+ T:Copy InferStr LatticeValue>(
+ &self,
+ vb: &ValsAndBindings<V, Bounds<T>>,
+ +v_id: V,
+ a: &Bounds<T>,
+ b: &Bounds<T>,
+ rank: uint) -> ures
+ {
+ /*!
+ *
+ * Updates the bounds for the variable `v_id` to be the intersection
+ * of `a` and `b`. That is, the new bounds for `v_id` will be
+ * a bounds c such that:
+ * c.ub <: a.ub
+ * c.ub <: b.ub
+ * a.lb <: c.lb
+ * b.lb <: c.lb
+ * If this cannot be achieved, the result is failure. */
+
+ // Think of the two diamonds, we want to find the
+ // intersection. There are basically four possibilities (you
+ // can swap A/B in these pictures):
+ //
+ // A A
+ // / \ / \
+ // / B \ / B \
+ // / / \ \ / / \ \
+ // * * * * * / * *
+ // \ \ / / \ / /
+ // \ B / / \ / /
+ // \ / * \ /
+ // A \ / A
+ // B
+
+ debug!("merge(%s,%s,%s)",
+ v_id.to_str(),
+ a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
+ let _indent = indenter();
+
+ // First, relate the lower/upper bounds of A and B.
+ // Note that these relations *must* hold for us to
+ // to be able to merge A and B at all, and relating
+ // them explicitly gives the type inferencer more
+ // information and helps to produce tighter bounds
+ // when necessary.
+ let () = if_ok!(self.bnds(&a.lb, &b.ub));
+ let () = if_ok!(self.bnds(&b.lb, &a.ub));
+ let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb));
+ let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub));
+ let bounds = {lb: lb, ub: ub};
+ debug!("merge(%s): bounds=%s",
+ v_id.to_str(),
+ bounds.inf_str(self.infcx));
+
+ // the new bounds must themselves
+ // be relatable:
+ let () = if_ok!(self.bnds(&bounds.lb, &bounds.ub));
+ self.infcx.set(vb, v_id, Root(bounds, rank));
+ uok()
+ }
+
+ fn bnds<T:Copy InferStr LatticeValue>(
+ &self,
+ a: &Bound<T>,
+ b: &Bound<T>) -> ures
+ {
+ debug!("bnds(%s <: %s)", a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
+ let _r = indenter();
+
+ match (*a, *b) {
+ (None, None) |
+ (Some(_), None) |
+ (None, Some(_)) => {
+ uok()
+ }
+ (Some(ref t_a), Some(ref t_b)) => {
+ LatticeValue::sub(self, t_a, t_b)
+ }
+ }
+ }
+}
// ______________________________________________________________________
// Lattice operations on variables
// This is common code used by both LUB and GLB to compute the LUB/GLB
// for pairs of variables or for variables and values.
-trait lattice_ops {
- fn bnd(b: bounds<ty::t>) -> Option<ty::t>;
- fn with_bnd(b: bounds<ty::t>, t: ty::t) -> bounds<ty::t>;
+trait LatticeDir {
+ fn combine_fields() -> CombineFields;
+ fn bnd<T:Copy>(b: &Bounds<T>) -> Option<T>;
+ fn with_bnd<T:Copy>(b: &Bounds<T>, +t: T) -> Bounds<T>;
+}
+
+trait TyLatticeDir {
fn ty_bot(t: ty::t) -> cres<ty::t>;
}
-impl Lub: lattice_ops {
- fn bnd(b: bounds<ty::t>) -> Option<ty::t> { b.ub }
- fn with_bnd(b: bounds<ty::t>, t: ty::t) -> bounds<ty::t> {
- {ub: Some(t),.. b}
+impl Lub: LatticeDir {
+ fn combine_fields() -> CombineFields { *self }
+ fn bnd<T:Copy>(b: &Bounds<T>) -> Option<T> { b.ub }
+ fn with_bnd<T:Copy>(b: &Bounds<T>, +t: T) -> Bounds<T> {
+ {ub: Some(t), ..*b}
}
+}
+
+impl Lub: TyLatticeDir {
fn ty_bot(t: ty::t) -> cres<ty::t> {
Ok(t)
}
}
-impl Glb: lattice_ops {
- fn bnd(b: bounds<ty::t>) -> Option<ty::t> { b.lb }
- fn with_bnd(b: bounds<ty::t>, t: ty::t) -> bounds<ty::t> {
- {lb: Some(t),.. b}
+impl Glb: LatticeDir {
+ fn combine_fields() -> CombineFields { *self }
+ fn bnd<T:Copy>(b: &Bounds<T>) -> Option<T> { b.lb }
+ fn with_bnd<T:Copy>(b: &Bounds<T>, +t: T) -> Bounds<T> {
+ {lb: Some(t), ..*b}
}
+}
+
+impl Glb: TyLatticeDir {
fn ty_bot(_t: ty::t) -> cres<ty::t> {
Ok(ty::mk_bot(self.infcx.tcx))
}
}
-fn lattice_tys<L:lattice_ops combine>(
- self: &L, a: ty::t, b: ty::t) -> cres<ty::t> {
-
+fn super_lattice_tys<L:LatticeDir TyLatticeDir Combine>(
+ self: &L,
+ a: ty::t,
+ b: ty::t) -> cres<ty::t>
+{
debug!("%s.lattice_tys(%s, %s)", self.tag(),
- a.to_str(self.infcx()),
- b.to_str(self.infcx()));
- if a == b { return Ok(a); }
- do indent {
- match (ty::get(a).sty, ty::get(b).sty) {
- (ty::ty_bot, _) => self.ty_bot(b),
- (_, ty::ty_bot) => self.ty_bot(a),
-
- (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => {
- lattice_vars(self, a, a_id, b_id,
- |x, y| self.tys(x, y) )
- }
-
- (ty::ty_infer(TyVar(a_id)), _) => {
- lattice_var_and_t(self, a_id, b,
- |x, y| self.tys(x, y) )
- }
-
- (_, ty::ty_infer(TyVar(b_id))) => {
- lattice_var_and_t(self, b_id, a,
- |x, y| self.tys(x, y) )
- }
- _ => {
- super_tys(self, a, b)
- }
+ a.inf_str(self.infcx()),
+ b.inf_str(self.infcx()));
+ let _r = indenter();
+
+ if a == b {
+ return Ok(a);
+ }
+
+ let tcx = self.infcx().tcx;
+
+ match (ty::get(a).sty, ty::get(b).sty) {
+ (ty::ty_bot, _) => { return self.ty_bot(b); }
+ (_, ty::ty_bot) => { return self.ty_bot(a); }
+
+ (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => {
+ let r = if_ok!(lattice_vars(self, &self.infcx().ty_var_bindings,
+ a_id, b_id,
+ |x, y| self.tys(*x, *y)));
+ return match r {
+ VarResult(v) => Ok(ty::mk_var(tcx, v)),
+ ValueResult(t) => Ok(t)
+ };
+ }
+
+ (ty::ty_infer(TyVar(a_id)), _) => {
+ return lattice_var_and_t(self, &self.infcx().ty_var_bindings,
+ a_id, &b,
+ |x, y| self.tys(*x, *y));
+ }
+
+ (_, ty::ty_infer(TyVar(b_id))) => {
+ return lattice_var_and_t(self, &self.infcx().ty_var_bindings,
+ b_id, &a,
+ |x, y| self.tys(*x, *y));
+ }
+
+ _ => {
+ return super_tys(self, a, b);
}
}
}
-fn lattice_vars<L:lattice_ops combine>(
- self: &L, +a_t: ty::t, +a_vid: ty::TyVid, +b_vid: ty::TyVid,
- c_ts: fn(ty::t, ty::t) -> cres<ty::t>) -> cres<ty::t> {
+type LatticeDirOp<T> = &fn(a: &T, b: &T) -> cres<T>;
- // The comments in this function are written for LUB and types,
- // but they apply equally well to GLB and regions if you inverse
- // upper/lower/sub/super/etc.
+enum LatticeVarResult<V,T> {
+ VarResult(V),
+ ValueResult(T)
+}
- // Need to find a type that is a supertype of both a and b:
- let vb = &self.infcx().ty_var_bindings;
+/**
+ * Computes the LUB or GLB of two bounded variables. These could be any
+ * sort of variables, but in the comments on this function I'll assume
+ * we are doing an LUB on two type variables.
+ *
+ * This computation can be done in one of two ways:
+ *
+ * - If both variables have an upper bound, we may just compute the
+ * LUB of those bounds and return that, in which case we are
+ * returning a type. This is indicated with a `ValueResult` return.
+ *
+ * - If the variables do not both have an upper bound, we will unify
+ * the variables and return the unified variable, in which case the
+ * result is a variable. This is indicated with a `VarResult`
+ * return. */
+fn lattice_vars<L:LatticeDir Combine,
+ V:Copy Eq Vid ToStr,
+ T:Copy InferStr LatticeValue>(
+ self: &L, // defines whether we want LUB or GLB
+ vb: &ValsAndBindings<V, Bounds<T>>, // relevant variable bindings
+ +a_vid: V, // first variable
+ +b_vid: V, // second variable
+ lattice_dir_op: LatticeDirOp<T>) // LUB or GLB operation on types
+ -> cres<LatticeVarResult<V,T>>
+{
let nde_a = self.infcx().get(vb, a_vid);
let nde_b = self.infcx().get(vb, b_vid);
let a_vid = nde_a.root;
let b_vid = nde_b.root;
- let a_bounds = nde_a.possible_types;
- let b_bounds = nde_b.possible_types;
+ let a_bounds = &nde_a.possible_types;
+ let b_bounds = &nde_b.possible_types;
debug!("%s.lattice_vars(%s=%s <: %s=%s)",
self.tag(),
- a_vid.to_str(), a_bounds.to_str(self.infcx()),
- b_vid.to_str(), b_bounds.to_str(self.infcx()));
+ a_vid.to_str(), a_bounds.inf_str(self.infcx()),
+ b_vid.to_str(), b_bounds.inf_str(self.infcx()));
+ // Same variable: the easy case.
if a_vid == b_vid {
- return Ok(a_t);
+ return Ok(VarResult(a_vid));
}
// If both A and B have an UB type, then we can just compute the
// LUB of those types:
let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds);
match (a_bnd, b_bnd) {
- (Some(a_ty), Some(b_ty)) => {
- match self.infcx().try(|| c_ts(a_ty, b_ty) ) {
- Ok(t) => return Ok(t),
- Err(_) => { /*fallthrough */ }
+ (Some(ref a_ty), Some(ref b_ty)) => {
+ match self.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) {
+ Ok(t) => return Ok(ValueResult(t)),
+ Err(_) => { /*fallthrough */ }
+ }
}
- }
- _ => {/*fallthrough*/}
+ _ => {/*fallthrough*/}
}
// Otherwise, we need to merge A and B into one variable. We can
// then use either variable as an upper bound:
- var_sub_var(self, a_vid, b_vid).then(|| Ok(a_t) )
+ let cf = self.combine_fields();
+ do cf.var_sub_var(vb, a_vid, b_vid).then {
+ Ok(VarResult(a_vid))
+ }
}
-fn lattice_var_and_t<L:lattice_ops combine>(
- self: &L, a_id: ty::TyVid, b: ty::t,
- c_ts: fn(ty::t, ty::t) -> cres<ty::t>) -> cres<ty::t> {
-
- let vb = &self.infcx().ty_var_bindings;
+fn lattice_var_and_t<L:LatticeDir Combine,
+ V:Copy Eq Vid ToStr,
+ T:Copy InferStr LatticeValue>(
+ self: &L,
+ vb: &ValsAndBindings<V, Bounds<T>>,
+ +a_id: V,
+ b: &T,
+ lattice_dir_op: LatticeDirOp<T>)
+ -> cres<T>
+{
let nde_a = self.infcx().get(vb, a_id);
let a_id = nde_a.root;
- let a_bounds = nde_a.possible_types;
+ let a_bounds = &nde_a.possible_types;
// The comments in this function are written for LUB, but they
// apply equally well to GLB if you inverse upper/lower/sub/super/etc.
debug!("%s.lattice_var_and_t(%s=%s <: %s)",
self.tag(),
- a_id.to_str(), a_bounds.to_str(self.infcx()),
- b.to_str(self.infcx()));
+ a_id.to_str(),
+ a_bounds.inf_str(self.infcx()),
+ b.inf_str(self.infcx()));
match self.bnd(a_bounds) {
- Some(a_bnd) => {
- // If a has an upper bound, return the LUB(a.ub, b)
- debug!("bnd=some(%s)", a_bnd.to_str(self.infcx()));
- return c_ts(a_bnd, b);
- }
- None => {
- // If a does not have an upper bound, make b the upper bound of a
- // and then return b.
- debug!("bnd=none");
- let a_bounds = self.with_bnd(a_bounds, b);
- do bnds(self, a_bounds.lb, a_bounds.ub).then {
- self.infcx().set(vb, a_id, root(a_bounds, nde_a.rank));
- Ok(b)
+ Some(ref a_bnd) => {
+ // If a has an upper bound, return the LUB(a.ub, b)
+ debug!("bnd=some(%s)", a_bnd.inf_str(self.infcx()));
+ lattice_dir_op(a_bnd, b)
+ }
+ None => {
+ // If a does not have an upper bound, make b the upper bound of a
+ // and then return b.
+ debug!("bnd=none");
+ let a_bounds = self.with_bnd(a_bounds, *b);
+ do self.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then {
+ self.infcx().set(vb, a_id, Root(a_bounds, nde_a.rank));
+ Ok(*b)
+ }
+ }
+ }
+}
+
+// ___________________________________________________________________________
+// Random utility functions used by LUB/GLB when computing LUB/GLB of
+// fn types
+
+fn var_ids<T: Combine>(self: &T, isr: isr_alist) -> ~[RegionVid] {
+ let mut result = ~[];
+ for list::each(isr) |pair| {
+ match pair.second() {
+ ty::re_infer(ty::ReVar(r)) => { result.push(r); }
+ r => {
+ self.infcx().tcx.sess.span_bug(
+ self.span(),
+ fmt!("Found non-region-vid: %?", r));
+ }
}
- }
+ }
+ return result;
+}
+
+fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
+ match r {
+ ty::re_infer(ty::ReVar(ref v)) => new_vars.contains(v),
+ _ => false
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::ty::RegionVid;
+use middle::ty;
use middle::typeck::infer::combine::*;
+use middle::typeck::infer::glb::Glb;
use middle::typeck::infer::lattice::*;
-use middle::typeck::infer::to_str::ToStr;
+use middle::typeck::infer::sub::Sub;
+use middle::typeck::infer::to_str::InferStr;
+use middle::typeck::isr_alist;
+use util::ppaux::mt_to_str;
-use syntax::ast::{Many, Once};
+use std::list;
+use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn, noreturn};
+use syntax::ast::{pure_fn, ret_style, return_val, unsafe_fn};
fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export.
-enum Lub = combine_fields; // "subtype", "subregion" etc
+enum Lub = CombineFields; // least-upper-bound: common supertype
impl Lub {
fn bot_ty(b: ty::t) -> cres<ty::t> { Ok(b) }
fn ty_bot(b: ty::t) -> cres<ty::t> { self.bot_ty(b) } // commutative
}
-impl Lub: combine {
- fn infcx() -> infer_ctxt { self.infcx }
+impl Lub: Combine {
+ fn infcx() -> @InferCtxt { self.infcx }
fn tag() -> ~str { ~"lub" }
fn a_is_expected() -> bool { self.a_is_expected }
+ fn span() -> span { self.span }
fn sub() -> Sub { Sub(*self) }
fn lub() -> Lub { Lub(*self) }
Glb(*self).tys(a, b)
}
- fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
- match (p1, p2) {
- (ast::ProtoBare, _) => Ok(p2),
- (_, ast::ProtoBare) => Ok(p1),
- _ if p1 == p2 => Ok(p1),
- _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2)))
- }
- }
-
fn purities(a: purity, b: purity) -> cres<purity> {
match (a, b) {
(unsafe_fn, _) | (_, unsafe_fn) => Ok(unsafe_fn),
}
}
- fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style> {
- match (r1, r2) {
- (ast::return_val, _) |
- (_, ast::return_val) => Ok(ast::return_val),
- (ast::noreturn, ast::noreturn) => Ok(ast::noreturn)
- }
- }
-
fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
return Glb(*self).regions(a, b);
}
fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
debug!("%s.regions(%?, %?)",
self.tag(),
- a.to_str(self.infcx),
- b.to_str(self.infcx));
+ a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
do indent {
self.infcx.region_vars.lub_regions(self.span, a, b)
}
}
- fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
+ fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
// Note: this is a subtle algorithm. For a full explanation,
// please see the large comment in `region_inference.rs`.
self.span, b);
// Collect constraints.
- let fn_ty0 = if_ok!(super_fns(&self, &a_with_fresh, &b_with_fresh));
- debug!("fn_ty0 = %s", fn_ty0.to_str(self.infcx));
+ let sig0 = if_ok!(super_fn_sigs(&self, &a_with_fresh, &b_with_fresh));
+ debug!("sig0 = %s", sig0.inf_str(self.infcx));
- // Generalize the regions appearing in fn_ty0 if possible
+ // Generalize the regions appearing in sig0 if possible
let new_vars =
self.infcx.region_vars.vars_created_since_snapshot(snapshot);
- let fn_ty1 =
- ty::apply_op_on_t_to_ty_fn(
- self.infcx.tcx, &fn_ty0,
- |t| ty::fold_regions(
- self.infcx.tcx, t,
- |r, _in_fn| generalize_region(&self, snapshot,
- new_vars, a_isr, r)));
- return Ok(move fn_ty1);
+ let sig1 =
+ self.infcx.fold_regions_in_sig(
+ &sig0,
+ |r, _in_fn| generalize_region(&self, snapshot, new_vars,
+ a_isr, r));
+ return Ok(move sig1);
fn generalize_region(self: &Lub,
snapshot: uint,
a_isr: isr_alist,
r0: ty::Region) -> ty::Region {
// Regions that pre-dated the LUB computation stay as they are.
- if !is_new_var(new_vars, r0) {
+ if !is_var_in_set(new_vars, r0) {
debug!("generalize_region(r0=%?): not new variable", r0);
return r0;
}
// Variables created during LUB computation which are
// *related* to regions that pre-date the LUB computation
// stay as they are.
- if !tainted.all(|r| is_new_var(new_vars, *r)) {
+ if !tainted.all(|r| is_var_in_set(new_vars, *r)) {
debug!("generalize_region(r0=%?): \
non-new-variables found in %?",
r0, tainted);
fmt!("Region %? is not associated with \
any bound region from A!", r0));
}
+ }
- fn is_new_var(new_vars: &[RegionVid], r: ty::Region) -> bool {
- match r {
- ty::re_infer(ty::ReVar(ref v)) => new_vars.contains(v),
- _ => false
- }
- }
+ fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
+ super_fns(&self, a, b)
}
fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
super_fn_metas(&self, a, b)
}
- fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
- super_fn_sigs(&self, a, b)
- }
-
// Traits please (FIXME: #2794):
+ fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
+ super_protos(&self, p1, p2)
+ }
+
fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
- lattice_tys(&self, a, b)
+ super_lattice_tys(&self, a, b)
}
fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
)
);
-}
\ No newline at end of file
+}
the regions for outer block scopes are superregions of those for inner
block scopes.
-## Integral type variables
+## Integral and floating-point type variables
There is a third variety of type variable that we use only for
inferring the types of unsuffixed integer literals. Integral type
variables differ from general-purpose type variables in that there's
no subtyping relationship among the various integral types, so instead
-of associating each variable with an upper and lower bound, we
-represent the set of possible integral types it can take on with an
-`int_ty_set`, which is a bitvector with one bit for each integral
-type. Because intersecting these sets with each other is simpler than
-merging bounds, we don't need to do so transactionally as we do for
-general-purpose type variables.
-
-We could conceivably define a subtyping relationship among integral
-types based on their ranges, but we choose not to open that particular
-can of worms. Our strategy is to treat integral type variables as
-unknown until the typing context constrains them to a unique integral
-type, at which point they take on that type. If the typing context
-overconstrains the type, it's a type error; if we reach the point at
-which type variables must be resolved and an integral type variable is
-still underconstrained, it defaults to `int` as a last resort.
-
-Floating point types are handled similarly to integral types.
+of associating each variable with an upper and lower bound, we just
+use simple unification. Each integer variable is associated with at
+most one integer type. Floating point types are handled similarly to
+integral types.
## GLB/LUB
#[warn(deprecated_mode)];
#[warn(deprecated_pattern)];
-use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, vid};
+use core::prelude::*;
+
+use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, Vid};
use middle::ty::{mk_fn, type_is_bot};
use middle::ty::{ty_int, ty_uint, get, terr_fn, TyVar, IntVar, FloatVar};
use middle::ty;
-use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_ty};
+use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig};
use middle::typeck::infer::assignment::Assign;
-use middle::typeck::infer::combine::{combine_fields, eq_tys};
-use middle::typeck::infer::floating::{float_ty_set, float_ty_set_all};
+use middle::typeck::infer::combine::{CombineFields, eq_tys};
use middle::typeck::infer::glb::Glb;
-use middle::typeck::infer::integral::{int_ty_set, int_ty_set_all};
use middle::typeck::infer::lub::Lub;
use middle::typeck::infer::region_inference::{RegionVarBindings};
use middle::typeck::infer::resolve::{force_all, not_regions};
use middle::typeck::infer::resolve::{resolve_nested_tvar, resolve_rvar};
use middle::typeck::infer::resolve::{resolver};
use middle::typeck::infer::sub::Sub;
-use middle::typeck::infer::to_str::ToStr;
-use middle::typeck::infer::unify::{vals_and_bindings, root};
+use middle::typeck::infer::to_str::InferStr;
+use middle::typeck::infer::unify::{ValsAndBindings, Root};
+use middle::typeck::isr_alist;
use util::common::{indent, indenter};
-use util::ppaux::{ty_to_str, mt_to_str};
+use util::ppaux::{bound_region_to_str, ty_to_str, mt_to_str};
use core::cmp::Eq;
use core::dvec::DVec;
use core::result::{Result, Ok, Err, map_vec, map_vec2, iter_vec2};
+use core::result;
+use core::vec;
+use std::list::Nil;
use std::map::HashMap;
use std::smallintmap;
use syntax::ast::{ret_style, purity};
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast::{unsafe_fn, impure_fn, pure_fn, extern_fn};
+use syntax::ast;
use syntax::ast_util::dummy_sp;
-use syntax::{ast, ast_util};
+use syntax::ast_util;
+use syntax::codemap::span;
-export infer_ctxt;
+export InferCtxt;
export new_infer_ctxt;
export mk_subty, can_mk_subty;
export mk_subr;
export resolve_and_force_all_but_regions, not_regions;
export resolve_type, resolve_region;
export resolve_borrowings;
-export methods; // for infer_ctxt
-export unify_methods; // for infer_ctxt
export cres, fres, fixup_err, fixup_err_to_str;
export assignment;
export root, to_str;
export int_ty_set_all;
export assignment;
export combine;
-export floating;
export glb;
export integral;
export lattice;
export sub;
export to_str;
export unify;
+export uok;
+export cyclic_ty, unresolved_ty, region_var_bound_by_region_var;
+export Bound, Bounds;
+export ures;
+export ares;
+export infer_ctxt;
+export fixup_err;
+export IntVarValue, IntType, UintType;
#[legacy_exports]
mod assignment;
#[legacy_exports]
mod glb;
#[legacy_exports]
-mod integral;
-mod floating;
-#[legacy_exports]
mod lattice;
#[legacy_exports]
mod lub;
#[legacy_exports]
mod unify;
-type bound<T:Copy> = Option<T>;
-type bounds<T:Copy> = {lb: bound<T>, ub: bound<T>};
+type Bound<T> = Option<T>;
+type Bounds<T> = {lb: Bound<T>, ub: Bound<T>};
type cres<T> = Result<T,ty::type_err>; // "combine result"
type ures = cres<()>; // "unify result"
type fres<T> = Result<T, fixup_err>; // "fixup result"
type ares = cres<Option<@ty::AutoAdjustment>>; // "assignment result"
-enum infer_ctxt = @{
+#[deriving_eq]
+enum IntVarValue {
+ IntType(ast::int_ty),
+ UintType(ast::uint_ty),
+}
+
+struct InferCtxt {
tcx: ty::ctxt,
- // We instantiate vals_and_bindings with bounds<ty::t> because the
+ // We instantiate ValsAndBindings with bounds<ty::t> because the
// types that might instantiate a general type variable have an
// order, represented by its upper and lower bounds.
- ty_var_bindings: vals_and_bindings<ty::TyVid, bounds<ty::t>>,
+ ty_var_bindings: ValsAndBindings<ty::TyVid, Bounds<ty::t>>,
+
+ // Number of type variables created thus far.
+ mut ty_var_counter: uint,
// The types that might instantiate an integral type variable are
// represented by an int_ty_set.
- int_var_bindings: vals_and_bindings<ty::IntVid, int_ty_set>,
+ int_var_bindings: ValsAndBindings<ty::IntVid, Option<IntVarValue>>,
+
+ // Number of integral variables created thus far.
+ mut int_var_counter: uint,
// The types that might instantiate a floating-point type variable are
// represented by an float_ty_set.
- float_var_bindings: vals_and_bindings<ty::FloatVid, float_ty_set>,
+ float_var_bindings: ValsAndBindings<ty::FloatVid, Option<ast::float_ty>>,
+
+ // Number of floating-point variables created thus far.
+ mut float_var_counter: uint,
// For region variables.
region_vars: RegionVarBindings,
-
- // For keeping track of existing type and region variables.
- ty_var_counter: @mut uint,
- int_var_counter: @mut uint,
- float_var_counter: @mut uint,
- region_var_counter: @mut uint
-};
+}
enum fixup_err {
unresolved_int_ty(IntVid),
}
}
-fn new_vals_and_bindings<V:Copy, T:Copy>() -> vals_and_bindings<V, T> {
- vals_and_bindings {
+fn new_ValsAndBindings<V:Copy, T:Copy>() -> ValsAndBindings<V, T> {
+ ValsAndBindings {
vals: smallintmap::mk(),
mut bindings: ~[]
}
}
-fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt {
- infer_ctxt(@{tcx: tcx,
- ty_var_bindings: new_vals_and_bindings(),
- int_var_bindings: new_vals_and_bindings(),
- float_var_bindings: new_vals_and_bindings(),
- region_vars: RegionVarBindings(tcx),
- ty_var_counter: @mut 0u,
- int_var_counter: @mut 0u,
- float_var_counter: @mut 0u,
- region_var_counter: @mut 0u})}
-
-fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span,
+fn new_infer_ctxt(tcx: ty::ctxt) -> @InferCtxt {
+ @InferCtxt {
+ tcx: tcx,
+
+ ty_var_bindings: new_ValsAndBindings(),
+ ty_var_counter: 0,
+
+ int_var_bindings: new_ValsAndBindings(),
+ int_var_counter: 0,
+
+ float_var_bindings: new_ValsAndBindings(),
+ float_var_counter: 0,
+
+ region_vars: RegionVarBindings(tcx),
+ }
+}
+
+fn mk_subty(cx: @InferCtxt, a_is_expected: bool, span: span,
a: ty::t, b: ty::t) -> ures {
- debug!("mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx));
+ debug!("mk_subty(%s <: %s)", a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.commit {
cx.sub(a_is_expected, span).tys(a, b)
}.to_ures()
}
-fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
- debug!("can_mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx));
+fn can_mk_subty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures {
+ debug!("can_mk_subty(%s <: %s)", a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.probe {
cx.sub(true, ast_util::dummy_sp()).tys(a, b)
}.to_ures()
}
-fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span,
+fn mk_subr(cx: @InferCtxt, a_is_expected: bool, span: span,
a: ty::Region, b: ty::Region) -> ures {
- debug!("mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx));
+ debug!("mk_subr(%s <: %s)", a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.commit {
cx.sub(a_is_expected, span).regions(a, b)
}.to_ures()
}
-fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span,
+fn mk_eqty(cx: @InferCtxt, a_is_expected: bool, span: span,
a: ty::t, b: ty::t) -> ures {
- debug!("mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx));
+ debug!("mk_eqty(%s <: %s)", a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.commit {
let suber = cx.sub(a_is_expected, span);
}.to_ures()
}
-fn mk_assignty(cx: infer_ctxt, a_is_expected: bool, span: span,
+fn mk_assignty(cx: @InferCtxt, a_is_expected: bool, span: span,
a: ty::t, b: ty::t) -> ares {
- debug!("mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx));
+ debug!("mk_assignty(%s -> %s)", a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.commit {
Assign(cx.combine_fields(a_is_expected, span)).tys(a, b)
}
}
-fn can_mk_assignty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
- debug!("can_mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx));
+fn can_mk_assignty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures {
+ debug!("can_mk_assignty(%s -> %s)", a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.probe {
let span = ast_util::dummy_sp();
}
// See comment on the type `resolve_state` below
-fn resolve_type(cx: infer_ctxt, a: ty::t, modes: uint)
+fn resolve_type(cx: @InferCtxt, a: ty::t, modes: uint)
-> fres<ty::t> {
resolver(cx, modes).resolve_type_chk(a)
}
-fn resolve_region(cx: infer_ctxt, r: ty::Region, modes: uint)
+fn resolve_region(cx: @InferCtxt, r: ty::Region, modes: uint)
-> fres<ty::Region> {
resolver(cx, modes).resolve_region_chk(r)
}
/*
-fn resolve_borrowings(cx: infer_ctxt) {
+fn resolve_borrowings(cx: @InferCtxt) {
for cx.borrowings.each |item| {
match resolve_region(cx, item.scope, resolve_all|force_all) {
Ok(region) => {
}
}
-fn uok() -> ures {
+pub fn uok() -> ures {
Ok(())
}
-fn rollback_to<V:Copy vid, T:Copy>(
- vb: &vals_and_bindings<V, T>, len: uint) {
-
+fn rollback_to<V:Copy Vid, T:Copy>(
+ vb: &ValsAndBindings<V, T>,
+ len: uint)
+{
while vb.bindings.len() != len {
let (vid, old_v) = vb.bindings.pop();
vb.vals.insert(vid.to_uint(), old_v);
region_vars_snapshot: uint,
}
-impl infer_ctxt {
+impl @InferCtxt {
fn combine_fields(a_is_expected: bool,
- span: span) -> combine_fields {
- combine_fields {infcx: self,
- a_is_expected: a_is_expected,
- span: span}
+ span: span) -> CombineFields {
+ CombineFields {infcx: self,
+ a_is_expected: a_is_expected,
+ span: span}
}
fn sub(a_is_expected: bool, span: span) -> Sub {
//rollback_to(&self.int_var_bindings,
// snapshot.int_var_bindings_len);
- self.region_vars.rollback_to(
- snapshot.region_vars_snapshot);
+ self.region_vars.rollback_to(snapshot.region_vars_snapshot);
}
/// Execute `f` and commit the bindings if successful
}
}
-impl infer_ctxt {
+impl @InferCtxt {
fn next_ty_var_id() -> TyVid {
- let id = *self.ty_var_counter;
- *self.ty_var_counter += 1u;
+ let id = self.ty_var_counter;
+ self.ty_var_counter += 1;
self.ty_var_bindings.vals.insert(id,
- root({lb: None, ub: None}, 0u));
+ Root({lb: None, ub: None}, 0u));
return TyVid(id);
}
}
fn next_int_var_id() -> IntVid {
- let id = *self.int_var_counter;
- *self.int_var_counter += 1u;
+ let id = self.int_var_counter;
+ self.int_var_counter += 1;
- self.int_var_bindings.vals.insert(id,
- root(int_ty_set_all(), 0u));
+ self.int_var_bindings.vals.insert(id, Root(None, 0));
return IntVid(id);
}
}
fn next_float_var_id() -> FloatVid {
- let id = *self.float_var_counter;
- *self.float_var_counter += 1;
+ let id = self.float_var_counter;
+ self.float_var_counter += 1;
- self.float_var_bindings.vals.insert(id, root(float_ty_set_all(), 0));
+ self.float_var_bindings.vals.insert(id, Root(None, 0));
return FloatVid(id);
}
let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
// Don't report an error if actual type is ty_err.
- match ty::get(actual_ty).sty {
- ty::ty_err => return,
- _ => ()
+ if ty::type_contains_err(actual_ty) {
+ return;
}
let error_str = err.map_default(~"", |t_err|
fmt!(" (%s)",
fn replace_bound_regions_with_fresh_regions(
&self, span: span,
- fty: &ty::FnTy) -> (ty::FnTy, isr_alist)
+ fsig: &ty::FnSig) -> (ty::FnSig, isr_alist)
{
- let {fn_ty: fn_ty, isr: isr, _} =
- replace_bound_regions_in_fn_ty(self.tcx, @Nil, None, fty, |br| {
+ let {fn_sig: fn_sig, isr: isr, _} =
+ replace_bound_regions_in_fn_sig(self.tcx, @Nil, None, fsig, |br| {
// N.B.: The name of the bound region doesn't have anything to
// do with the region variable that's created for it. The
// only thing we're doing with `br` here is using it in the
rvar);
rvar
});
- (fn_ty, isr)
+ (fn_sig, isr)
+ }
+
+ fn fold_regions_in_sig(
+ &self,
+ fn_sig: &ty::FnSig,
+ fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig
+ {
+ do ty::fold_sig(fn_sig) |t| {
+ ty::fold_regions(self.tcx, t, fldr)
+ }
}
}
LUB or GLB computation. We have to consider this. Here is the
algorithm I implemented.
+First though, let's discuss what we are trying to compute in more
+detail. The LUB is basically the "common supertype" and the GLB is
+"common subtype"; one catch is that the LUB should be the
+*most-specific* common supertype and the GLB should be *most general*
+common subtype (as opposed to any common supertype or any common
+subtype).
+
+Anyway, to help clarify, here is a table containing some
+function pairs and their LUB/GLB:
+
+```
+Type 1 Type 2 LUB GLB
+fn<a>(&a) fn(&X) fn(&X) fn<a>(&a)
+fn(&A) fn(&X) -- fn<a>(&a)
+fn<a,b>(&a, &b) fn<x>(&x, &x) fn<a>(&a, &a) fn<a,b>(&a, &b)
+fn<a,b>(&a, &b, &a) fn<x,y>(&x, &y, &y) fn<a>(&a, &a, &a) fn<a,b,c>(&a,&b,&c)
+```
+
+### Conventions
+
+I use lower-case letters (e.g., `&a`) for bound regions and upper-case
+letters for free regions (`&A`). Region variables written with a
+dollar-sign (e.g., `$a`). I will try to remember to enumerate the
+bound-regions on the fn type as well (e.g., `fn<a>(&a)`).
+
+### High-level summary
+
+Both the LUB and the GLB algorithms work in a similar fashion. They
+begin by replacing all bound regions (on both sides) with fresh region
+inference variables. Therefore, both functions are converted to types
+that contain only free regions. We can then compute the LUB/GLB in a
+straightforward way, as described in `combine.rs`. This results in an
+interim type T. The algorithms then examine the regions that appear
+in T and try to, in some cases, replace them with bound regions to
+yield the final result.
+
+To decide whether to replace a region `R` that appears in `T` with a
+bound region, the algorithms make use of two bits of information.
+First is a set `V` that contains all region variables created as part
+of the LUB/GLB computation. `V` will contain the region variables
+created to replace the bound regions in the input types, but it also
+contains 'intermediate' variables created to represent the LUB/GLB of
+individual regions. Basically, when asked to compute the LUB/GLB of a
+region variable with another region, the inferencer cannot oblige
+immediately since the valuese of that variables are not known.
+Therefore, it creates a new variable that is related to the two
+regions. For example, the LUB of two variables `$x` and `$y` is a
+fresh variable `$z` that is constrained such that `$x <= $z` and `$y
+<= $z`. So `V` will contain these intermediate variables as well.
+
+The other important factor in deciding how to replace a region in T is
+the function `Tainted($r)` which, for a region variable, identifies
+all regions that the region variable is related to in some way
+(`Tainted()` made an appearance in the subtype computation as well).
+
### LUB
The LUB algorithm proceeds in three steps:
inference variables.
2. Compute the LUB "as normal", meaning compute the GLB of each
pair of argument types and the LUB of the return types and
- so forth. Combine those to a new function type F.
-3. Map the regions appearing in `F` using the procedure described below.
-
-For each region `R` that appears in `F`, we may need to replace it
-with a bound region. Let `V` be the set of fresh variables created as
-part of the LUB procedure (either in step 1 or step 2). You may be
-wondering how variables can be created in step 2. The answer is that
-when we are asked to compute the LUB or GLB of two region variables,
-we do so by producing a new region variable that is related to those
-two variables. i.e., The LUB of two variables `$x` and `$y` is a
-fresh variable `$z` that is constrained such that `$x <= $z` and `$y
-<= $z`.
-
-To decide how to replace a region `R`, we must examine `Tainted(R)`.
-This function searches through the constraints which were generated
-when computing the bounds of all the argument and return types and
-produces a list of all regions to which `R` is related, directly or
-indirectly.
-
-If `R` is not in `V` or `Tainted(R)` contains any region that is not
-in `V`, then `R` is not replaced (that is, `R` is mapped to itself).
-Otherwise, if `Tainted(R)` is a subset of `V`, then we select the
-earliest variable in `Tainted(R)` that originates from the left-hand
-side and replace `R` with a bound version of that variable.
-
-So, let's work through the simplest example: `fn(&A)` and `fn(&a)`.
-In this case, `&a` will be replaced with `$a` (the $ indicates an
-inference variable) which will be linked to the free region `&A`, and
-hence `V = { $a }` and `Tainted($a) = { &A }`. Since `$a` is not a
-member of `V`, we leave `$a` as is. When region inference happens,
-`$a` will be resolved to `&A`, as we wanted.
-
-So, let's work through the simplest example: `fn(&A)` and `fn(&a)`.
-In this case, `&a` will be replaced with `$a` (the $ indicates an
-inference variable) which will be linked to the free region `&A`, and
-hence `V = { $a }` and `Tainted($a) = { $a, &A }`. Since `&A` is not a
-member of `V`, we leave `$a` as is. When region inference happens,
-`$a` will be resolved to `&A`, as we wanted.
-
-Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`.
-In this case, we'll end up with a graph that looks like:
+ so forth. Combine those to a new function type `F`.
+3. Replace each region `R` that appears in `F` as follows:
+ - Let `V` be the set of variables created during the LUB
+ computational steps 1 and 2, as described in the previous section.
+ - If `R` is not in `V`, replace `R` with itself.
+ - If `Tainted(R)` contains a region that is not in `V`,
+ replace `R` with itself.
+ - Otherwise, select the earliest variable in `Tainted(R)` that originates
+ from the left-hand side and replace `R` with the bound region that
+ this variable was a replacement for.
+
+So, let's work through the simplest example: `fn(&A)` and `fn<a>(&a)`.
+In this case, `&a` will be replaced with `$a` and the interim LUB type
+`fn($b)` will be computed, where `$b=GLB(&A,$a)`. Therefore, `V =
+{$a, $b}` and `Tainted($b) = { $b, $a, &A }`. When we go to replace
+`$b`, we find that since `&A \in Tainted($b)` is not a member of `V`,
+we leave `$b` as is. When region inference happens, `$b` will be
+resolved to `&A`, as we wanted.
+
+Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`. In
+this case, we'll end up with a (pre-replacement) LUB type of `fn(&g,
+&h)` and a graph that looks like:
```
$a $b *--$x
`Tainted` will look like:
```
-V = {$a, $b, $x}
-Tainted($g) = Tainted($h) = { $a, $b, $h, $x }
+V = {$a, $b, $g, $h, $x}
+Tainted($g) = Tainted($h) = { $a, $b, $h, $g, $x }
```
Therefore we replace both `$g` and `$h` with `$a`, and end up
region `R` that appears in the type `F`, we again compute `Tainted(R)`
and examine the results:
-1. If `Tainted(R) = {R}` is a singleton set, replace `R` with itself.
+1. If `R` is not in `V`, it is not replaced.
2. Else, if `Tainted(R)` contains only variables in `V`, and it
contains exactly one variable from the LHS and one variable from
the RHS, then `R` can be mapped to the bound version of the
variable from the LHS.
-3. Else, `R` is mapped to a fresh bound variable.
+3. Else, if `Tainted(R)` contains no variable from the LHS and no
+ variable from the RHS, then `R` can be mapped to itself.
+4. Else, `R` is mapped to a fresh bound variable.
These rules are pretty complex. Let's look at some examples to see
how they play out.
-Out first example was `fn(&a)` and `fn(&X)`---in
-this case, the LUB will be a variable `$g`, and `Tainted($g) =
-{$g,$a,$x}`. By these rules, we'll replace `$g` with a fresh bound
-variable, so the result is `fn(&z)`, which is fine.
-
-The next example is `fn(&A)` and `fn(&Z)`. XXX
-
-The next example is `fn(&a, &b)` and `fn(&x, &x)`. In this case, as
-before, we'll end up with `F=fn(&g, &h)` where `Tainted($g) =
-Tainted($h) = {$g, $a, $b, $x}`. This means that we'll select fresh
-bound varibales `g` and `h` and wind up with `fn(&g, &h)`.
+Out first example was `fn(&a)` and `fn(&X)`. In this case, `&a` will
+be replaced with `$a` and we will ultimately compute a
+(pre-replacement) GLB type of `fn($g)` where `$g=LUB($a,&X)`.
+Therefore, `V={$a,$g}` and `Tainted($g)={$g,$a,&X}. To find the
+replacement for `$g` we consult the rules above:
+- Rule (1) does not apply because `$g \in V`
+- Rule (2) does not apply because `&X \in Tainted($g)`
+- Rule (3) does not apply because `$a \in Tainted($g)`
+- Hence, by rule (4), we replace `$g` with a fresh bound variable `&z`.
+So our final result is `fn(&z)`, which is correct.
+
+The next example is `fn(&A)` and `fn(&Z)`. In this case, we will again
+have a (pre-replacement) GLB of `fn(&g)`, where `$g = LUB(&A,&Z)`.
+Therefore, `V={$g}` and `Tainted($g) = {$g, &A, &Z}`. In this case,
+by rule (3), `$g` is mapped to itself, and hence the result is
+`fn($g)`. This result is correct (in this case, at least), but it is
+indicative of a case that *can* lead us into concluding that there is
+no GLB when in fact a GLB does exist. See the section "Questionable
+Results" below for more details.
+
+The next example is `fn(&a, &b)` and `fn(&c, &c)`. In this case, as
+before, we'll end up with `F=fn($g, $h)` where `Tainted($g) =
+Tainted($h) = {$g, $h, $a, $b, $c}`. Only rule (4) applies and hence
+we'll select fresh bound variables `y` and `z` and wind up with
+`fn(&y, &z)`.
For the last example, let's consider what may seem trivial, but is
-not: `fn(&a, &a)` and `fn(&x, &x)`. In this case, we'll get `F=fn(&g,
-&h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a,
+not: `fn(&a, &a)` and `fn(&b, &b)`. In this case, we'll get `F=fn($g,
+$h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a,
$x}`. Both of these sets contain exactly one bound variable from each
-side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`.
-Horray!
-
-### Why are these correct?
-
-You may be wondering whether this algorithm is correct. So am I. But
-I believe it is. (Justification forthcoming, haven't had time to
-write it)
+side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`, which
+is the desired result.
+
+### Shortcomings and correctness
+
+You may be wondering whether this algorithm is correct. The answer is
+"sort of". There are definitely cases where they fail to compute a
+result even though a correct result exists. I believe, though, that
+if they succeed, then the result is valid, and I will attempt to
+convince you. The basic argument is that the "pre-replacement" step
+computes a set of constraints. The replacements, then, attempt to
+satisfy those constraints, using bound identifiers where needed.
+
+For now I will briefly go over the cases for LUB/GLB and identify
+their intent:
+
+- LUB:
+ - The region variables that are substituted in place of bound regions
+ are intended to collect constraints on those bound regions.
+ - If Tainted(R) contains only values in V, then this region is unconstrained
+ and can therefore be generalized, otherwise it cannot.
+- GLB:
+ - The region variables that are substituted in place of bound regions
+ are intended to collect constraints on those bound regions.
+ - If Tainted(R) contains exactly one variable from each side, and
+ only variables in V, that indicates that those two bound regions
+ must be equated.
+ - Otherwise, if Tainted(R) references any variables from left or right
+ side, then it is trying to combine a bound region with a free one or
+ multiple bound regions, so we need to select fresh bound regions.
+
+Sorry this is more of a shorthand to myself. I will try to write up something
+more convincing in the future.
+
+#### Where are the algorithms wrong?
+
+- The pre-replacement computation can fail even though using a
+ bound-region would have succeeded.
+- We will compute GLB(fn(fn($a)), fn(fn($b))) as fn($c) where $c is the
+ GLB of $a and $b. But if inference finds that $a and $b must be mapped
+ to regions without a GLB, then this is effectively a failure to compute
+ the GLB. However, the result `fn<$c>(fn($c))` is a valid GLB.
*/
#[warn(deprecated_mode)];
#[warn(deprecated_pattern)];
+use core::prelude::*;
+
use middle::region::is_subregion_of;
+use middle::region;
+use middle::ty;
use middle::ty::{Region, RegionVid, re_static, re_infer, re_free, re_bound};
-use middle::ty::{re_scope, ReVar, ReSkolemized};
-use middle::typeck::infer::to_str::ToStr;
+use middle::ty::{re_scope, ReVar, ReSkolemized, br_fresh};
+use middle::typeck::infer::to_str::InferStr;
+use middle::typeck::infer::cres;
use syntax::codemap;
+use util::common::indenter;
use util::ppaux::note_and_explain_region;
+use core::cmp;
use core::dvec::DVec;
+use core::to_bytes;
+use core::uint;
+use core::vec;
use result::Result;
use result::{Ok, Err};
use std::map::HashMap;
use std::cell::{Cell, empty_cell};
use std::list::{List, Nil, Cons};
+use syntax::codemap::span;
+use syntax::codemap;
export RegionVarBindings;
export make_subregion;
lubs: CombineMap,
glbs: CombineMap,
mut skolemization_count: uint,
+ mut bound_count: uint,
// The undo log records actions that might later be undone.
//
lubs: CombineMap(),
glbs: CombineMap(),
skolemization_count: 0,
+ bound_count: 0,
undo_log: ~[]
}
}
re_infer(ReSkolemized(sc, br))
}
+ fn new_bound(&self) -> Region {
+ // Creates a fresh bound variable for use in GLB computations.
+ // See discussion of GLB computation in the large comment at
+ // the top of this file for more details.
+ //
+ // This computation is mildly wrong in the face of rollover.
+ // It's conceivable, if unlikely, that one might wind up with
+ // accidental capture for nested functions in that case, if
+ // the outer function had bound regions created a very long
+ // time before and the inner function somehow wound up rolling
+ // over such that supposedly fresh identifiers were in fact
+ // shadowed. We should convert our bound_region
+ // representation to use deBruijn indices or something like
+ // that to eliminate that possibility.
+
+ let sc = self.bound_count;
+ self.bound_count += 1;
+ re_bound(br_fresh(sc))
+ }
+
fn add_constraint(&self, +constraint: Constraint, span: span) {
// cannot add constraints once regions are resolved
assert self.values.is_empty();
self.add_constraint(ConstrainVarSubReg(sub_id, r), span);
Ok(())
}
+ (re_bound(br), _) => {
+ self.tcx.sess.span_bug(
+ span,
+ fmt!("Cannot relate bound region as subregion: %?", br));
+ }
+ (_, re_bound(br)) => {
+ self.tcx.sess.span_bug(
+ span,
+ fmt!("Cannot relate bound region as superregion: %?", br));
+ }
_ => {
if self.is_subregion_of(sub, sup) {
Ok(())
// future). If you want to resolve everything but one type, you are
// probably better off writing `resolve_all - resolve_ivar`.
-use middle::typeck::infer::floating::*;
-use middle::typeck::infer::integral::*;
-use middle::typeck::infer::to_str::ToStr;
-
-const resolve_nested_tvar: uint = 0b00000001;
-const resolve_rvar: uint = 0b00000010;
-const resolve_ivar: uint = 0b00000100;
-const resolve_fvar: uint = 0b00001000;
-const resolve_all: uint = 0b00001111;
-const force_tvar: uint = 0b00010000;
-const force_rvar: uint = 0b00100000;
-const force_ivar: uint = 0b01000000;
-const force_fvar: uint = 0b11000000;
-const force_all: uint = 0b11110000;
+use core::prelude::*;
+
+use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid};
+use middle::ty::{type_is_bot};
+use middle::ty;
+use middle::typeck::infer::{cyclic_ty, fixup_err, fres, InferCtxt};
+use middle::typeck::infer::{region_var_bound_by_region_var, unresolved_ty};
+use middle::typeck::infer::{IntType, UintType};
+use middle::typeck::infer::to_str::InferStr;
+use middle::typeck::infer::unify::Root;
+use util::common::{indent, indenter};
+use util::ppaux::ty_to_str;
+
+use syntax::ast;
+
+use core::uint;
+use core::vec;
+
+const resolve_nested_tvar: uint = 0b0000000001;
+const resolve_rvar: uint = 0b0000000010;
+const resolve_ivar: uint = 0b0000000100;
+const resolve_fvar: uint = 0b0000001000;
+const resolve_fnvar: uint = 0b0000010000;
+const resolve_all: uint = 0b0000011111;
+const force_tvar: uint = 0b0000100000;
+const force_rvar: uint = 0b0001000000;
+const force_ivar: uint = 0b0010000000;
+const force_fvar: uint = 0b0100000000;
+const force_fnvar: uint = 0b1000000000;
+const force_all: uint = 0b1111100000;
const not_regions: uint = !(force_rvar | resolve_rvar);
const resolve_and_force_all_but_regions: uint =
(resolve_all | force_all) & not_regions;
-type resolve_state_ = {
- infcx: infer_ctxt,
+struct ResolveState {
+ infcx: @InferCtxt,
modes: uint,
mut err: Option<fixup_err>,
- mut v_seen: ~[TyVid]
-};
-
-enum resolve_state {
- resolve_state_(@resolve_state_)
+ mut v_seen: ~[TyVid],
+ mut type_depth: uint
}
-fn resolver(infcx: infer_ctxt, modes: uint) -> resolve_state {
- resolve_state_(@{infcx: infcx,
- modes: modes,
- mut err: None,
- mut v_seen: ~[]})
+fn resolver(infcx: @InferCtxt, modes: uint) -> ResolveState {
+ ResolveState {
+ infcx: infcx,
+ modes: modes,
+ err: None,
+ v_seen: ~[],
+ type_depth: 0
+ }
}
-impl resolve_state {
- fn should(mode: uint) -> bool {
+impl ResolveState {
+ fn should(&self, mode: uint) -> bool {
(self.modes & mode) == mode
}
- fn resolve_type_chk(typ: ty::t) -> fres<ty::t> {
+ fn resolve_type_chk(&self, typ: ty::t) -> fres<ty::t> {
self.err = None;
debug!("Resolving %s (modes=%x)",
assert vec::is_empty(self.v_seen);
match self.err {
None => {
- debug!("Resolved to %s (modes=%x)",
+ debug!("Resolved to %s + %s (modes=%x)",
+ ty_to_str(self.infcx.tcx, rty),
ty_to_str(self.infcx.tcx, rty),
self.modes);
return Ok(rty);
}
}
- fn resolve_region_chk(orig: ty::Region) -> fres<ty::Region> {
+ fn resolve_region_chk(&self, orig: ty::Region) -> fres<ty::Region> {
self.err = None;
let resolved = indent(|| self.resolve_region(orig) );
match self.err {
}
}
- fn resolve_type(typ: ty::t) -> ty::t {
- debug!("resolve_type(%s)", typ.to_str(self.infcx));
- indent(fn&() -> ty::t {
- if !ty::type_needs_infer(typ) { return typ; }
+ fn resolve_type(&self, typ: ty::t) -> ty::t {
+ debug!("resolve_type(%s)", typ.inf_str(self.infcx));
+ let _i = indenter();
+
+ if !ty::type_needs_infer(typ) {
+ return typ;
+ }
+
+ if self.type_depth > 0 && !self.should(resolve_nested_tvar) {
+ return typ;
+ }
- match ty::get(typ).sty {
- ty::ty_infer(TyVar(vid)) => {
+ match /*bad*/ copy ty::get(typ).sty {
+ ty::ty_infer(TyVar(vid)) => {
self.resolve_ty_var(vid)
- }
- ty::ty_infer(IntVar(vid)) => {
+ }
+ ty::ty_infer(IntVar(vid)) => {
self.resolve_int_var(vid)
- }
- ty::ty_infer(FloatVar(vid)) => {
+ }
+ ty::ty_infer(FloatVar(vid)) => {
self.resolve_float_var(vid)
- }
- _ => {
- if !self.should(resolve_rvar) &&
- !self.should(resolve_nested_tvar) {
- // shortcircuit for efficiency
+ }
+ _ => {
+ if self.modes & resolve_all == 0 {
+ // if we are only resolving top-level type
+ // variables, and this is not a top-level type
+ // variable, then shortcircuit for efficiency
typ
} else {
- ty::fold_regions_and_ty(
+ self.type_depth += 1;
+ let result = ty::fold_regions_and_ty(
self.infcx.tcx, typ,
|r| self.resolve_region(r),
- |t| self.resolve_nested_tvar(t),
- |t| self.resolve_nested_tvar(t))
+ |t| self.resolve_type(t),
+ |t| self.resolve_type(t));
+ self.type_depth -= 1;
+ result
}
- }
}
- })
- }
-
- fn resolve_nested_tvar(typ: ty::t) -> ty::t {
- debug!("Resolve_if_deep(%s)", typ.to_str(self.infcx));
- if !self.should(resolve_nested_tvar) {
- typ
- } else {
- self.resolve_type(typ)
}
}
- fn resolve_region(orig: ty::Region) -> ty::Region {
- debug!("Resolve_region(%s)", orig.to_str(self.infcx));
+ fn resolve_region(&self, orig: ty::Region) -> ty::Region {
+ debug!("Resolve_region(%s)", orig.inf_str(self.infcx));
match orig {
ty::re_infer(ty::ReVar(rid)) => self.resolve_region_var(rid),
_ => orig
}
}
- fn resolve_region_var(rid: RegionVid) -> ty::Region {
+ fn resolve_region_var(&self, rid: RegionVid) -> ty::Region {
if !self.should(resolve_rvar) {
return ty::re_infer(ty::ReVar(rid));
}
self.infcx.region_vars.resolve_var(rid)
}
- fn assert_not_rvar(rid: RegionVid, r: ty::Region) {
+ fn assert_not_rvar(&self, rid: RegionVid, r: ty::Region) {
match r {
ty::re_infer(ty::ReVar(rid2)) => {
self.err = Some(region_var_bound_by_region_var(rid, rid2));
}
}
- fn resolve_ty_var(vid: TyVid) -> ty::t {
+ fn resolve_ty_var(&self, vid: TyVid) -> ty::t {
if vec::contains(self.v_seen, &vid) {
self.err = Some(cyclic_ty(vid));
return ty::mk_var(self.infcx.tcx, vid);
}
}
- fn resolve_int_var(vid: IntVid) -> ty::t {
+ fn resolve_int_var(&self, vid: IntVid) -> ty::t {
if !self.should(resolve_ivar) {
return ty::mk_int_var(self.infcx.tcx, vid);
}
- let nde = self.infcx.get(&self.infcx.int_var_bindings, vid);
- let pt = nde.possible_types;
-
- // If there's only one type in the set of possible types, then
- // that's the answer.
- match integral::single_type_contained_in(self.infcx.tcx, pt) {
- Some(t) => t,
+ let node = self.infcx.get(&self.infcx.int_var_bindings, vid);
+ match node.possible_types {
+ Some(IntType(t)) => ty::mk_mach_int(self.infcx.tcx, t),
+ Some(UintType(t)) => ty::mk_mach_uint(self.infcx.tcx, t),
None => {
if self.should(force_ivar) {
// As a last resort, default to int.
let ty = ty::mk_int(self.infcx.tcx);
self.infcx.set(
&self.infcx.int_var_bindings, vid,
- root(convert_integral_ty_to_int_ty_set(self.infcx.tcx,
- ty),
- nde.rank));
+ Root(Some(IntType(ast::ty_i)), node.rank));
ty
} else {
ty::mk_int_var(self.infcx.tcx, vid)
}
}
- fn resolve_float_var(vid: FloatVid) -> ty::t {
+ fn resolve_float_var(&self, vid: FloatVid) -> ty::t {
if !self.should(resolve_fvar) {
return ty::mk_float_var(self.infcx.tcx, vid);
}
- let nde = self.infcx.get(&self.infcx.float_var_bindings, vid);
- let pt = nde.possible_types;
-
- // If there's only one type in the set of possible types, then
- // that's the answer.
- match floating::single_type_contained_in(self.infcx.tcx, pt) {
- Some(t) => t,
+ let node = self.infcx.get(&self.infcx.float_var_bindings, vid);
+ match node.possible_types {
+ Some(t) => ty::mk_mach_float(self.infcx.tcx, t),
None => {
if self.should(force_fvar) {
// As a last resort, default to float.
self.infcx.set(
&self.infcx.float_var_bindings,
vid,
- root(
- convert_floating_point_ty_to_float_ty_set(
- self.infcx.tcx, ty),
- nde.rank));
+ Root(Some(ast::ty_f), node.rank));
ty
} else {
ty::mk_float_var(self.infcx.tcx, vid)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::ty;
+use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
use middle::typeck::infer::combine::*;
-use middle::typeck::infer::to_str::ToStr;
+use middle::typeck::infer::cres;
+use middle::typeck::infer::glb::Glb;
+use middle::typeck::infer::InferCtxt;
+use middle::typeck::infer::lub::Lub;
+use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::unify::*;
+use util::ppaux::bound_region_to_str;
+use std::list::Nil;
use std::list;
+use syntax::ast::{m_const, purity, ret_style};
fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export.
-enum Sub = combine_fields; // "subtype", "subregion" etc
+enum Sub = CombineFields; // "subtype", "subregion" etc
-impl Sub: combine {
- fn infcx() -> infer_ctxt { self.infcx }
+impl Sub: Combine {
+ fn infcx() -> @InferCtxt { self.infcx }
fn tag() -> ~str { ~"sub" }
fn a_is_expected() -> bool { self.a_is_expected }
+ fn span() -> span { self.span }
fn sub() -> Sub { Sub(*self) }
fn lub() -> Lub { Lub(*self) }
fn glb() -> Glb { Glb(*self) }
fn contratys(a: ty::t, b: ty::t) -> cres<ty::t> {
- let opp = combine_fields {
+ let opp = CombineFields {
a_is_expected: !self.a_is_expected,.. *self
};
Sub(opp).tys(b, a)
}
fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
- let opp = combine_fields {
+ let opp = CombineFields {
a_is_expected: !self.a_is_expected,.. *self
};
Sub(opp).regions(b, a)
fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region> {
debug!("%s.regions(%s, %s)",
self.tag(),
- a.to_str(self.infcx),
- b.to_str(self.infcx));
+ a.inf_str(self.infcx),
+ b.inf_str(self.infcx));
do indent {
match self.infcx.region_vars.make_subregion(self.span, a, b) {
Ok(()) => Ok(a),
}
fn mts(a: ty::mt, b: ty::mt) -> cres<ty::mt> {
- debug!("mts(%s <: %s)", a.to_str(self.infcx), b.to_str(self.infcx));
+ debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx));
if a.mutbl != b.mutbl && b.mutbl != m_const {
return Err(ty::terr_mutability);
}
}
- fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
- match (p1, p2) {
- (ast::ProtoBare, _) => Ok(p1),
- _ if p1 == p2 => Ok(p1),
- _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2)))
- }
- }
-
fn purities(a: purity, b: purity) -> cres<purity> {
self.lub().purities(a, b).compare(b, || {
ty::terr_purity_mismatch(expected_found(&self, a, b))
})
}
- fn ret_styles(a: ret_style, b: ret_style) -> cres<ret_style> {
- self.lub().ret_styles(a, b).compare(b, || {
- ty::terr_ret_style_mismatch(expected_found(&self, a, b))
- })
- }
-
fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
debug!("%s.tys(%s, %s)", self.tag(),
- a.to_str(self.infcx), b.to_str(self.infcx));
+ a.inf_str(self.infcx), b.inf_str(self.infcx));
if a == b { return Ok(a); }
do indent {
match (ty::get(a).sty, ty::get(b).sty) {
- (ty::ty_bot, _) => {
- Ok(a)
- }
- (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => {
- var_sub_var(&self, a_id, b_id).then(|| Ok(a) )
- }
- (ty::ty_infer(TyVar(a_id)), _) => {
- var_sub_t(&self, a_id, b).then(|| Ok(a) )
- }
- (_, ty::ty_infer(TyVar(b_id))) => {
- t_sub_var(&self, a, b_id).then(|| Ok(a) )
- }
- (_, ty::ty_bot) => {
- Err(ty::terr_sorts(expected_found(&self, a, b)))
- }
- _ => {
- super_tys(&self, a, b)
- }
+ (ty::ty_bot, _) => {
+ Ok(a)
+ }
+
+ (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => {
+ do self.var_sub_var(&self.infcx.ty_var_bindings,
+ a_id, b_id).then {
+ Ok(a)
+ }
+ }
+ (ty::ty_infer(TyVar(a_id)), _) => {
+ do self.var_sub_t(&self.infcx.ty_var_bindings,
+ a_id, b).then {
+ Ok(a)
+ }
+ }
+ (_, ty::ty_infer(TyVar(b_id))) => {
+ do self.t_sub_var(&self.infcx.ty_var_bindings,
+ a, b_id).then {
+ Ok(a)
+ }
+ }
+
+ (_, ty::ty_bot) => {
+ Err(ty::terr_sorts(expected_found(&self, a, b)))
+ }
+
+ _ => {
+ super_tys(&self, a, b)
+ }
}
}
}
- fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
- debug!("fns(a=%s, b=%s)", a.to_str(self.infcx), b.to_str(self.infcx));
+ fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
+ debug!("fn_sigs(a=%s, b=%s)",
+ a.inf_str(self.infcx), b.inf_str(self.infcx));
let _indenter = indenter();
// Rather than checking the subtype relationship between `a` and `b`
// First, we instantiate each bound region in the subtype with a fresh
// region variable.
- let (a_fn_ty, _) =
+ let (a_sig, _) =
self.infcx.replace_bound_regions_with_fresh_regions(
self.span, a);
// Second, we instantiate each bound region in the supertype with a
// fresh concrete region.
- let {fn_ty: b_fn_ty, isr: skol_isr, _} = {
- do replace_bound_regions_in_fn_ty(self.infcx.tcx, @Nil,
+ let {fn_sig: b_sig, isr: skol_isr, _} = {
+ do replace_bound_regions_in_fn_sig(self.infcx.tcx, @Nil,
None, b) |br| {
let skol = self.infcx.region_vars.new_skolemized(br);
debug!("Bound region %s skolemized to %?",
}
};
- debug!("a_fn_ty=%s", a_fn_ty.to_str(self.infcx));
- debug!("b_fn_ty=%s", b_fn_ty.to_str(self.infcx));
+ debug!("a_sig=%s", a_sig.inf_str(self.infcx));
+ debug!("b_sig=%s", b_sig.inf_str(self.infcx));
// Compare types now that bound regions have been replaced.
- let fn_ty = if_ok!(super_fns(&self, &a_fn_ty, &b_fn_ty));
+ let sig = if_ok!(super_fn_sigs(&self, &a_sig, &b_sig));
// Presuming type comparison succeeds, we need to check
// that the skolemized regions do not "leak".
}
}
- return Ok(fn_ty)
+ return Ok(sig);
}
// Traits please (FIXME: #2794):
+ fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
+ super_protos(&self, p1, p2)
+ }
+
fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
super_flds(&self, a, b)
}
- fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
- super_fn_metas(&self, a, b)
+ fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
+ super_fns(&self, a, b)
}
- fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
- super_fn_sigs(&self, a, b)
+ fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
+ super_fn_metas(&self, a, b)
}
fn vstores(vk: ty::terr_vstore_kind,
*/
-use std::getopts;
-use std::map::HashMap;
-use std::getopts;
-use std::getopts::{opt_present};
-use std::getopts::groups;
-use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts};
-use driver::driver::{optgroups, build_session_options, build_session,
- str_input, build_configuration};
+use core::prelude::*;
+
use driver::diagnostic;
-use syntax::{ast, attr, parse};
-use syntax::parse::parse_crate_from_source_str;
+use driver::driver::{optgroups, build_session_options, build_session};
+use driver::driver::{str_input, build_configuration};
use middle::lang_items::{LanguageItems, language_items};
+use middle::ty::{FnTyBase, FnMeta, FnSig};
use util::ppaux::ty_to_str;
+
+use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts};
+use std::getopts::groups;
+use std::getopts::{opt_present};
+use std::getopts;
+use std::getopts;
+use std::map::HashMap;
use syntax::ast_util::dummy_sp;
-use middle::ty::{FnTyBase, FnMeta, FnSig};
+use syntax::parse::parse_crate_from_source_str;
+use syntax::{ast, attr, parse};
struct Env {
crate: @ast::crate,
tcx: ty::ctxt,
- infcx: infer::infer_ctxt
+ infcx: infer::infer_ctxt,
+ err_messages: @DVec<~str>
}
struct RH {
sub: &[RH]
}
+const EMPTY_SOURCE_STR: &str = "/* Hello, world! */";
+
fn setup_env(test_name: &str, source_string: &str) -> Env {
- let matches = &getopts(~[~"-Z", ~"verbose"], optgroups()).get();
- let sessopts = build_session_options(~"rustc", matches, diagnostic::emit);
- let sess = build_session(sessopts, diagnostic::emit);
+ let messages = @DVec();
+ let matches = getopts(~[~"-Z", ~"verbose"], optgroups()).get();
+ let diag = diagnostic::collect(messages);
+ let sessopts = build_session_options(~"rustc", &matches, diag);
+ let sess = build_session(sessopts, diag);
let cfg = build_configuration(sess, ~"whatever", str_input(~""));
let dm = HashMap();
let amap = HashMap();
let freevars = HashMap();
let region_paramd_items = HashMap();
let region_map = HashMap();
- let lang_items = language_items::make();
+ let lang_items = LanguageItems::new();
let parse_sess = parse::new_parse_sess(None);
let crate = parse_crate_from_source_str(
let infcx = infer::new_infer_ctxt(tcx);
- return Env { crate: crate, tcx: tcx, infcx: infcx };
+ return Env {crate: crate,
+ tcx: tcx,
+ infcx: infcx,
+ err_messages: messages};
}
impl Env {
proto: ast::ProtoBare,
onceness: ast::Many,
region: ty::re_static,
- bounds: @~[],
- ret_style: ast::return_val},
+ bounds: @~[]},
sig: FnSig {inputs: move inputs,
output: output_ty}
})
fn lub() -> Lub { Lub(self.infcx.combine_fields(true, dummy_sp())) }
+ fn glb() -> Glb { Glb(self.infcx.combine_fields(true, dummy_sp())) }
+
+ fn resolve_regions(exp_count: uint) {
+ debug!("resolve_regions(%u)", exp_count);
+
+ self.infcx.resolve_regions();
+ if self.err_messages.len() != exp_count {
+ for self.err_messages.each |msg| {
+ debug!("Error encountered: %s", *msg);
+ }
+ fmt!("Resolving regions encountered %u errors but expected %u!",
+ self.err_messages.len(),
+ exp_count);
+ }
+ }
+
/// Checks that `LUB(t1,t2) == t_lub`
fn check_lub(&self, t1: ty::t, t2: ty::t, t_lub: ty::t) {
match self.lub().tys(t1, t2) {
// sanity check for good measure:
self.assert_subtype(t1, t);
self.assert_subtype(t2, t);
+
+ self.resolve_regions(0);
+ }
+ }
+ }
+
+ /// Checks that `GLB(t1,t2) == t_glb`
+ fn check_glb(&self, t1: ty::t, t2: ty::t, t_glb: ty::t) {
+ debug!("check_glb(t1=%s, t2=%s, t_glb=%s)",
+ self.ty_to_str(t1),
+ self.ty_to_str(t2),
+ self.ty_to_str(t_glb));
+ match self.glb().tys(t1, t2) {
+ Err(e) => {
+ fail fmt!("Unexpected error computing LUB: %?", e)
+ }
+ Ok(t) => {
+ self.assert_eq(t, t_glb);
+
+ // sanity check for good measure:
+ self.assert_subtype(t, t1);
+ self.assert_subtype(t, t2);
+
+ self.resolve_regions(0);
}
}
}
}
}
}
+
+ /// Checks that `GLB(t1,t2)` is undefined
+ fn check_no_glb(&self, t1: ty::t, t2: ty::t) {
+ match self.glb().tys(t1, t2) {
+ Err(_) => {}
+ Ok(t) => {
+ fail fmt!("Unexpected success computing GLB: %?",
+ self.ty_to_str(t))
+ }
+ }
+ }
}
#[test]
fn contravariant_region_ptr() {
- let env = setup_env("contravariant_region_ptr", "");
+ let env = setup_env("contravariant_region_ptr", EMPTY_SOURCE_STR);
env.create_simple_region_hierarchy();
let t_rptr1 = env.t_rptr_scope(1);
let t_rptr10 = env.t_rptr_scope(10);
#[test]
fn lub_bound_bound() {
- let env = setup_env("lub_bound_bound", "");
+ let env = setup_env("lub_bound_bound", EMPTY_SOURCE_STR);
let t_rptr_bound1 = env.t_rptr_bound(1);
let t_rptr_bound2 = env.t_rptr_bound(2);
env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()),
#[test]
fn lub_bound_free() {
- let env = setup_env("lub_bound_free", "");
+ let env = setup_env("lub_bound_free", EMPTY_SOURCE_STR);
let t_rptr_bound1 = env.t_rptr_bound(1);
let t_rptr_free1 = env.t_rptr_free(0, 1);
env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()),
#[test]
fn lub_bound_static() {
- let env = setup_env("lub_bound_static", "");
+ let env = setup_env("lub_bound_static", EMPTY_SOURCE_STR);
let t_rptr_bound1 = env.t_rptr_bound(1);
let t_rptr_static = env.t_rptr_static();
env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()),
#[test]
fn lub_bound_bound_inverse_order() {
- let env = setup_env("lub_bound_bound_inverse_order", "");
+ let env = setup_env("lub_bound_bound_inverse_order", EMPTY_SOURCE_STR);
let t_rptr_bound1 = env.t_rptr_bound(1);
let t_rptr_bound2 = env.t_rptr_bound(2);
env.check_lub(env.t_fn([t_rptr_bound1, t_rptr_bound2], t_rptr_bound1),
#[test]
fn lub_free_free() {
- let env = setup_env("lub_free_free", "");
+ let env = setup_env("lub_free_free", EMPTY_SOURCE_STR);
let t_rptr_free1 = env.t_rptr_free(0, 1);
let t_rptr_free2 = env.t_rptr_free(0, 2);
let t_rptr_static = env.t_rptr_static();
#[test]
fn lub_returning_scope() {
- let env = setup_env("lub_returning_scope", "");
+ let env = setup_env("lub_returning_scope", EMPTY_SOURCE_STR);
let t_rptr_scope10 = env.t_rptr_scope(10);
let t_rptr_scope11 = env.t_rptr_scope(11);
env.check_no_lub(env.t_fn([], t_rptr_scope10),
env.t_fn([], t_rptr_scope11));
}
+#[test]
+fn glb_free_free_with_common_scope() {
+ let env = setup_env("glb_free_free", EMPTY_SOURCE_STR);
+ let t_rptr_free1 = env.t_rptr_free(0, 1);
+ let t_rptr_free2 = env.t_rptr_free(0, 2);
+ let t_rptr_scope = env.t_rptr_scope(0);
+ env.check_glb(env.t_fn([t_rptr_free1], env.t_int()),
+ env.t_fn([t_rptr_free2], env.t_int()),
+ env.t_fn([t_rptr_scope], env.t_int()));
+}
+
+#[test]
+fn glb_bound_bound() {
+ let env = setup_env("glb_bound_bound", EMPTY_SOURCE_STR);
+ let t_rptr_bound1 = env.t_rptr_bound(1);
+ let t_rptr_bound2 = env.t_rptr_bound(2);
+ env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()),
+ env.t_fn([t_rptr_bound2], env.t_int()),
+ env.t_fn([t_rptr_bound1], env.t_int()));
+}
+
+#[test]
+fn glb_bound_free() {
+ let env = setup_env("glb_bound_free", EMPTY_SOURCE_STR);
+ let t_rptr_bound1 = env.t_rptr_bound(1);
+ let t_rptr_free1 = env.t_rptr_free(0, 1);
+ env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()),
+ env.t_fn([t_rptr_free1], env.t_int()),
+ env.t_fn([t_rptr_bound1], env.t_int()));
+}
+
+#[test]
+fn glb_bound_static() {
+ let env = setup_env("glb_bound_static", EMPTY_SOURCE_STR);
+ let t_rptr_bound1 = env.t_rptr_bound(1);
+ let t_rptr_static = env.t_rptr_static();
+ env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()),
+ env.t_fn([t_rptr_static], env.t_int()),
+ env.t_fn([t_rptr_bound1], env.t_int()));
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::typeck::infer::integral::int_ty_set;
-use middle::typeck::infer::floating::float_ty_set;
-use middle::typeck::infer::unify::{redirect, root, var_value};
+use core::prelude::*;
-trait ToStr {
- fn to_str(cx: infer_ctxt) -> ~str;
+use middle::ty::{FnMeta, FnTyBase, FnSig, FnVid, Vid};
+use middle::ty;
+use middle::typeck::infer::{Bound, Bounds};
+use middle::typeck::infer::{IntVarValue, IntType, UintType};
+use middle::typeck::infer::InferCtxt;
+use middle::typeck::infer::unify::{Redirect, Root, VarValue};
+use util::ppaux::{mt_to_str, ty_to_str};
+use util::ppaux;
+
+use syntax::{ast, ast_util};
+
+use core::uint;
+use core::str;
+
+pub trait InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str;
}
-impl ty::t: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
+impl ty::t : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
ty_to_str(cx.tcx, self)
}
}
-impl ty::mt: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
- mt_to_str(cx.tcx, self)
+impl FnMeta : InferStr {
+ fn inf_str(_cx: @InferCtxt) -> ~str {
+ fmt!("%?", self)
}
}
-impl ty::Region: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
- util::ppaux::region_to_str(cx.tcx, self)
+impl FnSig : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
+ fmt!("(%s) -> %s",
+ str::connect(self.inputs.map(|a| a.ty.inf_str(cx)), ", "),
+ self.output.inf_str(cx))
}
}
-impl ty::FnTy: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
- ty::mk_fn(cx.tcx, self).to_str(cx)
+impl<M:InferStr> FnTyBase<M> : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
+ fmt!("%s%s", self.meta.inf_str(cx), self.sig.inf_str(cx))
+ }
+}
+
+impl ty::mt : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
+ mt_to_str(cx.tcx, self)
}
}
-impl<V:Copy ToStr> bound<V>: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
+impl ty::Region : InferStr {
+ fn inf_str(_cx: @InferCtxt) -> ~str {
+ fmt!("%?", self)
+ }
+}
+
+impl<V:InferStr> Bound<V> : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
match self {
- Some(ref v) => (*v).to_str(cx),
+ Some(ref v) => v.inf_str(cx),
None => ~"none"
}
}
}
-impl<T:Copy ToStr> bounds<T>: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
+impl<T:InferStr> Bounds<T> : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
fmt!("{%s <: %s}",
- self.lb.to_str(cx),
- self.ub.to_str(cx))
+ self.lb.inf_str(cx),
+ self.ub.inf_str(cx))
}
}
-impl int_ty_set: ToStr {
- fn to_str(_cx: infer_ctxt) -> ~str {
+impl<V:Vid ToStr, T:InferStr> VarValue<V, T> : InferStr {
+ fn inf_str(cx: @InferCtxt) -> ~str {
match self {
- int_ty_set(v) => uint::to_str(v, 10u)
+ Redirect(ref vid) => fmt!("Redirect(%s)", vid.to_str()),
+ Root(ref pt, rk) => fmt!("Root(%s, %s)", pt.inf_str(cx),
+ uint::to_str(rk, 10u))
}
}
}
-impl float_ty_set: ToStr {
- fn to_str(_cx: infer_ctxt) -> ~str {
+impl IntVarValue : InferStr {
+ fn inf_str(_cx: @InferCtxt) -> ~str {
match self {
- float_ty_set(v) => uint::to_str(v, 10u)
+ IntType(t) => ast_util::int_ty_to_str(t),
+ UintType(t) => ast_util::uint_ty_to_str(t)
}
}
}
-impl<V:Copy vid, T:Copy ToStr> var_value<V, T>: ToStr {
- fn to_str(cx: infer_ctxt) -> ~str {
- match self {
- redirect(ref vid) => fmt!("redirect(%s)", (*vid).to_str()),
- root(ref pt, rk) => fmt!("root(%s, %s)", (*pt).to_str(cx),
- uint::to_str(rk, 10u))
- }
+impl ast::float_ty : InferStr {
+ fn inf_str(_cx: @InferCtxt) -> ~str {
+ ast_util::float_ty_to_str(self)
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use middle::typeck::infer::combine::combine;
-use middle::typeck::infer::floating::*;
-use middle::typeck::infer::integral::*;
-use middle::typeck::infer::to_str::ToStr;
+use core::prelude::*;
+use middle::ty::Vid;
+use middle::ty;
+use middle::typeck::infer::{Bound, Bounds, cres, uok, ures};
+use middle::typeck::infer::combine::Combine;
+use middle::typeck::infer::InferCtxt;
+use middle::typeck::infer::to_str::InferStr;
+use util::common::{indent, indenter};
+
+use core::result;
use std::smallintmap::SmallIntMap;
-enum var_value<V:Copy, T:Copy> {
- redirect(V),
- root(T, uint),
+enum VarValue<V, T> {
+ Redirect(V),
+ Root(T, uint),
}
-struct vals_and_bindings<V:Copy, T:Copy> {
- vals: SmallIntMap<var_value<V, T>>,
- mut bindings: ~[(V, var_value<V, T>)],
+struct ValsAndBindings<V:Copy, T:Copy> {
+ vals: SmallIntMap<VarValue<V, T>>,
+ mut bindings: ~[(V, VarValue<V, T>)],
}
-struct node<V:Copy, T:Copy> {
+struct Node<V:Copy, T:Copy> {
root: V,
possible_types: T,
rank: uint,
}
-impl infer_ctxt {
- fn get<V:Copy vid Eq, T:Copy>(
- vb: &vals_and_bindings<V, T>, vid: V) -> node<V, T> {
+impl @InferCtxt {
+ fn get<V:Copy Eq Vid, T:Copy>(
+ vb: &ValsAndBindings<V, T>,
+ vid: V)
+ -> Node<V, T>
+ {
+ /*!
+ *
+ * Find the root node for `vid`. This uses the standard
+ * union-find algorithm with path compression:
+ * http://en.wikipedia.org/wiki/Disjoint-set_data_structure
+ */
let vid_u = vid.to_uint();
match vb.vals.find(vid_u) {
}
Some(ref var_val) => {
match (*var_val) {
- redirect(ref vid) => {
+ Redirect(ref vid) => {
let node = self.get(vb, (*vid));
if node.root.ne(vid) {
// Path compression
- vb.vals.insert((*vid).to_uint(), redirect(node.root));
+ vb.vals.insert(vid.to_uint(), Redirect(node.root));
}
node
}
- root(ref pt, rk) => {
- node {root: vid, possible_types: (*pt), rank: rk}
+ Root(ref pt, rk) => {
+ Node {root: vid, possible_types: *pt, rank: rk}
}
}
}
}
}
- fn set<V:Copy vid, T:Copy ToStr>(
- vb: &vals_and_bindings<V, T>, vid: V,
- +new_v: var_value<V, T>) {
+ fn set<V:Copy Vid ToStr, T:Copy InferStr>(
+ vb: &ValsAndBindings<V, T>,
+ vid: V,
+ +new_v: VarValue<V, T>)
+ {
+ /*!
+ *
+ * Sets the value for `vid` to `new_v`. `vid` MUST be a root node!
+ */
let old_v = vb.vals.get(vid.to_uint());
vb.bindings.push((vid, old_v));
vb.vals.insert(vid.to_uint(), new_v);
debug!("Updating variable %s from %s to %s",
- vid.to_str(), old_v.to_str(self), new_v.to_str(self));
- }
-}
-
-// Combines the two bounds into a more general bound.
-fn merge_bnd<C: combine>(
- self: &C, a: bound<ty::t>, b: bound<ty::t>,
- merge_op: fn(ty::t,ty::t) -> cres<ty::t>) -> cres<bound<ty::t>> {
-
- debug!("merge_bnd(%s,%s)",
- a.to_str(self.infcx()),
- b.to_str(self.infcx()));
- let _r = indenter();
-
- match (a, b) {
- (None, None) => Ok(None),
- (Some(_), None) => Ok(a),
- (None, Some(_)) => Ok(b),
- (Some(v_a), Some(v_b)) => {
- do merge_op(v_a, v_b).chain |v| {
- Ok(Some(v))
- }
- }
- }
-}
-
-fn merge_bnds<C: combine>(
- self: &C, a: bounds<ty::t>, b: bounds<ty::t>,
- lub: fn(ty::t,ty::t) -> cres<ty::t>,
- glb: fn(ty::t,ty::t) -> cres<ty::t>) -> cres<bounds<ty::t>> {
-
- let _r = indenter();
- do merge_bnd(self, a.ub, b.ub, glb).chain |ub| {
- debug!("glb of ubs %s and %s is %s",
- a.ub.to_str(self.infcx()),
- b.ub.to_str(self.infcx()),
- ub.to_str(self.infcx()));
- do merge_bnd(self, a.lb, b.lb, lub).chain |lb| {
- debug!("lub of lbs %s and %s is %s",
- a.lb.to_str(self.infcx()),
- b.lb.to_str(self.infcx()),
- lb.to_str(self.infcx()));
- Ok({lb: lb, ub: ub})
- }
- }
-}
-
-// Updates the bounds for the variable `v_id` to be the intersection
-// of `a` and `b`. That is, the new bounds for `v_id` will be
-// a bounds c such that:
-// c.ub <: a.ub
-// c.ub <: b.ub
-// a.lb <: c.lb
-// b.lb <: c.lb
-// If this cannot be achieved, the result is failure.
-
-fn set_var_to_merged_bounds<C: combine>(
- self: &C,
- v_id: ty::TyVid,
- a: bounds<ty::t>,
- b: bounds<ty::t>,
- rank: uint) -> ures {
-
- let vb = &self.infcx().ty_var_bindings;
-
- // Think of the two diamonds, we want to find the
- // intersection. There are basically four possibilities (you
- // can swap A/B in these pictures):
- //
- // A A
- // / \ / \
- // / B \ / B \
- // / / \ \ / / \ \
- // * * * * * / * *
- // \ \ / / \ / /
- // \ B / / \ / /
- // \ / * \ /
- // A \ / A
- // B
-
- debug!("merge(%s,%s,%s)",
- v_id.to_str(),
- a.to_str(self.infcx()),
- b.to_str(self.infcx()));
-
- // First, relate the lower/upper bounds of A and B.
- // Note that these relations *must* hold for us to
- // to be able to merge A and B at all, and relating
- // them explicitly gives the type inferencer more
- // information and helps to produce tighter bounds
- // when necessary.
- do indent {
- do bnds(self, a.lb, b.ub).then {
- do bnds(self, b.lb, a.ub).then {
- do merge_bnd(self, a.ub, b.ub,
- |x, y| self.glb().tys(x, y)).chain |ub| {
- do merge_bnd(self, a.lb, b.lb,
- |x, y| self.lub().tys(x, y)).chain |lb| {
- let bounds = {lb: lb, ub: ub};
- debug!("merge(%s): bounds=%s",
- v_id.to_str(),
- bounds.to_str(self.infcx()));
-
- // the new bounds must themselves
- // be relatable:
- do bnds(self, bounds.lb, bounds.ub).then {
- self.infcx().set(vb, v_id, root(bounds, rank));
- uok()
- }
- }
- }
- }
- }
- }
-}
-
-/// Ensure that variable A is a subtype of variable B. This is a
-/// subtle and tricky process, as described in detail at the top
-/// of infer.rs
-fn var_sub_var<C: combine>(self: &C,
- a_id: ty::TyVid,
- b_id: ty::TyVid) -> ures {
- let vb = &self.infcx().ty_var_bindings;
-
- // Need to make sub_id a subtype of sup_id.
- let nde_a = self.infcx().get(vb, a_id);
- let nde_b = self.infcx().get(vb, b_id);
- let a_id = nde_a.root;
- let b_id = nde_b.root;
- let a_bounds = nde_a.possible_types;
- let b_bounds = nde_b.possible_types;
-
- debug!("vars(%s=%s <: %s=%s)",
- a_id.to_str(), a_bounds.to_str(self.infcx()),
- b_id.to_str(), b_bounds.to_str(self.infcx()));
-
- if a_id == b_id { return uok(); }
-
- // If both A's UB and B's LB have already been bound to types,
- // see if we can make those types subtypes.
- match (a_bounds.ub, b_bounds.lb) {
- (Some(a_ub), Some(b_lb)) => {
- let r = self.infcx().try(|| self.sub().tys(a_ub, b_lb));
- match r {
- Ok(_ty) => return result::Ok(()),
- Err(_) => { /*fallthrough */ }
- }
- }
- _ => { /*fallthrough*/ }
- }
-
- // Otherwise, we need to merge A and B so as to guarantee that
- // A remains a subtype of B. Actually, there are other options,
- // but that's the route we choose to take.
-
- // Rank optimization
-
- // Make the node with greater rank the parent of the node with
- // smaller rank.
- if nde_a.rank > nde_b.rank {
- debug!("vars(): a has smaller rank");
- // a has greater rank, so a should become b's parent,
- // i.e., b should redirect to a.
- self.infcx().set(vb, b_id, redirect(a_id));
- set_var_to_merged_bounds(
- self, a_id, a_bounds, b_bounds, nde_a.rank)
- } else if nde_a.rank < nde_b.rank {
- debug!("vars(): b has smaller rank");
- // b has greater rank, so a should redirect to b.
- self.infcx().set(vb, a_id, redirect(b_id));
- set_var_to_merged_bounds(
- self, b_id, a_bounds, b_bounds, nde_b.rank)
- } else {
- debug!("vars(): a and b have equal rank");
- assert nde_a.rank == nde_b.rank;
- // If equal, just redirect one to the other and increment
- // the other's rank. We choose arbitrarily to redirect b
- // to a and increment a's rank.
- self.infcx().set(vb, b_id, redirect(a_id));
- set_var_to_merged_bounds(
- self, a_id, a_bounds, b_bounds, nde_a.rank + 1u
- )
- }
-}
-
-/// make variable a subtype of T
-fn var_sub_t<C: combine>(self: &C, a_id: ty::TyVid, b: ty::t) -> ures {
-
- let vb = &self.infcx().ty_var_bindings;
- let nde_a = self.infcx().get(vb, a_id);
- let a_id = nde_a.root;
- let a_bounds = nde_a.possible_types;
-
- debug!("var_sub_t(%s=%s <: %s)",
- a_id.to_str(),
- a_bounds.to_str(self.infcx()),
- b.to_str(self.infcx()));
- let b_bounds = {lb: None, ub: Some(b)};
- set_var_to_merged_bounds(self, a_id, a_bounds, b_bounds, nde_a.rank)
-}
-
-/// make T a subtype of variable
-fn t_sub_var<C: combine>(self: &C, a: ty::t, b_id: ty::TyVid) -> ures {
-
- let vb = &self.infcx().ty_var_bindings;
- let a_bounds = {lb: Some(a), ub: None};
- let nde_b = self.infcx().get(vb, b_id);
- let b_id = nde_b.root;
- let b_bounds = nde_b.possible_types;
-
- debug!("t_sub_var(%s <: %s=%s)",
- a.to_str(self.infcx()),
- b_id.to_str(),
- b_bounds.to_str(self.infcx()));
- set_var_to_merged_bounds(self, b_id, a_bounds, b_bounds, nde_b.rank)
-}
-
-fn bnds<C: combine>(
- self: &C, a: bound<ty::t>, b: bound<ty::t>) -> ures {
-
- debug!("bnds(%s <: %s)", a.to_str(self.infcx()), b.to_str(self.infcx()));
- do indent {
- match (a, b) {
- (None, None) |
- (Some(_), None) |
- (None, Some(_)) => {
- uok()
- }
- (Some(t_a), Some(t_b)) => {
- self.sub().tys(t_a, t_b).to_ures()
- }
- }
+ vid.to_str(), old_v.inf_str(self), new_v.inf_str(self));
}
-}
-
-// ______________________________________________________________________
-// Integral variables
-impl infer_ctxt {
- fn optimize_ranks<V:Copy vid Eq,T:Copy ToStr>(vb: &vals_and_bindings<V,T>,
- nde_a: node<V,T>,
- nde_b: node<V,T>,
- a_id: V,
- b_id: V,
- intersection: T) {
- if nde_a.rank > nde_b.rank {
- debug!("int_vars(): a has smaller rank");
+ fn unify<V:Copy Vid ToStr, T:Copy InferStr, R>(
+ vb: &ValsAndBindings<V, T>,
+ node_a: &Node<V, T>,
+ node_b: &Node<V, T>,
+ op: &fn(new_root: V, new_rank: uint) -> R
+ ) -> R {
+ // Rank optimization: if you don't know what it is, check
+ // out <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>
+
+ debug!("unify(node_a(id=%?, rank=%?), \
+ node_b(id=%?, rank=%?))",
+ node_a.root, node_a.rank,
+ node_b.root, node_b.rank);
+
+ if node_a.rank > node_b.rank {
// a has greater rank, so a should become b's parent,
// i.e., b should redirect to a.
- self.set(vb, a_id, root(intersection, nde_a.rank));
- self.set(vb, b_id, redirect(a_id));
- } else if nde_a.rank < nde_b.rank {
- debug!("int_vars(): b has smaller rank");
+ self.set(vb, node_b.root, Redirect(node_a.root));
+ op(node_a.root, node_a.rank)
+ } else if node_a.rank < node_b.rank {
// b has greater rank, so a should redirect to b.
- self.set(vb, b_id, root(intersection, nde_b.rank));
- self.set(vb, a_id, redirect(b_id));
+ self.set(vb, node_a.root, Redirect(node_b.root));
+ op(node_b.root, node_b.rank)
} else {
- debug!("int_vars(): a and b have equal rank");
- assert nde_a.rank == nde_b.rank;
- // If equal, just redirect one to the other and increment
- // the other's rank. We choose arbitrarily to redirect b
- // to a and increment a's rank.
- self.set(vb, a_id, root(intersection, nde_a.rank + 1u));
- self.set(vb, b_id, redirect(a_id));
- };
- }
-
- fn int_vars(a_id: ty::IntVid, b_id: ty::IntVid) -> ures {
- let vb = &self.int_var_bindings;
-
- let nde_a = self.get(vb, a_id);
- let nde_b = self.get(vb, b_id);
- let a_id = nde_a.root;
- let b_id = nde_b.root;
- let a_pt = nde_a.possible_types;
- let b_pt = nde_b.possible_types;
-
- // If we're already dealing with the same two variables,
- // there's nothing to do.
- if a_id == b_id { return uok(); }
-
- // Otherwise, take the intersection of the two sets of
- // possible types.
- let intersection = integral::intersection(a_pt, b_pt);
- if *intersection == INT_TY_SET_EMPTY {
- return Err(ty::terr_no_integral_type);
+ // If equal, redirect one to the other and increment the
+ // other's rank.
+ assert node_a.rank == node_b.rank;
+ self.set(vb, node_b.root, Redirect(node_a.root));
+ op(node_a.root, node_a.rank + 1)
}
-
- // Rank optimization
- self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection);
-
- uok()
}
- fn int_var_sub_t(a_id: ty::IntVid, b: ty::t) -> ures {
- assert ty::type_is_integral(b);
-
- let vb = &self.int_var_bindings;
- let nde_a = self.get(vb, a_id);
- let a_id = nde_a.root;
- let a_pt = nde_a.possible_types;
-
- let intersection =
- integral::intersection(a_pt,
- convert_integral_ty_to_int_ty_set(self.tcx, b));
- if *intersection == INT_TY_SET_EMPTY {
- return Err(ty::terr_no_integral_type);
- }
- self.set(vb, a_id, root(intersection, nde_a.rank));
- uok()
- }
-
- fn t_sub_int_var(a: ty::t, b_id: ty::IntVid) -> ures {
- assert ty::type_is_integral(a);
- let vb = &self.int_var_bindings;
-
- let nde_b = self.get(vb, b_id);
- let b_id = nde_b.root;
- let b_pt = nde_b.possible_types;
-
- let intersection =
- integral::intersection(b_pt,
- convert_integral_ty_to_int_ty_set(self.tcx, a));
- if *intersection == INT_TY_SET_EMPTY {
- return Err(ty::terr_no_integral_type);
- }
- self.set(vb, b_id, root(intersection, nde_b.rank));
- uok()
- }
-
-
}
// ______________________________________________________________________
-// Floating point variables
-
-impl infer_ctxt {
- fn float_vars(a_id: ty::FloatVid, b_id: ty::FloatVid) -> ures {
- let vb = &self.float_var_bindings;
-
- let nde_a = self.get(vb, a_id);
- let nde_b = self.get(vb, b_id);
- let a_id = nde_a.root;
- let b_id = nde_b.root;
- let a_pt = nde_a.possible_types;
- let b_pt = nde_b.possible_types;
+// Code to handle simple variables like ints, floats---anything that
+// doesn't have a subtyping relationship we need to worry about.
+
+impl @InferCtxt {
+ fn simple_vars<V:Copy Eq Vid ToStr, T:Copy Eq InferStr>(
+ vb: &ValsAndBindings<V, Option<T>>,
+ err: ty::type_err,
+ a_id: V,
+ b_id: V) -> ures
+ {
+ /*!
+ *
+ * Unifies two simple variables. Because simple variables do
+ * not have any subtyping relationships, if both variables
+ * have already been associated with a value, then those two
+ * values must be the same. */
+
+ let node_a = self.get(vb, a_id);
+ let node_b = self.get(vb, b_id);
+ let a_id = node_a.root;
+ let b_id = node_b.root;
- // If we're already dealing with the same two variables,
- // there's nothing to do.
if a_id == b_id { return uok(); }
- // Otherwise, take the intersection of the two sets of
- // possible types.
- let intersection = floating::intersection(a_pt, b_pt);
- if *intersection == FLOAT_TY_SET_EMPTY {
- return Err(ty::terr_no_floating_point_type);
- }
-
- // Rank optimization
- self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection);
+ let combined = match (&node_a.possible_types, &node_b.possible_types)
+ {
+ (&None, &None) => None,
+ (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(*v),
+ (&Some(ref v1), &Some(ref v2)) => {
+ if *v1 != *v2 { return Err(err); }
+ Some(*v1)
+ }
+ };
- uok()
+ self.unify(vb, &node_a, &node_b, |new_root, new_rank| {
+ self.set(vb, new_root, Root(combined, new_rank));
+ });
+ return uok();
}
- fn float_var_sub_t(a_id: ty::FloatVid, b: ty::t) -> ures {
- assert ty::type_is_fp(b);
-
- let vb = &self.float_var_bindings;
- let nde_a = self.get(vb, a_id);
- let a_id = nde_a.root;
- let a_pt = nde_a.possible_types;
-
- let intersection =
- floating::intersection(
- a_pt,
- convert_floating_point_ty_to_float_ty_set(self.tcx, b));
- if *intersection == FLOAT_TY_SET_EMPTY {
- return Err(ty::terr_no_floating_point_type);
+ fn simple_var_t<V:Copy Eq Vid ToStr, T:Copy Eq InferStr>(
+ vb: &ValsAndBindings<V, Option<T>>,
+ err: ty::type_err,
+ a_id: V,
+ b: T) -> ures
+ {
+ /*!
+ *
+ * Sets the value of the variable `a_id` to `b`. Because
+ * simple variables do not have any subtyping relationships,
+ * if `a_id` already has a value, it must be the same as
+ * `b`. */
+
+ let node_a = self.get(vb, a_id);
+ let a_id = node_a.root;
+
+ if node_a.possible_types.is_none() {
+ self.set(vb, a_id, Root(Some(b), node_a.rank));
+ return uok();
}
- self.set(vb, a_id, root(intersection, nde_a.rank));
- uok()
- }
-
- fn t_sub_float_var(a: ty::t, b_id: ty::FloatVid) -> ures {
- assert ty::type_is_fp(a);
- let vb = &self.float_var_bindings;
- let nde_b = self.get(vb, b_id);
- let b_id = nde_b.root;
- let b_pt = nde_b.possible_types;
-
- let intersection =
- floating::intersection(
- b_pt,
- convert_floating_point_ty_to_float_ty_set(self.tcx, a));
- if *intersection == FLOAT_TY_SET_EMPTY {
- return Err(ty::terr_no_floating_point_type);
+ if node_a.possible_types == Some(b) {
+ return uok();
}
- self.set(vb, b_id, root(intersection, nde_b.rank));
- uok()
+
+ return Err(err);
}
}
#[legacy_exports];
+use core::prelude::*;
+
use metadata::csearch;
use middle::pat_util::{pat_id_map, PatIdMap};
+use middle::resolve;
use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty};
use middle::ty::{ty_param_substs_and_ty, vstore_uniq};
use middle::ty;
use core::dvec::DVec;
use core::result::Result;
+use core::result;
+use core::vec;
use std::list::{List, Nil, Cons};
use std::list;
use std::map::HashMap;
export collect;
export coherence;
export deriving;
+export crate_ctxt;
+export write_ty_to_tcx, write_substs_to_tcx;
+export no_params;
+export isr_alist;
+export require_same_types;
+export lookup_def_ccx, lookup_def_tcx;
#[legacy_exports]
#[path = "check/mod.rs"]
type vtable_map = HashMap<ast::node_id, vtable_res>;
-type crate_ctxt_ = {// A mapping from method call sites to traits that have
- // that method.
- trait_map: resolve::TraitMap,
- method_map: method_map,
- vtable_map: vtable_map,
- coherence_info: @coherence::CoherenceInfo,
- tcx: ty::ctxt};
+struct crate_ctxt__ {
+ // A mapping from method call sites to traits that have that method.
+ trait_map: resolve::TraitMap,
+ method_map: method_map,
+ vtable_map: vtable_map,
+ coherence_info: @coherence::CoherenceInfo,
+ tcx: ty::ctxt
+}
-enum crate_ctxt {
- crate_ctxt_(crate_ctxt_)
+pub enum crate_ctxt {
+ crate_ctxt_(crate_ctxt__)
}
// Functions that write types into the node type table
fn require_same_types(
tcx: ty::ctxt,
- maybe_infcx: Option<infer::infer_ctxt>,
+ maybe_infcx: Option<@infer::InferCtxt>,
t1_is_expected: bool,
span: span,
t1: ty::t,
match tcx.items.find(main_id) {
Some(ast_map::node_item(it,_)) => {
match it.node {
- ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => {
+ ast::item_fn(_, _, ref ps, _)
+ if vec::is_not_empty(*ps) => {
tcx.sess.span_err(
main_span,
~"main function is not allowed \
crate: @ast::crate)
-> (method_map, vtable_map) {
- let ccx = @crate_ctxt_({trait_map: trait_map,
- method_map: std::map::HashMap(),
- vtable_map: std::map::HashMap(),
- coherence_info: @coherence::CoherenceInfo(),
- tcx: tcx
- });
+ let ccx = @crate_ctxt_(crate_ctxt__ {
+ trait_map: trait_map,
+ method_map: map::HashMap(),
+ vtable_map: map::HashMap(),
+ coherence_info: @coherence::CoherenceInfo(),
+ tcx: tcx
+ });
collect::collect_item_types(ccx, crate);
coherence::check_coherence(ccx, crate);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use middle::ty;
+
use core::result::Result;
+use core::result;
+use syntax::ast;
+use syntax::codemap::span;
use syntax::parse::token::special_idents;
trait region_scope {
#[license = "MIT"];
#[crate_type = "lib"];
-#[no_core];
-
#[legacy_modes];
#[legacy_exports];
-#[allow(vecs_implicitly_copyable)];
+#[allow(non_implicitly_copyable_typarams)];
#[allow(non_camel_case_types)];
#[allow(deprecated_mode)];
#[warn(deprecated_pattern)];
+#[no_core];
+
extern mod core(vers = "0.6");
+use core::*;
+
extern mod std(vers = "0.6");
extern mod syntax(vers = "0.6");
-use core::*;
-
/*
Alternate names for some modules.
#[legacy_exports]
mod base;
#[legacy_exports]
- mod alt;
+ mod _match;
#[legacy_exports]
mod uniq;
#[legacy_exports]
#[legacy_exports]
mod check_loop;
#[legacy_exports]
- mod check_alt;
+ mod check_match;
#[legacy_exports]
mod check_const;
#[legacy_exports]
#[legacy_exports]
mod upcall;
#[legacy_exports]
+ mod arm;
+ #[legacy_exports]
mod x86;
#[legacy_exports]
mod x86_64;
fn describe_debug_flags() {
io::println(fmt!("\nAvailable debug options:\n"));
for session::debugging_opts_map().each |pair| {
- let (name, desc, _) = *pair;
+ let (name, desc, _) = /*bad*/copy *pair;
io::println(fmt!(" -Z %-20s -- %s", name, desc));
}
}
// Don't display log spew by default. Can override with RUST_LOG.
logging::console_off();
- let mut args = *args;
+ let mut args = /*bad*/copy *args;
let binary = args.shift();
if args.is_empty() { usage(binary); return; }
let input = match vec::len(matches.free) {
0u => early_error(demitter, ~"no input filename given"),
1u => {
- let ifile = matches.free[0];
+ let ifile = /*bad*/copy matches.free[0];
if ifile == ~"-" {
let src = str::from_bytes(io::stdin().read_whole_stream());
str_input(src)
_ => early_error(demitter, ~"multiple input filenames provided")
};
- let sopts = build_session_options(binary, matches, demitter);
+ // XXX: Bad copy.
+ let sopts = build_session_options(copy binary, matches, demitter);
let sess = build_session(sopts, demitter);
let odir = getopts::opt_maybe_str(matches, ~"out-dir");
let odir = odir.map(|o| Path(*o));
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map::HashMap;
+use core::prelude::*;
+
use syntax::ast;
use syntax::codemap::{span};
use syntax::visit;
use syntax::print;
+use syntax;
+
+use core::option;
+use core::str;
+use core::vec;
+use std::map::HashMap;
fn indent<R>(op: fn() -> R) -> R {
// Use in conjunction with the log post-processor like `src/etc/indenter`
_ => visit::visit_expr(e, flag, v)
}
};
- let v = visit::mk_vt(@{visit_expr: visit_expr
- ,.. *visit::default_visitor()});
+ let v = visit::mk_vt(@visit::Visitor {
+ visit_expr: visit_expr,
+ .. *visit::default_visitor()});
visit::visit_block(b, rs, v);
return *rs;
}
*flag |= p(e);
visit::visit_expr(e, flag, v)
};
- let v = visit::mk_vt(@{visit_expr: visit_expr
- ,.. *visit::default_visitor()});
+ let v = visit::mk_vt(@visit::Visitor{
+ visit_expr: visit_expr,
+ .. *visit::default_visitor()});
visit::visit_block(b, rs, v);
return *rs;
}
)
}
-fn pluralize(n: uint, s: ~str) -> ~str {
+fn pluralize(n: uint, +s: ~str) -> ~str {
if n == 1 { s }
else { str::concat([s, ~"s"]) }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map::HashMap;
+use core::prelude::*;
+
use middle::ty;
use middle::ty::{arg, canon_mode};
use middle::ty::{bound_copy, bound_const, bound_durable, bound_owned,
bound_trait};
-use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
+use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid,
+ br_fresh};
use middle::ty::{ctxt, field, method};
use middle::ty::{mt, t, param_bound};
use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region};
use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
use middle::ty::{ty_ptr, ty_rec, ty_rptr, ty_self, ty_tup};
use middle::ty::{ty_type, ty_uniq, ty_uint, ty_infer};
-use middle::ty::{ty_unboxed_vec, vid};
+use middle::ty::{ty_unboxed_vec};
use metadata::encoder;
use syntax::codemap;
use syntax::codemap::span;
use syntax::print::pprust;
-use syntax::print::pprust::{path_to_str, proto_to_str,
- mode_to_str, purity_to_str,
- onceness_to_str};
+use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str};
use syntax::{ast, ast_util};
use syntax::ast_map;
+use core::str;
+use core::vec;
+use std::map::HashMap;
+
fn note_and_explain_region(cx: ctxt,
prefix: ~str,
region: ty::Region,
re_scope(node_id) => {
match cx.items.find(node_id) {
Some(ast_map::node_block(ref blk)) => {
- explain_span(cx, ~"block", (*blk).span)
+ explain_span(cx, "block", (*blk).span)
}
Some(ast_map::node_expr(expr)) => {
match expr.node {
- ast::expr_call(*) => explain_span(cx, ~"call", expr.span),
+ ast::expr_call(*) => explain_span(cx, "call", expr.span),
ast::expr_method_call(*) => {
- explain_span(cx, ~"method call", expr.span)
+ explain_span(cx, "method call", expr.span)
},
- ast::expr_match(*) => explain_span(cx, ~"match", expr.span),
- _ => explain_span(cx, ~"expression", expr.span)
+ ast::expr_match(*) => explain_span(cx, "match", expr.span),
+ _ => explain_span(cx, "expression", expr.span)
}
}
Some(_) | None => {
let prefix = match br {
br_anon(idx) => fmt!("the anonymous lifetime #%u defined on",
idx + 1),
+ br_fresh(_) => fmt!("an anonymous lifetime defined on"),
_ => fmt!("the lifetime %s as defined on",
bound_region_to_str(cx, br))
};
match cx.items.find(id) {
Some(ast_map::node_block(ref blk)) => {
- let (msg, opt_span) = explain_span(cx, ~"block", (*blk).span);
+ let (msg, opt_span) = explain_span(cx, "block", (*blk).span);
(fmt!("%s %s", prefix, msg), opt_span)
}
Some(_) | None => {
}
};
- fn explain_span(cx: ctxt, heading: ~str, span: span)
+ fn explain_span(cx: ctxt, heading: &str, span: span)
-> (~str, Option<span>)
{
let lo = cx.sess.codemap.lookup_char_pos_adj(span.lo);
}
fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
- bound_region_to_str_adorned(cx, ~"&", br, ~"")
+ bound_region_to_str_adorned(cx, "&", br, "")
}
-fn bound_region_to_str_adorned(cx: ctxt, prefix: ~str,
- br: bound_region, sep: ~str) -> ~str {
+fn bound_region_to_str_adorned(cx: ctxt, prefix: &str,
+ br: bound_region, sep: &str) -> ~str {
if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, sep); }
match br {
br_named(id) => fmt!("%s%s%s", prefix, cx.sess.str_of(id), sep),
br_self => fmt!("%sself%s", prefix, sep),
- br_anon(_) => prefix,
+ br_anon(_) => prefix.to_str(),
+ br_fresh(_) => prefix.to_str(),
br_cap_avoid(_, br) => bound_region_to_str_adorned(cx, prefix,
*br, sep)
}
cx.sess.codemap.span_to_str(expr.span))
}
ast::expr_match(*) => {
- fmt!("<alt at %s>",
+ fmt!("<match at %s>",
cx.sess.codemap.span_to_str(expr.span))
}
ast::expr_assign_op(*) |
// you should use `explain_region()` or, better yet,
// `note_and_explain_region()`
fn region_to_str(cx: ctxt, region: Region) -> ~str {
- region_to_str_adorned(cx, ~"&", region, ~"")
+ region_to_str_adorned(cx, "&", region, "")
}
-fn region_to_str_adorned(cx: ctxt, prefix: ~str,
- region: Region, sep: ~str) -> ~str {
+fn region_to_str_adorned(cx: ctxt, prefix: &str,
+ region: Region, sep: &str) -> ~str {
if cx.sess.verbose() {
return fmt!("%s%?%s", prefix, region, sep);
}
// to fit that into a short string. Hence the recommendation to use
// `explain_region()` or `note_and_explain_region()`.
match region {
- re_scope(_) => prefix,
+ re_scope(_) => prefix.to_str(),
re_bound(br) => bound_region_to_str_adorned(cx, prefix, br, sep),
re_free(_, br) => bound_region_to_str_adorned(cx, prefix, br, sep),
re_infer(ReSkolemized(_, br)) => {
bound_region_to_str_adorned(cx, prefix, br, sep)
}
- re_infer(ReVar(_)) => prefix,
+ re_infer(ReVar(_)) => prefix.to_str(),
re_static => fmt!("%sstatic%s", prefix, sep)
}
}
fn mt_to_str(cx: ctxt, m: mt) -> ~str {
let mstr = match m.mutbl {
- ast::m_mutbl => ~"mut ",
- ast::m_imm => ~"",
- ast::m_const => ~"const "
+ ast::m_mutbl => "mut ",
+ ast::m_imm => "",
+ ast::m_const => "const "
};
- return mstr + ty_to_str(cx, m.ty);
+ return fmt!("%s%s", mstr, ty_to_str(cx, m.ty));
}
fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
}
}
-fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> ~str {
+fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto,
+ followed_by_word: bool) -> &static/str {
match proto {
- ast::ProtoBare => ~"",
- ast::ProtoBox => ~"@",
- ast::ProtoBorrowed => ~"&",
- ast::ProtoUniq => ~"~",
+ ast::ProtoBare if followed_by_word => "extern ",
+ ast::ProtoBare => "extern",
+ ast::ProtoBox => "@",
+ ast::ProtoBorrowed => "&",
+ ast::ProtoUniq => "~",
}
}
pprust::expr_to_str(expr, cx.sess.intr()))
}
-fn tys_to_str(cx: ctxt, ts: ~[t]) -> ~str {
+fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
let tstrs = ts.map(|t| ty_to_str(cx, *t));
- fmt!("[%s]", str::connect(tstrs, ", "))
+ fmt!("(%s)", str::connect(tstrs, ", "))
}
fn bound_to_str(cx: ctxt, b: param_bound) -> ~str {
ty::param_bound_to_str(cx, &b)
}
+fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
+ fmt!("fn%s -> %s",
+ tys_to_str(cx, typ.inputs.map(|a| a.ty)),
+ ty_to_str(cx, typ.output))
+}
+
fn ty_to_str(cx: ctxt, typ: t) -> ~str {
fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
~str {
m == ty::default_arg_mode_for_ty(cx, ty) {
~""
} else {
- mode_to_str(ast::expl(m)) + ":"
+ mode_to_str(ast::expl(m)) + ~":"
}
}
};
- modestr + ty_to_str(cx, ty)
+ fmt!("%s%s", modestr, ty_to_str(cx, ty))
}
fn fn_to_str(cx: ctxt,
proto: ast::Proto,
purity: ast::purity,
onceness: ast::Onceness,
ident: Option<ast::ident>,
- inputs: ~[arg],
- output: t,
- cf: ast::ret_style) -> ~str {
+ inputs: &[arg],
+ output: t) -> ~str {
let mut s;
s = match purity {
ast::impure_fn => ~"",
- _ => purity_to_str(purity) + ~" "
+ _ => purity.to_str() + ~" "
};
s += match onceness {
ast::Many => ~"",
- ast::Once => onceness_to_str(onceness) + ~" "
+ ast::Once => onceness.to_str() + ~" "
};
- s += proto_ty_to_str(cx, proto);
+ s += proto_ty_to_str(cx, proto, true);
match (proto, region) {
(ast::ProtoBox, ty::re_static) |
s += ~")";
if ty::get(output).sty != ty_nil {
s += ~" -> ";
- match cf {
- ast::noreturn => { s += ~"!"; }
- ast::return_val => { s += ty_to_str(cx, output); }
+ if ty::type_is_bot(output) {
+ s += ~"!";
+ } else {
+ s += ty_to_str(cx, output);
}
}
return s;
m.fty.meta.onceness,
Some(m.ident),
m.fty.sig.inputs,
- m.fty.sig.output,
- m.fty.meta.ret_style) + ~";";
+ m.fty.sig.output) + ~";";
}
fn field_to_str(cx: ctxt, f: field) -> ~str {
return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt);
}
// if there is an id, print that instead of the structural type:
- for ty::type_def_id(typ).each |def_id| {
+ /*for ty::type_def_id(typ).each |def_id| {
// note that this typedef cannot have type parameters
return ast_map::path_to_str(ty::item_path(cx, *def_id),
cx.sess.intr());
- }
+ }*/
// pretty print the structural type representation:
- return match ty::get(typ).sty {
+ return match /*bad*/copy ty::get(typ).sty {
ty_nil => ~"()",
- ty_bot => ~"_|_",
+ ty_bot => ~"!",
ty_bool => ~"bool",
ty_int(ast::ty_i) => ~"int",
ty_int(ast::ty_char) => ~"char",
f.meta.onceness,
None,
f.sig.inputs,
- f.sig.output,
- f.meta.ret_style)
+ f.sig.output)
}
ty_infer(infer_ty) => infer_ty.to_str(),
ty_err => ~"[type error]",
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path, cx.sess.intr());
- parameterized(cx, base, (*substs).self_r, (*substs).tps)
+ parameterized(cx, base, substs.self_r, substs.tps)
}
ty_trait(did, ref substs, vs) => {
let path = ty::item_path(cx, did);
let base = ast_map::path_to_str(path, cx.sess.intr());
- let result = parameterized(cx, base, (*substs).self_r, (*substs).tps);
+ let result = parameterized(cx, base, substs.self_r, substs.tps);
vstore_ty_to_str(cx, result, vs)
}
ty_evec(mt, vs) => {
}
fn parameterized(cx: ctxt,
- base: ~str,
+ base: &str,
self_r: Option<ty::Region>,
- tps: ~[ty::t]) -> ~str {
+ tps: &[ty::t]) -> ~str {
let r_str = match self_r {
None => ~"",
if vec::len(tps) > 0u {
let strs = vec::map(tps, |t| ty_to_str(cx, *t));
- fmt!("%s%s<%s>", base, r_str, str::connect(strs, ~","))
+ fmt!("%s%s<%s>", base, r_str, str::connect(strs, ","))
} else {
fmt!("%s%s", base, r_str)
}
non-sendableness.
*/
+use core::prelude::*;
+
+use parse;
+use util;
+
+use core::oldcomm;
+use core::vec;
use rustc::back::link;
use rustc::driver::driver;
use rustc::driver::session::Session;
use syntax::codemap;
use syntax::diagnostic::handler;
use syntax::diagnostic;
+use syntax;
pub type Ctxt = {
ast: @ast::crate,
an AST's attributes.
*/
+use core::prelude::*;
+
+use core::str;
+use core::tuple;
+use core::vec;
use syntax::ast;
use syntax::attr;
-use core::tuple;
+use syntax::codemap;
+use syntax;
pub type CrateAttrs = {
name: Option<~str>
#[cfg(test)]
mod test {
- #[legacy_exports];
+ use syntax::ast;
+ use syntax;
+
+ use core::option::None;
- fn parse_attributes(+source: ~str) -> ~[ast::attribute] {
+ pub fn parse_attributes(+source: ~str) -> ~[ast::attribute] {
use syntax::parse;
use syntax::parse::parser;
use syntax::parse::attr::parser_attr;
of the natural-language documentation for a crate.
*/
+use core::prelude::*;
+
+use astsrv;
+use attr_parser;
use doc::ItemUtils;
+use doc;
use extract::to_str;
use fold::Fold;
+use fold;
+use pass::Pass;
+
+use core::option;
+use core::vec;
use syntax::ast;
use syntax::ast_map;
use std::map::HashMap;
+use std::par;
pub fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"attr",
f: run
}
}
-fn run(
+pub fn run(
srv: astsrv::Srv,
+doc: doc::Doc
) -> doc::Doc {
{
topmod: doc::ModDoc_({
item: {
- name: option::get_default(attrs.name, doc.topmod.name()),
+ name: option::get_or_default(attrs.name, doc.topmod.name()),
.. doc.topmod.item
},
.. *doc.topmod
#[cfg(test)]
mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+ use astsrv;
+ use attr_pass::run;
+ use doc;
+ use extract;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
run(srv, doc)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use result::Result;
+use core::prelude::*;
+
+use core::cmp;
+use core::os;
+use core::result;
+use core::run;
+use core::vec;
+use core::result::Result;
use std::getopts;
use std::cell::Cell;
pandoc_cmd: Option<~str>
};
-impl Config: Clone {
+pub impl Config: Clone {
fn clone(&self) -> Config { copy *self }
}
type ProgramOutput = fn~((&str), (&[~str])) ->
{status: int, out: ~str, err: ~str};
-fn mock_program_output(_prog: &str, _args: &[~str]) -> {
+pub fn mock_program_output(_prog: &str, _args: &[~str]) -> {
status: int, out: ~str, err: ~str
} {
{
parse_config_(args, run::program_output)
}
-fn parse_config_(
+pub fn parse_config_(
args: &[~str],
+program_output: ProgramOutput
) -> Result<Config, ~str> {
let output_dir = getopts::opt_maybe_str(matches, opt_output_dir());
let output_dir = output_dir.map(|s| Path(*s));
result::Ok({
- output_dir: output_dir.get_default(config.output_dir),
+ output_dir: output_dir.get_or_default(config.output_dir),
.. config
})
};
#[cfg(test)]
mod test {
- #[legacy_exports];
- fn parse_config(args: &[~str]) -> Result<Config, ~str> {
+ use config::{Config, mock_program_output, parse_config_};
+
+ use core::result::Result;
+
+ pub fn parse_config(args: &[~str]) -> Result<Config, ~str> {
parse_config_(args, mock_program_output)
}
}
* tests on this file
*/
+use core::prelude::*;
+
/// The base price of a muffin on a non-holiday
const price_of_a_muffin: float = 70f;
is interpreted as the brief description.
*/
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
+use doc;
use fold::Fold;
+use fold;
+use pass::Pass;
+
+use core::str;
+use core::vec;
+use std::par;
pub fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"desc_to_brief",
f: run
}
}
-fn run(
+pub fn run(
_srv: astsrv::Srv,
+doc: doc::Doc
) -> doc::Doc {
}
#[cfg(test)]
-mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+pub mod test {
+ use astsrv;
+ use attr_pass;
+ use desc_to_brief_pass::run;
+ use doc;
+ use extract;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
let doc = (attr_pass::mk_pass().f)(srv, doc);
//! The document model
+use core::prelude::*;
+
+use doc;
+use pass::Pass;
+
+use core::cmp;
+use core::option;
+use core::vec;
+
pub type AstId = int;
pub type Doc_ = {
//! Escapes text sequences
+use pass::Pass;
+use text_pass;
+
+use core::str;
+
pub fn mk_pass() -> Pass {
text_pass::mk_pass(~"escape", escape)
}
//! Converts the Rust AST to the rustdoc document model
-use syntax::ast;
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
-use task::local_data::local_data_get;
+use doc;
+
+use core::cast;
+use core::task::local_data::local_data_get;
+use core::vec;
+use syntax::ast;
+use syntax;
/* can't import macros yet, so this is copied from token.rs. See its comment
* there. */
mod test {
#[legacy_exports];
+ use astsrv;
+ use doc;
+ use extract::{extract, from_srv};
+ use parse;
+
+ use core::vec;
+
fn mk_doc(+source: ~str) -> doc::Doc {
let ast = parse::from_str(source);
extract(ast, ~"")
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use astsrv;
+use doc;
+use extract;
+use parse;
+use pass::Pass;
+
+use core::vec;
+use std::par;
+
pub struct Fold<T> {
ctxt: T,
fold_doc: FoldDoc<T>,
//! Build indexes as appropriate for the markdown pass
+use core::prelude::*;
+
+use astsrv;
+use config;
use doc::ItemUtils;
+use doc;
use fold::Fold;
+use fold;
+use markdown_pass;
+use markdown_writer;
+use pass::Pass;
+
+use core::str;
+use std::par;
pub fn mk_pass(+config: config::Config) -> Pass {
- {
+ Pass {
name: ~"markdown_index",
f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
run(srv, doc, config)
}
}
-fn run(
+pub fn run(
_srv: astsrv::Srv,
+doc: doc::Doc,
+config: config::Config
#[cfg(test)]
mod test {
- #[legacy_exports];
- fn mk_doc(output_style: config::OutputStyle, +source: ~str) -> doc::Doc {
+ use astsrv;
+ use attr_pass;
+ use config;
+ use desc_to_brief_pass;
+ use doc;
+ use extract;
+ use markdown_index_pass::run;
+ use path_pass;
+
+ use core::path::Path;
+
+ pub fn mk_doc(output_style: config::OutputStyle, +source: ~str)
+ -> doc::Doc {
do astsrv::from_str(source) |srv| {
let config = {
output_style: output_style,
//! Generate markdown from a document tree
+use core::prelude::*;
+
+use astsrv;
+use attr_pass;
+use config;
+use desc_to_brief_pass;
use doc::ItemUtils;
+use doc;
+use extract;
+use fold;
+use markdown_index_pass;
+use markdown_pass;
use markdown_writer::Writer;
use markdown_writer::WriterUtils;
use markdown_writer::WriterFactory;
+use markdown_writer;
+use page_pass;
+use pass::Pass;
+use path_pass;
+use sectionalize_pass;
+use sort_pass;
+use trim_pass;
+use unindent_pass;
+
+use core::iter;
+use core::oldcomm;
+use core::str;
+use core::vec;
+use std::par;
+use syntax;
pub fn mk_pass(+writer_factory: WriterFactory) -> Pass {
let f = fn~(move writer_factory,
run(srv, doc, copy writer_factory)
};
- {
+ Pass {
name: ~"markdown",
f: move f
}
w: Writer
};
-fn write_markdown(
+pub fn write_markdown(
+doc: doc::Doc,
+writer_factory: WriterFactory
) {
~"Enum"
}
doc::TraitTag(_) => {
- ~"Interface"
+ ~"Trait"
}
doc::ImplTag(_) => {
~"Implementation"
#[test]
fn should_write_trait_header() {
let markdown = test::render(~"trait i { fn a(); }");
- assert str::contains(markdown, ~"## Interface `i`");
+ assert str::contains(markdown, ~"## Trait `i`");
}
#[test]
#[cfg(test)]
mod test {
#[legacy_exports];
+
+ use astsrv;
+ use attr_pass;
+ use config;
+ use desc_to_brief_pass;
+ use doc;
+ use extract;
+ use markdown_index_pass;
+ use markdown_pass::{mk_pass, write_markdown};
+ use markdown_writer;
+ use path_pass;
+ use sectionalize_pass;
+ use trim_pass;
+ use tystr_pass;
+ use unindent_pass;
+
+ use core::oldcomm;
+ use core::path::Path;
+ use core::str;
+
fn render(+source: ~str) -> ~str {
let (srv, doc) = create_doc_srv(source);
let markdown = write_markdown_str_srv(srv, doc);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use config;
use doc::ItemUtils;
-use io::ReaderUtil;
+use doc;
+use pass::Pass;
+
+use core::io::ReaderUtil;
+use core::io;
+use core::libc;
+use core::oldcomm;
+use core::os;
+use core::pipes;
+use core::result;
+use core::run;
+use core::str;
+use core::task;
use std::future;
+use syntax;
pub enum WriteInstr {
Write(~str),
fn readclose(fd: libc::c_int) -> ~str {
// Copied from run::program_output
- let file = os::fdopen(fd);
- let reader = io::FILE_reader(file, false);
- let buf = io::with_bytes_writer(|writer| {
- let mut bytes = [mut 0, ..4096];
- while !reader.eof() {
- let nread = reader.read(bytes, bytes.len());
- writer.write(bytes.view(0, nread));
- }
- });
- os::fclose(file);
- str::from_bytes(buf)
+ unsafe {
+ let file = os::fdopen(fd);
+ let reader = io::FILE_reader(file, false);
+ let buf = io::with_bytes_writer(|writer| {
+ let mut bytes = [mut 0, ..4096];
+ while !reader.eof() {
+ let nread = reader.read(bytes, bytes.len());
+ writer.write(bytes.view(0, nread));
+ }
+ });
+ os::fclose(file);
+ str::from_bytes(buf)
+ }
}
fn generic_writer(+process: fn~(+markdown: ~str)) -> Writer {
#[cfg(test)]
mod test {
#[legacy_exports];
+
+ use astsrv;
+ use doc;
+ use extract;
+ use path_pass;
+
fn mk_doc(+name: ~str, +source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, name);
individual modules, pages for the crate, indexes, etc.
*/
+use core::prelude::*;
+
+use astsrv;
+use config;
use doc::{ItemUtils, PageUtils};
+use doc;
use fold::Fold;
-use syntax::ast;
+use fold;
+use pass::Pass;
+use sort_pass;
use util::NominalOp;
+use util;
+
+use core::oldcomm;
+use core::option;
+use core::vec;
+use syntax::ast;
pub fn mk_pass(output_style: config::OutputStyle) -> Pass {
- {
+ Pass {
name: ~"page",
f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
run(srv, doc, output_style)
}
}
-fn run(
+pub fn run(
_srv: astsrv::Srv,
+doc: doc::Doc,
output_style: config::OutputStyle
fn strip_mod(doc: doc::ModDoc) -> doc::ModDoc {
doc::ModDoc_({
- items: do vec::filter(doc.items) |item| {
+ items: do doc.items.filtered |item| {
match *item {
doc::ModTag(_) => false,
doc::NmodTag(_) => false,
#[cfg(test)]
mod test {
- #[legacy_exports];
- fn mk_doc_(
+ use astsrv;
+ use config;
+ use doc;
+ use extract;
+ use page_pass::run;
+
+ pub fn mk_doc_(
output_style: config::OutputStyle,
source: ~str
) -> doc::Doc {
}
}
- fn mk_doc(source: ~str) -> doc::Doc {
+ pub fn mk_doc(source: ~str) -> doc::Doc {
mk_doc_(config::DocPerMod, source)
}
}
//! AST-parsing helpers
+use core::prelude::*;
+
use rustc::driver::driver::{file_input, str_input};
use rustc::driver::driver;
use rustc::driver::session;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use astsrv;
+use doc;
+use extract;
+use time;
+
+use core::vec;
+
/// A single operation on the document model
-pub type Pass = {
+pub struct Pass {
name: ~str,
f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc
-};
+}
pub fn run_passes(
srv: astsrv::Srv,
let source = ~"";
do astsrv::from_str(source) |srv| {
let passes = ~[
- {
+ Pass {
name: ~"",
f: pass1
},
- {
+ Pass {
name: ~"",
f: pass2
}
//! Records the full path to items
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
+use doc;
+use extract;
use fold::Fold;
+use fold;
+use pass::Pass;
+
use syntax::ast;
pub fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"path",
f: run
}
//! Prunes things with the #[doc(hidden)] attribute
+use astsrv;
+use attr_parser;
use doc::ItemUtils;
+use doc;
use fold::Fold;
+use fold;
+use pass::Pass;
+
+use core::vec;
use std::map::HashMap;
pub fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"prune_hidden",
f: run
}
}
-fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
+pub fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
let fold = Fold {
fold_mod: fold_mod,
.. fold::default_any_fold(srv)
let doc = fold::default_any_fold_mod(fold, doc);
doc::ModDoc_({
- items: vec::filter(doc.items, |ItemTag| {
+ items: do doc.items.filtered |ItemTag| {
!is_hidden(fold.ctxt, ItemTag.item())
- }),
+ },
.. *doc
})
}
}
#[cfg(test)]
-mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+pub mod test {
+ use astsrv;
+ use doc;
+ use extract;
+ use prune_hidden_pass::run;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
run(srv, doc)
#[legacy_exports];
+use core::prelude::*;
+
+use astsrv;
+use doc;
use fold::Fold;
+use fold;
+use pass::Pass;
+
+use core::util;
+use core::vec;
+use syntax::ast;
export mk_pass;
+export run;
fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"prune_private",
f: run
}
}
-fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
+pub fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
let fold = Fold {
fold_mod: fold_mod,
.. fold::default_any_fold(srv)
let doc = fold::default_any_fold_mod(fold, doc);
doc::ModDoc_({
- items: do doc.items.filter |ItemTag| {
+ items: doc.items.filtered(|ItemTag| {
is_visible(fold.ctxt, ItemTag.item())
- },
+ }),
.. *doc
})
}
ast_map::node_item(item, _) => {
item.vis == ast::public
}
- _ => core::util::unreachable()
+ _ => util::unreachable()
}
}
}
}
#[cfg(test)]
-mod test {
+pub mod test {
+ use astsrv;
+ use doc;
+ use extract;
+ use prune_private_pass::run;
+
pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
//! Breaks rustdocs into sections according to their headers
+use core::prelude::*;
+
+use astsrv;
+use attr_pass;
use doc::ItemUtils;
+use doc;
+use extract;
use fold::Fold;
+use fold;
+use pass::Pass;
+
+use core::str;
+use core::vec;
+use std::par;
pub fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"sectionalize",
f: run
}
}
-fn run(_srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
+pub fn run(_srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
let fold = Fold {
fold_item: fold_item,
fold_trait: fold_trait,
}
#[cfg(test)]
-mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+pub mod test {
+ use astsrv;
+ use attr_pass;
+ use doc;
+ use extract;
+ use sectionalize_pass::run;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
let doc = (attr_pass::mk_pass().f)(srv, doc);
//! Sorts items by name
+use astsrv;
use doc::ItemUtils;
+use doc;
+use extract;
+use pass::Pass;
+use sort_pass;
pub fn mk_pass() -> Pass {
pure fn by_item_name(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool {
//! Sorts items by type
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
+use doc;
+use extract;
+use pass::Pass;
+use sort_pass;
pub fn mk_pass() -> Pass {
pure fn by_score(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool {
//! A general sorting pass
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
+use doc;
+use extract;
use fold::Fold;
-use std::sort;
+use fold;
+use pass::Pass;
use util::NominalOp;
+use std::sort;
+
pub type ItemLtEqOp = pure fn~(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool;
type ItemLtEq = NominalOp<ItemLtEqOp>;
pub fn mk_pass(name: ~str, +lteq: ItemLtEqOp) -> Pass {
- {
+ Pass {
name: name,
f: fn~(move lteq, srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
run(srv, doc, NominalOp { op: copy lteq })
//! Generic pass for performing an operation on all descriptions
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
+use doc;
use fold::Fold;
+use fold;
+use pass::Pass;
use util::NominalOp;
+use std::par;
+
pub fn mk_pass(name: ~str, +op: fn~(~str) -> ~str) -> Pass {
- {
+ Pass {
name: name,
f: fn~(move op, srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
run(srv, doc, copy op)
#[cfg(test)]
mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+ use astsrv;
+ use attr_pass;
+ use desc_to_brief_pass;
+ use doc;
+ use extract;
+ use sectionalize_pass;
+ use text_pass::mk_pass;
+
+ use core::str;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
let doc = (attr_pass::mk_pass().f)(srv, doc);
*/
use doc::ItemUtils;
+use doc;
+use pass::Pass;
+use text_pass;
+
+use core::option::Some;
+use core::str;
pub fn mk_pass() -> Pass {
text_pass::mk_pass(~"trim", |s| str::trim(s) )
#[cfg(test)]
mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+ use astsrv;
+ use attr_pass;
+ use doc;
+ use extract;
+ use trim_pass::mk_pass;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
let doc = (attr_pass::mk_pass().f)(srv, doc);
//! Pulls type information out of the AST and attaches it to the document
+use core::prelude::*;
+
+use astsrv;
use doc::ItemUtils;
+use doc;
+use extract::to_str;
+use extract;
use fold::Fold;
+use fold;
+use pass::Pass;
+
+use core::vec;
+use std::map::HashMap;
+use std::par;
use syntax::ast;
use syntax::print::pprust;
use syntax::ast_map;
-use std::map::HashMap;
-use extract::to_str;
pub fn mk_pass() -> Pass {
- {
+ Pass {
name: ~"tystr",
f: run
}
}
-fn run(
+pub fn run(
srv: astsrv::Srv,
+doc: doc::Doc
) -> doc::Doc {
}
#[cfg(test)]
-mod test {
- #[legacy_exports];
- fn mk_doc(source: ~str) -> doc::Doc {
+pub mod test {
+ use astsrv;
+ use doc;
+ use extract;
+ use tystr_pass::run;
+
+ pub fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
let doc = extract::from_srv(srv, ~"");
run(srv, doc)
middle of a line, and each of the following lines is indented.
*/
+use core::prelude::*;
+
+use pass::Pass;
+use text_pass;
+
+use core::str;
+use core::uint;
+use core::vec;
+use std::par;
+
pub fn mk_pass() -> Pass {
text_pass::mk_pass(~"unindent", unindent)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use core::oldcomm;
+use core::task;
+
// Just a named container for our op, so it can have impls
pub struct NominalOp<T> {
op: T
crate_type: session::unknown_crate,
binary: repl.binary,
addl_lib_search_paths: repl.lib_search_paths.map(|p| Path(*p)),
+ jit: true,
.. *session::basic_options()
};
repl.binary,
wrapped);
- debug!("parsing");
- let mut crate = driver::parse_input(sess, cfg, wrapped);
+ let outputs = driver::build_output_filenames(wrapped, &None, &None, sess);
+ debug!("calling compile_upto");
+ let {crate: crate, tcx: _} = driver::compile_upto(sess, cfg, wrapped,
+ driver::cu_everything,
+ Some(outputs));
+
let mut opt = None;
for crate.node.module.items.each |item| {
}
_ => fail
};
-
- debug!("configuration");
- crate = front::config::strip_unconfigured_items(crate);
-
- debug!("maybe building test harness");
- crate = front::test::modify_for_testing(sess, crate);
-
- debug!("expansion");
- crate = syntax::ext::expand::expand_crate(sess.parse_sess,
- sess.opts.cfg,
- crate);
-
- debug!("intrinsic injection");
- crate = front::intrinsic_inject::inject_intrinsic(sess, crate);
-
- debug!("core injection");
- crate = front::core_inject::maybe_inject_libcore_ref(sess, crate);
-
- debug!("building lint settings table");
- lint::build_settings_crate(sess, crate);
-
- debug!("ast indexing");
- let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate);
-
- debug!("external crate/lib resolution");
- creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
- sess.filesearch,
- session::sess_os_to_meta_os(sess.targ_cfg.os),
- sess.opts.static, sess.parse_sess.interner);
-
- debug!("language item collection");
- let lang_items = middle::lang_items::collect_language_items(crate, sess);
-
- debug!("resolution");
- let {def_map: def_map,
- exp_map2: exp_map2,
- trait_map: trait_map} = middle::resolve::resolve_crate(sess,
- lang_items,
- crate);
-
- debug!("freevar finding");
- let freevars = freevars::annotate_freevars(def_map, crate);
-
- debug!("region_resolution");
- let region_map = middle::region::resolve_crate(sess, def_map, crate);
-
- debug!("region paramaterization inference");
- let rp_set = middle::region::determine_rp_in_crate(sess, ast_map,
- def_map, crate);
-
- debug!("typechecking");
- let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
- region_map, rp_set, move lang_items, crate);
- let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map,
- crate);
-
- debug!("const marking");
- middle::const_eval::process_crate(crate, def_map, ty_cx);
-
- debug!("const checking");
- middle::check_const::check_crate(sess, crate, ast_map, def_map,
- method_map, ty_cx);
-
- debug!("privacy checking");
- middle::privacy::check_crate(ty_cx, &method_map, crate);
-
- debug!("loop checking");
- middle::check_loop::check_crate(ty_cx, crate);
-
- debug!("mode computation");
- middle::mode::compute_modes(ty_cx, method_map, crate);
-
- debug!("alt checking");
- middle::check_alt::check_crate(ty_cx, method_map, crate);
-
- debug!("liveness checking");
- let last_use_map = middle::liveness::check_crate(ty_cx,
- method_map, crate);
-
- debug!("borrow checking");
- let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx,
- method_map,
- last_use_map,
- crate);
-
- debug!("kind checking");
- kind::check_crate(ty_cx, method_map, last_use_map, crate);
-
- debug!("lint checking");
- lint::check_crate(ty_cx, crate);
-
- let maps = {mutbl_map: mutbl_map,
- root_map: root_map,
- last_use_map: last_use_map,
- method_map: method_map,
- vtable_map: vtable_map};
-
- debug!("translation");
- let path = ~path::GenericPath::from_str("<repl>");
- let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx,
- path,
- exp_map2, maps);
- let pm = llvm::LLVMCreatePassManager();
-
- debug!("executing jit");
- back::link::jit::exec(sess, pm, llmod, 0, false);
- llvm::LLVMDisposePassManager(pm);
-
debug!("recording input into repl history");
record(repl, blk, sess.parse_sess.interner)
}
io::println(
~":{\\n ..lines.. \\n:}\\n - execute multiline command\n" +
~":load <crate> ... - \
- loads given crates as dynamic libraries" +
+ loads given crates as dynamic libraries\n" +
~":clear - clear the screen\n" +
~":exit - exit from the repl\n" +
~":help - show this message");
* between tasks.
*/
-use private::{SharedMutableState, shared_mutable_state,
- clone_shared_mutable_state, unwrap_shared_mutable_state,
- get_shared_mutable_state, get_shared_immutable_state};
-use sync::{Mutex, mutex_with_condvars,
- RWlock, rwlock_with_condvars};
-
+use sync;
+use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars};
+
+use core::cast;
+use core::pipes;
+use core::prelude::*;
+use core::private::{SharedMutableState, shared_mutable_state};
+use core::private::{clone_shared_mutable_state, unwrap_shared_mutable_state};
+use core::private::{get_shared_mutable_state, get_shared_immutable_state};
+use core::ptr;
+use core::task;
+use core::util;
/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling.
pub struct Condvar { is_mutex: bool, failed: &mut bool, cond: &sync::Condvar }
#[cfg(test)]
mod tests {
#[legacy_exports];
- use comm::*;
+
+ use core::prelude::*;
+
+ use arc::*;
+ use arc;
+
+ use core::oldcomm::*;
+ use core::option::{Some, None};
+ use core::option;
+ use core::pipes;
+ use core::task;
+ use core::vec;
#[test]
fn manually_share_arc() {
#[forbid(deprecated_mode)];
+use arena;
+use list;
use list::{List, Cons, Nil};
-use cast::reinterpret_cast;
-use sys::TypeDesc;
-use libc::size_t;
+
+use core::at_vec;
+use core::cast::reinterpret_cast;
+use core::cast;
+use core::libc::size_t;
+use core::prelude::*;
+use core::ptr;
+use core::sys::TypeDesc;
+use core::sys;
+use core::uint;
+use core::vec;
#[abi = "rust-intrinsic"]
extern mod rusti {
extern mod rustrt {
#[rust_stack]
- fn rust_call_tydesc_glue(root: *u8, tydesc: *TypeDesc, field: size_t);
+ unsafe fn rust_call_tydesc_glue(root: *u8,
+ tydesc: *TypeDesc,
+ field: size_t);
}
// This probably belongs somewhere else. Needs to be kept in sync with
// changes to glue...
// except according to those terms.
#[forbid(deprecated_mode)];
-use io::Reader;
+
+use core::io::Reader;
+use core::iter;
+use core::str;
+use core::vec;
pub trait ToBase64 {
pure fn to_base64() -> ~str;
#[cfg(test)]
mod tests {
#[legacy_exports];
+
+ use core::str;
+
#[test]
fn test_to_base64() {
assert (~"").to_base64() == ~"";
--- /dev/null
+/*!
+
+A Big integer (signed version: BigInt, unsigned version: BigUint).
+
+A BigUint is represented as an array of BigDigits.
+A BigInt is a combination of BigUint and Sign.
+*/
+
+use core::cmp::{Eq, Ord};
+use core::num::{Num, Zero, One};
+use core::*;
+
+/**
+A BigDigit is a BigUint's composing element.
+
+A BigDigit is half the size of machine word size.
+*/
+#[cfg(target_arch = "x86")]
+#[cfg(target_arch = "arm")]
+pub type BigDigit = u16;
+
+/**
+A BigDigit is a BigUint's composing element.
+
+A BigDigit is half the size of machine word size.
+*/
+#[cfg(target_arch = "x86_64")]
+pub type BigDigit = u32;
+
+pub mod BigDigit {
+ use bigint::BigDigit;
+
+ #[cfg(target_arch = "x86")]
+ #[cfg(target_arch = "arm")]
+ pub const bits: uint = 16;
+
+ #[cfg(target_arch = "x86_64")]
+ pub const bits: uint = 32;
+
+ pub const base: uint = 1 << bits;
+ priv const hi_mask: uint = (-1 as uint) << bits;
+ priv const lo_mask: uint = (-1 as uint) >> bits;
+
+ priv pure fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit }
+ priv pure fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit }
+
+ /// Split one machine sized unsigned integer into two BigDigits.
+ pub pure fn from_uint(n: uint) -> (BigDigit, BigDigit) {
+ (get_hi(n), get_lo(n))
+ }
+
+ /// Join two BigDigits into one machine sized unsigned integer
+ pub pure fn to_uint(hi: BigDigit, lo: BigDigit) -> uint {
+ (lo as uint) | ((hi as uint) << bits)
+ }
+}
+
+/**
+A big unsigned integer type.
+
+A BigUint-typed value BigUint { data: @[a, b, c] } represents a number
+(a + b * BigDigit::base + c * BigDigit::base^2).
+*/
+pub struct BigUint {
+ priv data: ~[BigDigit]
+}
+
+impl BigUint : Eq {
+ pure fn eq(&self, other: &BigUint) -> bool { self.cmp(other) == 0 }
+ pure fn ne(&self, other: &BigUint) -> bool { self.cmp(other) != 0 }
+}
+
+impl BigUint : Ord {
+ pure fn lt(&self, other: &BigUint) -> bool { self.cmp(other) < 0 }
+ pure fn le(&self, other: &BigUint) -> bool { self.cmp(other) <= 0 }
+ pure fn ge(&self, other: &BigUint) -> bool { self.cmp(other) >= 0 }
+ pure fn gt(&self, other: &BigUint) -> bool { self.cmp(other) > 0 }
+}
+
+impl BigUint : ToStr {
+ pure fn to_str() -> ~str { self.to_str_radix(10) }
+}
+
+impl BigUint : from_str::FromStr {
+ static pure fn from_str(s: &str) -> Option<BigUint> {
+ BigUint::from_str_radix(s, 10)
+ }
+}
+
+impl BigUint : Shl<uint, BigUint> {
+ pure fn shl(&self, rhs: &uint) -> BigUint {
+ let n_unit = *rhs / BigDigit::bits;
+ let n_bits = *rhs % BigDigit::bits;
+ return self.shl_unit(n_unit).shl_bits(n_bits);
+ }
+}
+
+impl BigUint : Shr<uint, BigUint> {
+ pure fn shr(&self, rhs: &uint) -> BigUint {
+ let n_unit = *rhs / BigDigit::bits;
+ let n_bits = *rhs % BigDigit::bits;
+ return self.shr_unit(n_unit).shr_bits(n_bits);
+ }
+}
+
+impl BigUint : Zero {
+ static pure fn zero() -> BigUint { BigUint::new(~[]) }
+}
+
+impl BigUint : One {
+ static pub pure fn one() -> BigUint { BigUint::new(~[1]) }
+}
+
+impl BigUint : Num {
+ pure fn add(&self, other: &BigUint) -> BigUint {
+ let new_len = uint::max(self.data.len(), other.data.len());
+
+ let mut carry = 0;
+ let sum = do vec::from_fn(new_len) |i| {
+ let ai = if i < self.data.len() { self.data[i] } else { 0 };
+ let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ let (hi, lo) = BigDigit::from_uint(
+ (ai as uint) + (bi as uint) + (carry as uint)
+ );
+ carry = hi;
+ lo
+ };
+ if carry == 0 { return BigUint::new(sum) };
+ return BigUint::new(sum + [carry]);
+ }
+
+ pure fn sub(&self, other: &BigUint) -> BigUint {
+ let new_len = uint::max(self.data.len(), other.data.len());
+
+ let mut borrow = 0;
+ let diff = do vec::from_fn(new_len) |i| {
+ let ai = if i < self.data.len() { self.data[i] } else { 0 };
+ let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ let (hi, lo) = BigDigit::from_uint(
+ (BigDigit::base) +
+ (ai as uint) - (bi as uint) - (borrow as uint)
+ );
+ /*
+ hi * (base) + lo == 1*(base) + ai - bi - borrow
+ => ai - bi - borrow < 0 <=> hi == 0
+ */
+ borrow = if hi == 0 { 1 } else { 0 };
+ lo
+ };
+
+ assert borrow == 0; // <=> assert (self >= other);
+ return BigUint::new(diff);
+ }
+
+ pure fn mul(&self, other: &BigUint) -> BigUint {
+ if self.is_zero() || other.is_zero() { return Zero::zero(); }
+
+ let s_len = self.data.len(), o_len = other.data.len();
+ if s_len == 1 { return mul_digit(other, self.data[0]); }
+ if o_len == 1 { return mul_digit(self, other.data[0]); }
+
+ // Using Karatsuba multiplication
+ // (a1 * base + a0) * (b1 * base + b0)
+ // = a1*b1 * base^2 +
+ // (a1*b1 + a0*b0 - (a1-b0)*(b1-a0)) * base +
+ // a0*b0
+ let half_len = uint::max(s_len, o_len) / 2;
+ let (sHi, sLo) = cut_at(self, half_len);
+ let (oHi, oLo) = cut_at(other, half_len);
+
+ let ll = sLo * oLo;
+ let hh = sHi * oHi;
+ let mm = {
+ let (s1, n1) = sub_sign(sHi, sLo);
+ let (s2, n2) = sub_sign(oHi, oLo);
+ if s1 * s2 < 0 {
+ hh + ll + (n1 * n2)
+ } else if s1 * s2 > 0 {
+ hh + ll - (n1 * n2)
+ } else {
+ hh + ll
+ }
+ };
+
+ return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2);
+
+ pure fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
+ if n == 0 { return Zero::zero(); }
+ if n == 1 { return copy *a; }
+
+ let mut carry = 0;
+ let prod = do vec::map(a.data) |ai| {
+ let (hi, lo) = BigDigit::from_uint(
+ (*ai as uint) * (n as uint) + (carry as uint)
+ );
+ carry = hi;
+ lo
+ };
+ if carry == 0 { return BigUint::new(prod) };
+ return BigUint::new(prod + [carry]);
+ }
+
+ pure fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
+ let mid = uint::min(a.data.len(), n);
+ return (BigUint::from_slice(vec::view(a.data, mid, a.data.len())),
+ BigUint::from_slice(vec::view(a.data, 0, mid)));
+ }
+
+ pure fn sub_sign(a: BigUint, b: BigUint) -> (int, BigUint) {
+ match a.cmp(&b) {
+ s if s < 0 => (s, b - a),
+ s if s > 0 => (s, a - b),
+ _ => (0, Zero::zero())
+ }
+ }
+ }
+
+ pure fn div(&self, other: &BigUint) -> BigUint {
+ let (d, _) = self.divmod(other);
+ return d;
+ }
+ pure fn modulo(&self, other: &BigUint) -> BigUint {
+ let (_, m) = self.divmod(other);
+ return m;
+ }
+
+ pure fn neg(&self) -> BigUint { fail }
+
+ pure fn to_int(&self) -> int {
+ uint::min(self.to_uint(), int::max_value as uint) as int
+ }
+
+ static pure fn from_int(n: int) -> BigUint {
+ if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) }
+ }
+}
+
+pub impl BigUint {
+ /// Creates and initializes an BigUint.
+ static pub pure fn new(v: ~[BigDigit]) -> BigUint {
+ // omit trailing zeros
+ let new_len = v.rposition(|n| *n != 0).map_default(0, |p| *p + 1);
+
+ if new_len == v.len() { return BigUint { data: v }; }
+ let mut v = v;
+ unsafe { v.truncate(new_len); }
+ return BigUint { data: v };
+ }
+
+ /// Creates and initializes an BigUint.
+ static pub pure fn from_uint(n: uint) -> BigUint {
+ match BigDigit::from_uint(n) {
+ (0, 0) => Zero::zero(),
+ (0, n0) => BigUint::new(~[n0]),
+ (n1, n0) => BigUint::new(~[n0, n1])
+ }
+ }
+
+ /// Creates and initializes an BigUint.
+ static pub pure fn from_slice(slice: &[BigDigit]) -> BigUint {
+ return BigUint::new(vec::from_slice(slice));
+ }
+
+ /// Creates and initializes an BigUint.
+ static pub pure fn from_str_radix(s: &str, radix: uint)
+ -> Option<BigUint> {
+ BigUint::parse_bytes(str::to_bytes(s), radix)
+ }
+
+ /// Creates and initializes an BigUint.
+ static pub pure fn parse_bytes(buf: &[u8], radix: uint)
+ -> Option<BigUint> {
+ let (base, unit_len) = get_radix_base(radix);
+ let base_num: BigUint = BigUint::from_uint(base);
+
+ let mut end = buf.len();
+ let mut n: BigUint = Zero::zero();
+ let mut power: BigUint = One::one();
+ loop {
+ let start = uint::max(end, unit_len) - unit_len;
+ match uint::parse_bytes(vec::view(buf, start, end), radix) {
+ Some(d) => n += BigUint::from_uint(d) * power,
+ None => return None
+ }
+ if end <= unit_len {
+ return Some(n);
+ }
+ end -= unit_len;
+ power *= base_num;
+ }
+ }
+
+ pure fn abs(&self) -> BigUint { copy *self }
+
+ /// Compare two BigUint value.
+ pure fn cmp(&self, other: &BigUint) -> int {
+ let s_len = self.data.len(), o_len = other.data.len();
+ if s_len < o_len { return -1; }
+ if s_len > o_len { return 1; }
+
+ for vec::rev_eachi(self.data) |i, elm| {
+ match (*elm, other.data[i]) {
+ (l, r) if l < r => return -1,
+ (l, r) if l > r => return 1,
+ _ => loop
+ };
+ }
+ return 0;
+ }
+
+ pure fn divmod(&self, other: &BigUint) -> (BigUint, BigUint) {
+ if other.is_zero() { fail }
+ if self.is_zero() { return (Zero::zero(), Zero::zero()); }
+ if *other == One::one() { return (copy *self, Zero::zero()); }
+
+ match self.cmp(other) {
+ s if s < 0 => return (Zero::zero(), copy *self),
+ 0 => return (One::one(), Zero::zero()),
+ _ => {} // Do nothing
+ }
+
+ let mut shift = 0;
+ let mut n = other.data.last();
+ while n < (1 << BigDigit::bits - 2) {
+ n <<= 1;
+ shift += 1;
+ }
+ assert shift < BigDigit::bits;
+ let (d, m) = divmod_inner(self << shift, other << shift);
+ return (d, m >> shift);
+
+ pure fn divmod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
+ let mut r = a;
+ let mut d = Zero::zero::<BigUint>();
+ let mut n = 1;
+ while r >= b {
+ let mut (d0, d_unit, b_unit) = div_estimate(&r, &b, n);
+ let mut prod = b * d0;
+ while prod > r {
+ d0 -= d_unit;
+ prod -= b_unit;
+ }
+ if d0.is_zero() {
+ n = 2;
+ loop;
+ }
+ n = 1;
+ d += d0;
+ r -= prod;
+ }
+ return (d, r);
+ }
+
+ pure fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
+ -> (BigUint, BigUint, BigUint) {
+ if a.data.len() < n {
+ return (Zero::zero(), Zero::zero(), copy *a);
+ }
+
+ let an = vec::view(a.data, a.data.len() - n, a.data.len());
+ let bn = b.data.last();
+ let mut d = ~[];
+ let mut carry = 0;
+ for vec::rev_each(an) |elt| {
+ let ai = BigDigit::to_uint(carry, *elt);
+ let di = ai / (bn as uint);
+ assert di < BigDigit::base;
+ carry = (ai % (bn as uint)) as BigDigit;
+ d = ~[di as BigDigit] + d;
+ }
+
+ let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
+ if shift == 0 {
+ return (BigUint::new(d), One::one(), copy *b);
+ }
+ return (BigUint::from_slice(d).shl_unit(shift),
+ One::one::<BigUint>().shl_unit(shift),
+ b.shl_unit(shift));
+ }
+ }
+
+ pure fn quot(&self, other: &BigUint) -> BigUint {
+ let (q, _) = self.quotrem(other);
+ return q;
+ }
+ pure fn rem(&self, other: &BigUint) -> BigUint {
+ let (_, r) = self.quotrem(other);
+ return r;
+ }
+ pure fn quotrem(&self, other: &BigUint) -> (BigUint, BigUint) {
+ self.divmod(other)
+ }
+
+ pure fn is_zero(&self) -> bool { self.data.is_empty() }
+ pure fn is_not_zero(&self) -> bool { self.data.is_not_empty() }
+ pure fn is_positive(&self) -> bool { self.is_not_zero() }
+ pure fn is_negative(&self) -> bool { false }
+ pure fn is_nonpositive(&self) -> bool { self.is_zero() }
+ pure fn is_nonnegative(&self) -> bool { true }
+
+ pure fn to_uint(&self) -> uint {
+ match self.data.len() {
+ 0 => 0,
+ 1 => self.data[0] as uint,
+ 2 => BigDigit::to_uint(self.data[1], self.data[0]),
+ _ => uint::max_value
+ }
+ }
+
+ pure fn to_str_radix(&self, radix: uint) -> ~str {
+ assert 1 < radix && radix <= 16;
+ let (base, max_len) = get_radix_base(radix);
+ if base == BigDigit::base {
+ return fill_concat(self.data, radix, max_len)
+ }
+ return fill_concat(convert_base(copy *self, base), radix, max_len);
+
+ pure fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
+ let divider = BigUint::from_uint(base);
+ let mut result = ~[];
+ let mut r = n;
+ while r > divider {
+ let (d, r0) = r.divmod(÷r);
+ result += [r0.to_uint() as BigDigit];
+ r = d;
+ }
+ if r.is_not_zero() {
+ result += [r.to_uint() as BigDigit];
+ }
+ return result;
+ }
+
+ pure fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
+ if v.is_empty() { return ~"0" }
+ str::trim_left_chars(str::concat(vec::reversed(v).map(|n| {
+ let s = uint::to_str(*n as uint, radix);
+ str::from_chars(vec::from_elem(l - s.len(), '0')) + s
+ })), ['0'])
+ }
+ }
+
+ priv pure fn shl_unit(self, n_unit: uint) -> BigUint {
+ if n_unit == 0 || self.is_zero() { return self; }
+
+ return BigUint::new(vec::from_elem(n_unit, 0) + self.data);
+ }
+
+ priv pure fn shl_bits(self, n_bits: uint) -> BigUint {
+ if n_bits == 0 || self.is_zero() { return self; }
+
+ let mut carry = 0;
+ let shifted = do vec::map(self.data) |elem| {
+ let (hi, lo) = BigDigit::from_uint(
+ (*elem as uint) << n_bits | (carry as uint)
+ );
+ carry = hi;
+ lo
+ };
+ if carry == 0 { return BigUint::new(shifted); }
+ return BigUint::new(shifted + [carry]);
+ }
+
+ priv pure fn shr_unit(self, n_unit: uint) -> BigUint {
+ if n_unit == 0 { return self; }
+ if self.data.len() < n_unit { return Zero::zero(); }
+ return BigUint::from_slice(
+ vec::view(self.data, n_unit, self.data.len())
+ );
+ }
+
+ priv pure fn shr_bits(self, n_bits: uint) -> BigUint {
+ if n_bits == 0 || self.data.is_empty() { return self; }
+
+ let mut borrow = 0;
+ let mut shifted = ~[];
+ for vec::rev_each(self.data) |elem| {
+ shifted = ~[(*elem >> n_bits) | borrow] + shifted;
+ borrow = *elem << (uint::bits - n_bits);
+ }
+ return BigUint::new(shifted);
+ }
+}
+
+#[cfg(target_arch = "x86_64")]
+priv pure fn get_radix_base(radix: uint) -> (uint, uint) {
+ assert 1 < radix && radix <= 16;
+ match radix {
+ 2 => (4294967296, 32),
+ 3 => (3486784401, 20),
+ 4 => (4294967296, 16),
+ 5 => (1220703125, 13),
+ 6 => (2176782336, 12),
+ 7 => (1977326743, 11),
+ 8 => (1073741824, 10),
+ 9 => (3486784401, 10),
+ 10 => (1000000000, 9),
+ 11 => (2357947691, 9),
+ 12 => (429981696, 8),
+ 13 => (815730721, 8),
+ 14 => (1475789056, 8),
+ 15 => (2562890625, 8),
+ 16 => (4294967296, 8),
+ _ => fail
+ }
+}
+
+#[cfg(target_arch = "arm")]
+#[cfg(target_arch = "x86")]
+priv pure fn get_radix_base(radix: uint) -> (uint, uint) {
+ assert 1 < radix && radix <= 16;
+ match radix {
+ 2 => (65536, 16),
+ 3 => (59049, 10),
+ 4 => (65536, 8),
+ 5 => (15625, 6),
+ 6 => (46656, 6),
+ 7 => (16807, 5),
+ 8 => (32768, 5),
+ 9 => (59049, 5),
+ 10 => (10000, 4),
+ 11 => (14641, 4),
+ 12 => (20736, 4),
+ 13 => (28561, 4),
+ 14 => (38416, 4),
+ 15 => (50625, 4),
+ 16 => (65536, 4),
+ _ => fail
+ }
+}
+
+/// A Sign is a BigInt's composing element.
+pub enum Sign { Minus, Zero, Plus }
+
+impl Sign : Eq {
+ pure fn eq(&self, other: &Sign) -> bool { self.cmp(other) == 0 }
+ pure fn ne(&self, other: &Sign) -> bool { self.cmp(other) != 0 }
+}
+
+impl Sign : Ord {
+ pure fn lt(&self, other: &Sign) -> bool { self.cmp(other) < 0 }
+ pure fn le(&self, other: &Sign) -> bool { self.cmp(other) <= 0 }
+ pure fn ge(&self, other: &Sign) -> bool { self.cmp(other) >= 0 }
+ pure fn gt(&self, other: &Sign) -> bool { self.cmp(other) > 0 }
+}
+
+pub impl Sign {
+ /// Compare two Sign.
+ pure fn cmp(&self, other: &Sign) -> int {
+ match (*self, *other) {
+ (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => 0,
+ (Minus, Zero) | (Minus, Plus) | (Zero, Plus) => -1,
+ _ => 1
+ }
+ }
+
+ /// Negate Sign value.
+ pure fn neg(&self) -> Sign {
+ match *self {
+ Minus => Plus,
+ Zero => Zero,
+ Plus => Minus
+ }
+ }
+}
+
+/// A big signed integer type.
+pub struct BigInt {
+ priv sign: Sign,
+ priv data: BigUint
+}
+
+impl BigInt : Eq {
+ pure fn eq(&self, other: &BigInt) -> bool { self.cmp(other) == 0 }
+ pure fn ne(&self, other: &BigInt) -> bool { self.cmp(other) != 0 }
+}
+
+impl BigInt : Ord {
+ pure fn lt(&self, other: &BigInt) -> bool { self.cmp(other) < 0 }
+ pure fn le(&self, other: &BigInt) -> bool { self.cmp(other) <= 0 }
+ pure fn ge(&self, other: &BigInt) -> bool { self.cmp(other) >= 0 }
+ pure fn gt(&self, other: &BigInt) -> bool { self.cmp(other) > 0 }
+}
+
+impl BigInt : ToStr {
+ pure fn to_str() -> ~str { self.to_str_radix(10) }
+}
+
+impl BigInt : from_str::FromStr {
+ static pure fn from_str(s: &str) -> Option<BigInt> {
+ BigInt::from_str_radix(s, 10)
+ }
+}
+
+impl BigInt : Shl<uint, BigInt> {
+ pure fn shl(&self, rhs: &uint) -> BigInt {
+ BigInt::from_biguint(self.sign, self.data << *rhs)
+ }
+}
+
+impl BigInt : Shr<uint, BigInt> {
+ pure fn shr(&self, rhs: &uint) -> BigInt {
+ BigInt::from_biguint(self.sign, self.data >> *rhs)
+ }
+}
+
+impl BigInt : Zero {
+ static pub pure fn zero() -> BigInt {
+ BigInt::from_biguint(Zero, Zero::zero())
+ }
+}
+
+impl BigInt : One {
+ static pub pure fn one() -> BigInt {
+ BigInt::from_biguint(Plus, One::one())
+ }
+}
+
+impl BigInt : Num {
+ pure fn add(&self, other: &BigInt) -> BigInt {
+ match (self.sign, other.sign) {
+ (Zero, _) => copy *other,
+ (_, Zero) => copy *self,
+ (Plus, Plus) => BigInt::from_biguint(Plus,
+ self.data + other.data),
+ (Plus, Minus) => self - (-*other),
+ (Minus, Plus) => other - (-*self),
+ (Minus, Minus) => -((-self) + (-*other))
+ }
+ }
+ pure fn sub(&self, other: &BigInt) -> BigInt {
+ match (self.sign, other.sign) {
+ (Zero, _) => -other,
+ (_, Zero) => copy *self,
+ (Plus, Plus) => match self.data.cmp(&other.data) {
+ s if s < 0 =>
+ BigInt::from_biguint(Minus, other.data - self.data),
+ s if s > 0 =>
+ BigInt::from_biguint(Plus, self.data - other.data),
+ _ =>
+ Zero::zero()
+ },
+ (Plus, Minus) => self + (-*other),
+ (Minus, Plus) => -((-self) + *other),
+ (Minus, Minus) => (-other) - (-*self)
+ }
+ }
+ pure fn mul(&self, other: &BigInt) -> BigInt {
+ match (self.sign, other.sign) {
+ (Zero, _) | (_, Zero) => Zero::zero(),
+ (Plus, Plus) | (Minus, Minus) => {
+ BigInt::from_biguint(Plus, self.data * other.data)
+ },
+ (Plus, Minus) | (Minus, Plus) => {
+ BigInt::from_biguint(Minus, self.data * other.data)
+ }
+ }
+ }
+ pure fn div(&self, other: &BigInt) -> BigInt {
+ let (d, _) = self.divmod(other);
+ return d;
+ }
+ pure fn modulo(&self, other: &BigInt) -> BigInt {
+ let (_, m) = self.divmod(other);
+ return m;
+ }
+ pure fn neg(&self) -> BigInt {
+ BigInt::from_biguint(self.sign.neg(), copy self.data)
+ }
+
+ pure fn to_int(&self) -> int {
+ match self.sign {
+ Plus => uint::min(self.to_uint(), int::max_value as uint) as int,
+ Zero => 0,
+ Minus => uint::min((-self).to_uint(),
+ (int::max_value as uint) + 1) as int
+ }
+ }
+
+ static pure fn from_int(n: int) -> BigInt {
+ if n > 0 {
+ return BigInt::from_biguint(Plus, BigUint::from_uint(n as uint));
+ }
+ if n < 0 {
+ return BigInt::from_biguint(
+ Minus, BigUint::from_uint(uint::max_value - (n as uint) + 1)
+ );
+ }
+ return Zero::zero();
+ }
+}
+
+pub impl BigInt {
+ /// Creates and initializes an BigInt.
+ static pub pure fn new(sign: Sign, v: ~[BigDigit]) -> BigInt {
+ BigInt::from_biguint(sign, BigUint::new(v))
+ }
+
+ /// Creates and initializes an BigInt.
+ static pub pure fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
+ if sign == Zero || data.is_zero() {
+ return BigInt { sign: Zero, data: Zero::zero() };
+ }
+ return BigInt { sign: sign, data: data };
+ }
+
+ /// Creates and initializes an BigInt.
+ static pub pure fn from_uint(n: uint) -> BigInt {
+ if n == 0 { return Zero::zero(); }
+ return BigInt::from_biguint(Plus, BigUint::from_uint(n));
+ }
+
+ /// Creates and initializes an BigInt.
+ static pub pure fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
+ BigInt::from_biguint(sign, BigUint::from_slice(slice))
+ }
+
+ /// Creates and initializes an BigInt.
+ static pub pure fn from_str_radix(s: &str, radix: uint)
+ -> Option<BigInt> {
+ BigInt::parse_bytes(str::to_bytes(s), radix)
+ }
+
+ /// Creates and initializes an BigInt.
+ static pub pure fn parse_bytes(buf: &[u8], radix: uint)
+ -> Option<BigInt> {
+ if buf.is_empty() { return None; }
+ let mut sign = Plus;
+ let mut start = 0;
+ if buf[0] == ('-' as u8) {
+ sign = Minus;
+ start = 1;
+ }
+ return BigUint::parse_bytes(vec::view(buf, start, buf.len()), radix)
+ .map(|bu| BigInt::from_biguint(sign, *bu));
+ }
+
+ pure fn abs(&self) -> BigInt {
+ BigInt::from_biguint(Plus, copy self.data)
+ }
+
+ pure fn cmp(&self, other: &BigInt) -> int {
+ let ss = self.sign, os = other.sign;
+ if ss < os { return -1; }
+ if ss > os { return 1; }
+
+ assert ss == os;
+ match ss {
+ Zero => 0,
+ Plus => self.data.cmp(&other.data),
+ Minus => self.data.cmp(&other.data).neg(),
+ }
+ }
+
+ pure fn divmod(&self, other: &BigInt) -> (BigInt, BigInt) {
+ // m.sign == other.sign
+ let (d_ui, m_ui) = self.data.divmod(&other.data);
+ let d = BigInt::from_biguint(Plus, d_ui),
+ m = BigInt::from_biguint(Plus, m_ui);
+ match (self.sign, other.sign) {
+ (_, Zero) => fail,
+ (Plus, Plus) | (Zero, Plus) => (d, m),
+ (Plus, Minus) | (Zero, Minus) => if m.is_zero() {
+ (-d, Zero::zero())
+ } else {
+ (-d - One::one(), m + *other)
+ },
+ (Minus, Plus) => if m.is_zero() {
+ (-d, Zero::zero())
+ } else {
+ (-d - One::one(), other - m)
+ },
+ (Minus, Minus) => (d, -m)
+ }
+ }
+
+ pure fn quot(&self, other: &BigInt) -> BigInt {
+ let (q, _) = self.quotrem(other);
+ return q;
+ }
+ pure fn rem(&self, other: &BigInt) -> BigInt {
+ let (_, r) = self.quotrem(other);
+ return r;
+ }
+
+ pure fn quotrem(&self, other: &BigInt) -> (BigInt, BigInt) {
+ // r.sign == self.sign
+ let (q_ui, r_ui) = self.data.quotrem(&other.data);
+ let q = BigInt::from_biguint(Plus, q_ui);
+ let r = BigInt::from_biguint(Plus, r_ui);
+ match (self.sign, other.sign) {
+ (_, Zero) => fail,
+ (Plus, Plus) | (Zero, Plus) => ( q, r),
+ (Plus, Minus) | (Zero, Minus) => (-q, r),
+ (Minus, Plus) => (-q, -r),
+ (Minus, Minus) => ( q, -r)
+ }
+ }
+
+ pure fn is_zero(&self) -> bool { self.sign == Zero }
+ pure fn is_not_zero(&self) -> bool { self.sign != Zero }
+ pure fn is_positive(&self) -> bool { self.sign == Plus }
+ pure fn is_negative(&self) -> bool { self.sign == Minus }
+ pure fn is_nonpositive(&self) -> bool { self.sign != Plus }
+ pure fn is_nonnegative(&self) -> bool { self.sign != Minus }
+
+ pure fn to_uint(&self) -> uint {
+ match self.sign {
+ Plus => self.data.to_uint(),
+ Zero => 0,
+ Minus => 0
+ }
+ }
+
+ pure fn to_str_radix(&self, radix: uint) -> ~str {
+ match self.sign {
+ Plus => self.data.to_str_radix(radix),
+ Zero => ~"0",
+ Minus => ~"-" + self.data.to_str_radix(radix)
+ }
+ }
+}
+
+#[cfg(test)]
+mod biguint_tests {
+
+ use core::*;
+ use core::num::{Num, Zero, One};
+ use super::{BigInt, BigUint, BigDigit};
+
+ #[test]
+ fn test_from_slice() {
+ fn check(slice: &[BigDigit], data: &[BigDigit]) {
+ assert data == BigUint::from_slice(slice).data;
+ }
+ check(~[1], ~[1]);
+ check(~[0, 0, 0], ~[]);
+ check(~[1, 2, 0, 0], ~[1, 2]);
+ check(~[0, 0, 1, 2], ~[0, 0, 1, 2]);
+ check(~[0, 0, 1, 2, 0, 0], ~[0, 0, 1, 2]);
+ check(~[-1], ~[-1]);
+ }
+
+ #[test]
+ fn test_cmp() {
+ let data = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1] ]
+ .map(|v| BigUint::from_slice(*v));
+ for data.eachi |i, ni| {
+ for vec::view(data, i, data.len()).eachi |j0, nj| {
+ let j = j0 + i;
+ if i == j {
+ assert ni.cmp(nj) == 0;
+ assert nj.cmp(ni) == 0;
+ assert ni == nj;
+ assert !(ni != nj);
+ assert ni <= nj;
+ assert ni >= nj;
+ assert !(ni < nj);
+ assert !(ni > nj);
+ } else {
+ assert ni.cmp(nj) < 0;
+ assert nj.cmp(ni) > 0;
+
+ assert !(ni == nj);
+ assert ni != nj;
+
+ assert ni <= nj;
+ assert !(ni >= nj);
+ assert ni < nj;
+ assert !(ni > nj);
+
+ assert !(nj <= ni);
+ assert nj >= ni;
+ assert !(nj < ni);
+ assert nj > ni;
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_shl() {
+ fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) {
+ assert BigUint::new(v) << shift == BigUint::new(ans);
+ }
+
+ check(~[], 3, ~[]);
+ check(~[1, 1, 1], 3, ~[1 << 3, 1 << 3, 1 << 3]);
+ check(~[1 << (BigDigit::bits - 2)], 2, ~[0, 1]);
+ check(~[1 << (BigDigit::bits - 2)], 3, ~[0, 2]);
+ check(~[1 << (BigDigit::bits - 2)], 3 + BigDigit::bits, ~[0, 0, 2]);
+
+ test_shl_bits();
+
+ #[cfg(target_arch = "x86_64")]
+ fn test_shl_bits() {
+ check(~[0x7654_3210, 0xfedc_ba98,
+ 0x7654_3210, 0xfedc_ba98], 4,
+ ~[0x6543_2100, 0xedcb_a987,
+ 0x6543_210f, 0xedcb_a987, 0xf]);
+ check(~[0x2222_1111, 0x4444_3333,
+ 0x6666_5555, 0x8888_7777], 16,
+ ~[0x1111_0000, 0x3333_2222,
+ 0x5555_4444, 0x7777_6666, 0x8888]);
+ }
+
+ #[cfg(target_arch = "arm")]
+ #[cfg(target_arch = "x86")]
+ fn test_shl_bits() {
+ check(~[0x3210, 0x7654, 0xba98, 0xfedc,
+ 0x3210, 0x7654, 0xba98, 0xfedc], 4,
+ ~[0x2100, 0x6543, 0xa987, 0xedcb,
+ 0x210f, 0x6543, 0xa987, 0xedcb, 0xf]);
+ check(~[0x1111, 0x2222, 0x3333, 0x4444,
+ 0x5555, 0x6666, 0x7777, 0x8888], 16,
+ ~[0x0000, 0x1111, 0x2222, 0x3333,
+ 0x4444, 0x5555, 0x6666, 0x7777, 0x8888]);
+ }
+
+ }
+
+ #[test]
+ #[ignore(cfg(target_arch = "x86"))]
+ #[ignore(cfg(target_arch = "arm"))]
+ fn test_shr() {
+ fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) {
+ assert BigUint::new(v) >> shift == BigUint::new(ans);
+ }
+
+ check(~[], 3, ~[]);
+ check(~[1, 1, 1], 3,
+ ~[1 << (BigDigit::bits - 3), 1 << (BigDigit::bits - 3)]);
+ check(~[1 << 2], 2, ~[1]);
+ check(~[1, 2], 3, ~[1 << (BigDigit::bits - 2)]);
+ check(~[1, 1, 2], 3 + BigDigit::bits, ~[1 << (BigDigit::bits - 2)]);
+ test_shr_bits();
+
+ #[cfg(target_arch = "x86_64")]
+ fn test_shr_bits() {
+ check(~[0x6543_2100, 0xedcb_a987,
+ 0x6543_210f, 0xedcb_a987, 0xf], 4,
+ ~[0x7654_3210, 0xfedc_ba98,
+ 0x7654_3210, 0xfedc_ba98]);
+ check(~[0x1111_0000, 0x3333_2222,
+ 0x5555_4444, 0x7777_6666, 0x8888], 16,
+ ~[0x2222_1111, 0x4444_3333,
+ 0x6666_5555, 0x8888_7777]);
+ }
+
+ #[cfg(target_arch = "arm")]
+ #[cfg(target_arch = "x86")]
+ fn test_shr_bits() {
+ check(~[0x2100, 0x6543, 0xa987, 0xedcb,
+ 0x210f, 0x6543, 0xa987, 0xedcb, 0xf], 4,
+ ~[0x3210, 0x7654, 0xba98, 0xfedc,
+ 0x3210, 0x7654, 0xba98, 0xfedc]);
+ check(~[0x0000, 0x1111, 0x2222, 0x3333,
+ 0x4444, 0x5555, 0x6666, 0x7777, 0x8888], 16,
+ ~[0x1111, 0x2222, 0x3333, 0x4444,
+ 0x5555, 0x6666, 0x7777, 0x8888]);
+ }
+ }
+
+ #[test]
+ fn test_convert_int() {
+ fn check(v: ~[BigDigit], i: int) {
+ let b = BigUint::new(v);
+ assert b == Num::from_int(i);
+ assert b.to_int() == i;
+ }
+
+ check(~[], 0);
+ check(~[1], 1);
+ check(~[-1], (uint::max_value >> BigDigit::bits) as int);
+ check(~[ 0, 1], ((uint::max_value >> BigDigit::bits) + 1) as int);
+ check(~[-1, -1 >> 1], int::max_value);
+
+ assert BigUint::new(~[0, -1]).to_int() == int::max_value;
+ assert BigUint::new(~[0, 0, 1]).to_int() == int::max_value;
+ assert BigUint::new(~[0, 0, -1]).to_int() == int::max_value;
+ }
+
+ #[test]
+ fn test_convert_uint() {
+ fn check(v: ~[BigDigit], u: uint) {
+ let b = BigUint::new(v);
+ assert b == BigUint::from_uint(u);
+ assert b.to_uint() == u;
+ }
+
+ check(~[], 0);
+ check(~[ 1], 1);
+ check(~[-1], uint::max_value >> BigDigit::bits);
+ check(~[ 0, 1], (uint::max_value >> BigDigit::bits) + 1);
+ check(~[ 0, -1], uint::max_value << BigDigit::bits);
+ check(~[-1, -1], uint::max_value);
+
+ assert BigUint::new(~[0, 0, 1]).to_uint() == uint::max_value;
+ assert BigUint::new(~[0, 0, -1]).to_uint() == uint::max_value;
+ }
+
+ const sum_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[ 1]),
+ (&[ 1], &[ 1], &[ 2]),
+ (&[ 1], &[ 1, 1], &[ 2, 1]),
+ (&[ 1], &[-1], &[ 0, 1]),
+ (&[ 1], &[-1, -1], &[ 0, 0, 1]),
+ (&[-1, -1], &[-1, -1], &[-2, -1, 1]),
+ (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
+ (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
+ ];
+
+ #[test]
+ fn test_add() {
+ for sum_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ assert a + b == c;
+ assert b + a == c;
+ }
+ }
+
+ #[test]
+ fn test_sub() {
+ for sum_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ assert c - a == b;
+ assert c - b == a;
+ }
+ }
+
+ const mul_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[]),
+ (&[ 2], &[], &[]),
+ (&[ 1], &[ 1], &[1]),
+ (&[ 2], &[ 3], &[ 6]),
+ (&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
+ (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
+ (&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
+ (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
+ (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
+ (&[-1], &[-1], &[ 1, -2]),
+ (&[-1, -1], &[-1], &[ 1, -1, -2]),
+ (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
+ (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
+ (&[-1/2 + 1], &[ 2], &[ 0, 1]),
+ (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]),
+ (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
+ (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
+ (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
+ (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
+ (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
+ ];
+
+ const divmod_quadruples: &[(&[BigDigit], &[BigDigit],
+ &[BigDigit], &[BigDigit])]
+ = &[
+ (&[ 1], &[ 2], &[], &[1]),
+ (&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
+ (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
+ (&[ 0, 1], &[-1], &[1], &[1]),
+ (&[-1, -1], &[-2], &[2, 1], &[3])
+ ];
+
+ #[test]
+ fn test_mul() {
+ for mul_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ assert a * b == c;
+ assert b * a == c;
+ }
+
+ for divmod_quadruples.each |elm| {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+ let d = BigUint::from_slice(dVec);
+
+ assert a == b * c + d;
+ assert a == c * b + d;
+ }
+ }
+
+ #[test]
+ fn test_divmod() {
+ for mul_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+
+ if a.is_not_zero() {
+ assert c.divmod(&a) == (b, Zero::zero());
+ }
+ if b.is_not_zero() {
+ assert c.divmod(&b) == (a, Zero::zero());
+ }
+ }
+
+ for divmod_quadruples.each |elm| {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigUint::from_slice(aVec);
+ let b = BigUint::from_slice(bVec);
+ let c = BigUint::from_slice(cVec);
+ let d = BigUint::from_slice(dVec);
+
+ if b.is_not_zero() { assert a.divmod(&b) == (c, d); }
+ }
+ }
+
+ fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
+ let bits = BigDigit::bits;
+ ~[( Zero::zero(), ~[
+ (2, ~"0"), (3, ~"0")
+ ]), ( BigUint::from_slice([ 0xff ]), ~[
+ (2, ~"11111111"),
+ (3, ~"100110"),
+ (4, ~"3333"),
+ (5, ~"2010"),
+ (6, ~"1103"),
+ (7, ~"513"),
+ (8, ~"377"),
+ (9, ~"313"),
+ (10, ~"255"),
+ (11, ~"212"),
+ (12, ~"193"),
+ (13, ~"168"),
+ (14, ~"143"),
+ (15, ~"120"),
+ (16, ~"ff")
+ ]), ( BigUint::from_slice([ 0xfff ]), ~[
+ (2, ~"111111111111"),
+ (4, ~"333333"),
+ (16, ~"fff")
+ ]), ( BigUint::from_slice([ 1, 2 ]), ~[
+ (2,
+ ~"10" +
+ str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
+ (4,
+ ~"2" +
+ str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
+ (10, match bits {
+ 32 => ~"8589934593", 16 => ~"131073", _ => fail
+ }),
+ (16,
+ ~"2" +
+ str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
+ ]), ( BigUint::from_slice([ 1, 2, 3 ]), ~[
+ (2,
+ ~"11" +
+ str::from_chars(vec::from_elem(bits - 2, '0')) + "10" +
+ str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
+ (4,
+ ~"3" +
+ str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "2" +
+ str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
+ (10, match bits {
+ 32 => ~"55340232229718589441",
+ 16 => ~"12885032961",
+ _ => fail
+ }),
+ (16, ~"3" +
+ str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "2" +
+ str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
+ ]) ]
+ }
+
+ #[test]
+ fn test_to_str_radix() {
+ for to_str_pairs().each |num_pair| {
+ let &(n, rs) = num_pair;
+ for rs.each |str_pair| {
+ let &(radix, str) = str_pair;
+ assert n.to_str_radix(radix) == str;
+ }
+ }
+ }
+
+ #[test]
+ fn test_from_str_radix() {
+ for to_str_pairs().each |num_pair| {
+ let &(n, rs) = num_pair;
+ for rs.each |str_pair| {
+ let &(radix, str) = str_pair;
+ assert Some(n) == BigUint::from_str_radix(str, radix);
+ }
+ }
+
+ assert BigUint::from_str_radix(~"Z", 10) == None;
+ assert BigUint::from_str_radix(~"_", 2) == None;
+ assert BigUint::from_str_radix(~"-1", 10) == None;
+ }
+
+ #[test]
+ fn test_factor() {
+ fn factor(n: uint) -> BigUint {
+ let mut f= One::one::<BigUint>();
+ for uint::range(2, n + 1) |i| {
+ f *= BigUint::from_uint(i);
+ }
+ return f;
+ }
+
+ fn check(n: uint, s: &str) {
+ let n = factor(n);
+ let ans = match BigUint::from_str_radix(s, 10) {
+ Some(x) => x, None => fail
+ };
+ assert n == ans;
+ }
+
+ check(3, "6");
+ check(10, "3628800");
+ check(20, "2432902008176640000");
+ check(30, "265252859812191058636308480000000");
+ }
+}
+
+#[cfg(test)]
+mod bigint_tests {
+ use super::{BigInt, BigUint, BigDigit, Sign, Minus, Zero, Plus};
+
+ use core::*;
+ use core::num::{Num, Zero, One};
+
+ #[test]
+ fn test_from_biguint() {
+ fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) {
+ let inp = BigInt::from_biguint(inp_s, BigUint::from_uint(inp_n));
+ let ans = BigInt { sign: ans_s, data: BigUint::from_uint(ans_n)};
+ assert inp == ans;
+ }
+ check(Plus, 1, Plus, 1);
+ check(Plus, 0, Zero, 0);
+ check(Minus, 1, Minus, 1);
+ check(Zero, 1, Zero, 0);
+ }
+
+ #[test]
+ fn test_cmp() {
+ let vs = [ &[2], &[1, 1], &[2, 1], &[1, 1, 1] ];
+ let mut nums = vec::reversed(vs)
+ .map(|s| BigInt::from_slice(Minus, *s));
+ nums.push(Zero::zero());
+ nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
+
+ for nums.eachi |i, ni| {
+ for vec::view(nums, i, nums.len()).eachi |j0, nj| {
+ let j = i + j0;
+ if i == j {
+ assert ni.cmp(nj) == 0;
+ assert nj.cmp(ni) == 0;
+ assert ni == nj;
+ assert !(ni != nj);
+ assert ni <= nj;
+ assert ni >= nj;
+ assert !(ni < nj);
+ assert !(ni > nj);
+ } else {
+ assert ni.cmp(nj) < 0;
+ assert nj.cmp(ni) > 0;
+
+ assert !(ni == nj);
+ assert ni != nj;
+
+ assert ni <= nj;
+ assert !(ni >= nj);
+ assert ni < nj;
+ assert !(ni > nj);
+
+ assert !(nj <= ni);
+ assert nj >= ni;
+ assert !(nj < ni);
+ assert nj > ni;
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_convert_int() {
+ fn check(b: BigInt, i: int) {
+ assert b == Num::from_int(i);
+ assert b.to_int() == i;
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+ check(BigInt::from_biguint(
+ Plus, BigUint::from_uint(int::max_value as uint)
+ ), int::max_value);
+
+ assert BigInt::from_biguint(
+ Plus, BigUint::from_uint(int::max_value as uint + 1)
+ ).to_int() == int::max_value;
+ assert BigInt::from_biguint(
+ Plus, BigUint::new(~[1, 2, 3])
+ ).to_int() == int::max_value;
+
+ check(BigInt::from_biguint(
+ Minus, BigUint::from_uint(-int::min_value as uint)
+ ), int::min_value);
+ assert BigInt::from_biguint(
+ Minus, BigUint::from_uint(-int::min_value as uint + 1)
+ ).to_int() == int::min_value;
+ assert BigInt::from_biguint(
+ Minus, BigUint::new(~[1, 2, 3])
+ ).to_int() == int::min_value;
+ }
+
+ #[test]
+ fn test_convert_uint() {
+ fn check(b: BigInt, u: uint) {
+ assert b == BigInt::from_uint(u);
+ assert b.to_uint() == u;
+ }
+
+ check(Zero::zero(), 0);
+ check(One::one(), 1);
+
+ check(
+ BigInt::from_biguint(Plus, BigUint::from_uint(uint::max_value)),
+ uint::max_value);
+ assert BigInt::from_biguint(
+ Plus, BigUint::new(~[1, 2, 3])
+ ).to_uint() == uint::max_value;
+
+ assert BigInt::from_biguint(
+ Minus, BigUint::from_uint(uint::max_value)
+ ).to_uint() == 0;
+ assert BigInt::from_biguint(
+ Minus, BigUint::new(~[1, 2, 3])
+ ).to_uint() == 0;
+ }
+
+ const sum_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[ 1]),
+ (&[ 1], &[ 1], &[ 2]),
+ (&[ 1], &[ 1, 1], &[ 2, 1]),
+ (&[ 1], &[-1], &[ 0, 1]),
+ (&[ 1], &[-1, -1], &[ 0, 0, 1]),
+ (&[-1, -1], &[-1, -1], &[-2, -1, 1]),
+ (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]),
+ (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2])
+ ];
+
+ #[test]
+ fn test_add() {
+ for sum_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ assert a + b == c;
+ assert b + a == c;
+ assert c + (-a) == b;
+ assert c + (-b) == a;
+ assert a + (-c) == (-b);
+ assert b + (-c) == (-a);
+ assert (-a) + (-b) == (-c);
+ assert a + (-a) == Zero::zero();
+ }
+ }
+
+ #[test]
+ fn test_sub() {
+ for sum_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ assert c - a == b;
+ assert c - b == a;
+ assert (-b) - a == (-c);
+ assert (-a) - b == (-c);
+ assert b - (-a) == c;
+ assert a - (-b) == c;
+ assert (-c) - (-a) == (-b);
+ assert a - a == Zero::zero();
+ }
+ }
+
+ const mul_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[
+ (&[], &[], &[]),
+ (&[], &[ 1], &[]),
+ (&[ 2], &[], &[]),
+ (&[ 1], &[ 1], &[1]),
+ (&[ 2], &[ 3], &[ 6]),
+ (&[ 1], &[ 1, 1, 1], &[1, 1, 1]),
+ (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]),
+ (&[ 1, 1, 1], &[-1], &[-1, -1, -1]),
+ (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]),
+ (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]),
+ (&[-1], &[-1], &[ 1, -2]),
+ (&[-1, -1], &[-1], &[ 1, -1, -2]),
+ (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]),
+ (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]),
+ (&[-1/2 + 1], &[ 2], &[ 0, 1]),
+ (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]),
+ (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]),
+ (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]),
+ (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]),
+ (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]),
+ (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1])
+ ];
+
+ const divmod_quadruples: &[(&[BigDigit], &[BigDigit],
+ &[BigDigit], &[BigDigit])]
+ = &[
+ (&[ 1], &[ 2], &[], &[1]),
+ (&[ 1, 1], &[ 2], &[-1/2+1], &[1]),
+ (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
+ (&[ 0, 1], &[-1], &[1], &[1]),
+ (&[-1, -1], &[-2], &[2, 1], &[3])
+ ];
+
+ #[test]
+ fn test_mul() {
+ for mul_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ assert a * b == c;
+ assert b * a == c;
+
+ assert (-a) * b == -c;
+ assert (-b) * a == -c;
+ }
+
+ for divmod_quadruples.each |elm| {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+ let d = BigInt::from_slice(Plus, dVec);
+
+ assert a == b * c + d;
+ assert a == c * b + d;
+ }
+ }
+
+ #[test]
+ fn test_divmod() {
+ fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
+ let (d, m) = a.divmod(b);
+ if m.is_not_zero() {
+ assert m.sign == b.sign;
+ }
+ assert m.abs() <= b.abs();
+ assert *a == b * d + m;
+ assert d == *ans_d;
+ assert m == *ans_m;
+ }
+
+ fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) {
+ if m.is_zero() {
+ check_sub(a, b, d, m);
+ check_sub(a, &b.neg(), &d.neg(), m);
+ check_sub(&a.neg(), b, &d.neg(), m);
+ check_sub(&a.neg(), &b.neg(), d, m);
+ } else {
+ check_sub(a, b, d, m);
+ check_sub(a, &b.neg(), &(d.neg() - One::one()), &(m - *b));
+ check_sub(&a.neg(), b, &(d.neg() - One::one()), &(b - *m));
+ check_sub(&a.neg(), &b.neg(), d, &m.neg());
+ }
+ }
+
+ for mul_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
+ if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
+ }
+
+ for divmod_quadruples.each |elm| {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+ let d = BigInt::from_slice(Plus, dVec);
+
+ if b.is_not_zero() {
+ check(&a, &b, &c, &d);
+ }
+ }
+ }
+
+
+ #[test]
+ fn test_quotrem() {
+ fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
+ let (q, r) = a.quotrem(b);
+ if r.is_not_zero() {
+ assert r.sign == a.sign;
+ }
+ assert r.abs() <= b.abs();
+ assert *a == b * q + r;
+ assert q == *ans_q;
+ assert r == *ans_r;
+ }
+
+ fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) {
+ check_sub(a, b, q, r);
+ check_sub(a, &b.neg(), &q.neg(), r);
+ check_sub(&a.neg(), b, &q.neg(), &r.neg());
+ check_sub(&a.neg(), &b.neg(), q, &r.neg());
+ }
+ for mul_triples.each |elm| {
+ let (aVec, bVec, cVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+
+ if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
+ if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
+ }
+
+ for divmod_quadruples.each |elm| {
+ let (aVec, bVec, cVec, dVec) = *elm;
+ let a = BigInt::from_slice(Plus, aVec);
+ let b = BigInt::from_slice(Plus, bVec);
+ let c = BigInt::from_slice(Plus, cVec);
+ let d = BigInt::from_slice(Plus, dVec);
+
+ if b.is_not_zero() {
+ check(&a, &b, &c, &d);
+ }
+ }
+ }
+
+ #[test]
+ fn test_to_str_radix() {
+ fn check(n: int, ans: &str) {
+ assert ans == Num::from_int::<BigInt>(n).to_str_radix(10);
+ }
+ check(10, "10");
+ check(1, "1");
+ check(0, "0");
+ check(-1, "-1");
+ check(-10, "-10");
+ }
+
+
+ #[test]
+ fn test_from_str_radix() {
+ fn check(s: &str, ans: Option<int>) {
+ let ans = ans.map(|&n| Num::from_int(n));
+ assert BigInt::from_str_radix(s, 10) == ans;
+ }
+ check("10", Some(10));
+ check("1", Some(1));
+ check("0", Some(0));
+ check("-1", Some(-1));
+ check("-10", Some(-10));
+ check("Z", None);
+ check("_", None);
+ }
+
+ #[test]
+ fn test_neg() {
+ assert -BigInt::new(Plus, ~[1, 1, 1]) ==
+ BigInt::new(Minus, ~[1, 1, 1]);
+ assert -BigInt::new(Minus, ~[1, 1, 1]) ==
+ BigInt::new(Plus, ~[1, 1, 1]);
+ assert -Zero::zero::<BigInt>() == Zero::zero::<BigInt>();
+ }
+}
+
#[forbid(deprecated_mode)];
-use vec::{to_mut, from_elem};
+use core::ops;
+use core::prelude::*;
+use core::uint;
+use core::vec::{to_mut, from_elem};
+use core::vec;
struct SmallBitv {
/// only the lowest nbits of this value are used. the rest is undefined.
#[cfg(test)]
mod tests {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use bitv::*;
+ use bitv;
+
+ use core::uint;
+ use core::vec;
+
#[test]
fn test_to_str() {
let zerolen = Bitv(0u, false);
*/
#[forbid(deprecated_mode)];
+use core::libc;
+use core::oldcomm;
+use core::option;
+use core::prelude::*;
+use core::ptr;
+use core::task;
+
/**
* The type representing a foreign chunk of memory
*
#[cfg(test)]
mod tests {
- use libc::*;
+ use core::prelude::*;
+
+ use c_vec::*;
+
+ use core::libc::*;
+ use core::libc;
fn malloc(n: size_t) -> CVec<u8> {
- let mem = libc::malloc(n);
+ unsafe {
+ let mem = libc::malloc(n);
- assert mem as int != 0;
+ assert mem as int != 0;
- return unsafe { c_vec_with_dtor(mem as *mut u8, n as uint,
- ||free(mem)) };
+ return unsafe { c_vec_with_dtor(mem as *mut u8, n as uint,
+ || unsafe { free(mem) }) };
+ }
}
#[test]
// except according to those terms.
#[forbid(deprecated_mode)];
+
+use core::option;
+use core::prelude::*;
+
/// A dynamic, mutable location.
///
/// Similar to a mutable option type, but friendlier.
#[forbid(deprecated_mode)];
/// Additional general-purpose comparison functionality.
+use core::f32;
+use core::f64;
+use core::float;
+
const fuzzy_epsilon: float = 1.0e-6;
pub trait FuzzyEq {
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
-use pipes::{GenericChan, GenericSmartChan, GenericPort,
- Chan, Port, Selectable, Peekable};
+use core::pipes::{GenericChan, GenericSmartChan, GenericPort};
+use core::pipes::{Chan, Port, Selectable, Peekable};
+use core::pipes;
+use core::prelude::*;
/// An extension of `pipes::stream` that allows both sending and receiving.
pub struct DuplexStream<T: Owned, U: Owned> {
#[cfg(test)]
mod test {
#[legacy_exports];
+ use comm::DuplexStream;
+
#[test]
fn DuplexStream1() {
let (left, right) = DuplexStream();
#[forbid(deprecated_mode)];
//! Unsafe debugging functions for inspecting values.
-use cast::reinterpret_cast;
-
+use core::cast::reinterpret_cast;
+use core::ptr;
+use core::sys;
#[abi = "cdecl"]
extern mod rustrt {
#[legacy_exports];
- fn debug_tydesc(td: *sys::TypeDesc);
- fn debug_opaque(td: *sys::TypeDesc, x: *());
- fn debug_box(td: *sys::TypeDesc, x: *());
- fn debug_tag(td: *sys::TypeDesc, x: *());
- fn debug_fn(td: *sys::TypeDesc, x: *());
- fn debug_ptrcast(td: *sys::TypeDesc, x: *()) -> *();
- fn rust_dbg_breakpoint();
+ unsafe fn debug_tydesc(td: *sys::TypeDesc);
+ unsafe fn debug_opaque(td: *sys::TypeDesc, x: *());
+ unsafe fn debug_box(td: *sys::TypeDesc, x: *());
+ unsafe fn debug_tag(td: *sys::TypeDesc, x: *());
+ unsafe fn debug_fn(td: *sys::TypeDesc, x: *());
+ unsafe fn debug_ptrcast(td: *sys::TypeDesc, x: *()) -> *();
+ unsafe fn rust_dbg_breakpoint();
}
pub fn debug_tydesc<T>() {
- rustrt::debug_tydesc(sys::get_type_desc::<T>());
+ unsafe {
+ rustrt::debug_tydesc(sys::get_type_desc::<T>());
+ }
}
pub fn debug_opaque<T>(x: T) {
- rustrt::debug_opaque(sys::get_type_desc::<T>(), ptr::addr_of(&x) as *());
+ unsafe {
+ rustrt::debug_opaque(sys::get_type_desc::<T>(),
+ ptr::addr_of(&x) as *());
+ }
}
pub fn debug_box<T>(x: @T) {
- rustrt::debug_box(sys::get_type_desc::<T>(), ptr::addr_of(&x) as *());
+ unsafe {
+ rustrt::debug_box(sys::get_type_desc::<T>(),
+ ptr::addr_of(&x) as *());
+ }
}
pub fn debug_tag<T>(x: T) {
- rustrt::debug_tag(sys::get_type_desc::<T>(), ptr::addr_of(&x) as *());
+ unsafe {
+ rustrt::debug_tag(sys::get_type_desc::<T>(),
+ ptr::addr_of(&x) as *());
+ }
}
pub fn debug_fn<T>(x: T) {
- rustrt::debug_fn(sys::get_type_desc::<T>(), ptr::addr_of(&x) as *());
+ unsafe {
+ rustrt::debug_fn(sys::get_type_desc::<T>(),
+ ptr::addr_of(&x) as *());
+ }
}
pub unsafe fn ptr_cast<T, U>(x: @T) -> @U {
/// Triggers a debugger breakpoint
pub fn breakpoint() {
- rustrt::rust_dbg_breakpoint();
+ unsafe {
+ rustrt::rust_dbg_breakpoint();
+ }
}
#[test]
#[forbid(deprecated_mode)];
#[forbid(non_camel_case_types)];
-use option::{Some, None};
-use dvec::DVec;
-use core::cmp::{Eq};
+use core::cmp::Eq;
+use core::dvec::DVec;
+use core::dvec;
+use core::prelude::*;
+use core::uint;
+use core::vec;
pub trait Deque<T> {
fn size() -> uint;
#[cfg(test)]
mod tests {
+ use core::prelude::*;
+
+ use deque::*;
+ use deque;
+
#[test]
fn test_simple() {
let d: deque::Deque<int> = deque::create::<int>();
// except according to those terms.
#[forbid(deprecated_mode)];
+
use serialize;
+use core::io;
+use core::ops;
+use core::prelude::*;
+use core::str;
+use core::vec;
+
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here:
// http://www.matroska.org/technical/specs/rfc/index.html
data_pos: uint,
}
-struct Doc {
+pub struct Doc {
data: @~[u8],
start: uint,
end: uint,
}
-struct TaggedDoc {
+pub struct TaggedDoc {
tag: uint,
doc: Doc,
}
-enum EbmlEncoderTag {
+pub enum EbmlEncoderTag {
EsUint, EsU64, EsU32, EsU16, EsU8,
EsInt, EsI64, EsI32, EsI16, EsI8,
EsBool,
// --------------------------------------
pub mod reader {
+ use ebml::{Doc, EbmlEncoderTag, EsBool, EsEnum, EsEnumBody, EsEnumVid};
+ use ebml::{EsF32, EsF64, EsFloat, EsI16, EsI32, EsI64, EsI8, EsInt};
+ use ebml::{EsLabel, EsOpaque, EsStr, EsU16, EsU32, EsU64, EsU8, EsUint};
+ use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc};
+ use serialize;
+
+ use core::int;
+ use core::io;
+ use core::ops;
+ use core::prelude::*;
+ use core::str;
+ use core::vec;
// ebml reading
fn read_u8 (&self) -> u8 { doc_as_u8 (self.next_doc(EsU8 )) }
fn read_uint(&self) -> uint {
let v = doc_as_u64(self.next_doc(EsUint));
- if v > (core::uint::max_value as u64) {
+ if v > (::core::uint::max_value as u64) {
fail fmt!("uint %? too large for this architecture", v);
}
v as uint
}
pub mod writer {
+ use ebml::{Doc, EbmlEncoderTag, EsBool, EsEnum, EsEnumBody, EsEnumVid};
+ use ebml::{EsF32, EsF64, EsFloat, EsI16, EsI32, EsI64, EsI8, EsInt};
+ use ebml::{EsLabel, EsOpaque, EsStr, EsU16, EsU32, EsU64, EsU8, EsUint};
+ use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc};
+
+ use core::io;
+ use core::str;
+ use core::vec;
// ebml writing
pub struct Encoder {
}
}
- impl Encoder: serialize::Encoder {
+ impl Encoder: ::serialize::Encoder {
fn emit_nil(&self) {}
fn emit_uint(&self, v: uint) {
#[cfg(test)]
mod tests {
+ use ebml::reader;
+ use ebml::writer;
+ use serialize;
+
+ use core::io;
+ use core::option::{None, Option, Some};
+
#[test]
fn test_option_int() {
fn test_v(v: Option<int>) {
*/
// The basic send/recv interface FlatChan and PortChan will implement
+use core::io;
use core::pipes::GenericChan;
use core::pipes::GenericPort;
-
+use core::pipes;
+use core::prelude::*;
use core::sys::size_of;
+use core::uint;
+use core::vec;
/**
A FlatPort, consisting of a `BytePort` that recieves byte vectors,
Constructors for flat pipes that using serialization-based flattening.
*/
pub mod serial {
-
pub use DefaultEncoder = ebml::writer::Encoder;
pub use DefaultDecoder = ebml::reader::Decoder;
- use core::io::{Reader, Writer};
- use core::pipes::{Port, Chan};
use serialize::{Decodable, Encodable};
use flatpipes::flatteners::{DeserializingUnflattener,
SerializingFlattener};
use flatpipes::flatteners::{deserialize_buffer, serialize_value};
use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan};
use flatpipes::bytepipes::{PipeBytePort, PipeByteChan};
+ use flatpipes::{FlatPort, FlatChan};
+
+ use core::io::{Reader, Writer};
+ use core::pipes::{Port, Chan};
+ use core::pipes;
pub type ReaderPort<T, R> = FlatPort<
T, DeserializingUnflattener<DefaultDecoder, T>,
let (port, chan) = pipes::stream();
return (pipe_port(move port), pipe_chan(move chan));
}
-
}
// FIXME #4074 this doesn't correctly enforce POD bounds
*/
pub mod pod {
-
- use core::io::{Reader, Writer};
- use core::pipes::{Port, Chan};
use flatpipes::flatteners::{PodUnflattener, PodFlattener};
use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan};
use flatpipes::bytepipes::{PipeBytePort, PipeByteChan};
+ use flatpipes::{FlatPort, FlatChan};
+
+ use core::io::{Reader, Writer};
+ use core::pipes::{Port, Chan};
+ use core::pipes;
+ use core::prelude::*;
pub type ReaderPort<T: Copy Owned, R> =
FlatPort<T, PodUnflattener<T>, ReaderBytePort<R>>;
const CONTINUE: [u8 * 4] = [0xAA, 0xBB, 0xCC, 0xDD];
-impl<T, U: Unflattener<T>, P: BytePort> FlatPort<T, U, P>: GenericPort<T> {
+pub impl<T,U:Unflattener<T>,P:BytePort> FlatPort<T, U, P>: GenericPort<T> {
fn recv() -> T {
match self.try_recv() {
Some(move val) => move val,
}
}
-impl<T, F: Flattener<T>, C: ByteChan> FlatChan<T, F, C>: GenericChan<T> {
+impl<T,F:Flattener<T>,C:ByteChan> FlatChan<T, F, C>: GenericChan<T> {
fn send(val: T) {
self.byte_chan.send(CONTINUE.to_vec());
let bytes = self.flattener.flatten(move val);
}
}
-impl<T, U: Unflattener<T>, P: BytePort> FlatPort<T, U, P> {
+pub impl<T,U:Unflattener<T>,P:BytePort> FlatPort<T, U, P> {
static fn new(u: U, p: P) -> FlatPort<T, U, P> {
FlatPort {
unflattener: move u,
}
}
-impl<T, F: Flattener<T>, C: ByteChan> FlatChan<T, F, C> {
+pub impl<T,F:Flattener<T>,C:ByteChan> FlatChan<T, F, C> {
static fn new(f: F, c: C) -> FlatChan<T, F, C> {
FlatChan {
flattener: move f,
pub mod flatteners {
+ use ebml;
+ use flatpipes::{ByteChan, BytePort, Flattener, Unflattener};
+ use io_util::BufReader;
+ use json;
+ use serialize::{Encoder, Decoder, Encodable, Decodable};
+ use core::cast;
+ use core::io::{Writer, Reader, BytesWriter, ReaderUtil};
+ use core::prelude::*;
+ use core::ptr;
use core::sys::size_of;
+ use core::vec;
- use serialize::{Encoder, Decoder,
- Encodable, Decodable};
- use core::io::{Writer, Reader, BytesWriter, ReaderUtil};
- use flatpipes::util::BufReader;
-
- // XXX: Is copy/send equivalent to pod?
+ // FIXME #4074: Copy + Owned != POD
pub struct PodUnflattener<T: Copy Owned> {
bogus: ()
}
}
pub mod bytepipes {
+ use flatpipes::{ByteChan, BytePort};
use core::io::{Writer, Reader, ReaderUtil};
use core::pipes::{Port, Chan};
+ use core::pipes;
+ use core::prelude::*;
pub struct ReaderBytePort<R: Reader> {
reader: R
pub impl PipeBytePort: BytePort {
fn try_recv(&self, count: uint) -> Option<~[u8]> {
if self.buf.len() >= count {
- let mut bytes = core::util::replace(&mut self.buf, ~[]);
+ let mut bytes = ::core::util::replace(&mut self.buf, ~[]);
self.buf = bytes.slice(count, bytes.len());
bytes.truncate(count);
return Some(bytes);
} else if self.buf.len() > 0 {
- let mut bytes = core::util::replace(&mut self.buf, ~[]);
+ let mut bytes = ::core::util::replace(&mut self.buf, ~[]);
assert count > bytes.len();
match self.try_recv(count - bytes.len()) {
Some(move rest) => {
None => return None
}
} else {
- core::util::unreachable()
+ ::core::util::unreachable()
}
}
}
}
-// XXX: This belongs elsewhere
-mod util {
-
- use io::{Reader, BytesReader};
-
- pub struct BufReader {
- buf: ~[u8],
- mut pos: uint
- }
-
- pub impl BufReader {
- static pub fn new(v: ~[u8]) -> BufReader {
- BufReader {
- buf: move v,
- pos: 0
- }
- }
-
- priv fn as_bytes_reader<A>(f: &fn(&BytesReader) -> A) -> A {
- // Recreating the BytesReader state every call since
- // I can't get the borrowing to work correctly
- let bytes_reader = BytesReader {
- bytes: core::util::id::<&[u8]>(self.buf),
- pos: self.pos
- };
-
- let res = f(&bytes_reader);
-
- // XXX: This isn't correct if f fails
- self.pos = bytes_reader.pos;
-
- return move res;
- }
- }
-
- impl BufReader: Reader {
- fn read(&self, bytes: &[mut u8], len: uint) -> uint {
- self.as_bytes_reader(|r| r.read(bytes, len) )
- }
- fn read_byte(&self) -> int {
- self.as_bytes_reader(|r| r.read_byte() )
- }
- fn eof(&self) -> bool {
- self.as_bytes_reader(|r| r.eof() )
- }
- fn seek(&self, offset: int, whence: io::SeekStyle) {
- self.as_bytes_reader(|r| r.seek(offset, whence) )
- }
- fn tell(&self) -> uint {
- self.as_bytes_reader(|r| r.tell() )
- }
- }
-
-}
-
#[cfg(test)]
mod test {
+ use core::prelude::*;
- // XXX: json::Decoder doesn't work because of problems related to
- // its interior pointers
- //use DefaultEncoder = json::Encoder;
- //use DefaultDecoder = json::Decoder;
- use DefaultEncoder = ebml::writer::Encoder;
- use DefaultDecoder = ebml::reader::Decoder;
+ use DefaultEncoder = json::Encoder;
+ use DefaultDecoder = json::Decoder;
use flatpipes::flatteners::*;
use flatpipes::bytepipes::*;
+ use flatpipes::pod;
+ use flatpipes::serial;
+ use io_util::BufReader;
+ use flatpipes::{BytePort, FlatChan, FlatPort};
+ use net::ip;
+ use net::tcp::TcpSocketBuf;
use core::dvec::DVec;
- use io::BytesReader;
- use util::BufReader;
- use net::tcp::TcpSocketBuf;
+ use core::int;
+ use core::io::BytesReader;
+ use core::io;
+ use core::prelude::*;
+ use core::result;
+ use core::sys;
+ use core::task;
#[test]
fn test_serializing_memory_stream() {
}
}
- // XXX: Networking doesn't work on x86
+ // FIXME #2064: Networking doesn't work on x86
#[test]
#[cfg(target_arch = "x86_64")]
fn test_pod_tcp_stream() {
use net::ip;
use cell::Cell;
use net::tcp::TcpSocket;
+ use uv;
// Indicate to the client task that the server is listening
let (begin_connect_port, begin_connect_chan) = pipes::stream();
// Tests that the different backends behave the same when the
// binary streaming protocol is broken
mod broken_protocol {
+ use core::prelude::*;
+
+ use flatpipes::{BytePort, FlatPort};
+ use flatpipes::flatteners::PodUnflattener;
+ use flatpipes::pod;
+ use io_util::BufReader;
+
+ use core::io;
+ use core::pipes;
+ use core::sys;
+ use core::task;
+
type PortLoader<P: BytePort> =
~fn(~[u8]) -> FlatPort<int, PodUnflattener<int>, P>;
*/
use core::cmp::{Eq, Ord};
-use option::{Some, None};
-use option = option;
+use core::option::{Some, None};
+use core::prelude::*;
pub type Treemap<K, V> = @TreeNode<K, V>;
* ~~~
*/
-use either::Either;
-use pipes::{recv, oneshot, ChanOne, PortOne, send_one, recv_one};
-use cast::copy_lifetime;
+use core::cast::copy_lifetime;
+use core::cast;
+use core::either::Either;
+use core::option;
+use core::pipes::{recv, oneshot, ChanOne, PortOne, send_one, recv_one};
+use core::prelude::*;
+use core::task;
#[doc = "The future type"]
pub struct Future<A> {
- /*priv*/ mut state: FutureState<A>,
+ priv mut state: FutureState<A>,
}
// FIXME(#2829) -- futures should not be copyable, because they close
#[allow(non_implicitly_copyable_typarams)]
pub mod test {
+ use core::prelude::*;
+
+ use future::*;
+
+ use core::pipes::oneshot;
+ use core::task;
+
#[test]
pub fn test_from_value() {
let f = from_value(~"snail");
#[forbid(deprecated_mode)];
use core::cmp::Eq;
+use core::prelude::*;
use core::result::{Err, Ok};
+use core::result;
use core::option;
use core::option::{Some, None};
+use core::str;
+use core::vec;
#[deriving_eq]
-enum Name {
+pub enum Name {
Long(~str),
Short(char),
}
#[deriving_eq]
-enum HasArg { Yes, No, Maybe, }
+pub enum HasArg { Yes, No, Maybe, }
#[deriving_eq]
-enum Occur { Req, Optional, Multi, }
+pub enum Occur { Req, Optional, Multi, }
/// A description of a possible option
#[deriving_eq]
* groups of short and long option names, together.
*/
pub mod groups {
+ use getopts::{HasArg, Long, Maybe, Multi, No, Occur, Opt, Optional, Req};
+ use getopts::{Result, Short, Yes};
+
+ use core::prelude::*;
+ use core::str;
+ use core::vec;
/** one group of options, e.g., both -h and --help, along with
* their shared description and properties
/*
* Parse command line args with the provided long format options
*/
- pub fn getopts(args: &[~str], opts: &[OptGroup]) -> Result {
+ pub fn getopts(args: &[~str], opts: &[OptGroup]) -> ::getopts::Result {
::getopts::getopts(args, vec::flat_map(opts, long_to_short))
}
#[cfg(test)]
mod tests {
#[legacy_exports];
+ use core::prelude::*;
+
use opt = getopts;
- use result::{Err, Ok};
use getopts::groups::OptGroup;
+ use getopts::*;
+
+ use core::result::{Err, Ok};
+ use core::result;
fn check_fail_type(f: Fail_, ft: FailType) {
match f {
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use core::io::{Reader, BytesReader};
+use core::io;
+use core::prelude::*;
+
+pub struct BufReader {
+ buf: ~[u8],
+ mut pos: uint
+}
+
+pub impl BufReader {
+ static pub fn new(v: ~[u8]) -> BufReader {
+ BufReader {
+ buf: move v,
+ pos: 0
+ }
+ }
+
+ priv fn as_bytes_reader<A>(f: &fn(&BytesReader) -> A) -> A {
+ // Recreating the BytesReader state every call since
+ // I can't get the borrowing to work correctly
+ let bytes_reader = BytesReader {
+ bytes: ::core::util::id::<&[u8]>(self.buf),
+ pos: self.pos
+ };
+
+ let res = f(&bytes_reader);
+
+ // FIXME #4429: This isn't correct if f fails
+ self.pos = bytes_reader.pos;
+
+ return move res;
+ }
+}
+
+impl BufReader: Reader {
+ fn read(&self, bytes: &[mut u8], len: uint) -> uint {
+ self.as_bytes_reader(|r| r.read(bytes, len) )
+ }
+ fn read_byte(&self) -> int {
+ self.as_bytes_reader(|r| r.read_byte() )
+ }
+ fn eof(&self) -> bool {
+ self.as_bytes_reader(|r| r.eof() )
+ }
+ fn seek(&self, offset: int, whence: io::SeekStyle) {
+ self.as_bytes_reader(|r| r.seek(offset, whence) )
+ }
+ fn tell(&self) -> uint {
+ self.as_bytes_reader(|r| r.tell() )
+ }
+}
//! json serialization
-use core::cmp::{Eq, Ord};
-use io::{WriterUtil, ReaderUtil};
-use send_map::linear;
+use serialize;
use sort::Sort;
+use core::char;
+use core::cmp::{Eq, Ord};
+use core::float;
+use core::io::{WriterUtil, ReaderUtil};
+use core::io;
+use core::prelude::*;
+use core::send_map::linear;
+use core::str;
+use core::to_str;
+use core::vec;
+
/// Represents a json value
pub enum Json {
Number(float),
impl Json : Eq {
pure fn eq(&self, other: &Json) -> bool {
- // XXX: This is ugly because matching on references is broken, and
- // we can't match on dereferenced tuples without a copy.
- match (*self) {
- Number(f0) =>
- match *other { Number(f1) => f0 == f1, _ => false },
- String(ref s0) =>
- match *other { String(ref s1) => s0 == s1, _ => false },
- Boolean(b0) =>
- match *other { Boolean(b1) => b0 == b1, _ => false },
- Null =>
- match *other { Null => true, _ => false },
- List(ref v0) =>
- match *other { List(ref v1) => v0 == v1, _ => false },
- Object(ref d0) => {
- match *other {
- Object(ref d1) => {
+ match (self) {
+ &Number(f0) =>
+ match other { &Number(f1) => f0 == f1, _ => false },
+ &String(ref s0) =>
+ match other { &String(ref s1) => s0 == s1, _ => false },
+ &Boolean(b0) =>
+ match other { &Boolean(b1) => b0 == b1, _ => false },
+ &Null =>
+ match other { &Null => true, _ => false },
+ &List(ref v0) =>
+ match other { &List(ref v1) => v0 == v1, _ => false },
+ &Object(ref d0) => {
+ match other {
+ &Object(ref d1) => {
if d0.len() == d1.len() {
let mut equal = true;
for d0.each |k, v0| {
}
}
}
- pure fn ne(&self, other: &Json) -> bool { !(*self).eq(other) }
+ pure fn ne(&self, other: &Json) -> bool { !self.eq(other) }
}
/// Test if two json values are less than one another
let mut d0_flat = ~[];
let mut d1_flat = ~[];
- // XXX: this is horribly inefficient...
+ // FIXME #4430: this is horribly inefficient...
for d0.each |k, v| {
d0_flat.push((@copy *k, @copy *v));
}
#[cfg(test)]
mod tests {
+ use core::prelude::*;
+
+ use json::*;
+
+ use core::result;
+ use core::send_map::linear;
+
fn mk_object(items: &[(~str, Json)]) -> Json {
let mut d = ~linear::LinearMap();
use core::cmp::Eq;
use core::option;
-use option::*;
-use option::{Some, None};
+use core::option::*;
+use core::prelude::*;
+use core::vec;
#[deriving_eq]
pub enum List<T> {
mod tests {
#[legacy_exports];
+ use list::*;
+ use list;
+
+ use core::option;
+
#[test]
fn test_is_empty() {
let empty : @list::List<int> = from_vec(~[]);
//! A map type
#[forbid(deprecated_mode)];
-use io::WriterUtil;
-use to_str::ToStr;
-use mutable::Mut;
-use send_map::linear::LinearMap;
-
use core::cmp::Eq;
-use hash::Hash;
-use to_bytes::IterBytes;
+use core::hash::Hash;
+use core::io::WriterUtil;
+use core::io;
+use core::ops;
+use core::to_str::ToStr;
+use core::mutable::Mut;
+use core::prelude::*;
+use core::send_map::linear::LinearMap;
+use core::to_bytes::IterBytes;
+use core::uint;
+use core::vec;
/// A convenience type to treat a hashmap as a set
pub type Set<K:Eq IterBytes Hash> = HashMap<K, ()>;
* Add a value to the map.
*
* If the map contains a value for the key, use the function to
- * set a new value. (Like `insert_or_update_with_key`, but with a
+ * set a new value. (Like `update_with_key`, but with a
* function of only values.)
*/
fn update(key: K, newval: V, ff: fn(V, V) -> V) -> bool;
pure fn each_value_ref(fn(value: &V) -> bool);
}
-mod util {
+pub mod util {
pub type Rational = {num: int, den: int}; // : int::positive(*.den);
pub pure fn rational_leq(x: Rational, y: Rational) -> bool {
// FIXME (#2344): package this up and export it as a datatype usable for
// external code that doesn't want to pay the cost of a box.
pub mod chained {
+ use map::{Map, util};
+
+ use core::io;
+ use core::ops;
+ use core::option;
+ use core::prelude::*;
+ use core::uint;
+ use core::vec;
const initial_capacity: uint = 32u; // 2^5
map
}
-// XXX Transitional
+// FIXME #4431: Transitional
impl<K: Eq IterBytes Hash Copy, V: Copy> @Mut<LinearMap<K, V>>:
Map<K, V> {
pure fn size() -> uint {
#[cfg(test)]
mod tests {
+ use map;
+
+ use core::option::None;
+ use core::option;
+ use core::uint;
#[test]
fn test_simple() {
#[forbid(deprecated_mode)];
+use core::str;
+use core::uint;
+use core::vec;
+
pub pure fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} {
// subtle: if orig_len is merely uint, then the code below
// which performs shifts by 32 bits or more has undefined
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Top-level module for network-related functionality
+/*!
+Top-level module for network-related functionality.
+
+Basically, including this module gives you:
+
+* `net_tcp`
+* `net_ip`
+* `net_url`
+
+See each of those three modules for documentation on what they do.
+*/
pub use tcp = net_tcp;
pub use ip = net_ip;
//! Types/fns concerning Internet Protocol (IP), versions 4 & 6
#[forbid(deprecated_mode)];
+use core::libc;
+use core::oldcomm;
+use core::prelude::*;
+use core::ptr;
+use core::result;
+use core::str;
+use core::uint;
+use core::vec;
+
use iotask = uv::iotask::IoTask;
use interact = uv::iotask::interact;
}
/// Human-friendly feedback on why a parse_addr attempt failed
-type ParseAddrErr = {
+pub type ParseAddrErr = {
err_msg: ~str
};
}
pub mod v4 {
+ use net::ip::{IpAddr, Ipv4, Ipv6, ParseAddrErr};
+ use uv::ll;
+ use uv_ip4_addr = uv::ll::ip4_addr;
+ use uv_ip4_name = uv::ll::ip4_name;
+
+ use core::prelude::*;
+ use core::ptr;
+ use core::result;
+ use core::str;
+ use core::uint;
+ use core::vec;
+
/**
* Convert a str to `ip_addr`
*
}
}
pub mod v6 {
+ use net::ip::{IpAddr, Ipv6, ParseAddrErr};
+ use uv_ip6_addr = uv::ll::ip6_addr;
+ use uv_ip6_name = uv::ll::ip6_name;
+
+ use core::prelude::*;
+ use core::result;
+ use core::str;
+
/**
* Convert a str to `ip_addr`
*
#[cfg(test)]
mod test {
+ use core::prelude::*;
+
+ use net_ip::*;
+ use net_ip::v4;
+ use net_ip::v6;
+ use uv;
+
+ use core::result;
+ use core::vec;
+
#[test]
fn test_ip_ipv4_parse_and_format_ip() {
let localhost_str = ~"127.0.0.1";
// except according to those terms.
//! High-level interface to libuv's TCP functionality
-// XXX Need FFI fixes
+// FIXME #4425: Need FFI fixes
#[allow(deprecated_mode)];
+use future;
+use future_spawn = future::spawn;
use ip = net_ip;
+use uv;
use uv::iotask;
use uv::iotask::IoTask;
-use future_spawn = future::spawn;
-use result::{Result};
-use libc::size_t;
-use io::{Reader, ReaderUtil, Writer};
+
+use core::io::{Reader, ReaderUtil, Writer};
+use core::io;
+use core::libc::size_t;
+use core::libc;
+use core::oldcomm;
+use core::prelude::*;
+use core::ptr;
+use core::result::{Result};
+use core::result;
+use core::uint;
+use core::vec;
#[nolink]
extern mod rustrt {
- fn rust_uv_current_kernel_malloc(size: libc::c_uint) -> *libc::c_void;
- fn rust_uv_current_kernel_free(mem: *libc::c_void);
- fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_current_kernel_malloc(size: libc::c_uint)
+ -> *libc::c_void;
+ unsafe fn rust_uv_current_kernel_free(mem: *libc::c_void);
+ unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
}
/**
err_msg: ~str
};
/// Details returned as part of a `result::err` result from `tcp::listen`
-enum TcpListenErrData {
+pub enum TcpListenErrData {
/**
* Some unplanned-for error. The first and second fields correspond
* to libuv's `err_name` and `err_msg` fields, respectively.
* * `timeout_msecs` - a `uint` value, in msecs, to wait before dropping the
* read attempt. Pass `0u` to wait indefinitely
*/
-fn read(sock: &TcpSocket, timeout_msecs: uint)
+pub fn read(sock: &TcpSocket, timeout_msecs: uint)
-> result::Result<~[u8],TcpErrData> {
let socket_data = ptr::addr_of(&(*(sock.socket_data)));
read_common_impl(socket_data, timeout_msecs)
let mut data = ~[];
self.data.buf <-> data;
- vec::bytes::memcpy(buf, vec::view(data, 0, data.len()), count);
+ vec::bytes::copy_memory(buf, vec::view(data, 0, data.len()), count);
self.data.buf.push_all(vec::view(data, count, data.len()));
// shared implementation for tcp::read
fn read_common_impl(socket_data: *TcpSocketData, timeout_msecs: uint)
-> result::Result<~[u8],TcpErrData> unsafe {
+ use timer;
+
log(debug, ~"starting tcp::read");
let iotask = (*socket_data).iotask;
let rs_result = read_start_common_impl(socket_data);
};
//#[cfg(test)]
-mod test {
+pub mod test {
+ use net::ip;
+ use net::tcp::{GenericListenErr, TcpConnectErrData, TcpListenErrData};
+ use net::tcp::{connect, accept, read, listen, TcpSocket, socket_buf};
+ use net;
+ use uv::iotask::IoTask;
+ use uv;
+
+ use core::io;
+ use core::oldcomm;
+ use core::prelude::*;
+ use core::result;
+ use core::str;
+ use core::task;
+ use core::vec;
+
// FIXME don't run on fbsd or linux 32 bit (#2064)
#[cfg(target_os="win32")]
#[cfg(target_os="darwin")]
#[cfg(target_os="linux")]
- mod tcp_ipv4_server_and_client_test {
+ #[cfg(target_os="android")]
+ pub mod tcp_ipv4_server_and_client_test {
#[cfg(target_arch="x86_64")]
- mod impl64 {
+ pub mod impl64 {
+ use net::tcp::test::*;
+
#[test]
fn test_gl_tcp_server_and_client_ipv4() unsafe {
+ use net::tcp::test::tcp_ipv4_server_and_client_test::*;
impl_gl_tcp_ipv4_server_and_client();
}
#[test]
fn test_gl_tcp_server_access_denied() unsafe {
impl_gl_tcp_ipv4_server_access_denied();
}
+ // Strange failure on Windows. --pcwalton
#[test]
+ #[ignore(cfg(target_os = "win32"))]
fn test_gl_tcp_ipv4_server_client_reader_writer() {
impl_gl_tcp_ipv4_server_client_reader_writer();
}
}
}
#[cfg(target_arch="x86")]
- mod impl32 {
+ #[cfg(target_arch="arm")]
+ pub mod impl32 {
+ use net::tcp::test::*;
+
#[test]
#[ignore(cfg(target_os = "linux"))]
fn test_gl_tcp_server_and_client_ipv4() unsafe {
}
#[test]
#[ignore(cfg(target_os = "linux"))]
+ #[ignore(cfg(target_os = "win32"))]
fn test_gl_tcp_ipv4_server_client_reader_writer() {
impl_gl_tcp_ipv4_server_client_reader_writer();
}
}
}
- fn impl_gl_tcp_ipv4_server_and_client() {
+ pub fn impl_gl_tcp_ipv4_server_and_client() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 8888u;
assert str::contains(actual_req, expected_req);
assert str::contains(actual_resp, expected_resp);
}
- fn impl_gl_tcp_ipv4_get_peer_addr() {
+ pub fn impl_gl_tcp_ipv4_get_peer_addr() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 8887u;
client_ch.send(str::from_bytes(read_result.get()));
};
}
- fn impl_gl_tcp_ipv4_client_error_connection_refused() {
+ pub fn impl_gl_tcp_ipv4_client_error_connection_refused() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 8889u;
_ => fail ~"unknown error.. expected connection_refused"
}
}
- fn impl_gl_tcp_ipv4_server_address_in_use() {
+ pub fn impl_gl_tcp_ipv4_server_address_in_use() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 8890u;
}
}
}
- fn impl_gl_tcp_ipv4_server_access_denied() {
+ pub fn impl_gl_tcp_ipv4_server_access_denied() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 80u;
}
}
}
- fn impl_gl_tcp_ipv4_server_client_reader_writer() {
- /*
- XXX: Causes an ICE.
+ pub fn impl_gl_tcp_ipv4_server_client_reader_writer() {
let iotask = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let expected_req = ~"ping";
let expected_resp = ~"pong";
- let server_result_po = core::comm::port::<~str>();
- let server_result_ch = core::comm::chan(server_result_po);
+ let server_result_po = oldcomm::Port::<~str>();
+ let server_result_ch = oldcomm::Chan(&server_result_po);
- let cont_po = core::comm::port::<()>();
- let cont_ch = core::comm::chan(cont_po);
+ let cont_po = oldcomm::Port::<()>();
+ let cont_ch = oldcomm::Chan(&cont_po);
// server
do task::spawn_sched(task::ManualThreads(1u)) {
- let actual_req = do comm::listen |server_ch| {
+ let actual_req = do oldcomm::listen |server_ch| {
run_tcp_test_server(
server_ip,
server_port,
};
server_result_ch.send(actual_req);
};
- core::comm::recv(cont_po);
+ oldcomm::recv(cont_po);
// client
let server_addr = ip::v4::parse_addr(server_ip);
let conn_result = connect(server_addr, server_port, iotask);
- if result::is_err(conn_result) {
+ if result::is_err(&conn_result) {
assert false;
}
let sock_buf = @socket_buf(result::unwrap(conn_result));
buf_write(sock_buf, expected_req);
// so contrived!
- let actual_resp = do str::as_bytes(expected_resp) |resp_buf| {
- buf_read(sock_buf, vec::len(resp_buf))
+ let actual_resp = do str::as_bytes(&expected_resp) |resp_buf| {
+ buf_read(sock_buf, resp_buf.len())
};
- let actual_req = core::comm::recv(server_result_po);
+ let actual_req = oldcomm::recv(server_result_po);
log(debug, fmt!("REQ: expected: '%s' actual: '%s'",
expected_req, actual_req));
log(debug, fmt!("RESP: expected: '%s' actual: '%s'",
expected_resp, actual_resp));
assert str::contains(actual_req, expected_req);
assert str::contains(actual_resp, expected_resp);
- */
}
- fn impl_tcp_socket_impl_reader_handles_eof() {
- use io::{Reader,ReaderUtil};
+ pub fn impl_tcp_socket_impl_reader_handles_eof() {
+ use core::io::{Reader,ReaderUtil};
+
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 10041u;
//! Types/fns concerning URLs (see RFC 3986)
#[forbid(deprecated_mode)];
-use io::ReaderUtil;
-use send_map::linear::LinearMap;
+use map;
+use map::HashMap;
+
+use core::cmp::Eq;
+use core::dvec::DVec;
+use core::from_str::FromStr;
+use core::io::{Reader, ReaderUtil};
+use core::io;
+use core::prelude::*;
+use core::send_map::linear::LinearMap;
+use core::send_map;
+use core::str;
+use core::to_bytes::IterBytes;
+use core::to_bytes;
+use core::to_str::ToStr;
+use core::to_str;
+use core::uint;
+use core::util;
+use core::vec;
#[deriving_eq]
struct Url {
Ok(Url::new(scheme, userinfo, host, port, path, query, fragment))
}
-impl Url: from_str::FromStr {
+impl Url: FromStr {
static pure fn from_str(s: &str) -> Option<Url> {
match from_str(s) {
Ok(move url) => Some(url),
#[cfg(test)]
mod tests {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use net_url::*;
+ use net_url::UserInfo;
+
+ use core::result;
+ use core::str;
+
#[test]
fn test_split_char_first() {
let (u,v) = split_char_first(~"hello, sweet world", ',');
#[test]
fn test_decode_form_urlencoded() {
+ // FIXME #4449: Commented out because this causes an ICE, but only
+ // on FreeBSD
+ /*
assert decode_form_urlencoded(~[]).len() == 0;
let s = str::to_bytes("a=1&foo+bar=abc&foo+bar=12+%3D+34");
assert form.len() == 2;
assert form.get_ref(&~"a") == &~[~"1"];
assert form.get_ref(&~"foo bar") == &~[~"abc", ~"12 = 34"];
+ */
}
}
#[forbid(deprecated_mode)];
+use core::cast;
+use core::prelude::*;
+use core::ptr;
+use core::sys;
+use core::uint;
+use core::vec;
+
use future_spawn = future::spawn;
#[forbid(deprecated_mode)];
-use io::Writer;
-use io::WriterUtil;
use serialize;
-pub struct Encoder {
+use core::io::Writer;
+use core::io::WriterUtil;
+use core::io;
+
+pub struct Serializer {
wr: io::Writer,
}
-pub fn Encoder(wr: io::Writer) -> Encoder {
- Encoder { wr: wr }
+pub fn Serializer(wr: io::Writer) -> Serializer {
+ Serializer { wr: wr }
}
-pub impl Encoder: serialize::Encoder {
+pub impl Serializer: serialize::Encoder {
fn emit_nil(&self) {
self.wr.write_str(~"()")
}
//! A priority queue implemented with a binary heap
use core::cmp::Ord;
-use ptr::addr_of;
+use core::prelude::*;
+use core::ptr::addr_of;
+use core::vec;
#[abi = "rust-intrinsic"]
extern "C" mod rusti {
// FIXME #3921. This is unsafe because linenoise uses global mutable
// state without mutexes.
-use libc::{c_char, c_int};
+use core::libc::{c_char, c_int};
+use core::prelude::*;
+use core::str;
+use core::task;
extern mod rustrt {
#[legacy_exports];
- fn linenoise(prompt: *c_char) -> *c_char;
- fn linenoiseHistoryAdd(line: *c_char) -> c_int;
- fn linenoiseHistorySetMaxLen(len: c_int) -> c_int;
- fn linenoiseHistorySave(file: *c_char) -> c_int;
- fn linenoiseHistoryLoad(file: *c_char) -> c_int;
- fn linenoiseSetCompletionCallback(callback: *u8);
- fn linenoiseAddCompletion(completions: *(), line: *c_char);
+ unsafe fn linenoise(prompt: *c_char) -> *c_char;
+ unsafe fn linenoiseHistoryAdd(line: *c_char) -> c_int;
+ unsafe fn linenoiseHistorySetMaxLen(len: c_int) -> c_int;
+ unsafe fn linenoiseHistorySave(file: *c_char) -> c_int;
+ unsafe fn linenoiseHistoryLoad(file: *c_char) -> c_int;
+ unsafe fn linenoiseSetCompletionCallback(callback: *u8);
+ unsafe fn linenoiseAddCompletion(completions: *(), line: *c_char);
}
/// Add a line to history
}
rustrt::linenoiseSetCompletionCallback(callback);
-}
\ No newline at end of file
+}
#[forbid(deprecated_mode)];
+use core::cast;
+use core::char;
+use core::option;
+use core::prelude::*;
+use core::str;
+use core::uint;
+use core::vec;
+
/// The type of ropes.
pub type Rope = node::Root;
pub mod iterator {
pub mod leaf {
+ use rope::{Rope, node};
+
+ use core::prelude::*;
+
pub fn start(rope: Rope) -> node::leaf_iterator::T {
match (rope) {
node::Empty => return node::leaf_iterator::empty(),
}
}
pub mod char {
+ use rope::{Rope, node};
+
+ use core::prelude::*;
+
pub fn start(rope: Rope) -> node::char_iterator::T {
match (rope) {
node::Empty => return node::char_iterator::empty(),
/*
Section: Implementation
*/
-mod node {
+pub mod node {
+ use rope::node;
+
+ use core::cast;
+ use core::char;
+ use core::option;
+ use core::prelude::*;
+ use core::str;
+ use core::uint;
+ use core::vec;
/// Implementation of type `rope`
pub enum Root {
}
pub mod leaf_iterator {
+ use rope::node::{Concat, Leaf, Node, height};
+
+ use core::option;
+ use core::prelude::*;
+ use core::vec;
+
pub type T = {
stack: ~[mut @Node],
mut stackpos: int
}
pub mod char_iterator {
+ use rope::node::{Leaf, Node};
+ use rope::node::leaf_iterator;
+
+ use core::option;
+ use core::prelude::*;
+ use core::str;
+
pub type T = {
leaf_iterator: leaf_iterator::T,
mut leaf: Option<Leaf>,
#[cfg(test)]
mod tests {
+ use rope::*;
+
+ use core::option;
+ use core::str;
+ use core::uint;
+ use core::vec;
//Utility function, used for sanity check
fn rope_to_string(r: Rope) -> ~str {
#[forbid(deprecated_mode)];
#[forbid(non_camel_case_types)];
+use core::at_vec;
+use core::prelude::*;
+use core::vec;
+
pub trait Encoder {
// Primitive types:
fn emit_nil(&self);
#[forbid(deprecated_mode)];
+use core::str;
+use core::uint;
+use core::vec;
+
/*
* A SHA-1 implementation derived from Paul E. Jones's reference
* implementation, which is written for clarity, not speed. At some
/// The SHA-1 interface
trait Sha1 {
/// Provide message input as bytes
- fn input((&[u8]));
+ fn input(&[const u8]);
/// Provide message input as string
- fn input_str((&str));
+ fn input_str(&str);
/**
* Read the digest as a vector of 20 bytes. After calling this no further
* input may be provided until reset is called.
mut computed: bool,
work_buf: @~[mut u32]};
- fn add_input(st: &Sha1State, msg: &[u8]) {
+ fn add_input(st: &Sha1State, msg: &[const u8]) {
assert (!st.computed);
- for vec::each(msg) |element| {
+ for vec::each_const(msg) |element| {
st.msg_block[st.msg_block_idx] = *element;
st.msg_block_idx += 1u;
st.len_low += 8u32;
self.h[4] = 0xC3D2E1F0u32;
self.computed = false;
}
- fn input(msg: &[u8]) { add_input(&self, msg); }
+ fn input(msg: &[const u8]) { add_input(&self, msg); }
fn input_str(msg: &str) {
let bs = str::to_bytes(msg);
add_input(&self, bs);
mod tests {
#[legacy_exports];
+ use sha1;
+
+ use core::str;
+ use core::vec;
+
#[test]
fn test() unsafe {
type Test = {input: ~str, output: ~[u8]};
*/
#[forbid(deprecated_mode)];
-use core::option;
-use core::option::{Some, None};
-use dvec::DVec;
+use map;
use map::Map;
+use core::dvec::DVec;
+use core::ops;
+use core::option::{Some, None};
+use core::option;
+use core::prelude::*;
+
// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
// requires this to be.
type SmallIntMap_<T: Copy> = {v: DVec<Option<T>>};
#[cfg(test)]
mod tests {
+ use smallintmap::{mk, SmallIntMap};
+
+ use core::option::None;
+ use core::option;
#[test]
fn test_insert_with_key() {
//! Sorting methods
#[forbid(deprecated_mode)];
-use vec::{len, push};
use core::cmp::{Eq, Ord};
-use dvec::DVec;
+use core::dvec::DVec;
+use core::prelude::*;
+use core::util;
+use core::vec::{len, push};
+use core::vec;
type Le<T> = pure fn(v1: &T, v2: &T) -> bool;
#[cfg(test)]
mod test_qsort3 {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use sort::*;
+
+ use core::vec;
+
fn check_sort(v1: &[mut int], v2: &[mut int]) {
let len = vec::len::<int>(v1);
quick_sort3::<int>(v1);
#[cfg(test)]
mod test_qsort {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use sort::*;
+
+ use core::int;
+ use core::vec;
+
fn check_sort(v1: &[mut int], v2: &[mut int]) {
let len = vec::len::<int>(v1);
pure fn leual(a: &int, b: &int) -> bool { *a <= *b }
mod tests {
#[legacy_exports];
+ use core::prelude::*;
+
+ use sort::*;
+
+ use core::vec;
+
fn check_sort(v1: &[int], v2: &[int]) {
let len = vec::len::<int>(v1);
pub pure fn le(a: &int, b: &int) -> bool { *a <= *b }
#[cfg(test)]
mod test_tim_sort {
+ use core::prelude::*;
+
+ use sort::tim_sort;
+
+ use core::rand;
+ use core::vec;
+
struct CVal {
val: float,
}
#[cfg(test)]
mod big_tests {
+ use core::prelude::*;
+
+ use sort::*;
+
+ use core::rand;
+ use core::task;
+ use core::uint;
+ use core::vec;
#[test]
fn test_unique() {
#[license = "MIT"];
#[crate_type = "lib"];
-#[no_core];
-
#[allow(vecs_implicitly_copyable)];
#[deny(non_camel_case_types)];
// XXX this is set to allow because there are two methods in encoding
#[allow(deprecated_mode)];
#[forbid(deprecated_pattern)];
+#[no_core];
+
extern mod core(vers = "0.6");
use core::*;
pub mod c_vec;
pub mod timer;
pub mod cell;
+pub mod io_util;
// Concurrency
pub mod base64;
pub mod rl;
pub mod workcache;
+pub mod bigint;
#[cfg(unicode)]
mod unicode;
* in std.
*/
-use private::{Exclusive, exclusive};
+use core::option;
+use core::pipes;
+use core::prelude::*;
+use core::private::{Exclusive, exclusive};
+use core::ptr;
+use core::task;
+use core::util;
+use core::vec;
/****************************************************************************
* Internals
struct Semaphore { priv sem: Sem<()> }
/// Create a new semaphore with the specified count.
-fn semaphore(count: int) -> Semaphore {
+pub fn semaphore(count: int) -> Semaphore {
Semaphore { sem: new_sem(count, ()) }
}
* unwinds.
*/
struct RWlock {
- /* priv */ order_lock: Semaphore,
- /* priv */ access_lock: Sem<~[mut Waitqueue]>,
- /* priv */ state: Exclusive<RWlockInner>
+ priv order_lock: Semaphore,
+ priv access_lock: Sem<~[mut Waitqueue]>,
+ priv state: Exclusive<RWlockInner>
}
/// Create a new rwlock, with one associated condvar.
}
/// The "write permission" token used for rwlock.write_downgrade().
-pub struct RWlockWriteMode { /* priv */ lock: &RWlock }
+pub struct RWlockWriteMode { priv lock: &RWlock }
impl RWlockWriteMode : Drop { fn finalize(&self) {} }
/// The "read permission" token used for rwlock.write_downgrade().
pub struct RWlockReadMode { priv lock: &RWlock }
#[cfg(test)]
mod tests {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use sync::*;
+
+ use core::cast;
+ use core::option;
+ use core::pipes;
+ use core::ptr;
+ use core::result;
+ use core::task;
+ use core::vec;
+
/************************************************************************
* Semaphore tests
************************************************************************/
/// A task pool abstraction. Useful for achieving predictable CPU
/// parallelism.
-use pipes::{Chan, Port};
-use task::{SchedMode, SingleThreaded};
+use core::io;
+use core::pipes::{Chan, Port};
+use core::pipes;
+use core::prelude::*;
+use core::task::{SchedMode, SingleThreaded};
+use core::task;
+use core::vec;
enum Msg<T> {
Execute(~fn(&T)),
#[forbid(deprecated_mode)];
-use core::option;
-use option::{None, Some};
+use core::os;
+use core::prelude::*;
+use core::rand;
+use core::str;
pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
let r = rand::Rng();
//! Simple ANSI color library
#[forbid(deprecated_mode)];
-use core::Option;
+use core::i32;
+use core::io;
+use core::option;
+use core::os;
+use core::str;
+use core::vec;
// FIXME (#2807): Windows support.
#[forbid(deprecated_mode)];
+use getopts;
+use sort;
+use term;
+
use core::cmp::Eq;
-use either::Either;
-use result::{Ok, Err};
-use io::WriterUtil;
-use libc::size_t;
-use task::TaskBuilder;
+use core::either::Either;
+use core::either;
+use core::io::WriterUtil;
+use core::io;
+use core::libc::size_t;
+use core::oldcomm;
+use core::option;
+use core::prelude::*;
+use core::result;
+use core::str;
+use core::task::TaskBuilder;
+use core::task;
+use core::vec;
#[abi = "cdecl"]
extern mod rustrt {
#[legacy_exports];
- fn rust_sched_threads() -> libc::size_t;
+ unsafe fn rust_sched_threads() -> size_t;
}
// The name of a test. By convention this follows the rules for rust
// The definition of a single test. A test runner will run a list of
// these.
-pub type TestDesc = {
+pub struct TestDesc {
name: TestName,
testfn: TestFn,
ignore: bool,
should_fail: bool
-};
+}
// The default console test runner. It accepts the command line
// arguments and a vector of test_descs (generated at compile time).
type OptRes = Either<TestOpts, ~str>;
// Parses command line arguments into test options
-fn parse_opts(args: &[~str]) -> OptRes {
+pub fn parse_opts(args: &[~str]) -> OptRes {
let args_ = vec::tail(args);
let opts = ~[getopts::optflag(~"ignored"), getopts::optopt(~"logfile")];
let matches =
#[test]
fn should_sort_failures_before_printing_them() {
let s = do io::with_str_writer |wr| {
- let test_a = {
+ let test_a = TestDesc {
name: ~"a",
testfn: fn~() { },
ignore: false,
should_fail: false
};
- let test_b = {
+ let test_b = TestDesc {
name: ~"b",
testfn: fn~() { },
ignore: false,
type MonitorMsg = (TestDesc, TestResult);
-fn run_tests(opts: &TestOpts, tests: &[TestDesc],
+fn run_tests(opts: &TestOpts,
+ tests: &[TestDesc],
callback: fn@(e: TestEvent)) {
-
let mut filtered_tests = filter_tests(opts, tests);
callback(TeFiltered(copy filtered_tests));
const sched_overcommit : uint = 4u;
fn get_concurrency() -> uint {
- let threads = rustrt::rust_sched_threads() as uint;
- if threads == 1u { 1u }
- else { threads * sched_overcommit }
+ unsafe {
+ let threads = rustrt::rust_sched_threads() as uint;
+ if threads == 1u { 1u }
+ else { threads * sched_overcommit }
+ }
}
#[allow(non_implicitly_copyable_typarams)]
-fn filter_tests(opts: &TestOpts,
- tests: &[TestDesc]) -> ~[TestDesc] {
+pub fn filter_tests(opts: &TestOpts,
+ tests: &[TestDesc])
+ -> ~[TestDesc] {
let mut filtered = vec::slice(tests, 0, tests.len());
// Remove tests that don't match the test filter
} else {
fn filter(test: &TestDesc) -> Option<TestDesc> {
if test.ignore {
- return option::Some({name: test.name,
- testfn: copy test.testfn,
- ignore: false,
- should_fail: test.should_fail});
+ return option::Some(TestDesc {
+ name: test.name,
+ testfn: copy test.testfn,
+ ignore: false,
+ should_fail: test.should_fail});
} else { return option::None; }
};
type TestFuture = {test: TestDesc, wait: fn@() -> TestResult};
-fn run_test(test: TestDesc, monitor_ch: oldcomm::Chan<MonitorMsg>) {
+pub fn run_test(test: TestDesc, monitor_ch: oldcomm::Chan<MonitorMsg>) {
if test.ignore {
oldcomm::send(monitor_ch, (copy test, TrIgnored));
return;
mod tests {
#[legacy_exports];
+ use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc};
+ use test::{run_test};
+
+ use core::either;
+ use core::oldcomm;
+ use core::option;
+ use core::vec;
+
#[test]
fn do_not_run_ignored_tests() {
fn f() { fail; }
- let desc = {
+ let desc = TestDesc {
name: ~"whatever",
testfn: f,
ignore: true,
#[test]
fn ignored_tests_result_in_ignored() {
fn f() { }
- let desc = {
+ let desc = TestDesc {
name: ~"whatever",
testfn: f,
ignore: true,
#[ignore(cfg(windows))]
fn test_should_fail() {
fn f() { fail; }
- let desc = {
+ let desc = TestDesc {
name: ~"whatever",
testfn: f,
ignore: false,
#[test]
fn test_should_fail_but_succeeds() {
fn f() { }
- let desc = {
+ let desc = TestDesc {
name: ~"whatever",
testfn: f,
ignore: false,
let opts = {filter: option::None, run_ignored: true,
logfile: option::None};
let tests =
- ~[{name: ~"1", testfn: fn~() { },
- ignore: true, should_fail: false},
- {name: ~"2", testfn: fn~() { },
- ignore: false, should_fail: false}];
+ ~[TestDesc {name: ~"1", testfn: fn~() { },
+ ignore: true, should_fail: false},
+ TestDesc {name: ~"2", testfn: fn~() { },
+ ignore: false, should_fail: false}];
let filtered = filter_tests(&opts, tests);
assert (vec::len(filtered) == 1u);
let testfn = fn~() { };
let mut tests = ~[];
for vec::each(names) |name| {
- let test = {name: *name, testfn: copy testfn, ignore: false,
- should_fail: false};
+ let test = TestDesc {
+ name: *name, testfn: copy testfn, ignore: false,
+ should_fail: false};
tests.push(move test);
}
move tests
#[forbid(deprecated_mode)];
use core::cmp::Eq;
-use libc::{c_char, c_int, c_long, size_t, time_t};
-use io::{Reader, ReaderUtil};
-use result::{Result, Ok, Err};
+use core::int;
+use core::libc::{c_char, c_int, c_long, size_t, time_t};
+use core::i32;
+use core::io::{Reader, ReaderUtil};
+use core::io;
+use core::prelude::*;
+use core::result::{Result, Ok, Err};
+use core::str;
#[abi = "cdecl"]
extern mod rustrt {
#[legacy_exports]
- fn get_time(sec: &mut i64, nsec: &mut i32);
+ unsafe fn get_time(sec: &mut i64, nsec: &mut i32);
- fn precise_time_ns(ns: &mut u64);
+ unsafe fn precise_time_ns(ns: &mut u64);
- fn rust_tzset();
+ unsafe fn rust_tzset();
// FIXME: The i64 values can be passed by-val when #2064 is fixed.
- fn rust_gmtime(&&sec: i64, &&nsec: i32, &&result: Tm);
- fn rust_localtime(&&sec: i64, &&nsec: i32, &&result: Tm);
- fn rust_timegm(&&tm: Tm, sec: &mut i64);
- fn rust_mktime(&&tm: Tm, sec: &mut i64);
+ unsafe fn rust_gmtime(&&sec: i64, &&nsec: i32, &&result: Tm);
+ unsafe fn rust_localtime(&&sec: i64, &&nsec: i32, &&result: Tm);
+ unsafe fn rust_timegm(&&tm: Tm, sec: &mut i64);
+ unsafe fn rust_mktime(&&tm: Tm, sec: &mut i64);
}
/// A record specifying a time value in seconds and nanoseconds.
* nanoseconds since 1970-01-01T00:00:00Z.
*/
pub fn get_time() -> Timespec {
- let mut sec = 0i64;
- let mut nsec = 0i32;
- rustrt::get_time(&mut sec, &mut nsec);
- return Timespec::new(sec, nsec);
+ unsafe {
+ let mut sec = 0i64;
+ let mut nsec = 0i32;
+ rustrt::get_time(&mut sec, &mut nsec);
+ return Timespec::new(sec, nsec);
+ }
}
* in nanoseconds since an unspecified epoch.
*/
pub fn precise_time_ns() -> u64 {
- let mut ns = 0u64;
- rustrt::precise_time_ns(&mut ns);
- ns
+ unsafe {
+ let mut ns = 0u64;
+ rustrt::precise_time_ns(&mut ns);
+ ns
+ }
}
}
pub fn tzset() {
- rustrt::rust_tzset();
+ unsafe {
+ rustrt::rust_tzset();
+ }
}
#[auto_encode]
/// Returns the specified time in UTC
pub fn at_utc(clock: Timespec) -> Tm {
- let mut Timespec { sec, nsec } = clock;
- let mut tm = empty_tm();
- rustrt::rust_gmtime(sec, nsec, tm);
- move tm
+ unsafe {
+ let mut Timespec { sec, nsec } = clock;
+ let mut tm = empty_tm();
+ rustrt::rust_gmtime(sec, nsec, tm);
+ move tm
+ }
}
/// Returns the current time in UTC
/// Returns the specified time in the local timezone
pub fn at(clock: Timespec) -> Tm {
- let mut Timespec { sec, nsec } = clock;
- let mut tm = empty_tm();
- rustrt::rust_localtime(sec, nsec, tm);
- move tm
+ unsafe {
+ let mut Timespec { sec, nsec } = clock;
+ let mut tm = empty_tm();
+ rustrt::rust_localtime(sec, nsec, tm);
+ move tm
+ }
}
/// Returns the current time in the local timezone
impl Tm {
/// Convert time to the seconds from January 1, 1970
fn to_timespec() -> Timespec {
- let mut sec = 0i64;
- if self.tm_gmtoff == 0_i32 {
- rustrt::rust_timegm(self, &mut sec);
- } else {
- rustrt::rust_mktime(self, &mut sec);
+ unsafe {
+ let mut sec = 0i64;
+ if self.tm_gmtoff == 0_i32 {
+ rustrt::rust_timegm(self, &mut sec);
+ } else {
+ rustrt::rust_mktime(self, &mut sec);
+ }
+ Timespec::new(sec, self.tm_nsec)
}
- Timespec::new(sec, self.tm_nsec)
}
/// Convert time to the local timezone
mod tests {
#[legacy_exports];
+ use time::*;
+
+ use core::float;
+ use core::os;
+ use core::result;
+ use core::str;
+ use core::u64;
+ use core::uint;
+ use core::vec;
+
#[test]
fn test_get_time() {
const some_recent_date: i64 = 1325376000i64; // 2012-01-01T00:00:00Z
os::setenv(~"TZ", ~"America/Los_Angeles");
tzset();
- let time = Timespec::new(1234567890, 54321);
+ let time = ::time::Timespec::new(1234567890, 54321);
let utc = at_utc(time);
assert utc.tm_sec == 30_i32;
os::setenv(~"TZ", ~"America/Los_Angeles");
tzset();
- let time = Timespec::new(1234567890, 54321);
+ let time = ::time::Timespec::new(1234567890, 54321);
let local = at(time);
error!("time_at: %?", local);
os::setenv(~"TZ", ~"America/Los_Angeles");
tzset();
- let time = Timespec::new(1234567890, 54321);
+ let time = ::time::Timespec::new(1234567890, 54321);
let utc = at_utc(time);
assert utc.to_timespec() == time;
os::setenv(~"TZ", ~"America/Los_Angeles");
tzset();
- let time = Timespec::new(1234567890, 54321);
+ let time = ::time::Timespec::new(1234567890, 54321);
let utc = at_utc(time);
let local = at(time);
os::setenv(~"TZ", ~"America/Los_Angeles");
tzset();
- let time = Timespec::new(1234567890, 54321);
+ let time = ::time::Timespec::new(1234567890, 54321);
let utc = at_utc(time);
let local = at(time);
os::setenv(~"TZ", ~"America/Los_Angeles");
tzset();
- let time = Timespec::new(1234567890, 54321);
+ let time = ::time::Timespec::new(1234567890, 54321);
let utc = at_utc(time);
let local = at(time);
#[forbid(deprecated_mode)];
+use uv;
use uv::iotask;
use uv::iotask::IoTask;
+use core::either;
+use core::libc;
+use core::oldcomm;
+use core::prelude::*;
+use core::ptr;
+use core;
+
/**
* Wait for timeout period then send provided value over a channel
*
* * val - a value of type T to send over the provided `ch`
*/
pub fn delayed_send<T: Owned>(iotask: IoTask,
- msecs: uint, ch: oldcomm::Chan<T>, val: T) {
+ msecs: uint,
+ ch: oldcomm::Chan<T>,
+ val: T) {
unsafe {
let timer_done_po = oldcomm::Port::<()>();
let timer_done_ch = oldcomm::Chan(&timer_done_po);
* be a `some(T)`. If not, then `none` will be returned.
*/
pub fn recv_timeout<T: Copy Owned>(iotask: IoTask,
- msecs: uint,
- wait_po: oldcomm::Port<T>) -> Option<T> {
+ msecs: uint,
+ wait_po: oldcomm::Port<T>)
+ -> Option<T> {
let timeout_po = oldcomm::Port::<()>();
let timeout_ch = oldcomm::Chan(&timeout_po);
delayed_send(iotask, msecs, timeout_ch, ());
#[cfg(test)]
mod test {
#[legacy_exports];
+
+ use core::prelude::*;
+
+ use timer::*;
+ use uv;
+
+ use core::iter;
+ use core::oldcomm;
+ use core::rand;
+ use core::task;
+
#[test]
fn test_gl_timer_simple_sleep_test() {
let hl_loop = uv::global_loop::get();
#[forbid(deprecated_mode)];
use core::cmp::{Eq, Ord};
-use core::option::{Some, None};
-use Option = core::Option;
+use core::option::{Option, Some, None};
+use core::prelude::*;
pub type TreeMap<K: Copy Eq Ord, V: Copy> = @mut TreeEdge<K, V>;
mod tests {
#[legacy_exports];
+ use treemap::*;
+
+ use core::option::{None, Option, Some};
+ use core::str;
+
#[test]
fn init_treemap() { let _m = TreeMap::<int, int>(); }
#[link_name = "icuuc"]
#[abi = "cdecl"]
pub extern mod libicu {
- pure fn u_hasBinaryProperty(c: UChar32, which: UProperty) -> UBool;
- pure fn u_isdigit(c: UChar32) -> UBool;
- pure fn u_islower(c: UChar32) -> UBool;
- pure fn u_isspace(c: UChar32) -> UBool;
- pure fn u_isupper(c: UChar32) -> UBool;
- pure fn u_tolower(c: UChar32) -> UChar32;
- pure fn u_toupper(c: UChar32) -> UChar32;
+ unsafe fn u_hasBinaryProperty(c: UChar32, which: UProperty) -> UBool;
+ unsafe fn u_isdigit(c: UChar32) -> UBool;
+ unsafe fn u_islower(c: UChar32) -> UBool;
+ unsafe fn u_isspace(c: UChar32) -> UBool;
+ unsafe fn u_isupper(c: UChar32) -> UBool;
+ unsafe fn u_tolower(c: UChar32) -> UChar32;
+ unsafe fn u_toupper(c: UChar32) -> UChar32;
}
}
use iotask = uv_iotask;
use get_gl = get;
use uv_iotask::{IoTask, spawn_iotask};
-use private::{chan_from_global_ptr, weaken_task};
+
+use core::either::{Left, Right};
+use core::libc;
use core::oldcomm::{Port, Chan, select2, listen};
-use task::TaskBuilder;
-use either::{Left, Right};
+use core::private::{chan_from_global_ptr, weaken_task};
+use core::str;
+use core::task::TaskBuilder;
+use core::task;
+use core::vec;
extern mod rustrt {
- fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
+ unsafe fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
}
/**
#[cfg(test)]
mod test {
+ use core::prelude::*;
+
+ use uv::iotask;
+ use uv::ll;
+ use uv_global_loop::*;
+
+ use core::iter;
+ use core::libc;
+ use core::oldcomm;
+ use core::ptr;
+ use core::task;
+
extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) unsafe {
let exit_ch_ptr = ll::get_data_for_uv_handle(
timer_ptr as *libc::c_void) as *oldcomm::Chan<bool>;
*/
#[forbid(deprecated_mode)];
-use libc::c_void;
-use ptr::addr_of;
-use core::oldcomm::{Port, Chan, listen};
-use task::TaskBuilder;
use ll = uv_ll;
+use core::libc::c_void;
+use core::libc;
+use core::oldcomm::{Port, Chan, listen};
+use core::prelude::*;
+use core::ptr::addr_of;
+use core::task::TaskBuilder;
+use core::task;
+
/// Used to abstract-away direct interaction with a libuv loop.
pub enum IoTask {
IoTask_({
#[cfg(test)]
mod test {
+ use core::prelude::*;
+
+ use uv::ll;
+ use uv_iotask::*;
+
+ use core::iter;
+ use core::libc;
+ use core::oldcomm;
+ use core::ptr;
+ use core::task;
+
extern fn async_close_cb(handle: *ll::uv_async_t) unsafe {
log(debug, fmt!("async_close_cb handle %?", handle));
let exit_ch = (*(ll::get_data_for_uv_handle(handle)
#[allow(non_camel_case_types)]; // C types
-use libc::size_t;
-use ptr::to_unsafe_ptr;
+use core::libc::size_t;
+use core::libc;
+use core::prelude::*;
+use core::ptr::to_unsafe_ptr;
+use core::ptr;
+use core::str;
+use core::vec;
// libuv struct mappings
pub type uv_ip4_addr = {
a29: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type uv_tcp_t_32bit_unix_riders = {
a29: *u8, a30: *u8, a31: *u8,
a32: *u8, a33: *u8, a34: *u8,
a13: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type uv_write_t_32bit_unix_riders = {
a13: *u8, a14: *u8
};
a10: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type uv_async_t_32bit_unix_riders = {
a10: *u8, a11: *u8, a12: *u8, a13: *u8
};
a10: *u8, a11: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type uv_timer_t_32bit_unix_riders = {
a10: *u8, a11: *u8, a12: *u8, a13: *u8,
a14: *u8, a15: *u8, a16: *u8
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type sockaddr_in6 = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
a2: *u8, a3: *u8
};
#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
pub type addr_in = {
a0: *u8, a1: *u8,
a2: *u8, a3: *u8,
// unix size: 48, 32bit: 32
pub type addrinfo = addrinfo_impl::addrinfo;
#[cfg(target_os="linux")]
+#[cfg(target_os="android")]
pub mod addrinfo_impl {
#[cfg(target_arch="x86_64")]
pub type addrinfo = {
a04: *u8, a05: *u8
};
#[cfg(target_arch="x86")]
+ #[cfg(target_arch="arm")]
pub type addrinfo = {
a00: *u8, a01: *u8, a02: *u8, a03: *u8,
a04: *u8, a05: *u8, a06: *u8, a07: *u8
};
pub mod uv_ll_struct_stubgen {
+ use uv_ll::{uv_async_t, uv_connect_t, uv_getaddrinfo_t, uv_tcp_t};
+ use uv_ll::{uv_timer_t, uv_write_t};
+
+ use core::ptr;
+
pub fn gen_stub_uv_tcp_t() -> uv_tcp_t {
return gen_stub_os();
#[cfg(target_os = "linux")]
+ #[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub fn gen_stub_os() -> uv_tcp_t {
};
}
#[cfg(target_arch="x86")]
+ #[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_tcp_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
};
}
#[cfg(target_arch = "x86")]
+ #[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_async_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
};
}
#[cfg(target_arch = "x86")]
+ #[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_timer_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
};
}
#[cfg(target_arch="x86")]
+ #[cfg(target_arch="arm")]
pub fn gen_stub_arch() -> uv_write_t {
return { fields: { loop_handle: ptr::null(), type_: 0u32,
close_cb: ptr::null(),
#[nolink]
extern mod rustrt {
// libuv public API
- fn rust_uv_loop_new() -> *libc::c_void;
- fn rust_uv_loop_delete(lp: *libc::c_void);
- fn rust_uv_loop_refcount(loop_ptr: *libc::c_void) -> libc::c_int;
- fn rust_uv_run(loop_handle: *libc::c_void);
- fn rust_uv_close(handle: *libc::c_void, cb: *u8);
- fn rust_uv_async_send(handle: *uv_async_t);
- fn rust_uv_async_init(loop_handle: *libc::c_void,
+ unsafe fn rust_uv_loop_new() -> *libc::c_void;
+ unsafe fn rust_uv_loop_delete(lp: *libc::c_void);
+ unsafe fn rust_uv_loop_refcount(loop_ptr: *libc::c_void) -> libc::c_int;
+ unsafe fn rust_uv_run(loop_handle: *libc::c_void);
+ unsafe fn rust_uv_close(handle: *libc::c_void, cb: *u8);
+ unsafe fn rust_uv_async_send(handle: *uv_async_t);
+ unsafe fn rust_uv_async_init(loop_handle: *libc::c_void,
async_handle: *uv_async_t,
cb: *u8) -> libc::c_int;
- fn rust_uv_tcp_init(
+ unsafe fn rust_uv_tcp_init(
loop_handle: *libc::c_void,
handle_ptr: *uv_tcp_t) -> libc::c_int;
// FIXME ref #2604 .. ?
- fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8,
+ unsafe fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8,
len: libc::size_t);
- fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t;
+ unsafe fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t;
// FIXME ref #2064
- fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char;
+ unsafe fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char;
// FIXME ref #2064
- fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char;
- fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int)
+ unsafe fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char;
+ unsafe fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int)
-> sockaddr_in;
- fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int)
+ unsafe fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int)
-> sockaddr_in6;
- fn rust_uv_ip4_name(src: *sockaddr_in, dst: *u8, size: libc::size_t)
- -> libc::c_int;
- fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: libc::size_t)
- -> libc::c_int;
- fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint;
- fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint;
+ unsafe fn rust_uv_ip4_name(src: *sockaddr_in,
+ dst: *u8,
+ size: libc::size_t)
+ -> libc::c_int;
+ unsafe fn rust_uv_ip6_name(src: *sockaddr_in6,
+ dst: *u8,
+ size: libc::size_t)
+ -> libc::c_int;
+ unsafe fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint;
+ unsafe fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint;
// FIXME ref #2064
- fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
- tcp_handle_ptr: *uv_tcp_t,
- ++after_cb: *u8,
- ++addr: *sockaddr_in) -> libc::c_int;
+ unsafe fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
+ tcp_handle_ptr: *uv_tcp_t,
+ ++after_cb: *u8,
+ ++addr: *sockaddr_in) -> libc::c_int;
// FIXME ref #2064
- fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t,
- ++addr: *sockaddr_in) -> libc::c_int;
+ unsafe fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t,
+ ++addr: *sockaddr_in) -> libc::c_int;
// FIXME ref #2064
- fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t,
- tcp_handle_ptr: *uv_tcp_t,
- ++after_cb: *u8,
- ++addr: *sockaddr_in6) -> libc::c_int;
+ unsafe fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t,
+ tcp_handle_ptr: *uv_tcp_t,
+ ++after_cb: *u8,
+ ++addr: *sockaddr_in6) -> libc::c_int;
// FIXME ref #2064
- fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t,
- ++addr: *sockaddr_in6) -> libc::c_int;
- fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
- ++name: *sockaddr_in) -> libc::c_int;
- fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
- ++name: *sockaddr_in6) ->libc::c_int;
- fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int,
- cb: *u8) -> libc::c_int;
- fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void)
- -> libc::c_int;
- fn rust_uv_write(req: *libc::c_void, stream: *libc::c_void,
- ++buf_in: *uv_buf_t, buf_cnt: libc::c_int,
- cb: *u8) -> libc::c_int;
- fn rust_uv_read_start(stream: *libc::c_void, on_alloc: *u8,
- on_read: *u8) -> libc::c_int;
- fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int;
- fn rust_uv_timer_init(loop_handle: *libc::c_void,
- timer_handle: *uv_timer_t) -> libc::c_int;
- fn rust_uv_timer_start(
+ unsafe fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t,
+ ++addr: *sockaddr_in6) -> libc::c_int;
+ unsafe fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
+ ++name: *sockaddr_in) -> libc::c_int;
+ unsafe fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
+ ++name: *sockaddr_in6) ->libc::c_int;
+ unsafe fn rust_uv_listen(stream: *libc::c_void,
+ backlog: libc::c_int,
+ cb: *u8) -> libc::c_int;
+ unsafe fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void)
+ -> libc::c_int;
+ unsafe fn rust_uv_write(req: *libc::c_void,
+ stream: *libc::c_void,
+ ++buf_in: *uv_buf_t,
+ buf_cnt: libc::c_int,
+ cb: *u8)
+ -> libc::c_int;
+ unsafe fn rust_uv_read_start(stream: *libc::c_void,
+ on_alloc: *u8,
+ on_read: *u8)
+ -> libc::c_int;
+ unsafe fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int;
+ unsafe fn rust_uv_timer_init(loop_handle: *libc::c_void,
+ timer_handle: *uv_timer_t)
+ -> libc::c_int;
+ unsafe fn rust_uv_timer_start(
timer_handle: *uv_timer_t,
cb: *u8,
timeout: libc::c_uint,
repeat: libc::c_uint) -> libc::c_int;
- fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int;
-
- fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void,
- handle: *uv_getaddrinfo_t,
- cb: *u8,
- node_name_ptr: *u8,
- service_name_ptr: *u8,
- // should probably only pass ptr::null()
- hints: *addrinfo) -> libc::c_int;
- fn rust_uv_freeaddrinfo(res: *addrinfo);
+ unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int;
+
+ unsafe fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void,
+ handle: *uv_getaddrinfo_t,
+ cb: *u8,
+ node_name_ptr: *u8,
+ service_name_ptr: *u8,
+ // should probably only pass ptr::null()
+ hints: *addrinfo)
+ -> libc::c_int;
+ unsafe fn rust_uv_freeaddrinfo(res: *addrinfo);
// data accessors/helpers for rust-mapped uv structs
- fn rust_uv_helper_get_INADDR_NONE() -> u32;
- fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool;
- fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool;
- fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo;
- fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in;
- fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6;
- fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8;
- fn rust_uv_free_base_of_buf(++buf: uv_buf_t);
- fn rust_uv_get_stream_handle_from_connect_req(
+ unsafe fn rust_uv_helper_get_INADDR_NONE() -> u32;
+ unsafe fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool;
+ unsafe fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool;
+ unsafe fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo;
+ unsafe fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo)
+ -> *sockaddr_in;
+ unsafe fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo)
+ -> *sockaddr_in6;
+ unsafe fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8;
+ unsafe fn rust_uv_free_base_of_buf(++buf: uv_buf_t);
+ unsafe fn rust_uv_get_stream_handle_from_connect_req(
connect_req: *uv_connect_t)
-> *uv_stream_t;
- fn rust_uv_get_stream_handle_from_write_req(
+ unsafe fn rust_uv_get_stream_handle_from_write_req(
write_req: *uv_write_t)
-> *uv_stream_t;
- fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void)
- -> *libc::c_void;
- fn rust_uv_get_data_for_uv_loop(loop_ptr: *libc::c_void) -> *libc::c_void;
- fn rust_uv_set_data_for_uv_loop(loop_ptr: *libc::c_void,
- data: *libc::c_void);
- fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void)
+ unsafe fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void)
-> *libc::c_void;
- fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void,
- data: *libc::c_void);
- fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void;
- fn rust_uv_set_data_for_req(req: *libc::c_void,
- data: *libc::c_void);
- fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8;
- fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> libc::size_t;
+ unsafe fn rust_uv_get_data_for_uv_loop(loop_ptr: *libc::c_void)
+ -> *libc::c_void;
+ unsafe fn rust_uv_set_data_for_uv_loop(loop_ptr: *libc::c_void,
+ data: *libc::c_void);
+ unsafe fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void)
+ -> *libc::c_void;
+ unsafe fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void,
+ data: *libc::c_void);
+ unsafe fn rust_uv_get_data_for_req(req: *libc::c_void) -> *libc::c_void;
+ unsafe fn rust_uv_set_data_for_req(req: *libc::c_void,
+ data: *libc::c_void);
+ unsafe fn rust_uv_get_base_from_buf(++buf: uv_buf_t) -> *u8;
+ unsafe fn rust_uv_get_len_from_buf(++buf: uv_buf_t) -> libc::size_t;
// sizeof testing helpers
- fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
- fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint;
- fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint;
- fn rust_uv_helper_uv_write_t_size() -> libc::c_uint;
- fn rust_uv_helper_uv_err_t_size() -> libc::c_uint;
- fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint;
- fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint;
- fn rust_uv_helper_uv_async_t_size() -> libc::c_uint;
- fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint;
- fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint;
- fn rust_uv_helper_addrinfo_size() -> libc::c_uint;
- fn rust_uv_helper_addr_in_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_write_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_err_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_async_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_addrinfo_size() -> libc::c_uint;
+ unsafe fn rust_uv_helper_addr_in_size() -> libc::c_uint;
}
pub unsafe fn loop_new() -> *libc::c_void {
#[cfg(test)]
pub mod test {
+ use core::prelude::*;
+
+ use uv_ll::*;
+
+ use core::libc;
+ use core::oldcomm;
+ use core::ptr;
+ use core::str;
+ use core::sys;
+ use core::task;
+ use core::vec;
enum tcp_read_data {
tcp_read_eof,
#[cfg(target_os="win32")]
#[cfg(target_os="darwin")]
#[cfg(target_os="linux")]
+ #[cfg(target_os="android")]
pub mod tcp_and_server_client_test {
#[cfg(target_arch="x86_64")]
pub mod impl64 {
+ use uv_ll::test::*;
#[test]
pub fn test_uv_ll_tcp_server_and_request() unsafe {
impl_uv_tcp_server_and_request();
}
}
#[cfg(target_arch="x86")]
+ #[cfg(target_arch="arm")]
pub mod impl32 {
+ use uv_ll::test::*;
#[test]
#[ignore(cfg(target_os = "linux"))]
pub fn test_uv_ll_tcp_server_and_request() unsafe {
// struct size tests
#[test]
fn test_uv_ll_struct_size_uv_tcp_t() {
- let foreign_handle_size = rustrt::rust_uv_helper_uv_tcp_t_size();
- let rust_handle_size = sys::size_of::<uv_tcp_t>();
- let output = fmt!("uv_tcp_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_tcp_t_size();
+ let rust_handle_size = sys::size_of::<uv_tcp_t>();
+ let output = fmt!("uv_tcp_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_uv_connect_t() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_uv_connect_t_size();
- let rust_handle_size = sys::size_of::<uv_connect_t>();
- let output = fmt!("uv_connect_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_connect_t_size();
+ let rust_handle_size = sys::size_of::<uv_connect_t>();
+ let output = fmt!("uv_connect_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_uv_buf_t() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_uv_buf_t_size();
- let rust_handle_size = sys::size_of::<uv_buf_t>();
- let output = fmt!("uv_buf_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_buf_t_size();
+ let rust_handle_size = sys::size_of::<uv_buf_t>();
+ let output = fmt!("uv_buf_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_uv_write_t() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_uv_write_t_size();
- let rust_handle_size = sys::size_of::<uv_write_t>();
- let output = fmt!("uv_write_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_write_t_size();
+ let rust_handle_size = sys::size_of::<uv_write_t>();
+ let output = fmt!("uv_write_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_sockaddr_in() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_sockaddr_in_size();
- let rust_handle_size = sys::size_of::<sockaddr_in>();
- let output = fmt!("sockaddr_in -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_sockaddr_in_size();
+ let rust_handle_size = sys::size_of::<sockaddr_in>();
+ let output = fmt!("sockaddr_in -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_sockaddr_in6() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_sockaddr_in6_size();
- let rust_handle_size = sys::size_of::<sockaddr_in6>();
- let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- // FIXME #1645 .. rust appears to pad structs to the nearest byte..?
- // .. can't get the uv::ll::sockaddr_in6 to == 28 :/
- // .. so the type always appears to be 32 in size.. which is
- // good, i guess.. better too big than too little
- assert (4u+foreign_handle_size as uint) == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_sockaddr_in6_size();
+ let rust_handle_size = sys::size_of::<sockaddr_in6>();
+ let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ // FIXME #1645 .. rust appears to pad structs to the nearest
+ // byte..?
+ // .. can't get the uv::ll::sockaddr_in6 to == 28 :/
+ // .. so the type always appears to be 32 in size.. which is
+ // good, i guess.. better too big than too little
+ assert (4u+foreign_handle_size as uint) == rust_handle_size;
+ }
}
#[test]
#[ignore(reason = "questionable size calculations")]
fn test_uv_ll_struct_size_addr_in() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_addr_in_size();
- let rust_handle_size = sys::size_of::<addr_in>();
- let output = fmt!("addr_in -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- // FIXME #1645 .. see note above about struct padding
- assert (4u+foreign_handle_size as uint) == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_addr_in_size();
+ let rust_handle_size = sys::size_of::<addr_in>();
+ let output = fmt!("addr_in -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ // FIXME #1645 .. see note above about struct padding
+ assert (4u+foreign_handle_size as uint) == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_uv_async_t() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_uv_async_t_size();
- let rust_handle_size = sys::size_of::<uv_async_t>();
- let output = fmt!("uv_async_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_async_t_size();
+ let rust_handle_size = sys::size_of::<uv_async_t>();
+ let output = fmt!("uv_async_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
fn test_uv_ll_struct_size_uv_timer_t() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_uv_timer_t_size();
- let rust_handle_size = sys::size_of::<uv_timer_t>();
- let output = fmt!("uv_timer_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_timer_t_size();
+ let rust_handle_size = sys::size_of::<uv_timer_t>();
+ let output = fmt!("uv_timer_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
#[ignore(cfg(target_os = "win32"))]
fn test_uv_ll_struct_size_uv_getaddrinfo_t() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_uv_getaddrinfo_t_size();
- let rust_handle_size = sys::size_of::<uv_getaddrinfo_t>();
- let output = fmt!("uv_getaddrinfo_t -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_uv_getaddrinfo_t_size();
+ let rust_handle_size = sys::size_of::<uv_getaddrinfo_t>();
+ let output = fmt!("uv_getaddrinfo_t -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
#[test]
#[ignore(cfg(target_os = "macos"))]
#[ignore(cfg(target_os = "win32"))]
fn test_uv_ll_struct_size_addrinfo() {
- let foreign_handle_size =
- rustrt::rust_uv_helper_addrinfo_size();
- let rust_handle_size = sys::size_of::<addrinfo>();
- let output = fmt!("addrinfo -- foreign: %u rust: %u",
- foreign_handle_size as uint, rust_handle_size);
- log(debug, output);
- assert foreign_handle_size as uint == rust_handle_size;
+ unsafe {
+ let foreign_handle_size =
+ ::uv_ll::rustrt::rust_uv_helper_addrinfo_size();
+ let rust_handle_size = sys::size_of::<addrinfo>();
+ let output = fmt!("addrinfo -- foreign: %u rust: %u",
+ foreign_handle_size as uint, rust_handle_size);
+ log(debug, output);
+ assert foreign_handle_size as uint == rust_handle_size;
+ }
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::cmp::Eq;
-use send_map::linear::LinearMap;
-use pipes::{recv, oneshot, PortOne, send_one};
-use either::{Right,Left,Either};
-
use json;
use sha1;
use serialize::{Encoder, Encodable, Decoder, Decodable};
+use core::either::{Either, Left, Right};
+use core::io;
+use core::option;
+use core::pipes::{recv, oneshot, PortOne, send_one};
+use core::prelude::*;
+use core::result;
+use core::run;
+use core::send_map::linear::LinearMap;
+use core::task;
+use core::to_bytes;
+
/**
*
* This is a loose clone of the fbuild build system, made a touch more
type WorkMap = LinearMap<WorkKey, ~str>;
struct Database {
- // XXX: Fill in.
+ // FIXME #4432: Fill in.
a: ()
}
_declared_inputs: &const WorkMap,
_declared_outputs: &const WorkMap) ->
Option<(WorkMap, WorkMap, ~str)> {
- // XXX: load
+ // FIXME #4432: load
None
}
pure fn cache(_fn_name: &str,
_discovered_inputs: &WorkMap,
_discovered_outputs: &WorkMap,
_result: &str) {
- // XXX: store
+ // FIXME #4432: store
}
}
struct Logger {
- // XXX: Fill in
+ // FIXME #4432: Fill in
a: ()
}
Decodable<json::Decoder>>(t: &T) -> ~str {
let sha = sha1::sha1();
let s = do io::with_str_writer |wr| {
- // XXX: sha1 should be a writer itself, shouldn't
+ // FIXME #4432: sha1 should be a writer itself, shouldn't
// go via strings.
t.encode(&json::Encoder(wr));
};
#[test]
fn test() {
use io::WriterUtil;
+
let db = @Database { a: () };
let lg = @Logger { a: () };
let cfg = @LinearMap();
// The Rust abstract syntax tree.
-use std::serialize::{Encodable, Decodable, Encoder, Decoder};
+use ast;
use codemap::{span, FileName};
-use parse::token;
+
+use core::cast;
+use core::cmp;
+use core::option::{None, Option, Some};
+use core::ptr;
+use core::task;
+use core::to_bytes;
+use core::to_str::ToStr;
+use std::serialize::{Encodable, Decodable, Encoder, Decoder};
#[auto_encode]
#[auto_decode]
-type spanned<T> = {node: T, span: span};
-
+struct spanned<T> { node: T, span: span }
/* can't import macros yet, so this is copied from token.rs. See its comment
* there. */
macro_rules! interner_key (
- () => (cast::transmute::<(uint, uint), &fn(+v: @@token::ident_interner)>(
+ () => (cast::transmute::<(uint, uint),
+ &fn(+v: @@::parse::token::ident_interner)>(
(-3 as uint, 0u)))
)
// typeck::collect::compute_bounds matches these against
// the "special" built-in traits (see middle::lang_items) and
// detects Copy, Send, Owned, and Const.
-enum ty_param_bound = @Ty;
+enum ty_param_bound {
+ TraitTyParamBound(@Ty),
+ RegionTyParamBound
+}
#[auto_encode]
#[auto_decode]
#[auto_encode]
#[auto_decode]
+#[deriving_eq]
pub enum Proto {
ProtoBare, // bare functions (deprecated)
ProtoUniq, // ~fn
ProtoBorrowed, // &fn
}
-impl Proto : cmp::Eq {
- pure fn eq(&self, other: &Proto) -> bool {
- ((*self) as uint) == ((*other) as uint)
- }
- pure fn ne(&self, other: &Proto) -> bool { !(*self).eq(other) }
-}
-
impl Proto : to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
(*self as uint).iter_bytes(lsb0, f);
#[auto_decode]
#[doc="For macro invocations; parsing is delegated to the macro"]
enum token_tree {
- tt_tok(span, token::Token),
+ tt_tok(span, ::parse::token::Token),
tt_delim(~[token_tree]),
// These only make sense for right-hand-sides of MBE macros
- tt_seq(span, ~[token_tree], Option<token::Token>, bool),
+ tt_seq(span, ~[token_tree], Option<::parse::token::Token>, bool),
tt_nonterminal(span, ident)
}
#[auto_decode]
enum matcher_ {
// match one token
- match_tok(token::Token),
+ match_tok(::parse::token::Token),
// match repetitions of a sequence: body, separator, zero ok?,
// lo, hi position-in-match-array used:
- match_seq(~[matcher], Option<token::Token>, bool, uint, uint),
+ match_seq(~[matcher], Option<::parse::token::Token>, bool, uint, uint),
// parse a Rust NT: name to bind, name of NT, position in match array:
match_nonterminal(ident, ident, uint)
}
#[auto_encode]
#[auto_decode]
+#[deriving_eq]
enum Onceness {
Once,
Many
}
-impl Onceness : cmp::Eq {
- pure fn eq(&self, other: &Onceness) -> bool {
- match ((*self), *other) {
- (Once, Once) | (Many, Many) => true,
- _ => false
+impl Onceness : ToStr {
+ pure fn to_str() -> ~str {
+ match self {
+ ast::Once => ~"once",
+ ast::Many => ~"many"
}
}
- pure fn ne(&self, other: &Onceness) -> bool {
- !(*self).eq(other)
+}
+
+impl Onceness : to_bytes::IterBytes {
+ pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+ (*self as uint).iter_bytes(lsb0, f);
}
}
#[auto_encode]
#[auto_decode]
-enum purity {
+pub enum purity {
pure_fn, // declared with "pure fn"
unsafe_fn, // declared with "unsafe fn"
impure_fn, // declared with "fn"
extern_fn, // declared with "extern fn"
}
+impl purity : ToStr {
+ pure fn to_str() -> ~str {
+ match self {
+ impure_fn => ~"impure",
+ unsafe_fn => ~"unsafe",
+ pure_fn => ~"pure",
+ extern_fn => ~"extern"
+ }
+ }
+}
+
impl purity : to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
(*self as u8).iter_bytes(lsb0, f)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map;
-use std::map::HashMap;
+use core::prelude::*;
+
use ast::*;
-use print::pprust;
+use ast;
use ast_util::{path_to_ident, stmt_id};
+use ast_util;
+use attr;
+use codemap;
use diagnostic::span_handler;
use parse::token::ident_interner;
+use print::pprust;
+use visit;
+
+use core::cmp;
+use core::either;
+use core::str;
+use core::vec;
+use std::map::HashMap;
+use std::map;
+use std;
enum path_elt {
path_mod(ident),
path_to_str_with_sep(p, ~"::", itr)
}
+fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
+ match pe {
+ path_mod(s) => *itr.get(s),
+ path_name(s) => *itr.get(s)
+ }
+}
+
enum ast_node {
node_item(@item, @path),
node_foreign_item(@foreign_item, foreign_abi, @path),
}
fn mk_ast_map_visitor() -> vt {
- return visit::mk_vt(@{
+ return visit::mk_vt(@visit::Visitor {
visit_item: map_item,
visit_expr: map_expr,
visit_stmt: map_stmt,
cx.local_id += 1u;
}
match fk {
- visit::fk_dtor(tps, ref attrs, self_id, parent_id) => {
- let dt = @{node: {id: id, attrs: (*attrs), self_id: self_id,
- body: /* FIXME (#2543) */ copy body}, span: sp};
- cx.map.insert(id, node_dtor(/* FIXME (#2543) */ copy tps, dt,
- parent_id,
- @/* FIXME (#2543) */ copy cx.path));
+ visit::fk_dtor(tps, ref attrs, self_id, parent_id) => {
+ let dt = @spanned {
+ node: {id: id, attrs: (*attrs), self_id: self_id,
+ body: /* FIXME (#2543) */ copy body},
+ span: sp,
+ };
+ cx.map.insert(id, node_dtor(/* FIXME (#2543) */ copy tps, dt,
+ parent_id,
+ @/* FIXME (#2543) */ copy cx.path));
}
_ => ()
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use codemap::{span, BytePos};
+use core::prelude::*;
+
use ast::*;
+use ast;
+use ast_util;
+use codemap::{span, BytePos};
+use parse::token;
+use visit;
+
+use core::cmp;
+use core::int;
+use core::option;
+use core::str;
+use core::to_bytes;
+use core::vec;
pure fn spanned<T>(+lo: BytePos, +hi: BytePos, +t: T) -> spanned<T> {
respan(mk_sp(lo, hi), move t)
}
pure fn respan<T>(sp: span, +t: T) -> spanned<T> {
- {node: move t, span: sp}
+ spanned {node: t, span: sp}
}
pure fn dummy_spanned<T>(+t: T) -> spanned<T> {
-pure fn path_name_i(idents: ~[ident], intr: @token::ident_interner) -> ~str {
+pure fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str {
// FIXME: Bad copies (#2543 -- same for everything else that says "bad")
str::connect(idents.map(|i| *intr.get(*i)), ~"::")
}
}
// This makes def_id hashable
-impl def_id : core::to_bytes::IterBytes {
+impl def_id : to_bytes::IterBytes {
#[inline(always)]
- pure fn iter_bytes(&self, +lsb0: bool, f: core::to_bytes::Cb) {
- core::to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f);
+ pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+ to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f);
}
}
fn block_from_expr(e: @expr) -> blk {
let blk_ = default_block(~[], option::Some::<@expr>(e), e.id);
- return {node: blk_, span: e.span};
+ return spanned {node: blk_, span: e.span};
}
fn default_block(+stmts1: ~[@stmt], expr1: Option<@expr>, id1: node_id) ->
}
fn public_methods(ms: ~[@method]) -> ~[@method] {
- vec::filter(ms,
- |m| match m.vis {
- public => true,
- _ => false
- })
+ do ms.filtered |m| {
+ match m.vis {
+ public => true,
+ _ => false
+ }
+ }
}
// extract a ty_method from a trait_method. if the trait_method is
}
fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
- visit::mk_simple_visitor(@{
- visit_mod: fn@(_m: _mod, _sp: span, id: node_id) {
- vfn(id)
- },
+ visit::mk_simple_visitor(@visit::SimpleVisitor {
+ visit_mod: |_m, _sp, id| vfn(id),
visit_view_item: fn@(vi: @view_item) {
match vi.node {
// Functions dealing with attributes and meta_items
-use std::map;
-use std::map::HashMap;
-use either::Either;
-use diagnostic::span_handler;
+use core::prelude::*;
+
+use ast;
use ast_util::{spanned, dummy_spanned};
-use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
+use attr;
use codemap::BytePos;
+use diagnostic::span_handler;
+use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
+
+use core::cmp;
+use core::either::Either;
+use core::either;
+use core::option;
+use core::vec;
+use std::map::HashMap;
+use std::map;
+use std;
// Constructors
export mk_name_value_item_str;
/* Searching */
/// Search a list of attributes and return only those with a specific name
-fn find_attrs_by_name(attrs: ~[ast::attribute], name: ~str) ->
+fn find_attrs_by_name(attrs: &[ast::attribute], name: &str) ->
~[ast::attribute] {
- let filter = (
- fn@(a: &ast::attribute) -> Option<ast::attribute> {
- if get_attr_name(*a) == name {
- option::Some(*a)
- } else { option::None }
+ let filter: &fn(a: &ast::attribute) -> Option<ast::attribute> = |a| {
+ if name == get_attr_name(*a) {
+ option::Some(*a)
+ } else {
+ option::None
}
- );
+ };
return vec::filter_map(attrs, filter);
}
return vec::len(matches) > 0u;
}
-fn attrs_contains_name(attrs: ~[ast::attribute], name: ~str) -> bool {
+fn attrs_contains_name(attrs: &[ast::attribute], name: &str) -> bool {
vec::is_not_empty(find_attrs_by_name(attrs, name))
}
*/
-use dvec::DVec;
+use core::prelude::*;
+
+use ast_util;
+
+use core::cmp;
+use core::dvec::DVec;
+use core::str;
+use core::to_bytes;
+use core::uint;
+use core::vec;
use std::serialize::{Encodable, Decodable, Encoder, Decoder};
trait Pos {
}
pub fn span_to_str(&self, sp: span) -> ~str {
+ if self.files.len() == 0 && sp == ast_util::dummy_sp() {
+ return ~"no-location";
+ }
+
let lo = self.lookup_char_pos_adj(sp.lo);
let hi = self.lookup_char_pos_adj(sp.hi);
return fmt!("%s:%u:%u: %u:%u", lo.filename,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::term;
-use io::WriterUtil;
+use core::prelude::*;
+
use codemap::span;
+use codemap;
-export emitter, emit;
+use core::cmp;
+use core::io::WriterUtil;
+use core::io;
+use core::option;
+use core::str;
+use core::vec;
+use core::dvec::DVec;
+
+use std::term;
+
+export emitter, collect, emit;
export level, fatal, error, warning, note;
export span_handler, handler, mk_span_handler, mk_handler;
export codemap_span_handler, codemap_handler;
Some(e) => e,
None => {
let f = fn@(cmsp: Option<(@codemap::CodeMap, span)>,
- msg: &str, t: level) {
+ msg: &str, t: level) {
emit(cmsp, msg, t);
};
f
io::stderr().write_str(fmt!(" %s\n", msg));
}
+fn collect(messages: @DVec<~str>)
+ -> fn@(Option<(@codemap::CodeMap, span)>, &str, level)
+{
+ |_o, msg: &str, _l| { messages.push(msg.to_str()); }
+}
+
fn emit(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level) {
match cmsp {
Some((cm, sp)) => {
*/
-use ext::base::*;
+use core::prelude::*;
+
+use ast;
+use ast_util;
+use attr;
use codemap::span;
+use ext::base::*;
+use parse;
+
+use core::vec;
use std::map;
use std::map::HashMap;
}
fn filter_attrs(item: @ast::item) -> @ast::item {
- @{attrs: vec::filter(item.attrs, |a| !is_auto_encode(a)),
+ @{attrs: item.attrs.filtered(|a| !is_auto_encode(a)),
.. *item}
}
}
fn filter_attrs(item: @ast::item) -> @ast::item {
- @{attrs: vec::filter(item.attrs, |a| !is_auto_decode(a)),
+ @{attrs: item.attrs.filtered(|a| !is_auto_decode(a)),
.. *item}
}
path: @ast::path,
bounds: @~[ast::ty_param_bound]
) -> ast::ty_param {
- let bound = ast::ty_param_bound(@{
+ let bound = ast::TraitTyParamBound(@{
id: self.next_id(),
node: ast::ty_path(path, self.next_id()),
span: span,
@{span: span, global: false, idents: strs, rp: None, types: ~[]}
}
+ fn path_global(span: span, strs: ~[ast::ident]) -> @ast::path {
+ @{span: span, global: true, idents: strs, rp: None, types: ~[]}
+ }
+
fn path_tps(span: span, strs: ~[ast::ident],
tps: ~[@ast::Ty]) -> @ast::path {
@{span: span, global: false, idents: strs, rp: None, types: tps}
}
+ fn path_tps_global(span: span, strs: ~[ast::ident],
+ tps: ~[@ast::Ty]) -> @ast::path {
+ @{span: span, global: true, idents: strs, rp: None, types: tps}
+ }
+
fn ty_path(span: span, strs: ~[ast::ident],
tps: ~[@ast::Ty]) -> @ast::Ty {
@{id: self.next_id(),
}
fn stmt(expr: @ast::expr) -> @ast::stmt {
- @{node: ast::stmt_semi(expr, self.next_id()),
- span: expr.span}
+ @ast::spanned { node: ast::stmt_semi(expr, self.next_id()),
+ span: expr.span }
}
fn lit_str(span: span, s: @~str) -> @ast::expr {
self.expr(
span,
ast::expr_lit(
- @{node: ast::lit_str(s),
- span: span})),
+ @ast::spanned { node: ast::lit_str(s),
+ span: span})),
ast::expr_vstore_uniq))
}
self.expr(
span,
ast::expr_lit(
- @{node: ast::lit_uint(i as u64, ast::ty_u),
- span: span}))
+ @ast::spanned { node: ast::lit_uint(i as u64, ast::ty_u),
+ span: span}))
}
fn lambda(blk: ast::blk) -> @ast::expr {
}
fn blk(span: span, stmts: ~[@ast::stmt]) -> ast::blk {
- {node: {view_items: ~[],
- stmts: stmts,
- expr: None,
- id: self.next_id(),
- rules: ast::default_blk},
- span: span}
+ ast::spanned { node: { view_items: ~[],
+ stmts: stmts,
+ expr: None,
+ id: self.next_id(),
+ rules: ast::default_blk},
+ span: span }
}
fn expr_blk(expr: @ast::expr) -> ast::blk {
- {node: {view_items: ~[],
- stmts: ~[],
- expr: Some(expr),
- id: self.next_id(),
- rules: ast::default_blk},
- span: expr.span}
+ ast::spanned { node: { view_items: ~[],
+ stmts: ~[],
+ expr: Some(expr),
+ id: self.next_id(),
+ rules: ast::default_blk},
+ span: expr.span }
}
fn expr_path(span: span, strs: ~[ast::ident]) -> @ast::expr {
self.expr(span, ast::expr_path(self.path(span, strs)))
}
+ fn expr_path_global(span: span, strs: ~[ast::ident]) -> @ast::expr {
+ self.expr(span, ast::expr_path(self.path_global(span, strs)))
+ }
+
fn expr_var(span: span, var: ~str) -> @ast::expr {
self.expr_path(span, ~[self.ident_of(var)])
}
let mut trait_tps = vec::append(
~[ty_param],
do tps.map |tp| {
- let t_bound = ast::ty_param_bound(@{
+ let t_bound = ast::TraitTyParamBound(@{
id: cx.next_id(),
node: ast::ty_path(path, cx.next_id()),
span: span,
@{
// This is a new-style impl declaration.
// XXX: clownshoes
- ident: ast::token::special_idents::clownshoes_extensions,
+ ident: parse::token::special_idents::clownshoes_extensions,
attrs: ~[],
id: cx.next_id(),
node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]),
let ty_param = cx.bind_path(
span,
cx.ident_of(~"__S"),
- cx.path(
+ cx.path_global(
span,
~[
cx.ident_of(~"std"),
);
// Make a path to the std::serialize::Encodable trait.
- let path = cx.path_tps(
+ let path = cx.path_tps_global(
span,
~[
cx.ident_of(~"std"),
let ty_param = cx.bind_path(
span,
cx.ident_of(~"__D"),
- cx.path(
+ cx.path_global(
span,
~[
cx.ident_of(~"std"),
);
// Make a path to the std::serialize::Decodable trait.
- let path = cx.path_tps(
+ let path = cx.path_tps_global(
span,
~[
cx.ident_of(~"std"),
ident: cx.ident_of(~"encode"),
attrs: ~[],
tps: ~[],
- self_ty: { node: ast::sty_region(ast::m_imm), span: span },
+ self_ty: ast::spanned { node: ast::sty_region(ast::m_imm),
+ span: span },
purity: ast::impure_fn,
decl: ser_decl,
body: ser_body,
ident: cx.ident_of(~"decode"),
attrs: ~[],
tps: ~[],
- self_ty: { node: ast::sty_static, span: span },
+ self_ty: ast::spanned { node: ast::sty_static,
+ span: span },
purity: ast::impure_fn,
decl: deser_decl,
body: deser_body,
cx.expr_blk(
cx.expr_call(
span,
- cx.expr_path(span, ~[
+ cx.expr_path_global(span, ~[
cx.ident_of(~"std"),
cx.ident_of(~"serialize"),
cx.ident_of(~"Decodable"),
]
);
- {
+ ast::spanned {
node: { mutbl: field.mutbl, ident: field.ident, expr: expr },
span: span,
}
let expr_lambda = cx.lambda_expr(
cx.expr_call(
span,
- cx.expr_path(span, ~[
+ cx.expr_path_global(span, ~[
cx.ident_of(~"std"),
cx.ident_of(~"serialize"),
cx.ident_of(~"Decodable"),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map::HashMap;
-use parse::parser;
-use diagnostic::span_handler;
-use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom};
+use core::prelude::*;
+
+use ast;
use ast_util::dummy_sp;
-use parse::token;
+use codemap;
+use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom};
+use diagnostic::span_handler;
+use ext;
+use parse;
+use parse::{parser, token};
+
+use core::io;
+use core::vec;
+use std::map::HashMap;
// new-style macro! tt code:
//
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
+use ast;
+use codemap;
use codemap::span;
use ext::base::ext_ctxt;
+use ext::build;
+
+use core::dvec;
+use core::option;
fn mk_expr(cx: ext_ctxt, sp: codemap::span, expr: ast::expr_) ->
@ast::expr {
}
fn mk_lit(cx: ext_ctxt, sp: span, lit: ast::lit_) -> @ast::expr {
- let sp_lit = @{node: lit, span: sp};
+ let sp_lit = @ast::spanned { node: lit, span: sp };
mk_expr(cx, sp, ast::expr_lit(sp_lit))
}
fn mk_int(cx: ext_ctxt, sp: span, i: int) -> @ast::expr {
-> @ast::path {
@{ span: sp, global: false, idents: idents, rp: None, types: move types }
}
+fn mk_raw_path_global(sp: span, idents: ~[ast::ident]) -> @ast::path {
+ let p : @ast::path = @{span: sp, global: true, idents: idents,
+ rp: None, types: ~[]};
+ return p;
+}
fn mk_path(cx: ext_ctxt, sp: span, idents: ~[ast::ident]) ->
@ast::expr {
mk_expr(cx, sp, ast::expr_path(mk_raw_path(sp, idents)))
}
+fn mk_path_global(cx: ext_ctxt, sp: span, idents: ~[ast::ident]) ->
+ @ast::expr {
+ mk_expr(cx, sp, ast::expr_path(mk_raw_path_global(sp, idents)))
+}
fn mk_access_(cx: ext_ctxt, sp: span, p: @ast::expr, m: ast::ident)
-> @ast::expr {
mk_expr(cx, sp, ast::expr_field(p, m, ~[]))
let pathexpr = mk_path(cx, sp, fn_path);
return mk_call_(cx, sp, pathexpr, args);
}
+fn mk_call_global(cx: ext_ctxt, sp: span, fn_path: ~[ast::ident],
+ args: ~[@ast::expr]) -> @ast::expr {
+ let pathexpr = mk_path_global(cx, sp, fn_path);
+ return mk_call_(cx, sp, pathexpr, args);
+}
// e = expr, t = type
fn mk_base_vec_e(cx: ext_ctxt, sp: span, exprs: ~[@ast::expr]) ->
@ast::expr {
}
fn mk_field(sp: span, f: &{ident: ast::ident, ex: @ast::expr})
-> ast::field {
- {node: {mutbl: ast::m_imm, ident: f.ident, expr: f.ex}, span: sp}
+ ast::spanned { node: {mutbl: ast::m_imm, ident: f.ident, expr: f.ex},
+ span: sp }
}
fn mk_fields(sp: span, fields: ~[{ident: ast::ident, ex: @ast::expr}]) ->
~[ast::field] {
}
fn mk_glob_use(cx: ext_ctxt, sp: span,
path: ~[ast::ident]) -> @ast::view_item {
- let glob = @{node: ast::view_path_glob(mk_raw_path(sp, path),
- cx.next_id()),
- span: sp};
+ let glob = @ast::spanned {
+ node: ast::view_path_glob(mk_raw_path(sp, path), cx.next_id()),
+ span: sp,
+ };
@{node: ast::view_item_import(~[glob]),
attrs: ~[],
vis: ast::private,
None),
span: sp};
let ty : @ast::Ty = @{ id: cx.next_id(), node: ast::ty_infer, span: sp };
- let local : @ast::local = @{node: {is_mutbl: mutbl,
- ty: ty,
- pat: pat,
- init: Some(ex),
- id: cx.next_id()},
- span: sp};
- let decl = {node: ast::decl_local(~[local]), span: sp};
- @{ node: ast::stmt_decl(@decl, cx.next_id()), span: sp }
+ let local : @ast::local = @ast::spanned { node: { is_mutbl: mutbl,
+ ty: ty,
+ pat: pat,
+ init: Some(ex),
+ id: cx.next_id()},
+ span: sp};
+ let decl = ast::spanned {node: ast::decl_local(~[local]), span: sp};
+ @ast::spanned { node: ast::stmt_decl(@decl, cx.next_id()), span: sp }
}
fn mk_block(cx: ext_ctxt, sp: span,
view_items: ~[@ast::view_item],
stmts: ~[@ast::stmt],
expr: Option<@ast::expr>) -> @ast::expr {
- let blk = {node: {view_items: view_items,
- stmts: stmts,
- expr: expr,
- id: cx.next_id(),
- rules: ast::default_blk },
- span: sp };
+ let blk = ast::spanned { node: { view_items: view_items,
+ stmts: stmts,
+ expr: expr,
+ id: cx.next_id(),
+ rules: ast::default_blk },
+ span: sp };
mk_expr(cx, sp, ast::expr_block(blk))
}
fn mk_block_(cx: ext_ctxt, sp: span, +stmts: ~[@ast::stmt]) -> ast::blk {
- {
+ ast::spanned {
node: {
view_items: ~[],
stmts: move stmts,
id: cx.next_id(),
rules: ast::default_blk
};
- { node: move block, span: span }
+ ast::spanned { node: block, span: span }
}
fn mk_copy(cx: ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
mk_expr(cx, sp, ast::expr_copy(e))
mk_pat(cx, span, move pat)
}
fn mk_bool(cx: ext_ctxt, span: span, value: bool) -> @ast::expr {
- let lit_expr = ast::expr_lit(@{ node: ast::lit_bool(value), span: span });
+ let lit_expr = ast::expr_lit(@ast::spanned { node: ast::lit_bool(value),
+ span: span });
build::mk_expr(cx, span, move lit_expr)
}
fn mk_stmt(cx: ext_ctxt, span: span, expr: @ast::expr) -> @ast::stmt {
let stmt_ = ast::stmt_semi(expr, cx.next_id());
- @{ node: move stmt_, span: span }
+ @ast::spanned { node: move stmt_, span: span }
}
fn mk_ty_path(cx: ext_ctxt,
span: span,
let ty = @{ id: cx.next_id(), node: move ty, span: span };
ty
}
+fn mk_ty_path_global(cx: ext_ctxt,
+ span: span,
+ idents: ~[ ast::ident ])
+ -> @ast::Ty {
+ let ty = build::mk_raw_path_global(span, idents);
+ let ty = ast::ty_path(ty, cx.next_id());
+ let ty = @{ id: cx.next_id(), node: move ty, span: span };
+ ty
+}
fn mk_simple_ty_path(cx: ext_ctxt,
span: span,
ident: ast::ident)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
+
use ext::base::*;
+use ext::base;
fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree])
-> base::mac_result {
/// The compiler code necessary to implement the #[deriving_eq] and
/// #[deriving_iter_bytes] extensions.
-use ast::{Ty, and, bind_by_ref, binop, deref, enum_def, enum_variant_kind};
-use ast::{expr, expr_match, ident, item, item_, item_struct, item_enum};
-use ast::{item_impl, m_imm, meta_item, method, named_field, or, pat};
-use ast::{pat_ident, pat_wild, public, pure_fn, re_anon, stmt, struct_def};
-use ast::{struct_variant_kind, sty_by_ref, sty_region, tuple_variant_kind};
-use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_rptr, unnamed_field};
-use ast::{variant};
+use core::prelude::*;
+
+use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def};
+use ast::{enum_variant_kind, expr, expr_match, ident, item, item_};
+use ast::{item_enum, item_impl, item_struct, m_imm, meta_item, method};
+use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn};
+use ast::{re_anon, spanned, stmt, struct_def, struct_variant_kind};
+use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, ty_param};
+use ast::{ty_param_bound, ty_path, ty_rptr, unnamed_field, variant};
use ext::base::ext_ctxt;
+use ext::build;
use codemap::span;
use parse::token::special_idents::clownshoes_extensions;
+use core::dvec;
+use core::uint;
+
enum Junction {
Conjunction,
Disjunction,
let body_block = build::mk_simple_block(cx, span, body);
// Create the method.
- let self_ty = { node: sty_region(m_imm), span: span };
+ let self_ty = spanned { node: sty_region(m_imm), span: span };
return @{
ident: method_ident,
attrs: ~[],
// Create the type parameters.
let impl_ty_params = dvec::DVec();
for ty_params.each |ty_param| {
- let bound = build::mk_ty_path(cx, span, trait_path.map(|x| *x));
- let bounds = @~[ ty_param_bound(bound) ];
+ let bound = build::mk_ty_path_global(cx,
+ span,
+ trait_path.map(|x| *x));
+ let bounds = @~[ TraitTyParamBound(bound) ];
let impl_ty_param = build::mk_ty_param(cx, ty_param.ident, bounds);
impl_ty_params.push(move impl_ty_param);
}
// Create the reference to the trait.
let trait_path = {
span: span,
- global: false,
+ global: true,
idents: trait_path.map(|x| *x),
rp: None,
types: ~[]
let body_block = build::mk_block_(cx, span, move statements);
// Create the method.
- let self_ty = { node: sty_region(m_imm), span: span };
+ let self_ty = spanned { node: sty_region(m_imm), span: span };
let method_ident = cx.ident_of(~"iter_bytes");
return @{
ident: method_ident,
* should all get sucked into either the compiler syntax extension plugin
* interface.
*/
+
use ext::base::*;
+use ext::base;
use ext::build::mk_uniq_str;
+
+use core::option;
+use core::os;
+
export expand_syntax_ext;
fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree])
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map::HashMap;
+use core::prelude::*;
-use ast::{crate, expr_, expr_mac, mac_invoc_tt,
- tt_delim, tt_tok, item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
-use fold::*;
+use ast::{crate, expr_, expr_mac, mac_invoc_tt};
+use ast::{tt_delim, tt_tok, item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
+use ast;
+use codemap::{span, ExpandedFrom};
use ext::base::*;
+use fold::*;
use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};
-
-use codemap::{span, ExpandedFrom};
-
+use core::option;
+use core::vec;
+use std::map::HashMap;
fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
e: expr_, s: span, fld: ast_fold,
fld: ast_fold) -> Option<@ast::item> {
let (pth, tts) = match it.node {
- item_mac({node: mac_invoc_tt(pth, ref tts), _}) => (pth, (*tts)),
+ item_mac(ast::spanned { node: mac_invoc_tt(pth, ref tts), _}) => {
+ (pth, (*tts))
+ }
_ => cx.span_bug(it.span, ~"invalid item macro invocation")
};
{call_site: sp, callie: {name: *extname, span: exp_sp}}));
let expanded = match exp(cx, mac.span, tts) {
mr_expr(e) =>
- @{node: stmt_expr(e, cx.next_id()), span: e.span},
+ @ast::spanned { node: stmt_expr(e, cx.next_id()),
+ span: e.span},
mr_any(_,_,stmt_mkr) => stmt_mkr(),
_ => cx.span_fatal(
pth.span,
macro_rules! ignore (($($x:tt)*) => (()))
macro_rules! error ( ($( $arg:expr ),+) => (
- log(core::error, fmt!( $($arg),+ )) ))
+ log(::core::error, fmt!( $($arg),+ )) ))
macro_rules! warn ( ($( $arg:expr ),+) => (
- log(core::warn, fmt!( $($arg),+ )) ))
+ log(::core::warn, fmt!( $($arg),+ )) ))
macro_rules! info ( ($( $arg:expr ),+) => (
- log(core::info, fmt!( $($arg),+ )) ))
+ log(::core::info, fmt!( $($arg),+ )) ))
macro_rules! debug ( ($( $arg:expr ),+) => (
- log(core::debug, fmt!( $($arg),+ )) ))
+ log(::core::debug, fmt!( $($arg),+ )) ))
macro_rules! die(
($msg: expr) => (
- core::sys::begin_unwind($msg,
- file!().to_owned(), line!())
+ ::core::sys::begin_unwind($msg, file!().to_owned(), line!())
);
() => (
die!(~\"explicit failure\")
{ $c:ident: $in:ty -> $out:ty; } => {
mod $c {
- fn key(_x: @core::condition::Handler<$in,$out>) { }
+ fn key(_x: @::core::condition::Handler<$in,$out>) { }
- pub const cond : core::condition::Condition<$in,$out> =
- core::condition::Condition {
- name: stringify!(c),
+ pub const cond : ::core::condition::Condition<$in,$out> =
+ ::core::condition::Condition {
+ name: stringify!($c),
key: key
};
}
let exts = syntax_expander_table();
let afp = default_ast_fold();
let cx: ext_ctxt = mk_ctxt(parse_sess, cfg);
- let f_pre =
- @{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
- fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
- fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
- fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
- new_span: |a| new_span(cx, a),
- .. *afp};
+ let f_pre = @AstFoldFns {
+ fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
+ fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
+ fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
+ fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
+ new_span: |a| new_span(cx, a),
+ .. *afp};
let f = make_fold(f_pre);
let cm = parse_expr_from_source_str(~"<core-macros>",
@core_macros(),
* should all get sucked into either the standard library extfmt module or the
* compiler syntax extension plugin interface.
*/
-use extfmt::ct::*;
-use ext::base::*;
+
+use core::prelude::*;
+
+use ast;
use codemap::span;
+use ext::base::*;
+use ext::base;
use ext::build::*;
+use extfmt::ct::*;
+
export expand_syntax_ext;
fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree])
}
fn make_rt_path_expr(cx: ext_ctxt, sp: span, nm: @~str) -> @ast::expr {
let path = make_path_vec(cx, nm);
- return mk_path(cx, sp, path);
+ return mk_path_global(cx, sp, path);
}
// Produces an AST expression that represents a RT::conv record,
// which tells the RT::conv* functions how to perform the conversion
let count_lit = mk_uint(cx, sp, c as uint);
let count_is_path = make_path_vec(cx, @~"CountIs");
let count_is_args = ~[count_lit];
- return mk_call(cx, sp, count_is_path, count_is_args);
+ return mk_call_global(cx, sp, count_is_path, count_is_args);
}
_ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion")
}
let path = make_path_vec(cx, @fname);
let cnv_expr = make_rt_conv_expr(cx, sp, cnv);
let args = ~[cnv_expr, arg];
- return mk_call(cx, arg.span, path, args);
+ return mk_call_global(cx, arg.span, path, args);
}
fn make_new_conv(cx: ext_ctxt, sp: span, cnv: Conv, arg: @ast::expr) ->
}
let arg_vec = mk_fixed_vec_e(cx, fmt_sp, piece_exprs);
- return mk_call(cx, fmt_sp,
- ~[cx.parse_sess().interner.intern(@~"str"),
- cx.parse_sess().interner.intern(@~"concat")],
- ~[arg_vec]);
+ return mk_call_global(cx,
+ fmt_sp,
+ ~[cx.parse_sess().interner.intern(@~"str"),
+ cx.parse_sess().interner.intern(@~"concat")],
+ ~[arg_vec]);
}
//
// Local Variables:
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use ast;
+use codemap;
use ext::base::*;
-use io::WriterUtil;
+use ext::base;
+use print;
+
+use core::io::WriterUtil;
+use core::option;
fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, tt: ~[ast::token_tree])
-> base::mac_result {
// To start with, it will be use dummy spans, but it might someday do
// something smarter.
+use core::prelude::*;
+
use ast::{ident, node_id};
+use ast;
use ast_util::{ident_to_path, respan, dummy_sp};
+use ast_util;
+use attr;
use codemap::span;
-use ext::base::mk_ctxt;
+use ext::base::{ext_ctxt, mk_ctxt};
use ext::quote::rt::*;
+use core::vec;
+
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
#[legacy_exports];
types: ~[]}
}
+fn path_global(ids: ~[ident], span: span) -> @ast::path {
+ @{span: span,
+ global: true,
+ idents: ids,
+ rp: None,
+ types: ~[]}
+}
+
trait append_types {
fn add_ty(ty: @ast::Ty) -> @ast::path;
fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path;
+params: ~[ast::ty_param]) -> @ast::item;
fn item_ty(name: ident, span: span, ty: @ast::Ty) -> @ast::item;
fn ty_vars(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty];
+ fn ty_vars_global(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty];
fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field;
fn ty_rec(+v: ~[ast::ty_field]) -> @ast::Ty;
fn field_imm(name: ident, e: @ast::expr) -> ast::field;
impl ext_ctxt: ext_ctxt_ast_builder {
fn ty_option(ty: @ast::Ty) -> @ast::Ty {
- self.ty_path_ast_builder(path(~[self.ident_of(~"Option")],
- dummy_sp())
- .add_ty(ty))
+ self.ty_path_ast_builder(path_global(~[
+ self.ident_of(~"core"),
+ self.ident_of(~"option"),
+ self.ident_of(~"Option")
+ ], dummy_sp()).add_ty(ty))
}
fn block_expr(b: ast::blk) -> @ast::expr {
}
fn stmt_expr(e: @ast::expr) -> @ast::stmt {
- @{node: ast::stmt_expr(e, self.next_id()),
- span: dummy_sp()}
+ @spanned { node: ast::stmt_expr(e, self.next_id()),
+ span: dummy_sp()}
}
fn stmt_let(ident: ident, e: @ast::expr) -> @ast::stmt {
}
fn field_imm(name: ident, e: @ast::expr) -> ast::field {
- {node: {mutbl: ast::m_imm, ident: name, expr: e},
- span: dummy_sp()}
+ spanned { node: { mutbl: ast::m_imm, ident: name, expr: e },
+ span: dummy_sp()}
}
fn rec(+fields: ~[ast::field]) -> @ast::expr {
}
fn ty_field_imm(name: ident, ty: @ast::Ty) -> ast::ty_field {
- {node: {ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
- span: dummy_sp()}
+ spanned { node: { ident: name, mt: { ty: ty, mutbl: ast::m_imm } },
+ span: dummy_sp() }
}
fn ty_rec(+fields: ~[ast::ty_field]) -> @ast::Ty {
id: self.next_id(),
rules: ast::default_blk};
- {node: blk,
- span: dummy_sp()}
+ spanned { node: blk, span: dummy_sp() }
}
fn expr_block(e: @ast::expr) -> ast::blk {
+tys: ~[@ast::Ty]) -> ast::variant {
let args = tys.map(|ty| {ty: *ty, id: self.next_id()});
- {node: {name: name,
- attrs: ~[],
- kind: ast::tuple_variant_kind(args),
- id: self.next_id(),
- disr_expr: None,
- vis: ast::public},
- span: span}
+ spanned { node: { name: name,
+ attrs: ~[],
+ kind: ast::tuple_variant_kind(args),
+ id: self.next_id(),
+ disr_expr: None,
+ vis: ast::public},
+ span: span}
}
fn item_mod(name: ident,
span: span,
+items: ~[@ast::item]) -> @ast::item {
+ // XXX: Total hack: import `core::kinds::Owned` to work around a
+ // parser bug whereby `fn f<T: ::kinds::Owned>` doesn't parse.
+ let vi = ast::view_item_import(~[
+ @ast::spanned {
+ node: ast::view_path_simple(
+ self.ident_of(~"Owned"),
+ path(
+ ~[
+ self.ident_of(~"core"),
+ self.ident_of(~"kinds"),
+ self.ident_of(~"Owned")
+ ],
+ ast_util::dummy_sp()
+ ),
+ ast::type_value_ns,
+ self.next_id()
+ ),
+ span: ast_util::dummy_sp()
+ }
+ ]);
+ let vi = @{
+ node: vi,
+ attrs: ~[],
+ vis: ast::private,
+ span: ast_util::dummy_sp()
+ };
+
self.item(name,
span,
ast::item_mod({
- view_items: ~[],
+ view_items: ~[vi],
items: items}))
}
ty_params.map(|p| self.ty_path_ast_builder(
path(~[p.ident], dummy_sp())))
}
+
+ fn ty_vars_global(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty] {
+ ty_params.map(|p| self.ty_path_ast_builder(
+ path(~[p.ident], dummy_sp())))
+ }
}
*/
-use ext::base::ext_ctxt;
+use core::prelude::*;
+use ast;
+use codemap::span;
+use ext::base::ext_ctxt;
use ext::pipes::proto::{state, protocol, next_state};
+use ext::pipes::proto;
impl ext_ctxt: proto::visitor<(), (), ()> {
fn visit_proto(_proto: protocol,
*/
+use core::prelude::*;
+
+use ext::base::ext_ctxt;
+use ext::pipes::protocol;
+
+use core::str;
use std::bitv::{Bitv};
fn analyze(proto: protocol, _cx: ext_ctxt) {
*/
+use ast;
+use ast::tt_delim;
use codemap::span;
+use ext::base;
use ext::base::ext_ctxt;
-use ast::tt_delim;
+use ext::pipes::parse_proto::proto_parser;
+use ext::pipes::proto::{visit, protocol};
use parse::lexer::{new_tt_reader, reader};
use parse::parser::Parser;
-use ext::pipes::parse_proto::proto_parser;
-use ext::pipes::proto::{visit, protocol};
+use core::option::None;
#[legacy_exports]
mod ast_builder;
// Parsing pipes protocols from token trees.
+use ext::pipes::pipec::*;
use parse::parser;
use parse::token;
-use ext::pipes::pipec::*;
+use core::prelude::*;
trait proto_parser {
fn parse_proto(id: ~str) -> protocol;
// A protocol compiler for Rust.
-use to_str::ToStr;
-
-use dvec::DVec;
-
use ast::ident;
use ast_util::dummy_sp;
-use util::interner;
use ext::base::ext_ctxt;
-use parse::*;
+use ext::pipes::ast_builder::{append_types, path, path_global};
use ext::pipes::proto::*;
use ext::quote::rt::*;
-use ext::pipes::ast_builder::{append_types, path};
+use parse::*;
+use util::interner;
+
+use core::dvec::DVec;
+use core::prelude::*;
+use core::str;
+use core::to_str::ToStr;
+use core::vec;
trait gen_send {
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item;
let pipe_ty = cx.ty_path_ast_builder(
path(~[this.data_name()], span)
- .add_tys(cx.ty_vars(this.ty_params)));
+ .add_tys(cx.ty_vars_global(this.ty_params)));
let args_ast = vec::append(
~[cx.arg(cx.ident_of(~"pipe"),
pipe_ty)],
args_ast);
let mut body = ~"{\n";
+ body += fmt!("use super::%s;\n", self.name());
if this.proto.is_bounded() {
let (sp, rp) = match (this.dir, next.dir) {
};
body += ~"let b = pipe.reuse_buffer();\n";
- body += fmt!("let %s = pipes::SendPacketBuffered(\
- ptr::addr_of(&(b.buffer.data.%s)));\n",
+ body += fmt!("let %s = ::pipes::SendPacketBuffered(\
+ ::ptr::addr_of(&(b.buffer.data.%s)));\n",
sp, next.name);
- body += fmt!("let %s = pipes::RecvPacketBuffered(\
- ptr::addr_of(&(b.buffer.data.%s)));\n",
+ body += fmt!("let %s = ::pipes::RecvPacketBuffered(\
+ ::ptr::addr_of(&(b.buffer.data.%s)));\n",
rp, next.name);
}
else {
(recv, recv) => "(move c, move s)"
};
- body += fmt!("let %s = pipes::entangle();\n", pat);
+ body += fmt!("let %s = ::pipes::entangle();\n", pat);
}
- body += fmt!("let message = %s::%s(%s);\n",
- this.proto.name,
+ body += fmt!("let message = %s(%s);\n",
self.name(),
str::connect(vec::append_one(
arg_names.map(|x| ~"move " + cx.str_of(*x)),
~"move s"), ~", "));
if !try {
- body += fmt!("pipes::send(move pipe, move message);\n");
+ body += fmt!("::pipes::send(move pipe, move message);\n");
// return the new channel
body += ~"move c }";
}
else {
- body += fmt!("if pipes::send(move pipe, move message) {\n \
- pipes::rt::make_some(move c) \
- } else { pipes::rt::make_none() } }");
+ body += fmt!("if ::pipes::send(move pipe, move message) {\n \
+ ::pipes::rt::make_some(move c) \
+ } else { ::pipes::rt::make_none() } }");
}
let body = cx.parse_expr(body);
~[cx.arg(cx.ident_of(~"pipe"),
cx.ty_path_ast_builder(
path(~[this.data_name()], span)
- .add_tys(cx.ty_vars(this.ty_params))))],
+ .add_tys(cx.ty_vars_global(
+ this.ty_params))))],
args_ast);
let message_args = if arg_names.len() == 0 {
};
let mut body = ~"{ ";
- body += fmt!("let message = %s::%s%s;\n",
- this.proto.name,
+ body += fmt!("use super::%s;\n", self.name());
+ body += fmt!("let message = %s%s;\n",
self.name(),
message_args);
if !try {
- body += fmt!("pipes::send(move pipe, move message);\n");
+ body += fmt!("::pipes::send(move pipe, move message);\n");
body += ~" }";
} else {
- body += fmt!("if pipes::send(move pipe, move message) { \
- pipes::rt::make_some(()) \
- } else { pipes::rt::make_none() } }");
+ body += fmt!("if ::pipes::send(move pipe, move message) \
+ { \
+ ::pipes::rt::make_some(()) \
+ } else { \
+ ::pipes::rt::make_none() \
+ } }");
}
let body = cx.parse_expr(body);
fn to_ty(cx: ext_ctxt) -> @ast::Ty {
cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span())
- .add_tys(cx.ty_vars(self.get_params())))
+ .add_tys(cx.ty_vars_global(self.get_params())))
}
}
self.data_name(),
self.span,
cx.ty_path_ast_builder(
- path(~[cx.ident_of(~"pipes"),
- cx.ident_of(dir.to_str() + ~"Packet")],
+ path_global(~[cx.ident_of(~"pipes"),
+ cx.ident_of(dir.to_str() + ~"Packet")],
dummy_sp())
.add_ty(cx.ty_path_ast_builder(
- path(~[cx.ident_of(self.proto.name),
+ path(~[cx.ident_of(~"super"),
self.data_name()],
dummy_sp())
- .add_tys(cx.ty_vars(self.ty_params))))),
+ .add_tys(cx.ty_vars_global(self.ty_params))))),
self.ty_params));
}
else {
self.data_name(),
self.span,
cx.ty_path_ast_builder(
- path(~[cx.ident_of(~"pipes"),
- cx.ident_of(dir.to_str()
- + ~"PacketBuffered")],
+ path_global(~[cx.ident_of(~"pipes"),
+ cx.ident_of(dir.to_str()
+ + ~"PacketBuffered")],
dummy_sp())
.add_tys(~[cx.ty_path_ast_builder(
- path(~[cx.ident_of(self.proto.name),
+ path(~[cx.ident_of(~"super"),
self.data_name()],
- dummy_sp())
- .add_tys(cx.ty_vars(self.ty_params))),
+ dummy_sp())
+ .add_tys(cx.ty_vars_global(self.ty_params))),
self.proto.buffer_ty_path(cx)])),
self.ty_params));
};
let body = if !self.is_bounded() {
match start_state.dir {
- send => quote_expr!( pipes::entangle() ),
+ send => quote_expr!( ::pipes::entangle() ),
recv => {
quote_expr!({
- let (s, c) = pipes::entangle();
+ let (s, c) = ::pipes::entangle();
(move c, move s)
})
}
let fty = s.to_ty(ext_cx);
ext_cx.field_imm(ext_cx.ident_of(s.name),
quote_expr!(
- pipes::mk_packet::<$fty>()
+ ::pipes::mk_packet::<$fty>()
))
}))
}
debug!("gen_init_bounded");
let buffer_fields = self.gen_buffer_init(ext_cx);
let buffer = quote_expr!(
- ~{header: pipes::BufferHeader(),
+ ~{header: ::pipes::BufferHeader(),
data: $buffer_fields}
);
fmt!("data.%s.set_buffer_(buffer)",
s.name))),
ext_cx.parse_expr(
- fmt!("ptr::addr_of(&(data.%s))",
+ fmt!("::ptr::addr_of(&(data.%s))",
self.states[0].name))));
quote_expr!({
let buffer = $buffer;
- do pipes::entangle_buffer(move buffer) |buffer, data| {
+ do ::pipes::entangle_buffer(move buffer) |buffer, data| {
$entangle_body
}
})
}
}
- cx.ty_path_ast_builder(path(~[cx.ident_of(~"__Buffer")], self.span)
- .add_tys(cx.ty_vars(params)))
+ cx.ty_path_ast_builder(path(~[cx.ident_of(~"super"),
+ cx.ident_of(~"__Buffer")], self.span)
+ .add_tys(cx.ty_vars_global(params)))
}
fn gen_buffer_type(cx: ext_ctxt) -> @ast::item {
}
}
let ty = s.to_ty(cx);
- let fty = quote_ty!( pipes::Packet<$ty> );
+ let fty = quote_ty!( ::pipes::Packet<$ty> );
cx.ty_field_imm(cx.ident_of(s.name), fty)
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use to_str::ToStr;
-use dvec::DVec;
+use core::prelude::*;
+use ast;
+use codemap::span;
+use ext::base::ext_ctxt;
use ext::pipes::ast_builder::{path, append_types};
+use core::cmp;
+use core::dvec::DVec;
+use core::to_str::ToStr;
+
enum direction { send, recv }
impl direction : cmp::Eq {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use mod ast;
-use mod parse::token;
-
+use ast;
+use attr;
use codemap::{span, BytePos};
use ext::base::ext_ctxt;
+use ext::base;
+use ext::build;
use parse::token::*;
+use parse::token;
+use parse;
+
+use core::prelude::*;
+use core::str;
/**
*
*/
pub mod rt {
+ use ast;
+ use ext::base::ext_ctxt;
+ use parse;
+ use print::pprust;
+
+ use core::str;
+
pub use ast::*;
pub use parse::token::*;
pub use parse::new_parser_from_tts;
id_ext(cx, ~"parse_sess")), ~[]);
let new_parser_call =
- build::mk_call(cx, sp,
- ids_ext(cx, ~[~"syntax",
- ~"ext",
- ~"quote",
- ~"rt",
- ~"new_parser_from_tts"]),
- ~[parse_sess_call(),
- cfg_call(),
- tts_expr]);
+ build::mk_call_global(cx, sp,
+ ids_ext(cx, ~[~"syntax",
+ ~"ext",
+ ~"quote",
+ ~"rt",
+ ~"new_parser_from_tts"]),
+ ~[parse_sess_call(),
+ cfg_call(),
+ tts_expr]);
build::mk_call_(cx, sp,
build::mk_access_(cx, sp, new_parser_call,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ext::base::*;
+use codemap;
use codemap::{span, Loc, FileMap};
-use print::pprust;
+use ext::base::*;
+use ext::base;
use ext::build::{mk_base_vec_e, mk_uint, mk_u8, mk_base_str};
+use print::pprust;
+
+use core::io;
+use core::prelude::*;
+use core::result;
+use core::str;
+use core::vec;
export expand_line;
export expand_col;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use ast::tt_delim;
+use ast;
use codemap::span;
use ext::base::ext_ctxt;
-use ast::tt_delim;
+use ext::base;
use parse::lexer::{new_tt_reader, reader};
use parse::parser::Parser;
+use core::option::None;
+
fn expand_trace_macros(cx: ext_ctxt, sp: span,
- tt: ~[ast::token_tree]) -> base::mac_result
-{
+ tt: ~[ast::token_tree]) -> base::mac_result {
let sess = cx.parse_sess();
let cfg = cx.cfg();
let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
// except according to those terms.
// Earley-like parser for macros.
-use parse::token;
-use parse::token::{Token, EOF, to_str, nonterminal};
-use parse::lexer::*; //resolve bug?
-//import parse::lexer::{reader, tt_reader, tt_reader_as_reader};
-use parse::parser::Parser;
-//import parse::common::parser_common;
-use parse::common::*; //resolve bug?
-use parse::parse_sess;
-use dvec::DVec;
use ast::{matcher, match_tok, match_seq, match_nonterminal, ident};
use ast_util::mk_sp;
-use std::map::HashMap;
use codemap::BytePos;
+use codemap;
+use parse::common::*; //resolve bug?
+use parse::lexer::*; //resolve bug?
+use parse::parse_sess;
+use parse::parser::Parser;
+use parse::token::{Token, EOF, to_str, nonterminal};
+use parse::token;
+
+use core::dvec::DVec;
+use core::dvec;
+use core::io;
+use core::option;
+use core::str;
+use core::uint;
+use core::vec;
+use std::map::HashMap;
/* This is an Earley-like parser, without support for in-grammar nonterminals,
only by calling out to the main rust parser for named nonterminals (which it
fn n_rec(p_s: parse_sess, m: matcher, res: ~[@named_match],
ret_val: HashMap<ident, @named_match>) {
match m {
- {node: match_tok(_), span: _} => (),
- {node: match_seq(ref more_ms, _, _, _, _), span: _} => {
+ spanned {node: match_tok(_), _} => (),
+ spanned {node: match_seq(ref more_ms, _, _, _, _), _} => {
for (*more_ms).each() |next_m| {
n_rec(p_s, *next_m, res, ret_val)
};
}
- {node: match_nonterminal(bind_name, _, idx), span: sp} => {
+ spanned {node: match_nonterminal(bind_name, _, idx), span: sp} => {
if ret_val.contains_key(bind_name) {
p_s.span_diagnostic.span_fatal(sp, ~"Duplicated bind name: "+
*p_s.interner.get(bind_name))
/* at end of sequence */
if idx >= len {
- // can't move out of `alt`s, so:
+ // can't move out of `match`es, so:
if is_some(ei.up) {
// hack: a matcher sequence is repeating iff it has a
// parent (the top level is just a container)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ext::base::{ext_ctxt, mac_result, mr_any, mr_def, normal_tt};
+use core::prelude::*;
+
+use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
+use ast::{tt_delim};
+use ast;
+use ast_util::dummy_sp;
use codemap::span;
-use ast::{ident, matcher_, matcher, match_tok,
- match_nonterminal, match_seq, tt_delim};
+use ext::base::{ext_ctxt, mac_result, mr_any, mr_def, normal_tt};
+use ext::base;
+use ext::tt::macro_parser::{error};
+use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
+use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
use parse::lexer::{new_tt_reader, reader};
-use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt};
use parse::parser::Parser;
-use ext::tt::macro_parser::{parse, parse_or_else, success, failure,
- named_match, matched_seq, matched_nonterminal,
- error};
-use std::map::HashMap;
use parse::token::special_idents;
-use ast_util::dummy_sp;
+use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt};
+use print;
+
+use core::io;
+use std::map::HashMap;
fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
arg: ~[ast::token_tree]) -> base::mac_result {
// these spans won't matter, anyways
fn ms(m: matcher_) -> matcher {
- {node: m, span: dummy_sp()}
+ ast::spanned { node: m, span: dummy_sp() }
}
let lhs_nm = cx.parse_sess().interner.gensym(@~"lhs");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use diagnostic::span_handler;
+use core::prelude::*;
+
+use ast;
use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident};
-use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
+use ast_util;
use codemap::span;
+use diagnostic::span_handler;
+use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner};
+
+use core::option;
+use core::vec;
+use std;
use std::map::HashMap;
export tt_reader, new_tt_reader, dup_tt_reader, tt_next_token;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use codemap::span;
+use core::prelude::*;
+
use ast::*;
+use ast;
+use codemap::span;
-export ast_fold_precursor;
+use core::option;
+use core::vec;
+
+export ast_fold_fns;
export ast_fold;
export default_ast_fold;
export make_fold;
export fold_ty_params;
export fold_fn_decl;
export extensions;
+export AstFoldFns;
trait ast_fold {
fn fold_crate(crate) -> crate;
// We may eventually want to be able to fold over type parameters, too
-type ast_fold_precursor = @{
+struct AstFoldFns {
//unlike the others, item_ is non-trivial
fold_crate: fn@(crate_, span, ast_fold) -> (crate_, span),
fold_view_item: fn@(view_item_, ast_fold) -> view_item_,
fold_local: fn@(local_, span, ast_fold) -> (local_, span),
map_exprs: fn@(fn@(&&v: @expr) -> @expr, ~[@expr]) -> ~[@expr],
new_id: fn@(node_id) -> node_id,
- new_span: fn@(span) -> span};
+ new_span: fn@(span) -> span
+}
+
+type ast_fold_fns = @AstFoldFns;
/* some little folds that probably aren't useful to have in ast_fold itself*/
//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
fn fold_meta_item_(&&mi: @meta_item, fld: ast_fold) -> @meta_item {
- return @{node:
- match mi.node {
+ @spanned {
+ node:
+ match mi.node {
meta_word(ref id) => meta_word((*id)),
meta_list(ref id, mis) => {
- let fold_meta_item = |x|fold_meta_item_(x, fld);
- meta_list(/* FIXME: (#2543) */ copy (*id),
- vec::map(mis, |e| fold_meta_item(*e)))
+ let fold_meta_item = |x|fold_meta_item_(x, fld);
+ meta_list(/* FIXME: (#2543) */ copy (*id),
+ vec::map(mis, |e| fold_meta_item(*e)))
}
meta_name_value(ref id, s) => {
- meta_name_value((*id), /* FIXME (#2543) */ copy s)
+ meta_name_value((*id), /* FIXME (#2543) */ copy s)
}
- },
- span: fld.new_span(mi.span)};
+ },
+ span: fld.new_span(mi.span) }
}
//used in noop_fold_item and noop_fold_crate
-fn fold_attribute_(at: attribute, fld: ast_fold) ->
- attribute {
- return {node: {style: at.node.style,
- value: *fold_meta_item_(@at.node.value, fld),
- is_sugared_doc: at.node.is_sugared_doc },
- span: fld.new_span(at.span)};
+fn fold_attribute_(at: attribute, fld: ast_fold) -> attribute {
+ spanned { node: { style: at.node.style,
+ value: *fold_meta_item_(@at.node.value, fld),
+ is_sugared_doc: at.node.is_sugared_doc },
+ span: fld.new_span(at.span) }
}
//used in noop_fold_foreign_item and noop_fold_fn_decl
fn fold_arg_(a: arg, fld: ast_fold) -> arg {
}
//used in noop_fold_expr, and possibly elsewhere in the future
fn fold_mac_(m: mac, fld: ast_fold) -> mac {
- return {node:
- match m.node {
- mac_invoc_tt(*) => m.node,
- },
- span: fld.new_span(m.span)};
+ spanned { node: match m.node {
+ mac_invoc_tt(*) => m.node,
+ },
+ span: fld.new_span(m.span) }
}
fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl {
}
fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound {
- ty_param_bound(fld.fold_ty(*tpb))
+ match tpb {
+ TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)),
+ RegionTyParamBound => RegionTyParamBound
+ }
}
fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param {
fn noop_fold_struct_field(&&sf: @struct_field, fld: ast_fold)
-> @struct_field {
- @{node: {kind: copy sf.node.kind,
- id: sf.node.id,
- ty: fld.fold_ty(sf.node.ty)},
- span: sf.span}
+ @spanned { node: { kind: copy sf.node.kind,
+ id: sf.node.id,
+ ty: fld.fold_ty(sf.node.ty) },
+ span: sf.span }
}
fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
let dtor = do option::map(&struct_def.dtor) |dtor| {
let dtor_body = fld.fold_block(dtor.node.body);
let dtor_id = fld.new_id(dtor.node.id);
- {node: {body: dtor_body,
- id: dtor_id,.. dtor.node},
- .. *dtor}};
+ spanned { node: { body: dtor_body,
+ id: dtor_id, .. dtor.node},
+ span: dtor.span }
+ };
return @{
fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)),
dtor: dtor,
}
fn fold_struct_field(&&f: @struct_field, fld: ast_fold) -> @struct_field {
- @{node: {kind: copy f.node.kind,
- id: fld.new_id(f.node.id),
- ty: fld.fold_ty(f.node.ty)},
- span: fld.new_span(f.span)}
+ @spanned { node: { kind: copy f.node.kind,
+ id: fld.new_id(f.node.id),
+ ty: fld.fold_ty(f.node.ty) },
+ span: fld.new_span(f.span) }
}
fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
fn fold_field_(field: field, fld: ast_fold) -> field {
- return {node:
- {mutbl: field.node.mutbl,
- ident: fld.fold_ident(field.node.ident),
- expr: fld.fold_expr(field.node.expr)},
- span: fld.new_span(field.span)};
+ spanned { node: { mutbl: field.node.mutbl,
+ ident: fld.fold_ident(field.node.ident),
+ expr: fld.fold_expr(field.node.expr)},
+ span: fld.new_span(field.span) }
}
let fold_field = |x| fold_field_(x, fld);
{ty: fld.fold_ty(mt.ty), mutbl: mt.mutbl}
}
fn fold_field(f: ty_field, fld: ast_fold) -> ty_field {
- {node: {ident: fld.fold_ident(f.node.ident),
- mt: fold_mt(f.node.mt, fld)},
- span: fld.new_span(f.span)}
+ spanned { node: { ident: fld.fold_ident(f.node.ident),
+ mt: fold_mt(f.node.mt, fld) },
+ span: fld.new_span(f.span) }
}
match t {
ty_nil | ty_bot | ty_infer => copy t,
let dtor = do option::map(&struct_def.dtor) |dtor| {
let dtor_body = fld.fold_block(dtor.node.body);
let dtor_id = fld.new_id(dtor.node.id);
- {node: {body: dtor_body,
- id: dtor_id,.. dtor.node},
- .. *dtor}};
+ spanned { node: { body: dtor_body,
+ id: dtor_id, .. dtor.node},
+ .. *dtor }
+ };
kind = struct_variant_kind(@{
fields: vec::map(struct_def.fields,
|f| fld.fold_struct_field(*f)),
fn noop_span(sp: span) -> span { return sp; }
-fn default_ast_fold() -> ast_fold_precursor {
- return @{fold_crate: wrap(noop_fold_crate),
+fn default_ast_fold() -> ast_fold_fns {
+ return @AstFoldFns {fold_crate: wrap(noop_fold_crate),
fold_view_item: noop_fold_view_item,
fold_foreign_item: noop_fold_foreign_item,
fold_item: noop_fold_item,
new_span: noop_span};
}
-impl ast_fold_precursor: ast_fold {
+impl ast_fold_fns: ast_fold {
/* naturally, a macro to write these would be nice */
fn fold_crate(c: crate) -> crate {
let (n, s) = (self.fold_crate)(c.node, c.span, self as ast_fold);
- return {node: n, span: (self.new_span)(s)};
+ spanned { node: n, span: (self.new_span)(s) }
}
fn fold_view_item(&&x: @view_item) ->
@view_item {
return (self.fold_item)(i, self as ast_fold);
}
fn fold_struct_field(&&sf: @struct_field) -> @struct_field {
- @{node: {kind: copy sf.node.kind,
- id: sf.node.id,
- ty: (self as ast_fold).fold_ty(sf.node.ty)},
- span: (self.new_span)(sf.span)}
+ @spanned { node: { kind: copy sf.node.kind,
+ id: sf.node.id,
+ ty: (self as ast_fold).fold_ty(sf.node.ty) },
+ span: (self.new_span)(sf.span) }
}
fn fold_item_underscore(i: item_) ->
item_ {
}
fn fold_block(x: blk) -> blk {
let (n, s) = (self.fold_block)(x.node, x.span, self as ast_fold);
- return {node: n, span: (self.new_span)(s)};
+ spanned { node: n, span: (self.new_span)(s) }
}
fn fold_stmt(&&x: @stmt) -> @stmt {
let (n, s) = (self.fold_stmt)(x.node, x.span, self as ast_fold);
- return @{node: n, span: (self.new_span)(s)};
+ @spanned { node: n, span: (self.new_span)(s) }
}
fn fold_arm(x: arm) -> arm {
return (self.fold_arm)(x, self as ast_fold);
}
fn fold_decl(&&x: @decl) -> @decl {
let (n, s) = (self.fold_decl)(x.node, x.span, self as ast_fold);
- return @{node: n, span: (self.new_span)(s)};
+ @spanned { node: n, span: (self.new_span)(s) }
}
fn fold_expr(&&x: @expr) -> @expr {
let (n, s) = (self.fold_expr)(x.node, x.span, self as ast_fold);
fn fold_variant(x: variant) ->
variant {
let (n, s) = (self.fold_variant)(x.node, x.span, self as ast_fold);
- return {node: n, span: (self.new_span)(s)};
+ spanned { node: n, span: (self.new_span)(s) }
}
fn fold_ident(&&x: ident) -> ident {
return (self.fold_ident)(x, self as ast_fold);
}
fn fold_local(&&x: @local) -> @local {
let (n, s) = (self.fold_local)(x.node, x.span, self as ast_fold);
- return @{node: n, span: (self.new_span)(s)};
+ @spanned { node: n, span: (self.new_span)(s) }
}
fn map_exprs(f: fn@(&&v: @expr) -> @expr, e: ~[@expr]) -> ~[@expr] {
(self.map_exprs)(f, e)
}
}
-fn make_fold(afp: ast_fold_precursor) -> ast_fold {
+fn make_fold(afp: ast_fold_fns) -> ast_fold {
afp as ast_fold
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use either::{Either, Left, Right};
+use core::prelude::*;
+
+use ast;
use ast_util::spanned;
+use codemap::BytePos;
use parse::common::*; //resolve bug?
+use parse::token;
+
+use core::either::{Either, Left, Right};
export parser_attr;
Predicates on exprs and stmts that the pretty-printer and parser use
*/
+use ast;
use ast_util::operator_prec;
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
fn expr_is_simple_block(e: @ast::expr) -> bool {
match e.node {
- ast::expr_block({node: {rules: ast::default_blk, _}, _}) => true,
+ ast::expr_block(ast::spanned {node: {rules: ast::default_blk, _}, _}) =>
+ true,
_ => false
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use io::ReaderUtil;
+use core::prelude::*;
+
+use ast;
+use codemap::{BytePos, CharPos, CodeMap, FileMap};
+use diagnostic;
+use parse::lexer::{is_whitespace, get_str_from, reader};
+use parse::lexer::{string_reader, bump, is_eof, nextch};
+use parse::lexer;
+use parse::token;
+use parse;
use util::interner;
-use parse::lexer::{string_reader, bump, is_eof, nextch,
- is_whitespace, get_str_from, reader};
-use codemap::{FileMap, CharPos};
+
+use core::cmp;
+use core::io::ReaderUtil;
+use core::io;
+use core::str;
+use core::uint;
+use core::vec;
export cmnt;
export lit;
// drop leftmost columns that contain only values in chars
fn block_trim(lines: ~[~str], chars: ~str, max: Option<uint>) -> ~[~str] {
- let mut i = max.get_default(uint::max_value);
+ let mut i = max.get_or_default(uint::max_value);
for lines.each |line| {
if line.trim().is_empty() {
loop;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::map::{HashMap};
+use core::prelude::*;
+
+use ast;
use ast_util::spanned;
-use parse::parser::Parser;
+use codemap::BytePos;
use parse::lexer::reader;
+use parse::parser::Parser;
+use parse::token;
+
+use core::option::{None, Option, Some};
+use core::option;
+use std::map::HashMap;
type seq_sep = {
sep: Option<token::Token>,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use diagnostic::span_handler;
+use core::prelude::*;
+
+use ast;
+use ast_util;
use codemap::{span, CodeMap, CharPos, BytePos};
-use ext::tt::transcribe::{tt_reader, new_tt_reader, dup_tt_reader,
- tt_next_token};
+use codemap;
+use diagnostic::span_handler;
+use ext::tt::transcribe::{tt_next_token};
+use ext::tt::transcribe::{tt_reader, new_tt_reader, dup_tt_reader};
+use parse::token;
+
+use core::char;
+use core::either;
+use core::str;
+use core::u64;
+
+use std;
export reader, string_reader, new_string_reader, is_whitespace;
export tt_reader, new_tt_reader;
//! The main parser interface
-#[legacy_exports];
-
-export parser;
-export common;
-export lexer;
-export token;
-export comments;
-export prec;
-export classify;
-export attr;
-export obsolete;
-
-export parse_sess;
-export new_parse_sess, new_parse_sess_special_handler;
-export next_node_id;
-export new_parser_from_file, new_parser_etc_from_file;
-export new_parser_from_source_str;
-export new_parser_from_tts;
-export new_sub_parser_from_file;
-export parse_crate_from_file, parse_crate_from_crate_file;
-export parse_crate_from_source_str;
-export parse_expr_from_source_str, parse_item_from_source_str;
-export parse_stmt_from_source_str;
-export parse_tts_from_source_str;
-export parse_from_source_str;
-
use ast::node_id;
+use ast;
use codemap::{span, CodeMap, FileMap, CharPos, BytePos};
+use codemap;
use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter};
use parse::attr::parser_attr;
use parse::lexer::{reader, string_reader};
use parse::token::{ident_interner, mk_ident_interner};
use util::interner;
+use core::io;
+use core::option::{None, Option, Some};
+use core::path::Path;
+use core::result::{Err, Ok, Result};
+use core::result;
#[legacy_exports]
-mod lexer;
+pub mod lexer;
#[legacy_exports]
-mod parser;
+pub mod parser;
#[legacy_exports]
-mod token;
+pub mod token;
#[legacy_exports]
-mod comments;
+pub mod comments;
#[legacy_exports]
-mod attr;
+pub mod attr;
#[legacy_exports]
/// Common routines shared by parser mods
#[legacy_exports]
-mod common;
+pub mod common;
/// Functions dealing with operator precedence
#[legacy_exports]
-mod prec;
+pub mod prec;
/// Routines the parser uses to classify AST nodes
#[legacy_exports]
-mod classify;
+pub mod classify;
/// Reporting obsolete syntax
#[legacy_exports]
-mod obsolete;
-
+pub mod obsolete;
-type parse_sess = @{
+pub type parse_sess = @{
cm: @codemap::CodeMap,
mut next_id: node_id,
span_diagnostic: span_handler,
interner: @ident_interner,
};
-fn new_parse_sess(demitter: Option<emitter>) -> parse_sess {
+pub fn new_parse_sess(demitter: Option<emitter>) -> parse_sess {
let cm = @CodeMap::new();
return @{cm: cm,
mut next_id: 1,
};
}
-fn new_parse_sess_special_handler(sh: span_handler, cm: @codemap::CodeMap)
+pub fn new_parse_sess_special_handler(sh: span_handler, cm: @codemap::CodeMap)
-> parse_sess {
return @{cm: cm,
mut next_id: 1,
};
}
-fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
+pub fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate {
let p = new_crate_parser_from_file(sess, cfg, input);
let r = p.parse_crate_mod(cfg);
return r;
}
-fn parse_crate_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
- sess: parse_sess) -> @ast::crate {
+pub fn parse_crate_from_source_str(name: ~str,
+ source: @~str,
+ cfg: ast::crate_cfg,
+ sess: parse_sess) -> @ast::crate {
let p = new_parser_from_source_str(sess, cfg, name,
codemap::FssNone, source);
let r = p.parse_crate_mod(cfg);
return r;
}
-fn parse_expr_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
- sess: parse_sess) -> @ast::expr {
+pub fn parse_expr_from_source_str(name: ~str,
+ source: @~str,
+ cfg: ast::crate_cfg,
+ sess: parse_sess) -> @ast::expr {
let p = new_parser_from_source_str(sess, cfg, name,
codemap::FssNone, source);
let r = p.parse_expr();
return r;
}
-fn parse_item_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
- +attrs: ~[ast::attribute],
- sess: parse_sess) -> Option<@ast::item> {
+pub fn parse_item_from_source_str(name: ~str,
+ source: @~str,
+ cfg: ast::crate_cfg,
+ +attrs: ~[ast::attribute],
+ sess: parse_sess)
+ -> Option<@ast::item> {
let p = new_parser_from_source_str(sess, cfg, name,
codemap::FssNone, source);
let r = p.parse_item(attrs);
return r;
}
-fn parse_stmt_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
- +attrs: ~[ast::attribute],
- sess: parse_sess) -> @ast::stmt {
+pub fn parse_stmt_from_source_str(name: ~str,
+ source: @~str,
+ cfg: ast::crate_cfg,
+ +attrs: ~[ast::attribute],
+ sess: parse_sess) -> @ast::stmt {
let p = new_parser_from_source_str(sess, cfg, name,
codemap::FssNone, source);
let r = p.parse_stmt(attrs);
return r;
}
-fn parse_tts_from_source_str(name: ~str, source: @~str, cfg: ast::crate_cfg,
- sess: parse_sess) -> ~[ast::token_tree] {
+pub fn parse_tts_from_source_str(name: ~str,
+ source: @~str,
+ cfg: ast::crate_cfg,
+ sess: parse_sess) -> ~[ast::token_tree] {
let p = new_parser_from_source_str(sess, cfg, name,
codemap::FssNone, source);
p.quote_depth += 1u;
return r;
}
-fn parse_from_source_str<T>(f: fn (p: Parser) -> T,
+pub fn parse_from_source_str<T>(f: fn (p: Parser) -> T,
name: ~str, ss: codemap::FileSubstr,
source: @~str, cfg: ast::crate_cfg,
sess: parse_sess)
move r
}
-fn next_node_id(sess: parse_sess) -> node_id {
+pub fn next_node_id(sess: parse_sess) -> node_id {
let rv = sess.next_id;
sess.next_id += 1;
// ID 0 is reserved for the crate and doesn't actually exist in the AST
return rv;
}
-fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
+pub fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
+name: ~str, +ss: codemap::FileSubstr,
source: @~str) -> Parser {
let filemap = sess.cm.new_filemap_w_substr(name, ss, source);
return Parser(sess, cfg, srdr as reader);
}
-fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
+pub fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
path: &Path) -> Result<Parser, ~str> {
match io::read_whole_file_str(path) {
result::Ok(move src) => {
/// Create a new parser for an entire crate, handling errors as appropriate
/// if the file doesn't exist
-fn new_crate_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
+pub fn new_crate_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
path: &Path) -> Parser {
match new_parser_from_file(sess, cfg, path) {
Ok(move parser) => move parser,
/// Create a new parser based on a span from an existing parser. Handles
/// error messages correctly when the file does not exist.
-fn new_sub_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
+pub fn new_sub_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
path: &Path, sp: span) -> Parser {
match new_parser_from_file(sess, cfg, path) {
Ok(move parser) => move parser,
}
}
-fn new_parser_from_tts(sess: parse_sess, cfg: ast::crate_cfg,
+pub fn new_parser_from_tts(sess: parse_sess, cfg: ast::crate_cfg,
tts: ~[ast::token_tree]) -> Parser {
let trdr = lexer::new_tt_reader(sess.span_diagnostic, sess.interner,
None, tts);
removed.
*/
-use codemap::span;
+use core::prelude::*;
+
use ast::{expr, expr_lit, lit_nil};
+use ast;
use ast_util::{respan};
+use codemap::span;
+use parse::parser::Parser;
use parse::token::Token;
+use parse::token;
+
+use core::cmp;
+use core::option;
+use core::str;
+use core::to_bytes;
/// The specific types of unsupported syntax
pub enum ObsoleteSyntax {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use print::pprust::expr_to_str;
-
-use result::Result;
-use either::{Either, Left, Right};
-use std::map::HashMap;
-use parse::token::{can_begin_expr, is_ident, is_ident_or_path, is_plain_ident,
- INTERPOLATED, special_idents};
-use codemap::{span,FssNone, BytePos};
-use util::interner::Interner;
+use core::prelude::*;
+
+use ast::{ProtoBox, ProtoUniq, RegionTyParamBound, TraitTyParamBound};
+use ast::{provided, public, pure_fn, purity, re_static};
+use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
+use ast::{bind_by_value, bind_by_move, bitand, bitor, bitxor, blk};
+use ast::{blk_check_mode, box, by_copy, by_move, by_ref, by_val};
+use ast::{capture_clause, capture_item, crate, crate_cfg, decl, decl_item};
+use ast::{decl_local, default_blk, deref, div, enum_def, enum_variant_kind};
+use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again};
+use ast::{expr_assert, expr_assign, expr_assign_op, expr_binary, expr_block};
+use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
+use ast::{expr_fail, expr_field, expr_fn, expr_fn_block, expr_if, expr_index};
+use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
+use ast::{expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat};
+use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
+use ast::{expr_unary_move, expr_vec, expr_vstore, expr_vstore_mut_box};
+use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box};
+use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
+use ast::{expr_vstore_uniq, TyFn, Onceness, Once, Many};
+use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
+use ast::{ident, impure_fn, infer, inherited, item, item_, item_const};
+use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl};
+use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
+use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int};
+use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const};
+use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
+use ast::{match_seq, match_tok, method, mode, module_ns, mt, mul, mutability};
+use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
+use ast::{pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct};
+use ast::{pat_tup, pat_uniq, pat_wild, path, private, Proto, ProtoBare};
+use ast::{ProtoBorrowed, re_self, re_anon, re_named, region, rem, required};
+use ast::{ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl};
+use ast::{stmt_expr, stmt_semi, stmt_mac, struct_def, struct_field};
+use ast::{struct_immutable, struct_mutable, struct_variant_kind, subtract};
+use ast::{sty_box, sty_by_ref, sty_region, sty_static, sty_uniq, sty_value};
+use ast::{token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok};
+use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box};
+use ast::{ty_field, ty_fixed_length_vec, ty_fn, ty_infer, ty_mac, ty_method};
+use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr};
+use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, type_value_ns, uniq};
+use ast::{unnamed_field, unsafe_blk, unsafe_fn, variant, view_item};
+use ast::{view_item_, view_item_export, view_item_import, view_item_use};
+use ast::{view_path, view_path_glob, view_path_list, view_path_simple};
+use ast::{visibility, vstore, vstore_box, vstore_fixed, vstore_slice};
+use ast::{vstore_uniq};
+use ast;
use ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec};
+use ast_util;
+use classify;
+use codemap::{span,FssNone, BytePos};
+use codemap;
+use parse::attr::parser_attr;
+use parse::common::{seq_sep_none, token_to_str};
+use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed};
use parse::lexer::reader;
+use parse::obsolete::{ObsoleteClassTraits, ObsoleteModeInFnType};
+use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator};
+use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove};
+use parse::obsolete::{ObsoleteStructCtor, ObsoleteWith, ObsoleteClassMethod};
+use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds};
use parse::prec::{as_prec, token_to_binop};
-use parse::attr::parser_attr;
-use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed,
- seq_sep_none, token_to_str};
-use dvec::DVec;
-use vec::{push};
-use parse::obsolete::{
- ObsoleteSyntax,
- ObsoleteLowerCaseKindBounds, ObsoleteLet,
- ObsoleteFieldTerminator, ObsoleteStructCtor,
- ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits,
- ObsoleteModeInFnType, ObsoleteMoveInit, ObsoleteBinaryMove,
-};
-use ast::{_mod, add, arg, arm, attribute,
- bind_by_ref, bind_infer, bind_by_value, bind_by_move,
- bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy,
- by_move, by_ref, by_val, capture_clause,
- capture_item, struct_immutable, struct_mutable,
- crate, crate_cfg, decl, decl_item, decl_local,
- default_blk, deref, div, enum_def, enum_variant_kind, expl, expr,
- expr_, expr_addr_of, expr_match, expr_again, expr_assert,
- expr_assign, expr_assign_op, expr_binary, expr_block, expr_break,
- expr_call, expr_cast, expr_copy, expr_do_body, expr_fail,
- expr_field, expr_fn, expr_fn_block, expr_if, expr_index,
- expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac,
- expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat,
- expr_ret, expr_swap, expr_struct, expr_tup, expr_unary,
- expr_unary_move, expr_vec, expr_vstore, expr_vstore_mut_box,
- expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl,
- foreign_item, foreign_item_const, foreign_item_fn, foreign_mod,
- ident, impure_fn, infer, inherited,
- item, item_, item_struct, item_const, item_enum, item_fn,
- item_foreign_mod, item_impl, item_mac, item_mod, item_trait,
- item_ty, lit, lit_, lit_bool, lit_float, lit_float_unsuffixed,
- lit_int, lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local,
- m_const, m_imm, m_mutbl, mac_,
- mac_invoc_tt, matcher, match_nonterminal, match_seq,
- match_tok, method, mode, module_ns, mt, mul, mutability,
- named_field, neg, noreturn, not, pat, pat_box, pat_enum,
- pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct,
- pat_tup, pat_uniq, pat_wild, path, private, Proto, ProtoBare,
- ProtoBorrowed, ProtoBox, ProtoUniq, provided, public, pure_fn,
- purity, re_static, re_self, re_anon, re_named, region,
- rem, required, ret_style, return_val, self_ty, shl, shr, stmt,
- stmt_decl, stmt_expr, stmt_semi, stmt_mac, struct_def,
- struct_field, struct_variant_kind, subtract, sty_box, sty_by_ref,
- sty_region, sty_static, sty_uniq, sty_value, token_tree,
- trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
- tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot,
- ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil,
- ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr,
- ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length_vec,
- type_value_ns, uniq, unnamed_field, unsafe_blk, unsafe_fn,
- variant, view_item, view_item_, view_item_export,
- view_item_import, view_item_use, view_path, view_path_glob,
- view_path_list, view_path_simple, visibility, vstore, vstore_box,
- vstore_fixed, vstore_slice, vstore_uniq,
- expr_vstore_fixed, expr_vstore_slice, expr_vstore_box,
- expr_vstore_uniq, TyFn, Onceness, Once, Many};
+use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
+use parse::token::{is_plain_ident, INTERPOLATED, special_idents};
+use parse::token;
+use parse::{new_sub_parser_from_file, next_node_id, parse_sess};
+use print::pprust::expr_to_str;
+use util::interner::Interner;
+
+use core::cmp;
+use core::dvec::DVec;
+use core::dvec;
+use core::either::{Either, Left, Right};
+use core::either;
+use core::result::Result;
+use core::vec::push;
+use core::vec;
+use std::map::HashMap;
export Parser;
keywords: token::keyword_table(),
strict_keywords: token::strict_keyword_table(),
reserved_keywords: token::reserved_keyword_table(),
- obsolete_set: std::map::HashMap(),
+ obsolete_set: HashMap(),
mod_path_stack: ~[],
}
}
self.bump();
self.lit_from_token(tok)
};
- return {node: lit, span: mk_sp(lo, self.last_span.hi)};
+ spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
}
fn parse_path_without_tps() -> @path {
self.parse_seq_lt_gt(Some(token::COMMA),
|p| p.parse_ty(false))
} else {
- {node: ~[], span: path.span}
+ spanned {node: ~[], span: path.span}
}
};
fn mk_mac_expr(+lo: BytePos, +hi: BytePos, m: mac_) -> @expr {
return @{id: self.get_id(),
callee_id: self.get_id(),
- node: expr_mac({node: m, span: mk_sp(lo, hi)}),
+ node: expr_mac(spanned {node: m, span: mk_sp(lo, hi)}),
span: mk_sp(lo, hi)};
}
fn mk_lit_u32(i: u32) -> @expr {
let span = self.span;
- let lv_lit = @{node: lit_uint(i as u64, ty_u32),
- span: span};
+ let lv_lit = @spanned { node: lit_uint(i as u64, ty_u32),
+ span: span };
return @{id: self.get_id(), callee_id: self.get_id(),
node: expr_lit(lv_lit), span: span};
} else if self.eat_keyword(~"loop") {
return self.parse_loop_expr();
} else if self.eat_keyword(~"match") {
- return self.parse_alt_expr();
+ return self.parse_match_expr();
} else if self.eat_keyword(~"fn") {
let opt_proto = self.parse_fn_ty_proto();
let proto = match opt_proto {
hi = e.span.hi;
// HACK: turn &[...] into a &-evec
ex = match e.node {
- expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
+ expr_vec(*) | expr_lit(@spanned {node: lit_str(_), span: _})
if m == m_imm => {
expr_vstore(e, expr_vstore_slice)
}
expr_vec(*) if m == m_mutbl =>
expr_vstore(e, expr_vstore_mut_box),
expr_vec(*) if m == m_imm => expr_vstore(e, expr_vstore_box),
- expr_lit(@{node: lit_str(_), span: _}) if m == m_imm =>
+ expr_lit(@spanned {node: lit_str(_), span: _}) if m == m_imm =>
expr_vstore(e, expr_vstore_box),
_ => expr_unary(box(m), e)
};
hi = e.span.hi;
// HACK: turn ~[...] into a ~-evec
ex = match e.node {
- expr_vec(*) | expr_lit(@{node: lit_str(_), span: _})
+ expr_vec(*) | expr_lit(@spanned {node: lit_str(_), span: _})
if m == m_imm => expr_vstore(e, expr_vstore_uniq),
_ => expr_unary(uniq(m), e)
};
return expr_rec(fields, base);
}
- fn parse_alt_expr() -> @expr {
+ fn parse_match_expr() -> @expr {
let lo = self.last_span.lo;
let discriminant = self.parse_expr();
self.expect(token::LBRACE);
self.eat(token::COMMA);
}
- let blk = {node: {view_items: ~[],
- stmts: ~[],
- expr: Some(expr),
- id: self.get_id(),
- rules: default_blk},
- span: expr.span};
+ let blk = spanned { node: { view_items: ~[],
+ stmts: ~[],
+ expr: Some(expr),
+ id: self.get_id(),
+ rules: default_blk},
+ span: expr.span };
arms.push({pats: pats, guard: guard, body: blk});
}
// HACK: parse @"..." as a literal of a vstore @str
pat = match sub.node {
pat_lit(e@@{
- node: expr_lit(@{node: lit_str(_), span: _}), _
+ node: expr_lit(@spanned {node: lit_str(_), span: _}), _
}) => {
let vst = @{id: self.get_id(), callee_id: self.get_id(),
node: expr_vstore(e, expr_vstore_box),
// HACK: parse ~"..." as a literal of a vstore ~str
pat = match sub.node {
pat_lit(e@@{
- node: expr_lit(@{node: lit_str(_), span: _}), _
+ node: expr_lit(@spanned {node: lit_str(_), span: _}), _
}) => {
let vst = @{id: self.get_id(), callee_id: self.get_id(),
node: expr_vstore(e, expr_vstore_uniq),
// HACK: parse &"..." as a literal of a borrowed str
pat = match sub.node {
pat_lit(e@@{
- node: expr_lit(@{node: lit_str(_), span: _}), _
+ node: expr_lit(@spanned {node: lit_str(_), span: _}), _
}) => {
let vst = @{
id: self.get_id(),
if self.token == token::RPAREN {
hi = self.span.hi;
self.bump();
- let lit = @{node: lit_nil, span: mk_sp(lo, hi)};
+ let lit = @spanned {node: lit_nil, span: mk_sp(lo, hi)};
let expr = self.mk_expr(lo, hi, expr_lit(lit));
pat = pat_lit(expr);
} else {
match self.token {
token::SEMI => {
self.bump();
- stmts.push(@{node: stmt_semi(e, stmt_id),
- ..*stmt});
+ stmts.push(@spanned {
+ node: stmt_semi(e, stmt_id),
+ .. *stmt});
}
token::RBRACE => {
expr = Some(e);
match self.token {
token::SEMI => {
self.bump();
- stmts.push(@{node: stmt_mac((*m), true),
- ..*stmt});
+ stmts.push(@spanned {
+ node: stmt_mac((*m), true),
+ .. *stmt});
}
token::RBRACE => {
// if a block ends in `m!(arg)` without
fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
let mut bounds = ~[];
if self.eat(token::COLON) {
- while is_ident(self.token) {
- if is_ident(self.token) {
+ loop {
+ if self.eat(token::BINOP(token::AND)) {
+ if self.eat_keyword(~"static") {
+ bounds.push(RegionTyParamBound);
+ } else {
+ self.span_err(copy self.span,
+ ~"`&static` is the only permissible \
+ region bound here");
+ }
+ } else if is_ident(self.token) {
let maybe_bound = match self.token {
token::IDENT(copy sid, _) => {
match *self.id_to_str(sid) {
ObsoleteLowerCaseKindBounds);
// Bogus value, but doesn't matter, since
// is an error
- Some(ty_param_bound(self.mk_ty_path(sid)))
+ Some(TraitTyParamBound(self.mk_ty_path(sid)))
}
_ => None
bounds.push(bound);
}
None => {
- bounds.push(ty_param_bound(self.parse_ty(false)));
+ let ty = self.parse_ty(false);
+ bounds.push(TraitTyParamBound(ty));
}
}
} else {
- bounds.push(ty_param_bound(self.parse_ty(false)));
+ break;
}
}
}
let actual_dtor = do the_dtor.map |dtor| {
let (d_body, d_attrs, d_s) = *dtor;
- {node: {id: self.get_id(),
- attrs: d_attrs,
- self_id: self.get_id(),
- body: d_body},
- span: d_s}};
+ spanned { node: { id: self.get_id(),
+ attrs: d_attrs,
+ self_id: self.get_id(),
+ body: d_body},
+ span: d_s}};
let _ = self.get_id(); // XXX: Workaround for crazy bug.
let new_id = self.get_id();
(class_name,
self.bump();
let mut actual_dtor = do the_dtor.map |dtor| {
let (d_body, d_attrs, d_s) = *dtor;
- {node: {id: self.get_id(),
- attrs: d_attrs,
- self_id: self.get_id(),
- body: d_body},
- span: d_s}
+ spanned { node: { id: self.get_id(),
+ attrs: d_attrs,
+ self_id: self.get_id(),
+ body: d_body },
+ span: d_s }
};
return @{
_ => self.fatal(~"expected open delimiter")
};
let m = ast::mac_invoc_tt(pth, tts);
- let m: ast::mac = {node: m,
- span: mk_sp(self.span.lo,
- self.span.hi)};
+ let m: ast::mac = spanned { node: m,
+ span: mk_sp(self.span.lo,
+ self.span.hi) };
let item_ = item_mac(m);
return iovi_item(self.mk_item(lo, self.last_span.hi, id, item_,
visibility, attrs));
export unop_prec;
export token_to_binop;
+use ast::*;
use parse::token::*;
use parse::token::Token;
-use ast::*;
+
+use core::prelude::*;
/// Unary operators have higher precedence than binary
const unop_prec: uint = 100u;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use util::interner;
+use core::prelude::*;
+
+use ast;
+use ast_util;
+use parse::token;
use util::interner::Interner;
+use util::interner;
+
+use core::cast;
+use core::char;
+use core::cmp;
+use core::str;
+use core::task;
use std::map::HashMap;
#[auto_encode]
const clownshoes_foreign_mod: ident = ident { repr: 33 };
const unnamed_field: ident = ident { repr: 34 };
const c_abi: ident = ident { repr: 35 };
+ const type_self: ident = ident { repr: 36 }; // `Self`
}
struct ident_interner {
- priv interner: util::interner::Interner<@~str>,
+ priv interner: Interner<@~str>,
}
impl ident_interner {
// the indices here must correspond to the numbers in
// special_idents.
let init_vec = ~[
- @~"_", @~"anon", @~"drop", @~"", @~"unary", @~"!",
- @~"[]", @~"unary-", @~"__extensions__", @~"self",
- @~"item", @~"block", @~"stmt", @~"pat", @~"expr",
- @~"ty", @~"ident", @~"path", @~"tt", @~"matchers",
- @~"str", @~"TyVisitor", @~"arg", @~"descrim",
- @~"__rust_abi", @~"__rust_stack_shim", @~"TyDesc",
- @~"dtor", @~"main", @~"<opaque>", @~"blk", @~"static",
- @~"intrinsic", @~"__foreign_mod__", @~"__field__",
- @~"C"
+ @~"_", // 0
+ @~"anon", // 1
+ @~"drop", // 2
+ @~"", // 3
+ @~"unary", // 4
+ @~"!", // 5
+ @~"[]", // 6
+ @~"unary-", // 7
+ @~"__extensions__", // 8
+ @~"self", // 9
+ @~"item", // 10
+ @~"block", // 11
+ @~"stmt", // 12
+ @~"pat", // 13
+ @~"expr", // 14
+ @~"ty", // 15
+ @~"ident", // 16
+ @~"path", // 17
+ @~"tt", // 18
+ @~"matchers", // 19
+ @~"str", // 20
+ @~"TyVisitor", // 21
+ @~"arg", // 22
+ @~"descrim", // 23
+ @~"__rust_abi", // 24
+ @~"__rust_stack_shim", // 25
+ @~"TyDesc", // 26
+ @~"dtor", // 27
+ @~"main", // 28
+ @~"<opaque>", // 29
+ @~"blk", // 30
+ @~"static", // 31
+ @~"intrinsic", // 32
+ @~"__foreign_mod__", // 33
+ @~"__field__", // 34
+ @~"C", // 35
+ @~"Self", // 36
];
let rv = @ident_interner {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use io::WriterUtil;
-use dvec::DVec;
+use core::prelude::*;
+
+use core::cmp;
+use core::dvec::DVec;
+use core::io::WriterUtil;
+use core::io;
+use core::str;
+use core::vec;
/*
* This pretty-printer is a direct reimplementation of Philip Karlton's
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use parse::{comments, lexer, token};
+use core::prelude::*;
+
+use ast::{RegionTyParamBound, TraitTyParamBound, required, provided};
+use ast;
+use ast_util;
+use ast_util::{operator_prec};
+use attr;
use codemap::{CodeMap, BytePos};
+use codemap;
+use diagnostic;
+use parse::classify::{expr_is_simple_block, expr_requires_semi_to_be_stmt};
+use parse::classify::{stmt_ends_with_semi};
+use parse::token::ident_interner;
+use parse::{comments, lexer, token};
+use parse;
use print::pp::{break_offset, word, printer, space, zerobreak, hardbreak};
use print::pp::{breaks, consistent, inconsistent, eof};
-use ast::{required, provided};
-use ast_util::{operator_prec};
-use dvec::DVec;
-use parse::classify::*;
-use parse::token::ident_interner;
-use str::{push_str, push_char};
+use print::pp;
+use print::pprust;
+
+use core::char;
+use core::dvec::DVec;
+use core::io;
+use core::option;
+use core::str::{push_str, push_char};
+use core::str;
+use core::u64;
+use core::vec;
// The ps is stored here to prevent recursive type.
enum ann_node {
node_expr(ps, @ast::expr),
node_pat(ps, @ast::pat),
}
-type pp_ann = {pre: fn@(ann_node), post: fn@(ann_node)};
+struct pp_ann {
+ pre: fn@(ann_node),
+ post: fn@(ann_node)
+}
fn no_ann() -> pp_ann {
fn ignore(_node: ann_node) { }
- return {pre: ignore, post: ignore};
+ return pp_ann {pre: ignore, post: ignore};
}
type ps =
}
const indent_unit: uint = 4u;
-const alt_indent_unit: uint = 2u;
+const match_indent_unit: uint = 2u;
const default_columns: uint = 78u;
}
bclose(s, item.span);
}
- ast::item_mac({node: ast::mac_invoc_tt(pth, ref tts), _}) => {
+ ast::item_mac(ast::spanned { node: ast::mac_invoc_tt(pth, ref tts),
+ _}) => {
print_visibility(s, item.vis);
print_path(s, pth, false);
word(s.s, ~"! ");
print_block(s, (*blk));
}
ast::expr_match(expr, ref arms) => {
- cbox(s, alt_indent_unit);
+ cbox(s, match_indent_unit);
ibox(s, 4);
word_nbsp(s, ~"match");
print_expr(s, expr);
let len = (*arms).len();
for (*arms).eachi |i, arm| {
space(s.s);
- cbox(s, alt_indent_unit);
+ cbox(s, match_indent_unit);
ibox(s, 0u);
let mut first = true;
for arm.pats.each |p| {
ast::expr_block(ref blk) => {
// the block will close the pattern's ibox
print_block_unclosed_indent(
- s, (*blk), alt_indent_unit);
+ s, (*blk), match_indent_unit);
}
_ => {
end(s); // close the ibox for the pattern
}
} else {
// the block will close the pattern's ibox
- print_block_unclosed_indent(s, arm.body, alt_indent_unit);
+ print_block_unclosed_indent(s, arm.body, match_indent_unit);
}
}
- bclose_(s, expr.span, alt_indent_unit);
+ bclose_(s, expr.span, match_indent_unit);
}
ast::expr_fn(proto, decl, ref body, cap_clause) => {
// containing cbox, will be closed by print-block at }
fn print_bounds(s: ps, bounds: @~[ast::ty_param_bound]) {
if bounds.is_not_empty() {
word(s.s, ~":");
- for vec::each(*bounds) |bound| {
+ for vec::each(*bounds) |&bound| {
nbsp(s);
- print_type(s, **bound);
+ match bound {
+ TraitTyParamBound(ty) => print_type(s, ty),
+ RegionTyParamBound => word(s.s, ~"&static"),
+ }
}
}
}
#[crate_type = "lib"];
-#[no_core];
-
#[legacy_modes];
#[legacy_exports];
#[allow(deprecated_mode)];
#[warn(deprecated_pattern)];
-extern mod core(vers = "0.6");
-extern mod std(vers = "0.6");
+#[no_core];
+extern mod core(vers = "0.6");
use core::*;
+extern mod std(vers = "0.6");
+
pub mod syntax {
pub use ext;
pub use parse;
// An "interner" is a data structure that associates values with uint tags and
// allows bidirectional lookup; i.e. given a value, one can easily find the
// type, and vice versa.
-use std::map;
+
+use core::prelude::*;
+
+use core::dvec::DVec;
use std::map::HashMap;
-use dvec::DVec;
-use cmp::Eq;
-use hash::Hash;
-use to_bytes::IterBytes;
+use std::map;
type hash_interner<T: Const> =
{map: HashMap<T, uint>,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::prelude::*;
use ast::*;
+use ast;
+use ast_util;
use codemap::span;
+use parse;
+
+use core::option;
+use core::vec;
// Context-passing AST walker. Each overridden visit method has full control
// over what happens with its node, it can do its own traversal of the node's
}
}
-type visitor<E> =
- @{visit_mod: fn@(_mod, span, node_id, E, vt<E>),
- visit_view_item: fn@(@view_item, E, vt<E>),
- visit_foreign_item: fn@(@foreign_item, E, vt<E>),
- visit_item: fn@(@item, E, vt<E>),
- visit_local: fn@(@local, E, vt<E>),
- visit_block: fn@(ast::blk, E, vt<E>),
- visit_stmt: fn@(@stmt, E, vt<E>),
- visit_arm: fn@(arm, E, vt<E>),
- visit_pat: fn@(@pat, E, vt<E>),
- visit_decl: fn@(@decl, E, vt<E>),
- visit_expr: fn@(@expr, E, vt<E>),
- visit_expr_post: fn@(@expr, E, vt<E>),
- visit_ty: fn@(@Ty, E, vt<E>),
- visit_ty_params: fn@(~[ty_param], E, vt<E>),
- visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
- visit_ty_method: fn@(ty_method, E, vt<E>),
- visit_trait_method: fn@(trait_method, E, vt<E>),
- visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E,
- vt<E>),
- visit_struct_field: fn@(@struct_field, E, vt<E>),
- visit_struct_method: fn@(@method, E, vt<E>)};
+struct Visitor<E> {
+ visit_mod: fn@(_mod, span, node_id, E, vt<E>),
+ visit_view_item: fn@(@view_item, E, vt<E>),
+ visit_foreign_item: fn@(@foreign_item, E, vt<E>),
+ visit_item: fn@(@item, E, vt<E>),
+ visit_local: fn@(@local, E, vt<E>),
+ visit_block: fn@(ast::blk, E, vt<E>),
+ visit_stmt: fn@(@stmt, E, vt<E>),
+ visit_arm: fn@(arm, E, vt<E>),
+ visit_pat: fn@(@pat, E, vt<E>),
+ visit_decl: fn@(@decl, E, vt<E>),
+ visit_expr: fn@(@expr, E, vt<E>),
+ visit_expr_post: fn@(@expr, E, vt<E>),
+ visit_ty: fn@(@Ty, E, vt<E>),
+ visit_ty_params: fn@(~[ty_param], E, vt<E>),
+ visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
+ visit_ty_method: fn@(ty_method, E, vt<E>),
+ visit_trait_method: fn@(trait_method, E, vt<E>),
+ visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E,
+ vt<E>),
+ visit_struct_field: fn@(@struct_field, E, vt<E>),
+ visit_struct_method: fn@(@method, E, vt<E>)
+}
+
+type visitor<E> = @Visitor<E>;
fn default_visitor<E>() -> visitor<E> {
- return @{visit_mod: |a,b,c,d,e|visit_mod::<E>(a, b, c, d, e),
- visit_view_item: |a,b,c|visit_view_item::<E>(a, b, c),
- visit_foreign_item: |a,b,c|visit_foreign_item::<E>(a, b, c),
- visit_item: |a,b,c|visit_item::<E>(a, b, c),
- visit_local: |a,b,c|visit_local::<E>(a, b, c),
- visit_block: |a,b,c|visit_block::<E>(a, b, c),
- visit_stmt: |a,b,c|visit_stmt::<E>(a, b, c),
- visit_arm: |a,b,c|visit_arm::<E>(a, b, c),
- visit_pat: |a,b,c|visit_pat::<E>(a, b, c),
- visit_decl: |a,b,c|visit_decl::<E>(a, b, c),
- visit_expr: |a,b,c|visit_expr::<E>(a, b, c),
- visit_expr_post: |_a,_b,_c| (),
- visit_ty: |a,b,c|skip_ty::<E>(a, b, c),
- visit_ty_params: |a,b,c|visit_ty_params::<E>(a, b, c),
- visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
- visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
- visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
- visit_struct_def: |a,b,c,d,e,f|visit_struct_def::<E>(a, b, c,
- d, e, f),
- visit_struct_field: |a,b,c|visit_struct_field::<E>(a, b, c),
- visit_struct_method: |a,b,c|visit_struct_method::<E>(a, b, c)};
+ return @Visitor {
+ visit_mod: |a,b,c,d,e|visit_mod::<E>(a, b, c, d, e),
+ visit_view_item: |a,b,c|visit_view_item::<E>(a, b, c),
+ visit_foreign_item: |a,b,c|visit_foreign_item::<E>(a, b, c),
+ visit_item: |a,b,c|visit_item::<E>(a, b, c),
+ visit_local: |a,b,c|visit_local::<E>(a, b, c),
+ visit_block: |a,b,c|visit_block::<E>(a, b, c),
+ visit_stmt: |a,b,c|visit_stmt::<E>(a, b, c),
+ visit_arm: |a,b,c|visit_arm::<E>(a, b, c),
+ visit_pat: |a,b,c|visit_pat::<E>(a, b, c),
+ visit_decl: |a,b,c|visit_decl::<E>(a, b, c),
+ visit_expr: |a,b,c|visit_expr::<E>(a, b, c),
+ visit_expr_post: |_a,_b,_c| (),
+ visit_ty: |a,b,c|skip_ty::<E>(a, b, c),
+ visit_ty_params: |a,b,c|visit_ty_params::<E>(a, b, c),
+ visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
+ visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
+ visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
+ visit_struct_def: |a,b,c,d,e,f|visit_struct_def::<E>(a, b, c,
+ d, e, f),
+ visit_struct_field: |a,b,c|visit_struct_field::<E>(a, b, c),
+ visit_struct_method: |a,b,c|visit_struct_method::<E>(a, b, c)
+ };
}
fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
}
fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) {
- for vec::each(*bounds) |bound| {
- (v.visit_ty)(**bound, e, v)
+ for bounds.each |&bound| {
+ match bound {
+ TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v),
+ RegionTyParamBound => ()
+ }
}
}
// Simpler, non-context passing interface. Always walks the whole tree, simply
// calls the given functions on the nodes.
-type simple_visitor =
- @{visit_mod: fn@(_mod, span, node_id),
- visit_view_item: fn@(@view_item),
- visit_foreign_item: fn@(@foreign_item),
- visit_item: fn@(@item),
- visit_local: fn@(@local),
- visit_block: fn@(ast::blk),
- visit_stmt: fn@(@stmt),
- visit_arm: fn@(arm),
- visit_pat: fn@(@pat),
- visit_decl: fn@(@decl),
- visit_expr: fn@(@expr),
- visit_expr_post: fn@(@expr),
- visit_ty: fn@(@Ty),
- visit_ty_params: fn@(~[ty_param]),
- visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
- visit_ty_method: fn@(ty_method),
- visit_trait_method: fn@(trait_method),
- visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id),
- visit_struct_field: fn@(@struct_field),
- visit_struct_method: fn@(@method)};
+struct SimpleVisitor {
+ visit_mod: fn@(_mod, span, node_id),
+ visit_view_item: fn@(@view_item),
+ visit_foreign_item: fn@(@foreign_item),
+ visit_item: fn@(@item),
+ visit_local: fn@(@local),
+ visit_block: fn@(ast::blk),
+ visit_stmt: fn@(@stmt),
+ visit_arm: fn@(arm),
+ visit_pat: fn@(@pat),
+ visit_decl: fn@(@decl),
+ visit_expr: fn@(@expr),
+ visit_expr_post: fn@(@expr),
+ visit_ty: fn@(@Ty),
+ visit_ty_params: fn@(~[ty_param]),
+ visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
+ visit_ty_method: fn@(ty_method),
+ visit_trait_method: fn@(trait_method),
+ visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id),
+ visit_struct_field: fn@(@struct_field),
+ visit_struct_method: fn@(@method)
+}
+
+type simple_visitor = @SimpleVisitor;
fn simple_ignore_ty(_t: @Ty) {}
-fn default_simple_visitor() -> simple_visitor {
- return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { },
- visit_view_item: fn@(_vi: @view_item) { },
- visit_foreign_item: fn@(_ni: @foreign_item) { },
- visit_item: fn@(_i: @item) { },
- visit_local: fn@(_l: @local) { },
- visit_block: fn@(_b: ast::blk) { },
- visit_stmt: fn@(_s: @stmt) { },
- visit_arm: fn@(_a: arm) { },
- visit_pat: fn@(_p: @pat) { },
- visit_decl: fn@(_d: @decl) { },
- visit_expr: fn@(_e: @expr) { },
- visit_expr_post: fn@(_e: @expr) { },
+fn default_simple_visitor() -> @SimpleVisitor {
+ return @SimpleVisitor {visit_mod: |_m: _mod, _sp: span, _id: node_id| { },
+ visit_view_item: |_vi: @view_item| { },
+ visit_foreign_item: |_ni: @foreign_item| { },
+ visit_item: |_i: @item| { },
+ visit_local: |_l: @local| { },
+ visit_block: |_b: ast::blk| { },
+ visit_stmt: |_s: @stmt| { },
+ visit_arm: |_a: arm| { },
+ visit_pat: |_p: @pat| { },
+ visit_decl: |_d: @decl| { },
+ visit_expr: |_e: @expr| { },
+ visit_expr_post: |_e: @expr| { },
visit_ty: simple_ignore_ty,
visit_ty_params: fn@(_ps: ~[ty_param]) {},
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
f(m);
visit_struct_method(m, e, v);
}
- return mk_vt(@{visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e),
- visit_view_item: |a,b,c|
- v_view_item(v.visit_view_item, a, b, c),
- visit_foreign_item:
- |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c),
- visit_item: |a,b,c|v_item(v.visit_item, a, b, c),
- visit_local: |a,b,c|v_local(v.visit_local, a, b, c),
- visit_block: |a,b,c|v_block(v.visit_block, a, b, c),
- visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c),
- visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c),
- visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c),
- visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c),
- visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c),
- visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post,
- a, b, c),
- visit_ty: visit_ty,
- visit_ty_params: |a,b,c|
- v_ty_params(v.visit_ty_params, a, b, c),
- visit_fn: |a,b,c,d,e,f,g|
- v_fn(v.visit_fn, a, b, c, d, e, f, g),
- visit_ty_method: |a,b,c|
- v_ty_method(v.visit_ty_method, a, b, c),
- visit_trait_method: |a,b,c|
- v_trait_method(v.visit_trait_method, a, b, c),
- visit_struct_def: |a,b,c,d,e,f|
- v_struct_def(v.visit_struct_def, a, b, c, d, e, f),
- visit_struct_field: |a,b,c|
- v_struct_field(v.visit_struct_field, a, b, c),
- visit_struct_method: |a,b,c|
- v_struct_method(v.visit_struct_method, a, b, c)
- });
+ return mk_vt(@Visitor {
+ visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e),
+ visit_view_item: |a,b,c| v_view_item(v.visit_view_item, a, b, c),
+ visit_foreign_item:
+ |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c),
+ visit_item: |a,b,c|v_item(v.visit_item, a, b, c),
+ visit_local: |a,b,c|v_local(v.visit_local, a, b, c),
+ visit_block: |a,b,c|v_block(v.visit_block, a, b, c),
+ visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c),
+ visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c),
+ visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c),
+ visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c),
+ visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c),
+ visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post,
+ a, b, c),
+ visit_ty: visit_ty,
+ visit_ty_params: |a,b,c|
+ v_ty_params(v.visit_ty_params, a, b, c),
+ visit_fn: |a,b,c,d,e,f,g|
+ v_fn(v.visit_fn, a, b, c, d, e, f, g),
+ visit_ty_method: |a,b,c|
+ v_ty_method(v.visit_ty_method, a, b, c),
+ visit_trait_method: |a,b,c|
+ v_trait_method(v.visit_trait_method, a, b, c),
+ visit_struct_def: |a,b,c,d,e,f|
+ v_struct_def(v.visit_struct_def, a, b, c, d, e, f),
+ visit_struct_field: |a,b,c|
+ v_struct_field(v.visit_struct_field, a, b, c),
+ visit_struct_method: |a,b,c|
+ v_struct_method(v.visit_struct_method, a, b, c)
+ });
}
// Local Variables:
-Subproject commit 1170ffba3ac5191930b40c897d4569a9d8a296a3
+Subproject commit 4d392c86feb6389f550d8110d36fa90d66c09251
--- /dev/null
+.text
+.code 32
+.arm
+.align
+
+
+.globl swap_registers
+swap_registers:
+ str r0, [r0, #0]
+ str r3, [r0, #12]
+ str r4, [r0, #16]
+ str r5, [r0, #20]
+ str r6, [r0, #24]
+ str r7, [r0, #28]
+ str r8, [r0, #32]
+ str r9, [r0, #36]
+ str r10, [r0, #40]
+ str r11, [r0, #44]
+ str r12, [r0, #48]
+ str sp, [r0, #52]
+ str lr, [r0, #56]
+
+ mrs r2, cpsr
+ str r2, [r0, #64]
+
+
+ ldr r0, [r1, #0]
+ ldr r3, [r1, #12]
+ ldr r4, [r1, #16]
+ ldr r5, [r1, #20]
+ ldr r6, [r1, #24]
+ ldr r7, [r1, #28]
+ ldr r8, [r1, #32]
+ ldr r9, [r1, #36]
+ ldr r10, [r1, #40]
+ ldr r11, [r1, #44]
+ ldr r12, [r1, #48]
+
+ ldr sp, [r1, #52]
+ ldr lr, [r1, #56]
+
+ ldr r2, [r1, #64]
+ msr cpsr_cxsf, r2
+
+ mov pc, lr
+
+
--- /dev/null
+.text
+.code 32
+.arm
+.align
+
+.globl __morestack
+.hidden __morestack
+__morestack:
+ mov r3, sp
+ mov sp, r2
+
+ str r3, [sp]
+ str lr, [sp, #-4]
+
+ sub sp, #8
+
+ blx r1
+
+ add sp, #8
+
+ ldr lr, [sp, #-4]
+ ldr r3, [sp]
+
+ mov sp, r3
+ mov pc, lr
+
+
--- /dev/null
+
+#include "context.h"
+#include "../../rust_globals.h"
+
+extern "C" void CDECL swap_registers(registers_t *oregs,
+ registers_t *regs)
+asm ("swap_registers");
+
+context::context()
+{
+ assert((void*)®s == (void*)this);
+ memset(®s, 0, sizeof(regs));
+}
+
+void context::swap(context &out)
+{
+ swap_registers(&out.regs, ®s);
+}
+
+void context::call(void *f, void *arg, void *stack)
+{
+ // Get the current context, which we will then modify to call the
+ // given function.
+ swap(*this);
+
+ // set up the stack
+ uint32_t *sp = ( uint32_t *)stack;
+ //sp = align_down(sp);
+ // The final return address. 0 indicates the bottom of the stack
+ *--sp = 0;
+
+ regs.data[0] = ( uint32_t )arg; // r0
+ regs.data[13] = ( uint32_t )sp; //#52 sp, r13
+ regs.data[14] = ( uint32_t )f; //#60 pc, r15 --> lr,
+ // Last base pointer on the stack should be 0
+}
--- /dev/null
+// -*- mode: c++ -*-
+
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+#include <cstdlib>
+#include <inttypes.h>
+#include <stdint.h>
+//#include <xmmintrin.h>
+
+#include "vg/memcheck.h"
+
+template<typename T>
+T align_down(T sp)
+{
+ // There is no platform we care about that needs more than a
+ // 16-byte alignment.
+ return (T)((uint32_t)sp & ~(16 - 1));
+}
+
+// The struct in which we store the saved data. This is mostly the
+// volatile registers and instruction pointer, but it also includes
+// RCX/RDI which are used to pass arguments. The indices for each
+// register are found in "regs.h". Note that the alignment must be
+// 16 bytes so that SSE instructions can be used.
+#include "regs.h"
+struct registers_t {
+ uint32_t data[RUSTRT_MAX];
+} __attribute__((aligned(16)));
+
+class context {
+public:
+ registers_t regs;
+
+ context();
+
+ context *next;
+
+ void swap(context &out);
+ void call(void *f, void *arg, void *sp);
+};
+
+#endif
--- /dev/null
+#include "gpr.h"
+
+#define LOAD(rn) do { \
+ uintptr_t tmp; \
+ asm("mov %%" #rn ",%0" : "=r" (tmp) :); \
+ this->rn = tmp; \
+} while (0)
+
+void rust_gpr::load() {
+ LOAD(r0); LOAD(r1); LOAD(r2); LOAD(r3);
+ LOAD(r4); LOAD(r5); LOAD(r6); LOAD(r7);
+ LOAD(r8); LOAD(r9); LOAD(r10); LOAD(r11);
+ LOAD(r12); LOAD(r13); LOAD(r14); LOAD(r15);
+}
+
--- /dev/null
+// General-purpose registers. This structure is used during stack crawling.
+
+#ifndef GPR_H
+#define GPR_H
+
+#include "rust_gpr_base.h"
+
+class rust_gpr : public rust_gpr_base {
+public:
+ uintptr_t r0, r1, r2, r3, r4, r5, r6, r7;
+ uintptr_t r8, r9, r10, r11, r12, r13, r14, r15;
+
+ inline uintptr_t get_fp() { return r11; }
+ inline uintptr_t get_ip() { return r12; }
+
+ inline void set_fp(uintptr_t new_fp) { r11 = new_fp; }
+ inline void set_ip(uintptr_t new_ip) { r12 = new_ip; }
+
+ void load();
+};
+
+#endif
+
--- /dev/null
+.text
+.code 32
+.arm
+.align
+
+
+.globl record_sp_limit
+.globl get_sp_limit
+.globl get_sp
+
+record_sp_limit:
+ mov r3, r0
+ ldr r0, =my_cpu
+ mov r1, #0
+ mov r2, #0
+ stmfd sp!, {r3, r7}
+ ldr r7, =345
+ swi #0
+ ldmfd sp!, {r3, r7}
+ movs r0, r0
+ movmi r0, #0
+
+ ldr r1, =my_array
+ str r3, [r1, r0]
+ mov pc, lr
+
+
+get_sp_limit:
+ ldr r0, =my_cpu
+ mov r1, #0
+ mov r2, #0
+ stmfd sp!, {r4, r7}
+ ldr r7, =345
+ swi #0
+ ldmfd sp!, {r4, r7}
+ movs r0, r0
+ movmi r0, #0
+ mov r3, r0
+
+ ldr r1, =my_array
+ ldr r0, [r1, r3]
+ mov pc, lr
+
+
+get_sp:
+ mov r0, sp
+ mov pc, lr
+
+.data
+my_cpu: .long 0
+.global my_array
+my_array:
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+ .long 0
+.end
--- /dev/null
+#define RUSTRT_RBX 0
+#define RUSTRT_RSP 1
+#define RUSTRT_RBP 2
+// RCX on Windows, RDI elsewhere
+#define RUSTRT_ARG0 3
+#define RUSTRT_R12 4
+#define RUSTRT_R13 5
+#define RUSTRT_R14 6
+#define RUSTRT_R15 7
+#define RUSTRT_IP 8
+
+#define RUSTRT_MAX 32
+
+// ARG0 is the register in which the first argument goes.
+// Naturally this depends on your operating system.
+# define RUSTRT_ARG0_S r0
+# define RUSTRT_ARG1_S r1
+# define RUSTRT_ARG2_S r2
+# define RUSTRT_ARG3_S r3
+
+
+++ /dev/null
-/* bigint.h - include file for bigint package
-**
-** This library lets you do math on arbitrarily large integers. It's
-** pretty fast - compared with the multi-precision routines in the "bc"
-** calculator program, these routines are between two and twelve times faster,
-** except for division which is maybe half as fast.
-**
-** The calling convention is a little unusual. There's a basic problem
-** with writing a math library in a language that doesn't do automatic
-** garbage collection - what do you do about intermediate results?
-** You'd like to be able to write code like this:
-**
-** d = bi_sqrt( bi_add( bi_multiply( x, x ), bi_multiply( y, y ) ) );
-**
-** That works fine when the numbers being passed back and forth are
-** actual values - ints, floats, or even fixed-size structs. However,
-** when the numbers can be any size, as in this package, then you have
-** to pass them around as pointers to dynamically-allocated objects.
-** Those objects have to get de-allocated after you are done with them.
-** But how do you de-allocate the intermediate results in a complicated
-** multiple-call expression like the above?
-**
-** There are two common solutions to this problem. One, switch all your
-** code to a language that provides automatic garbage collection, for
-** example Java. This is a fine idea and I recommend you do it wherever
-** it's feasible. Two, change your routines to use a calling convention
-** that prevents people from writing multiple-call expressions like that.
-** The resulting code will be somewhat clumsy-looking, but it will work
-** just fine.
-**
-** This package uses a third method, which I haven't seen used anywhere
-** before. It's simple: each number can be used precisely once, after
-** which it is automatically de-allocated. This handles the anonymous
-** intermediate values perfectly. Named values still need to be copied
-** and freed explicitly. Here's the above example using this convention:
-**
-** d = bi_sqrt( bi_add(
-** bi_multiply( bi_copy( x ), bi_copy( x ) ),
-** bi_multiply( bi_copy( y ), bi_copy( y ) ) ) );
-** bi_free( x );
-** bi_free( y );
-**
-** Or, since the package contains a square routine, you could just write:
-**
-** d = bi_sqrt( bi_add( bi_square( x ), bi_square( y ) ) );
-**
-** This time the named values are only being used once, so you don't
-** have to copy and free them.
-**
-** This really works, however you do have to be very careful when writing
-** your code. If you leave out a bi_copy() and use a value more than once,
-** you'll get a runtime error about "zero refs" and a SIGFPE. Run your
-** code in a debugger, get a backtrace to see where the call was, and then
-** eyeball the code there to see where you need to add the bi_copy().
-**
-**
-** Copyright © 2000 by Jef Poskanzer <jef@mail.acme.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-** SUCH DAMAGE.
-*/
-
-
-/* Type definition for bigints - it's an opaque type, the real definition
-** is in bigint.c.
-*/
-typedef void* bigint;
-
-
-/* Some convenient pre-initialized numbers. These are all permanent,
-** so you can use them as many times as you want without calling bi_copy().
-*/
-extern bigint bi_0, bi_1, bi_2, bi_10, bi_m1, bi_maxint, bi_minint;
-
-
-/* Initialize the bigint package. You must call this when your program
-** starts up.
-*/
-void bi_initialize( void );
-
-/* Shut down the bigint package. You should call this when your program
-** exits. It's not actually required, but it does do some consistency
-** checks which help keep your program bug-free, so you really ought
-** to call it.
-*/
-void bi_terminate( void );
-
-/* Run in unsafe mode, skipping most runtime checks. Slightly faster.
-** Once your code is debugged you can add this call after bi_initialize().
-*/
-void bi_no_check( void );
-
-/* Make a copy of a bigint. You must call this if you want to use a
-** bigint more than once. (Or you can make the bigint permanent.)
-** Note that this routine is very cheap - all it actually does is
-** increment a reference counter.
-*/
-bigint bi_copy( bigint bi );
-
-/* Make a bigint permanent, so it doesn't get automatically freed when
-** used as an operand.
-*/
-void bi_permanent( bigint bi );
-
-/* Undo bi_permanent(). The next use will free the bigint. */
-void bi_depermanent( bigint bi );
-
-/* Explicitly free a bigint. Normally bigints get freed automatically
-** when they are used as an operand. This routine lets you free one
-** without using it. If the bigint is permanent, this doesn't do
-** anything, you have to depermanent it first.
-*/
-void bi_free( bigint bi );
-
-/* Compare two bigints. Returns -1, 0, or 1. */
-int bi_compare( bigint bia, bigint bib );
-
-/* Convert an int to a bigint. */
-bigint int_to_bi( int i );
-
-/* Convert a string to a bigint. */
-bigint str_to_bi( char* str );
-
-/* Convert a bigint to an int. SIGFPE on overflow. */
-int bi_to_int( bigint bi );
-
-/* Write a bigint to a file. */
-void bi_print( FILE* f, bigint bi );
-
-/* Read a bigint from a file. */
-bigint bi_scan( FILE* f );
-
-
-/* Operations on a bigint and a regular int. */
-
-/* Add an int to a bigint. */
-bigint bi_int_add( bigint bi, int i );
-
-/* Subtract an int from a bigint. */
-bigint bi_int_subtract( bigint bi, int i );
-
-/* Multiply a bigint by an int. */
-bigint bi_int_multiply( bigint bi, int i );
-
-/* Divide a bigint by an int. SIGFPE on divide-by-zero. */
-bigint bi_int_divide( bigint binumer, int denom );
-
-/* Take the remainder of a bigint by an int, with an int result.
-** SIGFPE if m is zero.
-*/
-int bi_int_rem( bigint bi, int m );
-
-/* Take the modulus of a bigint by an int, with an int result.
-** Note that mod is not rem: mod is always within [0..m), while
-** rem can be negative. SIGFPE if m is zero or negative.
-*/
-int bi_int_mod( bigint bi, int m );
-
-
-/* Basic operations on two bigints. */
-
-/* Add two bigints. */
-bigint bi_add( bigint bia, bigint bib );
-
-/* Subtract bib from bia. */
-bigint bi_subtract( bigint bia, bigint bib );
-
-/* Multiply two bigints. */
-bigint bi_multiply( bigint bia, bigint bib );
-
-/* Divide one bigint by another. SIGFPE on divide-by-zero. */
-bigint bi_divide( bigint binumer, bigint bidenom );
-
-/* Binary division of one bigint by another. SIGFPE on divide-by-zero.
-** This is here just for testing. It's about five times slower than
-** regular division.
-*/
-bigint bi_binary_divide( bigint binumer, bigint bidenom );
-
-/* Take the remainder of one bigint by another. SIGFPE if bim is zero. */
-bigint bi_rem( bigint bia, bigint bim );
-
-/* Take the modulus of one bigint by another. Note that mod is not rem:
-** mod is always within [0..bim), while rem can be negative. SIGFPE if
-** bim is zero or negative.
-*/
-bigint bi_mod( bigint bia, bigint bim );
-
-
-/* Some less common operations. */
-
-/* Negate a bigint. */
-bigint bi_negate( bigint bi );
-
-/* Absolute value of a bigint. */
-bigint bi_abs( bigint bi );
-
-/* Divide a bigint in half. */
-bigint bi_half( bigint bi );
-
-/* Multiply a bigint by two. */
-bigint bi_double( bigint bi );
-
-/* Square a bigint. */
-bigint bi_square( bigint bi );
-
-/* Raise bi to the power of biexp. SIGFPE if biexp is negative. */
-bigint bi_power( bigint bi, bigint biexp );
-
-/* Integer square root. */
-bigint bi_sqrt( bigint bi );
-
-/* Factorial. */
-bigint bi_factorial( bigint bi );
-
-
-/* Some predicates. */
-
-/* 1 if the bigint is odd, 0 if it's even. */
-int bi_is_odd( bigint bi );
-
-/* 1 if the bigint is even, 0 if it's odd. */
-int bi_is_even( bigint bi );
-
-/* 1 if the bigint equals zero, 0 if it's nonzero. */
-int bi_is_zero( bigint bi );
-
-/* 1 if the bigint equals one, 0 otherwise. */
-int bi_is_one( bigint bi );
-
-/* 1 if the bigint is less than zero, 0 if it's zero or greater. */
-int bi_is_negative( bigint bi );
-
-
-/* Now we get into the esoteric number-theory stuff used for cryptography. */
-
-/* Modular exponentiation. Much faster than bi_mod(bi_power(bi,biexp),bim).
-** Also, biexp can be negative.
-*/
-bigint bi_mod_power( bigint bi, bigint biexp, bigint bim );
-
-/* Modular inverse. mod( bi * modinv(bi), bim ) == 1. SIGFPE if bi is not
-** relatively prime to bim.
-*/
-bigint bi_mod_inverse( bigint bi, bigint bim );
-
-/* Produce a random number in the half-open interval [0..bi). You need
-** to have called srandom() before using this.
-*/
-bigint bi_random( bigint bi );
-
-/* Greatest common divisor of two bigints. Euclid's algorithm. */
-bigint bi_gcd( bigint bim, bigint bin );
-
-/* Greatest common divisor of two bigints, plus the corresponding multipliers.
-** Extended Euclid's algorithm.
-*/
-bigint bi_egcd( bigint bim, bigint bin, bigint* bim_mul, bigint* bin_mul );
-
-/* Least common multiple of two bigints. */
-bigint bi_lcm( bigint bia, bigint bib );
-
-/* The Jacobi symbol. SIGFPE if bib is even. */
-bigint bi_jacobi( bigint bia, bigint bib );
-
-/* Probabalistic prime checking. A non-zero return means the probability
-** that bi is prime is at least 1 - 1/2 ^ certainty.
-*/
-int bi_is_probable_prime( bigint bi, int certainty );
-
-/* Random probabilistic prime with the specified number of bits. */
-bigint bi_generate_prime( int bits, int certainty );
-
-/* Number of bits in the number. The log base 2, approximately. */
-int bi_bits( bigint bi );
+++ /dev/null
-/* bigint_ext - external portion of large integer package
-**
-** Copyright © 2000 by Jef Poskanzer <jef@mail.acme.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-** SUCH DAMAGE.
-*/
-
-#include <sys/types.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-
-#include "bigint.h"
-#include "low_primes.h"
-
-
-bigint bi_0, bi_1, bi_2, bi_10, bi_m1, bi_maxint, bi_minint;
-
-
-/* Forwards. */
-static void print_pos( FILE* f, bigint bi );
-
-
-bigint
-str_to_bi( char* str )
- {
- int sign;
- bigint biR;
-
- sign = 1;
- if ( *str == '-' )
- {
- sign = -1;
- ++str;
- }
- for ( biR = bi_0; *str >= '0' && *str <= '9'; ++str )
- biR = bi_int_add( bi_int_multiply( biR, 10 ), *str - '0' );
- if ( sign == -1 )
- biR = bi_negate( biR );
- return biR;
- }
-
-
-void
-bi_print( FILE* f, bigint bi )
- {
- if ( bi_is_negative( bi_copy( bi ) ) )
- {
- putc( '-', f );
- bi = bi_negate( bi );
- }
- print_pos( f, bi );
- }
-
-
-bigint
-bi_scan( FILE* f )
- {
- int sign;
- int c;
- bigint biR;
-
- sign = 1;
- c = getc( f );
- if ( c == '-' )
- sign = -1;
- else
- ungetc( c, f );
-
- biR = bi_0;
- for (;;)
- {
- c = getc( f );
- if ( c < '0' || c > '9' )
- break;
- biR = bi_int_add( bi_int_multiply( biR, 10 ), c - '0' );
- }
-
- if ( sign == -1 )
- biR = bi_negate( biR );
- return biR;
- }
-
-
-static void
-print_pos( FILE* f, bigint bi )
- {
- if ( bi_compare( bi_copy( bi ), bi_10 ) >= 0 )
- print_pos( f, bi_int_divide( bi_copy( bi ), 10 ) );
- putc( bi_int_mod( bi, 10 ) + '0', f );
- }
-
-
-int
-bi_int_mod( bigint bi, int m )
- {
- int r;
-
- if ( m <= 0 )
- {
- (void) fprintf( stderr, "bi_int_mod: zero or negative modulus\n" );
- (void) kill( getpid(), SIGFPE );
- }
- r = bi_int_rem( bi, m );
- if ( r < 0 )
- r += m;
- return r;
- }
-
-
-bigint
-bi_rem( bigint bia, bigint bim )
- {
- return bi_subtract(
- bia, bi_multiply( bi_divide( bi_copy( bia ), bi_copy( bim ) ), bim ) );
- }
-
-
-bigint
-bi_mod( bigint bia, bigint bim )
- {
- bigint biR;
-
- if ( bi_compare( bi_copy( bim ), bi_0 ) <= 0 )
- {
- (void) fprintf( stderr, "bi_mod: zero or negative modulus\n" );
- (void) kill( getpid(), SIGFPE );
- }
- biR = bi_rem( bia, bi_copy( bim ) );
- if ( bi_is_negative( bi_copy( biR ) ) )
- biR = bi_add( biR, bim );
- else
- bi_free( bim );
- return biR;
- }
-
-
-bigint
-bi_square( bigint bi )
- {
- bigint biR;
-
- biR = bi_multiply( bi_copy( bi ), bi_copy( bi ) );
- bi_free( bi );
- return biR;
- }
-
-
-bigint
-bi_power( bigint bi, bigint biexp )
- {
- bigint biR;
-
- if ( bi_is_negative( bi_copy( biexp ) ) )
- {
- (void) fprintf( stderr, "bi_power: negative exponent\n" );
- (void) kill( getpid(), SIGFPE );
- }
- biR = bi_1;
- for (;;)
- {
- if ( bi_is_odd( bi_copy( biexp ) ) )
- biR = bi_multiply( biR, bi_copy( bi ) );
- biexp = bi_half( biexp );
- if ( bi_compare( bi_copy( biexp ), bi_0 ) <= 0 )
- break;
- bi = bi_multiply( bi_copy( bi ), bi );
- }
- bi_free( bi );
- bi_free( biexp );
- return biR;
- }
-
-
-bigint
-bi_factorial( bigint bi )
- {
- bigint biR;
-
- biR = bi_1;
- while ( bi_compare( bi_copy( bi ), bi_1 ) > 0 )
- {
- biR = bi_multiply( biR, bi_copy( bi ) );
- bi = bi_int_subtract( bi, 1 );
- }
- bi_free( bi );
- return biR;
- }
-
-
-int
-bi_is_even( bigint bi )
- {
- return ! bi_is_odd( bi );
- }
-
-
-bigint
-bi_mod_power( bigint bi, bigint biexp, bigint bim )
- {
- int invert;
- bigint biR;
-
- invert = 0;
- if ( bi_is_negative( bi_copy( biexp ) ) )
- {
- biexp = bi_negate( biexp );
- invert = 1;
- }
-
- biR = bi_1;
- for (;;)
- {
- if ( bi_is_odd( bi_copy( biexp ) ) )
- biR = bi_mod( bi_multiply( biR, bi_copy( bi ) ), bi_copy( bim ) );
- biexp = bi_half( biexp );
- if ( bi_compare( bi_copy( biexp ), bi_0 ) <= 0 )
- break;
- bi = bi_mod( bi_multiply( bi_copy( bi ), bi ), bi_copy( bim ) );
- }
- bi_free( bi );
- bi_free( biexp );
-
- if ( invert )
- biR = bi_mod_inverse( biR, bim );
- else
- bi_free( bim );
- return biR;
- }
-
-
-bigint
-bi_mod_inverse( bigint bi, bigint bim )
- {
- bigint gcd, mul0, mul1;
-
- gcd = bi_egcd( bi_copy( bim ), bi, &mul0, &mul1 );
-
- /* Did we get gcd == 1? */
- if ( ! bi_is_one( gcd ) )
- {
- (void) fprintf( stderr, "bi_mod_inverse: not relatively prime\n" );
- (void) kill( getpid(), SIGFPE );
- }
-
- bi_free( mul0 );
- return bi_mod( mul1, bim );
- }
-
-
-/* Euclid's algorithm. */
-bigint
-bi_gcd( bigint bim, bigint bin )
- {
- bigint bit;
-
- bim = bi_abs( bim );
- bin = bi_abs( bin );
- while ( ! bi_is_zero( bi_copy( bin ) ) )
- {
- bit = bi_mod( bim, bi_copy( bin ) );
- bim = bin;
- bin = bit;
- }
- bi_free( bin );
- return bim;
- }
-
-
-/* Extended Euclidean algorithm. */
-bigint
-bi_egcd( bigint bim, bigint bin, bigint* bim_mul, bigint* bin_mul )
- {
- bigint a0, b0, c0, a1, b1, c1, q, t;
-
- if ( bi_is_negative( bi_copy( bim ) ) )
- {
- bigint biR;
-
- biR = bi_egcd( bi_negate( bim ), bin, &t, bin_mul );
- *bim_mul = bi_negate( t );
- return biR;
- }
- if ( bi_is_negative( bi_copy( bin ) ) )
- {
- bigint biR;
-
- biR = bi_egcd( bim, bi_negate( bin ), bim_mul, &t );
- *bin_mul = bi_negate( t );
- return biR;
- }
-
- a0 = bi_1; b0 = bi_0; c0 = bim;
- a1 = bi_0; b1 = bi_1; c1 = bin;
-
- while ( ! bi_is_zero( bi_copy( c1 ) ) )
- {
- q = bi_divide( bi_copy( c0 ), bi_copy( c1 ) );
- t = a0;
- a0 = bi_copy( a1 );
- a1 = bi_subtract( t, bi_multiply( bi_copy( q ), a1 ) );
- t = b0;
- b0 = bi_copy( b1 );
- b1 = bi_subtract( t, bi_multiply( bi_copy( q ), b1 ) );
- t = c0;
- c0 = bi_copy( c1 );
- c1 = bi_subtract( t, bi_multiply( bi_copy( q ), c1 ) );
- bi_free( q );
- }
-
- bi_free( a1 );
- bi_free( b1 );
- bi_free( c1 );
- *bim_mul = a0;
- *bin_mul = b0;
- return c0;
- }
-
-
-bigint
-bi_lcm( bigint bia, bigint bib )
- {
- bigint biR;
-
- biR = bi_divide(
- bi_multiply( bi_copy( bia ), bi_copy( bib ) ),
- bi_gcd( bi_copy( bia ), bi_copy( bib ) ) );
- bi_free( bia );
- bi_free( bib );
- return biR;
- }
-
-
-/* The Jacobi symbol. */
-bigint
-bi_jacobi( bigint bia, bigint bib )
- {
- bigint biR;
-
- if ( bi_is_even( bi_copy( bib ) ) )
- {
- (void) fprintf( stderr, "bi_jacobi: don't know how to compute Jacobi(n, even)\n" );
- (void) kill( getpid(), SIGFPE );
- }
-
- if ( bi_compare( bi_copy( bia ), bi_copy( bib ) ) >= 0 )
- return bi_jacobi( bi_mod( bia, bi_copy( bib ) ), bib );
-
- if ( bi_is_zero( bi_copy( bia ) ) || bi_is_one( bi_copy( bia ) ) )
- {
- bi_free( bib );
- return bia;
- }
-
- if ( bi_compare( bi_copy( bia ), bi_2 ) == 0 )
- {
- bi_free( bia );
- switch ( bi_int_mod( bib, 8 ) )
- {
- case 1: case 7:
- return bi_1;
- case 3: case 5:
- return bi_m1;
- }
- }
-
- if ( bi_is_even( bi_copy( bia ) ) )
- {
- biR = bi_multiply(
- bi_jacobi( bi_2, bi_copy( bib ) ),
- bi_jacobi( bi_half( bia ), bi_copy( bib ) ) );
- bi_free( bib );
- return biR;
- }
-
- if ( bi_int_mod( bi_copy( bia ), 4 ) == 3 &&
- bi_int_mod( bi_copy( bib ), 4 ) == 3 )
- return bi_negate( bi_jacobi( bib, bia ) );
- else
- return bi_jacobi( bib, bia );
- }
-
-
-/* Probabalistic prime checking. */
-int
-bi_is_probable_prime( bigint bi, int certainty )
- {
- int i, p;
- bigint bim1;
-
- /* First do trial division by a list of small primes. This eliminates
- ** many candidates.
- */
- for ( i = 0; i < sizeof(low_primes)/sizeof(*low_primes); ++i )
- {
- p = low_primes[i];
- switch ( bi_compare( int_to_bi( p ), bi_copy( bi ) ) )
- {
- case 0:
- bi_free( bi );
- return 1;
- case 1:
- bi_free( bi );
- return 0;
- }
- if ( bi_int_mod( bi_copy( bi ), p ) == 0 )
- {
- bi_free( bi );
- return 0;
- }
- }
-
- /* Now do the probabilistic tests. */
- bim1 = bi_int_subtract( bi_copy( bi ), 1 );
- for ( i = 0; i < certainty; ++i )
- {
- bigint a, j, jac;
-
- /* Pick random test number. */
- a = bi_random( bi_copy( bi ) );
-
- /* Decide whether to run the Fermat test or the Solovay-Strassen
- ** test. The Fermat test is fast but lets some composite numbers
- ** through. Solovay-Strassen runs slower but is more certain.
- ** So the compromise here is we run the Fermat test a couple of
- ** times to quickly reject most composite numbers, and then do
- ** the rest of the iterations with Solovay-Strassen so nothing
- ** slips through.
- */
- if ( i < 2 && certainty >= 5 )
- {
- /* Fermat test. Note that this is not state of the art. There's a
- ** class of numbers called Carmichael numbers which are composite
- ** but look prime to this test - it lets them slip through no
- ** matter how many reps you run. However, it's nice and fast so
- ** we run it anyway to help quickly reject most of the composites.
- */
- if ( ! bi_is_one( bi_mod_power( bi_copy( a ), bi_copy( bim1 ), bi_copy( bi ) ) ) )
- {
- bi_free( bi );
- bi_free( bim1 );
- bi_free( a );
- return 0;
- }
- }
- else
- {
- /* GCD test. This rarely hits, but we need it for Solovay-Strassen. */
- if ( ! bi_is_one( bi_gcd( bi_copy( bi ), bi_copy( a ) ) ) )
- {
- bi_free( bi );
- bi_free( bim1 );
- bi_free( a );
- return 0;
- }
-
- /* Solovay-Strassen test. First compute pseudo Jacobi. */
- j = bi_mod_power(
- bi_copy( a ), bi_half( bi_copy( bim1 ) ), bi_copy( bi ) );
- if ( bi_compare( bi_copy( j ), bi_copy( bim1 ) ) == 0 )
- {
- bi_free( j );
- j = bi_m1;
- }
-
- /* Now compute real Jacobi. */
- jac = bi_jacobi( bi_copy( a ), bi_copy( bi ) );
-
- /* If they're not equal, the number is definitely composite. */
- if ( bi_compare( j, jac ) != 0 )
- {
- bi_free( bi );
- bi_free( bim1 );
- bi_free( a );
- return 0;
- }
- }
-
- bi_free( a );
- }
-
- bi_free( bim1 );
-
- bi_free( bi );
- return 1;
- }
-
-
-bigint
-bi_generate_prime( int bits, int certainty )
- {
- bigint bimo2, bip;
- int i, inc = 0;
-
- bimo2 = bi_power( bi_2, int_to_bi( bits - 1 ) );
- for (;;)
- {
- bip = bi_add( bi_random( bi_copy( bimo2 ) ), bi_copy( bimo2 ) );
- /* By shoving the candidate numbers up to the next highest multiple
- ** of six plus or minus one, we pre-eliminate all multiples of
- ** two and/or three.
- */
- switch ( bi_int_mod( bi_copy( bip ), 6 ) )
- {
- case 0: inc = 4; bip = bi_int_add( bip, 1 ); break;
- case 1: inc = 4; break;
- case 2: inc = 2; bip = bi_int_add( bip, 3 ); break;
- case 3: inc = 2; bip = bi_int_add( bip, 2 ); break;
- case 4: inc = 2; bip = bi_int_add( bip, 1 ); break;
- case 5: inc = 2; break;
- }
- /* Starting from the generated random number, check a bunch of
- ** numbers in sequence. This is just to avoid calls to bi_random(),
- ** which is more expensive than a simple add.
- */
- for ( i = 0; i < 1000; ++i ) /* arbitrary */
- {
- if ( bi_is_probable_prime( bi_copy( bip ), certainty ) )
- {
- bi_free( bimo2 );
- return bip;
- }
- bip = bi_int_add( bip, inc );
- inc = 6 - inc;
- }
- /* We ran through the whole sequence and didn't find a prime.
- ** Shrug, just try a different random starting point.
- */
- bi_free( bip );
- }
- }
+++ /dev/null
-/* bigint - internal portion of large integer package
-**
-** Copyright © 2000 by Jef Poskanzer <jef@mail.acme.com>.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-** SUCH DAMAGE.
-*/
-
-#include <sys/types.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-
-#include "bigint.h"
-
-#define max(a,b) ((a)>(b)?(a):(b))
-#define min(a,b) ((a)<(b)?(a):(b))
-
-/* MAXINT and MININT extracted from <values.h>, which gives a warning
-** message if included.
-*/
-#define BITSPERBYTE 8
-#define BITS(type) (BITSPERBYTE * (int)sizeof(type))
-#define INTBITS BITS(int)
-#define MININT (1 << (INTBITS - 1))
-#define MAXINT (~MININT)
-
-
-/* The package represents arbitrary-precision integers as a sign and a sum
-** of components multiplied by successive powers of the basic radix, i.e.:
-**
-** sign * ( comp0 + comp1 * radix + comp2 * radix^2 + comp3 * radix^3 )
-**
-** To make good use of the computer's word size, the radix is chosen
-** to be a power of two. It could be chosen to be the full word size,
-** however this would require a lot of finagling in the middle of the
-** algorithms to get the inter-word overflows right. That would slow things
-** down. Instead, the radix is chosen to be *half* the actual word size.
-** With just a little care, this means the words can hold all intermediate
-** values, and the overflows can be handled all at once at the end, in a
-** normalization step. This simplifies the coding enormously, and is probably
-** somewhat faster to run. The cost is that numbers use twice as much
-** storage as they would with the most efficient representation, but storage
-** is cheap.
-**
-** A few more notes on the representation:
-**
-** - The sign is always 1 or -1, never 0. The number 0 is represented
-** with a sign of 1.
-** - The components are signed numbers, to allow for negative intermediate
-** values. After normalization, all components are >= 0 and the sign is
-** updated.
-*/
-
-/* Type definition for bigints. */
-typedef int64_t comp; /* should be the largest signed int type you have */
-struct _real_bigint {
- int refs;
- struct _real_bigint* next;
- int num_comps, max_comps;
- int sign;
- comp* comps;
- };
-typedef struct _real_bigint* real_bigint;
-
-
-#undef DUMP
-
-
-#define PERMANENT 123456789
-
-static comp bi_radix, bi_radix_o2;
-static int bi_radix_sqrt, bi_comp_bits;
-
-static real_bigint active_list, free_list;
-static int active_count, free_count;
-static int check_level;
-
-
-/* Forwards. */
-static bigint regular_multiply( real_bigint bia, real_bigint bib );
-static bigint multi_divide( bigint binumer, real_bigint bidenom );
-static bigint multi_divide2( bigint binumer, real_bigint bidenom );
-static void more_comps( real_bigint bi, int n );
-static real_bigint alloc( int num_comps );
-static real_bigint clone( real_bigint bi );
-static void normalize( real_bigint bi );
-static void check( real_bigint bi );
-static void double_check( void );
-static void triple_check( void );
-#ifdef DUMP
-static void dump( char* str, bigint bi );
-#endif /* DUMP */
-static int csqrt( comp c );
-static int cbits( comp c );
-
-
-void
-bi_initialize( void )
- {
- /* Set the radix. This does not actually have to be a power of
- ** two, that's just the most efficient value. It does have to
- ** be even for bi_half() to work.
- */
- bi_radix = 1;
- bi_radix <<= BITS(comp) / 2 - 1;
-
- /* Halve the radix. Only used by bi_half(). */
- bi_radix_o2 = bi_radix >> 1;
-
- /* Take the square root of the radix. Only used by bi_divide(). */
- bi_radix_sqrt = csqrt( bi_radix );
-
- /* Figure out how many bits in a component. Only used by bi_bits(). */
- bi_comp_bits = cbits( bi_radix - 1 );
-
- /* Init various globals. */
- active_list = (real_bigint) 0;
- active_count = 0;
- free_list = (real_bigint) 0;
- free_count = 0;
-
- /* This can be 0 through 3. */
- check_level = 3;
-
- /* Set up some convenient bigints. */
- bi_0 = int_to_bi( 0 ); bi_permanent( bi_0 );
- bi_1 = int_to_bi( 1 ); bi_permanent( bi_1 );
- bi_2 = int_to_bi( 2 ); bi_permanent( bi_2 );
- bi_10 = int_to_bi( 10 ); bi_permanent( bi_10 );
- bi_m1 = int_to_bi( -1 ); bi_permanent( bi_m1 );
- bi_maxint = int_to_bi( MAXINT ); bi_permanent( bi_maxint );
- bi_minint = int_to_bi( MININT ); bi_permanent( bi_minint );
- }
-
-
-void
-bi_terminate( void )
- {
- real_bigint p, pn;
-
- bi_depermanent( bi_0 ); bi_free( bi_0 );
- bi_depermanent( bi_1 ); bi_free( bi_1 );
- bi_depermanent( bi_2 ); bi_free( bi_2 );
- bi_depermanent( bi_10 ); bi_free( bi_10 );
- bi_depermanent( bi_m1 ); bi_free( bi_m1 );
- bi_depermanent( bi_maxint ); bi_free( bi_maxint );
- bi_depermanent( bi_minint ); bi_free( bi_minint );
-
- if ( active_count != 0 )
- (void) fprintf(
- stderr, "bi_terminate: there were %d un-freed bigints\n",
- active_count );
- if ( check_level >= 2 )
- double_check();
- if ( check_level >= 3 )
- {
- triple_check();
- for ( p = active_list; p != (bigint) 0; p = pn )
- {
- pn = p->next;
- free( p->comps );
- free( p );
- }
- }
- for ( p = free_list; p != (bigint) 0; p = pn )
- {
- pn = p->next;
- free( p->comps );
- free( p );
- }
- }
-
-
-void
-bi_no_check( void )
- {
- check_level = 0;
- }
-
-
-bigint
-bi_copy( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
-
- check( bi );
- if ( bi->refs != PERMANENT )
- ++bi->refs;
- return bi;
- }
-
-
-void
-bi_permanent( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
-
- check( bi );
- if ( check_level >= 1 && bi->refs != 1 )
- {
- (void) fprintf( stderr, "bi_permanent: refs was not 1\n" );
- (void) kill( getpid(), SIGFPE );
- }
- bi->refs = PERMANENT;
- }
-
-
-void
-bi_depermanent( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
-
- check( bi );
- if ( check_level >= 1 && bi->refs != PERMANENT )
- {
- (void) fprintf( stderr, "bi_depermanent: bigint was not permanent\n" );
- (void) kill( getpid(), SIGFPE );
- }
- bi->refs = 1;
- }
-
-
-void
-bi_free( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
-
- check( bi );
- if ( bi->refs == PERMANENT )
- return;
- --bi->refs;
- if ( bi->refs > 0 )
- return;
- if ( check_level >= 3 )
- {
- /* The active list only gets maintained at check levels 3 or higher. */
- real_bigint* nextP;
- for ( nextP = &active_list; *nextP != (real_bigint) 0; nextP = &((*nextP)->next) )
- if ( *nextP == bi )
- {
- *nextP = bi->next;
- break;
- }
- }
- --active_count;
- bi->next = free_list;
- free_list = bi;
- ++free_count;
- if ( check_level >= 1 && active_count < 0 )
- {
- (void) fprintf( stderr,
- "bi_free: active_count went negative - double-freed bigint?\n" );
- (void) kill( getpid(), SIGFPE );
- }
- }
-
-
-int
-bi_compare( bigint obia, bigint obib )
- {
- real_bigint bia = (real_bigint) obia;
- real_bigint bib = (real_bigint) obib;
- int r, c;
-
- check( bia );
- check( bib );
-
- /* First check for pointer equality. */
- if ( bia == bib )
- r = 0;
- else
- {
- /* Compare signs. */
- if ( bia->sign > bib->sign )
- r = 1;
- else if ( bia->sign < bib->sign )
- r = -1;
- /* Signs are the same. Check the number of components. */
- else if ( bia->num_comps > bib->num_comps )
- r = bia->sign;
- else if ( bia->num_comps < bib->num_comps )
- r = -bia->sign;
- else
- {
- /* Same number of components. Compare starting from the high end
- ** and working down.
- */
- r = 0; /* if we complete the loop, the numbers are equal */
- for ( c = bia->num_comps - 1; c >= 0; --c )
- {
- if ( bia->comps[c] > bib->comps[c] )
- { r = bia->sign; break; }
- else if ( bia->comps[c] < bib->comps[c] )
- { r = -bia->sign; break; }
- }
- }
- }
-
- bi_free( bia );
- bi_free( bib );
- return r;
- }
-
-
-bigint
-int_to_bi( int i )
- {
- real_bigint biR;
-
- biR = alloc( 1 );
- biR->sign = 1;
- biR->comps[0] = i;
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-int
-bi_to_int( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- comp v, m;
- int c, r;
-
- check( bi );
- if ( bi_compare( bi_copy( bi ), bi_maxint ) > 0 ||
- bi_compare( bi_copy( bi ), bi_minint ) < 0 )
- {
- (void) fprintf( stderr, "bi_to_int: overflow\n" );
- (void) kill( getpid(), SIGFPE );
- }
- v = 0;
- m = 1;
- for ( c = 0; c < bi->num_comps; ++c )
- {
- v += bi->comps[c] * m;
- m *= bi_radix;
- }
- r = (int) ( bi->sign * v );
- bi_free( bi );
- return r;
- }
-
-
-bigint
-bi_int_add( bigint obi, int i )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
-
- check( bi );
- biR = clone( bi );
- if ( biR->sign == 1 )
- biR->comps[0] += i;
- else
- biR->comps[0] -= i;
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_int_subtract( bigint obi, int i )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
-
- check( bi );
- biR = clone( bi );
- if ( biR->sign == 1 )
- biR->comps[0] -= i;
- else
- biR->comps[0] += i;
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_int_multiply( bigint obi, int i )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
- int c;
-
- check( bi );
- biR = clone( bi );
- if ( i < 0 )
- {
- i = -i;
- biR->sign = -biR->sign;
- }
- for ( c = 0; c < biR->num_comps; ++c )
- biR->comps[c] *= i;
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_int_divide( bigint obinumer, int denom )
- {
- real_bigint binumer = (real_bigint) obinumer;
- real_bigint biR;
- int c;
- comp r;
-
- check( binumer );
- if ( denom == 0 )
- {
- (void) fprintf( stderr, "bi_int_divide: divide by zero\n" );
- (void) kill( getpid(), SIGFPE );
- }
- biR = clone( binumer );
- if ( denom < 0 )
- {
- denom = -denom;
- biR->sign = -biR->sign;
- }
- r = 0;
- for ( c = biR->num_comps - 1; c >= 0; --c )
- {
- r = r * bi_radix + biR->comps[c];
- biR->comps[c] = r / denom;
- r = r % denom;
- }
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-int
-bi_int_rem( bigint obi, int m )
- {
- real_bigint bi = (real_bigint) obi;
- comp rad_r, r;
- int c;
-
- check( bi );
- if ( m == 0 )
- {
- (void) fprintf( stderr, "bi_int_rem: divide by zero\n" );
- (void) kill( getpid(), SIGFPE );
- }
- if ( m < 0 )
- m = -m;
- rad_r = 1;
- r = 0;
- for ( c = 0; c < bi->num_comps; ++c )
- {
- r = ( r + bi->comps[c] * rad_r ) % m;
- rad_r = ( rad_r * bi_radix ) % m;
- }
- if ( bi->sign < 1 )
- r = -r;
- bi_free( bi );
- return (int) r;
- }
-
-
-bigint
-bi_add( bigint obia, bigint obib )
- {
- real_bigint bia = (real_bigint) obia;
- real_bigint bib = (real_bigint) obib;
- real_bigint biR;
- int c;
-
- check( bia );
- check( bib );
- biR = clone( bia );
- more_comps( biR, max( biR->num_comps, bib->num_comps ) );
- for ( c = 0; c < bib->num_comps; ++c )
- if ( biR->sign == bib->sign )
- biR->comps[c] += bib->comps[c];
- else
- biR->comps[c] -= bib->comps[c];
- bi_free( bib );
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_subtract( bigint obia, bigint obib )
- {
- real_bigint bia = (real_bigint) obia;
- real_bigint bib = (real_bigint) obib;
- real_bigint biR;
- int c;
-
- check( bia );
- check( bib );
- biR = clone( bia );
- more_comps( biR, max( biR->num_comps, bib->num_comps ) );
- for ( c = 0; c < bib->num_comps; ++c )
- if ( biR->sign == bib->sign )
- biR->comps[c] -= bib->comps[c];
- else
- biR->comps[c] += bib->comps[c];
- bi_free( bib );
- normalize( biR );
- check( biR );
- return biR;
- }
-
-
-/* Karatsuba multiplication. This is supposedly O(n^1.59), better than
-** regular multiplication for large n. The define below sets the crossover
-** point - below that we use regular multiplication, above it we
-** use Karatsuba. Note that Karatsuba is a recursive algorithm, so
-** all Karatsuba calls involve regular multiplications as the base
-** steps.
-*/
-#define KARATSUBA_THRESH 12
-bigint
-bi_multiply( bigint obia, bigint obib )
- {
- real_bigint bia = (real_bigint) obia;
- real_bigint bib = (real_bigint) obib;
-
- check( bia );
- check( bib );
- if ( min( bia->num_comps, bib->num_comps ) < KARATSUBA_THRESH )
- return regular_multiply( bia, bib );
- else
- {
- /* The factors are large enough that Karatsuba multiplication
- ** is a win. The basic idea here is you break each factor up
- ** into two parts, like so:
- ** i * r^n + j k * r^n + l
- ** r is the radix we're representing numbers with, so this
- ** breaking up just means shuffling components around, no
- ** math required. With regular multiplication the product
- ** would be:
- ** ik * r^(n*2) + ( il + jk ) * r^n + jl
- ** That's four sub-multiplies and one addition, not counting the
- ** radix-shifting. With Karatsuba, you instead do:
- ** ik * r^(n*2) + ( (i+j)(k+l) - ik - jl ) * r^n + jl
- ** This is only three sub-multiplies. The number of adds
- ** (and subtracts) increases to four, but those run in linear time
- ** so they are cheap. The sub-multiplies are accomplished by
- ** recursive calls, eventually reducing to regular multiplication.
- */
- int n, c;
- real_bigint bi_i, bi_j, bi_k, bi_l;
- real_bigint bi_ik, bi_mid, bi_jl;
-
- n = ( max( bia->num_comps, bib->num_comps ) + 1 ) / 2;
- bi_i = alloc( n );
- bi_j = alloc( n );
- bi_k = alloc( n );
- bi_l = alloc( n );
- for ( c = 0; c < n; ++c )
- {
- if ( c + n < bia->num_comps )
- bi_i->comps[c] = bia->comps[c + n];
- else
- bi_i->comps[c] = 0;
- if ( c < bia->num_comps )
- bi_j->comps[c] = bia->comps[c];
- else
- bi_j->comps[c] = 0;
- if ( c + n < bib->num_comps )
- bi_k->comps[c] = bib->comps[c + n];
- else
- bi_k->comps[c] = 0;
- if ( c < bib->num_comps )
- bi_l->comps[c] = bib->comps[c];
- else
- bi_l->comps[c] = 0;
- }
- bi_i->sign = bi_j->sign = bi_k->sign = bi_l->sign = 1;
- normalize( bi_i );
- normalize( bi_j );
- normalize( bi_k );
- normalize( bi_l );
- bi_ik = bi_multiply( bi_copy( bi_i ), bi_copy( bi_k ) );
- bi_jl = bi_multiply( bi_copy( bi_j ), bi_copy( bi_l ) );
- bi_mid = bi_subtract(
- bi_subtract(
- bi_multiply( bi_add( bi_i, bi_j ), bi_add( bi_k, bi_l ) ),
- bi_copy( bi_ik ) ),
- bi_copy( bi_jl ) );
- more_comps(
- bi_jl, max( bi_mid->num_comps + n, bi_ik->num_comps + n * 2 ) );
- for ( c = 0; c < bi_mid->num_comps; ++c )
- bi_jl->comps[c + n] += bi_mid->comps[c];
- for ( c = 0; c < bi_ik->num_comps; ++c )
- bi_jl->comps[c + n * 2] += bi_ik->comps[c];
- bi_free( bi_ik );
- bi_free( bi_mid );
- bi_jl->sign = bia->sign * bib->sign;
- bi_free( bia );
- bi_free( bib );
- normalize( bi_jl );
- check( bi_jl );
- return bi_jl;
- }
- }
-
-
-/* Regular O(n^2) multiplication. */
-static bigint
-regular_multiply( real_bigint bia, real_bigint bib )
- {
- real_bigint biR;
- int new_comps, c1, c2;
-
- check( bia );
- check( bib );
- biR = clone( bi_0 );
- new_comps = bia->num_comps + bib->num_comps;
- more_comps( biR, new_comps );
- for ( c1 = 0; c1 < bia->num_comps; ++c1 )
- {
- for ( c2 = 0; c2 < bib->num_comps; ++c2 )
- biR->comps[c1 + c2] += bia->comps[c1] * bib->comps[c2];
- /* Normalize after each inner loop to avoid overflowing any
- ** components. But be sure to reset biR's components count,
- ** in case a previous normalization lowered it.
- */
- biR->num_comps = new_comps;
- normalize( biR );
- }
- check( biR );
- if ( ! bi_is_zero( bi_copy( biR ) ) )
- biR->sign = bia->sign * bib->sign;
- bi_free( bia );
- bi_free( bib );
- return biR;
- }
-
-
-/* The following three routines implement a multi-precision divide method
-** that I haven't seen used anywhere else. It is not quite as fast as
-** the standard divide method, but it is a lot simpler. In fact it's
-** about as simple as the binary shift-and-subtract method, which goes
-** about five times slower than this.
-**
-** The method assumes you already have multi-precision multiply and subtract
-** routines, and also a multi-by-single precision divide routine. The latter
-** is used to generate approximations, which are then checked and corrected
-** using the former. The result converges to the correct value by about
-** 16 bits per loop.
-*/
-
-/* Public routine to divide two arbitrary numbers. */
-bigint
-bi_divide( bigint binumer, bigint obidenom )
- {
- real_bigint bidenom = (real_bigint) obidenom;
- int sign;
- bigint biquotient;
-
- /* Check signs and trivial cases. */
- sign = 1;
- switch ( bi_compare( bi_copy( bidenom ), bi_0 ) )
- {
- case 0:
- (void) fprintf( stderr, "bi_divide: divide by zero\n" );
- (void) kill( getpid(), SIGFPE );
- case -1:
- sign *= -1;
- bidenom = bi_negate( bidenom );
- break;
- }
- switch ( bi_compare( bi_copy( binumer ), bi_0 ) )
- {
- case 0:
- bi_free( binumer );
- bi_free( bidenom );
- return bi_0;
- case -1:
- sign *= -1;
- binumer = bi_negate( binumer );
- break;
- }
- switch ( bi_compare( bi_copy( binumer ), bi_copy( bidenom ) ) )
- {
- case -1:
- bi_free( binumer );
- bi_free( bidenom );
- return bi_0;
- case 0:
- bi_free( binumer );
- bi_free( bidenom );
- if ( sign == 1 )
- return bi_1;
- else
- return bi_m1;
- }
-
- /* Is the denominator small enough to do an int divide? */
- if ( bidenom->num_comps == 1 )
- {
- /* Win! */
- biquotient = bi_int_divide( binumer, bidenom->comps[0] );
- bi_free( bidenom );
- }
- else
- {
- /* No, we have to do a full multi-by-multi divide. */
- biquotient = multi_divide( binumer, bidenom );
- }
-
- if ( sign == -1 )
- biquotient = bi_negate( biquotient );
- return biquotient;
- }
-
-
-/* Divide two multi-precision positive numbers. */
-static bigint
-multi_divide( bigint binumer, real_bigint bidenom )
- {
- /* We use a successive approximation method that is kind of like a
- ** continued fraction. The basic approximation is to do an int divide
- ** by the high-order component of the denominator. Then we correct
- ** based on the remainder from that.
- **
- ** However, if the high-order component is too small, this doesn't
- ** work well. In particular, if the high-order component is 1 it
- ** doesn't work at all. Easily fixed, though - if the component
- ** is too small, increase it!
- */
- if ( bidenom->comps[bidenom->num_comps-1] < bi_radix_sqrt )
- {
- /* We use the square root of the radix as the threshhold here
- ** because that's the largest value guaranteed to not make the
- ** high-order component overflow and become too small again.
- **
- ** We increase binumer along with bidenom to keep the end result
- ** the same.
- */
- binumer = bi_int_multiply( binumer, bi_radix_sqrt );
- bidenom = bi_int_multiply( bidenom, bi_radix_sqrt );
- }
-
- /* Now start the recursion. */
- return multi_divide2( binumer, bidenom );
- }
-
-
-/* Divide two multi-precision positive conditioned numbers. */
-static bigint
-multi_divide2( bigint binumer, real_bigint bidenom )
- {
- real_bigint biapprox;
- bigint birem, biquotient;
- int c, o;
-
- /* Figure out the approximate quotient. Since we're dividing by only
- ** the top component of the denominator, which is less than or equal to
- ** the full denominator, the result is guaranteed to be greater than or
- ** equal to the correct quotient.
- */
- o = bidenom->num_comps - 1;
- biapprox = bi_int_divide( bi_copy( binumer ), bidenom->comps[o] );
- /* And downshift the result to get the approximate quotient. */
- for ( c = o; c < biapprox->num_comps; ++c )
- biapprox->comps[c - o] = biapprox->comps[c];
- biapprox->num_comps -= o;
-
- /* Find the remainder from the approximate quotient. */
- birem = bi_subtract(
- bi_multiply( bi_copy( biapprox ), bi_copy( bidenom ) ), binumer );
-
- /* If the remainder is negative, zero, or in fact any value less
- ** than bidenom, then we have the correct quotient and we're done.
- */
- if ( bi_compare( bi_copy( birem ), bi_copy( bidenom ) ) < 0 )
- {
- biquotient = biapprox;
- bi_free( birem );
- bi_free( bidenom );
- }
- else
- {
- /* The real quotient is now biapprox - birem / bidenom. We still
- ** have to do a divide. However, birem is smaller than binumer,
- ** so the next divide will go faster. We do the divide by
- ** recursion. Since this is tail-recursion or close to it, we
- ** could probably re-arrange things and make it a non-recursive
- ** loop, but the overhead of recursion is small and the bookkeeping
- ** is simpler this way.
- **
- ** Note that since the sub-divide uses the same denominator, it
- ** doesn't have to adjust the values again - the high-order component
- ** will still be good.
- */
- biquotient = bi_subtract( biapprox, multi_divide2( birem, bidenom ) );
- }
-
- return biquotient;
- }
-
-
-/* Binary division - about five times slower than the above. */
-bigint
-bi_binary_divide( bigint binumer, bigint obidenom )
- {
- real_bigint bidenom = (real_bigint) obidenom;
- int sign;
- bigint biquotient;
-
- /* Check signs and trivial cases. */
- sign = 1;
- switch ( bi_compare( bi_copy( bidenom ), bi_0 ) )
- {
- case 0:
- (void) fprintf( stderr, "bi_divide: divide by zero\n" );
- (void) kill( getpid(), SIGFPE );
- case -1:
- sign *= -1;
- bidenom = bi_negate( bidenom );
- break;
- }
- switch ( bi_compare( bi_copy( binumer ), bi_0 ) )
- {
- case 0:
- bi_free( binumer );
- bi_free( bidenom );
- return bi_0;
- case -1:
- sign *= -1;
- binumer = bi_negate( binumer );
- break;
- }
- switch ( bi_compare( bi_copy( binumer ), bi_copy( bidenom ) ) )
- {
- case -1:
- bi_free( binumer );
- bi_free( bidenom );
- return bi_0;
- case 0:
- bi_free( binumer );
- bi_free( bidenom );
- if ( sign == 1 )
- return bi_1;
- else
- return bi_m1;
- }
-
- /* Is the denominator small enough to do an int divide? */
- if ( bidenom->num_comps == 1 )
- {
- /* Win! */
- biquotient = bi_int_divide( binumer, bidenom->comps[0] );
- bi_free( bidenom );
- }
- else
- {
- /* No, we have to do a full multi-by-multi divide. */
- int num_bits, den_bits, i;
-
- num_bits = bi_bits( bi_copy( binumer ) );
- den_bits = bi_bits( bi_copy( bidenom ) );
- bidenom = bi_multiply( bidenom, bi_power( bi_2, int_to_bi( num_bits - den_bits ) ) );
- biquotient = bi_0;
- for ( i = den_bits; i <= num_bits; ++i )
- {
- biquotient = bi_double( biquotient );
- if ( bi_compare( bi_copy( binumer ), bi_copy( bidenom ) ) >= 0 )
- {
- biquotient = bi_int_add( biquotient, 1 );
- binumer = bi_subtract( binumer, bi_copy( bidenom ) );
- }
- bidenom = bi_half( bidenom );
- }
- bi_free( binumer );
- bi_free( bidenom );
- }
-
- if ( sign == -1 )
- biquotient = bi_negate( biquotient );
- return biquotient;
- }
-
-
-bigint
-bi_negate( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
-
- check( bi );
- biR = clone( bi );
- biR->sign = -biR->sign;
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_abs( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
-
- check( bi );
- biR = clone( bi );
- biR->sign = 1;
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_half( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
- int c;
-
- check( bi );
- /* This depends on the radix being even. */
- biR = clone( bi );
- for ( c = 0; c < biR->num_comps; ++c )
- {
- if ( biR->comps[c] & 1 )
- if ( c > 0 )
- biR->comps[c - 1] += bi_radix_o2;
- biR->comps[c] = biR->comps[c] >> 1;
- }
- /* Avoid normalization. */
- if ( biR->num_comps > 1 && biR->comps[biR->num_comps-1] == 0 )
- --biR->num_comps;
- check( biR );
- return biR;
- }
-
-
-bigint
-bi_double( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- real_bigint biR;
- int c;
-
- check( bi );
- biR = clone( bi );
- for ( c = biR->num_comps - 1; c >= 0; --c )
- {
- biR->comps[c] = biR->comps[c] << 1;
- if ( biR->comps[c] >= bi_radix )
- {
- if ( c + 1 >= biR->num_comps )
- more_comps( biR, biR->num_comps + 1 );
- biR->comps[c] -= bi_radix;
- biR->comps[c + 1] += 1;
- }
- }
- check( biR );
- return biR;
- }
-
-
-/* Find integer square root by Newton's method. */
-bigint
-bi_sqrt( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- bigint biR, biR2, bidiff;
-
- switch ( bi_compare( bi_copy( bi ), bi_0 ) )
- {
- case -1:
- (void) fprintf( stderr, "bi_sqrt: imaginary result\n" );
- (void) kill( getpid(), SIGFPE );
- case 0:
- return bi;
- }
- if ( bi_is_one( bi_copy( bi ) ) )
- return bi;
-
- /* Newton's method converges reasonably fast, but it helps to have
- ** a good initial guess. We can make a *very* good initial guess
- ** by taking the square root of the top component times the square
- ** root of the radix part. Both of those are easy to compute.
- */
- biR = bi_int_multiply(
- bi_power( int_to_bi( bi_radix_sqrt ), int_to_bi( bi->num_comps - 1 ) ),
- csqrt( bi->comps[bi->num_comps - 1] ) );
-
- /* Now do the Newton loop until we have the answer. */
- for (;;)
- {
- biR2 = bi_divide( bi_copy( bi ), bi_copy( biR ) );
- bidiff = bi_subtract( bi_copy( biR ), bi_copy( biR2 ) );
- if ( bi_is_zero( bi_copy( bidiff ) ) ||
- bi_compare( bi_copy( bidiff ), bi_m1 ) == 0 )
- {
- bi_free( bi );
- bi_free( bidiff );
- bi_free( biR2 );
- return biR;
- }
- if ( bi_is_one( bi_copy( bidiff ) ) )
- {
- bi_free( bi );
- bi_free( bidiff );
- bi_free( biR );
- return biR2;
- }
- bi_free( bidiff );
- biR = bi_half( bi_add( biR, biR2 ) );
- }
- }
-
-
-int
-bi_is_odd( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- int r;
-
- check( bi );
- r = bi->comps[0] & 1;
- bi_free( bi );
- return r;
- }
-
-
-int
-bi_is_zero( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- int r;
-
- check( bi );
- r = ( bi->sign == 1 && bi->num_comps == 1 && bi->comps[0] == 0 );
- bi_free( bi );
- return r;
- }
-
-
-int
-bi_is_one( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- int r;
-
- check( bi );
- r = ( bi->sign == 1 && bi->num_comps == 1 && bi->comps[0] == 1 );
- bi_free( bi );
- return r;
- }
-
-
-int
-bi_is_negative( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- int r;
-
- check( bi );
- r = ( bi->sign == -1 );
- bi_free( bi );
- return r;
- }
-
-
-bigint
-bi_random( bigint bi )
- {
- real_bigint biR;
- int c;
-
- biR = bi_multiply( bi_copy( bi ), bi_copy( bi ) );
- for ( c = 0; c < biR->num_comps; ++c )
- biR->comps[c] = random();
- normalize( biR );
- biR = bi_mod( biR, bi );
- return biR;
- }
-
-
-int
-bi_bits( bigint obi )
- {
- real_bigint bi = (real_bigint) obi;
- int bits;
-
- bits =
- bi_comp_bits * ( bi->num_comps - 1 ) +
- cbits( bi->comps[bi->num_comps - 1] );
- bi_free( bi );
- return bits;
- }
-
-
-/* Allocate and zero more components. Does not consume bi, of course. */
-static void
-more_comps( real_bigint bi, int n )
- {
- if ( n > bi->max_comps )
- {
- bi->max_comps = max( bi->max_comps * 2, n );
- bi->comps = (comp*) realloc(
- (void*) bi->comps, bi->max_comps * sizeof(comp) );
- if ( bi->comps == (comp*) 0 )
- {
- (void) fprintf( stderr, "out of memory\n" );
- exit( 1 );
- }
- }
- for ( ; bi->num_comps < n; ++bi->num_comps )
- bi->comps[bi->num_comps] = 0;
- }
-
-
-/* Make a new empty bigint. Fills in everything except sign and the
-** components.
-*/
-static real_bigint
-alloc( int num_comps )
- {
- real_bigint biR;
-
- /* Can we recycle an old bigint? */
- if ( free_list != (real_bigint) 0 )
- {
- biR = free_list;
- free_list = biR->next;
- --free_count;
- if ( check_level >= 1 && biR->refs != 0 )
- {
- (void) fprintf( stderr, "alloc: refs was not 0\n" );
- (void) kill( getpid(), SIGFPE );
- }
- more_comps( biR, num_comps );
- }
- else
- {
- /* No free bigints available - create a new one. */
- biR = (real_bigint) malloc( sizeof(struct _real_bigint) );
- if ( biR == (real_bigint) 0 )
- {
- (void) fprintf( stderr, "out of memory\n" );
- exit( 1 );
- }
- biR->comps = (comp*) malloc( num_comps * sizeof(comp) );
- if ( biR->comps == (comp*) 0 )
- {
- (void) fprintf( stderr, "out of memory\n" );
- exit( 1 );
- }
- biR->max_comps = num_comps;
- }
- biR->num_comps = num_comps;
- biR->refs = 1;
- if ( check_level >= 3 )
- {
- /* The active list only gets maintained at check levels 3 or higher. */
- biR->next = active_list;
- active_list = biR;
- }
- else
- biR->next = (real_bigint) 0;
- ++active_count;
- return biR;
- }
-
-
-/* Make a modifiable copy of bi. DOES consume bi. */
-static real_bigint
-clone( real_bigint bi )
- {
- real_bigint biR;
- int c;
-
- /* Very clever optimization. */
- if ( bi->refs != PERMANENT && bi->refs == 1 )
- return bi;
-
- biR = alloc( bi->num_comps );
- biR->sign = bi->sign;
- for ( c = 0; c < bi->num_comps; ++c )
- biR->comps[c] = bi->comps[c];
- bi_free( bi );
- return biR;
- }
-
-
-/* Put bi into normal form. Does not consume bi, of course.
-**
-** Normal form is:
-** - All components >= 0 and < bi_radix.
-** - Leading 0 components removed.
-** - Sign either 1 or -1.
-** - The number zero represented by a single 0 component and a sign of 1.
-*/
-static void
-normalize( real_bigint bi )
- {
- int c;
-
- /* Borrow for negative components. Got to be careful with the math here:
- ** -9 / 10 == 0 -9 % 10 == -9
- ** -10 / 10 == -1 -10 % 10 == 0
- ** -11 / 10 == -1 -11 % 10 == -1
- */
- for ( c = 0; c < bi->num_comps - 1; ++c )
- if ( bi->comps[c] < 0 )
- {
- bi->comps[c+1] += bi->comps[c] / bi_radix - 1;
- bi->comps[c] = bi->comps[c] % bi_radix;
- if ( bi->comps[c] != 0 )
- bi->comps[c] += bi_radix;
- else
- bi->comps[c+1] += 1;
- }
- /* Is the top component negative? */
- if ( bi->comps[bi->num_comps - 1] < 0 )
- {
- /* Switch the sign of the number, and fix up the components. */
- bi->sign = -bi->sign;
- for ( c = 0; c < bi->num_comps - 1; ++c )
- {
- bi->comps[c] = bi_radix - bi->comps[c];
- bi->comps[c + 1] += 1;
- }
- bi->comps[bi->num_comps - 1] = -bi->comps[bi->num_comps - 1];
- }
-
- /* Carry for components larger than the radix. */
- for ( c = 0; c < bi->num_comps; ++c )
- if ( bi->comps[c] >= bi_radix )
- {
- if ( c + 1 >= bi->num_comps )
- more_comps( bi, bi->num_comps + 1 );
- bi->comps[c+1] += bi->comps[c] / bi_radix;
- bi->comps[c] = bi->comps[c] % bi_radix;
- }
-
- /* Trim off any leading zero components. */
- for ( ; bi->num_comps > 1 && bi->comps[bi->num_comps-1] == 0; --bi->num_comps )
- ;
-
- /* Check for -0. */
- if ( bi->num_comps == 1 && bi->comps[0] == 0 && bi->sign == -1 )
- bi->sign = 1;
- }
-
-
-static void
-check( real_bigint bi )
- {
- if ( check_level == 0 )
- return;
- if ( bi->refs == 0 )
- {
- (void) fprintf( stderr, "check: zero refs in bigint\n" );
- (void) kill( getpid(), SIGFPE );
- }
- if ( bi->refs < 0 )
- {
- (void) fprintf( stderr, "check: negative refs in bigint\n" );
- (void) kill( getpid(), SIGFPE );
- }
- if ( check_level < 3 )
- {
- /* At check levels less than 3, active bigints have a zero next. */
- if ( bi->next != (real_bigint) 0 )
- {
- (void) fprintf(
- stderr, "check: attempt to use a bigint from the free list\n" );
- (void) kill( getpid(), SIGFPE );
- }
- }
- else
- {
- /* At check levels 3 or higher, active bigints must be on the active
- ** list.
- */
- real_bigint p;
-
- for ( p = active_list; p != (real_bigint) 0; p = p->next )
- if ( p == bi )
- break;
- if ( p == (real_bigint) 0 )
- {
- (void) fprintf( stderr,
- "check: attempt to use a bigint not on the active list\n" );
- (void) kill( getpid(), SIGFPE );
- }
- }
- if ( check_level >= 2 )
- double_check();
- if ( check_level >= 3 )
- triple_check();
- }
-
-
-static void
-double_check( void )
- {
- real_bigint p;
- int c;
-
- for ( p = free_list, c = 0; p != (real_bigint) 0; p = p->next, ++c )
- if ( p->refs != 0 )
- {
- (void) fprintf( stderr,
- "double_check: found a non-zero ref on the free list\n" );
- (void) kill( getpid(), SIGFPE );
- }
- if ( c != free_count )
- {
- (void) fprintf( stderr,
- "double_check: free_count is %d but the free list has %d items\n",
- free_count, c );
- (void) kill( getpid(), SIGFPE );
- }
- }
-
-
-static void
-triple_check( void )
- {
- real_bigint p;
- int c;
-
- for ( p = active_list, c = 0; p != (real_bigint) 0; p = p->next, ++c )
- if ( p->refs == 0 )
- {
- (void) fprintf( stderr,
- "triple_check: found a zero ref on the active list\n" );
- (void) kill( getpid(), SIGFPE );
- }
- if ( c != active_count )
- {
- (void) fprintf( stderr,
- "triple_check: active_count is %d but active_list has %d items\n",
- free_count, c );
- (void) kill( getpid(), SIGFPE );
- }
- }
-
-
-#ifdef DUMP
-/* Debug routine to dump out a complete bigint. Does not consume bi. */
-static void
-dump( char* str, bigint obi )
- {
- int c;
- real_bigint bi = (real_bigint) obi;
-
- (void) fprintf( stdout, "dump %s at 0x%08x:\n", str, (unsigned int) bi );
- (void) fprintf( stdout, " refs: %d\n", bi->refs );
- (void) fprintf( stdout, " next: 0x%08x\n", (unsigned int) bi->next );
- (void) fprintf( stdout, " num_comps: %d\n", bi->num_comps );
- (void) fprintf( stdout, " max_comps: %d\n", bi->max_comps );
- (void) fprintf( stdout, " sign: %d\n", bi->sign );
- for ( c = bi->num_comps - 1; c >= 0; --c )
- (void) fprintf( stdout, " comps[%d]: %11lld (0x%016llx)\n", c, (long long) bi->comps[c], (long long) bi->comps[c] );
- (void) fprintf( stdout, " print: " );
- bi_print( stdout, bi_copy( bi ) );
- (void) fprintf( stdout, "\n" );
- }
-#endif /* DUMP */
-
-
-/* Trivial square-root routine so that we don't have to link in the math lib. */
-static int
-csqrt( comp c )
- {
- comp r, r2, diff;
-
- if ( c < 0 )
- {
- (void) fprintf( stderr, "csqrt: imaginary result\n" );
- (void) kill( getpid(), SIGFPE );
- }
-
- r = c / 2;
- for (;;)
- {
- r2 = c / r;
- diff = r - r2;
- if ( diff == 0 || diff == -1 )
- return (int) r;
- if ( diff == 1 )
- return (int) r2;
- r = ( r + r2 ) / 2;
- }
- }
-
-
-/* Figure out how many bits are in a number. */
-static int
-cbits( comp c )
- {
- int b;
-
- for ( b = 0; c != 0; ++b )
- c >>= 1;
- return b;
- }
+++ /dev/null
-/* Primes up to 100000. */
-static long low_primes[] = {
- 2, 3, 5, 7, 11, 13, 17, 19, 23,
- 29, 31, 37, 41, 43, 47, 53, 59, 61,
- 67, 71, 73, 79, 83, 89, 97, 101, 103,
- 107, 109, 113, 127, 131, 137, 139, 149, 151,
- 157, 163, 167, 173, 179, 181, 191, 193, 197,
- 199, 211, 223, 227, 229, 233, 239, 241, 251,
- 257, 263, 269, 271, 277, 281, 283, 293, 307,
- 311, 313, 317, 331, 337, 347, 349, 353, 359,
- 367, 373, 379, 383, 389, 397, 401, 409, 419,
- 421, 431, 433, 439, 443, 449, 457, 461, 463,
- 467, 479, 487, 491, 499, 503, 509, 521, 523,
- 541, 547, 557, 563, 569, 571, 577, 587, 593,
- 599, 601, 607, 613, 617, 619, 631, 641, 643,
- 647, 653, 659, 661, 673, 677, 683, 691, 701,
- 709, 719, 727, 733, 739, 743, 751, 757, 761,
- 769, 773, 787, 797, 809, 811, 821, 823, 827,
- 829, 839, 853, 857, 859, 863, 877, 881, 883,
- 887, 907, 911, 919, 929, 937, 941, 947, 953,
- 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
- 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
- 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129,
- 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
- 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
- 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
- 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427,
- 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481,
- 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543,
- 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601,
- 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663,
- 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
- 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801,
- 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
- 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951,
- 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017,
- 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087,
- 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143,
- 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239,
- 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
- 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371,
- 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
- 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521,
- 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593,
- 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671,
- 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713,
- 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789,
- 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851,
- 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927,
- 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
- 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083,
- 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
- 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253,
- 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323,
- 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389,
- 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467,
- 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
- 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
- 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673,
- 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739,
- 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823,
- 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
- 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967,
- 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049,
- 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127,
- 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
- 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261,
- 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349,
- 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441,
- 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513,
- 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591,
- 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
- 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733,
- 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
- 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919,
- 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973,
- 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039,
- 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113,
- 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209,
- 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297,
- 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393,
- 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
- 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519,
- 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591,
- 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
- 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743,
- 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827,
- 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879,
- 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987,
- 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
- 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143,
- 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
- 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299,
- 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359,
- 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449,
- 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551,
- 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619,
- 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
- 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781,
- 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857,
- 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947,
- 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
- 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079,
- 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187,
- 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247,
- 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
- 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459,
- 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529,
- 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583,
- 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669,
- 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727,
- 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
- 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907,
- 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
- 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089,
- 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171,
- 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243,
- 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317,
- 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423,
- 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521,
- 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599,
- 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
- 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737,
- 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819,
- 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887,
- 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971,
- 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049,
- 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151,
- 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221,
- 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311,
- 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391,
- 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439,
- 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521,
- 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623,
- 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697,
- 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781,
- 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851,
- 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929,
- 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039,
- 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111,
- 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181,
- 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271,
- 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337,
- 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453,
- 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529,
- 10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627,
- 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, 10709,
- 10711, 10723, 10729, 10733, 10739, 10753, 10771, 10781, 10789,
- 10799, 10831, 10837, 10847, 10853, 10859, 10861, 10867, 10883,
- 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973,
- 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069,
- 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149,
- 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243,
- 11251, 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317,
- 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, 11411,
- 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491,
- 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593,
- 11597, 11617, 11621, 11633, 11657, 11677, 11681, 11689, 11699,
- 11701, 11717, 11719, 11731, 11743, 11777, 11779, 11783, 11789,
- 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, 11863,
- 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939,
- 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
- 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107,
- 12109, 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197,
- 12203, 12211, 12227, 12239, 12241, 12251, 12253, 12263, 12269,
- 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347, 12373,
- 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437,
- 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511,
- 12517, 12527, 12539, 12541, 12547, 12553, 12569, 12577, 12583,
- 12589, 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653,
- 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 12743,
- 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829,
- 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919,
- 12923, 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001,
- 13003, 13007, 13009, 13033, 13037, 13043, 13049, 13063, 13093,
- 13099, 13103, 13109, 13121, 13127, 13147, 13151, 13159, 13163,
- 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241, 13249,
- 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337,
- 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441,
- 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, 13523,
- 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627,
- 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697,
- 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763,
- 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873,
- 13877, 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931,
- 13933, 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033,
- 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, 14149,
- 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243, 14249,
- 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347,
- 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431,
- 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 14533,
- 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593,
- 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683,
- 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753,
- 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827,
- 14831, 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897,
- 14923, 14929, 14939, 14947, 14951, 14957, 14969, 14983, 15013,
- 15017, 15031, 15053, 15061, 15073, 15077, 15083, 15091, 15101,
- 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173, 15187,
- 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269,
- 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329,
- 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
- 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493,
- 15497, 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583,
- 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661,
- 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739,
- 15749, 15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809,
- 15817, 15823, 15859, 15877, 15881, 15887, 15889, 15901, 15907,
- 15913, 15919, 15923, 15937, 15959, 15971, 15973, 15991, 16001,
- 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087,
- 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187,
- 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267,
- 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369,
- 16381, 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453,
- 16477, 16481, 16487, 16493, 16519, 16529, 16547, 16553, 16561,
- 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651,
- 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741,
- 16747, 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843,
- 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, 16931,
- 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, 17021,
- 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099,
- 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191,
- 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299,
- 17317, 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383,
- 17387, 17389, 17393, 17401, 17417, 17419, 17431, 17443, 17449,
- 17467, 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519,
- 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609,
- 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713,
- 17729, 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807,
- 17827, 17837, 17839, 17851, 17863, 17881, 17891, 17903, 17909,
- 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 17977,
- 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059,
- 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133,
- 18143, 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223,
- 18229, 18233, 18251, 18253, 18257, 18269, 18287, 18289, 18301,
- 18307, 18311, 18313, 18329, 18341, 18353, 18367, 18371, 18379,
- 18397, 18401, 18413, 18427, 18433, 18439, 18443, 18451, 18457,
- 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541,
- 18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679,
- 18691, 18701, 18713, 18719, 18731, 18743, 18749, 18757, 18773,
- 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 18911,
- 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009,
- 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087,
- 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211,
- 19213, 19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289,
- 19301, 19309, 19319, 19333, 19373, 19379, 19381, 19387, 19391,
- 19403, 19417, 19421, 19423, 19427, 19429, 19433, 19441, 19447,
- 19457, 19463, 19469, 19471, 19477, 19483, 19489, 19501, 19507,
- 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597,
- 19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717,
- 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801,
- 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891,
- 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979,
- 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051,
- 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129,
- 20143, 20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219,
- 20231, 20233, 20249, 20261, 20269, 20287, 20297, 20323, 20327,
- 20333, 20341, 20347, 20353, 20357, 20359, 20369, 20389, 20393,
- 20399, 20407, 20411, 20431, 20441, 20443, 20477, 20479, 20483,
- 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593,
- 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707,
- 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771,
- 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887,
- 20897, 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963,
- 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023, 21031,
- 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143,
- 21149, 21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211,
- 21221, 21227, 21247, 21269, 21277, 21283, 21313, 21317, 21319,
- 21323, 21341, 21347, 21377, 21379, 21383, 21391, 21397, 21401,
- 21407, 21419, 21433, 21467, 21481, 21487, 21491, 21493, 21499,
- 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569,
- 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647,
- 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739,
- 21751, 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821,
- 21839, 21841, 21851, 21859, 21863, 21871, 21881, 21893, 21911,
- 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003, 22013,
- 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079,
- 22091, 22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153,
- 22157, 22159, 22171, 22189, 22193, 22229, 22247, 22259, 22271,
- 22273, 22277, 22279, 22283, 22291, 22303, 22307, 22343, 22349,
- 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 22447,
- 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543,
- 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639,
- 22643, 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717,
- 22721, 22727, 22739, 22741, 22751, 22769, 22777, 22783, 22787,
- 22807, 22811, 22817, 22853, 22859, 22861, 22871, 22877, 22901,
- 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993, 23003,
- 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057,
- 23059, 23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143,
- 23159, 23167, 23173, 23189, 23197, 23201, 23203, 23209, 23227,
- 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 23327,
- 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447,
- 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557,
- 23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623,
- 23627, 23629, 23633, 23663, 23669, 23671, 23677, 23687, 23689,
- 23719, 23741, 23743, 23747, 23753, 23761, 23767, 23773, 23789,
- 23801, 23813, 23819, 23827, 23831, 23833, 23857, 23869, 23873,
- 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929, 23957,
- 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029,
- 24043, 24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103,
- 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179,
- 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281,
- 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407,
- 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499,
- 24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611,
- 24623, 24631, 24659, 24671, 24677, 24683, 24691, 24697, 24709,
- 24733, 24749, 24763, 24767, 24781, 24793, 24799, 24809, 24821,
- 24841, 24847, 24851, 24859, 24877, 24889, 24907, 24917, 24919,
- 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989, 25013,
- 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117,
- 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189,
- 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303,
- 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373,
- 25391, 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463,
- 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583,
- 25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657,
- 25667, 25673, 25679, 25693, 25703, 25717, 25733, 25741, 25747,
- 25759, 25763, 25771, 25793, 25799, 25801, 25819, 25841, 25847,
- 25849, 25867, 25873, 25889, 25903, 25913, 25919, 25931, 25933,
- 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003, 26017,
- 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113,
- 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203,
- 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293,
- 26297, 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387,
- 26393, 26399, 26407, 26417, 26423, 26431, 26437, 26449, 26459,
- 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573,
- 26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683,
- 26687, 26693, 26699, 26701, 26711, 26713, 26717, 26723, 26729,
- 26731, 26737, 26759, 26777, 26783, 26801, 26813, 26821, 26833,
- 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, 26903,
- 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993,
- 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077,
- 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197,
- 27211, 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283,
- 27299, 27329, 27337, 27361, 27367, 27397, 27407, 27409, 27427,
- 27431, 27437, 27449, 27457, 27479, 27481, 27487, 27509, 27527,
- 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631,
- 27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737,
- 27739, 27743, 27749, 27751, 27763, 27767, 27773, 27779, 27791,
- 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, 27851,
- 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953,
- 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051,
- 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123,
- 28151, 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277,
- 28279, 28283, 28289, 28297, 28307, 28309, 28319, 28349, 28351,
- 28387, 28393, 28403, 28409, 28411, 28429, 28433, 28439, 28447,
- 28463, 28477, 28493, 28499, 28513, 28517, 28537, 28541, 28547,
- 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607,
- 28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663,
- 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, 28753,
- 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843,
- 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933,
- 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033,
- 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147,
- 29153, 29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221,
- 29231, 29243, 29251, 29269, 29287, 29297, 29303, 29311, 29327,
- 29333, 29339, 29347, 29363, 29383, 29387, 29389, 29399, 29401,
- 29411, 29423, 29429, 29437, 29443, 29453, 29473, 29483, 29501,
- 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599,
- 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717,
- 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 29833,
- 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921,
- 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047,
- 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119,
- 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203,
- 30211, 30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307,
- 30313, 30319, 30323, 30341, 30347, 30367, 30389, 30391, 30403,
- 30427, 30431, 30449, 30467, 30469, 30491, 30493, 30497, 30509,
- 30517, 30529, 30539, 30553, 30557, 30559, 30577, 30593, 30631,
- 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703,
- 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809,
- 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871,
- 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977,
- 30983, 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079,
- 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153, 31159,
- 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237,
- 31247, 31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319,
- 31321, 31327, 31333, 31337, 31357, 31379, 31387, 31391, 31393,
- 31397, 31469, 31477, 31481, 31489, 31511, 31513, 31517, 31531,
- 31541, 31543, 31547, 31567, 31573, 31583, 31601, 31607, 31627,
- 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723,
- 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817,
- 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963,
- 31973, 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057,
- 32059, 32063, 32069, 32077, 32083, 32089, 32099, 32117, 32119,
- 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203, 32213,
- 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309,
- 32321, 32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371,
- 32377, 32381, 32401, 32411, 32413, 32423, 32429, 32441, 32443,
- 32467, 32479, 32491, 32497, 32503, 32507, 32531, 32533, 32537,
- 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 32611,
- 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717,
- 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803,
- 32831, 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917,
- 32933, 32939, 32941, 32957, 32969, 32971, 32983, 32987, 32993,
- 32999, 33013, 33023, 33029, 33037, 33049, 33053, 33071, 33073,
- 33083, 33091, 33107, 33113, 33119, 33149, 33151, 33161, 33179,
- 33181, 33191, 33199, 33203, 33211, 33223, 33247, 33287, 33289,
- 33301, 33311, 33317, 33329, 33331, 33343, 33347, 33349, 33353,
- 33359, 33377, 33391, 33403, 33409, 33413, 33427, 33457, 33461,
- 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, 33547,
- 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613,
- 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703,
- 33713, 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773,
- 33791, 33797, 33809, 33811, 33827, 33829, 33851, 33857, 33863,
- 33871, 33889, 33893, 33911, 33923, 33931, 33937, 33941, 33961,
- 33967, 33997, 34019, 34031, 34033, 34039, 34057, 34061, 34123,
- 34127, 34129, 34141, 34147, 34157, 34159, 34171, 34183, 34211,
- 34213, 34217, 34231, 34253, 34259, 34261, 34267, 34273, 34283,
- 34297, 34301, 34303, 34313, 34319, 34327, 34337, 34351, 34361,
- 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, 34469,
- 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537,
- 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631,
- 34649, 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721,
- 34729, 34739, 34747, 34757, 34759, 34763, 34781, 34807, 34819,
- 34841, 34843, 34847, 34849, 34871, 34877, 34883, 34897, 34913,
- 34919, 34939, 34949, 34961, 34963, 34981, 35023, 35027, 35051,
- 35053, 35059, 35069, 35081, 35083, 35089, 35099, 35107, 35111,
- 35117, 35129, 35141, 35149, 35153, 35159, 35171, 35201, 35221,
- 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, 35317,
- 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407,
- 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509,
- 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591,
- 35593, 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747,
- 35753, 35759, 35771, 35797, 35801, 35803, 35809, 35831, 35837,
- 35839, 35851, 35863, 35869, 35879, 35897, 35899, 35911, 35923,
- 35933, 35951, 35963, 35969, 35977, 35983, 35993, 35999, 36007,
- 36011, 36013, 36017, 36037, 36061, 36067, 36073, 36083, 36097,
- 36107, 36109, 36131, 36137, 36151, 36161, 36187, 36191, 36209,
- 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293, 36299,
- 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389,
- 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497,
- 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583,
- 36587, 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677,
- 36683, 36691, 36697, 36709, 36713, 36721, 36739, 36749, 36761,
- 36767, 36779, 36781, 36787, 36791, 36793, 36809, 36821, 36833,
- 36847, 36857, 36871, 36877, 36887, 36899, 36901, 36913, 36919,
- 36923, 36929, 36931, 36943, 36947, 36973, 36979, 36997, 37003,
- 37013, 37019, 37021, 37039, 37049, 37057, 37061, 37087, 37097,
- 37117, 37123, 37139, 37159, 37171, 37181, 37189, 37199, 37201,
- 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, 37313,
- 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397,
- 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501,
- 37507, 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567,
- 37571, 37573, 37579, 37589, 37591, 37607, 37619, 37633, 37643,
- 37649, 37657, 37663, 37691, 37693, 37699, 37717, 37747, 37781,
- 37783, 37799, 37811, 37813, 37831, 37847, 37853, 37861, 37871,
- 37879, 37889, 37897, 37907, 37951, 37957, 37963, 37967, 37987,
- 37991, 37993, 37997, 38011, 38039, 38047, 38053, 38069, 38083,
- 38113, 38119, 38149, 38153, 38167, 38177, 38183, 38189, 38197,
- 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, 38287,
- 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371,
- 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501,
- 38543, 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611,
- 38629, 38639, 38651, 38653, 38669, 38671, 38677, 38693, 38699,
- 38707, 38711, 38713, 38723, 38729, 38737, 38747, 38749, 38767,
- 38783, 38791, 38803, 38821, 38833, 38839, 38851, 38861, 38867,
- 38873, 38891, 38903, 38917, 38921, 38923, 38933, 38953, 38959,
- 38971, 38977, 38993, 39019, 39023, 39041, 39043, 39047, 39079,
- 39089, 39097, 39103, 39107, 39113, 39119, 39133, 39139, 39157,
- 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, 39229,
- 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323,
- 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409,
- 39419, 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511,
- 39521, 39541, 39551, 39563, 39569, 39581, 39607, 39619, 39623,
- 39631, 39659, 39667, 39671, 39679, 39703, 39709, 39719, 39727,
- 39733, 39749, 39761, 39769, 39779, 39791, 39799, 39821, 39827,
- 39829, 39839, 39841, 39847, 39857, 39863, 39869, 39877, 39883,
- 39887, 39901, 39929, 39937, 39953, 39971, 39979, 39983, 39989,
- 40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, 40099,
- 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, 40177,
- 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283,
- 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429,
- 40433, 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519,
- 40529, 40531, 40543, 40559, 40577, 40583, 40591, 40597, 40609,
- 40627, 40637, 40639, 40693, 40697, 40699, 40709, 40739, 40751,
- 40759, 40763, 40771, 40787, 40801, 40813, 40819, 40823, 40829,
- 40841, 40847, 40849, 40853, 40867, 40879, 40883, 40897, 40903,
- 40927, 40933, 40939, 40949, 40961, 40973, 40993, 41011, 41017,
- 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, 41117,
- 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189,
- 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257,
- 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381,
- 41387, 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479,
- 41491, 41507, 41513, 41519, 41521, 41539, 41543, 41549, 41579,
- 41593, 41597, 41603, 41609, 41611, 41617, 41621, 41627, 41641,
- 41647, 41651, 41659, 41669, 41681, 41687, 41719, 41729, 41737,
- 41759, 41761, 41771, 41777, 41801, 41809, 41813, 41843, 41849,
- 41851, 41863, 41879, 41887, 41893, 41897, 41903, 41911, 41927,
- 41941, 41947, 41953, 41957, 41959, 41969, 41981, 41983, 41999,
- 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083,
- 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187,
- 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281,
- 42283, 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359,
- 42373, 42379, 42391, 42397, 42403, 42407, 42409, 42433, 42437,
- 42443, 42451, 42457, 42461, 42463, 42467, 42473, 42487, 42491,
- 42499, 42509, 42533, 42557, 42569, 42571, 42577, 42589, 42611,
- 42641, 42643, 42649, 42667, 42677, 42683, 42689, 42697, 42701,
- 42703, 42709, 42719, 42727, 42737, 42743, 42751, 42767, 42773,
- 42787, 42793, 42797, 42821, 42829, 42839, 42841, 42853, 42859,
- 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, 42961,
- 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051,
- 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177,
- 43189, 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291,
- 43313, 43319, 43321, 43331, 43391, 43397, 43399, 43403, 43411,
- 43427, 43441, 43451, 43457, 43481, 43487, 43499, 43517, 43541,
- 43543, 43573, 43577, 43579, 43591, 43597, 43607, 43609, 43613,
- 43627, 43633, 43649, 43651, 43661, 43669, 43691, 43711, 43717,
- 43721, 43753, 43759, 43777, 43781, 43783, 43787, 43789, 43793,
- 43801, 43853, 43867, 43889, 43891, 43913, 43933, 43943, 43951,
- 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, 44021,
- 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101,
- 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189,
- 44201, 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269,
- 44273, 44279, 44281, 44293, 44351, 44357, 44371, 44381, 44383,
- 44389, 44417, 44449, 44453, 44483, 44491, 44497, 44501, 44507,
- 44519, 44531, 44533, 44537, 44543, 44549, 44563, 44579, 44587,
- 44617, 44621, 44623, 44633, 44641, 44647, 44651, 44657, 44683,
- 44687, 44699, 44701, 44711, 44729, 44741, 44753, 44771, 44773,
- 44777, 44789, 44797, 44809, 44819, 44839, 44843, 44851, 44867,
- 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, 44959,
- 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077,
- 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179,
- 45181, 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289,
- 45293, 45307, 45317, 45319, 45329, 45337, 45341, 45343, 45361,
- 45377, 45389, 45403, 45413, 45427, 45433, 45439, 45481, 45491,
- 45497, 45503, 45523, 45533, 45541, 45553, 45557, 45569, 45587,
- 45589, 45599, 45613, 45631, 45641, 45659, 45667, 45673, 45677,
- 45691, 45697, 45707, 45737, 45751, 45757, 45763, 45767, 45779,
- 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, 45869,
- 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989,
- 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099,
- 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187,
- 46199, 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301,
- 46307, 46309, 46327, 46337, 46349, 46351, 46381, 46399, 46411,
- 46439, 46441, 46447, 46451, 46457, 46471, 46477, 46489, 46499,
- 46507, 46511, 46523, 46549, 46559, 46567, 46573, 46589, 46591,
- 46601, 46619, 46633, 46639, 46643, 46649, 46663, 46679, 46681,
- 46687, 46691, 46703, 46723, 46727, 46747, 46751, 46757, 46769,
- 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853, 46861,
- 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997,
- 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119,
- 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207,
- 47221, 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303,
- 47309, 47317, 47339, 47351, 47353, 47363, 47381, 47387, 47389,
- 47407, 47417, 47419, 47431, 47441, 47459, 47491, 47497, 47501,
- 47507, 47513, 47521, 47527, 47533, 47543, 47563, 47569, 47581,
- 47591, 47599, 47609, 47623, 47629, 47639, 47653, 47657, 47659,
- 47681, 47699, 47701, 47711, 47713, 47717, 47737, 47741, 47743,
- 47777, 47779, 47791, 47797, 47807, 47809, 47819, 47837, 47843,
- 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, 47947,
- 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049,
- 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163,
- 48179, 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271,
- 48281, 48299, 48311, 48313, 48337, 48341, 48353, 48371, 48383,
- 48397, 48407, 48409, 48413, 48437, 48449, 48463, 48473, 48479,
- 48481, 48487, 48491, 48497, 48523, 48527, 48533, 48539, 48541,
- 48563, 48571, 48589, 48593, 48611, 48619, 48623, 48647, 48649,
- 48661, 48673, 48677, 48679, 48731, 48733, 48751, 48757, 48761,
- 48767, 48779, 48781, 48787, 48799, 48809, 48817, 48821, 48823,
- 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, 48947,
- 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033,
- 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121,
- 49123, 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201,
- 49207, 49211, 49223, 49253, 49261, 49277, 49279, 49297, 49307,
- 49331, 49333, 49339, 49363, 49367, 49369, 49391, 49393, 49409,
- 49411, 49417, 49429, 49433, 49451, 49459, 49463, 49477, 49481,
- 49499, 49523, 49529, 49531, 49537, 49547, 49549, 49559, 49597,
- 49603, 49613, 49627, 49633, 49639, 49663, 49667, 49669, 49681,
- 49697, 49711, 49727, 49739, 49741, 49747, 49757, 49783, 49787,
- 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, 49871,
- 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957,
- 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053,
- 50069, 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129,
- 50131, 50147, 50153, 50159, 50177, 50207, 50221, 50227, 50231,
- 50261, 50263, 50273, 50287, 50291, 50311, 50321, 50329, 50333,
- 50341, 50359, 50363, 50377, 50383, 50387, 50411, 50417, 50423,
- 50441, 50459, 50461, 50497, 50503, 50513, 50527, 50539, 50543,
- 50549, 50551, 50581, 50587, 50591, 50593, 50599, 50627, 50647,
- 50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, 50773,
- 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, 50873,
- 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971,
- 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071,
- 51109, 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197,
- 51199, 51203, 51217, 51229, 51239, 51241, 51257, 51263, 51283,
- 51287, 51307, 51329, 51341, 51343, 51347, 51349, 51361, 51383,
- 51407, 51413, 51419, 51421, 51427, 51431, 51437, 51439, 51449,
- 51461, 51473, 51479, 51481, 51487, 51503, 51511, 51517, 51521,
- 51539, 51551, 51563, 51577, 51581, 51593, 51599, 51607, 51613,
- 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, 51713,
- 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817,
- 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899,
- 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991,
- 52009, 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103,
- 52121, 52127, 52147, 52153, 52163, 52177, 52181, 52183, 52189,
- 52201, 52223, 52237, 52249, 52253, 52259, 52267, 52289, 52291,
- 52301, 52313, 52321, 52361, 52363, 52369, 52379, 52387, 52391,
- 52433, 52453, 52457, 52489, 52501, 52511, 52517, 52529, 52541,
- 52543, 52553, 52561, 52567, 52571, 52579, 52583, 52609, 52627,
- 52631, 52639, 52667, 52673, 52691, 52697, 52709, 52711, 52721,
- 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817,
- 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919,
- 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003,
- 53017, 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101,
- 53113, 53117, 53129, 53147, 53149, 53161, 53171, 53173, 53189,
- 53197, 53201, 53231, 53233, 53239, 53267, 53269, 53279, 53281,
- 53299, 53309, 53323, 53327, 53353, 53359, 53377, 53381, 53401,
- 53407, 53411, 53419, 53437, 53441, 53453, 53479, 53503, 53507,
- 53527, 53549, 53551, 53569, 53591, 53593, 53597, 53609, 53611,
- 53617, 53623, 53629, 53633, 53639, 53653, 53657, 53681, 53693,
- 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, 53791,
- 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891,
- 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987,
- 53993, 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091,
- 54101, 54121, 54133, 54139, 54151, 54163, 54167, 54181, 54193,
- 54217, 54251, 54269, 54277, 54287, 54293, 54311, 54319, 54323,
- 54331, 54347, 54361, 54367, 54371, 54377, 54401, 54403, 54409,
- 54413, 54419, 54421, 54437, 54443, 54449, 54469, 54493, 54497,
- 54499, 54503, 54517, 54521, 54539, 54541, 54547, 54559, 54563,
- 54577, 54581, 54583, 54601, 54617, 54623, 54629, 54631, 54647,
- 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, 54767,
- 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877,
- 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979,
- 54983, 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073,
- 55079, 55103, 55109, 55117, 55127, 55147, 55163, 55171, 55201,
- 55207, 55213, 55217, 55219, 55229, 55243, 55249, 55259, 55291,
- 55313, 55331, 55333, 55337, 55339, 55343, 55351, 55373, 55381,
- 55399, 55411, 55439, 55441, 55457, 55469, 55487, 55501, 55511,
- 55529, 55541, 55547, 55579, 55589, 55603, 55609, 55619, 55621,
- 55631, 55633, 55639, 55661, 55663, 55667, 55673, 55681, 55691,
- 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, 55799,
- 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849,
- 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933,
- 55949, 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053,
- 56081, 56087, 56093, 56099, 56101, 56113, 56123, 56131, 56149,
- 56167, 56171, 56179, 56197, 56207, 56209, 56237, 56239, 56249,
- 56263, 56267, 56269, 56299, 56311, 56333, 56359, 56369, 56377,
- 56383, 56393, 56401, 56417, 56431, 56437, 56443, 56453, 56467,
- 56473, 56477, 56479, 56489, 56501, 56503, 56509, 56519, 56527,
- 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, 56629,
- 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713,
- 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809,
- 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897,
- 56909, 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963,
- 56983, 56989, 56993, 56999, 57037, 57041, 57047, 57059, 57073,
- 57077, 57089, 57097, 57107, 57119, 57131, 57139, 57143, 57149,
- 57163, 57173, 57179, 57191, 57193, 57203, 57221, 57223, 57241,
- 57251, 57259, 57269, 57271, 57283, 57287, 57301, 57329, 57331,
- 57347, 57349, 57367, 57373, 57383, 57389, 57397, 57413, 57427,
- 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557, 57559,
- 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667,
- 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737,
- 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829,
- 57839, 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923,
- 57943, 57947, 57973, 57977, 57991, 58013, 58027, 58031, 58043,
- 58049, 58057, 58061, 58067, 58073, 58099, 58109, 58111, 58129,
- 58147, 58151, 58153, 58169, 58171, 58189, 58193, 58199, 58207,
- 58211, 58217, 58229, 58231, 58237, 58243, 58271, 58309, 58313,
- 58321, 58337, 58363, 58367, 58369, 58379, 58391, 58393, 58403,
- 58411, 58417, 58427, 58439, 58441, 58451, 58453, 58477, 58481,
- 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, 58603,
- 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711,
- 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831,
- 58889, 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943,
- 58963, 58967, 58979, 58991, 58997, 59009, 59011, 59021, 59023,
- 59029, 59051, 59053, 59063, 59069, 59077, 59083, 59093, 59107,
- 59113, 59119, 59123, 59141, 59149, 59159, 59167, 59183, 59197,
- 59207, 59209, 59219, 59221, 59233, 59239, 59243, 59263, 59273,
- 59281, 59333, 59341, 59351, 59357, 59359, 59369, 59377, 59387,
- 59393, 59399, 59407, 59417, 59419, 59441, 59443, 59447, 59453,
- 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, 59561,
- 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659,
- 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743,
- 59747, 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863,
- 59879, 59887, 59921, 59929, 59951, 59957, 59971, 59981, 59999,
- 60013, 60017, 60029, 60037, 60041, 60077, 60083, 60089, 60091,
- 60101, 60103, 60107, 60127, 60133, 60139, 60149, 60161, 60167,
- 60169, 60209, 60217, 60223, 60251, 60257, 60259, 60271, 60289,
- 60293, 60317, 60331, 60337, 60343, 60353, 60373, 60383, 60397,
- 60413, 60427, 60443, 60449, 60457, 60493, 60497, 60509, 60521,
- 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, 60631,
- 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719,
- 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793,
- 60811, 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913,
- 60917, 60919, 60923, 60937, 60943, 60953, 60961, 61001, 61007,
- 61027, 61031, 61043, 61051, 61057, 61091, 61099, 61121, 61129,
- 61141, 61151, 61153, 61169, 61211, 61223, 61231, 61253, 61261,
- 61283, 61291, 61297, 61331, 61333, 61339, 61343, 61357, 61363,
- 61379, 61381, 61403, 61409, 61417, 61441, 61463, 61469, 61471,
- 61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, 61553,
- 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, 61637,
- 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717,
- 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843,
- 61861, 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967,
- 61979, 61981, 61987, 61991, 62003, 62011, 62017, 62039, 62047,
- 62053, 62057, 62071, 62081, 62099, 62119, 62129, 62131, 62137,
- 62141, 62143, 62171, 62189, 62191, 62201, 62207, 62213, 62219,
- 62233, 62273, 62297, 62299, 62303, 62311, 62323, 62327, 62347,
- 62351, 62383, 62401, 62417, 62423, 62459, 62467, 62473, 62477,
- 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, 62581,
- 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659,
- 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773,
- 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897,
- 62903, 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983,
- 62987, 62989, 63029, 63031, 63059, 63067, 63073, 63079, 63097,
- 63103, 63113, 63127, 63131, 63149, 63179, 63197, 63199, 63211,
- 63241, 63247, 63277, 63281, 63299, 63311, 63313, 63317, 63331,
- 63337, 63347, 63353, 63361, 63367, 63377, 63389, 63391, 63397,
- 63409, 63419, 63421, 63439, 63443, 63463, 63467, 63473, 63487,
- 63493, 63499, 63521, 63527, 63533, 63541, 63559, 63577, 63587,
- 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649,
- 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719,
- 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803,
- 63809, 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907,
- 63913, 63929, 63949, 63977, 63997, 64007, 64013, 64019, 64033,
- 64037, 64063, 64067, 64081, 64091, 64109, 64123, 64151, 64153,
- 64157, 64171, 64187, 64189, 64217, 64223, 64231, 64237, 64271,
- 64279, 64283, 64301, 64303, 64319, 64327, 64333, 64373, 64381,
- 64399, 64403, 64433, 64439, 64451, 64453, 64483, 64489, 64499,
- 64513, 64553, 64567, 64577, 64579, 64591, 64601, 64609, 64613,
- 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, 64709,
- 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849,
- 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927,
- 64937, 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033,
- 65053, 65063, 65071, 65089, 65099, 65101, 65111, 65119, 65123,
- 65129, 65141, 65147, 65167, 65171, 65173, 65179, 65183, 65203,
- 65213, 65239, 65257, 65267, 65269, 65287, 65293, 65309, 65323,
- 65327, 65353, 65357, 65371, 65381, 65393, 65407, 65413, 65419,
- 65423, 65437, 65447, 65449, 65479, 65497, 65519, 65521, 65537,
- 65539, 65543, 65551, 65557, 65563, 65579, 65581, 65587, 65599,
- 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, 65687,
- 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761,
- 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851,
- 65867, 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963,
- 65981, 65983, 65993, 66029, 66037, 66041, 66047, 66067, 66071,
- 66083, 66089, 66103, 66107, 66109, 66137, 66161, 66169, 66173,
- 66179, 66191, 66221, 66239, 66271, 66293, 66301, 66337, 66343,
- 66347, 66359, 66361, 66373, 66377, 66383, 66403, 66413, 66431,
- 66449, 66457, 66463, 66467, 66491, 66499, 66509, 66523, 66529,
- 66533, 66541, 66553, 66569, 66571, 66587, 66593, 66601, 66617,
- 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, 66733,
- 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841,
- 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931,
- 66943, 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033,
- 67043, 67049, 67057, 67061, 67073, 67079, 67103, 67121, 67129,
- 67139, 67141, 67153, 67157, 67169, 67181, 67187, 67189, 67211,
- 67213, 67217, 67219, 67231, 67247, 67261, 67271, 67273, 67289,
- 67307, 67339, 67343, 67349, 67369, 67391, 67399, 67409, 67411,
- 67421, 67427, 67429, 67433, 67447, 67453, 67477, 67481, 67489,
- 67493, 67499, 67511, 67523, 67531, 67537, 67547, 67559, 67567,
- 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, 67679,
- 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763,
- 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853,
- 67867, 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943,
- 67957, 67961, 67967, 67979, 67987, 67993, 68023, 68041, 68053,
- 68059, 68071, 68087, 68099, 68111, 68113, 68141, 68147, 68161,
- 68171, 68207, 68209, 68213, 68219, 68227, 68239, 68261, 68279,
- 68281, 68311, 68329, 68351, 68371, 68389, 68399, 68437, 68443,
- 68447, 68449, 68473, 68477, 68483, 68489, 68491, 68501, 68507,
- 68521, 68531, 68539, 68543, 68567, 68581, 68597, 68611, 68633,
- 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, 68729,
- 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819,
- 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909,
- 68917, 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029,
- 69031, 69061, 69067, 69073, 69109, 69119, 69127, 69143, 69149,
- 69151, 69163, 69191, 69193, 69197, 69203, 69221, 69233, 69239,
- 69247, 69257, 69259, 69263, 69313, 69317, 69337, 69341, 69371,
- 69379, 69383, 69389, 69401, 69403, 69427, 69431, 69439, 69457,
- 69463, 69467, 69473, 69481, 69491, 69493, 69497, 69499, 69539,
- 69557, 69593, 69623, 69653, 69661, 69677, 69691, 69697, 69709,
- 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, 69827,
- 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929,
- 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019,
- 70039, 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121,
- 70123, 70139, 70141, 70157, 70163, 70177, 70181, 70183, 70199,
- 70201, 70207, 70223, 70229, 70237, 70241, 70249, 70271, 70289,
- 70297, 70309, 70313, 70321, 70327, 70351, 70373, 70379, 70381,
- 70393, 70423, 70429, 70439, 70451, 70457, 70459, 70481, 70487,
- 70489, 70501, 70507, 70529, 70537, 70549, 70571, 70573, 70583,
- 70589, 70607, 70619, 70621, 70627, 70639, 70657, 70663, 70667,
- 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, 70823,
- 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901,
- 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979,
- 70981, 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069,
- 71081, 71089, 71119, 71129, 71143, 71147, 71153, 71161, 71167,
- 71171, 71191, 71209, 71233, 71237, 71249, 71257, 71261, 71263,
- 71287, 71293, 71317, 71327, 71329, 71333, 71339, 71341, 71347,
- 71353, 71359, 71363, 71387, 71389, 71399, 71411, 71413, 71419,
- 71429, 71437, 71443, 71453, 71471, 71473, 71479, 71483, 71503,
- 71527, 71537, 71549, 71551, 71563, 71569, 71593, 71597, 71633,
- 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, 71719,
- 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843,
- 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917,
- 71933, 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999,
- 72019, 72031, 72043, 72047, 72053, 72073, 72077, 72089, 72091,
- 72101, 72103, 72109, 72139, 72161, 72167, 72169, 72173, 72211,
- 72221, 72223, 72227, 72229, 72251, 72253, 72269, 72271, 72277,
- 72287, 72307, 72313, 72337, 72341, 72353, 72367, 72379, 72383,
- 72421, 72431, 72461, 72467, 72469, 72481, 72493, 72497, 72503,
- 72533, 72547, 72551, 72559, 72577, 72613, 72617, 72623, 72643,
- 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, 72707,
- 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823,
- 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911,
- 72923, 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997,
- 73009, 73013, 73019, 73037, 73039, 73043, 73061, 73063, 73079,
- 73091, 73121, 73127, 73133, 73141, 73181, 73189, 73237, 73243,
- 73259, 73277, 73291, 73303, 73309, 73327, 73331, 73351, 73361,
- 73363, 73369, 73379, 73387, 73417, 73421, 73433, 73453, 73459,
- 73471, 73477, 73483, 73517, 73523, 73529, 73547, 73553, 73561,
- 73571, 73583, 73589, 73597, 73607, 73609, 73613, 73637, 73643,
- 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, 73727,
- 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859,
- 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961,
- 73973, 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077,
- 74093, 74099, 74101, 74131, 74143, 74149, 74159, 74161, 74167,
- 74177, 74189, 74197, 74201, 74203, 74209, 74219, 74231, 74257,
- 74279, 74287, 74293, 74297, 74311, 74317, 74323, 74353, 74357,
- 74363, 74377, 74381, 74383, 74411, 74413, 74419, 74441, 74449,
- 74453, 74471, 74489, 74507, 74509, 74521, 74527, 74531, 74551,
- 74561, 74567, 74573, 74587, 74597, 74609, 74611, 74623, 74653,
- 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, 74747,
- 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843,
- 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923,
- 74929, 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037,
- 75041, 75079, 75083, 75109, 75133, 75149, 75161, 75167, 75169,
- 75181, 75193, 75209, 75211, 75217, 75223, 75227, 75239, 75253,
- 75269, 75277, 75289, 75307, 75323, 75329, 75337, 75347, 75353,
- 75367, 75377, 75389, 75391, 75401, 75403, 75407, 75431, 75437,
- 75479, 75503, 75511, 75521, 75527, 75533, 75539, 75541, 75553,
- 75557, 75571, 75577, 75583, 75611, 75617, 75619, 75629, 75641,
- 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, 75721,
- 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821,
- 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967,
- 75979, 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039,
- 76079, 76081, 76091, 76099, 76103, 76123, 76129, 76147, 76157,
- 76159, 76163, 76207, 76213, 76231, 76243, 76249, 76253, 76259,
- 76261, 76283, 76289, 76303, 76333, 76343, 76367, 76369, 76379,
- 76387, 76403, 76421, 76423, 76441, 76463, 76471, 76481, 76487,
- 76493, 76507, 76511, 76519, 76537, 76541, 76543, 76561, 76579,
- 76597, 76603, 76607, 76631, 76649, 76651, 76667, 76673, 76679,
- 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, 76801,
- 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907,
- 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017,
- 77023, 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137,
- 77141, 77153, 77167, 77171, 77191, 77201, 77213, 77237, 77239,
- 77243, 77249, 77261, 77263, 77267, 77269, 77279, 77291, 77317,
- 77323, 77339, 77347, 77351, 77359, 77369, 77377, 77383, 77417,
- 77419, 77431, 77447, 77471, 77477, 77479, 77489, 77491, 77509,
- 77513, 77521, 77527, 77543, 77549, 77551, 77557, 77563, 77569,
- 77573, 77587, 77591, 77611, 77617, 77621, 77641, 77647, 77659,
- 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, 77731,
- 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839,
- 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969,
- 77977, 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059,
- 78079, 78101, 78121, 78137, 78139, 78157, 78163, 78167, 78173,
- 78179, 78191, 78193, 78203, 78229, 78233, 78241, 78259, 78277,
- 78283, 78301, 78307, 78311, 78317, 78341, 78347, 78367, 78401,
- 78427, 78437, 78439, 78467, 78479, 78487, 78497, 78509, 78511,
- 78517, 78539, 78541, 78553, 78569, 78571, 78577, 78583, 78593,
- 78607, 78623, 78643, 78649, 78653, 78691, 78697, 78707, 78713,
- 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, 78809,
- 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901,
- 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043,
- 79063, 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153,
- 79159, 79181, 79187, 79193, 79201, 79229, 79231, 79241, 79259,
- 79273, 79279, 79283, 79301, 79309, 79319, 79333, 79337, 79349,
- 79357, 79367, 79379, 79393, 79397, 79399, 79411, 79423, 79427,
- 79433, 79451, 79481, 79493, 79531, 79537, 79549, 79559, 79561,
- 79579, 79589, 79601, 79609, 79613, 79621, 79627, 79631, 79633,
- 79657, 79669, 79687, 79691, 79693, 79697, 79699, 79757, 79769,
- 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, 79843,
- 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939,
- 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039,
- 80051, 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153,
- 80167, 80173, 80177, 80191, 80207, 80209, 80221, 80231, 80233,
- 80239, 80251, 80263, 80273, 80279, 80287, 80309, 80317, 80329,
- 80341, 80347, 80363, 80369, 80387, 80407, 80429, 80447, 80449,
- 80471, 80473, 80489, 80491, 80513, 80527, 80537, 80557, 80567,
- 80599, 80603, 80611, 80621, 80627, 80629, 80651, 80657, 80669,
- 80671, 80677, 80681, 80683, 80687, 80701, 80713, 80737, 80747,
- 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, 80819,
- 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923,
- 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019,
- 81023, 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083,
- 81097, 81101, 81119, 81131, 81157, 81163, 81173, 81181, 81197,
- 81199, 81203, 81223, 81233, 81239, 81281, 81283, 81293, 81299,
- 81307, 81331, 81343, 81349, 81353, 81359, 81371, 81373, 81401,
- 81409, 81421, 81439, 81457, 81463, 81509, 81517, 81527, 81533,
- 81547, 81551, 81553, 81559, 81563, 81569, 81611, 81619, 81629,
- 81637, 81647, 81649, 81667, 81671, 81677, 81689, 81701, 81703,
- 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, 81817,
- 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929,
- 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007,
- 82009, 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073,
- 82129, 82139, 82141, 82153, 82163, 82171, 82183, 82189, 82193,
- 82207, 82217, 82219, 82223, 82231, 82237, 82241, 82261, 82267,
- 82279, 82301, 82307, 82339, 82349, 82351, 82361, 82373, 82387,
- 82393, 82421, 82457, 82463, 82469, 82471, 82483, 82487, 82493,
- 82499, 82507, 82529, 82531, 82549, 82559, 82561, 82567, 82571,
- 82591, 82601, 82609, 82613, 82619, 82633, 82651, 82657, 82699,
- 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, 82787,
- 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891,
- 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023,
- 83047, 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117,
- 83137, 83177, 83203, 83207, 83219, 83221, 83227, 83231, 83233,
- 83243, 83257, 83267, 83269, 83273, 83299, 83311, 83339, 83341,
- 83357, 83383, 83389, 83399, 83401, 83407, 83417, 83423, 83431,
- 83437, 83443, 83449, 83459, 83471, 83477, 83497, 83537, 83557,
- 83561, 83563, 83579, 83591, 83597, 83609, 83617, 83621, 83639,
- 83641, 83653, 83663, 83689, 83701, 83717, 83719, 83737, 83761,
- 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, 83873,
- 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987,
- 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121,
- 84127, 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199,
- 84211, 84221, 84223, 84229, 84239, 84247, 84263, 84299, 84307,
- 84313, 84317, 84319, 84347, 84349, 84377, 84389, 84391, 84401,
- 84407, 84421, 84431, 84437, 84443, 84449, 84457, 84463, 84467,
- 84481, 84499, 84503, 84509, 84521, 84523, 84533, 84551, 84559,
- 84589, 84629, 84631, 84649, 84653, 84659, 84673, 84691, 84697,
- 84701, 84713, 84719, 84731, 84737, 84751, 84761, 84787, 84793,
- 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, 84919,
- 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027,
- 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109,
- 85121, 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223,
- 85229, 85237, 85243, 85247, 85259, 85297, 85303, 85313, 85331,
- 85333, 85361, 85363, 85369, 85381, 85411, 85427, 85429, 85439,
- 85447, 85451, 85453, 85469, 85487, 85513, 85517, 85523, 85531,
- 85549, 85571, 85577, 85597, 85601, 85607, 85619, 85621, 85627,
- 85639, 85643, 85661, 85667, 85669, 85691, 85703, 85711, 85717,
- 85733, 85751, 85781, 85793, 85817, 85819, 85829, 85831, 85837,
- 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, 85991,
- 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111,
- 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183,
- 86197, 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269,
- 86287, 86291, 86293, 86297, 86311, 86323, 86341, 86351, 86353,
- 86357, 86369, 86371, 86381, 86389, 86399, 86413, 86423, 86441,
- 86453, 86461, 86467, 86477, 86491, 86501, 86509, 86531, 86533,
- 86539, 86561, 86573, 86579, 86587, 86599, 86627, 86629, 86677,
- 86689, 86693, 86711, 86719, 86729, 86743, 86753, 86767, 86771,
- 86783, 86813, 86837, 86843, 86851, 86857, 86861, 86869, 86923,
- 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, 87011,
- 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119,
- 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221,
- 87223, 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313,
- 87317, 87323, 87337, 87359, 87383, 87403, 87407, 87421, 87427,
- 87433, 87443, 87473, 87481, 87491, 87509, 87511, 87517, 87523,
- 87539, 87541, 87547, 87553, 87557, 87559, 87583, 87587, 87589,
- 87613, 87623, 87629, 87631, 87641, 87643, 87649, 87671, 87679,
- 87683, 87691, 87697, 87701, 87719, 87721, 87739, 87743, 87751,
- 87767, 87793, 87797, 87803, 87811, 87833, 87853, 87869, 87877,
- 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, 87973,
- 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079,
- 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241,
- 88259, 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379,
- 88397, 88411, 88423, 88427, 88463, 88469, 88471, 88493, 88499,
- 88513, 88523, 88547, 88589, 88591, 88607, 88609, 88643, 88651,
- 88657, 88661, 88663, 88667, 88681, 88721, 88729, 88741, 88747,
- 88771, 88789, 88793, 88799, 88801, 88807, 88811, 88813, 88817,
- 88819, 88843, 88853, 88861, 88867, 88873, 88883, 88897, 88903,
- 88919, 88937, 88951, 88969, 88993, 88997, 89003, 89009, 89017,
- 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, 89101,
- 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209,
- 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303,
- 89317, 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413,
- 89417, 89431, 89443, 89449, 89459, 89477, 89491, 89501, 89513,
- 89519, 89521, 89527, 89533, 89561, 89563, 89567, 89591, 89597,
- 89599, 89603, 89611, 89627, 89633, 89653, 89657, 89659, 89669,
- 89671, 89681, 89689, 89753, 89759, 89767, 89779, 89783, 89797,
- 89809, 89819, 89821, 89833, 89839, 89849, 89867, 89891, 89897,
- 89899, 89909, 89917, 89923, 89939, 89959, 89963, 89977, 89983,
- 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, 90053,
- 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149,
- 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227,
- 90239, 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359,
- 90371, 90373, 90379, 90397, 90401, 90403, 90407, 90437, 90439,
- 90469, 90473, 90481, 90499, 90511, 90523, 90527, 90529, 90533,
- 90547, 90583, 90599, 90617, 90619, 90631, 90641, 90647, 90659,
- 90677, 90679, 90697, 90703, 90709, 90731, 90749, 90787, 90793,
- 90803, 90821, 90823, 90833, 90841, 90847, 90863, 90887, 90901,
- 90907, 90911, 90917, 90931, 90947, 90971, 90977, 90989, 90997,
- 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, 91127,
- 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193,
- 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297,
- 91303, 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393,
- 91397, 91411, 91423, 91433, 91453, 91457, 91459, 91463, 91493,
- 91499, 91513, 91529, 91541, 91571, 91573, 91577, 91583, 91591,
- 91621, 91631, 91639, 91673, 91691, 91703, 91711, 91733, 91753,
- 91757, 91771, 91781, 91801, 91807, 91811, 91813, 91823, 91837,
- 91841, 91867, 91873, 91909, 91921, 91939, 91943, 91951, 91957,
- 91961, 91967, 91969, 91997, 92003, 92009, 92033, 92041, 92051,
- 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, 92177,
- 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243,
- 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357,
- 92363, 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413,
- 92419, 92431, 92459, 92461, 92467, 92479, 92489, 92503, 92507,
- 92551, 92557, 92567, 92569, 92581, 92593, 92623, 92627, 92639,
- 92641, 92647, 92657, 92669, 92671, 92681, 92683, 92693, 92699,
- 92707, 92717, 92723, 92737, 92753, 92761, 92767, 92779, 92789,
- 92791, 92801, 92809, 92821, 92831, 92849, 92857, 92861, 92863,
- 92867, 92893, 92899, 92921, 92927, 92941, 92951, 92957, 92959,
- 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, 93089,
- 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179,
- 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263,
- 93281, 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371,
- 93377, 93383, 93407, 93419, 93427, 93463, 93479, 93481, 93487,
- 93491, 93493, 93497, 93503, 93523, 93529, 93553, 93557, 93559,
- 93563, 93581, 93601, 93607, 93629, 93637, 93683, 93701, 93703,
- 93719, 93739, 93761, 93763, 93787, 93809, 93811, 93827, 93851,
- 93871, 93887, 93889, 93893, 93901, 93911, 93913, 93923, 93937,
- 93941, 93949, 93967, 93971, 93979, 93983, 93997, 94007, 94009,
- 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, 94117,
- 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253,
- 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343,
- 94349, 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439,
- 94441, 94447, 94463, 94477, 94483, 94513, 94529, 94531, 94541,
- 94543, 94547, 94559, 94561, 94573, 94583, 94597, 94603, 94613,
- 94621, 94649, 94651, 94687, 94693, 94709, 94723, 94727, 94747,
- 94771, 94777, 94781, 94789, 94793, 94811, 94819, 94823, 94837,
- 94841, 94847, 94849, 94873, 94889, 94903, 94907, 94933, 94949,
- 94951, 94961, 94993, 94999, 95003, 95009, 95021, 95027, 95063,
- 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, 95131,
- 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231,
- 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311,
- 95317, 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419,
- 95429, 95441, 95443, 95461, 95467, 95471, 95479, 95483, 95507,
- 95527, 95531, 95539, 95549, 95561, 95569, 95581, 95597, 95603,
- 95617, 95621, 95629, 95633, 95651, 95701, 95707, 95713, 95717,
- 95723, 95731, 95737, 95747, 95773, 95783, 95789, 95791, 95801,
- 95803, 95813, 95819, 95857, 95869, 95873, 95881, 95891, 95911,
- 95917, 95923, 95929, 95947, 95957, 95959, 95971, 95987, 95989,
- 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, 96137,
- 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223,
- 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329,
- 96331, 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451,
- 96457, 96461, 96469, 96479, 96487, 96493, 96497, 96517, 96527,
- 96553, 96557, 96581, 96587, 96589, 96601, 96643, 96661, 96667,
- 96671, 96697, 96703, 96731, 96737, 96739, 96749, 96757, 96763,
- 96769, 96779, 96787, 96797, 96799, 96821, 96823, 96827, 96847,
- 96851, 96857, 96893, 96907, 96911, 96931, 96953, 96959, 96973,
- 96979, 96989, 96997, 97001, 97003, 97007, 97021, 97039, 97073,
- 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, 97171,
- 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303,
- 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423,
- 97429, 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523,
- 97547, 97549, 97553, 97561, 97571, 97577, 97579, 97583, 97607,
- 97609, 97613, 97649, 97651, 97673, 97687, 97711, 97729, 97771,
- 97777, 97787, 97789, 97813, 97829, 97841, 97843, 97847, 97849,
- 97859, 97861, 97871, 97879, 97883, 97919, 97927, 97931, 97943,
- 97961, 97967, 97973, 97987, 98009, 98011, 98017, 98041, 98047,
- 98057, 98081, 98101, 98123, 98129, 98143, 98179, 98207, 98213,
- 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, 98321,
- 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411,
- 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491,
- 98507, 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621,
- 98627, 98639, 98641, 98663, 98669, 98689, 98711, 98713, 98717,
- 98729, 98731, 98737, 98773, 98779, 98801, 98807, 98809, 98837,
- 98849, 98867, 98869, 98873, 98887, 98893, 98897, 98899, 98909,
- 98911, 98927, 98929, 98939, 98947, 98953, 98963, 98981, 98993,
- 98999, 99013, 99017, 99023, 99041, 99053, 99079, 99083, 99089,
- 99103, 99109, 99119, 99131, 99133, 99137, 99139, 99149, 99173,
- 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, 99277,
- 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397,
- 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527,
- 99529, 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611,
- 99623, 99643, 99661, 99667, 99679, 99689, 99707, 99709, 99713,
- 99719, 99721, 99733, 99761, 99767, 99787, 99793, 99809, 99817,
- 99823, 99829, 99833, 99839, 99859, 99871, 99877, 99881, 99901,
- 99907, 99923, 99929, 99961, 99971, 99989, 99991,
- };
#include "rust_scheduler.h"
#include "rust_gc_metadata.h"
-// Creates a rust argument vector from the platform argument vector
-struct
-command_line_args : public kernel_owned<command_line_args>
-{
- rust_kernel *kernel;
- rust_task *task;
- int argc;
- char **argv;
-
- // [str] passed to rust_task::start.
- rust_vec_box *args;
-
- command_line_args(rust_task *task,
- int sys_argc,
- char **sys_argv)
- : kernel(task->kernel),
- task(task),
- argc(sys_argc),
- argv(sys_argv)
- {
-#if defined(__WIN32__)
- LPCWSTR cmdline = GetCommandLineW();
- LPWSTR *wargv = CommandLineToArgvW(cmdline, &argc);
- kernel->win32_require("CommandLineToArgvW", wargv != NULL);
- argv = (char **) kernel->malloc(sizeof(char*) * argc,
- "win32 command line");
- for (int i = 0; i < argc; ++i) {
- int n_chars = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1,
- NULL, 0, NULL, NULL);
- kernel->win32_require("WideCharToMultiByte(0)", n_chars != 0);
- argv[i] = (char *) kernel->malloc(n_chars,
- "win32 command line arg");
- n_chars = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1,
- argv[i], n_chars, NULL, NULL);
- kernel->win32_require("WideCharToMultiByte(1)", n_chars != 0);
- }
- LocalFree(wargv);
-#endif
-
- args = make_str_vec(kernel, argc, argv);
- }
-
- ~command_line_args() {
- for (int i = 0; i < argc; ++i) {
- rust_vec *s = ((rust_vec**)&args->body.data)[i];
- kernel->free(s);
- }
- kernel->free(args);
-
-#ifdef __WIN32__
- for (int i = 0; i < argc; ++i) {
- kernel->free(argv[i]);
- }
- kernel->free(argv);
-#endif
- }
-};
-
void* global_crate_map = NULL;
/**
assert(sched != NULL);
rust_task *root_task = sched->create_task(NULL, "main");
- // Build the command line arguments to pass to the root task
- command_line_args *args
- = new (kernel, "main command line args")
- command_line_args(root_task, argc, argv);
-
- LOG(root_task, dom, "startup: %d args in 0x%" PRIxPTR,
- args->argc, (uintptr_t)args->args);
- for (int i = 0; i < args->argc; i++) {
- LOG(root_task, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
- }
-
// Schedule the main Rust task
- root_task->start((spawn_fn)main_fn, NULL, args->args);
+ root_task->start((spawn_fn)main_fn, NULL, NULL);
// At this point the task lifecycle is responsible for it
// and our pointer may not be valid
// Run the kernel until all schedulers exit
int ret = kernel->run();
- delete args;
delete kernel;
free_env(env);
--- /dev/null
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "rust_android_dummy.h"
+#include <math.h>
+
+#ifdef __ANDROID__
+
+int backtrace(void **array, int size) { return 0; }
+
+char **backtrace_symbols(void *const *array, int size) { return 0; }
+
+void backtrace_symbols_fd (void *const *array, int size, int fd) {}
+
+
+extern "C" float log2f(float f)
+{
+ return logf( f ) / logf( 2 );
+}
+
+extern "C" double log2( double n )
+{
+ return log( n ) / log( 2 );
+}
+
+extern "C" void telldir()
+{
+}
+
+extern "C" void seekdir()
+{
+}
+
+extern "C" void mkfifo()
+{
+}
+
+extern "C" void abs()
+{
+}
+
+extern "C" void labs()
+{
+}
+
+extern "C" void rand()
+{
+}
+
+extern "C" void srand()
+{
+}
+
+extern "C" void atof()
+{
+}
+extern "C" void tgammaf()
+{
+}
+#endif
--- /dev/null
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef _RUST_ANDROID_DUMMY_H
+#define _RUST_ANDROID_DUMMY_H
+
+int backtrace (void **__array, int __size);
+
+char **backtrace_symbols (void *__const *__array, int __size);
+
+void backtrace_symbols_fd (void *__const *__array, int __size, int __fd);
+
+#endif
+
#include "rust_util.h"
#include "rust_scheduler.h"
#include "sync/timer.h"
+#include "sync/rust_thread.h"
#include "rust_abi.h"
#include "rust_port.h"
extern char **environ;
#endif
+#ifdef __ANDROID__
+time_t
+timegm(struct tm *tm)
+{
+ time_t ret;
+ char *tz;
+
+ tz = getenv("TZ");
+ setenv("TZ", "", 1);
+ tzset();
+ ret = mktime(tm);
+ if (tz)
+ setenv("TZ", tz, 1);
+ else
+ unsetenv("TZ");
+ tzset();
+ return ret;
+}
+#endif
+
+
extern "C" CDECL rust_str*
last_os_error() {
rust_task *task = rust_get_current_task();
task->fail();
return NULL;
}
-#elif defined(_GNU_SOURCE)
+#elif defined(_GNU_SOURCE) && !defined(__ANDROID__)
char cbuf[BUF_BYTES];
char *buf = strerror_r(errno, cbuf, sizeof(cbuf));
if (!buf) {
task->sched_loop->get_log().log(task, level, "%.*s", (int)size, str);
}
+extern "C" CDECL void record_sp_limit(void *limit);
+
+class raw_thread: public rust_thread {
+public:
+ fn_env_pair *fn;
+
+ raw_thread(fn_env_pair *fn) : fn(fn) { }
+
+ virtual void run() {
+ record_sp_limit(0);
+ fn->f(NULL, fn->env, NULL);
+ }
+};
+
+extern "C" raw_thread*
+rust_raw_thread_start(fn_env_pair *fn) {
+ assert(fn);
+ raw_thread *thread = new raw_thread(fn);
+ thread->start();
+ return thread;
+}
+
+extern "C" void
+rust_raw_thread_join_delete(raw_thread *thread) {
+ assert(thread);
+ thread->join();
+ delete thread;
+}
+
+
//
// Local Variables:
// mode: C++
id(id),
should_exit(false),
cached_c_stack(NULL),
+ extra_c_stack(NULL),
dead_task(NULL),
killed(killed),
pump_signal(NULL),
size_t
rust_sched_loop::number_of_live_tasks() {
+ lock.must_have_lock();
return running_tasks.length() + blocked_tasks.length();
}
rust_task *
rust_sched_loop::schedule_task() {
lock.must_have_lock();
- assert(this);
if (running_tasks.length() > 0) {
size_t k = isaac_rand(&rctx);
- // Look around for a runnable task, starting at k.
- for(size_t j = 0; j < running_tasks.length(); ++j) {
- size_t i = (j + k) % running_tasks.length();
- return (rust_task *)running_tasks[i];
- }
+ size_t i = k % running_tasks.length();
+ return (rust_task *)running_tasks[i];
}
return NULL;
}
#ifndef __WIN32__
+#ifdef __ANDROID__
+#include "rust_android_dummy.h"
+#else
#include <execinfo.h>
#endif
+#endif
#include <iostream>
#include <algorithm>
#define RED_ZONE_SIZE RZ_BSD_64
#endif
#endif
+#ifdef __ANDROID__
+#define RED_ZONE_SIZE RZ_MAC_32
+#endif
struct rust_box;
LOG_UPCALL_ENTRY(task);
size_t total_size = get_box_size(args->size, args->td->align);
- // FIXME--does this have to be calloc? (Issue #2682)
- void *p = task->kernel->calloc(total_size, "exchange malloc");
+ void *p = task->kernel->malloc(total_size, "exchange malloc");
rust_opaque_box *header = static_cast<rust_opaque_box*>(p);
header->ref_count = -1; // This is not ref counted
LOG_UPCALL_ENTRY(task);
LOG(task, mem, "upcall malloc(0x%" PRIxPTR ")", args->td);
- // FIXME--does this have to be calloc? (Issue #2682)
- rust_opaque_box *box = task->boxed.calloc(args->td, args->size);
+ rust_opaque_box *box = task->boxed.malloc(args->td, args->size);
void *body = box_body(box);
debug::maybe_track_origin(task, box);
linenoiseHistorySetMaxLen
linenoiseHistorySave
linenoiseHistoryLoad
+rust_raw_thread_start
+rust_raw_thread_join_delete
void LLVMInitializeX86AsmPrinter();
void LLVMInitializeX86AsmParser();
+
+void LLVMInitializeARMTargetInfo();
+void LLVMInitializeARMTarget();
+void LLVMInitializeARMTargetMC();
+void LLVMInitializeARMAsmPrinter();
+void LLVMInitializeARMAsmParser();
// Only initialize the platforms supported by Rust here,
// because using --llvm-root will have multiple platforms
// that rustllvm doesn't actually link to and it's pointless to put target info
LLVMInitializeX86TargetMC();
LLVMInitializeX86AsmPrinter();
LLVMInitializeX86AsmParser();
+
+ LLVMInitializeARMTargetInfo();
+ LLVMInitializeARMTarget();
+ LLVMInitializeARMTargetMC();
+ LLVMInitializeARMAsmPrinter();
+ LLVMInitializeARMAsmParser();
}
// Custom memory manager for MCJITting. It needs special features
if (Name == "mknod") return (void*)(intptr_t)&mknod;
#endif
- if (Name == "__morestack") return &__morestack;
+ if (Name == "__morestack" || Name == "___morestack") return &__morestack;
const char *NameStr = Name.c_str();
LLVMInitializeScalarOpts
LLVMInitializeTarget
LLVMInitializeTransformUtils
+LLVMInitializeARMAsmLexer
LLVMInitializeX86AsmLexer
-LLVMInitializeX86AsmLexer
-LLVMInitializeX86AsmParser
+LLVMInitializeARMAsmParser
LLVMInitializeX86AsmParser
+LLVMInitializeARMAsmPrinter
LLVMInitializeX86AsmPrinter
-LLVMInitializeX86AsmPrinter
-LLVMInitializeX86Disassembler
+LLVMInitializeARMDisassembler
LLVMInitializeX86Disassembler
+LLVMInitializeARMTarget
LLVMInitializeX86Target
-LLVMInitializeX86Target
-LLVMInitializeX86TargetMC
+LLVMInitializeARMTargetMC
LLVMInitializeX86TargetMC
-LLVMInitializeX86TargetInfo
+LLVMInitializeARMTargetInfo
LLVMInitializeX86TargetInfo
LLVMInsertBasicBlock
LLVMInsertBasicBlockInContext
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_exports];
-
-export foo;
-
use core::oldcomm::*;
-fn foo<T: Owned Copy>(x: T) -> Port<T> {
+pub fn foo<T: Owned Copy>(x: T) -> Port<T> {
let p = Port();
let c = Chan(&p);
do task::spawn() |copy c, copy x| {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_exports];
+use core::to_str::*;
-use to_str::*;
-use to_str::ToStr;
-
-mod kitty {
- #[legacy_exports];
-
-struct cat {
- priv mut meows : uint,
- mut how_hungry : int,
- name : ~str,
-}
+pub mod kitty {
+ pub struct cat {
+ priv mut meows : uint,
+ mut how_hungry : int,
+ name : ~str,
+ }
- impl cat : ToStr {
+ pub impl cat : ToStr {
pure fn to_str() -> ~str { copy self.name }
}
}
- impl cat {
+ pub impl cat {
fn speak() { self.meow(); }
fn eat() -> bool {
}
}
}
-fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
- cat {
- meows: in_x,
- how_hungry: in_y,
- name: in_name
- }
-}
+ pub fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
+ cat {
+ meows: in_x,
+ how_hungry: in_y,
+ name: in_name
+ }
+ }
}
use dvec::DVec;
type entry<A,B> = {key: A, value: B};
-type alist<A,B> = { eq_fn: fn@(A,A) -> bool, data: DVec<entry<A,B>> };
+struct alist<A,B> { eq_fn: fn@(A,A) -> bool, data: DVec<entry<A,B>> }
fn alist_add<A: Copy, B: Copy>(lst: alist<A,B>, k: A, v: B) {
lst.data.push({key:k, value:v});
#[inline]
fn new_int_alist<B: Copy>() -> alist<int, B> {
fn eq_int(&&a: int, &&b: int) -> bool { a == b }
- return {eq_fn: eq_int, data: DVec()};
+ return alist {eq_fn: eq_int, data: DVec()};
}
#[inline]
fn new_int_alist_2<B: Copy>() -> alist<int, B> {
#[inline]
fn eq_int(&&a: int, &&b: int) -> bool { a == b }
- return {eq_fn: eq_int, data: DVec()};
+ return alist {eq_fn: eq_int, data: DVec()};
}
#[link(name = "req")];
#[crate_type = "lib"];
-#[legacy_exports];
extern mod std;
-use dvec::*;
-use dvec::DVec;
+use core::dvec::*;
use std::map::HashMap;
-type header_map = HashMap<~str, @DVec<@~str>>;
+pub type header_map = HashMap<~str, @DVec<@~str>>;
// the unused ty param is necessary so this gets monomorphized
-fn request<T: Copy>(req: header_map) {
+pub fn request<T: Copy>(req: header_map) {
let _x = copy *(copy *req.get(~"METHOD"))[0u];
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[link(name = "linenoise",
+ vers = "0.1")];
+#[crate_type = "lib"];
+
+pub mod issue_3882;
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod issue_3882 {
+ struct Completions {
+ mut len: libc::size_t,
+ }
+
+ extern mod c {
+ fn linenoiseAddCompletion(lc: *Completions);
+ }
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_exports];
-export foo;
type oint = Option<int>;
-fn foo() -> oint { Some(3) }
+pub fn foo() -> oint { Some(3) }
vers = "0.1")];
#[crate_type = "lib"];
-#[legacy_exports];
-export read, readMaybe;
-trait read {
+pub trait read {
static fn readMaybe(s: ~str) -> Option<self>;
}
}
}
-fn read<T: read Copy>(s: ~str) -> T {
+pub fn read<T: read Copy>(s: ~str) -> T {
match read::readMaybe(s) {
Some(x) => x,
_ => fail ~"read failed!"
}
pub mod float {
- impl float: num::Num2 {
+ impl float: ::num::Num2 {
#[inline]
static pure fn from_int2(n: int) -> float { return n as float; }
}
}
pub mod float {
- impl float: num::Num2 {
+ impl float: ::num::Num2 {
static pure fn from_int2(n: int) -> float { return n as float; }
}
-}
\ No newline at end of file
+}
Could probably be more minimal.
*/
-#[legacy_exports];
-use libc::size_t;
-
-export port;
-export recv;
+use core::libc::size_t;
/**
* transmitted. If a port value is copied, both copies refer to the same
* port. Ports may be associated with multiple `chan`s.
*/
-enum port<T: Owned> {
+pub enum port<T: Owned> {
port_t(@port_ptr<T>)
}
/// Constructs a port
-fn port<T: Owned>() -> port<T> {
+pub fn port<T: Owned>() -> port<T> {
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
}
* Receive from a port. If no data is available on the port then the
* task will block until data becomes available.
*/
-fn recv<T: Owned>(p: port<T>) -> T { recv_((**p).po) }
+pub fn recv<T: Owned>(p: port<T>) -> T { recv_((**p).po) }
/// Receive on a raw port pointer
-fn recv_<T: Owned>(p: *rust_port) -> T {
+pub fn recv_<T: Owned>(p: *rust_port) -> T {
let yield = 0;
let yieldp = ptr::addr_of(&yield);
let mut res;
extern mod std;
use std::map;
-use mutable::Mut;
-use send_map::linear::*;
-use io::WriterUtil;
+use core::mutable::Mut;
+use core::send_map::linear::*;
+use core::io::WriterUtil;
struct Results {
sequential_ints: float,
rng, num_keys, &mut results);
write_results("libstd::map::hashmap", &results);
}
-}
\ No newline at end of file
+}
use std::deque;
use std::deque::Deque;
use std::par;
-use io::WriterUtil;
-use oldcomm::*;
-use int::abs;
+use core::io::WriterUtil;
+use core::oldcomm::*;
+use core::int::abs;
type node_id = i64;
type graph = ~[~[node_id]];
// that things will look really good once we get that lock out of the
// message path.
-use oldcomm::*;
+use core::oldcomm::*;
+use core::oldcomm;
extern mod std;
use std::time;
rv
}
-fn chanmb(i: uint, size: uint, ch: oldcomm::Chan<Line>) -> ()
+fn chanmb(i: uint, size: uint) -> Line
{
let mut crv = ~[];
let incr = 2f64/(size as f64);
let x = cmplx {re: xincr*(j as f64) - 1.5f64, im: y};
crv.push(fillbyte(x, incr));
};
- oldcomm::send(ch, Line {i:i, b: move crv});
+ Line {i:i, b:crv}
}
-type devnull = {dn: int};
+struct Devnull();
-impl devnull: io::Writer {
+impl Devnull: io::Writer {
fn write(&self, _b: &[const u8]) {}
fn seek(&self, _i: int, _s: io::SeekStyle) {}
fn tell(&self) -> uint {0_u}
fn get_type(&self) -> io::WriterType { io::File }
}
-fn writer(path: ~str, writech: oldcomm::Chan<oldcomm::Chan<Line>>, size: uint)
+fn writer(path: ~str, pport: pipes::Port<Line>, size: uint)
{
- let p: oldcomm::Port<Line> = oldcomm::Port();
- let ch = oldcomm::Chan(&p);
- oldcomm::send(writech, ch);
let cout: io::Writer = match path {
~"" => {
- {dn: 0} as io::Writer
+ Devnull as io::Writer
}
~"-" => {
io::stdout()
let mut done = 0_u;
let mut i = 0_u;
while i < size {
- let aline = oldcomm::recv(p);
+ let aline = pport.recv();
if aline.i == done {
debug!("W %u", aline.i);
cout.write(aline.b);
let size = if vec::len(args) < 2_u { 80_u }
else { uint::from_str(args[1]).get() };
- let writep = oldcomm::Port();
- let writech = oldcomm::Chan(&writep);
- do task::spawn |move path| {
- writer(copy path, writech, size);
- };
- let ch = oldcomm::recv(writep);
+ let (pport, pchan) = pipes::stream();
+ let pchan = pipes::SharedChan(pchan);
for uint::range(0_u, size) |j| {
- do task::spawn { chanmb(j, size, ch) };
+ let cchan = pchan.clone();
+ do task::spawn |move cchan| { cchan.send(chanmb(j, size)) };
};
+ writer(path, pport, size);
}
extern mod std;
+use core::os;
+
// Using sqrt from the standard library is way slower than using libc
// directly even though std just calls libc, I guess it must be
// because the the indirection through another dynamic linker
}
mod NBodySystem {
- #[legacy_exports];
+ use Body;
- fn make() -> ~[Body::props] {
+ pub fn make() -> ~[Body::props] {
let mut bodies: ~[Body::props] =
~[Body::sun(),
Body::jupiter(),
return bodies;
}
- fn advance(bodies: &mut [Body::props], dt: float) {
-
+ pub fn advance(bodies: &mut [Body::props], dt: float) {
let mut i = 0;
while i < 5 {
let mut j = i + 1;
}
}
- fn advance_one(bi: &mut Body::props,
- bj: &mut Body::props,
- dt: float) unsafe {
+ pub fn advance_one(bi: &mut Body::props,
+ bj: &mut Body::props,
+ dt: float) unsafe {
let dx = bi.x - bj.x;
let dy = bi.y - bj.y;
let dz = bi.z - bj.z;
let dSquared = dx * dx + dy * dy + dz * dz;
- let distance = libc::sqrt(dSquared);
+ let distance = ::libc::sqrt(dSquared);
let mag = dt / (dSquared * distance);
bi.vx -= dx * bj.mass * mag;
bj.vz += dz * bi.mass * mag;
}
- fn move_(b: &mut Body::props, dt: float) {
+ pub fn move_(b: &mut Body::props, dt: float) {
b.x += dt * b.vx;
b.y += dt * b.vy;
b.z += dt * b.vz;
}
- fn energy(bodies: &[Body::props]) -> float unsafe {
+ pub fn energy(bodies: &[Body::props]) -> float unsafe {
let mut dx;
let mut dy;
let mut dz;
dy = bodies[i].y - bodies[j].y;
dz = bodies[i].z - bodies[j].z;
- distance = libc::sqrt(dx * dx + dy * dy + dz * dz);
+ distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz);
e -= bodies[i].mass * bodies[j].mass / distance;
j += 1;
}
mod Body {
- #[legacy_exports];
+ use Body;
- const PI: float = 3.141592653589793;
- const SOLAR_MASS: float = 39.478417604357432;
+ pub const PI: float = 3.141592653589793;
+ pub const SOLAR_MASS: float = 39.478417604357432;
// was 4 * PI * PI originally
- const DAYS_PER_YEAR: float = 365.24;
+ pub const DAYS_PER_YEAR: float = 365.24;
- type props =
+ pub type props =
{mut x: float,
mut y: float,
mut z: float,
mut vz: float,
mass: float};
- fn jupiter() -> Body::props {
+ pub fn jupiter() -> Body::props {
return {mut x: 4.84143144246472090e+00,
mut y: -1.16032004402742839e+00,
mut z: -1.03622044471123109e-01,
mass: 9.54791938424326609e-04 * SOLAR_MASS};
}
- fn saturn() -> Body::props {
+ pub fn saturn() -> Body::props {
return {mut x: 8.34336671824457987e+00,
mut y: 4.12479856412430479e+00,
mut z: -4.03523417114321381e-01,
mass: 2.85885980666130812e-04 * SOLAR_MASS};
}
- fn uranus() -> Body::props {
+ pub fn uranus() -> Body::props {
return {mut x: 1.28943695621391310e+01,
mut y: -1.51111514016986312e+01,
mut z: -2.23307578892655734e-01,
mass: 4.36624404335156298e-05 * SOLAR_MASS};
}
- fn neptune() -> Body::props {
+ pub fn neptune() -> Body::props {
return {mut x: 1.53796971148509165e+01,
mut y: -2.59193146099879641e+01,
mut z: 1.79258772950371181e-01,
mass: 5.15138902046611451e-05 * SOLAR_MASS};
}
- fn sun() -> Body::props {
+ pub fn sun() -> Body::props {
return {mut x: 0.0,
mut y: 0.0,
mut z: 0.0,
mass: SOLAR_MASS};
}
- fn offset_momentum(props: &mut Body::props,
+ pub fn offset_momentum(props: &mut Body::props,
px: float, py: float, pz: float) {
props.vx = -px / SOLAR_MASS;
props.vy = -py / SOLAR_MASS;
extern mod std;
-use option = option;
-use option::Some;
-use option::None;
+use core::option;
use std::map;
use std::map::HashMap;
-use hash::Hash;
-use io::{ReaderUtil, WriterUtil};
+use core::hash::Hash;
+use core::io::{ReaderUtil, WriterUtil};
use std::time;
-use oldcomm::Chan;
-use oldcomm::Port;
-use oldcomm::recv;
-use oldcomm::send;
-use cmp::Eq;
-use to_bytes::IterBytes;
+use core::oldcomm::Chan;
+use core::oldcomm::Port;
+use core::oldcomm::recv;
+use core::oldcomm::send;
+use core::cmp::Eq;
+use core::to_bytes::IterBytes;
macro_rules! move_out (
{ $x:expr } => { unsafe { let y = move *ptr::addr_of(&($x)); move y } }
fn read_word() -> Option<~str>;
}
-// These used to be in task, but they disappeard.
-type joinable_task = Port<()>;
-fn spawn_joinable(+f: fn~()) -> joinable_task {
+// These used to be in task, but they disappeared.
+pub type joinable_task = Port<()>;
+pub fn spawn_joinable(+f: fn~()) -> joinable_task {
let p = Port();
let c = Chan(&p);
do task::spawn() |move f| {
p
}
-fn join(t: joinable_task) {
+pub fn join(t: joinable_task) {
t.recv()
}
io::println(fmt!("%s\t%?", *word, count));
}
-struct box<T> {
+pub struct box<T> {
mut contents: Option<T>,
}
-impl<T> box<T> {
+pub impl<T> box<T> {
fn swap(f: fn(+v: T) -> T) {
let mut tmp = None;
self.contents <-> tmp;
}
}
-fn box<T>(+x: T) -> box<T> {
+pub fn box<T>(+x: T) -> box<T> {
box {
contents: Some(move x)
}
}
mod map_reduce {
- #[legacy_exports];
- export putter;
- export getter;
- export mapper;
- export reducer;
- export map_reduce;
+ use core::oldcomm::*;
- type putter<K: Owned, V: Owned> = fn(&K, V);
+ use std::map::HashMap;
+ use std::map;
- type mapper<K1: Owned, K2: Owned, V: Owned> = fn~(K1, putter<K2, V>);
+ pub type putter<K: Owned, V: Owned> = fn(&K, V);
- type getter<V: Owned> = fn() -> Option<V>;
+ pub type mapper<K1: Owned, K2: Owned, V: Owned> = fn~(K1, putter<K2, V>);
- type reducer<K: Copy Owned, V: Copy Owned> = fn~(&K, getter<V>);
+ pub type getter<V: Owned> = fn() -> Option<V>;
+
+ pub type reducer<K: Copy Owned, V: Copy Owned> = fn~(&K, getter<V>);
enum ctrl_proto<K: Copy Owned, V: Copy Owned> {
- find_reducer(K, Chan<Chan<reduce_proto<V>>>),
+ find_reducer(K, Chan<Chan<::map_reduce::reduce_proto<V>>>),
mapper_done
}
}
reducer_response: recv<K: Copy Owned, V: Copy Owned> {
- reducer(Chan<reduce_proto<V>>) -> open<K, V>
+ reducer(::core::oldcomm::Chan<::map_reduce::reduce_proto<V>>)
+ -> open<K, V>
}
)
- enum reduce_proto<V: Copy Owned> { emit_val(V), done, addref, release }
+ pub enum reduce_proto<V: Copy Owned> {
+ emit_val(V),
+ done,
+ addref,
+ release
+ }
fn start_mappers<K1: Copy Owned, K2: Hash IterBytes Eq Const Copy Owned,
V: Copy Owned>(
map: &mapper<K1, K2, V>,
ctrls: &mut ~[ctrl_proto::server::open<K2, V>],
inputs: &~[K1])
- -> ~[joinable_task]
+ -> ~[::joinable_task]
{
let mut tasks = ~[];
for inputs.each |i| {
let (ctrl, ctrl_server) = ctrl_proto::init();
- let ctrl = box(move ctrl);
+ let ctrl = ::box(move ctrl);
let i = copy *i;
let m = copy *map;
- tasks.push(spawn_joinable(|move ctrl, move i| map_task(copy m, &ctrl, i)));
+ tasks.push(::spawn_joinable(|move ctrl, move i| map_task(copy m, &ctrl, i)));
ctrls.push(move ctrl_server);
}
move tasks
fn map_task<K1: Copy Owned, K2: Hash IterBytes Eq Const Copy Owned, V: Copy Owned>(
map: mapper<K1, K2, V>,
- ctrl: &box<ctrl_proto::client::open<K2, V>>,
+ ctrl: &::box<ctrl_proto::client::open<K2, V>>,
input: K1)
{
// log(error, "map_task " + input);
- let intermediates: HashMap<K2, Chan<reduce_proto<V>>>
+ let intermediates: HashMap<K2, Chan<::map_reduce::reduce_proto<V>>>
= map::HashMap();
do map(input) |key: &K2, val| {
let mut c = None;
- let found: Option<Chan<reduce_proto<V>>>
+ let found: Option<Chan<::map_reduce::reduce_proto<V>>>
= intermediates.find(*key);
match found {
Some(_c) => { c = Some(_c); }
send(c.get(), emit_val(val));
}
- fn finish<K: Copy Owned, V: Copy Owned>(_k: K, v: Chan<reduce_proto<V>>)
+ fn finish<K: Copy Owned, V: Copy Owned>(
+ _k: K, v: Chan<::map_reduce::reduce_proto<V>>)
{
send(v, release);
}
fn reduce_task<K: Copy Owned, V: Copy Owned>(
reduce: ~reducer<K, V>,
key: K,
- out: Chan<Chan<reduce_proto<V>>>)
+ out: Chan<Chan<::map_reduce::reduce_proto<V>>>)
{
let p = Port();
let mut ref_count = 0;
let mut is_done = false;
- fn get<V: Copy Owned>(p: Port<reduce_proto<V>>,
+ fn get<V: Copy Owned>(p: Port<::map_reduce::reduce_proto<V>>,
ref_count: &mut int, is_done: &mut bool)
-> Option<V> {
while !*is_done || *ref_count > 0 {
(*reduce)(&key, || get(p, &mut ref_count, &mut is_done) );
}
- fn map_reduce<K1: Copy Owned, K2: Hash IterBytes Eq Const Copy Owned, V: Copy Owned>(
+ pub fn map_reduce<K1: Copy Owned, K2: Hash IterBytes Eq Const Copy Owned, V: Copy Owned>(
map: mapper<K1, K2, V>,
reduce: reducer<K2, V>,
inputs: ~[K1])
let p = Port();
let ch = Chan(&p);
let r = copy reduce, kk = k;
- tasks.push(spawn_joinable(|move r|
+ tasks.push(::spawn_joinable(|move r|
reduce_task(~copy r, kk, ch)
));
c = recv(p);
for reducers.each_value |v| { send(v, done) }
- for tasks.each |t| { join(*t); }
+ for tasks.each |t| { ::join(*t); }
}
}
let readers: ~[fn~() -> word_reader] = if argv.len() >= 2 {
vec::view(argv, 1u, argv.len()).map(|f| {
- let f = *f;
- fn~() -> word_reader { file_word_reader(f) }
+ let f = copy *f;
+ fn~() -> word_reader { file_word_reader(copy f) }
})
}
else {
--- /dev/null
+enum sty = ~[int];
+
+fn unpack(_unpack: &fn(v: &sty) -> ~[int]) {}
+
+fn main() {
+ let _foo = unpack(|s| {
+ // Test that `s` is moved here.
+ match *s { sty(v) => v } //~ ERROR moving out of dereference of immutable & pointer
+ });
+}
fn bad_bang(i: uint) -> ! {
return 7u;
- //~^ ERROR expected `_|_` but found `uint`
+ //~^ ERROR expected `!` but found `uint`
}
fn main() { bad_bang(5u); }
fn bad_bang(i: uint) -> ! {
if i < 0u { } else { fail; }
- //~^ ERROR expected `_|_` but found `()`
+ //~^ ERROR expected `!` but found `()`
}
fn main() { bad_bang(5u); }
// except according to those terms.
fn f() -> ! {
- 3i //~ ERROR expected `_|_` but found `int`
+ 3i //~ ERROR expected `!` but found `int`
}
fn main() { }
}
f(g);
- //~^ ERROR mismatched types: expected `fn(fn(fn()))`
+ //~^ ERROR mismatched types: expected `extern fn(extern fn(extern fn()))`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use either::*;
-enum X = Either<(uint,uint),fn()>;
+use core::either::*;
+enum X = Either<(uint,uint),extern fn()>;
impl &X {
- fn with(blk: fn(x: &Either<(uint,uint),fn()>)) {
+ fn with(blk: fn(x: &Either<(uint,uint),extern fn()>)) {
blk(&**self)
}
}
_ => fail
}
}
-}
\ No newline at end of file
+}
--- /dev/null
+fn foo(f: fn() -> !) {}
+
+fn main() {
+ // Type inference didn't use to be able to handle this:
+ foo(|| fail);
+ foo(|| 22); //~ ERROR mismatched types
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn closure2(+x: util::NonCopyable) -> (util::NonCopyable,
- fn@() -> util::NonCopyable) {
- let f = fn@(copy x) -> util::NonCopyable {
+fn closure2(+x: core::util::NonCopyable)
+ -> (core::util::NonCopyable, fn@() -> core::util::NonCopyable) {
+ let f = fn@(copy x) -> core::util::NonCopyable {
//~^ ERROR copying a noncopyable value
//~^^ NOTE non-copyable value cannot be copied into a @fn closure
copy x
};
(move x,f)
}
-fn closure3(+x: util::NonCopyable) {
+fn closure3(+x: core::util::NonCopyable) {
do task::spawn |copy x| {
//~^ ERROR copying a noncopyable value
//~^^ NOTE non-copyable value cannot be copied into a ~fn closure
// Test that we use fully-qualified type names in error messages.
+// xfail-test
type T1 = uint;
type T2 = int;
// Testing that we don't fail abnormally after hitting the errors
-use unresolved::*; //~ ERROR unresolved name
-//~^ ERROR failed to resolve import
+use unresolved::*; //~ ERROR unresolved import
fn main() {
}
{
let mut res = foo(x);
-
+
let mut v = ~[mut];
- v = move ~[mut (move res)] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `durable`, missing `copy`)
+ v = move ~[mut (move res)] + v; //~ ERROR instantiating a type parameter with an incompatible type (needs `copy`, got `&static`, missing `copy`)
assert (v.len() == 2);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct send_packet<T: Copy> {
+pub struct send_packet<T: Copy> {
p: T
}
mod pingpong {
- #[legacy_exports];
- type ping = send_packet<pong>;
- enum pong = send_packet<ping>; //~ ERROR illegal recursive enum type; wrap the inner value in a box to make it representable
+ use send_packet;
+ pub type ping = send_packet<pong>;
+ pub enum pong = send_packet<ping>; //~ ERROR illegal recursive enum type; wrap the inner value in a box to make it representable
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-mod stream {
- #[legacy_exports];
- enum Stream<T: Owned> { send(T, server::Stream<T>), }
- mod server {
- #[legacy_exports];
+pub mod stream {
+ pub enum Stream<T: Owned> { send(T, ::stream::server::Stream<T>), }
+ pub mod server {
+ use core::option;
+ use core::pipes;
+
impl<T: Owned> Stream<T> {
- fn recv() -> extern fn(+v: Stream<T>) -> stream::Stream<T> {
+ pub fn recv() -> extern fn(+v: Stream<T>) -> ::stream::Stream<T> {
// resolve really should report just one error here.
// Change the test case when it changes.
- fn recv(+pipe: Stream<T>) -> stream::Stream<T> { //~ ERROR attempt to use a type argument out of scope
+ pub fn recv(+pipe: Stream<T>) -> ::stream::Stream<T> { //~ ERROR attempt to use a type argument out of scope
//~^ ERROR use of undeclared type name
//~^^ ERROR attempt to use a type argument out of scope
//~^^^ ERROR use of undeclared type name
recv
}
}
- type Stream<T: Owned> = pipes::RecvPacket<stream::Stream<T>>;
+
+ pub type Stream<T: Owned> = pipes::RecvPacket<::stream::Stream<T>>;
}
}
--- /dev/null
+fn main() {
+ let _p: char = 100; //~ ERROR mismatched types: expected `char` but found
+}
\ No newline at end of file
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait A {
+ fn a(&self) {
+ || self.b() //~ ERROR type `&self/self` does not implement any method in scope named `b`
+ }
+}
+fn main() {}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+struct HTMLImageData {
+ mut image: Option<~str>
+}
+
+struct ElementData {
+ kind: ~ElementKind
+}
+
+enum ElementKind {
+ HTMLImageElement(HTMLImageData)
+}
+
+enum NodeKind {
+ Element(ElementData)
+}
+
+enum NodeData = {
+ kind: ~NodeKind
+};
+
+fn main() {
+ let id = HTMLImageData { image: None };
+ let ed = ElementData { kind: ~HTMLImageElement(id) };
+ let n = NodeData({kind : ~Element(ed)});
+ match n.kind {
+ ~Element(ed) => match ed.kind {
+ ~HTMLImageElement(d) if d.image.is_some() => { true }
+ },
+ _ => fail ~"WAT" //~ ERROR wat
+ };
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+struct Obj {
+ member: uint
+}
+
+impl Obj {
+ static pure fn boom() -> bool {
+ return 1+1 == 2
+ }
+ pure fn chirp() {
+ self.boom(); //~ ERROR wat
+ }
+}
+
+fn main() {
+ let o = Obj { member: 0 };
+ o.chirp();
+ 1 + 1;
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+struct Thing {
+ x: int
+}
+
+impl Thing/*: Mul<int, Thing>*/ { //~ ERROR Look ma, no Mul!
+ pure fn mul(c: &int) -> Thing {
+ Thing {x: self.x * *c}
+ }
+}
+
+fn main() {
+ let u = Thing {x: 2};
+ let _v = u.mul(&3); // Works
+ let w = u * 3; // Works!!
+ io::println(fmt!("%i", w.x));
+
+ /*
+ // This doesn't work though.
+ let u2 = u as @Mul<int, Thing>;
+ let w2 = u2.mul(&4);
+ io::println(fmt!("%i", w2.x));
+ */
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+
+struct Point {
+ mut x: float,
+ mut y: float,
+}
+
+impl Point : ToStr { //~ ERROR implements a method not defined in the trait
+ static fn new(x: float, y: float) -> Point {
+ Point { x: x, y: y }
+ }
+
+ pure fn to_str() -> ~str {
+ fmt!("(%f, %f)", self.x, self.y)
+ }
+}
+
+fn main() {
+ let p = Point::new(0.0f, 0.0f);
+ io::println(p.to_str());
+}
fn g() -> ! { fail; }
fn f() -> ! {
- return 42i; //~ ERROR expected `_|_` but found `int`
+ return 42i; //~ ERROR expected `!` but found `int`
g(); //~ WARNING unreachable statement
}
fn main() { }
// except according to those terms.
fn f() -> ! {
- return 42i; //~ ERROR expected `_|_` but found `int`
+ return 42i; //~ ERROR expected `!` but found `int`
fail; //~ WARNING unreachable statement
}
fn main() { }
fn to_foo_2<T:Copy>(t: T) -> foo {
// Not OK---T may contain borrowed ptrs and it is going to escape
// as part of the returned foo value
- {f:t} as foo //~ ERROR value may contain borrowed pointers; use `durable` bound
+ {f:t} as foo //~ ERROR value may contain borrowed pointers; use `&static` bound
}
-fn to_foo_3<T:Copy Durable>(t: T) -> foo {
+fn to_foo_3<T:Copy &static>(t: T) -> foo {
// OK---T may escape as part of the returned foo value, but it is
// owned and hence does not contain borrowed ptrs
{f:t} as foo
trait foo { fn foo(); }
fn to_foo<T: Copy foo>(t: T) -> foo {
- t as foo //~ ERROR value may contain borrowed pointers; use `durable` bound
+ t as foo //~ ERROR value may contain borrowed pointers; use `&static` bound
}
-fn to_foo2<T: Copy foo Durable>(t: T) -> foo {
+fn to_foo2<T: Copy foo &static>(t: T) -> foo {
t as foo
}
fn@() -> T { t } //~ ERROR value may contain borrowed pointers
}
-fn copy2<T: Copy Durable>(t: T) -> fn@() -> T {
+fn copy2<T: Copy &static>(t: T) -> fn@() -> T {
fn@() -> T { t }
}
fn main() {
let x = &3;
- copy2(&x); //~ ERROR missing `durable`
+ copy2(&x); //~ ERROR missing `&static`
copy2(@3);
- copy2(@&x); //~ ERROR missing `durable`
+ copy2(@&x); //~ ERROR missing `&static`
copy2(fn@() {});
copy2(fn~() {}); //~ WARNING instantiating copy type parameter with a not implicitly copyable type
- copy2(fn&() {}); //~ ERROR missing `copy durable`
+ copy2(fn&() {}); //~ ERROR missing `copy &static`
}
loop {
break;
}
- return 42i; //~ ERROR expected `_|_` but found `int`
+ return 42i; //~ ERROR expected `!` but found `int`
}
fn main() {
// except according to those terms.
fn main() -> char {
-//~^ ERROR Wrong type in main function: found `fn() -> char`
+//~^ ERROR Wrong type in main function: found `extern fn() -> char`
}
// except according to those terms.
fn main(foo: {x: int, y: int}) {
-//~^ ERROR Wrong type in main function: found `fn({x: int,y: int})`
+//~^ ERROR Wrong type in main function: found `extern fn({x: int,y: int})`
}
fn main() {
~"" || 42; //~ ERROR binary operation || cannot be applied to type `~str`
- foo || {}; //~ ERROR binary operation || cannot be applied to type `fn(&fn())`
+ foo || {}; //~ ERROR binary operation || cannot be applied to type `extern fn(&fn())`
//~^ NOTE did you forget the 'do' keyword for the call?
}
// except according to those terms.
// error-pattern:declaration of `None` shadows
-use option::*;
+use core::option::*;
fn main() {
let None: int = 42;
extern mod std;
use std::arc;
-use oldcomm::*;
+use core::oldcomm::*;
fn main() {
let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
extern mod std;
use std::arc;
-use oldcomm::*;
+use core::oldcomm::*;
fn main() {
let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test
type foo = Option<int>;
fn bar(_t: foo) {}
--- /dev/null
+fn f<T:&static>(_: T) {}
+
+fn main() {
+ let x = @3;
+ f(x);
+ let x = &3;
+ f(x); //~ ERROR instantiating a type parameter with an incompatible type
+}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
+// xfail-test
type rec = {f: int};
fn f(p: *rec) -> int {
let carrots = @~"crunchy";
fn@(tasties: @~str, macerate: fn(~str)) {
- macerate(*tasties);
+ macerate(copy *tasties);
} (carrots, |food| {
let mush = food + cheese;
let f = fn@() {
extern mod std;
extern mod syntax;
-use io::*;
+use core::io::*;
use syntax::diagnostic;
use syntax::ast;
a: A, b: B
};
-fn f<A:Copy Durable>(a: A, b: u16) -> fn@() -> (A, u16) {
+fn f<A:Copy &static>(a: A, b: u16) -> fn@() -> (A, u16) {
fn@() -> (A, u16) { (a, b) }
}
enum t { make_t(@int), clam, }
fn foo(s: @int) {
- let count = core::sys::refcount(s);
+ let count = ::core::sys::refcount(s);
let x: t = make_t(s); // ref up
match x {
}
_ => { debug!("?"); fail; }
}
- log(debug, core::sys::refcount(s));
- assert (core::sys::refcount(s) == count + 1u);
- let _ = core::sys::refcount(s); // don't get bitten by last-use.
+ log(debug, ::core::sys::refcount(s));
+ assert (::core::sys::refcount(s) == count + 1u);
+ let _ = ::core::sys::refcount(s); // don't get bitten by last-use.
}
fn main() {
let s: @int = @0; // ref up
- let count = core::sys::refcount(s);
+ let count = ::core::sys::refcount(s);
foo(s); // ref up then down
- log(debug, core::sys::refcount(s));
- let count2 = core::sys::refcount(s);
- let _ = core::sys::refcount(s); // don't get bitten by last-use.
+ log(debug, ::core::sys::refcount(s));
+ let count2 = ::core::sys::refcount(s);
+ let _ = ::core::sys::refcount(s); // don't get bitten by last-use.
assert count == count2;
}
use std::prettyprint;
use std::time;
-fn test_prettyprint<A: Encodable<prettyprint::Encoder>>(
+fn test_prettyprint<A: Encodable<prettyprint::Serializer>>(
a: &A,
expected: &~str
) {
let s = do io::with_str_writer |w| {
- a.encode(&prettyprint::Encoder(w))
+ a.encode(&prettyprint::Serializer(w))
};
debug!("s == %?", s);
assert s == *expected;
// except according to those terms.
-fn a(c: core::oldcomm::Chan<int>) { core::oldcomm::send(c, 10); }
+fn a(c: ::core::oldcomm::Chan<int>) { ::core::oldcomm::send(c, 10); }
fn main() {
- let p = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
task::spawn(|| a(ch) );
task::spawn(|| a(ch) );
let mut n: int = 0;
- n = core::oldcomm::recv(p);
- n = core::oldcomm::recv(p);
+ n = ::core::oldcomm::recv(p);
+ n = ::core::oldcomm::recv(p);
// debug!("Finished.");
}
-fn b(c: core::oldcomm::Chan<int>) {
+fn b(c: ::core::oldcomm::Chan<int>) {
// debug!("task b0");
// debug!("task b1");
// debug!("task b2");
// debug!("task b3");
// debug!("task b4");
// debug!("task b5");
- core::oldcomm::send(c, 10);
+ ::core::oldcomm::send(c, 10);
}
// except according to those terms.
-fn a(c: core::oldcomm::Chan<int>) {
+fn a(c: ::core::oldcomm::Chan<int>) {
debug!("task a0");
debug!("task a1");
- core::oldcomm::send(c, 10);
+ ::core::oldcomm::send(c, 10);
}
fn main() {
- let p = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
task::spawn(|| a(ch) );
task::spawn(|| b(ch) );
let mut n: int = 0;
- n = core::oldcomm::recv(p);
- n = core::oldcomm::recv(p);
+ n = ::core::oldcomm::recv(p);
+ n = ::core::oldcomm::recv(p);
debug!("Finished.");
}
-fn b(c: core::oldcomm::Chan<int>) {
+fn b(c: ::core::oldcomm::Chan<int>) {
debug!("task b0");
debug!("task b1");
debug!("task b2");
debug!("task b2");
debug!("task b3");
- core::oldcomm::send(c, 10);
+ ::core::oldcomm::send(c, 10);
}
// except according to those terms.
-fn a(c: core::oldcomm::Chan<int>) {
+fn a(c: ::core::oldcomm::Chan<int>) {
if true {
debug!("task a");
debug!("task a");
debug!("task a");
debug!("task a");
}
- core::oldcomm::send(c, 10);
+ ::core::oldcomm::send(c, 10);
}
fn k(x: int) -> int { return 15; }
let mut n: int = 2 + 3 * 7;
let s: ~str = ~"hello there";
let p = oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let ch = ::core::oldcomm::Chan(&p);
task::spawn(|| a(ch) );
task::spawn(|| b(ch) );
let mut x: int = 10;
x = g(n, s);
log(debug, x);
- n = core::oldcomm::recv(p);
- n = core::oldcomm::recv(p);
+ n = ::core::oldcomm::recv(p);
+ n = ::core::oldcomm::recv(p);
debug!("children finished, root finishing");
}
-fn b(c: core::oldcomm::Chan<int>) {
+fn b(c: ::core::oldcomm::Chan<int>) {
if true {
debug!("task b");
debug!("task b");
debug!("task b");
debug!("task b");
}
- core::oldcomm::send(c, 10);
+ ::core::oldcomm::send(c, 10);
}
}
fn test_ptr() unsafe {
- let p1: *u8 = core::cast::reinterpret_cast(&0);
- let p2: *u8 = core::cast::reinterpret_cast(&0);
- let p3: *u8 = core::cast::reinterpret_cast(&1);
+ let p1: *u8 = ::core::cast::reinterpret_cast(&0);
+ let p2: *u8 = ::core::cast::reinterpret_cast(&0);
+ let p3: *u8 = ::core::cast::reinterpret_cast(&1);
assert p1 == p2;
assert p1 != p3;
unsafe {
error!("q = %x, r = %x",
- (core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&q))),
- (core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&r))));
+ (::core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&q))),
+ (::core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&r))));
}
assert(q == r);
r.y = 17;
// course preferable, as the value itself is
// irrelevant).
-fn foo(&&x: ()) -> core::oldcomm::Port<()> {
- let p = core::oldcomm::Port();
- let c = core::oldcomm::Chan(&p);
+fn foo(&&x: ()) -> ::core::oldcomm::Port<()> {
+ let p = ::core::oldcomm::Port();
+ let c = ::core::oldcomm::Chan(&p);
do task::spawn() |copy c, copy x| {
c.send(x);
}
extern mod cci_capture_clause;
-use oldcomm::recv;
+use core::oldcomm::recv;
fn main() {
cci_capture_clause::foo(()).recv()
// Issue #763
-enum request { quit, close(core::oldcomm::Chan<bool>), }
+enum request { quit, close(::core::oldcomm::Chan<bool>), }
-type ctx = core::oldcomm::Chan<request>;
+type ctx = ::core::oldcomm::Chan<request>;
-fn request_task(c: core::oldcomm::Chan<ctx>) {
- let p = core::oldcomm::Port();
- core::oldcomm::send(c, core::oldcomm::Chan(&p));
+fn request_task(c: ::core::oldcomm::Chan<ctx>) {
+ let p = ::core::oldcomm::Port();
+ ::core::oldcomm::send(c, ::core::oldcomm::Chan(&p));
let mut req: request;
- req = core::oldcomm::recv(p);
+ req = ::core::oldcomm::recv(p);
// Need to drop req before receiving it again
- req = core::oldcomm::recv(p);
+ req = ::core::oldcomm::recv(p);
}
fn new_cx() -> ctx {
- let p = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
let t = task::spawn(|| request_task(ch) );
let mut cx: ctx;
- cx = core::oldcomm::recv(p);
+ cx = ::core::oldcomm::recv(p);
return cx;
}
fn main() {
let cx = new_cx();
- let p = core::oldcomm::Port::<bool>();
- core::oldcomm::send(cx, close(core::oldcomm::Chan(&p)));
- core::oldcomm::send(cx, quit);
+ let p = ::core::oldcomm::Port::<bool>();
+ ::core::oldcomm::send(cx, close(::core::oldcomm::Chan(&p)));
+ ::core::oldcomm::send(cx, quit);
}
// xfail-fast
// aux-build:cci_class_cast.rs
extern mod cci_class_cast;
-use to_str::ToStr;
+use core::to_str::ToStr;
use cci_class_cast::kitty::*;
fn print_out<T: ToStr>(thing: T, expected: ~str) {
// except according to those terms.
// xfail-fast
-use to_str::*;
-use to_str::ToStr;
+use core::to_str::*;
struct cat {
priv mut meows : uint,
a: A, b: B
};
-fn f<A:Copy Durable>(a: A, b: u16) -> fn@() -> (A, u16) {
+fn f<A:Copy &static>(a: A, b: u16) -> fn@() -> (A, u16) {
fn@() -> (A, u16) { (a, b) }
}
fn main() {
enum x { foo }
- impl x : core::cmp::Eq {
+ impl x : ::core::cmp::Eq {
pure fn eq(&self, other: &x) -> bool {
(*self) as int == (*other) as int
}
fn main() {
let p = oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let ch = ::core::oldcomm::Chan(&p);
let t = task::spawn(|| child(ch) );
- let y = core::oldcomm::recv(p);
+ let y = ::core::oldcomm::recv(p);
error!("received");
log(error, y);
assert (y == 10);
}
-fn child(c: core::oldcomm::Chan<int>) {
+fn child(c: ::core::oldcomm::Chan<int>) {
error!("sending");
- core::oldcomm::send(c, 10);
+ ::core::oldcomm::send(c, 10);
error!("value sent");
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+ Bar(u32),
+ Baz,
+ Quux(u64, u16)
+}
+
+const X: Foo = Baz;
+
+fn main() {
+ match X {
+ Baz => {}
+ _ => fail
+ }
+ match Y {
+ Bar(s) => assert(s == 2654435769),
+ _ => fail
+ }
+ match Z {
+ Quux(d,h) => {
+ assert(d == 0x123456789abcdef0);
+ assert(h == 0x1234);
+ }
+ _ => fail
+ }
+}
+
+const Y: Foo = Bar(2654435769);
+const Z: Foo = Quux(0x123456789abcdef0, 0x1234);
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum E { V, VV(int) }
+const C: E = V;
+
+impl E {
+ fn method(&self) {
+ match *self {
+ V => {}
+ VV(*) => fail
+ }
+ }
+}
+
+fn main() {
+ C.method()
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum E { V, VV(int) }
+const C: E = V;
+
+fn f(a: &E) {
+ match *a {
+ V => {}
+ VV(*) => fail
+ }
+}
+
+fn main() {
+ f(&C)
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo = u32;
+
+const X: Foo = Foo(17);
+
+fn main() {
+ assert(*X == 17);
+ assert(*Y == 23);
+}
+
+const Y: Foo = Foo(23);
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Bar => {}
Baz | Boo => fail
}
+ match Y {
+ Baz => {}
+ Bar | Boo => fail
+ }
}
+const Y: Foo = Baz;
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+ Bar = 0xDEADBEE
+}
+
+const X: Foo = Bar;
+
+fn main() {
+ assert((X as uint) == 0xDEADBEE);
+ assert((Y as uint) == 0xDEADBEE);
+}
+
+const Y: Foo = Bar;
let digits: uint = 10 as uint;
- core::io::println(float::to_str(f64::sqrt(42.0f64) as float, digits));
+ ::core::io::println(float::to_str(f64::sqrt(42.0f64) as float, digits));
}
fn main() {
- let po = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&po);
- core::oldcomm::send(ch, 10);
- let i = core::oldcomm::recv(po);
+ let po = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&po);
+ ::core::oldcomm::send(ch, 10);
+ let i = ::core::oldcomm::recv(po);
assert (i == 10);
- core::oldcomm::send(ch, 11);
- let j = core::oldcomm::recv(po);
+ ::core::oldcomm::send(ch, 11);
+ let j = ::core::oldcomm::recv(po);
assert (j == 11);
}
+// xfail-fast
+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
+// xfail-fast
+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
+// xfail-fast
+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
x: T
}
-impl<T> S<T> : core::ops::Drop {
+impl<T> S<T> : ::core::ops::Drop {
fn finalize(&self) {
io::println("bye");
}
--- /dev/null
+enum Animal {
+ Dog (~str, float),
+ Cat { name: ~str, weight: float }
+}
+
+fn main() {
+ let mut a: Animal = Dog(~"Cocoa", 37.2);
+ a = Cat{ name: ~"Spotty", weight: 2.7 };
+ // permuting the fields should work too
+ let c = Cat { weight: 3.1, name: ~"Spreckles" };
+}
// except according to those terms.
mod foo {
- #[legacy_exports];
-
- export bar;
-
mod bar {
- #[legacy_exports];
- fn y() { x(); }
+ pub fn y() { super::super::foo::x(); }
}
- fn x() { debug!("x"); }
+ pub fn x() { debug!("x"); }
}
-fn main() { foo::bar::y(); }
+fn main() { self::foo::bar::y(); }
+// xfail-fast
+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-mod foo {
- #[legacy_exports];
- export x;
-
- fn x() { bar::x(); }
+pub mod foo {
+ pub fn x() { ::bar::x(); }
}
-mod bar {
- #[legacy_exports];
- export x;
-
- fn x() { debug!("x"); }
+pub mod bar {
+ pub fn x() { debug!("x"); }
}
fn main() { foo::x(); }
// xfail-fast
#[legacy_modes];
-fn fix_help<A: Durable, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B, x: A) -> B {
+fn fix_help<A: &static, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B, x: A) -> B {
return f({|a|fix_help(f, a)}, x);
}
-fn fix<A: Durable, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
+fn fix<A: &static, B: Owned>(f: extern fn(fn@(A) -> B, A) -> B) -> fn@(A) -> B {
return {|a|fix_help(f, a)};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-type r = {
+struct r {
field: fn@()
-};
+}
fn main() {
fn f() {}
- let i: r = {field: f};
+ let i: r = r {field: f};
}
\ No newline at end of file
extern mod libc {
#[legacy_exports];
fn write(fd: int, buf: *u8,
- count: core::libc::size_t) -> core::libc::ssize_t;
+ count: ::core::libc::size_t) -> ::core::libc::ssize_t;
}
#[abi = "cdecl"]
use std::map;
use std::map::HashMap;
-use oldcomm::Chan;
-use oldcomm::Port;
-use oldcomm::send;
-use oldcomm::recv;
+use core::oldcomm::Chan;
+use core::oldcomm::Port;
+use core::oldcomm::send;
+use core::oldcomm::recv;
-fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); }
+pub fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); }
mod map_reduce {
- #[legacy_exports];
- export putter;
- export mapper;
- export map_reduce;
+ use std::map;
+ use std::map::HashMap;
+ use core::oldcomm::Chan;
+ use core::oldcomm::Port;
+ use core::oldcomm::send;
+ use core::oldcomm::recv;
- type putter = fn@(~str, ~str);
+ pub type putter = fn@(~str, ~str);
- type mapper = extern fn(~str, putter);
+ pub type mapper = extern fn(~str, putter);
enum ctrl_proto { find_reducer(~[u8], Chan<int>), mapper_done, }
}
}
- map(input, |a,b| emit(intermediates, ctrl, a, b) );
+ ::map(input, |a,b| emit(intermediates, ctrl, a, b) );
send(ctrl, mapper_done);
}
- fn map_reduce(inputs: ~[~str]) {
+ pub fn map_reduce(inputs: ~[~str]) {
let ctrl = Port();
// This task becomes the master control task. It spawns others
extern mod std;
-use vec::*;
+use core::vec::*;
fn main() {
let mut v = from_elem(0u, 0);
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
mod m {
- #[legacy_exports];
#[cfg(target_arch = "x86")]
- fn main() {
- assert rusti::pref_align_of::<u64>() == 8u;
- assert rusti::min_align_of::<u64>() == 4u;
+ pub fn main() {
+ assert ::rusti::pref_align_of::<u64>() == 8u;
+ assert ::rusti::min_align_of::<u64>() == 4u;
}
#[cfg(target_arch = "x86_64")]
- fn main() {
- assert rusti::pref_align_of::<u64>() == 8u;
- assert rusti::min_align_of::<u64>() == 8u;
+ pub fn main() {
+ assert ::rusti::pref_align_of::<u64>() == 8u;
+ assert ::rusti::min_align_of::<u64>() == 8u;
}
}
#[cfg(target_os = "win32")]
mod m {
- #[legacy_exports];
#[cfg(target_arch = "x86")]
- fn main() {
- assert rusti::pref_align_of::<u64>() == 8u;
- assert rusti::min_align_of::<u64>() == 8u;
+ pub fn main() {
+ assert ::rusti::pref_align_of::<u64>() == 8u;
+ assert ::rusti::min_align_of::<u64>() == 8u;
}
}
#[abi = "rust-intrinsic"]
extern mod rusti {
#[legacy_exports];
- fn frame_address(f: fn(*u8));
+ fn frame_address(f: &once fn(*u8));
}
fn main() {
fn cttz16(x: i16) -> i16;
fn cttz32(x: i32) -> i32;
fn cttz64(x: i64) -> i64;
+
+ fn bswap16(x: i16) -> i16;
+ fn bswap32(x: i32) -> i32;
+ fn bswap64(x: i64) -> i64;
}
fn main() {
assert(cttz32(-1i32) == 0i32);
assert(cttz64(-1i64) == 0i64);
+ assert(bswap16(0x0A0Bi16) == 0x0B0Ai16);
+ assert(bswap32(0x0ABBCC0Di32) == 0x0DCCBB0Ai32);
+ assert(bswap64(0x0122334455667708i64) == 0x0877665544332201i64);
+
}
return f() + 1;
}
-fn ret_plus_one() -> fn(fn() -> int) -> int {
+fn ret_plus_one() -> extern fn(fn() -> int) -> int {
return plus_one;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use libc::{c_double, c_int};
-use f64::*;
+use core::cast;
+use core::libc::{c_double, c_int};
+use core::f64::*;
fn to_c_int(v: &mut int) -> &mut c_int unsafe {
cast::reinterpret_cast(&v)
#[link_name = "m"]
#[abi = "cdecl"]
extern mod m {
- #[legacy_exports];
#[cfg(unix)]
- #[link_name="lgamma_r"] fn lgamma(n: c_double, sign: &mut c_int)
+ #[link_name="lgamma_r"] pub fn lgamma(n: c_double, sign: &mut c_int)
-> c_double;
#[cfg(windows)]
- #[link_name="__lgamma_r"] fn lgamma(n: c_double,
- sign: &mut c_int) -> c_double;
+ #[link_name="__lgamma_r"] pub fn lgamma(n: c_double,
+ sign: &mut c_int) -> c_double;
}
// except according to those terms.
// tjc: I don't know why
-mod pipes {
- #[legacy_exports];
- use cast::{forget, transmute};
+pub mod pipes {
+ use core::cast::{forget, transmute};
- enum state {
+ pub enum state {
empty,
full,
blocked,
terminated
}
- impl state : cmp::Eq {
+ pub impl state : cmp::Eq {
pure fn eq(&self, other: &state) -> bool {
((*self) as uint) == ((*other) as uint)
}
pure fn ne(&self, other: &state) -> bool { !(*self).eq(other) }
}
- type packet<T: Owned> = {
+ pub type packet<T: Owned> = {
mut state: state,
mut blocked_task: Option<task::Task>,
mut payload: Option<T>
};
- fn packet<T: Owned>() -> *packet<T> unsafe {
+ pub fn packet<T: Owned>() -> *packet<T> unsafe {
let p: *packet<T> = cast::transmute(~{
mut state: empty,
mut blocked_task: None::<task::Task>,
#[abi = "rust-intrinsic"]
mod rusti {
- #[legacy_exports];
- fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail; }
- fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail; }
- fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail; }
+ pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail; }
+ pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail; }
+ pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail; }
}
- // We should consider moving this to core::unsafe, although I
+ // We should consider moving this to ::core::unsafe, although I
// suspect graydon would want us to use void pointers instead.
- unsafe fn uniquify<T>(+x: *T) -> ~T {
+ pub unsafe fn uniquify<T>(+x: *T) -> ~T {
unsafe { cast::transmute(move x) }
}
- fn swap_state_acq(+dst: &mut state, src: state) -> state {
+ pub fn swap_state_acq(+dst: &mut state, src: state) -> state {
unsafe {
transmute(rusti::atomic_xchg_acq(transmute(move dst), src as int))
}
}
- fn swap_state_rel(+dst: &mut state, src: state) -> state {
+ pub fn swap_state_rel(+dst: &mut state, src: state) -> state {
unsafe {
transmute(rusti::atomic_xchg_rel(transmute(move dst), src as int))
}
}
- fn send<T: Owned>(-p: send_packet<T>, -payload: T) {
+ pub fn send<T: Owned>(-p: send_packet<T>, -payload: T) {
let p = p.unwrap();
let p = unsafe { uniquify(p) };
assert (*p).payload.is_none();
}
}
- fn recv<T: Owned>(-p: recv_packet<T>) -> Option<T> {
+ pub fn recv<T: Owned>(-p: recv_packet<T>) -> Option<T> {
let p = p.unwrap();
let p = unsafe { uniquify(p) };
loop {
}
}
- fn sender_terminate<T: Owned>(p: *packet<T>) {
+ pub fn sender_terminate<T: Owned>(p: *packet<T>) {
let p = unsafe { uniquify(p) };
match swap_state_rel(&mut (*p).state, terminated) {
empty | blocked => {
}
}
- fn receiver_terminate<T: Owned>(p: *packet<T>) {
+ pub fn receiver_terminate<T: Owned>(p: *packet<T>) {
let p = unsafe { uniquify(p) };
match swap_state_rel(&mut (*p).state, terminated) {
empty => {
}
}
- struct send_packet<T: Owned> {
+ pub struct send_packet<T: Owned> {
mut p: Option<*packet<T>>,
}
- impl<T: Owned> send_packet<T> : Drop {
+ pub impl<T: Owned> send_packet<T> : Drop {
fn finalize(&self) {
if self.p != None {
let mut p = None;
}
}
- impl<T: Owned> send_packet<T> {
+ pub impl<T: Owned> send_packet<T> {
fn unwrap() -> *packet<T> {
let mut p = None;
p <-> self.p;
}
}
- fn send_packet<T: Owned>(p: *packet<T>) -> send_packet<T> {
+ pub fn send_packet<T: Owned>(p: *packet<T>) -> send_packet<T> {
send_packet {
p: Some(p)
}
}
- struct recv_packet<T: Owned> {
+ pub struct recv_packet<T: Owned> {
mut p: Option<*packet<T>>,
}
- impl<T: Owned> recv_packet<T> : Drop {
+ pub impl<T: Owned> recv_packet<T> : Drop {
fn finalize(&self) {
if self.p != None {
let mut p = None;
}
}
- impl<T: Owned> recv_packet<T> {
+ pub impl<T: Owned> recv_packet<T> {
fn unwrap() -> *packet<T> {
let mut p = None;
p <-> self.p;
}
}
- fn recv_packet<T: Owned>(p: *packet<T>) -> recv_packet<T> {
+ pub fn recv_packet<T: Owned>(p: *packet<T>) -> recv_packet<T> {
recv_packet {
p: Some(p)
}
}
- fn entangle<T: Owned>() -> (send_packet<T>, recv_packet<T>) {
+ pub fn entangle<T: Owned>() -> (send_packet<T>, recv_packet<T>) {
let p = packet();
(send_packet(p), recv_packet(p))
}
}
-mod pingpong {
- #[legacy_exports];
- enum ping = pipes::send_packet<pong>;
- enum pong = pipes::send_packet<ping>;
+pub mod pingpong {
+ use core::cast;
+ use core::ptr;
- fn liberate_ping(-p: ping) -> pipes::send_packet<pong> unsafe {
- let addr : *pipes::send_packet<pong> = match &p {
+ pub enum ping = ::pipes::send_packet<pong>;
+ pub enum pong = ::pipes::send_packet<ping>;
+
+ pub fn liberate_ping(-p: ping) -> ::pipes::send_packet<pong> unsafe {
+ let addr : *::pipes::send_packet<pong> = match &p {
&ping(ref x) => { cast::transmute(ptr::addr_of(x)) }
};
let liberated_value = move *addr;
move liberated_value
}
- fn liberate_pong(-p: pong) -> pipes::send_packet<ping> unsafe {
- let addr : *pipes::send_packet<ping> = match &p {
+ pub fn liberate_pong(-p: pong) -> ::pipes::send_packet<ping> unsafe {
+ let addr : *::pipes::send_packet<ping> = match &p {
&pong(ref x) => { cast::transmute(ptr::addr_of(x)) }
};
let liberated_value = move *addr;
move liberated_value
}
- fn init() -> (client::ping, server::ping) {
- pipes::entangle()
+ pub fn init() -> (client::ping, server::ping) {
+ ::pipes::entangle()
}
- mod client {
- #[legacy_exports];
- type ping = pipes::send_packet<pingpong::ping>;
- type pong = pipes::recv_packet<pingpong::pong>;
+ pub mod client {
+ use core::option;
+ use pingpong;
+
+ pub type ping = ::pipes::send_packet<pingpong::ping>;
+ pub type pong = ::pipes::recv_packet<pingpong::pong>;
- fn do_ping(-c: ping) -> pong {
- let (sp, rp) = pipes::entangle();
+ pub fn do_ping(-c: ping) -> pong {
+ let (sp, rp) = ::pipes::entangle();
- pipes::send(move c, ping(move sp));
+ ::pipes::send(move c, pingpong::ping(move sp));
move rp
}
- fn do_pong(-c: pong) -> (ping, ()) {
- let packet = pipes::recv(move c);
+ pub fn do_pong(-c: pong) -> (ping, ()) {
+ let packet = ::pipes::recv(move c);
if packet.is_none() {
fail ~"sender closed the connection"
}
- (liberate_pong(option::unwrap(move packet)), ())
+ (pingpong::liberate_pong(option::unwrap(move packet)), ())
}
}
- mod server {
- #[legacy_exports];
- type ping = pipes::recv_packet<pingpong::ping>;
- type pong = pipes::send_packet<pingpong::pong>;
+ pub mod server {
+ use pingpong;
+
+ pub type ping = ::pipes::recv_packet<pingpong::ping>;
+ pub type pong = ::pipes::send_packet<pingpong::pong>;
- fn do_ping(-c: ping) -> (pong, ()) {
- let packet = pipes::recv(move c);
+ pub fn do_ping(-c: ping) -> (pong, ()) {
+ let packet = ::pipes::recv(move c);
if packet.is_none() {
fail ~"sender closed the connection"
}
- (liberate_ping(option::unwrap(move packet)), ())
+ (pingpong::liberate_ping(option::unwrap(move packet)), ())
}
- fn do_pong(-c: pong) -> ping {
- let (sp, rp) = pipes::entangle();
- pipes::send(move c, pong(move sp));
+ pub fn do_pong(-c: pong) -> ping {
+ let (sp, rp) = ::pipes::entangle();
+ ::pipes::send(move c, pingpong::pong(move sp));
move rp
}
}
trait hax { }
impl <A> A: hax { }
-fn perform_hax<T: Durable>(x: @T) -> hax {
+fn perform_hax<T: &static>(x: @T) -> hax {
x as hax
}
trait hax { }
impl <A> A: hax { }
-fn perform_hax<T: Durable>(x: @T) -> hax {
+fn perform_hax<T: &static>(x: @T) -> hax {
x as hax
}
}
}
-fn read_board_grid<rdr: Durable io::Reader>(+in: rdr) -> ~[~[square]] {
+fn read_board_grid<rdr: &static io::Reader>(+in: rdr) -> ~[~[square]] {
let in = (move in) as io::Reader;
let mut grid = ~[];
for in.each_line |line| {
// rustc --test map_to_str.rs && ./map_to_str
extern mod std;
-use io::{WriterUtil};
+
+use core::io::{WriterUtil};
use std::map::*;
#[cfg(test)]
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(default_methods)]
+trait Canvas {
+ fn add_point(point: &int);
+ fn add_points(shapes: &[int]) {
+ for shapes.each |pt| {
+ self.add_point(pt)
+ }
+ }
+
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ASCII art shape renderer.
+// Demonstrates traits, impls, operator overloading, non-copyable struct, unit testing.
+// To run execute: rustc --test shapes.rs && ./shapes
+
+// Rust's core library is tightly bound to the language itself so it is automatically linked in.
+// However the std library is designed to be optional (for code that must run on constrained
+// environments like embedded devices or special environments like kernel code) so it must
+// be explicitly linked in.
+extern mod std;
+
+// Extern mod controls linkage. Use controls the visibility of names to modules that are
+// already linked in. Using WriterUtil allows us to use the write_line method.
+use io::WriterUtil;
+
+// Represents a position on a canvas.
+struct Point
+{
+ x: int,
+ y: int,
+}
+
+// Represents an offset on a canvas. (This has the same structure as a Point.
+// but different semantics).
+struct Size
+{
+ width: int,
+ height: int,
+}
+
+struct Rect
+{
+ top_left: Point,
+ size: Size,
+}
+
+// TODO: operators
+
+// Contains the information needed to do shape rendering via ASCII art.
+struct AsciiArt
+{
+ width: uint,
+ height: uint,
+ priv fill: char,
+ priv lines: ~[~[mut char]],
+
+ // This struct can be quite large so we'll disable copying: developers need
+ // to either pass these structs around via borrowed pointers or move them.
+ drop {}
+}
+
+// It's common to define a constructor sort of function to create struct instances.
+// If there is a canonical constructor it is typically named the same as the type.
+// Other constructor sort of functions are typically named from_foo, from_bar, etc.
+fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt
+{
+ // Use an anonymous function to build a vector of vectors containing
+ // blank characters for each position in our canvas.
+ let lines = do vec::build_sized(height)
+ |push|
+ {
+ for height.times
+ {
+ let mut line = ~[];
+ vec::grow_set(&mut line, width-1, &'.', '.');
+ push(vec::to_mut(line));
+ }
+ };
+
+ // Rust code often returns values by omitting the trailing semi-colon
+ // instead of using an explicit return statement.
+ AsciiArt {width: width, height: height, fill: fill, lines: lines}
+}
+
+// Methods particular to the AsciiArt struct.
+impl AsciiArt
+{
+ fn add_pt(x: int, y: int)
+ {
+ if x >= 0 && x < self.width as int
+ {
+ if y >= 0 && y < self.height as int
+ {
+ // Note that numeric types don't implicitly convert to each other.
+ let v = y as uint;
+ let h = x as uint;
+
+ // Vector subscripting will normally copy the element, but &v[i]
+ // will return a reference which is what we need because the
+ // element is:
+ // 1) potentially large
+ // 2) needs to be modified
+ let row = &self.lines[v];
+ row[h] = self.fill;
+ }
+ }
+ }
+}
+
+// Allows AsciiArt to be converted to a string using the libcore ToStr trait.
+// Note that the %s fmt! specifier will not call this automatically.
+impl AsciiArt : ToStr
+{
+ pure fn to_str() -> ~str
+ {
+ // Convert each line into a string.
+ let lines = do self.lines.map |line| {str::from_chars(*line)};
+
+ // Concatenate the lines together using a new-line.
+ str::connect(lines, "\n")
+ }
+}
+
+// This is similar to an interface in other languages: it defines a protocol which
+// developers can implement for arbitrary concrete types.
+#[allow(default_methods)]
+trait Canvas
+{
+ fn add_point(shape: Point);
+ fn add_rect(shape: Rect);
+
+ // Unlike interfaces traits support default implementations.
+ // Got an ICE as soon as I added this method.
+ fn add_points(shapes: &[Point])
+ {
+ for shapes.each |pt| {self.add_point(*pt)};
+ }
+}
+
+// Here we provide an implementation of the Canvas methods for AsciiArt.
+// Other implementations could also be provided (e.g. for PDF or Apple's Quartz)
+// and code can use them polymorphically via the Canvas trait.
+impl AsciiArt : Canvas
+{
+ fn add_point(shape: Point)
+ {
+ self.add_pt(shape.x, shape.y);
+ }
+
+ fn add_rect(shape: Rect)
+ {
+ // Add the top and bottom lines.
+ for int::range(shape.top_left.x, shape.top_left.x + shape.size.width)
+ |x|
+ {
+ self.add_pt(x, shape.top_left.y);
+ self.add_pt(x, shape.top_left.y + shape.size.height - 1);
+ }
+
+ // Add the left and right lines.
+ for int::range(shape.top_left.y, shape.top_left.y + shape.size.height)
+ |y|
+ {
+ self.add_pt(shape.top_left.x, y);
+ self.add_pt(shape.top_left.x + shape.size.width - 1, y);
+ }
+ }
+}
+
+// Rust's unit testing framework is currently a bit under-developed so we'll use
+// this little helper.
+pub fn check_strs(actual: &str, expected: &str) -> bool
+{
+ if actual != expected
+ {
+ io::stderr().write_line(fmt!("Found:\n%s\nbut expected\n%s", actual, expected));
+ return false;
+ }
+ return true;
+}
+
+
+fn test_ascii_art_ctor()
+{
+ let art = AsciiArt(3, 3, '*');
+ assert check_strs(art.to_str(), "...\n...\n...");
+}
+
+
+fn test_add_pt()
+{
+ let art = AsciiArt(3, 3, '*');
+ art.add_pt(0, 0);
+ art.add_pt(0, -10);
+ art.add_pt(1, 2);
+ assert check_strs(art.to_str(), "*..\n...\n.*.");
+}
+
+
+fn test_shapes()
+{
+ let art = AsciiArt(4, 4, '*');
+ art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}});
+ art.add_point(Point {x: 2, y: 2});
+ assert check_strs(art.to_str(), "****\n*..*\n*.**\n****");
+}
+
+fn main() {
+ test_ascii_art_ctor();
+ test_add_pt();
+ test_shapes();
+}
+
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// xfail-test
-trait A {
- fn a(&self) {
- || self.b()
- }
-}
--- /dev/null
+extern mod std;
+
+use pipes::Chan;
+
+type RingBuffer = ~[float];
+type SamplesFn = fn~ (samples: &RingBuffer);
+
+enum Msg
+{
+ GetSamples(~str, SamplesFn), // sample set name, callback which receives samples
+}
+
+fn foo(name: ~str, samples_chan: Chan<Msg>) {
+ do task::spawn
+ |copy name|
+ {
+ let callback: SamplesFn =
+ |buffer|
+ {
+ for uint::range(0, buffer.len())
+ |i| {error!("%?: %f", i, buffer[i])}
+ };
+ samples_chan.send(GetSamples(copy name, callback));
+ };
+}
+
+fn main() {}
+
// Incorrect struct size computation in the FFI, because of not taking
// the alignment of elements into account.
-use libc::*;
+use core::libc::*;
struct KEYGEN {
hash_algorithm: [c_uint * 2],
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod buildings {
+ pub struct Tower { height: uint }
+}
+
+fn main() {
+ let sears = buildings::Tower { height: 1451 };
+ let h: uint = match sears {
+ buildings::Tower { height: h } => { h }
+ };
+
+ io::println(h.to_str());
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+
+fn vec_peek<T>(v: &r/[T]) -> Option< (&r/T, &r/[T]) > {
+ if v.len() == 0 {
+ None
+ } else {
+ let head = &v[0];
+ let tail = v.view(1, v.len());
+ Some( (head, tail) )
+ }
+}
+
+
+fn test_peek_empty_stack() {
+ let v : &[int] = &[];
+ assert (None == vec_peek(v));
+}
+
+fn test_peek_empty_unique() {
+ let v : ~[int] = ~[];
+ assert (None == vec_peek(v));
+}
+
+fn test_peek_empty_managed() {
+ let v : @[int] = @[];
+ assert (None == vec_peek(v));
+}
+
+
+fn main() {}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+type ErrPrinter = &fn(&str, &str);
+
+fn example_err(prog: &str, arg: &str) {
+ io::println(fmt!("%s: %s", prog, arg))
+}
+
+fn exit(+print: ErrPrinter, prog: &str, arg: &str) {
+ print(prog, arg);
+}
+
+struct X {
+ mut err: ErrPrinter
+}
+
+impl X {
+ fn boom() {
+ exit(self.err, "prog", "arg");
+ }
+}
+
+fn main(){
+ let val = &X{
+ err: example_err,
+ };
+ val.boom();
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deriving_eq]
+struct Bike {
+ name: ~str,
+}
+
+pub fn main() {
+ let town_bike = Bike { name: ~"schwinn" };
+ let my_bike = Bike { name: ~"surly" };
+
+ assert town_bike != my_bike;
+}
https://github.com/graydon/rust/issues/507
*/
-fn grandchild(c: core::oldcomm::Chan<int>) { core::oldcomm::send(c, 42); }
+fn grandchild(c: ::core::oldcomm::Chan<int>) { ::core::oldcomm::send(c, 42); }
-fn child(c: core::oldcomm::Chan<int>) {
+fn child(c: ::core::oldcomm::Chan<int>) {
task::spawn(|| grandchild(c) )
}
fn main() {
- let p = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
task::spawn(|| child(ch) );
- let x: int = core::oldcomm::recv(p);
+ let x: int = ::core::oldcomm::recv(p);
log(debug, x);
enum msg { closed, received(~[u8]), }
-fn producer(c: core::oldcomm::Chan<~[u8]>) {
- core::oldcomm::send(c, ~[1u8, 2u8, 3u8, 4u8]);
+fn producer(c: ::core::oldcomm::Chan<~[u8]>) {
+ ::core::oldcomm::send(c, ~[1u8, 2u8, 3u8, 4u8]);
let empty: ~[u8] = ~[];
- core::oldcomm::send(c, empty);
+ ::core::oldcomm::send(c, empty);
}
-fn packager(cb: core::oldcomm::Chan<core::oldcomm::Chan<~[u8]>>, msg: core::oldcomm::Chan<msg>) {
- let p: core::oldcomm::Port<~[u8]> = core::oldcomm::Port();
- core::oldcomm::send(cb, core::oldcomm::Chan(&p));
+fn packager(cb: ::core::oldcomm::Chan<::core::oldcomm::Chan<~[u8]>>, msg: ::core::oldcomm::Chan<msg>) {
+ let p: ::core::oldcomm::Port<~[u8]> = ::core::oldcomm::Port();
+ ::core::oldcomm::send(cb, ::core::oldcomm::Chan(&p));
loop {
debug!("waiting for bytes");
- let data = core::oldcomm::recv(p);
+ let data = ::core::oldcomm::recv(p);
debug!("got bytes");
if vec::len(data) == 0u {
debug!("got empty bytes, quitting");
}
debug!("sending non-empty buffer of length");
log(debug, vec::len(data));
- core::oldcomm::send(msg, received(data));
+ ::core::oldcomm::send(msg, received(data));
debug!("sent non-empty buffer");
}
debug!("sending closed message");
- core::oldcomm::send(msg, closed);
+ ::core::oldcomm::send(msg, closed);
debug!("sent closed message");
}
fn main() {
- let p: core::oldcomm::Port<msg> = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
- let recv_reader: core::oldcomm::Port<core::oldcomm::Chan<~[u8]>> = core::oldcomm::Port();
- let recv_reader_chan = core::oldcomm::Chan(&recv_reader);
+ let p: ::core::oldcomm::Port<msg> = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
+ let recv_reader: ::core::oldcomm::Port<::core::oldcomm::Chan<~[u8]>> = ::core::oldcomm::Port();
+ let recv_reader_chan = ::core::oldcomm::Chan(&recv_reader);
let pack = task::spawn(|| packager(recv_reader_chan, ch) );
- let source_chan: core::oldcomm::Chan<~[u8]> = core::oldcomm::recv(recv_reader);
+ let source_chan: ::core::oldcomm::Chan<~[u8]> = ::core::oldcomm::recv(recv_reader);
let prod = task::spawn(|| producer(source_chan) );
loop {
- let msg = core::oldcomm::recv(p);
+ let msg = ::core::oldcomm::recv(p);
match msg {
closed => { debug!("Got close message"); break; }
received(data) => {
fn a() {
fn doit() {
- fn b(c: core::oldcomm::Chan<core::oldcomm::Chan<int>>) {
- let p = core::oldcomm::Port();
- core::oldcomm::send(c, core::oldcomm::Chan(&p));
+ fn b(c: ::core::oldcomm::Chan<::core::oldcomm::Chan<int>>) {
+ let p = ::core::oldcomm::Port();
+ ::core::oldcomm::send(c, ::core::oldcomm::Chan(&p));
}
- let p = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
task::spawn(|| b(ch) );
- core::oldcomm::recv(p);
+ ::core::oldcomm::recv(p);
}
let mut i = 0;
while i < 100 {
--- /dev/null
+// xfail-test
+
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue_3882.rc
+extern mod linenoise;
+use linenoise::issue_3882::*;
+
+fn main() {}
-fn producer(c: core::oldcomm::Chan<~[u8]>) {
- core::oldcomm::send(c,
+fn producer(c: ::core::oldcomm::Chan<~[u8]>) {
+ ::core::oldcomm::send(c,
~[1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8,
13u8]);
}
fn main() {
- let p: core::oldcomm::Port<~[u8]> = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p: ::core::oldcomm::Port<~[u8]> = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
let prod = task::spawn(|| producer(ch) );
- let data: ~[u8] = core::oldcomm::recv(p);
+ let data: ~[u8] = ::core::oldcomm::recv(p);
}
// Verify that blocks can't interfere with each other.
fn two_blocks(a: fn(), b: fn()) { a(); b(); a(); b(); }
let q = ~50;
- two_blocks(|| { let a = q; assert *a == 50;},
- || { let a = q; assert *a == 50;});
+ two_blocks(|| { let a = copy q; assert *a == 50;},
+ || { let a = copy q; assert *a == 50;});
}
// except according to those terms.
fn main() {
- let p = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&p);
let mut y: int;
task::spawn(|| child(ch) );
- y = core::oldcomm::recv(p);
+ y = ::core::oldcomm::recv(p);
debug!("received 1");
log(debug, y);
assert (y == 10);
task::spawn(|| child(ch) );
- y = core::oldcomm::recv(p);
+ y = ::core::oldcomm::recv(p);
debug!("received 2");
log(debug, y);
assert (y == 10);
}
-fn child(c: core::oldcomm::Chan<int>) { core::oldcomm::send(c, 10); }
+fn child(c: ::core::oldcomm::Chan<int>) { ::core::oldcomm::send(c, 10); }
fn main() {
assert transform(Some(10)) == Some(~"11");
assert transform(None) == None;
- assert (~[~"hi"]).bind(|x| ~[x, x + ~"!"] ).bind(|x| ~[x, x + ~"?"] ) ==
+ assert (~[~"hi"])
+ .bind(|x| ~[copy x, x + ~"!"] )
+ .bind(|x| ~[copy x, x + ~"?"] ) ==
~[~"hi", ~"hi?", ~"hi!", ~"hi!?"];
}
}
}
+impl Point : ops::Not<Point> {
+ pure fn not(&self) -> Point {
+ Point {x: !self.x, y: !self.y }
+ }
+}
+
impl Point : ops::Index<bool,int> {
pure fn index(&self, +x: bool) -> int {
if x { self.x } else { self.y }
assert -p == Point {x: -11, y: -22};
assert p[true] == 11;
assert p[false] == 22;
+
+ let q = !p;
+ assert q.x == !(p.x);
+ assert q.y == !(p.y);
+
// Issue #1733
fn~(_x: int){}(p[true]);
}
use pipes::try_recv;
-type username = ~str;
-type password = ~str;
-type money = float;
-type amount = float;
+pub type username = ~str;
+pub type password = ~str;
+pub type money = float;
+pub type amount = float;
proto! bank (
login:send {
- login(username, password) -> login_response
+ login(::username, ::password) -> login_response
}
login_response:recv {
}
connected:send {
- deposit(money) -> connected,
- withdrawal(amount) -> withdrawal_response
+ deposit(::money) -> connected,
+ withdrawal(::amount) -> withdrawal_response
}
withdrawal_response:recv {
- money(money) -> connected,
+ money(::money) -> connected,
insufficient_funds -> connected
}
)
// This was generated initially by the pipe compiler, but it's been
// modified in hopefully straightforward ways.
mod pingpong {
- #[legacy_exports];
- use pipes::*;
+ use core::pipes::*;
+ use core::ptr;
- type packets = {
- // This is probably a resolve bug, I forgot to export packet,
- // but since I didn't import pipes::*, it worked anyway.
+ pub type packets = {
ping: Packet<ping>,
pong: Packet<pong>,
};
- fn init() -> (client::ping, server::ping) {
+ pub fn init() -> (client::ping, server::ping) {
let buffer = ~{
header: BufferHeader(),
data: {
ptr::addr_of(&(data.ping))
}
}
- enum ping = server::pong;
- enum pong = client::ping;
- mod client {
- #[legacy_exports];
- fn ping(+pipe: ping) -> pong {
+ pub enum ping = server::pong;
+ pub enum pong = client::ping;
+ pub mod client {
+ use core::pipes::*;
+ use core::ptr;
+
+ pub fn ping(+pipe: ping) -> pong {
{
let b = pipe.reuse_buffer();
let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
- let message = pingpong::ping(move s);
- pipes::send(move pipe, move message);
+ let message = ::pingpong::ping(move s);
+ ::pipes::send(move pipe, move message);
move c
}
}
- type ping = pipes::SendPacketBuffered<pingpong::ping,
- pingpong::packets>;
- type pong = pipes::RecvPacketBuffered<pingpong::pong,
- pingpong::packets>;
+ pub type ping = pipes::SendPacketBuffered<::pingpong::ping,
+ ::pingpong::packets>;
+ pub type pong = pipes::RecvPacketBuffered<::pingpong::pong,
+ ::pingpong::packets>;
}
- mod server {
- #[legacy_exports];
- type ping = pipes::RecvPacketBuffered<pingpong::ping,
- pingpong::packets>;
- fn pong(+pipe: pong) -> ping {
+ pub mod server {
+ use core::pipes::*;
+ use core::ptr;
+
+ pub type ping = pipes::RecvPacketBuffered<::pingpong::ping,
+ ::pingpong::packets>;
+ pub fn pong(+pipe: pong) -> ping {
{
let b = pipe.reuse_buffer();
let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
- let message = pingpong::pong(move s);
- pipes::send(move pipe, move message);
+ let message = ::pingpong::pong(move s);
+ ::pipes::send(move pipe, move message);
move c
}
}
- type pong = pipes::SendPacketBuffered<pingpong::pong,
- pingpong::packets>;
+ pub type pong = pipes::SendPacketBuffered<::pingpong::pong,
+ ::pingpong::packets>;
}
}
mod test {
- #[legacy_exports];
use pipes::recv;
use pingpong::{ping, pong};
- fn client(-chan: pingpong::client::ping) {
+ pub fn client(-chan: ::pingpong::client::ping) {
use pingpong::client;
let chan = client::ping(move chan); return;
log(error, "Received pong");
}
- fn server(-chan: pingpong::server::ping) {
+ pub fn server(-chan: ::pingpong::server::ping) {
use pingpong::server;
let ping(chan) = recv(move chan); return;
}
fn main() {
- let (client_, server_) = pingpong::init();
+ let (client_, server_) = ::pingpong::init();
let client_ = ~mut Some(move client_);
let server_ = ~mut Some(move server_);
do task::spawn |move client_| {
// An example to make sure the protocol parsing syntax extension works.
+use core::option;
proto! pingpong (
ping:send {
)
mod test {
- #[legacy_exports];
- use pipes::recv;
+ use core::pipes::recv;
use pingpong::{ping, pong};
- fn client(-chan: pingpong::client::ping) {
+ pub fn client(-chan: ::pingpong::client::ping) {
use pingpong::client;
let chan = client::ping(move chan);
log(error, ~"Received pong");
}
- fn server(-chan: pingpong::server::ping) {
+ pub fn server(-chan: ::pingpong::server::ping) {
use pingpong::server;
let ping(chan) = recv(move chan);
)
// Types and protocols
-struct Buffer {
+pub struct Buffer {
foo: (),
}
-impl Buffer : Drop {
+pub impl Buffer : Drop {
fn finalize(&self) {}
}
}
wait_buffer:recv {
- give_buffer(Buffer) -> release
+ give_buffer(::Buffer) -> release
}
release:send {
- release(Buffer) -> acquire
+ release(::Buffer) -> acquire
}
)
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-test
+enum Nil {Nil}
+struct Cons<T> {head:int, tail:T}
+trait Dot {fn dot(other:self) -> int;}
+impl Nil:Dot {
+ fn dot(_:Nil) -> int {0}
+}
+impl<T:Dot> Cons<T>:Dot {
+ fn dot(other:Cons<T>) -> int {
+ self.head * other.head + self.tail.dot(other.tail)
+ }
+}
+fn test<T:Dot> (n:int, i:int, first:T, second:T) ->int {
+ match n {
+ 0 => {first.dot(second)}
+ // Error message should be here. It should be a type error
+ // to instantiate `test` at a type other than T. (See #4287)
+ _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
+ }
+}
+fn main() {
+ let n = test(1, 0, Nil, Nil);
+ io::println(fmt!("%d", n));
+}
// xfail-fast
#[legacy_modes];
+use core::bool;
use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
use libc::c_void;
use vec::UnboxedVecRepr;
// Regression tests for circular_buffer when using a unit
// that has a size that is not a power of two
-// A 12-byte unit to core::oldcomm::send over the channel
+// A 12-byte unit to ::core::oldcomm::send over the channel
type record = {val1: u32, val2: u32, val3: u32};
// power of two so needs to be rounded up. Don't trigger any
// assertions.
fn test_init() {
- let myport = core::oldcomm::Port();
- let mychan = core::oldcomm::Chan(&myport);
+ let myport = ::core::oldcomm::Port();
+ let mychan = ::core::oldcomm::Chan(&myport);
let val: record = {val1: 0u32, val2: 0u32, val3: 0u32};
- core::oldcomm::send(mychan, val);
+ ::core::oldcomm::send(mychan, val);
}
// Dump lots of items into the channel so it has to grow.
// Don't trigger any assertions.
fn test_grow() {
- let myport = core::oldcomm::Port();
- let mychan = core::oldcomm::Chan(&myport);
+ let myport = ::core::oldcomm::Port();
+ let mychan = ::core::oldcomm::Chan(&myport);
for uint::range(0u, 100u) |i| {
let val: record = {val1: 0u32, val2: 0u32, val3: 0u32};
- core::oldcomm::send(mychan, val);
+ ::core::oldcomm::send(mychan, val);
}
}
// Don't allow the buffer to shrink below it's original size
fn test_shrink1() {
- let myport = core::oldcomm::Port();
- let mychan = core::oldcomm::Chan(&myport);
- core::oldcomm::send(mychan, 0i8);
- let x = core::oldcomm::recv(myport);
+ let myport = ::core::oldcomm::Port();
+ let mychan = ::core::oldcomm::Chan(&myport);
+ ::core::oldcomm::send(mychan, 0i8);
+ let x = ::core::oldcomm::recv(myport);
}
fn test_shrink2() {
- let myport = core::oldcomm::Port();
- let mychan = core::oldcomm::Chan(&myport);
+ let myport = ::core::oldcomm::Port();
+ let mychan = ::core::oldcomm::Chan(&myport);
for uint::range(0u, 100u) |_i| {
let val: record = {val1: 0u32, val2: 0u32, val3: 0u32};
- core::oldcomm::send(mychan, val);
+ ::core::oldcomm::send(mychan, val);
}
- for uint::range(0u, 100u) |_i| { let x = core::oldcomm::recv(myport); }
+ for uint::range(0u, 100u) |_i| { let x = ::core::oldcomm::recv(myport); }
}
// Test rotating the buffer when the unit size is not a power of two
fn test_rotate() {
- let myport = core::oldcomm::Port();
- let mychan = core::oldcomm::Chan(&myport);
+ let myport = ::core::oldcomm::Port();
+ let mychan = ::core::oldcomm::Chan(&myport);
for uint::range(0u, 100u) |i| {
let val = {val1: i as u32, val2: i as u32, val3: i as u32};
- core::oldcomm::send(mychan, val);
- let x = core::oldcomm::recv(myport);
+ ::core::oldcomm::send(mychan, val);
+ let x = ::core::oldcomm::recv(myport);
assert (x.val1 == i as u32);
assert (x.val2 == i as u32);
assert (x.val3 == i as u32);
// Test rotating and growing the buffer when
// the unit size is not a power of two
fn test_rotate_grow() {
- let myport = core::oldcomm::Port::<record>();
- let mychan = core::oldcomm::Chan(&myport);
+ let myport = ::core::oldcomm::Port::<record>();
+ let mychan = ::core::oldcomm::Chan(&myport);
for uint::range(0u, 10u) |j| {
for uint::range(0u, 10u) |i| {
let val: record =
{val1: i as u32, val2: i as u32, val3: i as u32};
- core::oldcomm::send(mychan, val);
+ ::core::oldcomm::send(mychan, val);
}
for uint::range(0u, 10u) |i| {
- let x = core::oldcomm::recv(myport);
+ let x = ::core::oldcomm::recv(myport);
assert (x.val1 == i as u32);
assert (x.val2 == i as u32);
assert (x.val3 == i as u32);
--- /dev/null
+trait MyTrait {
+ fn f(&self) -> Self;
+}
+
+struct S {
+ x: int
+}
+
+impl S : MyTrait {
+ fn f(&self) -> S {
+ S { x: 3 }
+ }
+}
+
+fn main() {}
+
}
fn main() {
- let p = core::oldcomm::Port();
- let c = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let c = ::core::oldcomm::Chan(&p);
do task::spawn() {
- let p = core::oldcomm::Port();
- c.send(core::oldcomm::Chan(&p));
+ let p = ::core::oldcomm::Port();
+ c.send(::core::oldcomm::Chan(&p));
let _r = p.recv();
}
// xfail-fast
#[legacy_modes];
-use a::*;
-
-trait plus {
+pub trait plus {
fn plus() -> int;
}
mod a {
- #[legacy_exports];
- impl uint: plus { fn plus() -> int { self as int + 20 } }
+ use plus;
+ pub impl uint: plus { fn plus() -> int { self as int + 20 } }
}
mod b {
- #[legacy_exports];
- impl ~str: plus { fn plus() -> int { 200 } }
+ use plus;
+ pub impl ~str: plus { fn plus() -> int { 200 } }
}
trait uint_utils {
--- /dev/null
+struct Foo {
+ x: &int
+}
+
+fn main() {
+ let f = Foo { x: @3 };
+ assert *f.x == 3;
+}
+
--- /dev/null
+pub mod a {
+ pub fn f() {}
+ pub mod b {
+ fn g() {
+ super::f();
+ }
+ }
+}
+
+fn main() {
+}
+
test06();
}
-fn test00_start(ch: core::oldcomm::Chan<int>, message: int, count: int) {
+fn test00_start(ch: ::core::oldcomm::Chan<int>, message: int, count: int) {
debug!("Starting test00_start");
let mut i: int = 0;
while i < count {
debug!("Sending Message");
- core::oldcomm::send(ch, message + 0);
+ ::core::oldcomm::send(ch, message + 0);
i = i + 1;
}
debug!("Ending test00_start");
let number_of_messages: int = 4;
debug!("Creating tasks");
- let po = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&po);
+ let po = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&po);
let mut i: int = 0;
let mut sum: int = 0;
for results.each |r| {
i = 0;
- while i < number_of_messages { sum += core::oldcomm::recv(po); i = i + 1; }
+ while i < number_of_messages { sum += ::core::oldcomm::recv(po); i = i + 1; }
}
for results.each |r| { r.recv(); }
}
fn test01() {
- let p = core::oldcomm::Port();
+ let p = ::core::oldcomm::Port();
debug!("Reading from a port that is never written to.");
- let value: int = core::oldcomm::recv(p);
+ let value: int = ::core::oldcomm::recv(p);
log(debug, value);
}
fn test02() {
- let p = core::oldcomm::Port();
- let c = core::oldcomm::Chan(&p);
+ let p = ::core::oldcomm::Port();
+ let c = ::core::oldcomm::Chan(&p);
debug!("Writing to a local task channel.");
- core::oldcomm::send(c, 42);
+ ::core::oldcomm::send(c, 42);
debug!("Reading from a local task port.");
- let value: int = core::oldcomm::recv(p);
+ let value: int = ::core::oldcomm::recv(p);
log(debug, value);
}
debug!("Finishing up.");
}
-fn test05_start(ch: core::oldcomm::Chan<int>) {
- core::oldcomm::send(ch, 10);
- core::oldcomm::send(ch, 20);
- core::oldcomm::send(ch, 30);
- core::oldcomm::send(ch, 30);
- core::oldcomm::send(ch, 30);
+fn test05_start(ch: ::core::oldcomm::Chan<int>) {
+ ::core::oldcomm::send(ch, 10);
+ ::core::oldcomm::send(ch, 20);
+ ::core::oldcomm::send(ch, 30);
+ ::core::oldcomm::send(ch, 30);
+ ::core::oldcomm::send(ch, 30);
}
fn test05() {
- let po = core::oldcomm::Port();
- let ch = core::oldcomm::Chan(&po);
+ let po = ::core::oldcomm::Port();
+ let ch = ::core::oldcomm::Chan(&po);
task::spawn(|| test05_start(ch) );
let mut value: int;
- value = core::oldcomm::recv(po);
- value = core::oldcomm::recv(po);
- value = core::oldcomm::recv(po);
+ value = ::core::oldcomm::recv(po);
+ value = ::core::oldcomm::recv(po);
+ value = ::core::oldcomm::recv(po);
log(debug, value);
}
+// xfail-fast
+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
dummy: (),
}
- pub impl Foo : base::HasNew<Foo> {
+ pub impl Foo : ::base::HasNew<Foo> {
static pure fn new() -> Foo {
unsafe { io::println("Foo"); }
Foo { dummy: () }
dummy: (),
}
- pub impl Bar : base::HasNew<Bar> {
+ pub impl Bar : ::base::HasNew<Bar> {
static pure fn new() -> Bar {
unsafe { io::println("Bar"); }
Bar { dummy: () }
fn main() {
let x = @[1, 2, 3];
match x {
- [2, .._] => core::util::unreachable(),
+ [2, .._] => ::core::util::unreachable(),
[1, ..tail] => {
assert tail == [2, 3];
}
- [_] => core::util::unreachable(),
- [] => core::util::unreachable()
+ [_] => ::core::util::unreachable(),
+ [] => ::core::util::unreachable()
}
let y = (~[(1, true), (2, false)], 0.5);
match y {
- ([_, _, _], 0.5) => core::util::unreachable(),
+ ([_, _, _], 0.5) => ::core::util::unreachable(),
([(1, a), (b, false), ..tail], _) => {
assert a == true;
assert b == 2;
assert tail.is_empty();
}
- ([..tail], _) => core::util::unreachable()
+ ([..tail], _) => ::core::util::unreachable()
}
}
if !x.is_empty() {
let el = match x {
[1, ..ref tail] => &tail[0],
- _ => core::util::unreachable()
+ _ => ::core::util::unreachable()
};
io::println(fmt!("%d", *el));
}
let x = [1, 2, 3, 4, 5];
match x {
[a, b, c, d, e, f] => {
- core::util::unreachable();
+ ::core::util::unreachable();
}
[a, b, c, d, e] => {
assert a == 1;
assert e == 5;
}
_ => {
- core::util::unreachable();
+ ::core::util::unreachable();
}
}
match tail {
[Foo { _ }, _, Foo { _ }, ..tail] => {
- core::util::unreachable();
+ ::core::util::unreachable();
}
[Foo { string: a }, Foo { string: b }] => {
assert a == ~"bar";
assert b == ~"baz";
}
_ => {
- core::util::unreachable();
+ ::core::util::unreachable();
}
}
}
_ => {
- core::util::unreachable();
+ ::core::util::unreachable();
}
}
}