<commit_before>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use crate::intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub const unsafe fn unreachable_unchecked() -> ! {
    // SAFETY: the safety contract for `intrinsics::unreachable` must
    // be upheld by the caller.
    unsafe { intrinsics::unreachable() }
}

/// Emits a machine instruction hinting to the processor that it is running in busy-wait
/// spin-loop ("spin lock").
///
/// For a discussion of different locking strategies and their trade-offs, see
/// [`core::sync::atomic::spin_loop_hint`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
    {
        #[cfg(target_arch = "x86")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
    {
        #[cfg(target_arch = "aarch64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
            // with support for the v6 feature.
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
///
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
/// certain optimizations are not desired, such as benchmarks.
///
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
///
/// [`std::convert::identity`]: ../convert/fn.identity.html
#[cfg_attr(not(miri), inline)]
#[cfg_attr(miri, inline(never))]
#[unstable(feature = "test", issue = "50297")]
#[cfg_attr(miri, allow(unused_mut))]
pub fn black_box<T>(mut dummy: T) -> T {
    // We need to "use" the argument in some way LLVM can't introspect, and on
    // targets that support it we can typically leverage inline assembly to do
    // this. LLVM's interpretation of inline assembly is that it's, well, a black
    // box. This isn't the greatest implementation since it probably deoptimizes
    // more than we want, but it's so far good enough.

    #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
    // SAFETY: the inline assembly is a no-op.
    unsafe {
        // FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
        llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
    }

    dummy
}
<commit_msg>hint doc use intra-doc links<commit_after>#![stable(feature = "core_hint", since = "1.27.0")]

//! Hints to compiler that affects how code should be emitted or optimized.

use crate::intrinsics;

/// Informs the compiler that this point in the code is not reachable, enabling
/// further optimizations.
///
/// # Safety
///
/// Reaching this function is completely *undefined behavior* (UB). In
/// particular, the compiler assumes that all UB must never happen, and
/// therefore will eliminate all branches that reach to a call to
/// `unreachable_unchecked()`.
///
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
/// `unreachable_unchecked()` call is actually reachable among all possible
/// control flow, the compiler will apply the wrong optimization strategy, and
/// may sometimes even corrupt seemingly unrelated code, causing
/// difficult-to-debug problems.
///
/// Use this function only when you can prove that the code will never call it.
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
///
/// # Example
///
/// ```
/// fn div_1(a: u32, b: u32) -> u32 {
///     use std::hint::unreachable_unchecked;
///
///     // `b.saturating_add(1)` is always positive (not zero),
///     // hence `checked_div` will never return `None`.
///     // Therefore, the else branch is unreachable.
///     a.checked_div(b.saturating_add(1))
///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
/// }
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub const unsafe fn unreachable_unchecked() -> ! {
    // SAFETY: the safety contract for `intrinsics::unreachable` must
    // be upheld by the caller.
    unsafe { intrinsics::unreachable() }
}

/// Emits a machine instruction hinting to the processor that it is running in busy-wait
/// spin-loop ("spin lock").
///
/// For a discussion of different locking strategies and their trade-offs, see
/// [`core::sync::atomic::spin_loop_hint`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
    {
        #[cfg(target_arch = "x86")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
            unsafe { crate::arch::x86::_mm_pause() };
        }

        #[cfg(target_arch = "x86_64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
            unsafe { crate::arch::x86_64::_mm_pause() };
        }
    }

    #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
    {
        #[cfg(target_arch = "aarch64")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
            unsafe { crate::arch::aarch64::__yield() };
        }
        #[cfg(target_arch = "arm")]
        {
            // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
            // with support for the v6 feature.
            unsafe { crate::arch::arm::__yield() };
        }
    }
}

/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
///
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
/// certain optimizations are not desired, such as benchmarks.
///
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
///
/// [`std::convert::identity`]: crate::convert::identity
#[cfg_attr(not(miri), inline)]
#[cfg_attr(miri, inline(never))]
#[unstable(feature = "test", issue = "50297")]
#[cfg_attr(miri, allow(unused_mut))]
pub fn black_box<T>(mut dummy: T) -> T {
    // We need to "use" the argument in some way LLVM can't introspect, and on
    // targets that support it we can typically leverage inline assembly to do
    // this. LLVM's interpretation of inline assembly is that it's, well, a black
    // box. This isn't the greatest implementation since it probably deoptimizes
    // more than we want, but it's so far good enough.

    #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
    // SAFETY: the inline assembly is a no-op.
    unsafe {
        // FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
        llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
    }

    dummy
}
<|endoftext|>


<commit_before>
extern crate getopts;
extern crate toml;

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path;

use getopts::Options;

const CONFIG: &'static str = ".plugwise.toml";
const CONFIG_HEAD: &'static str = "config";
const CONFIG_DEVICE: &'static str = "device";

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] [mac|alias]", program);
    println!("{}", opts.usage(&brief));
}

fn load_config(configfile: &path::PathBuf) -> toml::Table {
    let mut config = String::new();
    if let Ok(mut file) = File::open(configfile) {
        file.read_to_string(&mut config).ok().expect(
            &format!("unable to read file `{}`", configfile.display()));
    } // errors are silently ignored (assuming file didn't exist)
    toml::Parser::new(&config).parse().expect(&format!("unable to parse `{}`", configfile.display()))
}

fn write_config(configfile: &path::PathBuf, config: &toml::Table) {
    let mut file = File::create(configfile).ok().expect(
        &format!("unable to create `{}`", configfile.display()));
    write!(file, "{}", toml::Value::Table(config.clone())).ok().expect(
        &format!("unable to write to `{}`", configfile.display()));
}

fn get_device_from_config<'a>(config: &'a toml::Table) -> Option<&'a str> {
    config.get(CONFIG_HEAD)
          .map_or(None, |item|item.as_table())
          .map_or(None, |table|table.get(CONFIG_DEVICE))
          .map_or(None, |string|string.as_str())
}

fn update_device_from_config<'a>(config: &'a toml::Table, device: &'a str) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.insert(CONFIG_DEVICE.to_string(), toml::Value::String(device.to_string()));
    config_table
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();

    opts.optopt("s", "serial", "configure serial-port", "DEVICE")
        .optflag("t", "stub", "configure to use stub implementation") // XXX
        .optopt("a", "alias", "assign a alias to Mac", "NAME") // XXX
        .optflag("u", "unalias", "forget alias") // XXX
        .optflag("l", "list", "list aliassed circles") // XXX
        .optflag("r", "relaystatus", "print the relay status of a circle") // XXX
        .optflag("e", "enable", "enable the relay of a circle") // XXX
        .optflag("d", "disable", "disable the relay of a circle") // XXX
        .optflag("p", "powerusage", "print the actual power usage of a circle") // XXX
        .optopt("o", "powersince", "print the total power usage of a given number of days", "DAYS") // XXX
        .optflag("c", "clock", "print the internal clock value of a circle") // XXX
        .optflag("j", "updateclock", "update the internal clock of a circle using Internet time") // XXX
        .optflag("h", "help", "print this help menu") // XXX
        .optflag("v", "verbose", "print debug information"); // XXX

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let mut configfile = env::home_dir().expect("unable to find home/user directory");
    configfile.push(CONFIG);

    let mut config = load_config(&configfile);
    let mut update_config = false;

    if let Some(new_device) = matches.opt_str("s") {
        // client has provided new device; update (any) loaded configuration
        let new_config = update_device_from_config(&config, &new_device);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    }

    let device = get_device_from_config(&config);

    println!("{:?}", device); // FIXME: remove this
    // FIXME: implement more options

    if update_config {
        write_config(&configfile, &config);
    }

}
<commit_msg>circle: implement stub option<commit_after>
extern crate getopts;
extern crate toml;

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path;

use getopts::Options;

const CONFIG: &'static str = ".plugwise.toml";
const CONFIG_HEAD: &'static str = "config";
const CONFIG_DEVICE: &'static str = "device";

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] [mac|alias]", program);
    println!("{}", opts.usage(&brief));
}

fn load_config(configfile: &path::PathBuf) -> toml::Table {
    let mut config = String::new();
    if let Ok(mut file) = File::open(configfile) {
        file.read_to_string(&mut config).ok().expect(
            &format!("unable to read file `{}`", configfile.display()));
    } // errors are silently ignored (assuming file didn't exist)
    toml::Parser::new(&config).parse().expect(&format!("unable to parse `{}`", configfile.display()))
}

fn write_config(configfile: &path::PathBuf, config: &toml::Table) {
    let mut file = File::create(configfile).ok().expect(
        &format!("unable to create `{}`", configfile.display()));
    write!(file, "{}", toml::Value::Table(config.clone())).ok().expect(
        &format!("unable to write to `{}`", configfile.display()));
}

fn get_device_from_config<'a>(config: &'a toml::Table) -> Option<&'a str> {
    config.get(CONFIG_HEAD)
          .map_or(None, |item|item.as_table())
          .map_or(None, |table|table.get(CONFIG_DEVICE))
          .map_or(None, |string|string.as_str())
}

fn update_device_from_config<'a>(config: &'a toml::Table, device: &'a str) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.insert(CONFIG_DEVICE.to_string(), toml::Value::String(device.to_string()));
    config_table
}

