mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-18 06:56:59 +00:00
Begin documenting std and add doc generation using naturaldocs
Naturaldocs isn't really that great but it seems easier to get something working than with doxygen, for which we would need to convert rust code to something C++ish. We probably want to just write a rustdoc utility at some point.
This commit is contained in:
parent
013107a25c
commit
7ae757583a
3
configure
vendored
3
configure
vendored
@ -387,7 +387,8 @@ rm -f config.mk.bak
|
||||
|
||||
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 \
|
||||
|
124
doc/Languages.txt
Normal file
124
doc/Languages.txt
Normal file
@ -0,0 +1,124 @@
|
||||
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: {
|
159
doc/Topics.txt
Normal file
159
doc/Topics.txt
Normal file
@ -0,0 +1,159 @@
|
||||
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
|
13
mk/docs.mk
13
mk/docs.mk
@ -19,3 +19,16 @@ doc/%.html: %.texi doc/version.texi
|
||||
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 $< $@
|
||||
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
Module: bitv
|
||||
|
||||
Bitvectors.
|
||||
*/
|
||||
|
||||
export t;
|
||||
export create;
|
||||
@ -23,12 +28,26 @@ export eq_vec;
|
||||
// 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);
|
||||
|
@ -1,6 +1,15 @@
|
||||
/*
|
||||
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);
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
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';
|
||||
|
@ -1,3 +1,26 @@
|
||||
/*
|
||||
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;
|
||||
@ -30,31 +53,66 @@ type port_id = int;
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
@ -1,5 +1,12 @@
|
||||
// FIXME: This can't be right
|
||||
type size_t = uint;
|
||||
type ssize_t = int;
|
||||
/*
|
||||
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;
|
||||
|
@ -1,21 +1,38 @@
|
||||
/*
|
||||
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>;
|
||||
|
||||
|
@ -1,15 +1,46 @@
|
||||
/*
|
||||
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 {
|
||||
@ -18,6 +49,11 @@ fn lefts<T, U>(eithers: [t<T, U>]) -> [T] {
|
||||
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 {
|
||||
@ -26,6 +62,14 @@ fn rights<T, U>(eithers: [t<T, U>]) -> [U] {
|
||||
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] = [];
|
||||
@ -34,6 +78,7 @@ fn partition<T, U>(eithers: [t<T, U>]) -> {lefts: [T], rights: [U]} {
|
||||
}
|
||||
ret {lefts: lefts, rights: rights};
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
@ -1,19 +1,28 @@
|
||||
/*
|
||||
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};
|
||||
|
||||
|
||||
|
@ -1,7 +1,21 @@
|
||||
/*
|
||||
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;
|
||||
@ -19,23 +33,30 @@ fn to_str(num: float, digits: uint) -> str {
|
||||
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).
|
||||
@ -144,17 +165,21 @@ fn from_str(num: str) -> float {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
@ -177,20 +202,23 @@ fn pow_uint_to_uint_as_float(x: uint, pow: uint) -> float {
|
||||
|
||||
|
||||
/**
|
||||
* 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.;
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
/*
|
||||
Module: fs
|
||||
|
||||
File system manipulation
|
||||
*/
|
||||
|
||||
import os::getcwd;
|
||||
import os_fs;
|
||||
@ -6,10 +11,32 @@ native "c-stack-cdecl" mod rustrt {
|
||||
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 {
|
||||
@ -19,6 +46,17 @@ fn dirname(p: path) -> path {
|
||||
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 {
|
||||
@ -32,6 +70,15 @@ fn basename(p: path) -> path {
|
||||
|
||||
|
||||
// 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 {
|
||||
@ -41,6 +88,13 @@ fn connect(pre: path, post: path) -> path {
|
||||
} 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]
|
||||
@ -51,10 +105,20 @@ fn connect_many(paths: [path]) : vec::is_not_empty(paths) -> path {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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);
|
||||
@ -68,14 +132,41 @@ fn list_dir(p: path) -> [str] {
|
||||
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 = [];
|
||||
@ -85,6 +176,13 @@ fn split(p: path) -> [path] {
|
||||
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);
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
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
|
||||
@ -19,15 +21,35 @@ export insert;
|
||||
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) }
|
||||
@ -41,6 +63,11 @@ fn insert<K, V>(m: treemap<K, V>, k: K, v: V) -> treemap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 }
|
||||
@ -52,8 +79,11 @@ fn find<K, V>(m: treemap<K, V>, k: K) -> option<V> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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. { }
|
||||
|
@ -1,5 +1,30 @@
|
||||
/*
|
||||
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")]
|
||||
|
@ -1,13 +1,50 @@
|
||||
/*
|
||||
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;
|
||||
@ -34,6 +71,11 @@ tag hasarg { yes; no; maybe; }
|
||||
|
||||
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 {
|
||||
@ -42,28 +84,60 @@ 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 {
|
||||
@ -81,6 +155,12 @@ fn find_opt(opts: [opt], nm: name) -> option::t<uint> {
|
||||
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);
|
||||
@ -89,6 +169,11 @@ tag fail_ {
|
||||
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." }
|
||||
@ -103,8 +188,29 @@ fn fail_str(f: fail_) -> str {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
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 []; }
|
||||
@ -208,14 +314,35 @@ fn opt_vals(m: match, nm: str) -> [optval] {
|
||||
|
||||
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) {
|
||||
@ -224,6 +351,11 @@ fn opt_strs(m: match, nm: str) -> [str] {
|
||||
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>; }
|
||||
@ -231,9 +363,15 @@ fn opt_maybe_str(m: match, nm: str) -> option::t<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>; }
|
||||
|
@ -1,52 +1,105 @@
|
||||
/*
|
||||
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";
|
||||
@ -68,16 +121,41 @@ fn parse_buf(buf: [u8], radix: uint) -> int {
|
||||
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; }
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import os::libc;
|
||||
|
||||
native "c-stack-cdecl" mod rustrt {
|
||||
|
@ -1,30 +1,85 @@
|
||||
// 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); } }
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#[link(name = "std",
|
||||
vers = "0.1",
|
||||
uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
Module: treemap
|
||||
|
||||
A key,value store that works on anything.
|
||||
|
||||
This works using a binary search tree. In the first version, it's a
|
||||
@ -16,12 +18,32 @@ export insert;
|
||||
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); }
|
||||
@ -36,6 +58,11 @@ fn insert<K, V>(m: treemap<K, V>, k: K, v: V) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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 }
|
||||
@ -51,7 +78,11 @@ fn find<K, V>(m: treemap<K, V>, k: K) -> option<V> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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. { }
|
||||
|
387
src/lib/vec.rs
387
src/lib/vec.rs
@ -1,4 +1,6 @@
|
||||
// Interior vector utility functions.
|
||||
/*
|
||||
Module: vec
|
||||
*/
|
||||
|
||||
import option::{some, none};
|
||||
import uint::next_power_of_two;
|
||||
@ -17,15 +19,40 @@ native "c-stack-cdecl" mod rustrt {
|
||||
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);
|
||||
@ -35,6 +62,14 @@ fn init_fn<T>(op: init_op<T>, n_elts: uint) -> [T] {
|
||||
}
|
||||
|
||||
// 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);
|
||||
@ -43,6 +78,14 @@ fn init_fn_mut<T>(op: init_op<T>, n_elts: uint) -> [mutable T] {
|
||||
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);
|
||||
@ -52,6 +95,14 @@ fn init_elt<T>(t: T, n_elts: uint) -> [T] {
|
||||
}
|
||||
|
||||
// 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);
|
||||
@ -62,6 +113,11 @@ fn init_elt_mut<T>(t: T, n_elts: uint) -> [mutable T] {
|
||||
|
||||
// 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]; }
|
||||
@ -69,43 +125,91 @@ fn to_mut<T>(v: [T]) -> [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));
|
||||
@ -117,6 +221,11 @@ fn slice<T>(v: [mutable? T], start: uint, end: uint) -> [T] {
|
||||
}
|
||||
|
||||
// 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));
|
||||
@ -130,6 +239,11 @@ fn slice_mut<T>(v: [mutable? T], start: uint, end: uint) -> [mutable T] {
|
||||
|
||||
// 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);
|
||||
@ -139,6 +253,11 @@ fn shift<T>(&v: [mutable? T]) -> T {
|
||||
}
|
||||
|
||||
// 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);
|
||||
@ -153,7 +272,17 @@ fn pop<T>(&v: [mutable? T]) -> T {
|
||||
|
||||
// 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;
|
||||
@ -161,23 +290,54 @@ fn grow<T>(&v: [T], n: uint, initval: T) {
|
||||
}
|
||||
|
||||
// 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;
|
||||
@ -186,6 +346,11 @@ fn grow_set<T>(&v: [mutable T], index: uint, initval: T, val: T) {
|
||||
|
||||
// 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));
|
||||
@ -196,6 +361,11 @@ fn map<T, U>(f: block(T) -> U, v: [mutable? T]) -> [U] {
|
||||
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; }
|
||||
@ -205,6 +375,14 @@ fn map2<T, U, V>(f: block(T, U) -> V, v0: [T], v1: [U]) -> [V] {
|
||||
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 {
|
||||
@ -217,6 +395,15 @@ fn filter_map<T, U>(f: block(T) -> option::t<U>, v: [mutable? T]) -> [U] {
|
||||
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 {
|
||||
@ -228,6 +415,11 @@ fn filter<T>(f: block(T) -> bool, v: [mutable? T]) -> [T] {
|
||||
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; }
|
||||
@ -236,44 +428,97 @@ fn foldl<T, U>(p: block(U, T) -> U, z: U, v: [mutable? T]) -> U {
|
||||
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)
|
||||
}
|
||||
@ -282,12 +527,34 @@ pure fn same_length<T, U>(xs: [T], ys: [U]) -> bool {
|
||||
// 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;
|
||||
@ -296,14 +563,27 @@ fn zip<T, U>(v: [T], u: [U]) : same_length(v, u) -> [(T, U)] {
|
||||
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);
|
||||
@ -311,7 +591,11 @@ fn reverse<T>(v: [mutable T]) {
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
@ -321,7 +605,12 @@ fn reversed<T>(v: [T]) -> [T] {
|
||||
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 = [];
|
||||
@ -329,6 +618,12 @@ fn enum_chars(start: u8, end: u8) : u8::le(start, end) -> [char] {
|
||||
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 = [];
|
||||
@ -336,6 +631,14 @@ fn enum_uints(start: uint, end: uint) : uint::le(start, end) -> [uint] {
|
||||
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);
|
||||
@ -346,33 +649,75 @@ fn eachi<T>(f: block(T, uint) -> (), v: [mutable? T]) {
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
Loading…
Reference in New Issue
Block a user