commit b365552c825499b1452842a0fb1074267eb28af7 Author: Jake Goulding Date: Thu May 19 14:22:50 2016 -0400 Initial diff --git a/avr-core/.gitignore b/avr-core/.gitignore new file mode 100644 index 0000000..1e7caa9 --- /dev/null +++ b/avr-core/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target/ diff --git a/avr-core/Cargo.toml b/avr-core/Cargo.toml new file mode 100644 index 0000000..c97bd37 --- /dev/null +++ b/avr-core/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "avr-core" +version = "0.1.0" +authors = ["The Rust Project"] + +[dependencies] diff --git a/avr-core/src/clone.rs b/avr-core/src/clone.rs new file mode 100644 index 0000000..d869d8c --- /dev/null +++ b/avr-core/src/clone.rs @@ -0,0 +1,84 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The `Clone` trait for types that cannot be 'implicitly copied' +//! +//! In Rust, some simple types are "implicitly copyable" and when you +//! assign them or pass them as arguments, the receiver will get a copy, +//! leaving the original value in place. These types do not require +//! allocation to copy and do not have finalizers (i.e. they do not +//! contain owned boxes or implement `Drop`), so the compiler considers +//! them cheap and safe to copy. For other types copies must be made +//! explicitly, by convention implementing the `Clone` trait and calling +//! the `clone` method. + + +use marker::Sized; + +/// A common trait for cloning an object. +/// +/// This trait can be used with `#[derive]`. +pub trait Clone : Sized { + /// Returns a copy of the value. + /// + /// # Examples + /// + /// ``` + /// let hello = "Hello"; // &str implements Clone + /// + /// assert_eq!("Hello", hello.clone()); + /// ``` + fn clone(&self) -> Self; + + /// Performs copy-assignment from `source`. + /// + /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality, + /// but can be overridden to reuse the resources of `a` to avoid unnecessary + /// allocations. + #[inline(always)] + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } +} + +impl<'a, T: ?Sized> Clone for &'a T { + /// Returns a shallow copy of the reference. + #[inline] + fn clone(&self) -> &'a T { *self } +} + +macro_rules! clone_impl { + ($t:ty) => { + impl Clone for $t { + /// Returns a deep copy of the value. + #[inline] + fn clone(&self) -> $t { *self } + } + } +} + +clone_impl! { isize } +clone_impl! { i8 } +clone_impl! { i16 } +clone_impl! { i32 } +clone_impl! { i64 } + +clone_impl! { usize } +clone_impl! { u8 } +clone_impl! { u16 } +clone_impl! { u32 } +clone_impl! { u64 } + +clone_impl! { f32 } +clone_impl! { f64 } + +clone_impl! { () } +clone_impl! { bool } +clone_impl! { char } diff --git a/avr-core/src/cmp.rs b/avr-core/src/cmp.rs new file mode 100644 index 0000000..e4ee984 --- /dev/null +++ b/avr-core/src/cmp.rs @@ -0,0 +1,550 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Functionality for ordering and comparison. +//! +//! This module defines both `PartialOrd` and `PartialEq` traits which are used +//! by the compiler to implement comparison operators. Rust programs may +//! implement `PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators, +//! and may implement `PartialEq` to overload the `==` and `!=` operators. + + +use self::Ordering::*; + +use marker::Sized; +use option::Option::{self, Some}; + +/// Trait for equality comparisons which are [partial equivalence +/// relations](http://en.wikipedia.org/wiki/Partial_equivalence_relation). +/// +/// This trait allows for partial equality, for types that do not have a full +/// equivalence relation. For example, in floating point numbers `NaN != NaN`, +/// so floating point types implement `PartialEq` but not `Eq`. +/// +/// Formally, the equality must be (for all `a`, `b` and `c`): +/// +/// - symmetric: `a == b` implies `b == a`; and +/// - transitive: `a == b` and `b == c` implies `a == c`. +/// +/// Note that these requirements mean that the trait itself must be implemented +/// symmetrically and transitively: if `T: PartialEq` and `U: PartialEq` +/// then `U: PartialEq` and `T: PartialEq`. +/// +/// PartialEq only requires the `eq` method to be implemented; `ne` is defined +/// in terms of it by default. Any manual implementation of `ne` *must* respect +/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and +/// only if `a != b`. +/// +/// This trait can be used with `#[derive]`. +#[lang = "eq"] +pub trait PartialEq { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + fn eq(&self, other: &Rhs) -> bool; + + /// This method tests for `!=`. + #[inline] + fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } +} + +/// Trait for equality comparisons which are [equivalence relations]( +/// https://en.wikipedia.org/wiki/Equivalence_relation). +/// +/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must +/// be (for all `a`, `b` and `c`): +/// +/// - reflexive: `a == a`; +/// - symmetric: `a == b` implies `b == a`; and +/// - transitive: `a == b` and `b == c` implies `a == c`. +/// +/// This property cannot be checked by the compiler, and therefore `Eq` implies +/// `PartialEq`, and has no extra methods. +/// +/// This trait can be used with `#[derive]`. +pub trait Eq: PartialEq { + // FIXME #13101: this method is used solely by #[deriving] to + // assert that every component of a type implements #[deriving] + // itself, the current deriving infrastructure means doing this + // assertion without using a method on this trait is nearly + // impossible. + // + // This should never be implemented by hand. + #[doc(hidden)] + #[inline(always)] + fn assert_receiver_is_total_eq(&self) {} +} + +/// An `Ordering` is the result of a comparison between two values. +/// +/// # Examples +/// +/// ``` +/// use std::cmp::Ordering; +/// +/// let result = 1.cmp(&2); +/// assert_eq!(Ordering::Less, result); +/// +/// let result = 1.cmp(&1); +/// assert_eq!(Ordering::Equal, result); +/// +/// let result = 2.cmp(&1); +/// assert_eq!(Ordering::Greater, result); +/// ``` +#[derive(Clone, Copy, PartialEq)] +pub enum Ordering { + /// An ordering where a compared value is less [than another]. + Less = -1, + /// An ordering where a compared value is equal [to another]. + Equal = 0, + /// An ordering where a compared value is greater [than another]. + Greater = 1, +} + +// impl Ordering { +// unsafe fn from_i8_unchecked(v: i8) -> Ordering { +// mem::transmute(v) +// } + +// /// Reverse the `Ordering`. +// /// +// /// * `Less` becomes `Greater`. +// /// * `Greater` becomes `Less`. +// /// * `Equal` becomes `Equal`. +// /// +// /// # Examples +// /// +// /// Basic behavior: +// /// +// /// ``` +// /// use std::cmp::Ordering; +// /// +// /// assert_eq!(Ordering::Less.reverse(), Ordering::Greater); +// /// assert_eq!(Ordering::Equal.reverse(), Ordering::Equal); +// /// assert_eq!(Ordering::Greater.reverse(), Ordering::Less); +// /// ``` +// /// +// /// This method can be used to reverse a comparison: +// /// +// /// ``` +// /// let mut data: &mut [_] = &mut [2, 10, 5, 8]; +// /// +// /// // sort the array from largest to smallest. +// /// data.sort_by(|a, b| a.cmp(b).reverse()); +// /// +// /// let b: &mut [_] = &mut [10, 8, 5, 2]; +// /// assert!(data == b); +// /// ``` +// #[inline] +// pub fn reverse(self) -> Ordering { +// unsafe { +// // this compiles really nicely (to a single instruction); +// // an explicit match has a pile of branches and +// // comparisons. +// // +// // NB. it is safe because of the explicit discriminants +// // given above. +// Ordering::from_i8_unchecked(-(self as i8)) +// } +// } +// } + +/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order). +/// +/// An order is a total order if it is (for all `a`, `b` and `c`): +/// +/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and +/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. +/// +/// When this trait is `derive`d, it produces a lexicographic ordering. +/// +/// This trait can be used with `#[derive]`. +pub trait Ord: Eq + PartialOrd { + /// This method returns an `Ordering` between `self` and `other`. + /// + /// By convention, `self.cmp(&other)` returns the ordering matching the expression + /// `self other` if true. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// assert_eq!(5.cmp(&10), Ordering::Less); + /// assert_eq!(10.cmp(&5), Ordering::Greater); + /// assert_eq!(5.cmp(&5), Ordering::Equal); + /// ``` + fn cmp(&self, other: &Self) -> Ordering; +} + +impl Eq for Ordering {} + +impl Ord for Ordering { + #[inline] + fn cmp(&self, other: &Ordering) -> Ordering { + (*self as i32).cmp(&(*other as i32)) + } +} + +impl PartialOrd for Ordering { + #[inline] + fn partial_cmp(&self, other: &Ordering) -> Option { + (*self as i32).partial_cmp(&(*other as i32)) + } +} + +/// Trait for values that can be compared for a sort-order. +/// +/// The comparison must satisfy, for all `a`, `b` and `c`: +/// +/// - antisymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and +/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. +/// +/// Note that these requirements mean that the trait itself must be implemented symmetrically and +/// transitively: if `T: PartialOrd` and `U: PartialOrd` then `U: PartialOrd` and `T: +/// PartialOrd`. +/// +/// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated +/// from default implementations. +/// +/// However it remains possible to implement the others separately for types which do not have a +/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 == +/// false` (cf. IEEE 754-2008 section 5.11). +/// +/// This trait can be used with `#[derive]`. +#[lang = "ord"] +pub trait PartialOrd: PartialEq { + /// This method returns an ordering between `self` and `other` values if one exists. + /// + /// # Examples + /// + /// ``` + /// use std::cmp::Ordering; + /// + /// let result = 1.0.partial_cmp(&2.0); + /// assert_eq!(result, Some(Ordering::Less)); + /// + /// let result = 1.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Equal)); + /// + /// let result = 2.0.partial_cmp(&1.0); + /// assert_eq!(result, Some(Ordering::Greater)); + /// ``` + /// + /// When comparison is impossible: + /// + /// ``` + /// let result = std::f64::NAN.partial_cmp(&1.0); + /// assert_eq!(result, None); + /// ``` + fn partial_cmp(&self, other: &Rhs) -> Option; + + /// This method tests less than (for `self` and `other`) and is used by the `<` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 < 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 < 1.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Some(Less) => true, + _ => false, + } + } + + /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 <= 2.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 <= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Some(Less) | Some(Equal) => true, + _ => false, + } + } + + /// This method tests greater than (for `self` and `other`) and is used by the `>` operator. + /// + /// # Examples + /// + /// ``` + /// let result = 1.0 > 2.0; + /// assert_eq!(result, false); + /// + /// let result = 2.0 > 2.0; + /// assert_eq!(result, false); + /// ``` + #[inline] + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Some(Greater) => true, + _ => false, + } + } + + /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=` + /// operator. + /// + /// # Examples + /// + /// ``` + /// let result = 2.0 >= 1.0; + /// assert_eq!(result, true); + /// + /// let result = 2.0 >= 2.0; + /// assert_eq!(result, true); + /// ``` + #[inline] + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Some(Greater) | Some(Equal) => true, + _ => false, + } + } +} + +/// Compare and return the minimum of two values. +/// +/// Returns the first argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// assert_eq!(1, cmp::min(1, 2)); +/// assert_eq!(2, cmp::min(2, 2)); +/// ``` +#[inline] +pub fn min(v1: T, v2: T) -> T { + if v1 <= v2 { v1 } else { v2 } +} + +/// Compare and return the maximum of two values. +/// +/// Returns the second argument if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// use std::cmp; +/// +/// assert_eq!(2, cmp::max(1, 2)); +/// assert_eq!(2, cmp::max(2, 2)); +/// ``` +#[inline] +pub fn max(v1: T, v2: T) -> T { + if v2 >= v1 { v2 } else { v1 } +} + +// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types +mod impls { + use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering}; + use cmp::Ordering::{Less, Greater, Equal}; + use marker::Sized; + use option::Option; + use option::Option::{Some, None}; + + macro_rules! partial_eq_impl { + ($($t:ty)*) => ($( + impl PartialEq for $t { + #[inline] + fn eq(&self, other: &$t) -> bool { (*self) == (*other) } + #[inline] + fn ne(&self, other: &$t) -> bool { (*self) != (*other) } + } + )*) + } + + impl PartialEq for () { + #[inline] + fn eq(&self, _other: &()) -> bool { true } + #[inline] + fn ne(&self, _other: &()) -> bool { false } + } + + partial_eq_impl! { + bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 + } + + macro_rules! eq_impl { + ($($t:ty)*) => ($( + impl Eq for $t {} + )*) + } + + eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } + + macro_rules! partial_ord_impl { + ($($t:ty)*) => ($( + impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &$t) -> Option { + match (self <= other, self >= other) { + (false, false) => None, + (false, true) => Some(Greater), + (true, false) => Some(Less), + (true, true) => Some(Equal), + } + } + #[inline] + fn lt(&self, other: &$t) -> bool { (*self) < (*other) } + #[inline] + fn le(&self, other: &$t) -> bool { (*self) <= (*other) } + #[inline] + fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } + #[inline] + fn gt(&self, other: &$t) -> bool { (*self) > (*other) } + } + )*) + } + + impl PartialOrd for () { + #[inline] + fn partial_cmp(&self, _: &()) -> Option { + Some(Equal) + } + } + + impl PartialOrd for bool { + #[inline] + fn partial_cmp(&self, other: &bool) -> Option { + (*self as u8).partial_cmp(&(*other as u8)) + } + } + + partial_ord_impl! { f32 f64 } + + macro_rules! ord_impl { + ($($t:ty)*) => ($( + impl PartialOrd for $t { + #[inline] + fn partial_cmp(&self, other: &$t) -> Option { + Some(self.cmp(other)) + } + #[inline] + fn lt(&self, other: &$t) -> bool { (*self) < (*other) } + #[inline] + fn le(&self, other: &$t) -> bool { (*self) <= (*other) } + #[inline] + fn ge(&self, other: &$t) -> bool { (*self) >= (*other) } + #[inline] + fn gt(&self, other: &$t) -> bool { (*self) > (*other) } + } + + impl Ord for $t { + #[inline] + fn cmp(&self, other: &$t) -> Ordering { + if *self == *other { Equal } + else if *self < *other { Less } + else { Greater } + } + } + )*) + } + + impl Ord for () { + #[inline] + fn cmp(&self, _other: &()) -> Ordering { Equal } + } + + impl Ord for bool { + #[inline] + fn cmp(&self, other: &bool) -> Ordering { + (*self as u8).cmp(&(*other as u8)) + } + } + + ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 } + + // & pointers + + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq { + #[inline] + fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) } + #[inline] + fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) } + } + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd { + #[inline] + fn partial_cmp(&self, other: &&'b B) -> Option { + PartialOrd::partial_cmp(*self, *other) + } + #[inline] + fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) } + #[inline] + fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) } + #[inline] + fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) } + #[inline] + fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) } + } + impl<'a, A: ?Sized> Ord for &'a A where A: Ord { + #[inline] + fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) } + } + impl<'a, A: ?Sized> Eq for &'a A where A: Eq {} + + // &mut pointers + + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } + #[inline] + fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } + } + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd { + #[inline] + fn partial_cmp(&self, other: &&'b mut B) -> Option { + PartialOrd::partial_cmp(*self, *other) + } + #[inline] + fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) } + #[inline] + fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) } + #[inline] + fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) } + #[inline] + fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) } + } + impl<'a, A: ?Sized> Ord for &'a mut A where A: Ord { + #[inline] + fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) } + } + impl<'a, A: ?Sized> Eq for &'a mut A where A: Eq {} + + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) } + #[inline] + fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) } + } + + impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq { + #[inline] + fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) } + #[inline] + fn ne(&self, other: &&'b B) -> bool { PartialEq::ne(*self, *other) } + } +} diff --git a/avr-core/src/intrinsics.rs b/avr-core/src/intrinsics.rs new file mode 100644 index 0000000..bd42906 --- /dev/null +++ b/avr-core/src/intrinsics.rs @@ -0,0 +1,585 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! rustc compiler intrinsics. +//! +//! The corresponding definitions are in librustc_trans/trans/intrinsic.rs. +//! +//! # Volatiles +//! +//! The volatile intrinsics provide operations intended to act on I/O +//! memory, which are guaranteed to not be reordered by the compiler +//! across other volatile intrinsics. See the LLVM documentation on +//! [[volatile]]. +//! +//! [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses +//! +//! # Atomics +//! +//! The atomic intrinsics provide common atomic operations on machine +//! words, with multiple possible memory orderings. They obey the same +//! semantics as C++11. See the LLVM documentation on [[atomics]]. +//! +//! [atomics]: http://llvm.org/docs/Atomics.html +//! +//! A quick refresher on memory ordering: +//! +//! * Acquire - a barrier for acquiring a lock. Subsequent reads and writes +//! take place after the barrier. +//! * Release - a barrier for releasing a lock. Preceding reads and writes +//! take place before the barrier. +//! * Sequentially consistent - sequentially consistent operations are +//! guaranteed to happen in order. This is the standard mode for working +//! with atomic types and is equivalent to Java's `volatile`. + +#![allow(missing_docs)] + +use marker::Sized; + +extern "rust-intrinsic" { + + // NB: These intrinsics take raw pointers because they mutate aliased + // memory, which is not valid for either `&` or `&mut`. + + pub fn atomic_cxchg(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_acq(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_rel(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_acqrel(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_failacq(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_acq_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchg_acqrel_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); + + pub fn atomic_cxchgweak(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_acq(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_rel(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_acqrel(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_failacq(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_acq_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); + pub fn atomic_cxchgweak_acqrel_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); + + pub fn atomic_load(src: *const T) -> T; + pub fn atomic_load_acq(src: *const T) -> T; + pub fn atomic_load_relaxed(src: *const T) -> T; + pub fn atomic_load_unordered(src: *const T) -> T; + + pub fn atomic_store(dst: *mut T, val: T); + pub fn atomic_store_rel(dst: *mut T, val: T); + pub fn atomic_store_relaxed(dst: *mut T, val: T); + pub fn atomic_store_unordered(dst: *mut T, val: T); + + pub fn atomic_xchg(dst: *mut T, src: T) -> T; + pub fn atomic_xchg_acq(dst: *mut T, src: T) -> T; + pub fn atomic_xchg_rel(dst: *mut T, src: T) -> T; + pub fn atomic_xchg_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_xchg_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_xadd(dst: *mut T, src: T) -> T; + pub fn atomic_xadd_acq(dst: *mut T, src: T) -> T; + pub fn atomic_xadd_rel(dst: *mut T, src: T) -> T; + pub fn atomic_xadd_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_xadd_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_xsub(dst: *mut T, src: T) -> T; + pub fn atomic_xsub_acq(dst: *mut T, src: T) -> T; + pub fn atomic_xsub_rel(dst: *mut T, src: T) -> T; + pub fn atomic_xsub_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_xsub_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_and(dst: *mut T, src: T) -> T; + pub fn atomic_and_acq(dst: *mut T, src: T) -> T; + pub fn atomic_and_rel(dst: *mut T, src: T) -> T; + pub fn atomic_and_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_and_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_nand(dst: *mut T, src: T) -> T; + pub fn atomic_nand_acq(dst: *mut T, src: T) -> T; + pub fn atomic_nand_rel(dst: *mut T, src: T) -> T; + pub fn atomic_nand_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_nand_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_or(dst: *mut T, src: T) -> T; + pub fn atomic_or_acq(dst: *mut T, src: T) -> T; + pub fn atomic_or_rel(dst: *mut T, src: T) -> T; + pub fn atomic_or_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_or_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_xor(dst: *mut T, src: T) -> T; + pub fn atomic_xor_acq(dst: *mut T, src: T) -> T; + pub fn atomic_xor_rel(dst: *mut T, src: T) -> T; + pub fn atomic_xor_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_xor_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_max(dst: *mut T, src: T) -> T; + pub fn atomic_max_acq(dst: *mut T, src: T) -> T; + pub fn atomic_max_rel(dst: *mut T, src: T) -> T; + pub fn atomic_max_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_max_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_min(dst: *mut T, src: T) -> T; + pub fn atomic_min_acq(dst: *mut T, src: T) -> T; + pub fn atomic_min_rel(dst: *mut T, src: T) -> T; + pub fn atomic_min_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_min_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_umin(dst: *mut T, src: T) -> T; + pub fn atomic_umin_acq(dst: *mut T, src: T) -> T; + pub fn atomic_umin_rel(dst: *mut T, src: T) -> T; + pub fn atomic_umin_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_umin_relaxed(dst: *mut T, src: T) -> T; + + pub fn atomic_umax(dst: *mut T, src: T) -> T; + pub fn atomic_umax_acq(dst: *mut T, src: T) -> T; + pub fn atomic_umax_rel(dst: *mut T, src: T) -> T; + pub fn atomic_umax_acqrel(dst: *mut T, src: T) -> T; + pub fn atomic_umax_relaxed(dst: *mut T, src: T) -> T; +} + +extern "rust-intrinsic" { + + pub fn atomic_fence(); + pub fn atomic_fence_acq(); + pub fn atomic_fence_rel(); + pub fn atomic_fence_acqrel(); + + /// A compiler-only memory barrier. + /// + /// Memory accesses will never be reordered across this barrier by the + /// compiler, but no instructions will be emitted for it. This is + /// appropriate for operations on the same thread that may be preempted, + /// such as when interacting with signal handlers. + pub fn atomic_singlethreadfence(); + pub fn atomic_singlethreadfence_acq(); + pub fn atomic_singlethreadfence_rel(); + pub fn atomic_singlethreadfence_acqrel(); + + /// Aborts the execution of the process. + pub fn abort() -> !; + + /// Tells LLVM that this point in the code is not reachable, + /// enabling further optimizations. + /// + /// NB: This is very different from the `unreachable!()` macro! + pub fn unreachable() -> !; + + /// Informs the optimizer that a condition is always true. + /// If the condition is false, the behavior is undefined. + /// + /// No code is generated for this intrinsic, but the optimizer will try + /// to preserve it (and its condition) between passes, which may interfere + /// with optimization of surrounding code and reduce performance. It should + /// not be used if the invariant can be discovered by the optimizer on its + /// own, or if it does not enable any significant optimizations. + pub fn assume(b: bool); + + /// Executes a breakpoint trap, for inspection by a debugger. + pub fn breakpoint(); + + /// The size of a type in bytes. + /// + /// More specifically, this is the offset in bytes between successive + /// items of the same type, including alignment padding. + pub fn size_of() -> usize; + + /// Moves a value to an uninitialized memory location. + /// + /// Drop glue is not run on the destination. + pub fn move_val_init(dst: *mut T, src: T); + + pub fn min_align_of() -> usize; + pub fn pref_align_of() -> usize; + + pub fn size_of_val(_: &T) -> usize; + pub fn min_align_of_val(_: &T) -> usize; + + /// Executes the destructor (if any) of the pointed-to value. + /// + /// This has two use cases: + /// + /// * It is *required* to use `drop_in_place` to drop unsized types like + /// trait objects, because they can't be read out onto the stack and + /// dropped normally. + /// + /// * It is friendlier to the optimizer to do this over `ptr::read` when + /// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), + /// as the compiler doesn't need to prove that it's sound to elide the + /// copy. + /// + /// # Undefined Behavior + /// + /// This has all the same safety problems as `ptr::read` with respect to + /// invalid pointers, types, and double drops. + pub fn drop_in_place(to_drop: *mut T); + + /// Gets a static string slice containing the name of a type. + pub fn type_name() -> &'static str; + + /// Gets an identifier which is globally unique to the specified type. This + /// function will return the same value for a type regardless of whichever + /// crate it is invoked in. + pub fn type_id() -> u64; + + /// Creates a value initialized to so that its drop flag, + /// if any, says that it has been dropped. + /// + /// `init_dropped` is unsafe because it returns a datum with all + /// of its bytes set to the drop flag, which generally does not + /// correspond to a valid value. + /// + /// This intrinsic is likely to be deprecated in the future when + /// Rust moves to non-zeroing dynamic drop (and thus removes the + /// embedded drop flags that are being established by this + /// intrinsic). + pub fn init_dropped() -> T; + + /// Creates a value initialized to zero. + /// + /// `init` is unsafe because it returns a zeroed-out datum, + /// which is unsafe unless T is `Copy`. Also, even if T is + /// `Copy`, an all-zero value may not correspond to any legitimate + /// state for the type in question. + pub fn init() -> T; + + /// Creates an uninitialized value. + /// + /// `uninit` is unsafe because there is no guarantee of what its + /// contents are. In particular its drop-flag may be set to any + /// state, which means it may claim either dropped or + /// undropped. In the general case one must use `ptr::write` to + /// initialize memory previous set to the result of `uninit`. + pub fn uninit() -> T; + + /// Moves a value out of scope without running drop glue. + pub fn forget(_: T) -> (); + + /// Unsafely transforms a value of one type into a value of another type. + /// + /// Both types must have the same size. + /// + /// # Examples + /// + /// ``` + /// use std::mem; + /// + /// let array: &[u8] = unsafe { mem::transmute("Rust") }; + /// assert_eq!(array, [82, 117, 115, 116]); + /// ``` + pub fn transmute(e: T) -> U; + + /// Gives the address for the return value of the enclosing function. + /// + /// Using this intrinsic in a function that does not use an out pointer + /// will trigger a compiler error. + pub fn return_address() -> *const u8; + + /// Returns `true` if the actual type given as `T` requires drop + /// glue; returns `false` if the actual type provided for `T` + /// implements `Copy`. + /// + /// If the actual type neither requires drop glue nor implements + /// `Copy`, then may return `true` or `false`. + pub fn needs_drop() -> bool; + + /// Calculates the offset from a pointer. + /// + /// This is implemented as an intrinsic to avoid converting to and from an + /// integer, since the conversion would throw away aliasing information. + /// + /// # Safety + /// + /// Both the starting and resulting pointer must be either in bounds or one + /// byte past the end of an allocated object. If either pointer is out of + /// bounds or arithmetic overflow occurs then any further use of the + /// returned value will result in undefined behavior. + pub fn offset(dst: *const T, offset: isize) -> *const T; + + /// Calculates the offset from a pointer, potentially wrapping. + /// + /// This is implemented as an intrinsic to avoid converting to and from an + /// integer, since the conversion inhibits certain optimizations. + /// + /// # Safety + /// + /// Unlike the `offset` intrinsic, this intrinsic does not restrict the + /// resulting pointer to point into or one byte past the end of an allocated + /// object, and it wraps with two's complement arithmetic. The resulting + /// value is not necessarily valid to be used to actually access memory. + pub fn arith_offset(dst: *const T, offset: isize) -> *const T; + + /// Copies `count * size_of` bytes from `src` to `dst`. The source + /// and destination may *not* overlap. + /// + /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. + /// + /// # Safety + /// + /// Beyond requiring that the program must be allowed to access both regions + /// of memory, it is Undefined Behavior for source and destination to + /// overlap. Care must also be taken with the ownership of `src` and + /// `dst`. This method semantically moves the values of `src` into `dst`. + /// However it does not drop the contents of `dst`, or prevent the contents + /// of `src` from being dropped or used. + /// + /// # Examples + /// + /// A safe swap function: + /// + /// ``` + /// use std::mem; + /// use std::ptr; + /// + /// # #[allow(dead_code)] + /// fn swap(x: &mut T, y: &mut T) { + /// unsafe { + /// // Give ourselves some scratch space to work with + /// let mut t: T = mem::uninitialized(); + /// + /// // Perform the swap, `&mut` pointers never alias + /// ptr::copy_nonoverlapping(x, &mut t, 1); + /// ptr::copy_nonoverlapping(y, x, 1); + /// ptr::copy_nonoverlapping(&t, y, 1); + /// + /// // y and t now point to the same thing, but we need to completely forget `tmp` + /// // because it's no longer relevant. + /// mem::forget(t); + /// } + /// } + /// ``` + pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); + + /// Copies `count * size_of` bytes from `src` to `dst`. The source + /// and destination may overlap. + /// + /// `copy` is semantically equivalent to C's `memmove`. + /// + /// # Safety + /// + /// Care must be taken with the ownership of `src` and `dst`. + /// This method semantically moves the values of `src` into `dst`. + /// However it does not drop the contents of `dst`, or prevent the contents of `src` + /// from being dropped or used. + /// + /// # Examples + /// + /// Efficiently create a Rust vector from an unsafe buffer: + /// + /// ``` + /// use std::ptr; + /// + /// # #[allow(dead_code)] + /// unsafe fn from_buf_raw(ptr: *const T, elts: usize) -> Vec { + /// let mut dst = Vec::with_capacity(elts); + /// dst.set_len(elts); + /// ptr::copy(ptr, dst.as_mut_ptr(), elts); + /// dst + /// } + /// ``` + /// + pub fn copy(src: *const T, dst: *mut T, count: usize); + + /// Invokes memset on the specified pointer, setting `count * size_of::()` + /// bytes of memory starting at `dst` to `val`. + pub fn write_bytes(dst: *mut T, val: u8, count: usize); + + /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with + /// a size of `count` * `size_of::()` and an alignment of + /// `min_align_of::()` + /// + /// The volatile parameter is set to `true`, so it will not be optimized out. + pub fn volatile_copy_nonoverlapping_memory(dst: *mut T, src: *const T, + count: usize); + /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with + /// a size of `count` * `size_of::()` and an alignment of + /// `min_align_of::()` + /// + /// The volatile parameter is set to `true`, so it will not be optimized out. + pub fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); + /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a + /// size of `count` * `size_of::()` and an alignment of + /// `min_align_of::()`. + /// + /// The volatile parameter is set to `true`, so it will not be optimized out. + pub fn volatile_set_memory(dst: *mut T, val: u8, count: usize); + + /// Perform a volatile load from the `src` pointer. + pub fn volatile_load(src: *const T) -> T; + /// Perform a volatile store to the `dst` pointer. + pub fn volatile_store(dst: *mut T, val: T); + + /// Returns the square root of an `f32` + pub fn sqrtf32(x: f32) -> f32; + /// Returns the square root of an `f64` + pub fn sqrtf64(x: f64) -> f64; + + /// Raises an `f32` to an integer power. + pub fn powif32(a: f32, x: i32) -> f32; + /// Raises an `f64` to an integer power. + pub fn powif64(a: f64, x: i32) -> f64; + + /// Returns the sine of an `f32`. + pub fn sinf32(x: f32) -> f32; + /// Returns the sine of an `f64`. + pub fn sinf64(x: f64) -> f64; + + /// Returns the cosine of an `f32`. + pub fn cosf32(x: f32) -> f32; + /// Returns the cosine of an `f64`. + pub fn cosf64(x: f64) -> f64; + + /// Raises an `f32` to an `f32` power. + pub fn powf32(a: f32, x: f32) -> f32; + /// Raises an `f64` to an `f64` power. + pub fn powf64(a: f64, x: f64) -> f64; + + /// Returns the exponential of an `f32`. + pub fn expf32(x: f32) -> f32; + /// Returns the exponential of an `f64`. + pub fn expf64(x: f64) -> f64; + + /// Returns 2 raised to the power of an `f32`. + pub fn exp2f32(x: f32) -> f32; + /// Returns 2 raised to the power of an `f64`. + pub fn exp2f64(x: f64) -> f64; + + /// Returns the natural logarithm of an `f32`. + pub fn logf32(x: f32) -> f32; + /// Returns the natural logarithm of an `f64`. + pub fn logf64(x: f64) -> f64; + + /// Returns the base 10 logarithm of an `f32`. + pub fn log10f32(x: f32) -> f32; + /// Returns the base 10 logarithm of an `f64`. + pub fn log10f64(x: f64) -> f64; + + /// Returns the base 2 logarithm of an `f32`. + pub fn log2f32(x: f32) -> f32; + /// Returns the base 2 logarithm of an `f64`. + pub fn log2f64(x: f64) -> f64; + + /// Returns `a * b + c` for `f32` values. + pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; + /// Returns `a * b + c` for `f64` values. + pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; + + /// Returns the absolute value of an `f32`. + pub fn fabsf32(x: f32) -> f32; + /// Returns the absolute value of an `f64`. + pub fn fabsf64(x: f64) -> f64; + + /// Copies the sign from `y` to `x` for `f32` values. + pub fn copysignf32(x: f32, y: f32) -> f32; + /// Copies the sign from `y` to `x` for `f64` values. + pub fn copysignf64(x: f64, y: f64) -> f64; + + /// Returns the largest integer less than or equal to an `f32`. + pub fn floorf32(x: f32) -> f32; + /// Returns the largest integer less than or equal to an `f64`. + pub fn floorf64(x: f64) -> f64; + + /// Returns the smallest integer greater than or equal to an `f32`. + pub fn ceilf32(x: f32) -> f32; + /// Returns the smallest integer greater than or equal to an `f64`. + pub fn ceilf64(x: f64) -> f64; + + /// Returns the integer part of an `f32`. + pub fn truncf32(x: f32) -> f32; + /// Returns the integer part of an `f64`. + pub fn truncf64(x: f64) -> f64; + + /// Returns the nearest integer to an `f32`. May raise an inexact floating-point exception + /// if the argument is not an integer. + pub fn rintf32(x: f32) -> f32; + /// Returns the nearest integer to an `f64`. May raise an inexact floating-point exception + /// if the argument is not an integer. + pub fn rintf64(x: f64) -> f64; + + /// Returns the nearest integer to an `f32`. + pub fn nearbyintf32(x: f32) -> f32; + /// Returns the nearest integer to an `f64`. + pub fn nearbyintf64(x: f64) -> f64; + + /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. + pub fn roundf32(x: f32) -> f32; + /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. + pub fn roundf64(x: f64) -> f64; + + /// Float addition that allows optimizations based on algebraic rules. + /// May assume inputs are finite. + pub fn fadd_fast(a: T, b: T) -> T; + + /// Float subtraction that allows optimizations based on algebraic rules. + /// May assume inputs are finite. + pub fn fsub_fast(a: T, b: T) -> T; + + /// Float multiplication that allows optimizations based on algebraic rules. + /// May assume inputs are finite. + pub fn fmul_fast(a: T, b: T) -> T; + + /// Float division that allows optimizations based on algebraic rules. + /// May assume inputs are finite. + pub fn fdiv_fast(a: T, b: T) -> T; + + /// Float remainder that allows optimizations based on algebraic rules. + /// May assume inputs are finite. + pub fn frem_fast(a: T, b: T) -> T; + + + /// Returns the number of bits set in an integer type `T` + pub fn ctpop(x: T) -> T; + + /// Returns the number of leading bits unset in an integer type `T` + pub fn ctlz(x: T) -> T; + + /// Returns the number of trailing bits unset in an integer type `T` + pub fn cttz(x: T) -> T; + + /// Reverses the bytes in an integer type `T`. + pub fn bswap(x: T) -> T; + + /// Performs checked integer addition. + pub fn add_with_overflow(x: T, y: T) -> (T, bool); + + /// Performs checked integer subtraction + pub fn sub_with_overflow(x: T, y: T) -> (T, bool); + + /// Performs checked integer multiplication + pub fn mul_with_overflow(x: T, y: T) -> (T, bool); + + /// Performs an unchecked division, resulting in undefined behavior + /// where y = 0 or x = `T::min_value()` and y = -1 + pub fn unchecked_div(x: T, y: T) -> T; + /// Returns the remainder of an unchecked division, resulting in + /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1 + pub fn unchecked_rem(x: T, y: T) -> T; + + /// Returns (a + b) mod 2^N, where N is the width of T in bits. + pub fn overflowing_add(a: T, b: T) -> T; + /// Returns (a - b) mod 2^N, where N is the width of T in bits. + pub fn overflowing_sub(a: T, b: T) -> T; + /// Returns (a * b) mod 2^N, where N is the width of T in bits. + pub fn overflowing_mul(a: T, b: T) -> T; + + /// Returns the value of the discriminant for the variant in 'v', + /// cast to a `u64`; if `T` has no discriminant, returns 0. + pub fn discriminant_value(v: &T) -> u64; + + /// Rust's "try catch" construct which invokes the function pointer `f` with + /// the data pointer `data`. + /// + /// The third pointer is a target-specific data pointer which is filled in + /// with the specifics of the exception that occurred. For examples on Unix + /// platforms this is a `*mut *mut T` which is filled in by the compiler and + /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's + /// source as well as std's catch implementation. + pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32; +} diff --git a/avr-core/src/lib.rs b/avr-core/src/lib.rs new file mode 100644 index 0000000..b810f19 --- /dev/null +++ b/avr-core/src/lib.rs @@ -0,0 +1,32 @@ +#![feature(no_core)] +#![feature(lang_items)] +#![feature(fundamental)] +#![feature(intrinsics)] +#![feature(on_unimplemented)] +#![feature(optin_builtin_traits)] +#![feature(reflect)] +#![feature(unboxed_closures)] +#![feature(associated_type_defaults)] + +#![no_core] + +pub mod prelude { + pub use option::Option::*; + pub use ops::*; +} + +#[lang = "eh_personality"] +extern fn eh_personality() {} + +#[lang = "panic"] +pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! { + loop {} +} + +// All this is copied from libcore +pub mod option; +pub mod intrinsics; +pub mod clone; +pub mod cmp; +pub mod marker; +pub mod ops; diff --git a/avr-core/src/marker.rs b/avr-core/src/marker.rs new file mode 100644 index 0000000..b03d458 --- /dev/null +++ b/avr-core/src/marker.rs @@ -0,0 +1,434 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Primitive traits and marker types representing basic 'kinds' of types. +//! +//! Rust types can be classified in various useful ways according to +//! intrinsic properties of the type. These classifications, often called +//! 'kinds', are represented as traits. + + +use clone::Clone; +use cmp; +//use default::Default; +use option::Option; +// use hash::Hash; +// use hash::Hasher; + +/// Types that can be transferred across thread boundaries. +/// +/// This trait is automatically derived when the compiler determines it's appropriate. +#[lang = "send"] +#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] +pub unsafe trait Send { + // empty. +} + +unsafe impl Send for .. { } + +impl !Send for *const T { } +impl !Send for *mut T { } + +/// Types with a constant size known at compile-time. +/// +/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax +/// `?Sized` can be used to remove this bound if it is not appropriate. +/// +/// ``` +/// # #![allow(dead_code)] +/// struct Foo(T); +/// struct Bar(T); +/// +/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32] +/// struct BarUse(Bar<[i32]>); // OK +/// ``` +#[lang = "sized"] +#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] +#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable +pub trait Sized { + // Empty. +} + +/// Types that can be "unsized" to a dynamically sized type. +#[lang="unsize"] +pub trait Unsize { + // Empty. +} + +/// Types that can be copied by simply copying bits (i.e. `memcpy`). +/// +/// By default, variable bindings have 'move semantics.' In other +/// words: +/// +/// ``` +/// #[derive(Debug)] +/// struct Foo; +/// +/// let x = Foo; +/// +/// let y = x; +/// +/// // `x` has moved into `y`, and so cannot be used +/// +/// // println!("{:?}", x); // error: use of moved value +/// ``` +/// +/// However, if a type implements `Copy`, it instead has 'copy semantics': +/// +/// ``` +/// // we can just derive a `Copy` implementation +/// #[derive(Debug, Copy, Clone)] +/// struct Foo; +/// +/// let x = Foo; +/// +/// let y = x; +/// +/// // `y` is a copy of `x` +/// +/// println!("{:?}", x); // A-OK! +/// ``` +/// +/// It's important to note that in these two examples, the only difference is if you are allowed to +/// access `x` after the assignment: a move is also a bitwise copy under the hood. +/// +/// ## When can my type be `Copy`? +/// +/// A type can implement `Copy` if all of its components implement `Copy`. For example, this +/// `struct` can be `Copy`: +/// +/// ``` +/// # #[allow(dead_code)] +/// struct Point { +/// x: i32, +/// y: i32, +/// } +/// ``` +/// +/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`. +/// +/// ``` +/// # #![allow(dead_code)] +/// # struct Point; +/// struct PointList { +/// points: Vec, +/// } +/// ``` +/// +/// The `PointList` `struct` cannot implement `Copy`, because `Vec` is not `Copy`. If we +/// attempt to derive a `Copy` implementation, we'll get an error: +/// +/// ```text +/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy` +/// ``` +/// +/// ## How can I implement `Copy`? +/// +/// There are two ways to implement `Copy` on your type: +/// +/// ``` +/// #[derive(Copy, Clone)] +/// struct MyStruct; +/// ``` +/// +/// and +/// +/// ``` +/// struct MyStruct; +/// impl Copy for MyStruct {} +/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } } +/// ``` +/// +/// There is a small difference between the two: the `derive` strategy will also place a `Copy` +/// bound on type parameters, which isn't always desired. +/// +/// ## When can my type _not_ be `Copy`? +/// +/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased +/// mutable reference, and copying `String` would result in two attempts to free the same buffer. +/// +/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's +/// managing some resource besides its own `size_of::()` bytes. +/// +/// ## When should my type be `Copy`? +/// +/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing +/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future, +/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking +/// change: that second example would fail to compile if we made `Foo` non-`Copy`. +/// +/// # Derivable +/// +/// This trait can be used with `#[derive]`. +#[lang = "copy"] +pub trait Copy : Clone { + // Empty. +} + +/// Types that can be safely shared between threads when aliased. +/// +/// The precise definition is: a type `T` is `Sync` if `&T` is +/// thread-safe. In other words, there is no possibility of data races +/// when passing `&T` references between threads. +/// +/// As one would expect, primitive types like `u8` and `f64` are all +/// `Sync`, and so are simple aggregate types containing them (like +/// tuples, structs and enums). More instances of basic `Sync` types +/// include "immutable" types like `&T` and those with simple +/// inherited mutability, such as `Box`, `Vec` and most other +/// collection types. (Generic parameters need to be `Sync` for their +/// container to be `Sync`.) +/// +/// A somewhat surprising consequence of the definition is `&mut T` is +/// `Sync` (if `T` is `Sync`) even though it seems that it might +/// provide unsynchronized mutation. The trick is a mutable reference +/// stored in an aliasable reference (that is, `& &mut T`) becomes +/// read-only, as if it were a `& &T`, hence there is no risk of a data +/// race. +/// +/// Types that are not `Sync` are those that have "interior +/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell` +/// in `std::cell`. These types allow for mutation of their contents +/// even when in an immutable, aliasable slot, e.g. the contents of +/// `&Cell` can be `.set`, and do not ensure data races are +/// impossible, hence they cannot be `Sync`. A higher level example +/// of a non-`Sync` type is the reference counted pointer +/// `std::rc::Rc`, because any reference `&Rc` can clone a new +/// reference, which modifies the reference counts in a non-atomic +/// way. +/// +/// For cases when one does need thread-safe interior mutability, +/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in +/// the `sync` crate do ensure that any mutation cannot cause data +/// races. Hence these types are `Sync`. +/// +/// Any types with interior mutability must also use the `std::cell::UnsafeCell` +/// wrapper around the value(s) which can be mutated when behind a `&` +/// reference; not doing this is undefined behavior (for example, +/// `transmute`-ing from `&T` to `&mut T` is invalid). +/// +/// This trait is automatically derived when the compiler determines it's appropriate. +#[lang = "sync"] +#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] +pub unsafe trait Sync { + // Empty +} + +unsafe impl Sync for .. { } + +impl !Sync for *const T { } +impl !Sync for *mut T { } + +macro_rules! impls{ + ($t: ident) => ( + // impl Hash for $t { + // #[inline] + // fn hash(&self, _: &mut H) { + // } + // } + + impl cmp::PartialEq for $t { + fn eq(&self, _other: &$t) -> bool { + true + } + } + + impl cmp::Eq for $t { + } + + impl cmp::PartialOrd for $t { + fn partial_cmp(&self, _other: &$t) -> Option { + Option::Some(cmp::Ordering::Equal) + } + } + + impl cmp::Ord for $t { + fn cmp(&self, _other: &$t) -> cmp::Ordering { + cmp::Ordering::Equal + } + } + + impl Copy for $t { } + + impl Clone for $t { + fn clone(&self) -> $t { + $t + } + } + + // impl Default for $t { + // fn default() -> $t { + // $t + // } + // } + ) +} + +/// `PhantomData` allows you to describe that a type acts as if it stores a value of type `T`, +/// even though it does not. This allows you to inform the compiler about certain safety properties +/// of your code. +/// +/// For a more in-depth explanation of how to use `PhantomData`, please see [the Nomicon]. +/// +/// [the Nomicon]: ../../nomicon/phantom-data.html +/// +/// # A ghastly note 👻👻👻 +/// +/// Though they both have scary names, `PhantomData` and 'phantom types' are related, but not +/// identical. Phantom types are a more general concept that don't require `PhantomData` to +/// implement, but `PhantomData` is the most common way to implement them in a correct manner. +/// +/// # Examples +/// +/// ## Unused lifetime parameter +/// +/// Perhaps the most common time that `PhantomData` is required is +/// with a struct that has an unused lifetime parameter, typically as +/// part of some unsafe code. For example, here is a struct `Slice` +/// that has two pointers of type `*const T`, presumably pointing into +/// an array somewhere: +/// +/// ```ignore +/// struct Slice<'a, T> { +/// start: *const T, +/// end: *const T, +/// } +/// ``` +/// +/// The intention is that the underlying data is only valid for the +/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this +/// intent is not expressed in the code, since there are no uses of +/// the lifetime `'a` and hence it is not clear what data it applies +/// to. We can correct this by telling the compiler to act *as if* the +/// `Slice` struct contained a borrowed reference `&'a T`: +/// +/// ``` +/// use std::marker::PhantomData; +/// +/// # #[allow(dead_code)] +/// struct Slice<'a, T:'a> { +/// start: *const T, +/// end: *const T, +/// phantom: PhantomData<&'a T> +/// } +/// ``` +/// +/// This also in turn requires that we annotate `T:'a`, indicating +/// that `T` is a type that can be borrowed for the lifetime `'a`. +/// +/// ## Unused type parameters +/// +/// It sometimes happens that there are unused type parameters that +/// indicate what type of data a struct is "tied" to, even though that +/// data is not actually found in the struct itself. Here is an +/// example where this arises when handling external resources over a +/// foreign function interface. `PhantomData` can prevent +/// mismatches by enforcing types in the method implementations: +/// +/// ``` +/// # #![allow(dead_code)] +/// # trait ResType { fn foo(&self); } +/// # struct ParamType; +/// # mod foreign_lib { +/// # pub fn new(_: usize) -> *mut () { 42 as *mut () } +/// # pub fn do_stuff(_: *mut (), _: usize) {} +/// # } +/// # fn convert_params(_: ParamType) -> usize { 42 } +/// use std::marker::PhantomData; +/// use std::mem; +/// +/// struct ExternalResource { +/// resource_handle: *mut (), +/// resource_type: PhantomData, +/// } +/// +/// impl ExternalResource { +/// fn new() -> ExternalResource { +/// let size_of_res = mem::size_of::(); +/// ExternalResource { +/// resource_handle: foreign_lib::new(size_of_res), +/// resource_type: PhantomData, +/// } +/// } +/// +/// fn do_stuff(&self, param: ParamType) { +/// let foreign_params = convert_params(param); +/// foreign_lib::do_stuff(self.resource_handle, foreign_params); +/// } +/// } +/// ``` +/// +/// ## Indicating ownership +/// +/// Adding a field of type `PhantomData` also indicates that your +/// struct owns data of type `T`. This in turn implies that when your +/// struct is dropped, it may in turn drop one or more instances of +/// the type `T`, though that may not be apparent from the other +/// structure of the type itself. This is commonly necessary if the +/// structure is using a raw pointer like `*mut T` whose referent +/// may be dropped when the type is dropped, as a `*mut T` is +/// otherwise not treated as owned. +/// +/// If your struct does not in fact *own* the data of type `T`, it is +/// better to use a reference type, like `PhantomData<&'a T>` +/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so +/// as not to indicate ownership. +#[lang = "phantom_data"] +pub struct PhantomData; + +impls! { PhantomData } + +mod impls { + use super::{Send, Sync, Sized}; + + unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {} + unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {} +} + +/// Types that can be reflected over. +/// +/// This trait is implemented for all types. Its purpose is to ensure +/// that when you write a generic function that will employ +/// reflection, that must be reflected (no pun intended) in the +/// generic bounds of that function. Here is an example: +/// +/// ``` +/// #![feature(reflect_marker)] +/// use std::marker::Reflect; +/// use std::any::Any; +/// +/// # #[allow(dead_code)] +/// fn foo(x: &T) { +/// let any: &Any = x; +/// if any.is::() { println!("u32"); } +/// } +/// ``` +/// +/// Without the declaration `T:Reflect`, `foo` would not type check +/// (note: as a matter of style, it would be preferable to write +/// `T:Any`, because `T:Any` implies `T:Reflect` and `T:'static`, but +/// we use `Reflect` here to show how it works). The `Reflect` bound +/// thus serves to alert `foo`'s caller to the fact that `foo` may +/// behave differently depending on whether `T=u32` or not. In +/// particular, thanks to the `Reflect` bound, callers know that a +/// function declared like `fn bar(...)` will always act in +/// precisely the same way no matter what type `T` is supplied, +/// because there are no bounds declared on `T`. (The ability for a +/// caller to reason about what a function may do based solely on what +/// generic bounds are declared is often called the ["parametricity +/// property"][1].) +/// +/// [1]: http://en.wikipedia.org/wiki/Parametricity +#[rustc_reflect_like] +#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \ + ensure all type parameters are bounded by `Any`"] +pub trait Reflect {} + +impl Reflect for .. { } diff --git a/avr-core/src/ops.rs b/avr-core/src/ops.rs new file mode 100644 index 0000000..fc2b7e4 --- /dev/null +++ b/avr-core/src/ops.rs @@ -0,0 +1,1724 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Overloadable operators +//! +//! Implementing these traits allows you to get an effect similar to +//! overloading operators. +//! +//! Some of these traits are imported by the prelude, so they are available in +//! every Rust program. +//! +//! Many of the operators take their operands by value. In non-generic +//! contexts involving built-in types, this is usually not a problem. +//! However, using these operators in generic code, requires some +//! attention if values have to be reused as opposed to letting the operators +//! consume them. One option is to occasionally use `clone()`. +//! Another option is to rely on the types involved providing additional +//! operator implementations for references. For example, for a user-defined +//! type `T` which is supposed to support addition, it is probably a good +//! idea to have both `T` and `&T` implement the traits `Add` and `Add<&T>` +//! so that generic code can be written without unnecessary cloning. +//! +//! # Examples +//! +//! This example creates a `Point` struct that implements `Add` and `Sub`, and +//! then demonstrates adding and subtracting two `Point`s. +//! +//! ```rust +//! use std::ops::{Add, Sub}; +//! +//! #[derive(Debug)] +//! struct Point { +//! x: i32, +//! y: i32, +//! } +//! +//! impl Add for Point { +//! type Output = Point; +//! +//! fn add(self, other: Point) -> Point { +//! Point {x: self.x + other.x, y: self.y + other.y} +//! } +//! } +//! +//! impl Sub for Point { +//! type Output = Point; +//! +//! fn sub(self, other: Point) -> Point { +//! Point {x: self.x - other.x, y: self.y - other.y} +//! } +//! } +//! fn main() { +//! println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); +//! println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); +//! } +//! ``` +//! +//! See the documentation for each trait for a minimum implementation that +//! prints something to the screen. + + +use marker::{Sized, Unsize}; +//use fmt; + +/// The `Drop` trait is used to run some code when a value goes out of scope. +/// This is sometimes called a 'destructor'. +/// +/// # Examples +/// +/// A trivial implementation of `Drop`. The `drop` method is called when `_x` +/// goes out of scope, and therefore `main` prints `Dropping!`. +/// +/// ``` +/// struct HasDrop; +/// +/// impl Drop for HasDrop { +/// fn drop(&mut self) { +/// println!("Dropping!"); +/// } +/// } +/// +/// fn main() { +/// let _x = HasDrop; +/// } +/// ``` +#[lang = "drop"] +pub trait Drop { + /// A method called when the value goes out of scope. + fn drop(&mut self); +} + +// implements the unary operator "op &T" +// based on "op T" where T is expected to be `Copy`able +macro_rules! forward_ref_unop { + (impl $imp:ident, $method:ident for $t:ty) => { + impl<'a> $imp for &'a $t { + type Output = <$t as $imp>::Output; + + #[inline] + fn $method(self) -> <$t as $imp>::Output { + $imp::$method(*self) + } + } + } +} + +// implements binary operators "&T op U", "T op &U", "&T op &U" +// based on "T op U" where T and U are expected to be `Copy`able +macro_rules! forward_ref_binop { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + impl<'a> $imp<$u> for &'a $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, other) + } + } + + impl<'a> $imp<&'a $u> for $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + $imp::$method(self, *other) + } + } + + impl<'a, 'b> $imp<&'a $u> for &'b $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, *other) + } + } + } +} + +/// The `Add` trait is used to specify the functionality of `+`. +/// +/// # Examples +/// +/// A trivial implementation of `Add`. When `Foo + Foo` happens, it ends up +/// calling `add`, and therefore, `main` prints `Adding!`. +/// +/// ``` +/// use std::ops::Add; +/// +/// struct Foo; +/// +/// impl Add for Foo { +/// type Output = Foo; +/// +/// fn add(self, _rhs: Foo) -> Foo { +/// println!("Adding!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo + Foo; +/// } +/// ``` +#[lang = "add"] +pub trait Add { + /// The resulting type after applying the `+` operator + type Output; + + /// The method for the `+` operator + fn add(self, rhs: RHS) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + impl Add for $t { + type Output = $t; + + #[inline] + fn add(self, other: $t) -> $t { self + other } + } + + forward_ref_binop! { impl Add, add for $t, $t } + )*) +} + +add_impl! { usize u8 u16 isize i8 i16 } + +/// The `Sub` trait is used to specify the functionality of `-`. +/// +/// # Examples +/// +/// A trivial implementation of `Sub`. When `Foo - Foo` happens, it ends up +/// calling `sub`, and therefore, `main` prints `Subtracting!`. +/// +/// ``` +/// use std::ops::Sub; +/// +/// struct Foo; +/// +/// impl Sub for Foo { +/// type Output = Foo; +/// +/// fn sub(self, _rhs: Foo) -> Foo { +/// println!("Subtracting!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo - Foo; +/// } +/// ``` +#[lang = "sub"] +pub trait Sub { + /// The resulting type after applying the `-` operator + type Output; + + /// The method for the `-` operator + fn sub(self, rhs: RHS) -> Self::Output; +} + +macro_rules! sub_impl { + ($($t:ty)*) => ($( + impl Sub for $t { + type Output = $t; + + #[inline] + fn sub(self, other: $t) -> $t { self - other } + } + + forward_ref_binop! { impl Sub, sub for $t, $t } + )*) +} + +sub_impl! { usize u8 u16 isize i8 i16 } + +/// The `Mul` trait is used to specify the functionality of `*`. +/// +/// # Examples +/// +/// A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up +/// calling `mul`, and therefore, `main` prints `Multiplying!`. +/// +/// ``` +/// use std::ops::Mul; +/// +/// struct Foo; +/// +/// impl Mul for Foo { +/// type Output = Foo; +/// +/// fn mul(self, _rhs: Foo) -> Foo { +/// println!("Multiplying!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo * Foo; +/// } +/// ``` +#[lang = "mul"] +pub trait Mul { + /// The resulting type after applying the `*` operator + type Output; + + /// The method for the `*` operator + fn mul(self, rhs: RHS) -> Self::Output; +} + +macro_rules! mul_impl { + ($($t:ty)*) => ($( + impl Mul for $t { + type Output = $t; + + #[inline] + fn mul(self, other: $t) -> $t { self * other } + } + + forward_ref_binop! { impl Mul, mul for $t, $t } + )*) +} + +mul_impl! { usize u8 u16 isize i8 i16 } + +/// The `Div` trait is used to specify the functionality of `/`. +/// +/// # Examples +/// +/// A trivial implementation of `Div`. When `Foo / Foo` happens, it ends up +/// calling `div`, and therefore, `main` prints `Dividing!`. +/// +/// ``` +/// use std::ops::Div; +/// +/// struct Foo; +/// +/// impl Div for Foo { +/// type Output = Foo; +/// +/// fn div(self, _rhs: Foo) -> Foo { +/// println!("Dividing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo / Foo; +/// } +/// ``` +#[lang = "div"] +pub trait Div { + /// The resulting type after applying the `/` operator + type Output; + + /// The method for the `/` operator + fn div(self, rhs: RHS) -> Self::Output; +} + +macro_rules! div_impl_integer { + ($($t:ty)*) => ($( + /// This operation rounds towards zero, truncating any + /// fractional part of the exact result. + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + +div_impl_integer! { usize u8 u16 isize i8 i16 } + +macro_rules! div_impl_float { + ($($t:ty)*) => ($( + impl Div for $t { + type Output = $t; + + #[inline] + fn div(self, other: $t) -> $t { self / other } + } + + forward_ref_binop! { impl Div, div for $t, $t } + )*) +} + + +/// The `Rem` trait is used to specify the functionality of `%`. +/// +/// # Examples +/// +/// A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up +/// calling `rem`, and therefore, `main` prints `Remainder-ing!`. +/// +/// ``` +/// use std::ops::Rem; +/// +/// struct Foo; +/// +/// impl Rem for Foo { +/// type Output = Foo; +/// +/// fn rem(self, _rhs: Foo) -> Foo { +/// println!("Remainder-ing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo % Foo; +/// } +/// ``` +#[lang = "rem"] +pub trait Rem { + /// The resulting type after applying the `%` operator + type Output = Self; + + /// The method for the `%` operator + fn rem(self, rhs: RHS) -> Self::Output; +} + +macro_rules! rem_impl_integer { + ($($t:ty)*) => ($( + /// This operation satisfies `n % d == n - (n / d) * d`. The + /// result has the same sign as the left operand. + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +rem_impl_integer! { usize u8 u16 isize i8 i16 } + +macro_rules! rem_impl_float { + ($($t:ty)*) => ($( + impl Rem for $t { + type Output = $t; + + #[inline] + fn rem(self, other: $t) -> $t { self % other } + } + + forward_ref_binop! { impl Rem, rem for $t, $t } + )*) +} + +/// The `Neg` trait is used to specify the functionality of unary `-`. +/// +/// # Examples +/// +/// A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling +/// `neg`, and therefore, `main` prints `Negating!`. +/// +/// ``` +/// use std::ops::Neg; +/// +/// struct Foo; +/// +/// impl Neg for Foo { +/// type Output = Foo; +/// +/// fn neg(self) -> Foo { +/// println!("Negating!"); +/// self +/// } +/// } +/// +/// fn main() { +/// -Foo; +/// } +/// ``` +#[lang = "neg"] +pub trait Neg { + /// The resulting type after applying the `-` operator + type Output; + + /// The method for the unary `-` operator + fn neg(self) -> Self::Output; +} + + + +macro_rules! neg_impl_core { + ($id:ident => $body:expr, $($t:ty)*) => ($( + impl Neg for $t { + type Output = $t; + + #[inline] + fn neg(self) -> $t { let $id = self; $body } + } + + forward_ref_unop! { impl Neg, neg for $t } + )*) +} + +macro_rules! neg_impl_numeric { + ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} } +} + +macro_rules! neg_impl_unsigned { + ($($t:ty)*) => { + neg_impl_core!{ x => { + !x.wrapping_add(1) + }, $($t)*} } +} + +neg_impl_numeric! { isize i8 i16 } + +/// The `Not` trait is used to specify the functionality of unary `!`. +/// +/// # Examples +/// +/// A trivial implementation of `Not`. When `!Foo` happens, it ends up calling +/// `not`, and therefore, `main` prints `Not-ing!`. +/// +/// ``` +/// use std::ops::Not; +/// +/// struct Foo; +/// +/// impl Not for Foo { +/// type Output = Foo; +/// +/// fn not(self) -> Foo { +/// println!("Not-ing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// !Foo; +/// } +/// ``` +#[lang = "not"] +pub trait Not { + /// The resulting type after applying the `!` operator + type Output; + + /// The method for the unary `!` operator + fn not(self) -> Self::Output; +} + +macro_rules! not_impl { + ($($t:ty)*) => ($( + impl Not for $t { + type Output = $t; + + #[inline] + fn not(self) -> $t { !self } + } + + forward_ref_unop! { impl Not, not for $t } + )*) +} + +not_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `BitAnd` trait is used to specify the functionality of `&`. +/// +/// # Examples +/// +/// A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up +/// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// struct Foo; +/// +/// impl BitAnd for Foo { +/// type Output = Foo; +/// +/// fn bitand(self, _rhs: Foo) -> Foo { +/// println!("Bitwise And-ing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo & Foo; +/// } +/// ``` +#[lang = "bitand"] +pub trait BitAnd { + /// The resulting type after applying the `&` operator + type Output; + + /// The method for the `&` operator + fn bitand(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitand_impl { + ($($t:ty)*) => ($( + impl BitAnd for $t { + type Output = $t; + + #[inline] + fn bitand(self, rhs: $t) -> $t { self & rhs } + } + + forward_ref_binop! { impl BitAnd, bitand for $t, $t } + )*) +} + +bitand_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `BitOr` trait is used to specify the functionality of `|`. +/// +/// # Examples +/// +/// A trivial implementation of `BitOr`. When `Foo | Foo` happens, it ends up +/// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`. +/// +/// ``` +/// use std::ops::BitOr; +/// +/// struct Foo; +/// +/// impl BitOr for Foo { +/// type Output = Foo; +/// +/// fn bitor(self, _rhs: Foo) -> Foo { +/// println!("Bitwise Or-ing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo | Foo; +/// } +/// ``` +#[lang = "bitor"] +pub trait BitOr { + /// The resulting type after applying the `|` operator + type Output; + + /// The method for the `|` operator + fn bitor(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitor_impl { + ($($t:ty)*) => ($( + impl BitOr for $t { + type Output = $t; + + #[inline] + fn bitor(self, rhs: $t) -> $t { self | rhs } + } + + forward_ref_binop! { impl BitOr, bitor for $t, $t } + )*) +} + +bitor_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `BitXor` trait is used to specify the functionality of `^`. +/// +/// # Examples +/// +/// A trivial implementation of `BitXor`. When `Foo ^ Foo` happens, it ends up +/// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`. +/// +/// ``` +/// use std::ops::BitXor; +/// +/// struct Foo; +/// +/// impl BitXor for Foo { +/// type Output = Foo; +/// +/// fn bitxor(self, _rhs: Foo) -> Foo { +/// println!("Bitwise Xor-ing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo ^ Foo; +/// } +/// ``` +#[lang = "bitxor"] +pub trait BitXor { + /// The resulting type after applying the `^` operator + type Output; + + /// The method for the `^` operator + fn bitxor(self, rhs: RHS) -> Self::Output; +} + +macro_rules! bitxor_impl { + ($($t:ty)*) => ($( + impl BitXor for $t { + type Output = $t; + + #[inline] + fn bitxor(self, other: $t) -> $t { self ^ other } + } + + forward_ref_binop! { impl BitXor, bitxor for $t, $t } + )*) +} + +bitxor_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `Shl` trait is used to specify the functionality of `<<`. +/// +/// # Examples +/// +/// A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up +/// calling `shl`, and therefore, `main` prints `Shifting left!`. +/// +/// ``` +/// use std::ops::Shl; +/// +/// struct Foo; +/// +/// impl Shl for Foo { +/// type Output = Foo; +/// +/// fn shl(self, _rhs: Foo) -> Foo { +/// println!("Shifting left!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo << Foo; +/// } +/// ``` +#[lang = "shl"] +pub trait Shl { + /// The resulting type after applying the `<<` operator + type Output; + + /// The method for the `<<` operator + fn shl(self, rhs: RHS) -> Self::Output; +} + +macro_rules! shl_impl { + ($t:ty, $f:ty) => ( + impl Shl<$f> for $t { + type Output = $t; + + #[inline] + fn shl(self, other: $f) -> $t { + self << other + } + } + + forward_ref_binop! { impl Shl, shl for $t, $f } + ) +} + +macro_rules! shl_impl_all { + ($($t:ty)*) => ($( + shl_impl! { $t, u8 } + shl_impl! { $t, u16 } + shl_impl! { $t, usize } + + shl_impl! { $t, i8 } + shl_impl! { $t, i16 } + shl_impl! { $t, isize } + )*) +} + +shl_impl_all! { u8 u16 usize i8 i16 isize } + +/// The `Shr` trait is used to specify the functionality of `>>`. +/// +/// # Examples +/// +/// A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up +/// calling `shr`, and therefore, `main` prints `Shifting right!`. +/// +/// ``` +/// use std::ops::Shr; +/// +/// struct Foo; +/// +/// impl Shr for Foo { +/// type Output = Foo; +/// +/// fn shr(self, _rhs: Foo) -> Foo { +/// println!("Shifting right!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo >> Foo; +/// } +/// ``` +#[lang = "shr"] +pub trait Shr { + /// The resulting type after applying the `>>` operator + type Output; + + /// The method for the `>>` operator + fn shr(self, rhs: RHS) -> Self::Output; +} + +macro_rules! shr_impl { + ($t:ty, $f:ty) => ( + impl Shr<$f> for $t { + type Output = $t; + + #[inline] + fn shr(self, other: $f) -> $t { + self >> other + } + } + + forward_ref_binop! { impl Shr, shr for $t, $f } + ) +} + +macro_rules! shr_impl_all { + ($($t:ty)*) => ($( + shr_impl! { $t, u8 } + shr_impl! { $t, u16 } + shr_impl! { $t, usize } + + shr_impl! { $t, i8 } + shr_impl! { $t, i16 } + shr_impl! { $t, isize } + )*) +} + +shr_impl_all! { u8 u16 usize i8 i16 isize } + +/// The `AddAssign` trait is used to specify the functionality of `+=`. +/// +/// # Examples +/// +/// A trivial implementation of `AddAssign`. When `Foo += Foo` happens, it ends up +/// calling `add_assign`, and therefore, `main` prints `Adding!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::AddAssign; +/// +/// struct Foo; +/// +/// impl AddAssign for Foo { +/// fn add_assign(&mut self, _rhs: Foo) { +/// println!("Adding!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo += Foo; +/// } +/// ``` +#[lang = "add_assign"] +pub trait AddAssign { + /// The method for the `+=` operator + fn add_assign(&mut self, Rhs); +} + +macro_rules! add_assign_impl { + ($($t:ty)+) => ($( + impl AddAssign for $t { + #[inline] + fn add_assign(&mut self, other: $t) { *self += other } + } + )+) +} + +add_assign_impl! { usize u8 u16 isize i8 i16 } + +/// The `SubAssign` trait is used to specify the functionality of `-=`. +/// +/// # Examples +/// +/// A trivial implementation of `SubAssign`. When `Foo -= Foo` happens, it ends up +/// calling `sub_assign`, and therefore, `main` prints `Subtracting!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::SubAssign; +/// +/// struct Foo; +/// +/// impl SubAssign for Foo { +/// fn sub_assign(&mut self, _rhs: Foo) { +/// println!("Subtracting!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo -= Foo; +/// } +/// ``` +#[lang = "sub_assign"] +pub trait SubAssign { + /// The method for the `-=` operator + fn sub_assign(&mut self, Rhs); +} + +macro_rules! sub_assign_impl { + ($($t:ty)+) => ($( + impl SubAssign for $t { + #[inline] + fn sub_assign(&mut self, other: $t) { *self -= other } + } + )+) +} + +sub_assign_impl! { usize u8 u16 isize i8 i16 } + +/// The `MulAssign` trait is used to specify the functionality of `*=`. +/// +/// # Examples +/// +/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up +/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::MulAssign; +/// +/// struct Foo; +/// +/// impl MulAssign for Foo { +/// fn mul_assign(&mut self, _rhs: Foo) { +/// println!("Multiplying!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo *= Foo; +/// } +/// ``` +#[lang = "mul_assign"] +pub trait MulAssign { + /// The method for the `*=` operator + fn mul_assign(&mut self, Rhs); +} + +macro_rules! mul_assign_impl { + ($($t:ty)+) => ($( + impl MulAssign for $t { + #[inline] + fn mul_assign(&mut self, other: $t) { *self *= other } + } + )+) +} + +mul_assign_impl! { usize u8 u16 isize i8 i16 } + +/// The `DivAssign` trait is used to specify the functionality of `/=`. +/// +/// # Examples +/// +/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up +/// calling `div_assign`, and therefore, `main` prints `Dividing!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::DivAssign; +/// +/// struct Foo; +/// +/// impl DivAssign for Foo { +/// fn div_assign(&mut self, _rhs: Foo) { +/// println!("Dividing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo /= Foo; +/// } +/// ``` +#[lang = "div_assign"] +pub trait DivAssign { + /// The method for the `/=` operator + fn div_assign(&mut self, Rhs); +} + +macro_rules! div_assign_impl { + ($($t:ty)+) => ($( + impl DivAssign for $t { + #[inline] + fn div_assign(&mut self, other: $t) { *self /= other } + } + )+) +} + +div_assign_impl! { usize u8 u16 isize i8 i16 } + +/// The `RemAssign` trait is used to specify the functionality of `%=`. +/// +/// # Examples +/// +/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up +/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::RemAssign; +/// +/// struct Foo; +/// +/// impl RemAssign for Foo { +/// fn rem_assign(&mut self, _rhs: Foo) { +/// println!("Remainder-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo %= Foo; +/// } +/// ``` +#[lang = "rem_assign"] +pub trait RemAssign { + /// The method for the `%=` operator + fn rem_assign(&mut self, Rhs); +} + +macro_rules! rem_assign_impl { + ($($t:ty)+) => ($( + impl RemAssign for $t { + #[inline] + fn rem_assign(&mut self, other: $t) { *self %= other } + } + )+) +} + +rem_assign_impl! { usize u8 u16 isize i8 i16 } + +/// The `BitAndAssign` trait is used to specify the functionality of `&=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitAndAssign`. When `Foo &= Foo` happens, it ends up +/// calling `bitand_assign`, and therefore, `main` prints `Bitwise And-ing!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::BitAndAssign; +/// +/// struct Foo; +/// +/// impl BitAndAssign for Foo { +/// fn bitand_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise And-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo &= Foo; +/// } +/// ``` +#[lang = "bitand_assign"] +pub trait BitAndAssign { + /// The method for the `&` operator + fn bitand_assign(&mut self, Rhs); +} + +macro_rules! bitand_assign_impl { + ($($t:ty)+) => ($( + impl BitAndAssign for $t { + #[inline] + fn bitand_assign(&mut self, other: $t) { *self &= other } + } + )+) +} + +bitand_assign_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `BitOrAssign` trait is used to specify the functionality of `|=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up +/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::BitOrAssign; +/// +/// struct Foo; +/// +/// impl BitOrAssign for Foo { +/// fn bitor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Or-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo |= Foo; +/// } +/// ``` +#[lang = "bitor_assign"] +pub trait BitOrAssign { + /// The method for the `|=` operator + fn bitor_assign(&mut self, Rhs); +} + +macro_rules! bitor_assign_impl { + ($($t:ty)+) => ($( + impl BitOrAssign for $t { + #[inline] + fn bitor_assign(&mut self, other: $t) { *self |= other } + } + )+) +} + +bitor_assign_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `BitXorAssign` trait is used to specify the functionality of `^=`. +/// +/// # Examples +/// +/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up +/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::BitXorAssign; +/// +/// struct Foo; +/// +/// impl BitXorAssign for Foo { +/// fn bitxor_assign(&mut self, _rhs: Foo) { +/// println!("Bitwise Xor-ing!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo ^= Foo; +/// } +/// ``` +#[lang = "bitxor_assign"] +pub trait BitXorAssign { + /// The method for the `^=` operator + fn bitxor_assign(&mut self, Rhs); +} + +macro_rules! bitxor_assign_impl { + ($($t:ty)+) => ($( + impl BitXorAssign for $t { + #[inline] + fn bitxor_assign(&mut self, other: $t) { *self ^= other } + } + )+) +} + +bitxor_assign_impl! { bool usize u8 u16 isize i8 i16 } + +/// The `ShlAssign` trait is used to specify the functionality of `<<=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up +/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::ShlAssign; +/// +/// struct Foo; +/// +/// impl ShlAssign for Foo { +/// fn shl_assign(&mut self, _rhs: Foo) { +/// println!("Shifting left!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo <<= Foo; +/// } +/// ``` +#[lang = "shl_assign"] +pub trait ShlAssign { + /// The method for the `<<=` operator + fn shl_assign(&mut self, Rhs); +} + +macro_rules! shl_assign_impl { + ($t:ty, $f:ty) => ( + impl ShlAssign<$f> for $t { + #[inline] + fn shl_assign(&mut self, other: $f) { + *self <<= other + } + } + ) +} + +macro_rules! shl_assign_impl_all { + ($($t:ty)*) => ($( + shl_assign_impl! { $t, u8 } + shl_assign_impl! { $t, u16 } + shl_assign_impl! { $t, usize } + + shl_assign_impl! { $t, i8 } + shl_assign_impl! { $t, i16 } + shl_assign_impl! { $t, isize } + )*) +} + +shl_assign_impl_all! { u8 u16 usize i8 i16 isize } + +/// The `ShrAssign` trait is used to specify the functionality of `>>=`. +/// +/// # Examples +/// +/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up +/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`. +/// +/// ``` +/// #![feature(augmented_assignments)] +/// #![feature(op_assign_traits)] +/// +/// use std::ops::ShrAssign; +/// +/// struct Foo; +/// +/// impl ShrAssign for Foo { +/// fn shr_assign(&mut self, _rhs: Foo) { +/// println!("Shifting right!"); +/// } +/// } +/// +/// # #[allow(unused_assignments)] +/// fn main() { +/// let mut foo = Foo; +/// foo >>= Foo; +/// } +/// ``` +#[lang = "shr_assign"] +pub trait ShrAssign { + /// The method for the `>>=` operator + fn shr_assign(&mut self, Rhs); +} + +macro_rules! shr_assign_impl { + ($t:ty, $f:ty) => ( + impl ShrAssign<$f> for $t { + #[inline] + fn shr_assign(&mut self, other: $f) { + *self >>= other + } + } + ) +} + +macro_rules! shr_assign_impl_all { + ($($t:ty)*) => ($( + shr_assign_impl! { $t, u8 } + shr_assign_impl! { $t, u16 } + shr_assign_impl! { $t, usize } + + shr_assign_impl! { $t, i8 } + shr_assign_impl! { $t, i16 } + shr_assign_impl! { $t, isize } + )*) +} + +shr_assign_impl_all! { u8 u16 usize i8 i16 isize } + +/// The `Index` trait is used to specify the functionality of indexing operations +/// like `arr[idx]` when used in an immutable context. +/// +/// # Examples +/// +/// A trivial implementation of `Index`. When `Foo[Bar]` happens, it ends up +/// calling `index`, and therefore, `main` prints `Indexing!`. +/// +/// ``` +/// use std::ops::Index; +/// +/// #[derive(Copy, Clone)] +/// struct Foo; +/// struct Bar; +/// +/// impl Index for Foo { +/// type Output = Foo; +/// +/// fn index<'a>(&'a self, _index: Bar) -> &'a Foo { +/// println!("Indexing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// Foo[Bar]; +/// } +/// ``` +#[lang = "index"] +#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"] +pub trait Index { + /// The returned type after indexing + type Output: ?Sized; + + /// The method for the indexing (`Foo[Bar]`) operation + fn index(&self, index: Idx) -> &Self::Output; +} + +/// The `IndexMut` trait is used to specify the functionality of indexing +/// operations like `arr[idx]`, when used in a mutable context. +/// +/// # Examples +/// +/// A trivial implementation of `IndexMut`. When `Foo[Bar]` happens, it ends up +/// calling `index_mut`, and therefore, `main` prints `Indexing!`. +/// +/// ``` +/// use std::ops::{Index, IndexMut}; +/// +/// #[derive(Copy, Clone)] +/// struct Foo; +/// struct Bar; +/// +/// impl Index for Foo { +/// type Output = Foo; +/// +/// fn index<'a>(&'a self, _index: Bar) -> &'a Foo { +/// self +/// } +/// } +/// +/// impl IndexMut for Foo { +/// fn index_mut<'a>(&'a mut self, _index: Bar) -> &'a mut Foo { +/// println!("Indexing!"); +/// self +/// } +/// } +/// +/// fn main() { +/// &mut Foo[Bar]; +/// } +/// ``` +#[lang = "index_mut"] +#[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"] +pub trait IndexMut: Index { + /// The method for the indexing (`Foo[Bar]`) operation + fn index_mut(&mut self, index: Idx) -> &mut Self::Output; +} + +/// An unbounded range. +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct RangeFull; + +// impl fmt::Debug for RangeFull { +// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +// write!(fmt, "..") +// } +// } + +/// A (half-open) range which is bounded at both ends. +#[derive(Clone, PartialEq, Eq)] +pub struct Range { + /// The lower bound of the range (inclusive). + pub start: Idx, + /// The upper bound of the range (exclusive). + pub end: Idx, +} + +// impl fmt::Debug for Range { +// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +// write!(fmt, "{:?}..{:?}", self.start, self.end) +// } +// } + +/// A range which is only bounded below. +#[derive(Clone, PartialEq, Eq)] +pub struct RangeFrom { + /// The lower bound of the range (inclusive). + pub start: Idx, +} + +// impl fmt::Debug for RangeFrom { +// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +// write!(fmt, "{:?}..", self.start) +// } +// } + +/// A range which is only bounded above. +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct RangeTo { + /// The upper bound of the range (exclusive). + pub end: Idx, +} + +// impl fmt::Debug for RangeTo { +// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { +// write!(fmt, "..{:?}", self.end) +// } +// } + +/// The `Deref` trait is used to specify the functionality of dereferencing +/// operations, like `*v`. +/// +/// `Deref` also enables ['`Deref` coercions'][coercions]. +/// +/// [coercions]: ../../book/deref-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is accessible via dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::Deref; +/// +/// struct DerefExample { +/// value: T +/// } +/// +/// impl Deref for DerefExample { +/// type Target = T; +/// +/// fn deref(&self) -> &T { +/// &self.value +/// } +/// } +/// +/// fn main() { +/// let x = DerefExample { value: 'a' }; +/// assert_eq!('a', *x); +/// } +/// ``` +#[lang = "deref"] +pub trait Deref { + /// The resulting type after dereferencing + type Target: ?Sized; + + /// The method called to dereference a value + fn deref(&self) -> &Self::Target; +} + +impl<'a, T: ?Sized> Deref for &'a T { + type Target = T; + + fn deref(&self) -> &T { *self } +} + +impl<'a, T: ?Sized> Deref for &'a mut T { + type Target = T; + + fn deref(&self) -> &T { *self } +} + +/// The `DerefMut` trait is used to specify the functionality of dereferencing +/// mutably like `*v = 1;` +/// +/// `DerefMut` also enables ['`Deref` coercions'][coercions]. +/// +/// [coercions]: ../../book/deref-coercions.html +/// +/// # Examples +/// +/// A struct with a single field which is modifiable via dereferencing the +/// struct. +/// +/// ``` +/// use std::ops::{Deref, DerefMut}; +/// +/// struct DerefMutExample { +/// value: T +/// } +/// +/// impl Deref for DerefMutExample { +/// type Target = T; +/// +/// fn deref<'a>(&'a self) -> &'a T { +/// &self.value +/// } +/// } +/// +/// impl DerefMut for DerefMutExample { +/// fn deref_mut<'a>(&'a mut self) -> &'a mut T { +/// &mut self.value +/// } +/// } +/// +/// fn main() { +/// let mut x = DerefMutExample { value: 'a' }; +/// *x = 'b'; +/// assert_eq!('b', *x); +/// } +/// ``` +#[lang = "deref_mut"] +pub trait DerefMut: Deref { + /// The method called to mutably dereference a value + fn deref_mut(&mut self) -> &mut Self::Target; +} + +impl<'a, T: ?Sized> DerefMut for &'a mut T { + fn deref_mut(&mut self) -> &mut T { *self } +} + +/// A version of the call operator that takes an immutable receiver. +#[lang = "fn"] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait Fn : FnMut { + /// This is called when the call operator is used. + extern "rust-call" fn call(&self, args: Args) -> Self::Output; +} + +/// A version of the call operator that takes a mutable receiver. +#[lang = "fn_mut"] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnMut : FnOnce { + /// This is called when the call operator is used. + extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; +} + +/// A version of the call operator that takes a by-value receiver. +#[lang = "fn_once"] +#[rustc_paren_sugar] +#[fundamental] // so that regex can rely that `&str: !FnMut` +pub trait FnOnce { + /// The returned type after the call operator is used. + type Output; + + /// This is called when the call operator is used. + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +mod impls { + use marker::Sized; + use super::{Fn, FnMut, FnOnce}; + + impl<'a,A,F:?Sized> Fn for &'a F + where F : Fn + { + extern "rust-call" fn call(&self, args: A) -> F::Output { + (**self).call(args) + } + } + + impl<'a,A,F:?Sized> FnMut for &'a F + where F : Fn + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (**self).call(args) + } + } + + impl<'a,A,F:?Sized> FnOnce for &'a F + where F : Fn + { + type Output = F::Output; + + extern "rust-call" fn call_once(self, args: A) -> F::Output { + (*self).call(args) + } + } + + impl<'a,A,F:?Sized> FnMut for &'a mut F + where F : FnMut + { + extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } + + impl<'a,A,F:?Sized> FnOnce for &'a mut F + where F : FnMut + { + type Output = F::Output; + extern "rust-call" fn call_once(mut self, args: A) -> F::Output { + (*self).call_mut(args) + } + } +} + +/// Trait that indicates that this is a pointer or a wrapper for one, +/// where unsizing can be performed on the pointee. +#[lang="coerce_unsized"] +pub trait CoerceUnsized { + // Empty. +} + +// &mut T -> &mut U +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} +// &mut T -> &U +impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {} +// &mut T -> *mut U +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {} +// &mut T -> *const U +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {} + +// &T -> &U +impl<'a, 'b: 'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +// &T -> *const U +impl<'a, T: ?Sized+Unsize, U: ?Sized> CoerceUnsized<*const U> for &'a T {} + +// *mut T -> *mut U +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} +// *mut T -> *const U +impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} + +// *const T -> *const U +impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} + +/// Both `in (PLACE) EXPR` and `box EXPR` desugar into expressions +/// that allocate an intermediate "place" that holds uninitialized +/// state. The desugaring evaluates EXPR, and writes the result at +/// the address returned by the `pointer` method of this trait. +/// +/// A `Place` can be thought of as a special representation for a +/// hypothetical `&uninit` reference (which Rust cannot currently +/// express directly). That is, it represents a pointer to +/// uninitialized storage. +/// +/// The client is responsible for two steps: First, initializing the +/// payload (it can access its address via `pointer`). Second, +/// converting the agent to an instance of the owning pointer, via the +/// appropriate `finalize` method (see the `InPlace`. +/// +/// If evaluating EXPR fails, then the destructor for the +/// implementation of Place to clean up any intermediate state +/// (e.g. deallocate box storage, pop a stack, etc). +pub trait Place { + /// Returns the address where the input value will be written. + /// Note that the data at this address is generally uninitialized, + /// and thus one should use `ptr::write` for initializing it. + fn pointer(&mut self) -> *mut Data; +} + +/// Interface to implementations of `in (PLACE) EXPR`. +/// +/// `in (PLACE) EXPR` effectively desugars into: +/// +/// ```rust,ignore +/// let p = PLACE; +/// let mut place = Placer::make_place(p); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// std::ptr::write(raw_place, value); +/// InPlace::finalize(place) +/// } +/// ``` +/// +/// The type of `in (PLACE) EXPR` is derived from the type of `PLACE`; +/// if the type of `PLACE` is `P`, then the final type of the whole +/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed` +/// traits). +/// +/// Values for types implementing this trait usually are transient +/// intermediate values (e.g. the return value of `Vec::emplace_back`) +/// or `Copy`, since the `make_place` method takes `self` by value. +pub trait Placer { + /// `Place` is the intermedate agent guarding the + /// uninitialized state for `Data`. + type Place: InPlace; + + /// Creates a fresh place from `self`. + fn make_place(self) -> Self::Place; +} + +/// Specialization of `Place` trait supporting `in (PLACE) EXPR`. +pub trait InPlace: Place { + /// `Owner` is the type of the end value of `in (PLACE) EXPR` + /// + /// Note that when `in (PLACE) EXPR` is solely used for + /// side-effecting an existing data-structure, + /// e.g. `Vec::emplace_back`, then `Owner` need not carry any + /// information at all (e.g. it can be the unit type `()` in that + /// case). + type Owner; + + /// Converts self into the final value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// the returned instance of `Owner` and forgetting self. + unsafe fn finalize(self) -> Self::Owner; +} + +/// Core trait for the `box EXPR` form. +/// +/// `box EXPR` effectively desugars into: +/// +/// ```rust,ignore +/// let mut place = BoxPlace::make_place(); +/// let raw_place = Place::pointer(&mut place); +/// let value = EXPR; +/// unsafe { +/// ::std::ptr::write(raw_place, value); +/// Boxed::finalize(place) +/// } +/// ``` +/// +/// The type of `box EXPR` is supplied from its surrounding +/// context; in the above expansion, the result type `T` is used +/// to determine which implementation of `Boxed` to use, and that +/// `` in turn dictates determines which +/// implementation of `BoxPlace` to use, namely: +/// `<::Place as BoxPlace>`. +pub trait Boxed { + /// The kind of data that is stored in this kind of box. + type Data; /* (`Data` unused b/c cannot yet express below bound.) */ + /// The place that will negotiate the storage of the data. + type Place: BoxPlace; + + /// Converts filled place into final owning value, shifting + /// deallocation/cleanup responsibilities (if any remain), over to + /// returned instance of `Self` and forgetting `filled`. + unsafe fn finalize(filled: Self::Place) -> Self; +} + +/// Specialization of `Place` trait supporting `box EXPR`. +pub trait BoxPlace : Place { + /// Creates a globally fresh place. + fn make_place() -> Self; +} diff --git a/avr-core/src/option.rs b/avr-core/src/option.rs new file mode 100644 index 0000000..459d5aa --- /dev/null +++ b/avr-core/src/option.rs @@ -0,0 +1,7 @@ +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)] +pub enum Option { + /// No value + None, + /// Some value `T` + Some(T) +} diff --git a/blink/.gitignore b/blink/.gitignore new file mode 100644 index 0000000..77c732d --- /dev/null +++ b/blink/.gitignore @@ -0,0 +1,2 @@ +target/ +blink.hex diff --git a/blink/Cargo.lock b/blink/Cargo.lock new file mode 100644 index 0000000..9796679 --- /dev/null +++ b/blink/Cargo.lock @@ -0,0 +1,11 @@ +[root] +name = "blink" +version = "0.1.0" +dependencies = [ + "avr-core 0.1.0", +] + +[[package]] +name = "avr-core" +version = "0.1.0" + diff --git a/blink/Cargo.toml b/blink/Cargo.toml new file mode 100644 index 0000000..e103913 --- /dev/null +++ b/blink/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "blink" +version = "0.1.0" +authors = ["Jake Goulding "] + +[dependencies.avr-core] +path = "../avr-core" diff --git a/blink/Makefile b/blink/Makefile new file mode 100644 index 0000000..6115053 --- /dev/null +++ b/blink/Makefile @@ -0,0 +1,17 @@ +COMPILED:=target/arduino/release/blink.elf +HEX:=blink.hex + +all: ${HEX} + +.PHONY: ${COMPILED} +${COMPILED}: + cargo build --release --target=./arduino.json + +# Convert binary to an Intel HEX file for upload +${HEX}: ${COMPILED} + avr-objcopy -O ihex -R .eeprom $< $@ + +# Download the HEX to the board +.PHONY: program +program: ${HEX} + avrdude -p atmega328p -c arduino -P /dev/cu.usbmodem1411 -U flash:w:$<:i diff --git a/blink/arduino.json b/blink/arduino.json new file mode 100644 index 0000000..d31feee --- /dev/null +++ b/blink/arduino.json @@ -0,0 +1,19 @@ +{ + "llvm-target": "avr-atmel-none", + "target-endian": "little", + "target-pointer-width": "16", + "os": "none", + "target-env": "gnu", + "target-vendor": "unknown", + "arch": "avr", + "data-layout": "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-i64:8:8-f32:8:8-f64:8:8-n8", + + "executables": true, + + "linker": "avr-gcc", + "pre-link-args": ["-mmcu=atmega328p", "-nostartfiles", "../interrupt_vector.S"], + "exe-suffix": ".elf", + "post-link-args": ["-Wl,--no-gc-sections"], + + "no-compiler-rt": true +} diff --git a/blink/src/main.rs b/blink/src/main.rs new file mode 100644 index 0000000..87a3533 --- /dev/null +++ b/blink/src/main.rs @@ -0,0 +1,109 @@ +#![feature(no_core)] +#![feature(asm)] + +#![no_core] +#![no_main] + +extern crate avr_core; + +use avr_core::prelude::*; +use avr_core::intrinsics::{volatile_load, volatile_store}; +use avr_core::marker::PhantomData; + +pub mod avr { + pub const DDRB: *mut u8 = 0x24 as *mut u8; + pub const PORTB: *mut u8 = 0x25 as *mut u8; + + pub const TCCR0A: *mut u8 = 0x44 as *mut u8; + pub const TCCR0B: *mut u8 = 0x45 as *mut u8; + pub const TCNT0: *mut u8 = 0x46 as *mut u8; + pub const OCR0A: *mut u8 = 0x47 as *mut u8; + pub const TIMSK0: *mut u8 = 0x6E as *mut u8; + + pub const TCCR1A: *mut u8 = 0x80 as *mut u8; + pub const TCCR1B: *mut u8 = 0x81 as *mut u8; + pub const TCCR1L: *mut u8 = 0x84 as *mut u8; + pub const TCCR1H: *mut u8 = 0x85 as *mut u8; + pub const OCR1AL: *mut u8 = 0x88 as *mut u8; + pub const OCR1AH: *mut u8 = 0x89 as *mut u8; + + pub const TCNT1L: *mut u8 = 0x84 as *mut u8; + pub const TCNT1H: *mut u8 = 0x85 as *mut u8; + + pub const TIMSK1: *mut u8 = 0x6F as *mut u8; + + // Should pins be represented in this way? + pub const PINB5: u8 = 0b0010_0000; + + pub const WGM12: u8 = 0b0000_1000; + pub const CS12: u8 = 0b0000_0100; + pub const CS10: u8 = 0b0000_0001; + pub const OCIE1A: u8 = 0b0000_0010; +} + +use avr::*; + +#[no_mangle] +pub unsafe extern "avr-interrupt" fn _ivr_timer1_compare_a() { + let prev_value = volatile_load(PORTB); + volatile_store(PORTB, prev_value ^ PINB5); +} + +struct DisableInterrupts(PhantomData<()>); + +impl DisableInterrupts { + fn new() -> DisableInterrupts { + unsafe { asm!("CLI") } + DisableInterrupts(PhantomData) + } +} + +impl Drop for DisableInterrupts { + fn drop(&mut self) { + unsafe { asm!("SEI") } + } +} + +fn without_interrupts(f: F) -> T + where F: FnOnce() -> T +{ + let _disabled = DisableInterrupts::new(); + f() +} + +#[no_mangle] +pub extern fn main() { + unsafe { + without_interrupts(|| { + // Configure all Port B pins as outputs + volatile_store(DDRB, 0xFF); + // Turn on all Port B pins + volatile_store(PORTB, 0xFF); + + // Initialize timer settings + volatile_store(TCCR1A, 0); + volatile_store(TCCR1B, 0); + + // Initialize timer counter + volatile_store(TCNT1L, 0); + volatile_store(TCNT1H, 0); + + // Set compare match register for 1hz increments (must be <65536) + // (16*10^6) / (1*1024) - 1 => 15624 => 0x3D08 + volatile_store(OCR1AH, 0x3D); + volatile_store(OCR1AL, 0x08); + + // Configure timer + let ctc_mode = WGM12; + let prescaler_1024x = CS12 | CS10; + volatile_store(TCCR1B, ctc_mode | prescaler_1024x); + + // Enable timer compare interrupt + volatile_store(TIMSK1, OCIE1A); + }); + + loop { + // forever! + } + } +} diff --git a/interrupt_vector.S b/interrupt_vector.S new file mode 100644 index 0000000..9026570 --- /dev/null +++ b/interrupt_vector.S @@ -0,0 +1,65 @@ +ivr: + jmp _ivr_reset + jmp _ivr_irq0 + jmp _ivr_irq1 + jmp _ivr_pin_change_0 + jmp _ivr_pin_change_1 + jmp _ivr_pin_change_2 + jmp _ivr_watchdog_timer + jmp _ivr_timer2_compare_a + jmp _ivr_timer2_compare_b + jmp _ivr_timer2_overflow + jmp _ivr_timer1_capture + jmp _ivr_timer1_compare_a + jmp _ivr_timer1_compare_b + jmp _ivr_timer1_overflow + jmp _ivr_timer0_compare_a + jmp _ivr_timer0_compare_b + jmp _ivr_timer0_overflow + jmp _ivr_spi_transfer_complete + jmp _ivr_usart_rx_complete + jmp _ivr_usart_udr_empty + jmp _ivr_usart_tx_complete + jmp _ivr_adc_conversion_complete + jmp _ivr_eeprom_ready + jmp _ivr_analog_comparator + jmp _ivr_two_wire_serial_interface + jmp _ivr_store_program_memory_ready + +_ivr_undefined: + reti + +;;; By default, start all interrupt handlers as doing a no-op +;;; return. Since these symbols are weakly linked, user code can +;;; override each one on demand. +.macro _ivr_default name target=_ivr_undefined +.weak \name +.set \name, \target +.endm + +_ivr_default _ivr_reset main ; Default to `main` here, no need for indirection +_ivr_default _ivr_irq0 +_ivr_default _ivr_irq1 +_ivr_default _ivr_pin_change_0 +_ivr_default _ivr_pin_change_1 +_ivr_default _ivr_pin_change_2 +_ivr_default _ivr_watchdog_timer +_ivr_default _ivr_timer2_compare_a +_ivr_default _ivr_timer2_compare_b +_ivr_default _ivr_timer2_overflow +_ivr_default _ivr_timer1_capture +_ivr_default _ivr_timer1_compare_a +_ivr_default _ivr_timer1_compare_b +_ivr_default _ivr_timer1_overflow +_ivr_default _ivr_timer0_compare_a +_ivr_default _ivr_timer0_compare_b +_ivr_default _ivr_timer0_overflow +_ivr_default _ivr_spi_transfer_complete +_ivr_default _ivr_usart_rx_complete +_ivr_default _ivr_usart_udr_empty +_ivr_default _ivr_usart_tx_complete +_ivr_default _ivr_adc_conversion_complete +_ivr_default _ivr_eeprom_ready +_ivr_default _ivr_analog_comparator +_ivr_default _ivr_two_wire_serial_interface +_ivr_default _ivr_store_program_memory_ready