fn remove_device_from_config<'a>(config: &'a toml::Table) -> toml::Table {
    let mut config_table = config.get(CONFIG_HEAD)
                                 .map_or(None, |item|item.as_table())
                                 .map_or(toml::Table::new(), |table|table.clone());
    config_table.remove(CONFIG_DEVICE);
    config_table
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();

    opts.optopt("s", "serial", "configure serial-port", "DEVICE")
        .optflag("t", "stub", "configure to use stub implementation")
        .optopt("a", "alias", "assign a alias to Mac", "NAME") // XXX
        .optflag("u", "unalias", "forget alias") // XXX
        .optflag("l", "list", "list aliassed circles") // XXX
        .optflag("r", "relaystatus", "print the relay status of a circle") // XXX
        .optflag("e", "enable", "enable the relay of a circle") // XXX
        .optflag("d", "disable", "disable the relay of a circle") // XXX
        .optflag("p", "powerusage", "print the actual power usage of a circle") // XXX
        .optopt("o", "powersince", "print the total power usage of a given number of days", "DAYS") // XXX
        .optflag("c", "clock", "print the internal clock value of a circle") // XXX
        .optflag("j", "updateclock", "update the internal clock of a circle using Internet time") // XXX
        .optflag("h", "help", "print this help menu") // XXX
        .optflag("v", "verbose", "print debug information"); // XXX

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }

    let mut configfile = env::home_dir().expect("unable to find home/user directory");
    configfile.push(CONFIG);

    let mut config = load_config(&configfile);
    let mut update_config = false;

    if let Some(new_device) = matches.opt_str("s") {
        // client has provided new device; update (any) loaded configuration
        let new_config = update_device_from_config(&config, &new_device);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    } else if matches.opt_present("t") {
        // client has indicated to use stub
        let new_config = remove_device_from_config(&config);
        config.insert(CONFIG_HEAD.to_string(), toml::Value::Table(new_config));
        update_config = true;
    }

    let device = get_device_from_config(&config);

    println!("{:?}", device); // FIXME: remove this
    // FIXME: implement more options

    if update_config {
        write_config(&configfile, &config);
    }

}
<|endoftext|>


<commit_before>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate glfw;

use glfw::{Action, Context, Key};

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::WindowHint::Resizable(true));

    let (mut window, events) = glfw.create_window(800, 600, "Hello, I am a window.", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.set_sticky_keys(true);

    // Polling of events can be turned on and off by the specific event type
    window.set_pos_polling(true);
    window.set_all_polling(true);
    window.set_size_polling(true);
    window.set_close_polling(true);
    window.set_refresh_polling(true);
    window.set_focus_polling(true);
    window.set_iconify_polling(true);
    window.set_framebuffer_size_polling(true);
    window.set_key_polling(true);
    window.set_char_polling(true);
    window.set_char_mods_polling(true);
    window.set_mouse_button_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_cursor_enter_polling(true);
    window.set_scroll_polling(true);

    // Alternatively, all event types may be set to poll at once. Note that
    // in this example, this call is redundant as all events have been set
    // to poll in the above code.
    window.set_all_polling(true);

    window.make_current();

    while !window.should_close() {
        glfw.poll_events();
        for event in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }
    }
}

fn handle_window_event(window: &mut glfw::Window, (time, event): (f64, glfw::WindowEvent)) {
    match event {
        glfw::WindowEvent::Pos(x, y)                      => window.set_title(&format!("Time: {:?}, Window pos: ({:?}, {:?})", time, x, y)),
        glfw::WindowEvent::Size(w, h)                     => window.set_title(&format!("Time: {:?}, Window size: ({:?}, {:?})", time, w, h)),
        glfw::WindowEvent::Close                          => println!("Time: {:?}, Window close requested.", time),
        glfw::WindowEvent::Refresh                        => println!("Time: {:?}, Window refresh callback triggered.", time),
        glfw::WindowEvent::Focus(true)                    => println!("Time: {:?}, Window focus gained.", time),
        glfw::WindowEvent::Focus(false)                   => println!("Time: {:?}, Window focus lost.", time),
        glfw::WindowEvent::Iconify(true)                  => println!("Time: {:?}, Window was minimised", time),
        glfw::WindowEvent::Iconify(false)                 => println!("Time: {:?}, Window was maximised.", time),
        glfw::WindowEvent::FramebufferSize(w, h)          => println!("Time: {:?}, Framebuffer size: ({:?}, {:?})", time, w, h),
        glfw::WindowEvent::Char(character)                => println!("Time: {:?}, Character: {:?}", time, character),
        glfw::WindowEvent::CharModifiers(character, mods) => println!("Time: {:?}, Character: {:?}, Modifiers: [{:?}]", time, character, mods),
        glfw::WindowEvent::MouseButton(btn, action, mods) => println!("Time: {:?}, Button: {:?}, Action: {:?}, Modifiers: [{:?}]", time, glfw::DebugAliases(btn), action, mods),
        glfw::WindowEvent::CursorPos(xpos, ypos)          => window.set_title(&format!("Time: {:?}, Cursor position: ({:?}, {:?})", time, xpos, ypos)),
        glfw::WindowEvent::CursorEnter(true)              => println!("Time: {:?}, Cursor entered window.", time),
        glfw::WindowEvent::CursorEnter(false)             => println!("Time: {:?}, Cursor left window.", time),
        glfw::WindowEvent::Scroll(x, y)                   => window.set_title(&format!("Time: {:?}, Scroll offset: ({:?}, {:?})", time, x, y)),
        glfw::WindowEvent::Key(key, scancode, action, mods) => {
            println!("Time: {:?}, Key: {:?}, ScanCode: {:?}, Action: {:?}, Modifiers: [{:?}]", time, key, scancode, action, mods);
            match (key, action) {
                (Key::Escape, Action::Press) => window.set_should_close(true),
                (Key::R, Action::Press) => {
                    // Resize should cause the window to "refresh"
                    let (window_width, window_height) = window.get_size();
                    window.set_size(window_width + 1, window_height);
                    window.set_size(window_width, window_height);
                }
                _ => {}
            }
        }
        glfw::WindowEvent::FileDrop(paths)                => println!("Time: {:?}, Files dropped: {:?}", time, paths),
    }
}
<commit_msg>Fix events example<commit_after>// Copyright 2013 The GLFW-RS Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate glfw;

use glfw::{Action, Context, Key};

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::WindowHint::Resizable(true));

    let (mut window, events) = glfw.create_window(800, 600, "Hello, I am a window.", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.set_sticky_keys(true);

    // Polling of events can be turned on and off by the specific event type
    window.set_pos_polling(true);
    window.set_all_polling(true);
    window.set_size_polling(true);
    window.set_close_polling(true);
    window.set_refresh_polling(true);
    window.set_focus_polling(true);
    window.set_iconify_polling(true);
    window.set_framebuffer_size_polling(true);
    window.set_key_polling(true);
    window.set_char_polling(true);
    window.set_char_mods_polling(true);
    window.set_mouse_button_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_cursor_enter_polling(true);
    window.set_scroll_polling(true);
    window.set_maximize_polling(true);
    window.set_content_scale_polling(true);

    // Alternatively, all event types may be set to poll at once. Note that
    // in this example, this call is redundant as all events have been set
    // to poll in the above code.
    window.set_all_polling(true);

    window.make_current();

    while !window.should_close() {
        glfw.poll_events();
        for event in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }
    }
}

fn handle_window_event(window: &mut glfw::Window, (time, event): (f64, glfw::WindowEvent)) {
    match event {
        glfw::WindowEvent::Pos(x, y)                      => window.set_title(&format!("Time: {:?}, Window pos: ({:?}, {:?})", time, x, y)),
        glfw::WindowEvent::Size(w, h)                     => window.set_title(&format!("Time: {:?}, Window size: ({:?}, {:?})", time, w, h)),
        glfw::WindowEvent::Close                          => println!("Time: {:?}, Window close requested.", time),
        glfw::WindowEvent::Refresh                        => println!("Time: {:?}, Window refresh callback triggered.", time),
        glfw::WindowEvent::Focus(true)                    => println!("Time: {:?}, Window focus gained.", time),
        glfw::WindowEvent::Focus(false)                   => println!("Time: {:?}, Window focus lost.", time),
        glfw::WindowEvent::Iconify(true)                  => println!("Time: {:?}, Window was minimised", time),
        glfw::WindowEvent::Iconify(false)                 => println!("Time: {:?}, Window was maximised.", time),
        glfw::WindowEvent::FramebufferSize(w, h)          => println!("Time: {:?}, Framebuffer size: ({:?}, {:?})", time, w, h),
        glfw::WindowEvent::Char(character)                => println!("Time: {:?}, Character: {:?}", time, character),
        glfw::WindowEvent::CharModifiers(character, mods) => println!("Time: {:?}, Character: {:?}, Modifiers: [{:?}]", time, character, mods),
        glfw::WindowEvent::MouseButton(btn, action, mods) => println!("Time: {:?}, Button: {:?}, Action: {:?}, Modifiers: [{:?}]", time, glfw::DebugAliases(btn), action, mods),
        glfw::WindowEvent::CursorPos(xpos, ypos)          => window.set_title(&format!("Time: {:?}, Cursor position: ({:?}, {:?})", time, xpos, ypos)),
        glfw::WindowEvent::CursorEnter(true)              => println!("Time: {:?}, Cursor entered window.", time),
        glfw::WindowEvent::CursorEnter(false)             => println!("Time: {:?}, Cursor left window.", time),
        glfw::WindowEvent::Scroll(x, y)                   => window.set_title(&format!("Time: {:?}, Scroll offset: ({:?}, {:?})", time, x, y)),
        glfw::WindowEvent::Key(key, scancode, action, mods) => {
            println!("Time: {:?}, Key: {:?}, ScanCode: {:?}, Action: {:?}, Modifiers: [{:?}]", time, key, scancode, action, mods);
            match (key, action) {
                (Key::Escape, Action::Press) => window.set_should_close(true),
                (Key::R, Action::Press) => {
                    // Resize should cause the window to "refresh"
                    let (window_width, window_height) = window.get_size();
                    window.set_size(window_width + 1, window_height);
                    window.set_size(window_width, window_height);
                }
                _ => {}
            }
        }
        glfw::WindowEvent::FileDrop(paths)                => println!("Time: {:?}, Files dropped: {:?}", time, paths),
        glfw::WindowEvent::Maximize(maximized) => println!("Time: {:?}, Window maximized: {:?}.", time, maximized),
        glfw::WindowEvent::ContentScale(xscale, yscale) => println!("Time: {:?}, Content scale x: {:?}, Content scale y: {:?}", time, xscale, yscale),
    }
}
<|endoftext|>


<commit_before>use turtle::{Angle, Color, Distance, Drawing, Point, Size, Turtle};

