step_msg "making directories"
for i in \
- doc \
+ doc doc/std \
+ nd nd/std \
rt rt/isaac rt/bigint rt/sync rt/test rt/arch/i386 \
rt/libuv rt/libuv/src/ares rt/libuv/src/eio rt/libuv/src/ev \
rustllvm dl \
--- /dev/null
+Format: 1.51
+
+# This is the Natural Docs languages file for this project. If you change
+# anything here, it will apply to THIS PROJECT ONLY. If you'd like to change
+# something for all your projects, edit the Languages.txt in Natural Docs'
+# Config directory instead.
+
+
+# You can prevent certain file extensions from being scanned like this:
+# Ignore Extensions: [extension] [extension] ...
+
+
+#-------------------------------------------------------------------------------
+# SYNTAX:
+#
+# Unlike other Natural Docs configuration files, in this file all comments
+# MUST be alone on a line. Some languages deal with the # character, so you
+# cannot put comments on the same line as content.
+#
+# Also, all lists are separated with spaces, not commas, again because some
+# languages may need to use them.
+#
+# Language: [name]
+# Alter Language: [name]
+# Defines a new language or alters an existing one. Its name can use any
+# characters. If any of the properties below have an add/replace form, you
+# must use that when using Alter Language.
+#
+# The language Shebang Script is special. It's entry is only used for
+# extensions, and files with those extensions have their shebang (#!) lines
+# read to determine the real language of the file. Extensionless files are
+# always treated this way.
+#
+# The language Text File is also special. It's treated as one big comment
+# so you can put Natural Docs content in them without special symbols. Also,
+# if you don't specify a package separator, ignored prefixes, or enum value
+# behavior, it will copy those settings from the language that is used most
+# in the source tree.
+#
+# Extensions: [extension] [extension] ...
+# [Add/Replace] Extensions: [extension] [extension] ...
+# Defines the file extensions of the language's source files. You can
+# redefine extensions found in the main languages file. You can use * to
+# mean any undefined extension.
+#
+# Shebang Strings: [string] [string] ...
+# [Add/Replace] Shebang Strings: [string] [string] ...
+# Defines a list of strings that can appear in the shebang (#!) line to
+# designate that it's part of the language. You can redefine strings found
+# in the main languages file.
+#
+# Ignore Prefixes in Index: [prefix] [prefix] ...
+# [Add/Replace] Ignored Prefixes in Index: [prefix] [prefix] ...
+#
+# Ignore [Topic Type] Prefixes in Index: [prefix] [prefix] ...
+# [Add/Replace] Ignored [Topic Type] Prefixes in Index: [prefix] [prefix] ...
+# Specifies prefixes that should be ignored when sorting symbols in an
+# index. Can be specified in general or for a specific topic type.
+#
+#------------------------------------------------------------------------------
+# For basic language support only:
+#
+# Line Comments: [symbol] [symbol] ...
+# Defines a space-separated list of symbols that are used for line comments,
+# if any.
+#
+# Block Comments: [opening sym] [closing sym] [opening sym] [closing sym] ...
+# Defines a space-separated list of symbol pairs that are used for block
+# comments, if any.
+#
+# Package Separator: [symbol]
+# Defines the default package separator symbol. The default is a dot.
+#
+# [Topic Type] Prototype Enders: [symbol] [symbol] ...
+# When defined, Natural Docs will attempt to get a prototype from the code
+# immediately following the topic type. It stops when it reaches one of
+# these symbols. Use \n for line breaks.
+#
+# Line Extender: [symbol]
+# Defines the symbol that allows a prototype to span multiple lines if
+# normally a line break would end it.
+#
+# Enum Values: [global|under type|under parent]
+# Defines how enum values are referenced. The default is global.
+# global - Values are always global, referenced as 'value'.
+# under type - Values are under the enum type, referenced as
+# 'package.enum.value'.
+# under parent - Values are under the enum's parent, referenced as
+# 'package.value'.
+#
+# Perl Package: [perl package]
+# Specifies the Perl package used to fine-tune the language behavior in ways
+# too complex to do in this file.
+#
+#------------------------------------------------------------------------------
+# For full language support only:
+#
+# Full Language Support: [perl package]
+# Specifies the Perl package that has the parsing routines necessary for full
+# language support.
+#
+#-------------------------------------------------------------------------------
+
+# The following languages are defined in the main file, if you'd like to alter
+# them:
+#
+# Text File, Shebang Script, C/C++, C#, Java, JavaScript, Perl, Python,
+# PHP, SQL, Visual Basic, Pascal, Assembly, Ada, Tcl, Ruby, Makefile,
+# ActionScript, ColdFusion, R, Fortran
+
+# If you add a language that you think would be useful to other developers
+# and should be included in Natural Docs by default, please e-mail it to
+# languages [at] naturaldocs [dot] org.
+
+
+Language: Rust
+
+ Extensions: rc rs
+ Line Comment: //
+ Block Comment: /* */
+ Package Separator: ::
+ Function Prototype Enders: ; {
+ Type Prototype Enders: ; }
+ Class Prototype Enders: {
--- /dev/null
+Format: 1.51
+
+# This is the Natural Docs topics file for this project. If you change anything
+# here, it will apply to THIS PROJECT ONLY. If you'd like to change something
+# for all your projects, edit the Topics.txt in Natural Docs' Config directory
+# instead.
+
+
+# If you'd like to prevent keywords from being recognized by Natural Docs, you
+# can do it like this:
+# Ignore Keywords: [keyword], [keyword], ...
+#
+# Or you can use the list syntax like how they are defined:
+# Ignore Keywords:
+# [keyword]
+# [keyword], [plural keyword]
+# ...
+
+
+#-------------------------------------------------------------------------------
+# SYNTAX:
+#
+# Topic Type: [name]
+# Alter Topic Type: [name]
+# Creates a new topic type or alters one from the main file. Each type gets
+# its own index and behavior settings. Its name can have letters, numbers,
+# spaces, and these charaters: - / . '
+#
+# Plural: [name]
+# Sets the plural name of the topic type, if different.
+#
+# Keywords:
+# [keyword]
+# [keyword], [plural keyword]
+# ...
+# Defines or adds to the list of keywords for the topic type. They may only
+# contain letters, numbers, and spaces and are not case sensitive. Plural
+# keywords are used for list topics. You can redefine keywords found in the
+# main topics file.
+#
+# Index: [yes|no]
+# Whether the topics get their own index. Defaults to yes. Everything is
+# included in the general index regardless of this setting.
+#
+# Scope: [normal|start|end|always global]
+# How the topics affects scope. Defaults to normal.
+# normal - Topics stay within the current scope.
+# start - Topics start a new scope for all the topics beneath it,
+# like class topics.
+# end - Topics reset the scope back to global for all the topics
+# beneath it.
+# always global - Topics are defined as global, but do not change the scope
+# for any other topics.
+#
+# Class Hierarchy: [yes|no]
+# Whether the topics are part of the class hierarchy. Defaults to no.
+#
+# Page Title If First: [yes|no]
+# Whether the topic's title becomes the page title if it's the first one in
+# a file. Defaults to no.
+#
+# Break Lists: [yes|no]
+# Whether list topics should be broken into individual topics in the output.
+# Defaults to no.
+#
+# Can Group With: [type], [type], ...
+# Defines a list of topic types that this one can possibly be grouped with.
+# Defaults to none.
+#-------------------------------------------------------------------------------
+
+# The following topics are defined in the main file, if you'd like to alter
+# their behavior or add keywords:
+#
+# Generic, Class, Interface, Section, File, Group, Function, Variable,
+# Property, Type, Constant, Enumeration, Event, Delegate, Macro,
+# Database, Database Table, Database View, Database Index, Database
+# Cursor, Database Trigger, Cookie, Build Target
+
+# If you add something that you think would be useful to other developers
+# and should be included in Natural Docs by default, please e-mail it to
+# topics [at] naturaldocs [dot] org.
+
+
+#Topic Type: Crate
+
+# Plural: Crates
+# Scope: Always Global
+
+# Keywords:
+# crate, crates
+
+Topic Type: Syntax Extension
+
+ Plural: Syntax Extensions
+ Scope: Always Global
+
+ Keywords:
+ syntax extension, syntax extensions
+
+#Alter Topic Type: Class
+
+# Keywords:
+# object, objects
+# tag, tags
+# resource, resources
+
+Topic Type: Module
+ Plural: Modules
+ Scope: Start
+ Class Hierarchy: Yes
+ Page Title If First: Yes
+
+ Keywords:
+ module, modules
+
+Topic Type: Object
+ Plural: Objects
+ Scope: Start
+ Class Hierarchy: Yes
+
+ Keywords:
+ obj, objs
+
+Topic Type: Tag
+ Plural: Tags
+ Scope: Start
+ Class Hierarchy: Yes
+
+ Keywords:
+ tag, tags
+
+#Alter Topic Type: Function
+
+# Scope: Start
+# predicate, predicates
+
+# Ignore Keywords:
+# method, methods
+# Keywords:
+# variant, variants
+
+Topic Type: Variant
+
+ Plural: Variants
+ Keywords:
+ variant, variants
+
+#Alter Topic Type: Type
+
+# Keywords:
+# tag, tags
+
+Topic Type: Predicate
+
+ Plural: Predicates
+ Break Lists: Yes
+
+ Keywords:
+ predicate, predicates
docsnap: doc/rust.pdf
@$(call E, snap: doc/rust-$(shell date +"%Y-%m-%d")-snap.pdf)
$(Q)mv $< doc/rust-$(shell date +"%Y-%m-%d")-snap.pdf
+
+doc/std/index.html: nd/std/Languages.txt nd/std/Topics.txt \
+ $(STDLIB_CRATE) $(STDLIB_INPUTS)
+ @$(call E, naturaldocs: $@)
+ naturaldocs -i $(S)src/lib -o HTML doc/std -p nd/std -r
+
+nd/std/Languages.txt: $(S)doc/Languages.txt
+ @$(call E, cp: $@)
+ $(Q)cp $< $@
+
+nd/std/Topics.txt: $(S)doc/Topics.txt
+ @$(call E, cp: $@)
+ $(Q)cp $< $@
+/*
+Module: bitv
+
+Bitvectors.
+*/
export t;
export create;
// an optimizing version of this module that produces a different obj
// for the case where nbits <= 32.
+/*
+Type: t
+
+The bitvector type.
+*/
type t = @{storage: [mutable uint], nbits: uint};
// FIXME: this should be a constant once they work
fn uint_bits() -> uint { ret 32u + (1u << 32u >> 27u); }
+/*
+Function: create
+
+Constructs a bitvector.
+
+Parameters:
+nbits - The number of bits in the bitvector
+init - If true then the bits are initialized to 1, otherwise 0
+*/
fn create(nbits: uint, init: bool) -> t {
let elt = if init { !0u } else { 0u };
let storage = vec::init_elt_mut::<uint>(elt, nbits / uint_bits() + 1u);
+/*
+Module: box
+*/
+
export ptr_eq;
+/*
+Function: ptr_eq
+
+Determine if two shared boxes point to the same object
+*/
fn ptr_eq<T>(a: @T, b: @T) -> bool {
let a_ptr: uint = unsafe::reinterpret_cast(a);
let b_ptr: uint = unsafe::reinterpret_cast(b);
+/*
+Module: char
+
+Utilities for manipulating the char type
+*/
+
+/*
+Function: is_whitespace
+
+Indicates whether a character is whitespace.
+
+Whitespace characters include space (U+0020), tab (U+0009), line feed
+(U+000A), carriage return (U+000D), and a number of less common
+ASCII and unicode characters.
+*/
pure fn is_whitespace(c: char) -> bool {
const ch_space: char = '\u0020';
const ch_ogham_space_mark: char = '\u1680';
+/*
+Module: comm
+
+Communication between tasks
+
+Communication between tasks is facilitated by ports (in the receiving task),
+and channels (in the sending task). Any number of channels may feed into a
+single port.
+
+Example:
+
+> use std::task;
+> use std::comm;
+>
+> let p = comm::port();
+> task::spawn(comm::chan(p), fn (c: chan<str>) {
+> comm::send(c, "Hello, World");
+> });
+>
+> log comm::recv(p);
+
+*/
+
import sys;
import ptr;
import unsafe;
// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
-tag chan<unique T> { chan_t(task::task, port_id); }
+/*
+Type: chan
+
+A handle through which data may be sent.
+
+Each channel is associated with a single <port>.
+*/
+tag chan<unique T> {
+ chan_t(task::task, port_id);
+}
resource port_ptr(po: *rustrt::rust_port) {
rustrt::drop_port(po);
rustrt::del_port(po);
}
+/*
+Type: port
+
+A handle through which data may be received.
+
+Ports may be associated with multiple <chan>s.
+*/
tag port<unique T> { port_t(@port_ptr); }
+/*
+Function: send
+
+Sends data over a channel.
+
+The sent data is moved into the channel, whereupon the caller loses access
+to it.
+*/
fn send<unique T>(ch: chan<T>, -data: T) {
let chan_t(t, p) = ch;
rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
task::yield();
}
+/*
+Function: port
+
+Constructs a port.
+*/
fn port<unique T>() -> port<T> {
- let p = rustrt::new_port(sys::size_of::<T>());
- ret port_t(@port_ptr(p));
+ port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}
-fn recv<unique T>(p: port<T>) -> T {
- ret rusti::recv(***p);
-}
+/*
+Function: recv
+
+Receive from a port.
+*/
+fn recv<unique T>(p: port<T>) -> T { ret rusti::recv(***p) }
+
+/*
+Function: chan
+Constructs a channel.
+*/
fn chan<unique T>(p: port<T>) -> chan<T> {
- let id = rustrt::get_port_id(***p);
- ret chan_t(task::get_task_id(), id);
+ chan_t(task::get_task_id(), rustrt::get_port_id(***p))
}
-// FIXME: This can't be right
+/*
+Module: ctypes
+
+Definitions useful for C interop
+*/
+
+/* Type: size_t */
type size_t = uint;
+/* Type: ssize_t */
type ssize_t = int;
-
+/* Type: uint32_t */
type uint32_t = u32;
+/*
+Module: deque
+A deque. Untested as of yet. Likely buggy.
+*/
-
-/**
- * A deque, for fun. Untested as of yet. Likely buggy.
- */
-type t<T> =
- obj {
- fn size() -> uint;
- fn add_front(T);
- fn add_back(T);
- fn pop_front() -> T;
- fn pop_back() -> T;
- fn peek_front() -> T;
- fn peek_back() -> T;
- fn get(int) -> T;
+/*
+Object: t
+*/
+type t<T> = obj {
+ // Method: size
+ fn size() -> uint;
+ // Method: add_front
+ fn add_front(T);
+ // Method: add_back
+ fn add_back(T);
+ // Method: pop_front
+ fn pop_front() -> T;
+ // Method: pop_back
+ fn pop_back() -> T;
+ // Method: peek_front
+ fn peek_front() -> T;
+ // Method: peek_back
+ fn peek_back() -> T;
+ // Method: get
+ fn get(int) -> T;
};
+/*
+Section: Functions
+*/
+
+/*
+Function: create
+*/
fn create<T>() -> t<T> {
type cell<T> = option::t<T>;
+/*
+Module: either
+
+A type that represents one of two alternatives
+*/
import option;
import option::{some, none};
-tag t<T, U> { left(T); right(U); }
+/*
+Tag: t
+
+The either type
+*/
+tag t<T, U> {
+ /* Variant: left */
+ left(T);
+ /* Variant: right */
+ right(U);
+}
+
+/* Section: Operations */
+
+/*
+Function: either
+
+Applies a function based on the given either value
+If `value` is left(T) then `f_left` is applied to its contents, if
+`value` is right(U) then `f_right` is applied to its contents, and
+the result is returned.
+*/
fn either<T, U,
V>(f_left: block(T) -> V, f_right: block(U) -> V, value: t<T, U>) ->
V {
alt value { left(l) { f_left(l) } right(r) { f_right(r) } }
}
+/*
+Function: lefts
+
+Extracts from a vector of either all the left values.
+*/
fn lefts<T, U>(eithers: [t<T, U>]) -> [T] {
let result: [T] = [];
for elt: t<T, U> in eithers {
ret result;
}
+/*
+Function: rights
+
+Extracts from a vector of either all the right values
+*/
fn rights<T, U>(eithers: [t<T, U>]) -> [U] {
let result: [U] = [];
for elt: t<T, U> in eithers {
ret result;
}
+/*
+Function: partition
+
+Extracts from a vector of either all the left values and right values
+
+Returns a structure containing a vector of left values and a vector of
+right values.
+*/
fn partition<T, U>(eithers: [t<T, U>]) -> {lefts: [T], rights: [U]} {
let lefts: [T] = [];
let rights: [U] = [];
}
ret {lefts: lefts, rights: rights};
}
+
//
// Local Variables:
// mode: rust
+/*
+Syntax Extension: fmt
+Format a string
+
+The 'fmt' extension is modeled on the posix printf system.
+
+A posix conversion ostensibly looks like this
+
+> %[parameter][flags][width][.precision][length]type
+
+Given the different numeric type bestiary we have, we omit the 'length'
+parameter and support slightly different conversions for 'type'
+
+> %[parameter][flags][width][.precision]type
+
+we also only support translating-to-rust a tiny subset of the possible
+combinations at the moment.
+
+Example:
+
+log #fmt("hello, %s!", "world");
+
+*/
-/* The 'fmt' extension is modeled on the posix printf system.
- *
- * A posix conversion ostensibly looks like this:
- *
- * %[parameter][flags][width][.precision][length]type
- *
- * Given the different numeric type bestiary we have, we omit the 'length'
- * parameter and support slightly different conversions for 'type':
- *
- * %[parameter][flags][width][.precision]type
- *
- * we also only support translating-to-rust a tiny subset of the possible
- * combinations at the moment.
- */
import option::{some, none};
+/*
+Module: float
+*/
+
/**
- * String conversions
+ * Section: String Conversions
*/
+/*
+Function: to_str
+
+Converts a float to a string
+
+Parameters:
+
+num - The float value
+digits: The number of significant digits
+*/
fn to_str(num: float, digits: uint) -> str {
let accum = if num < 0.0 { num = -num; "-" } else { "" };
let trunc = num as uint;
ret accum;
}
-/**
- * Convert a string to a float
- *
- * This function accepts strings such as
- * * "3.14"
- * * "+3.14", equivalent to "3.14"
- * * "-3.14"
- * * "2.5E10", or equivalently, "2.5e10"
- * * "2.5E-10"
- * * "", or, equivalently, "." (understood as 0)
- * * "5."
- * * ".5", or, equivalently, "0.5"
- *
- * @param num A string, possibly empty.
- * @return [NaN] if the string did not represent a valid number.
- * @return Otherwise, the floating-point number represented [num].
- */
+/*
+Function: from_str
+
+Convert a string to a float
+
+This function accepts strings such as
+* "3.14"
+* "+3.14", equivalent to "3.14"
+* "-3.14"
+* "2.5E10", or equivalently, "2.5e10"
+* "2.5E-10"
+* "", or, equivalently, "." (understood as 0)
+* "5."
+* ".5", or, equivalently, "0.5"
+
+Parameters:
+
+num - A string, possibly empty.
+
+Returns:
+
+<NaN> If the string did not represent a valid number.
+Otherwise, the floating-point number represented [num].
+*/
fn from_str(num: str) -> float {
let pos = 0u; //Current byte position in the string.
//Used to walk the string in O(n).
}
/**
- * Arithmetics
+ * Section: Arithmetics
*/
-/**
- * Compute the exponentiation of an integer by another integer as a float.
- *
- *
- * @param x The base.
- * @param pow The exponent.
- * @return [NaN] of both [x] and [pow] are [0u], otherwise [x^pow].
- */
+/*
+Function: pow_uint_to_uint_as_float
+
+Compute the exponentiation of an integer by another integer as a float.
+
+Parameters:
+x - The base.
+pow - The exponent.
+
+Returns:
+<NaN> of both `x` and `pow` are `0u`, otherwise `x^pow`.
+*/
fn pow_uint_to_uint_as_float(x: uint, pow: uint) -> float {
if x == 0u {
if pow == 0u {
/**
- * Constants
+ * Section: Constants
*/
//TODO: Once this is possible, replace the body of these functions
//by an actual constant.
+/* Function: NaN */
fn NaN() -> float {
ret 0./0.;
}
+/* Function: infinity */
fn infinity() -> float {
ret 1./0.;
}
+/* Function: neg_infinity */
fn neg_infinity() -> float {
ret -1./0.;
}
+/*
+Module: fs
+
+File system manipulation
+*/
import os::getcwd;
import os_fs;
fn rust_file_is_dir(path: str::sbuf) -> int;
}
+/*
+Function: path_sep
+
+Get the default path separator for the host platform
+*/
fn path_sep() -> str { ret str::from_char(os_fs::path_sep); }
+// FIXME: This type should probably be constrained
+/*
+Type: path
+
+A path or fragment of a filesystem path
+*/
type path = str;
+/*
+Function: dirname
+
+Get the directory portion of a path
+
+Returns all of the path up to, but excluding, the final path separator.
+The dirname of "/usr/share" will be "/usr", but the dirname of
+"/usr/share/" is "/usr/share".
+
+If the path is not prefixed with a directory, then "." is returned.
+*/
fn dirname(p: path) -> path {
let i: int = str::rindex(p, os_fs::path_sep as u8);
if i == -1 {
ret str::substr(p, 0u, i as uint);
}
+/*
+Function: basename
+
+Get the file name portion of a path
+
+Returns the portion of the path after the final path separator.
+The basename of "/usr/share" will be "share". If there are no
+path separators in the path then the returned path is identical to
+the provided path. If an empty path is provided or the path ends
+with a path separator then an empty path is returned.
+*/
fn basename(p: path) -> path {
let i: int = str::rindex(p, os_fs::path_sep as u8);
if i == -1 {
// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
+/*
+Function: connect
+
+Connects to path segments
+
+Given paths `pre` and `post` this function will return a path
+that is equal to `post` appended to `pre`, inserting a path separator
+between the two as needed.
+*/
fn connect(pre: path, post: path) -> path {
let len = str::byte_len(pre);
ret if pre[len - 1u] == os_fs::path_sep as u8 {
} else { pre + path_sep() + post };
}
+/*
+Function: connect_many
+
+Connects a vector of path segments into a single path.
+
+Inserts path separators as needed.
+*/
fn connect_many(paths: [path]) : vec::is_not_empty(paths) -> path {
ret if vec::len(paths) == 1u {
paths[0]
}
}
+/*
+Function: file_id_dir
+
+Indicates whether a path represents a directory.
+*/
fn file_is_dir(p: path) -> bool {
ret str::as_buf(p, {|buf| rustrt::rust_file_is_dir(buf) != 0 });
}
+/*
+Function: list_dir
+
+Lists the contents of a directory.
+*/
fn list_dir(p: path) -> [str] {
let p = p;
let pl = str::byte_len(p);
ret full_paths;
}
+/*
+Function: path_is_absolute
+
+Indicates whether a path is absolute.
+
+A path is considered absolute if it begins at the filesystem root ("/") or,
+on Windows, begins with a drive letter.
+*/
fn path_is_absolute(p: path) -> bool { ret os_fs::path_is_absolute(p); }
// FIXME: under Windows, we should prepend the current drive letter to paths
// that start with a slash.
+/*
+Function: make_absolute
+
+Convert a relative path to an absolute path
+
+If the given path is relative, return it prepended with the current working
+directory. If the given path is already an absolute path, return it
+as is.
+*/
fn make_absolute(p: path) -> path {
if path_is_absolute(p) { ret p; } else { ret connect(getcwd(), p); }
}
+/*
+Function: split
+
+Split a path into it's individual components
+
+Splits a given path by path separators and returns a vector containing
+each piece of the path. On Windows, if the path is absolute then
+the first element of the returned vector will be the drive letter
+followed by a colon.
+*/
fn split(p: path) -> [path] {
let split1 = str::split(p, os_fs::path_sep as u8);
let split2 = [];
ret split2;
}
+/*
+Function: normalize
+
+Removes extra "." and ".." entries from paths.
+
+Does not follow symbolic links.
+*/
fn normalize(p: path) -> path {
let s = split(p);
let s = strip_dots(s);
/*
+Module: fun_treemap
+
A functional key,value store that works on anything.
This works using a binary search tree. In the first version, it's a
export find;
export traverse;
+/* Section: Types */
+
+/*
+Type: treemap
+*/
+type treemap<K, V> = @tree_node<K, V>;
+
+/*
+Tag: tree_node
+*/
tag tree_node<K, V> {
empty;
node(@K, @V, @tree_node<K, V>, @tree_node<K, V>);
}
-type treemap<K, V> = @tree_node<K, V>;
+/* Section: Operations */
+
+/*
+Function: init
+Create a treemap
+*/
fn init<K, V>() -> treemap<K, V> { @empty }
+/*
+Function: insert
+
+Insert a value into the map
+*/
fn insert<K, V>(m: treemap<K, V>, k: K, v: V) -> treemap<K, V> {
@alt m {
@empty. { node(@k, @v, @empty, @empty) }
}
}
+/*
+Function: find
+
+Find a value based on the key
+*/
fn find<K, V>(m: treemap<K, V>, k: K) -> option<V> {
alt *m {
empty. { none }
}
}
+/*
+Function: traverse
-// Performs an in-order traversal
+Visit all pairs in the map in order.
+*/
fn traverse<K, V>(m: treemap<K, V>, f: fn(K, V)) {
alt *m {
empty. { }
+/*
+Module: generic_os
+
+Some miscellaneous platform functions.
+
+These should be rolled into another module.
+*/
+
import str::sbuf;
+// Wow, this is an ugly way to write doc comments
+
+#[cfg(bogus)]
+/*
+Function: getenv
+
+Get the value of an environment variable
+*/
+fn getenv(n: str) -> option::t<str> { }
+
+#[cfg(bogus)]
+/*
+Function: setenv
+
+Set the value of an environment variable
+*/
+fn setenv(n: str, v: str) { }
#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
+/*
+Module: getopts
+Simple getopt alternative. Construct a vector of options, either by using
+reqopt, optopt, and optflag or by building them from components yourself, and
+pass them to getopts, along with a vector of actual arguments (not including
+argv[0]). You'll either get a failure code back, or a match. You'll have to
+verify whether the amount of 'free' arguments in the match is what you
+expect. Use opt_* accessors to get argument values out of the match object.
+
+Single-character options are expected to appear on the command line with a
+single preceeding dash; multiple-character options are expected to be
+proceeded by two dashes. Options that expect an argument accept their argument
+following either a space or an equals sign.
+
+Example:
+
+The following example shows simple command line parsing for an application
+that requires an input file to be specified, accepts an optional output file
+name following -o, and accepts both -h and --help as optional flags.
+
+> fn main(args: [str]) {
+> let opts = [
+> optopt("o"),
+> optflag("h"),
+> optflag("help")
+> ];
+> let match = alt getopts(vec::shift(args), opts) {
+> success(m) { m }
+> failure(f) { fail fail_str(f) }
+> };
+> if opt_present(match, "h") || opt_present(match, "help") {
+> print_usage();
+> ret;
+> }
+> let output = opt_maybe_str(match, "o");
+> let input = if !vec::is_empty(match.free) {
+> match.free[0]
+> } else {
+> print_usage();
+> ret;
+> }
+> do_work(input, output);
+> }
+
+*/
-/* Simple getopt alternative. Construct a vector of options, either by using
- * reqopt, optopt, and optflag or by building them from components yourself,
- * and pass them to getopts, along with a vector of actual arguments (not
- * including argv[0]). You'll either get a failure code back, or a match.
- * You'll have to verify whether the amount of 'free' arguments in the match
- * is what you expect. Use opt_* accessors (bottom of the file) to get
- * argument values out of the match object.
- */
import option::{some, none};
export opt;
export reqopt;
tag occur { req; optional; multi; }
+/*
+Type: opt
+
+A description of a possible option
+*/
type opt = {name: name, hasarg: hasarg, occur: occur};
fn mkname(nm: str) -> name {
} else { long(nm) };
}
+/*
+Function: reqopt
+
+Create an option that is required and takes an argument
+*/
fn reqopt(name: str) -> opt {
ret {name: mkname(name), hasarg: yes, occur: req};
}
+/*
+Function: optopt
+
+Create an option that is optional and takes an argument
+*/
fn optopt(name: str) -> opt {
ret {name: mkname(name), hasarg: yes, occur: optional};
}
+/*
+Function: optflag
+
+Create an option that is optional and does not take an argument
+*/
fn optflag(name: str) -> opt {
ret {name: mkname(name), hasarg: no, occur: optional};
}
+/*
+Function: optflagopt
+
+Create an option that is optional and takes an optional argument
+*/
fn optflagopt(name: str) -> opt {
ret {name: mkname(name), hasarg: maybe, occur: optional};
}
+/*
+Function: optmulti
+
+Create an option that is optional, takes an argument, and may occur
+multiple times
+*/
fn optmulti(name: str) -> opt {
ret {name: mkname(name), hasarg: yes, occur: multi};
}
tag optval { val(str); given; }
+/*
+Type: match
+
+The result of checking command line arguments. Contains a vector
+of matches and a vector of free strings.
+*/
type match = {opts: [opt], vals: [mutable [optval]], free: [str]};
fn is_arg(arg: str) -> bool {
ret none::<uint>;
}
+/*
+Type: fail_
+
+The type returned when the command line does not conform to the
+expected format. Pass this value to <fail_str> to get an error message.
+*/
tag fail_ {
argument_missing(str);
unrecognized_option(str);
unexpected_argument(str);
}
+/*
+Function: fail_str
+
+Convert a <fail_> tag into an error string
+*/
fn fail_str(f: fail_) -> str {
ret alt f {
argument_missing(nm) { "Argument to option '" + nm + "' missing." }
};
}
+/*
+Type: result
+
+The result of parsing a command line with a set of options
+
+Variants:
+
+success(match) - Returned from getopts on success
+failure(fail_) - Returned from getopts on failure
+*/
tag result { success(match); failure(fail_); }
+/*
+Function: getopts
+
+Parse command line arguments according to the provided options
+
+Returns:
+
+success(match) - On success. Use functions such as <opt_present>
+ <opt_str>, etc. to interrogate results.
+failure(fail_) - On failure. Use <fail_str> to get an error message.
+*/
fn getopts(args: [str], opts: [opt]) -> result {
let n_opts = vec::len::<opt>(opts);
fn f(_x: uint) -> [optval] { ret []; }
fn opt_val(m: match, nm: str) -> optval { ret opt_vals(m, nm)[0]; }
+/*
+Function: opt_present
+
+Returns true if an option was matched
+*/
fn opt_present(m: match, nm: str) -> bool {
ret vec::len::<optval>(opt_vals(m, nm)) > 0u;
}
+/*
+Function: opt_str
+
+Returns the string argument supplied to a matching option
+
+Failure:
+
+- If the option was not matched
+- If the match did not take an argument
+*/
fn opt_str(m: match, nm: str) -> str {
ret alt opt_val(m, nm) { val(s) { s } _ { fail } };
}
+/*
+Function: opt_str
+
+Returns a vector of the arguments provided to all matches of the given option.
+Used when an option accepts multiple values.
+*/
fn opt_strs(m: match, nm: str) -> [str] {
let acc: [str] = [];
for v: optval in opt_vals(m, nm) {
ret acc;
}
+/*
+Function: opt_str
+
+Returns the string argument supplied to a matching option or none
+*/
fn opt_maybe_str(m: match, nm: str) -> option::t<str> {
let vals = opt_vals(m, nm);
if vec::len::<optval>(vals) == 0u { ret none::<str>; }
}
-/// Returns none if the option was not present, `def` if the option was
-/// present but no argument was provided, and the argument if the option was
-/// present and an argument was provided.
+/*
+Function: opt_default
+
+Returns the matching string, a default, or none
+
+Returns none if the option was not present, `def` if the option was
+present but no argument was provided, and the argument if the option was
+present and an argument was provided.
+*/
fn opt_default(m: match, nm: str, def: str) -> option::t<str> {
let vals = opt_vals(m, nm);
if vec::len::<optval>(vals) == 0u { ret none::<str>; }
+/*
+Module: int
+*/
+
+/*
+Function: max_value
+
+The maximum value of an integer
+*/
fn max_value() -> int {
ret min_value() - 1;
}
+/*
+Function: min_value
+
+The minumum value of an integer
+*/
fn min_value() -> int {
ret (-1 << (sys::size_of::<int>() * 8u as int - 1)) as int;
}
-
+/* Function: add */
pure fn add(x: int, y: int) -> int { ret x + y; }
+/* Function: sub */
pure fn sub(x: int, y: int) -> int { ret x - y; }
+/* Function: mul */
pure fn mul(x: int, y: int) -> int { ret x * y; }
+/* Function: div */
pure fn div(x: int, y: int) -> int { ret x / y; }
+/* Function: rem */
pure fn rem(x: int, y: int) -> int { ret x % y; }
+/* Predicate: lt */
pure fn lt(x: int, y: int) -> bool { ret x < y; }
+/* Predicate: le */
pure fn le(x: int, y: int) -> bool { ret x <= y; }
+/* Predicate: eq */
pure fn eq(x: int, y: int) -> bool { ret x == y; }
+/* Predicate: ne */
pure fn ne(x: int, y: int) -> bool { ret x != y; }
+/* Predicate: ge */
pure fn ge(x: int, y: int) -> bool { ret x >= y; }
+/* Predicate: gt */
pure fn gt(x: int, y: int) -> bool { ret x > y; }
+/* Predicate: positive */
pure fn positive(x: int) -> bool { ret x > 0; }
+/* Predicate: negative */
pure fn negative(x: int) -> bool { ret x < 0; }
+/* Predicate: nonpositive */
pure fn nonpositive(x: int) -> bool { ret x <= 0; }
+/* Predicate: nonnegative */
pure fn nonnegative(x: int) -> bool { ret x >= 0; }
// FIXME: Make sure this works with negative integers.
+/*
+Function: hash
+
+Produce a uint suitable for use in a hash table
+*/
fn hash(x: int) -> uint { ret x as uint; }
+// FIXME: This is redundant
fn eq_alias(x: int, y: int) -> bool { ret x == y; }
+/*
+Function: range
+
+Iterate over the range [`lo`..`hi`)
+*/
fn range(lo: int, hi: int, it: block(int)) {
while lo < hi { it(lo); lo += 1; }
}
+/*
+Function: parse_buf
+
+Parse a buffer of bytes
+
+Parameters:
+
+buf - A byte buffer
+radix - The base of the number
+
+Failure:
+
+buf must not be empty
+*/
fn parse_buf(buf: [u8], radix: uint) -> int {
if vec::len::<u8>(buf) == 0u {
log_err "parse_buf(): buf is empty";
fail;
}
+/*
+Function: from_str
+
+Parse a string to an int
+
+Failure:
+
+s must not be empty
+*/
fn from_str(s: str) -> int { parse_buf(str::bytes(s), 10u) }
+/*
+Function: to_str
+
+Convert to a string in a given base
+*/
fn to_str(n: int, radix: uint) -> str {
assert (0u < radix && radix <= 16u);
ret if n < 0 {
"-" + uint::to_str(-n as uint, radix)
} else { uint::to_str(n as uint, radix) };
}
+
+/*
+Function: str
+
+Convert to a string
+*/
fn str(i: int) -> str { ret to_str(i, 10u); }
+/*
+Function: pow
+
+Returns `base` raised to the power of `exponent`
+*/
fn pow(base: int, exponent: uint) -> int {
if exponent == 0u { ret 1; } //Not mathemtically true if [base == 0]
if base == 0 { ret 0; }
-
import os::libc;
native "c-stack-cdecl" mod rustrt {
-// lib/option::rs
+/*
+Module: option
-tag t<T> { none; some(T); }
+Represents the presence or absence of a value.
+Every option<T> value can either be some(T) or none. Where in other languages
+you might use a nullable type, in Rust you would use an option type.
+*/
+
+/*
+Tag: t
+
+The option type
+*/
+tag t<T> {
+ /* Variant: none */
+ none;
+ /* Variant: some */
+ some(T);
+}
+
+/* Section: Operations */
+
+/*
+Function: get
+
+Gets the value out of an option
+
+Failure:
+
+Fails if the value equals `none`.
+*/
fn get<T>(opt: t<T>) -> &T {
alt opt { some(x) { ret x; } none. { fail "option none"; } }
}
+/*
+*/
fn map<T, U>(f: block(T) -> U, opt: t<T>) -> t<U> {
alt opt { some(x) { some(f(x)) } none. { none } }
}
+/*
+Function: is_none
+
+Returns true if the option equals none
+*/
fn is_none<T>(opt: t<T>) -> bool {
alt opt { none. { true } some(_) { false } }
}
+/*
+Function: is_some
+
+Returns true if the option contains some value
+*/
fn is_some<T>(opt: t<T>) -> bool { !is_none(opt) }
+/*
+Function: from_maybe
+
+Returns the contained value or a default
+*/
fn from_maybe<T>(def: T, opt: t<T>) -> T {
alt opt { some(x) { x } none. { def } }
}
+/*
+Function: maybe
+
+Applies a function to the contained value or returns a default
+*/
fn maybe<T, U>(def: U, f: block(T) -> U, opt: t<T>) -> U {
alt opt { none. { def } some(t) { f(t) } }
}
-// Can be defined in terms of the above when/if we have const bind.
+// FIXME: Can be defined in terms of the above when/if we have const bind.
+/*
+Function: may
+
+Performs an operation on the contained value or does nothing
+*/
fn may<T>(f: block(T), opt: t<T>) {
alt opt { none. {/* nothing */ } some(t) { f(t); } }
}
-
#[link(name = "std",
vers = "0.1",
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
/*
+Module: treemap
+
A key,value store that works on anything.
This works using a binary search tree. In the first version, it's a
export find;
export traverse;
-tag tree_node<K, V> { empty; node(@K, @V, treemap<K, V>, treemap<K, V>); }
+/* Section: Types */
+/*
+Type: treemap
+*/
type treemap<K, V> = @mutable tree_node<K, V>;
+/*
+Tag: tree_node
+*/
+tag tree_node<K, V> { empty; node(@K, @V, treemap<K, V>, treemap<K, V>); }
+
+/* Section: Operations */
+
+/*
+Function: init
+
+Create a treemap
+*/
fn init<K, V>() -> treemap<K, V> { @mutable empty }
+/*
+Function: insert
+
+Insert a value into the map
+*/
fn insert<K, V>(m: treemap<K, V>, k: K, v: V) {
alt m {
@empty. { *m = node(@k, @v, @mutable empty, @mutable empty); }
}
}
+/*
+Function: find
+
+Find a value based on the key
+*/
fn find<K, V>(m: treemap<K, V>, k: K) -> option<V> {
alt *m {
empty. { none }
}
}
-// Performs an in-order traversal
+/*
+Function: traverse
+
+Visit all pairs in the map in order.
+*/
fn traverse<K, V>(m: treemap<K, V>, f: fn@(K, V)) {
alt *m {
empty. { }
-// Interior vector utility functions.
+/*
+Module: vec
+*/
import option::{some, none};
import uint::next_power_of_two;
count: uint) -> [T];
}
-/// Reserves space for `n` elements in the given vector.
+/*
+Function: reserve
+
+Reserves capacity for `n` elements in the given vector.
+
+If the capacity for `v` is already equal to or greater than the requested
+capacity, then no action is taken.
+
+Parameters:
+
+v - A vector
+n - The number of elements to reserve space for
+*/
fn reserve<T>(&v: [mutable? T], n: uint) {
rustrt::vec_reserve_shared(sys::get_type_desc::<T>(), v, n);
}
pure fn len<T>(v: [mutable? T]) -> uint { unchecked { rusti::vec_len(v) } }
+/*
+Type: init_op
+
+A function used to initialize the elements of a vector.
+*/
type init_op<T> = fn@(uint) -> T;
+/*
+Function: init_fn
+
+Creates and initializes an immutable vector.
+
+Creates an immutable vector of size `n_elts` and initializes the elements
+to the value returned by the function `op`.
+*/
fn init_fn<T>(op: init_op<T>, n_elts: uint) -> [T] {
let v = [];
reserve(v, n_elts);
}
// TODO: Remove me once we have slots.
+/*
+Function: init_fn
+
+Creates and initializes a mutable vector.
+
+Creates a mutable vector of size `n_elts` and initializes the elements to
+the value returned by the function `op`.
+*/
fn init_fn_mut<T>(op: init_op<T>, n_elts: uint) -> [mutable T] {
let v = [mutable];
reserve(v, n_elts);
ret v;
}
+/*
+Function: init_elt
+
+Creates and initializes an immutable vector.
+
+Creates an immutable vector of size `n_elts` and initializes the elements
+to the value `t`.
+*/
fn init_elt<T>(t: T, n_elts: uint) -> [T] {
let v = [];
reserve(v, n_elts);
}
// TODO: Remove me once we have slots.
+/*
+Function: init_elt_mut
+
+Creates and initializes a mutable vector.
+
+Creates a mutable vector of size `n_elts` and initializes the elements
+to the value `t`.
+*/
fn init_elt_mut<T>(t: T, n_elts: uint) -> [mutable T] {
let v = [mutable];
reserve(v, n_elts);
// FIXME: Possible typestate postcondition:
// len(result) == len(v) (needs issue #586)
+/*
+Function: to_mut
+
+Produces a mutable vector from an immutable vector.
+*/
fn to_mut<T>(v: [T]) -> [mutable T] {
let vres = [mutable];
for t: T in v { vres += [mutable t]; }
}
// Same comment as from_mut
+/*
+Function: from_mut
+
+Produces an immutable vector from a mutable vector.
+*/
fn from_mut<T>(v: [mutable T]) -> [T] {
let vres = [];
for t: T in v { vres += [t]; }
ret vres;
}
-// Predicates
+/*
+Predicate: is_empty
+
+Returns true if a vector contains no elements.
+*/
pure fn is_empty<T>(v: [mutable? T]) -> bool {
// FIXME: This would be easier if we could just call len
for t: T in v { ret false; }
ret true;
}
+/*
+Predicate: is_not_empty
+
+Returns true if a vector contains some elements.
+*/
pure fn is_not_empty<T>(v: [mutable? T]) -> bool { ret !is_empty(v); }
// Accessors
-/// Returns the first element of a vector
+/*
+Function: head
+
+Returns the first element of a vector
+
+Predicates:
+<is_not_empty> (v)
+*/
fn head<T>(v: [mutable? T]) : is_not_empty(v) -> T { ret v[0]; }
-/// Returns all but the first element of a vector
+/*
+Function: tail
+
+Returns all but the first element of a vector
+
+Predicates:
+<is_not_empty> (v)
+*/
fn tail<T>(v: [mutable? T]) : is_not_empty(v) -> [T] {
ret slice(v, 1u, len(v));
}
-/// Returns the last element of `v`.
+/*
+Function: last
+
+Returns the last element of `v`
+
+Returns:
+
+An option containing the last element of `v` if `v` is not empty, or
+none if `v` is empty.
+*/
fn last<T>(v: [mutable? T]) -> option::t<T> {
if len(v) == 0u { ret none; }
ret some(v[len(v) - 1u]);
}
-/// Returns the last element of a non-empty vector `v`.
+/*
+Function: last_total
+
+Returns the last element of a non-empty vector `v`
+
+Predicates:
+<is_not_empty> (v)
+*/
fn last_total<T>(v: [mutable? T]) : is_not_empty(v) -> T {
ret v[len(v) - 1u];
}
-/// Returns a copy of the elements from [`start`..`end`) from `v`.
+/*
+Function: slice
+
+Returns a copy of the elements from [`start`..`end`) from `v`.
+*/
fn slice<T>(v: [mutable? T], start: uint, end: uint) -> [T] {
assert (start <= end);
assert (end <= len(v));
}
// TODO: Remove me once we have slots.
+/*
+Function: slice_mut
+
+Returns a copy of the elements from [`start`..`end`) from `v`.
+*/
fn slice_mut<T>(v: [mutable? T], start: uint, end: uint) -> [mutable T] {
assert (start <= end);
assert (end <= len(v));
// Mutators
+/*
+Function: shift
+
+Removes the first element from a vector and return it
+*/
fn shift<T>(&v: [mutable? T]) -> T {
let ln = len::<T>(v);
assert (ln > 0u);
}
// TODO: Write this, unsafely, in a way that's not O(n).
+/*
+Function: pop
+
+Remove the last element from a vector and return it
+*/
fn pop<T>(&v: [mutable? T]) -> T {
let ln = len(v);
assert (ln > 0u);
// Appending
-/// Expands the given vector in-place by appending `n` copies of `initval`.
+/*
+Function: grow
+
+Expands a vector in place, initializing the new elements to a given value
+
+Parameters:
+
+v - The vector to grow
+n - The number of elements to add
+initval - The value for the new elements
+*/
fn grow<T>(&v: [T], n: uint, initval: T) {
reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u;
}
// TODO: Remove me once we have slots.
+// FIXME: Can't grow take a [mutable? T]
+/*
+Function: grow_mut
+
+Expands a vector in place, initializing the new elements to a given value
+
+Parameters:
+
+v - The vector to grow
+n - The number of elements to add
+initval - The value for the new elements
+*/
fn grow_mut<T>(&v: [mutable T], n: uint, initval: T) {
reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u;
while i < n { v += [mutable initval]; i += 1u; }
}
-/// Calls `f` `n` times and appends the results of these calls to the given
-/// vector.
+/*
+Function: grow_fn
+
+Expands a vector in place, initializing the new elements to the result of a
+function
+
+Function `init_fn` is called `n` times with the values [0..`n`)
+
+Parameters:
+
+v - The vector to grow
+n - The number of elements to add
+init_fn - A function to call to retreive each appended element's value
+*/
fn grow_fn<T>(&v: [T], n: uint, init_fn: fn(uint) -> T) {
reserve(v, next_power_of_two(len(v) + n));
let i: uint = 0u;
while i < n { v += [init_fn(i)]; i += 1u; }
}
-/// Sets the element at position `index` to `val`. If `index` is past the end
-/// of the vector, expands the vector by replicating `initval` to fill the
-/// intervening space.
+/*
+Function: grow_set
+
+Sets the value of a vector element at a given index, growing the vector as
+needed
+
+Sets the element at position `index` to `val`. If `index` is past the end
+of the vector, expands the vector by replicating `initval` to fill the
+intervening space.
+*/
fn grow_set<T>(&v: [mutable T], index: uint, initval: T, val: T) {
if index >= len(v) { grow_mut(v, index - len(v) + 1u, initval); }
v[index] = val;
// Functional utilities
+/*
+Function: map
+
+Apply a function to each element of a vector and return the results
+*/
fn map<T, U>(f: block(T) -> U, v: [mutable? T]) -> [U] {
let result = [];
reserve(result, len(v));
ret result;
}
+/*
+Function: map2
+
+Apply a function to each pair of elements and return the results
+*/
fn map2<T, U, V>(f: block(T, U) -> V, v0: [T], v1: [U]) -> [V] {
let v0_len = len::<T>(v0);
if v0_len != len::<U>(v1) { fail; }
ret u;
}
+/*
+Function: filter_map
+
+Apply a function to each element of a vector and return the results
+
+If function `f` returns `none` then that element is excluded from
+the resulting vector.
+*/
fn filter_map<T, U>(f: block(T) -> option::t<U>, v: [mutable? T]) -> [U] {
let result = [];
for elem: T in v {
ret result;
}
+/*
+Function: filter
+
+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.
+*/
fn filter<T>(f: block(T) -> bool, v: [mutable? T]) -> [T] {
let result = [];
for elem: T in v {
ret result;
}
+/*
+Function: foldl
+
+FIXME: This looks like it's actually foldr
+*/
fn foldl<T, U>(p: block(U, T) -> U, z: U, v: [mutable? T]) -> U {
let sz = len(v);
if sz == 0u { ret z; }
ret p(foldl(p, z, rest), first);
}
+/*
+Function: any
+
+Return true if a predicate matches any elements
+
+If the vector contains no elements then false is returned.
+*/
fn any<T>(f: block(T) -> bool, v: [T]) -> bool {
for elem: T in v { if f(elem) { ret true; } }
ret false;
}
+/*
+Function: all
+
+Return true if a predicate matches all elements
+
+If the vector contains no elements then true is returned.
+*/
fn all<T>(f: block(T) -> bool, v: [T]) -> bool {
for elem: T in v { if !f(elem) { ret false; } }
ret true;
}
+/*
+Function: member
+
+Return true if a vector contains an element with the given value
+*/
fn member<T>(x: T, v: [T]) -> bool {
for elt: T in v { if x == elt { ret true; } }
ret false;
}
+/*
+Function: count
+
+Returns the number of elements that are equal to a given value
+*/
fn count<T>(x: T, v: [mutable? T]) -> uint {
let cnt = 0u;
for elt: T in v { if x == elt { cnt += 1u; } }
ret cnt;
}
+/*
+Function: find
+
+Search for an element that matches a given predicate
+
+Apply function `f` to each element of `v`, starting from the first.
+When function `f` matches then an option containing the element
+is returned. If `f` matches no elements then none is returned.
+*/
fn find<T>(f: block(T) -> bool, v: [T]) -> option::t<T> {
for elt: T in v { if f(elt) { ret some(elt); } }
ret none;
}
+/*
+Function: position
+
+Find the first index containing a matching value
+
+Returns:
+
+option::some(uint) - The first index containing a matching value
+option::none - No elements matched
+*/
fn position<T>(x: T, v: [T]) -> option::t<uint> {
let i: uint = 0u;
while i < len(v) { if x == v[i] { ret some::<uint>(i); } i += 1u; }
ret none;
}
+/*
+Function: position_pred
+
+Find the first index for which the value matches some predicate
+*/
fn position_pred<T>(f: fn(T) -> bool, v: [T]) -> option::t<uint> {
let i: uint = 0u;
while i < len(v) { if f(v[i]) { ret some::<uint>(i); } i += 1u; }
ret none;
}
+/*
+Predicate: same_length
+
+Returns true if two vectors have the same length
+*/
pure fn same_length<T, U>(xs: [T], ys: [U]) -> bool {
vec::len(xs) == vec::len(ys)
}
// saying the two result lists have the same length -- or, could
// return a nominal record with a constraint saying that, instead of
// returning a tuple (contingent on issue #869)
+/*
+Function: unzip
+
+Convert a vector of pairs into a pair of vectors
+
+Returns a tuple containing two vectors where the i-th element of the first
+vector contains the first element of the i-th tuple of the input vector,
+and the i-th element of the second vector contains the second element
+of the i-th tuple of the input vector.
+*/
fn unzip<T, U>(v: [(T, U)]) -> ([T], [U]) {
let as = [], bs = [];
for (a, b) in v { as += [a]; bs += [b]; }
ret (as, bs);
}
+/*
+Function: zip
+
+Convert two vectors to a vector of pairs
+
+Returns a vector of tuples, where the i-th tuple contains contains the
+i-th elements from each of the input vectors.
+
+Preconditions:
+
+<same_length> (v, u)
+*/
fn zip<T, U>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] {
let zipped = [];
let sz = len(v), i = 0u;
ret zipped;
}
-// Swaps two elements in a vector
+/*
+Function: swap
+
+Swaps two elements in a vector
+
+Parameters:
+v - The input vector
+a - The index of the first element
+b - The index of the second element
+*/
fn swap<T>(v: [mutable T], a: uint, b: uint) {
let t: T = v[a];
v[a] = v[b];
v[b] = t;
}
-// In place vector reversal
+/*
+Function: reverse
+
+Reverse the order of elements in a vector, in place
+*/
fn reverse<T>(v: [mutable T]) {
let i: uint = 0u;
let ln = len::<T>(v);
}
-// Functional vector reversal. Returns a reversed copy of v.
+/*
+Function: reversed
+
+Returns a vector with the order of elements reversed
+*/
fn reversed<T>(v: [T]) -> [T] {
let rs: [T] = [];
let i = len::<T>(v);
ret rs;
}
-// Generating vecs.
+// FIXME: Seems like this should take char params. Maybe belongs in char
+/*
+Function: enum_chars
+
+Returns a vector containing a range of chars
+*/
fn enum_chars(start: u8, end: u8) : u8::le(start, end) -> [char] {
let i = start;
let r = [];
ret r;
}
+// FIXME: Probably belongs in uint. Compare to uint::range
+/*
+Function: enum_uints
+
+Returns a vector containing a range of uints
+*/
fn enum_uints(start: uint, end: uint) : uint::le(start, end) -> [uint] {
let i = start;
let r = [];
ret r;
}
+/*
+Function: eachi
+
+Iterates over a vector's elements and indexes
+
+Iterates over vector `v` and, for each element, calls function `f`
+with the element's value and index.
+*/
fn eachi<T>(f: block(T, uint) -> (), v: [mutable? T]) {
let i = 0u;
let l = len(v);
}
}
-// Iterate over a list with with the indexes
+/*
+Function: iter2
+
+FIXME: This is exactly the same as eachi
+*/
fn iter2<T>(v: [T], it: block(uint, T)) {
let i = 0u;
for x in v { it(i, x); i += 1u; }
}
+/*
+Function: to_ptr
+
+FIXME: We don't need this wrapper
+*/
+unsafe fn to_ptr<T>(v: [T]) -> *T { ret unsafe::to_ptr(v); }
+
+/*
+Module: unsafe
+*/
mod unsafe {
type vec_repr = {mutable fill: uint, mutable alloc: uint, data: u8};
+ /*
+ Function: from_buf
+
+ Constructs a vector from an unsafe pointer to a buffer
+
+ Parameters:
+
+ ptr - An unsafe pointer to a buffer of `T`
+ elts - The number of elements in the buffer
+ */
unsafe fn from_buf<T>(ptr: *T, elts: uint) -> [T] {
ret rustrt::vec_from_buf_shared(sys::get_type_desc::<T>(),
ptr, elts);
}
+ /*
+ Function: set_len
+
+ Sets the length of a vector
+
+ This well explicitly set the size of the vector, without actually
+ modifing its buffers, so it is up to the caller to ensure that
+ the vector is actually the specified size.
+ */
unsafe fn set_len<T>(&v: [T], new_len: uint) {
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).fill = new_len * sys::size_of::<T>();
}
+ /*
+ Function: to_ptr
+
+ Returns an unsafe pointer to the vector's buffer
+
+ The caller must ensure that the vector outlives the pointer this
+ function returns, or else it will end up pointing to garbage.
+
+ Modifying the vector may cause its buffer to be reallocated, which
+ would also make any pointers to it invalid.
+ */
unsafe fn to_ptr<T>(v: [T]) -> *T {
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
ret ::unsafe::reinterpret_cast(addr_of((**repr).data));
}
}
-unsafe fn to_ptr<T>(v: [T]) -> *T { ret unsafe::to_ptr(v); }
-
// Local Variables:
// mode: rust;
// fill-column: 78;