trait CubicBezier {
    const DEFAULT_SAMPLES: usize = 100;

    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]);
    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]);

    fn bezier_abs(&mut self, points: [Point; 4]) {
        self.bezier_abs_pr(Self::DEFAULT_SAMPLES, points)
    }

    fn bezier_rel(&mut self, rel_points: [Point; 3]) {
        self.bezier_rel_pr(Self::DEFAULT_SAMPLES, rel_points)
    }

    fn curve_at(t: f64, points: [Point; 4]) -> Point {
        (1.0 - t).powi(3) * points[0]
            + 3.0 * (1.0 - t).powi(2) * t * points[1]
            + 3.0 * (1.0 - t) * t.powi(2) * points[2]
            + t.powi(3) * points[3]
    }
}

impl CubicBezier for Turtle {
    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]) {
        (0..=samples)
            .map(|i| i as f64 / samples as f64)
            .map(|t| Self::curve_at(t, points))
            .for_each(|point| {
                self.turn_towards(point);
                self.go_to(point);
            })
    }

    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]) {
        let pos = self.position();
        self.bezier_abs_pr(
            samples,
            [
                pos,
                pos + rel_points[0],
                pos + rel_points[1],
                pos + rel_points[2],
            ],
        )
    }
}

const FRONT_SHELL_COLOR: &str = "#f74c00";
const BACK_SHELL_COLOR: &str = "#a52b00";
const PUPIL_COLOR: &str = "#ffffff";
const MOUTH_COLOR: &str = "#000000";
const ORIGINAL_SIZE: Size = Size {
    width: 1200,
    height: 800,
};

fn adapt_point(point: impl Into<Point>, size: Size) -> Point {
    let point = point.into();
    Point {
        x: size.width as f64 * point.x / ORIGINAL_SIZE.width as f64,
        y: -(size.height as f64) * point.y / ORIGINAL_SIZE.height as f64,
    }
}

fn rel_points(abs_points: [Point; 4]) -> [Point; 3] {
    [
        abs_points[1] - abs_points[0],
        abs_points[2] - abs_points[0],
        abs_points[3] - abs_points[0],
    ]
}

fn adapt_distance(distance: Distance, angle: Angle, size: Size) -> Distance {
    ((distance * angle.cos() * size.width as f64 / ORIGINAL_SIZE.width as f64).powi(2)
        + (distance * angle.sin() * size.height as f64 / ORIGINAL_SIZE.height as f64).powi(2))
    .sqrt()
}

fn main() {
    let mut drawing = Drawing::new();
    let size = drawing.size();
    drawing.set_center([size.width as f64 / 2.0, -(size.height as f64) / 2.0]);

    let mut turtle = drawing.add_turtle();
    turtle.use_radians();
    turtle.pen_up();

    let rp = rel_points;
    let ap = |point| adapt_point(point, size);
    let ad = |distance, angle| adapt_distance(distance, angle, size);

    // turtle.bezier_rel(rp([
    //     ap([]),
    //     ap([]),
    //     ap([]),
    //     ap([]),
    // ]));
}
<commit_msg>Add back shell part of Ferris example<commit_after>use turtle::{Angle, Color, Distance, Drawing, Point, Size, Turtle};

trait CubicBezier {
    const DEFAULT_SAMPLES: usize = 100;

    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]);
    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]);

    fn bezier_abs(&mut self, points: [Point; 4]) {
        self.bezier_abs_pr(Self::DEFAULT_SAMPLES, points)
    }

    fn bezier_rel(&mut self, rel_points: [Point; 3]) {
        self.bezier_rel_pr(Self::DEFAULT_SAMPLES, rel_points)
    }

    fn curve_at(t: f64, points: [Point; 4]) -> Point {
        (1.0 - t).powi(3) * points[0]
            + 3.0 * (1.0 - t).powi(2) * t * points[1]
            + 3.0 * (1.0 - t) * t.powi(2) * points[2]
            + t.powi(3) * points[3]
    }
}

impl CubicBezier for Turtle {
    fn bezier_abs_pr(&mut self, samples: usize, points: [Point; 4]) {
        (0..=samples)
            .map(|i| i as f64 / samples as f64)
            .map(|t| Self::curve_at(t, points))
            .for_each(|point| {
                self.turn_towards(point);
                self.go_to(point);
            })
    }

    fn bezier_rel_pr(&mut self, samples: usize, rel_points: [Point; 3]) {
        let pos = self.position();
        self.bezier_abs_pr(
            samples,
            [
                pos,
                pos + rel_points[0],
                pos + rel_points[1],
                pos + rel_points[2],
            ],
        )
    }
}

const FRONT_SHELL_COLOR: &str = "#f74c00";
const BACK_SHELL_COLOR: &str = "#a52b00";
const PUPIL_COLOR: &str = "#ffffff";
const MOUTH_COLOR: &str = "#000000";
const ORIGINAL_SIZE: Size = Size {
    width: 1200,
    height: 800,
};

fn adapt_point(point: impl Into<Point>, size: Size) -> Point {
    let point = point.into();
    Point {
        x: size.width as f64 * point.x / ORIGINAL_SIZE.width as f64,
        y: -(size.height as f64) * point.y / ORIGINAL_SIZE.height as f64,
    }
}

fn rel_points(abs_points: [Point; 4]) -> [Point; 3] {
    [
        abs_points[1] - abs_points[0],
        abs_points[2] - abs_points[0],
        abs_points[3] - abs_points[0],
    ]
}

fn adapt_distance(distance: Distance, angle: Angle, size: Size) -> Distance {
    ((distance * angle.cos() * size.width as f64 / ORIGINAL_SIZE.width as f64).powi(2)
        + (distance * angle.sin() * size.height as f64 / ORIGINAL_SIZE.height as f64).powi(2))
    .sqrt()
}

fn main() {
    let mut drawing = Drawing::new();
    let size = drawing.size();
    drawing.set_center([size.width as f64 / 2.0, -(size.height as f64) / 2.0]);

    let mut turtle = drawing.add_turtle();
    turtle.use_radians();
    turtle.pen_up();

    let rp = rel_points;
    let ap = |point| adapt_point(point, size);
    let ad = |distance, angle| adapt_distance(distance, angle, size);

    let start_point = ap([240.0, 504.0]);
    turtle.set_fill_color(BACK_SHELL_COLOR);
    turtle.set_speed("instant");
    turtle.turn_towards(start_point);
    turtle.go_to(start_point);
    turtle.set_speed("faster");
    turtle.begin_fill();

    let start_heading = (180.0 + 32.01f64).to_radians();
    turtle.set_heading(start_heading);
    turtle.forward(ad(18.9, start_heading));
    turtle.bezier_rel(rp([
        ap([223.64, 514.18]),
        ap([222.18, 525.09]),
        ap([288.00, 597.09]),
        ap([323.94, 645.06]),
    ]));
    turtle.bezier_rel(rp([
        ap([323.91, 645.18]),
        ap([324.00, 623.09]),
        ap([283.27, 565.27]),
        ap([270.69, 529.94]),
    ]));
    turtle.bezier_rel(rp([
        ap([270.75, 529.94]),
        ap([444.75, 621.50]),
        ap([826.25, 622.50]),
        ap([973.09, 515.22]),
    ]));
    turtle.bezier_rel(rp([
        ap([973.12, 515.25]),
        ap([965.45, 552.18]),
        ap([923.09, 619.45]),
        ap([922.09, 646.52]),
    ]));
    turtle.bezier_rel(rp([
        ap([922.38, 647.00]),
        ap([931.09, 631.09]),
        ap([988.91, 554.55]),
        ap([1008.00, 517.12]),
    ]));
    let middle_curve_part1 = rp([
        ap([1008.12, 517.06]),
        ap([979.25, 500.88]),
        ap([960.12, 507.19]),
        ap([946.69, 510.31]),
    ]);
    turtle.bezier_rel(middle_curve_part1);
    let middle_curve_part2 = rp([
        ap([946.66, 510.41]),
        ap([750.73, 606.91]),
        ap([472.55, 603.45]),
        ap([239.57, 505.39]),
    ]);
    turtle.bezier_rel(middle_curve_part2);

    turtle.end_fill();
}
<|endoftext|>


<commit_before>use std::mem;

use cbox::{CSemiBox, DisposeRef};
use ffi::prelude::{LLVMBuilderRef, LLVMValueRef};
use ffi::{core, LLVMBuilder, LLVMRealPredicate, LLVMIntPredicate};
use libc::{c_char, c_uint};

use context::Context;
use block::BasicBlock;
use ty::Type;
use value::{Function, Value, Predicate};

static NULL_NAME:[c_char; 1] = [0];

/// This provides a uniform API for creating instructions and inserting them into a basic block.
pub struct Builder;
native_ref!(&Builder = LLVMBuilderRef);

macro_rules! bin_op (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, left: &Value, right: &Value) -> &Value
    {
      unsafe { core::$func(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()) }.into()
    }
  );
  ($name:ident, $ifunc:ident, $ffunc:ident) => (
    pub fn $name(&self, left: &Value, right: &Value) -> &Value {
      let ty = left.get_type();
      unsafe {
        (if ty.is_integer() {
           core::$ifunc
         } else {
           core::$ffunc
         })(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()).into()
      }
    }
  );
);

macro_rules! unary_op (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, value: &Value) -> &Value {
      unsafe { core::$func(self.into(), value.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
    }
  );
);

impl Builder
{
  /// Create a new builder in the context given.
  pub fn new(context: &Context) -> CSemiBox<Builder>
  {
    CSemiBox::new(unsafe { core::LLVMCreateBuilderInContext(context.into()) }.into())
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.into(), block.into()) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> &Value
  {
    unsafe { core::LLVMBuildRetVoid(self.into()) }.into()
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> &Value
  {
    unsafe { core::LLVMBuildRet(self.into(), value.into()) }.into()
  }

  /// Build an instruction that allocates an array with the element type `elem` and the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Type, size: &Value) -> &Value
  {
    unsafe {
    	core::LLVMBuildArrayAlloca(self.into(),
    														 elem.into(),
    														 size.into(),
    														 NULL_NAME.as_ptr() as *const c_char)
    }.into()
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Type) -> &Value
  {
    unsafe {
    	core::LLVMBuildAlloca(self.into(),
    												ty.into(),
    												NULL_NAME.as_ptr() as *const c_char)
    }.into()
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> &Value
  {
    unsafe { core::LLVMBuildFree(self.into(), val.into()) }.into()
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> &Value
  {
    unsafe { core::LLVMBuildStore(self.into(), val.into(), ptr.into()) }.into()
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> &Value
  {
    unsafe { core::LLVMBuildBr(self.into(), dest.into()).into() }
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> &Value
  {
    unsafe {
    	core::LLVMBuildCondBr(self.into(),
    		                    cond.into(),
    		                    if_block.into(),
    		                    mem::transmute(else_block)).into()
    }
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> &Value
  {
    unsafe {
        let call = core::LLVMBuildCall(self.into(),
        	                             func.into(), args.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, 0);
        call.into()
    }
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> &Value
  {
    unsafe {
        let call = core::LLVMBuildCall(self.into(),
        	                             func.into(), args.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, 1);
        call.into()
    }
  }
  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val` otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> &Value
  {
    unsafe {
    	core::LLVMBuildSelect(self.into(),
    		                    cond.into(),
    		                    true_val.into(),
    		                    false_val.into(),
    		                    NULL_NAME.as_ptr()).into() }
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Type) -> &Value
  {
    unsafe { core::LLVMBuildBitCast(
    		self.into(),
    		value.into(),
    		dest.into(),
    		NULL_NAME.as_ptr()).into()
    }
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> &Value
  {
    unsafe {
    	core::LLVMBuildInsertValue(self.into(),
    		                         agg.into(),
    		                         elem.into(),
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr()).into()
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> &Value
  {
    unsafe {
    	core::LLVMBuildInBoundsGEP(self.into(),
    	                           pointer.into(),
    	                           indices.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr()).into()
    }
  }
  /// Build an instruction that runs whichever block matches the value, or `default` if none of them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> &Value
  {
    unsafe {
      let switch = core::LLVMBuildSwitch(self.into(),
      	                                 value.into(),
      	                                 default.into(),
      	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, case.0.into(), case.1.into());
      }
      switch.into()
    }
  }

  unary_op!{create_load, LLVMBuildLoad}
  unary_op!{create_neg, LLVMBuildNeg}
  unary_op!{create_not, LLVMBuildNot}

  bin_op!{create_add, LLVMBuildAdd, LLVMBuildFAdd}
  bin_op!{create_sub, LLVMBuildSub, LLVMBuildFSub}
  bin_op!{create_mul, LLVMBuildMul, LLVMBuildFMul}
  bin_op!{create_div, LLVMBuildSDiv, LLVMBuildFDiv}
  bin_op!{create_shl, LLVMBuildShl}
  bin_op!{create_ashr, LLVMBuildAShr}
  bin_op!{create_and, LLVMBuildAnd}
  bin_op!{create_or, LLVMBuildOr}

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, a: &Value, b: &Value, pred: Predicate) -> &Value
  {
    let (at, bt) = (a.get_type(), b.get_type());
    assert_eq!(at, bt);

    if at.is_integer() {
      let pred = match pred {
          Predicate::Equal => LLVMIntPredicate::LLVMIntEQ,
          Predicate::NotEqual => LLVMIntPredicate::LLVMIntNE,
          Predicate::GreaterThan => LLVMIntPredicate::LLVMIntSGT,
          Predicate::GreaterThanOrEqual => LLVMIntPredicate::LLVMIntSGE,
          Predicate::LessThan => LLVMIntPredicate::LLVMIntSLT,
          Predicate::LessThanOrEqual => LLVMIntPredicate::LLVMIntSLE
      };
      unsafe {
      	core::LLVMBuildICmp(self.into(),
      		                  pred,
      		                  a.into(), b.into(),
      		                  NULL_NAME.as_ptr())
      }.into()

    } else if at.is_float() {
      let pred = match pred {
          Predicate::Equal => LLVMRealPredicate::LLVMRealOEQ,
          Predicate::NotEqual => LLVMRealPredicate::LLVMRealONE,
          Predicate::GreaterThan => LLVMRealPredicate::LLVMRealOGT,
          Predicate::GreaterThanOrEqual => LLVMRealPredicate::LLVMRealOGE,
          Predicate::LessThan => LLVMRealPredicate::LLVMRealOLT,
          Predicate::LessThanOrEqual => LLVMRealPredicate::LLVMRealOLE
      };
      unsafe {
      	core::LLVMBuildFCmp(self.into(),
      		                 pred, a.into(), b.into(),
      		                 NULL_NAME.as_ptr())
      }.into()

    } else {
        panic!("expected numbers, got {:?}", at)
    }
  }
}

impl DisposeRef for Builder {
  type RefTo = LLVMBuilder;
  #[inline(always)]
  unsafe fn dispose(ptr: LLVMBuilderRef) {
      core::LLVMDisposeBuilder(ptr)
  }
}
<commit_msg>Add create_xor to Builder.<commit_after>use std::mem;

use cbox::{CSemiBox, DisposeRef};
use ffi::prelude::{LLVMBuilderRef, LLVMValueRef};
use ffi::{core, LLVMBuilder, LLVMRealPredicate, LLVMIntPredicate};
use libc::{c_char, c_uint};

use context::Context;
use block::BasicBlock;
use ty::Type;
use value::{Function, Value, Predicate};

static NULL_NAME:[c_char; 1] = [0];

/// This provides a uniform API for creating instructions and inserting them into a basic block.
pub struct Builder;
native_ref!(&Builder = LLVMBuilderRef);

macro_rules! bin_op (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, left: &Value, right: &Value) -> &Value
    {
      unsafe { core::$func(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()) }.into()
    }
  );
  ($name:ident, $ifunc:ident, $ffunc:ident) => (
    pub fn $name(&self, left: &Value, right: &Value) -> &Value {
      let ty = left.get_type();
      unsafe {
        (if ty.is_integer() {
           core::$ifunc
         } else {
           core::$ffunc
         })(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()).into()
      }
    }
  );
);

macro_rules! unary_op (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, value: &Value) -> &Value {
      unsafe { core::$func(self.into(), value.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
    }
  );
);

impl Builder
{
  /// Create a new builder in the context given.
  pub fn new(context: &Context) -> CSemiBox<Builder>
  {
    CSemiBox::new(unsafe { core::LLVMCreateBuilderInContext(context.into()) }.into())
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.into(), block.into()) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> &Value
  {
    unsafe { core::LLVMBuildRetVoid(self.into()) }.into()
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> &Value
  {
    unsafe { core::LLVMBuildRet(self.into(), value.into()) }.into()
  }

  /// Build an instruction that allocates an array with the element type `elem` and the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Type, size: &Value) -> &Value
  {
    unsafe {
    	core::LLVMBuildArrayAlloca(self.into(),
    														 elem.into(),
    														 size.into(),
    														 NULL_NAME.as_ptr() as *const c_char)
    }.into()
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Type) -> &Value
  {
    unsafe {
    	core::LLVMBuildAlloca(self.into(),
    												ty.into(),
    												NULL_NAME.as_ptr() as *const c_char)
    }.into()
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> &Value
  {
    unsafe { core::LLVMBuildFree(self.into(), val.into()) }.into()
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> &Value
  {
    unsafe { core::LLVMBuildStore(self.into(), val.into(), ptr.into()) }.into()
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> &Value
  {
    unsafe { core::LLVMBuildBr(self.into(), dest.into()).into() }
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> &Value
  {
    unsafe {
    	core::LLVMBuildCondBr(self.into(),
    		                    cond.into(),
    		                    if_block.into(),
    		                    mem::transmute(else_block)).into()
    }
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> &Value
  {
    unsafe {
        let call = core::LLVMBuildCall(self.into(),
        	                             func.into(), args.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, 0);
        call.into()
    }
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> &Value
  {
    unsafe {
        let call = core::LLVMBuildCall(self.into(),
        	                             func.into(), args.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, 1);
        call.into()
    }
  }
  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val` otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> &Value
  {
    unsafe {
    	core::LLVMBuildSelect(self.into(),
    		                    cond.into(),
    		                    true_val.into(),
    		                    false_val.into(),
    		                    NULL_NAME.as_ptr()).into() }
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Type) -> &Value
  {
    unsafe { core::LLVMBuildBitCast(
    		self.into(),
    		value.into(),
    		dest.into(),
    		NULL_NAME.as_ptr()).into()
    }
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> &Value
  {
    unsafe {
    	core::LLVMBuildInsertValue(self.into(),
    		                         agg.into(),
    		                         elem.into(),
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr()).into()
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> &Value
  {
    unsafe {
    	core::LLVMBuildInBoundsGEP(self.into(),
    	                           pointer.into(),
    	                           indices.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr()).into()
    }
  }
  /// Build an instruction that runs whichever block matches the value, or `default` if none of them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> &Value
  {
    unsafe {
      let switch = core::LLVMBuildSwitch(self.into(),
      	                                 value.into(),
      	                                 default.into(),
      	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, case.0.into(), case.1.into());
      }
      switch.into()
    }
  }

  unary_op!{create_load, LLVMBuildLoad}
  unary_op!{create_neg, LLVMBuildNeg}
  unary_op!{create_not, LLVMBuildNot}

  bin_op!{create_add, LLVMBuildAdd, LLVMBuildFAdd}
  bin_op!{create_sub, LLVMBuildSub, LLVMBuildFSub}
  bin_op!{create_mul, LLVMBuildMul, LLVMBuildFMul}
  bin_op!{create_div, LLVMBuildSDiv, LLVMBuildFDiv}
  bin_op!{create_shl, LLVMBuildShl}
  bin_op!{create_ashr, LLVMBuildAShr}
  bin_op!{create_and, LLVMBuildAnd}
  bin_op!{create_or, LLVMBuildOr}
  bin_op!{create_xor, LLVMBuildXor}

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, a: &Value, b: &Value, pred: Predicate) -> &Value
  {
    let (at, bt) = (a.get_type(), b.get_type());
    assert_eq!(at, bt);

    if at.is_integer() {
      let pred = match pred {
          Predicate::Equal => LLVMIntPredicate::LLVMIntEQ,
          Predicate::NotEqual => LLVMIntPredicate::LLVMIntNE,
          Predicate::GreaterThan => LLVMIntPredicate::LLVMIntSGT,
          Predicate::GreaterThanOrEqual => LLVMIntPredicate::LLVMIntSGE,
          Predicate::LessThan => LLVMIntPredicate::LLVMIntSLT,
          Predicate::LessThanOrEqual => LLVMIntPredicate::LLVMIntSLE
      };
      unsafe {
      	core::LLVMBuildICmp(self.into(),
      		                  pred,
      		                  a.into(), b.into(),
      		                  NULL_NAME.as_ptr())
      }.into()

    } else if at.is_float() {
      let pred = match pred {
          Predicate::Equal => LLVMRealPredicate::LLVMRealOEQ,
          Predicate::NotEqual => LLVMRealPredicate::LLVMRealONE,
          Predicate::GreaterThan => LLVMRealPredicate::LLVMRealOGT,
          Predicate::GreaterThanOrEqual => LLVMRealPredicate::LLVMRealOGE,
          Predicate::LessThan => LLVMRealPredicate::LLVMRealOLT,
          Predicate::LessThanOrEqual => LLVMRealPredicate::LLVMRealOLE
      };
      unsafe {
      	core::LLVMBuildFCmp(self.into(),
      		                 pred, a.into(), b.into(),
      		                 NULL_NAME.as_ptr())
      }.into()

    } else {
        panic!("expected numbers, got {:?}", at)
    }
  }
}

impl DisposeRef for Builder {
  type RefTo = LLVMBuilder;
  #[inline(always)]
  unsafe fn dispose(ptr: LLVMBuilderRef) {
      core::LLVMDisposeBuilder(ptr)
  }
}
<|endoftext|>


<commit_before>use nom::*;
use std::str;
use std::str::FromStr;
use std::str::Utf8Error;

mod token;
use lexer::token::*;

// operators
named!(equal_operator<&[u8], Token>,
  do_parse!(tag!("==") >> (Token::Equal))
);

named!(not_equal_operator<&[u8], Token>,
  do_parse!(tag!("!=") >> (Token::NotEqual))
);

named!(assign_operator<&[u8], Token>,
  do_parse!(tag!("=") >> (Token::Assign))
);

named!(plus_operator<&[u8], Token>,
  do_parse!(tag!("+") >> (Token::Plus))
);

named!(minus_operator<&[u8], Token>,
  do_parse!(tag!("-") >> (Token::Minus))
);

named!(multiply_operator<&[u8], Token>,
  do_parse!(tag!("*") >> (Token::Multiply))
);

named!(divide_operator<&[u8], Token>,
  do_parse!(tag!("/") >> (Token::Divide))
);

named!(not_operator<&[u8], Token>,
  do_parse!(tag!("!") >> (Token::Not))
);

named!(greater_operator<&[u8], Token>,
  do_parse!(tag!(">") >> (Token::GreaterThan))
);

named!(lesser_operator<&[u8], Token>,
  do_parse!(tag!("<") >> (Token::LessThan))
);

named!(lex_operator<&[u8], Token>, alt!(
    equal_operator |
    not_equal_operator |
    assign_operator |
    plus_operator |
    minus_operator |
    multiply_operator |
    divide_operator |
    not_operator |
    greater_operator |
    lesser_operator
));

// punctuations
named!(comma_punctuation<&[u8], Token>,
  do_parse!(tag!(",") >> (Token::Comma))
);

named!(semicolon_punctuation<&[u8], Token>,
  do_parse!(tag!(";") >> (Token::SemiColon))
);

named!(colon_punctuation<&[u8], Token>,
  do_parse!(tag!(":") >> (Token::Colon))
);

named!(lparen_punctuation<&[u8], Token>,
  do_parse!(tag!("(") >> (Token::LParen))
);

named!(rparen_punctuation<&[u8], Token>,
  do_parse!(tag!(")") >> (Token::RParen))
);

named!(lbrace_punctuation<&[u8], Token>,
  do_parse!(tag!("{") >> (Token::LBrace))
);

named!(rbrace_punctuation<&[u8], Token>,
  do_parse!(tag!("}") >> (Token::RBrace))
);

named!(lbracket_punctuation<&[u8], Token>,
  do_parse!(tag!("[") >> (Token::LBracket))
);

named!(rbracket_punctuation<&[u8], Token>,
  do_parse!(tag!("]") >> (Token::RBracket))
);

named!(lex_punctuations<&[u8], Token>, alt!(
    comma_punctuation |
    semicolon_punctuation |
    colon_punctuation |
    lparen_punctuation |
    rparen_punctuation |
    lbrace_punctuation |
    rbrace_punctuation |
    lbracket_punctuation |
    rbracket_punctuation
));

// Strings
fn pis(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
    let (i1, c1) = try_parse!(input, take!(1));
    match c1 {
        b"\"" => IResult::Done(input, vec![]),
        b"\\" => {
            let (i2, c2) = try_parse!(i1, take!(1));
            pis(i2).map(|done| concat_slice_vec(c2, done))
        },
        c => pis(i1).map(|done| concat_slice_vec(c, done)),
    }
}

fn concat_slice_vec(c: &[u8], done: Vec<u8>) -> Vec<u8> {
    let mut new_vec = c.to_vec();
    new_vec.extend(&done);
    new_vec
}

fn convert_vec_utf8(v: Vec<u8>) -> Result<String, Utf8Error> {
    let slice = v.as_slice();
    str::from_utf8(slice).map(|s| s.to_owned())
}

named!(string<String>,
  delimited!(
    tag!("\""),
    map_res!(pis, convert_vec_utf8),
    tag!("\"")
  )
);

named!(lex_string<&[u8], Token>,
    do_parse!(
        s: string >>
        (Token::StringLiteral(s))
    )
);

macro_rules! check(
  ($input:expr, $submac:ident!( $($args:tt)* )) => (
    {
      let mut failed = false;
      for &idx in $input {
        if !$submac!(idx, $($args)*) {
            failed = true;
            break;
        }
      }
      if failed {
        IResult::Error(ErrorKind::Custom(20))
      } else {
        IResult::Done(&b""[..], $input)
      }
    }
  );
  ($input:expr, $f:expr) => (
    check!($input, call!($f));
  );
);

named!(take_1_char, flat_map!(take!(1), check!(is_alphabetic)));

// Reserved or ident
fn parse_reserved(c: &str, rest: Option<&str>) -> Token {
    let mut string = c.to_owned();
    string.push_str(rest.unwrap_or(""));
    match string.as_ref() {
        "let" => Token::Let,
        "fn" => Token::Function,
        "if" => Token::If,
        "else" => Token::Else,
        "return" => Token::Return,
        "true" => Token::BoolLiteral(true),
        "false" => Token::BoolLiteral(false),
        _ => Token::Ident(string),
    }
}

named!(lex_reserved_ident<&[u8], Token>,
    do_parse!(
        c: map_res!(call!(take_1_char), str::from_utf8) >>
        rest: opt!(map_res!(alphanumeric, str::from_utf8)) >>
        (parse_reserved(c, rest))
    )
);

// Integers parsing
named!(lex_integer<&[u8], Token>,
    do_parse!(
        i: map_res!(map_res!(digit, str::from_utf8), FromStr::from_str) >>
        (Token::IntLiteral(i))
    )
);

// Illegal tokens
named!(lex_illegal<&[u8], Token>,
    do_parse!(take!(1) >> (Token::Illegal))
);

named!(lex_token<&[u8], Token>, alt!(
    lex_operator |
    lex_punctuations |
    lex_string |
    lex_reserved_ident |
    lex_integer |
    lex_illegal
));

named!(lex_tokens<&[u8], Vec<Token>>, ws!(many0!(lex_token)));

macro_rules! tag_token (
  ($i: expr, $tag: expr) => (
    {
        let (i1, t1) = try_parse!($i, take!(1));
        if t1.tok.len() == 0 {
            IResult::Incomplete(Needed::Size(1))
        } else {
            if t1.tok[0] == $tag {
                IResult::Done(i1, t1)
            } else {
                IResult::Error(error_position!(ErrorKind::Tag, $i))
            }
        }
    }
  );
);

named!(parse_tokens<Tokens, Tokens>,
    do_parse!(
        tag_token!(Token::Minus) >>
        a: take!(1) >>
        tag_token!(Token::Plus) >>
        (a)
    )
);

pub struct Lexer;

impl Lexer {
    pub fn lex_tokens(bytes: &[u8]) -> IResult<&[u8], Vec<Token>> {
        let vec = vec![Token::Minus, Token::Divide, Token::Plus];
        let slices = vec.as_slice();
        let tokens = Tokens { tok: slices, start: 0, end: vec.len() };

        println!("{:?}", parse_tokens(tokens));

        lex_tokens(bytes).map(|result|
            [&result[..], &vec![Token::EOF][..]]
                .concat()
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_lexer1() {
        let input = &b"=+(){},;"[..];
        let result = Lexer::lex_tokens(input).to_result().unwrap();

        let expected_results = vec![
            Token::Assign,
            Token::Plus,
            Token::LParen,
            Token::RParen,
            Token::LBrace,
            Token::RBrace,
            Token::Comma,
            Token::SemiColon,
            Token::EOF,
        ];

        assert_eq!(result, expected_results);
    }

    #[test]
    fn test_lexer2() {
        let input =
            "let five = 5;\
             let ten = 10;\

             let add = fn(x, y) {\
                 x + y;\
             };\

             let result = add(five, ten);"
            .as_bytes();

        let result = Lexer::lex_tokens(input).to_result().unwrap();

        let expected_results = vec![
            Token::Let,
            Token::Ident("five".to_owned()),
            Token::Assign,
            Token::IntLiteral(5),
            Token::SemiColon,
            Token::Let,
            Token::Ident("ten".to_owned()),
            Token::Assign,
            Token::IntLiteral(10),
            Token::SemiColon,
            Token::Let,
            Token::Ident("add".to_owned()),
            Token::Assign,
            Token::Function,
            Token::LParen,
            Token::Ident("x".to_owned()),
            Token::Comma,
            Token::Ident("y".to_owned()),
            Token::RParen,
            Token::LBrace,
            Token::Ident("x".to_owned()),
            Token::Plus,
            Token::Ident("y".to_owned()),
            Token::SemiColon,
            Token::RBrace,
            Token::SemiColon,
            Token::Let,
            Token::Ident("result".to_owned()),
            Token::Assign,
            Token::Ident("add".to_owned()),
            Token::LParen,
            Token::Ident("five".to_owned()),
            Token::Comma,
            Token::Ident("ten".to_owned()),
            Token::RParen,
            Token::SemiColon,
            Token::EOF,
        ];

        assert_eq!(result, expected_results);
    }

    #[test]
    fn test_lexer3() {
        let input =
            "if (a == 10) {\
                return a;\
             } else if (a != 20) {\
                return !a;\
            } else if (a > 20) {\
                return -30 / 40 * 50;\
            } else if (a < 30) {\
                return true;\
            }\
            return false;\
            "
            .as_bytes();

        let result = Lexer::lex_tokens(input).to_result().unwrap();

        let expected_results = vec![
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::Equal,
            Token::IntLiteral(10),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::Ident("a".to_owned()),
            Token::SemiColon,
            Token::RBrace,
            Token::Else,
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::NotEqual,
            Token::IntLiteral(20),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::Not,
            Token::Ident("a".to_owned()),
            Token::SemiColon,
            Token::RBrace,
            Token::Else,
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::GreaterThan,
            Token::IntLiteral(20),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::Minus,
            Token::IntLiteral(30),
            Token::Divide,
            Token::IntLiteral(40),
            Token::Multiply,
            Token::IntLiteral(50),
            Token::SemiColon,
            Token::RBrace,
            Token::Else,
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::LessThan,
            Token::IntLiteral(30),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::BoolLiteral(true),
            Token::SemiColon,
            Token::RBrace,
            Token::Return,
            Token::BoolLiteral(false),
            Token::SemiColon,
            Token::EOF,
        ];

        assert_eq!(result, expected_results);
    }

    #[test]
    fn string_literals() {
        let result = Lexer::lex_tokens(&b"\"foobar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foobar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo bar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo bar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\nbar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\nbar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\tbar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\tbar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\\\"bar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\"bar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\\\"bar with \xf0\x9f\x92\x96 emojis\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\"bar with 💖 emojis".to_owned()), Token::EOF]);
    }

    #[test]
    fn id_with_numbers() {
        let result = Lexer::lex_tokens(&b"hello2 hel301oo120"[..]).to_result().unwrap();
        let expected = vec![
            Token::Ident("hello2".to_owned()),
            Token::Ident("hel301oo120".to_owned()),
            Token::EOF,
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn array_tokens() {
        let result = Lexer::lex_tokens(&b"[1, 2];"[..]).to_result().unwrap();
        let expected = vec![
            Token::LBracket,
            Token::IntLiteral(1),
            Token::Comma,
            Token::IntLiteral(2),
            Token::RBracket,
            Token::SemiColon,
            Token::EOF
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn hash_tokens() {
        let result = Lexer::lex_tokens(&b"{\"hello\": \"world\"}"[..]).to_result().unwrap();
        let expected = vec![
            Token::LBrace,
            Token::StringLiteral("hello".to_owned()),
            Token::Colon,
            Token::StringLiteral("world".to_owned()),
            Token::RBrace,
            Token::EOF,
        ];
        assert_eq!(result, expected);
    }
}
<commit_msg>fix lexer for Ident with single char<commit_after>use nom::*;
use std::str;
use std::str::FromStr;
use std::str::Utf8Error;

mod token;
use lexer::token::*;

// operators
named!(equal_operator<&[u8], Token>,
  do_parse!(tag!("==") >> (Token::Equal))
);

named!(not_equal_operator<&[u8], Token>,
  do_parse!(tag!("!=") >> (Token::NotEqual))
);

named!(assign_operator<&[u8], Token>,
  do_parse!(tag!("=") >> (Token::Assign))
);

named!(plus_operator<&[u8], Token>,
  do_parse!(tag!("+") >> (Token::Plus))
);

named!(minus_operator<&[u8], Token>,
  do_parse!(tag!("-") >> (Token::Minus))
);

named!(multiply_operator<&[u8], Token>,
  do_parse!(tag!("*") >> (Token::Multiply))
);

named!(divide_operator<&[u8], Token>,
  do_parse!(tag!("/") >> (Token::Divide))
);

named!(not_operator<&[u8], Token>,
  do_parse!(tag!("!") >> (Token::Not))
);

named!(greater_operator<&[u8], Token>,
  do_parse!(tag!(">") >> (Token::GreaterThan))
);

named!(lesser_operator<&[u8], Token>,
  do_parse!(tag!("<") >> (Token::LessThan))
);

named!(lex_operator<&[u8], Token>, alt!(
    equal_operator |
    not_equal_operator |
    assign_operator |
    plus_operator |
    minus_operator |
    multiply_operator |
    divide_operator |
    not_operator |
    greater_operator |
    lesser_operator
));

// punctuations
named!(comma_punctuation<&[u8], Token>,
  do_parse!(tag!(",") >> (Token::Comma))
);

named!(semicolon_punctuation<&[u8], Token>,
  do_parse!(tag!(";") >> (Token::SemiColon))
);

named!(colon_punctuation<&[u8], Token>,
  do_parse!(tag!(":") >> (Token::Colon))
);

named!(lparen_punctuation<&[u8], Token>,
  do_parse!(tag!("(") >> (Token::LParen))
);

named!(rparen_punctuation<&[u8], Token>,
  do_parse!(tag!(")") >> (Token::RParen))
);

named!(lbrace_punctuation<&[u8], Token>,
  do_parse!(tag!("{") >> (Token::LBrace))
);

named!(rbrace_punctuation<&[u8], Token>,
  do_parse!(tag!("}") >> (Token::RBrace))
);

named!(lbracket_punctuation<&[u8], Token>,
  do_parse!(tag!("[") >> (Token::LBracket))
);

named!(rbracket_punctuation<&[u8], Token>,
  do_parse!(tag!("]") >> (Token::RBracket))
);

named!(lex_punctuations<&[u8], Token>, alt!(
    comma_punctuation |
    semicolon_punctuation |
    colon_punctuation |
    lparen_punctuation |
    rparen_punctuation |
    lbrace_punctuation |
    rbrace_punctuation |
    lbracket_punctuation |
    rbracket_punctuation
));

// Strings
fn pis(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
    let (i1, c1) = try_parse!(input, take!(1));
    match c1 {
        b"\"" => IResult::Done(input, vec![]),
        b"\\" => {
            let (i2, c2) = try_parse!(i1, take!(1));
            pis(i2).map(|done| concat_slice_vec(c2, done))
        },
        c => pis(i1).map(|done| concat_slice_vec(c, done)),
    }
}

fn concat_slice_vec(c: &[u8], done: Vec<u8>) -> Vec<u8> {
    let mut new_vec = c.to_vec();
    new_vec.extend(&done);
    new_vec
}

fn convert_vec_utf8(v: Vec<u8>) -> Result<String, Utf8Error> {
    let slice = v.as_slice();
    str::from_utf8(slice).map(|s| s.to_owned())
}

named!(string<String>,
  delimited!(
    tag!("\""),
    map_res!(pis, convert_vec_utf8),
    tag!("\"")
  )
);

named!(lex_string<&[u8], Token>,
    do_parse!(
        s: string >>
        (Token::StringLiteral(s))
    )
);

macro_rules! check(
  ($input:expr, $submac:ident!( $($args:tt)* )) => (
    {
      let mut failed = false;
      for &idx in $input {
        if !$submac!(idx, $($args)*) {
            failed = true;
            break;
        }
      }
      if failed {
        IResult::Error(ErrorKind::Custom(20))
      } else {
        IResult::Done(&b""[..], $input)
      }
    }
  );
  ($input:expr, $f:expr) => (
    check!($input, call!($f));
  );
);

// Reserved or ident
fn parse_reserved(c: &str, rest: Option<&str>) -> Token {
    let mut string = c.to_owned();
    string.push_str(rest.unwrap_or(""));
    match string.as_ref() {
        "let" => Token::Let,
        "fn" => Token::Function,
        "if" => Token::If,
        "else" => Token::Else,
        "return" => Token::Return,
        "true" => Token::BoolLiteral(true),
        "false" => Token::BoolLiteral(false),
        _ => Token::Ident(string),
    }
}

named!(take_1_char, flat_map!(take!(1), check!(is_alphabetic)));

named!(lex_reserved_ident<&[u8], Token>,
    do_parse!(
        c: map_res!(call!(take_1_char), str::from_utf8) >>
        rest: opt!(complete!(map_res!(alphanumeric, str::from_utf8))) >>
        (parse_reserved(c, rest))
    )
);

// Integers parsing
named!(lex_integer<&[u8], Token>,
    do_parse!(
        i: map_res!(map_res!(digit, str::from_utf8), FromStr::from_str) >>
        (Token::IntLiteral(i))
    )
);

// Illegal tokens
named!(lex_illegal<&[u8], Token>,
    do_parse!(take!(1) >> (Token::Illegal))
);

named!(lex_token<&[u8], Token>, alt_complete!(
    lex_operator |
    lex_punctuations |
    lex_string |
    lex_reserved_ident |
    lex_integer |
    lex_illegal
));

named!(lex_tokens<&[u8], Vec<Token>>, ws!(many0!(lex_token)));

macro_rules! tag_token (
  ($i: expr, $tag: expr) => (
    {
        let (i1, t1) = try_parse!($i, take!(1));
        if t1.tok.len() == 0 {
            IResult::Incomplete(Needed::Size(1))
        } else {
            if t1.tok[0] == $tag {
                IResult::Done(i1, t1)
            } else {
                IResult::Error(error_position!(ErrorKind::Tag, $i))
            }
        }
    }
  );
);

named!(parse_tokens<Tokens, Tokens>,
    do_parse!(
        tag_token!(Token::Minus) >>
        a: take!(1) >>
        tag_token!(Token::Plus) >>
        (a)
    )
);

pub struct Lexer;

impl Lexer {
    pub fn lex_tokens(bytes: &[u8]) -> IResult<&[u8], Vec<Token>> {
        //let vec = vec![Token::Minus, Token::Divide, Token::Plus];
        //let slices = vec.as_slice();
        //let tokens = Tokens { tok: slices, start: 0, end: vec.len() };

        //println!("{:?}", parse_tokens(tokens));

        lex_tokens(bytes).map(|result|
            [&result[..], &vec![Token::EOF][..]]
                .concat()
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_lexer1() {
        let input = &b"=+(){},;"[..];
        let result = Lexer::lex_tokens(input).to_result().unwrap();

        let expected_results = vec![
            Token::Assign,
            Token::Plus,
            Token::LParen,
            Token::RParen,
            Token::LBrace,
            Token::RBrace,
            Token::Comma,
            Token::SemiColon,
            Token::EOF,
        ];

        assert_eq!(result, expected_results);
    }

    #[test]
    fn test_lexer2() {
        let input =
            "let five = 5;\
             let ten = 10;\

             let add = fn(x, y) {\
                 x + y;\
             };\

             let result = add(five, ten);"
            .as_bytes();

        let result = Lexer::lex_tokens(input).to_result().unwrap();

        let expected_results = vec![
            Token::Let,
            Token::Ident("five".to_owned()),
            Token::Assign,
            Token::IntLiteral(5),
            Token::SemiColon,
            Token::Let,
            Token::Ident("ten".to_owned()),
            Token::Assign,
            Token::IntLiteral(10),
            Token::SemiColon,
            Token::Let,
            Token::Ident("add".to_owned()),
            Token::Assign,
            Token::Function,
            Token::LParen,
            Token::Ident("x".to_owned()),
            Token::Comma,
            Token::Ident("y".to_owned()),
            Token::RParen,
            Token::LBrace,
            Token::Ident("x".to_owned()),
            Token::Plus,
            Token::Ident("y".to_owned()),
            Token::SemiColon,
            Token::RBrace,
            Token::SemiColon,
            Token::Let,
            Token::Ident("result".to_owned()),
            Token::Assign,
            Token::Ident("add".to_owned()),
            Token::LParen,
            Token::Ident("five".to_owned()),
            Token::Comma,
            Token::Ident("ten".to_owned()),
            Token::RParen,
            Token::SemiColon,
            Token::EOF,
        ];

        assert_eq!(result, expected_results);
    }

    #[test]
    fn test_lexer3() {
        let input =
            "if (a == 10) {\
                return a;\
             } else if (a != 20) {\
                return !a;\
            } else if (a > 20) {\
                return -30 / 40 * 50;\
            } else if (a < 30) {\
                return true;\
            }\
            return false;\
            "
            .as_bytes();

        let result = Lexer::lex_tokens(input).to_result().unwrap();

        let expected_results = vec![
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::Equal,
            Token::IntLiteral(10),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::Ident("a".to_owned()),
            Token::SemiColon,
            Token::RBrace,
            Token::Else,
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::NotEqual,
            Token::IntLiteral(20),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::Not,
            Token::Ident("a".to_owned()),
            Token::SemiColon,
            Token::RBrace,
            Token::Else,
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::GreaterThan,
            Token::IntLiteral(20),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::Minus,
            Token::IntLiteral(30),
            Token::Divide,
            Token::IntLiteral(40),
            Token::Multiply,
            Token::IntLiteral(50),
            Token::SemiColon,
            Token::RBrace,
            Token::Else,
            Token::If,
            Token::LParen,
            Token::Ident("a".to_owned()),
            Token::LessThan,
            Token::IntLiteral(30),
            Token::RParen,
            Token::LBrace,
            Token::Return,
            Token::BoolLiteral(true),
            Token::SemiColon,
            Token::RBrace,
            Token::Return,
            Token::BoolLiteral(false),
            Token::SemiColon,
            Token::EOF,
        ];

        assert_eq!(result, expected_results);
    }

    #[test]
    fn string_literals() {
        let result = Lexer::lex_tokens(&b"\"foobar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foobar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo bar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo bar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\nbar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\nbar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\tbar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\tbar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\\\"bar\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\"bar".to_owned()), Token::EOF]);

        let result = Lexer::lex_tokens(&b"\"foo\\\"bar with \xf0\x9f\x92\x96 emojis\""[..]).to_result().unwrap();
        assert_eq!(result, vec![Token::StringLiteral("foo\"bar with 💖 emojis".to_owned()), Token::EOF]);
    }

    #[test]
    fn id_with_numbers() {
        let result = Lexer::lex_tokens(&b"hello2 hel301oo120"[..]).to_result().unwrap();
        let expected = vec![
            Token::Ident("hello2".to_owned()),
            Token::Ident("hel301oo120".to_owned()),
            Token::EOF,
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn array_tokens() {
        let result = Lexer::lex_tokens(&b"[1, 2];"[..]).to_result().unwrap();
        let expected = vec![
            Token::LBracket,
            Token::IntLiteral(1),
            Token::Comma,
            Token::IntLiteral(2),
            Token::RBracket,
            Token::SemiColon,
            Token::EOF
        ];
        assert_eq!(result, expected);
    }

    #[test]
    fn hash_tokens() {
        let result = Lexer::lex_tokens(&b"{\"hello\": \"world\"}"[..]).to_result().unwrap();
        let expected = vec![
            Token::LBrace,
            Token::StringLiteral("hello".to_owned()),
            Token::Colon,
            Token::StringLiteral("world".to_owned()),
            Token::RBrace,
            Token::EOF,
        ];
        assert_eq!(result, expected);
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate "handlebars-iron" as hbs;
extern crate "rustc-serialize" as serialize;

use iron::prelude::*;
use iron::{status};
use hbs::{Template, HandlebarsEngine};
use serialize::json::{ToJson, Json};
use std::collections::BTreeMap;

/// this function is for making example data
fn make_data() -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();

    data.insert("year".to_string(), "2015".to_json());

    let mut teams = Vec::new();

    for v in vec![("Jiangsu", 43u16), ("Beijing", 27u16), ("Guangzhou", 22u16), ("Shandong", 12u16)].iter() {
        let (name, score) = *v;
        let mut t = BTreeMap::new();
        t.insert("name".to_string(), name.to_json());
        t.insert("score".to_string(), score.to_json());
        teams.push(t)
    }

    data.insert("teams".to_string(), teams.to_json());
    data
}

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = make_data();
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

fn main() {
    let mut chain = Chain::new(hello_world);
    chain.link_after(HandlebarsEngine::new("./examples/templates/", ".hbs"));
    Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>(chore) added print information in example<commit_after>extern crate iron;
extern crate "handlebars-iron" as hbs;
extern crate "rustc-serialize" as serialize;

use iron::prelude::*;
use iron::{status};
use hbs::{Template, HandlebarsEngine};
use serialize::json::{ToJson, Json};
use std::collections::BTreeMap;

/// this function is for making example data
fn make_data() -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();

    data.insert("year".to_string(), "2015".to_json());

    let mut teams = Vec::new();

    for v in vec![("Jiangsu", 43u16), ("Beijing", 27u16), ("Guangzhou", 22u16), ("Shandong", 12u16)].iter() {
        let (name, score) = *v;
        let mut t = BTreeMap::new();
        t.insert("name".to_string(), name.to_json());
        t.insert("score".to_string(), score.to_json());
        teams.push(t)
    }

    data.insert("teams".to_string(), teams.to_json());
    data
}

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = make_data();
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

fn main() {
    let mut chain = Chain::new(hello_world);
    chain.link_after(HandlebarsEngine::new("./examples/templates/", ".hbs"));
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

use std::fmt::Debug;
use std::fmt::Display;

use auto_enums::enum_derive;
use derive_more::From;
use proptest::arbitrary::any;
use proptest::arbitrary::Arbitrary;
use proptest::collection::vec;
use proptest::prop_oneof;
use proptest::strategy::BoxedStrategy;
use proptest::strategy::Just;
use proptest::strategy::Strategy;

use crate::primitives::tau;
use crate::primitives::tick;
use crate::primitives::Tau;
use crate::primitives::Tick;

/// An event that is identified by a number.  Makes it easy to construct distinct events in
/// test cases.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct NumberedEvent(pub u32);

impl From<u32> for NumberedEvent {
    fn from(from: u32) -> NumberedEvent {
        NumberedEvent(from)
    }
}

const SUBSCRIPT_DIGITS: [char; 10] = ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'];

impl Display for NumberedEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let digits: String = self
            .0
            .to_string()
            .chars()
            .map(|ch| SUBSCRIPT_DIGITS[ch.to_digit(10).unwrap() as usize])
            .collect();
        write!(f, "E{}", digits)
    }
}

impl Debug for NumberedEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

impl Arbitrary for NumberedEvent {
    type Parameters = ();
    type Strategy = BoxedStrategy<NumberedEvent>;

    fn arbitrary_with(_args: ()) -> Self::Strategy {
        (0..100u32).prop_map_into().boxed()
    }
}

#[test]
fn can_display_events() {
    assert_eq!(NumberedEvent(0).to_string(), "E₀");
    assert_eq!(NumberedEvent(10).to_string(), "E₁₀");
    assert_eq!(NumberedEvent(0123456789).to_string(), "E₁₂₃₄₅₆₇₈₉");
}

/// An event type that is useful in test cases.  It can be a NumberedEvent or any of the
/// built-in event types.
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, From, Hash, PartialEq)]
pub enum TestEvent {
    Tau(Tau),
    Tick(Tick),
    NumberedEvent(NumberedEvent),
}

impl Arbitrary for TestEvent {
    type Parameters = ();
    type Strategy = BoxedStrategy<TestEvent>;

    fn arbitrary_with(_args: ()) -> Self::Strategy {
        prop_oneof![
            Just(tau()),
            Just(tick()),
            any::<NumberedEvent>().prop_map_into(),
        ]
        .boxed()
    }
}

/// A proptest helper type that generates a non-empty vector of values.
#[derive(Clone, Debug)]
pub struct NonemptyVec<T> {
    pub vec: Vec<T>,
}

impl<T> Arbitrary for NonemptyVec<T>
where
    T: Arbitrary + Clone + Debug + 'static,
{
    type Parameters = ();
    type Strategy = BoxedStrategy<NonemptyVec<T>>;

    fn arbitrary_with(_args: ()) -> Self::Strategy {
        vec(any::<T>(), 1..16)
            .prop_map(|vec| NonemptyVec { vec })
            .boxed()
    }
}
<commit_msg>Use 16 bits for numbered events<commit_after>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.  See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------------------------------

use std::fmt::Debug;
use std::fmt::Display;

use auto_enums::enum_derive;
use derive_more::From;
use proptest::arbitrary::any;
use proptest::arbitrary::Arbitrary;
use proptest::collection::vec;
use proptest::prop_oneof;
use proptest::strategy::BoxedStrategy;
use proptest::strategy::Just;
use proptest::strategy::Strategy;

use crate::primitives::tau;
use crate::primitives::tick;
use crate::primitives::Tau;
use crate::primitives::Tick;

/// An event that is identified by a number.  Makes it easy to construct distinct events in
/// test cases.
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct NumberedEvent(pub u16);

impl From<u16> for NumberedEvent {
    fn from(from: u16) -> NumberedEvent {
        NumberedEvent(from)
    }
}

const SUBSCRIPT_DIGITS: [char; 10] = ['₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'];

impl Display for NumberedEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let digits: String = self
            .0
            .to_string()
            .chars()
            .map(|ch| SUBSCRIPT_DIGITS[ch.to_digit(10).unwrap() as usize])
            .collect();
        write!(f, "E{}", digits)
    }
}

impl Debug for NumberedEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

impl Arbitrary for NumberedEvent {
    type Parameters = ();
    type Strategy = BoxedStrategy<NumberedEvent>;

    fn arbitrary_with(_args: ()) -> Self::Strategy {
        any::<u16>().prop_map_into().boxed()
    }
}

#[test]
fn can_display_events() {
    assert_eq!(NumberedEvent(0).to_string(), "E₀");
    assert_eq!(NumberedEvent(10).to_string(), "E₁₀");
    assert_eq!(NumberedEvent(01234).to_string(), "E₁₂₃₄");
}

/// An event type that is useful in test cases.  It can be a NumberedEvent or any of the
/// built-in event types.
#[enum_derive(Debug, Display)]
#[derive(Clone, Eq, From, Hash, PartialEq)]
pub enum TestEvent {
    Tau(Tau),
    Tick(Tick),
    NumberedEvent(NumberedEvent),
}

impl Arbitrary for TestEvent {
    type Parameters = ();
    type Strategy = BoxedStrategy<TestEvent>;

    fn arbitrary_with(_args: ()) -> Self::Strategy {
        prop_oneof![
            Just(tau()),
            Just(tick()),
            any::<NumberedEvent>().prop_map_into(),
        ]
        .boxed()
    }
}

/// A proptest helper type that generates a non-empty vector of values.
#[derive(Clone, Debug)]
pub struct NonemptyVec<T> {
    pub vec: Vec<T>,
}

impl<T> Arbitrary for NonemptyVec<T>
where
    T: Arbitrary + Clone + Debug + 'static,
{
    type Parameters = ();
    type Strategy = BoxedStrategy<NonemptyVec<T>>;

    fn arbitrary_with(_args: ()) -> Self::Strategy {
        vec(any::<T>(), 1..16)
            .prop_map(|vec| NonemptyVec { vec })
            .boxed()
    }
}
<|endoftext|>


<commit_before>//! An example of a simple volume node oscillating the amplitude of a synth node.

use dsp::{sample::ToFrameSliceMut, Frame, FromSample, Graph, Node, Sample};
use portaudio as pa;

const CHANNELS: usize = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;

fn main() -> Result<(), pa::Error> {
    // Construct our dsp graph.
    let mut graph = Graph::new();

    // Construct our fancy Synth and add it to the graph!
    let synth = graph.add_node(DspNode::Synth(0.0));

    // Output our synth to a marvellous volume node.
    let (_, volume) = graph.add_output(synth, DspNode::Volume(1.0));

    // Set the synth as the master node for the graph.
    graph.set_master(Some(volume));

    // We'll use this to count down from three seconds and then break from the loop.
    let mut timer: f64 = 0.0;

    // This will be used to determine the delta time between calls to the callback.
    let mut prev_time = None;

    // The callback we'll use to pass to the Stream. It will request audio from our graph.
    let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
        let buffer: &mut [[f32; CHANNELS]] = buffer.to_frame_slice_mut().unwrap();

        // Zero the sample buffer.
        dsp::slice::equilibrium(buffer);

        // Request audio from the graph.
        graph.audio_requested(buffer, SAMPLE_HZ);

        // Oscillate the volume.
        if let &mut DspNode::Volume(ref mut vol) = &mut graph[volume] {
            *vol = (4.0 * timer as f32).sin() * 0.5;
        }

        let last_time = prev_time.unwrap_or(time.current);
        let dt = time.current - last_time;
        timer += dt;
        prev_time = Some(time.current);
        if timer <= 5.0 {
            pa::Continue
        } else {
            pa::Complete
        }
    };

    // Construct PortAudio and the stream.
    let pa = pa::PortAudio::new()?;
    let settings = pa.default_output_stream_settings::<f32>(CHANNELS as i32, SAMPLE_HZ, FRAMES)?;
    let mut stream = pa.open_non_blocking_stream(settings, callback)?;
    stream.start()?;

    // Wait for our stream to finish.
    while let Ok(true) = stream.is_active() {
        std::thread::sleep(::std::time::Duration::from_millis(16));
    }

    Ok(())
}

/// Our Node to be used within the Graph.
enum DspNode {
    Synth(f64),
    Volume(f32),
}

/// Implement the `Node` trait for our DspNode.
impl Node<[f32; CHANNELS]> for DspNode {
    fn audio_requested(&mut self, buffer: &mut [[f32; CHANNELS]], sample_hz: f64) {
        match *self {
            DspNode::Synth(ref mut phase) => dsp::slice::map_in_place(buffer, |_| {
                let val = sine_wave(*phase);
                const SYNTH_HZ: f64 = 110.0;
                *phase += SYNTH_HZ / sample_hz;
                Frame::from_fn(|_| val)
            }),
            DspNode::Volume(vol) => dsp::slice::map_in_place(buffer, |f| f.map(|s| s.mul_amp(vol))),
        }
    }
}

/// Return a sine wave for the given phase.
fn sine_wave<S: Sample>(phase: f64) -> S
where
    S: Sample + FromSample<f32>,
{
    use std::f64::consts::PI;
    ((phase * PI * 2.0).sin() as f32).to_sample::<S>()
}
<commit_msg>Clean up warnings<commit_after>//! An example of a simple volume node oscillating the amplitude of a synth node.

use dsp::{sample::ToFrameSliceMut, Frame, FromSample, Graph, Node, Sample};
use portaudio as pa;

const CHANNELS: usize = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;

fn main() -> Result<(), pa::Error> {
    // Construct our dsp graph.
    let mut graph = Graph::new();

    // Construct our fancy Synth and add it to the graph!
    let synth = graph.add_node(DspNode::Synth(0.0));

    // Output our synth to a marvellous volume node.
    let (_, volume) = graph.add_output(synth, DspNode::Volume(1.0));

    // Set the synth as the master node for the graph.
    graph.set_master(Some(volume));

    // We'll use this to count down from three seconds and then break from the loop.
    let mut timer: f64 = 0.0;

    // This will be used to determine the delta time between calls to the callback.
    let mut prev_time = None;

    // The callback we'll use to pass to the Stream. It will request audio from our graph.
    let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
        let buffer: &mut [[f32; CHANNELS]] = buffer.to_frame_slice_mut().unwrap();

        // Zero the sample buffer.
        dsp::slice::equilibrium(buffer);

        // Request audio from the graph.
        graph.audio_requested(buffer, SAMPLE_HZ);

        // Oscillate the volume.
        if let DspNode::Volume(ref mut vol) = &mut graph[volume] {
            *vol = (4.0 * timer as f32).sin() * 0.5;
        }

        let last_time = prev_time.unwrap_or(time.current);
        let dt = time.current - last_time;
        timer += dt;
        prev_time = Some(time.current);
        if timer <= 5.0 {
            pa::Continue
        } else {
            pa::Complete
        }
    };

    // Construct PortAudio and the stream.
    let pa = pa::PortAudio::new()?;
    let settings = pa.default_output_stream_settings::<f32>(CHANNELS as i32, SAMPLE_HZ, FRAMES)?;
    let mut stream = pa.open_non_blocking_stream(settings, callback)?;
    stream.start()?;

    // Wait for our stream to finish.
    while let Ok(true) = stream.is_active() {
        std::thread::sleep(::std::time::Duration::from_millis(16));
    }

    Ok(())
}

/// Our Node to be used within the Graph.
enum DspNode {
    Synth(f64),
    Volume(f32),
}

/// Implement the `Node` trait for our DspNode.
impl Node<[f32; CHANNELS]> for DspNode {
    fn audio_requested(&mut self, buffer: &mut [[f32; CHANNELS]], sample_hz: f64) {
        match *self {
            DspNode::Synth(ref mut phase) => dsp::slice::map_in_place(buffer, |_| {
                let val = sine_wave(*phase);
                const SYNTH_HZ: f64 = 110.0;
                *phase += SYNTH_HZ / sample_hz;
                Frame::from_fn(|_| val)
            }),
            DspNode::Volume(vol) => dsp::slice::map_in_place(buffer, |f| f.map(|s| s.mul_amp(vol))),
        }
    }
}

/// Return a sine wave for the given phase.
fn sine_wave<S: Sample>(phase: f64) -> S
where
    S: Sample + FromSample<f32>,
{
    use std::f64::consts::PI;
    ((phase * PI * 2.0).sin() as f32).to_sample::<S>()
}
<|endoftext|>