<commit_before>extern mod xlib;
use std::ptr;
use std::option::Option;
use xlib::xlib;
use xlib::{Display, XSelectInput, XOpenDisplay, Window, XDefaultRootWindow};
use xlib::{XNextEvent, Union__XEvent};

// taken from X.h
//static KeyPress:i32 = 2;
static KeyRelease:i32 = 3;
/*static ButtonPress:i32 = 4;
static ButtonRelease:i32 = 5;
static MotionNotify:i32 = 6;
static EnterNotify:i32 = 7;
static LeaveNotify:i32 = 8;
static FocusIn:i32 = 9;
static FocusOut:i32 = 10;
static KeymapNotify:i32 = 11;
static Expose:i32 = 12;
static GraphicsExpose:i32 = 13;
static NoExpose:i32 = 14;
static VisibilityNotify:i32 = 15;
static CreateNotify:i32 = 16;
static DestroyNotify:i32 = 17;
static UnmapNotify:i32 = 18;
static MapNotify:i32 = 19;
*/
static MapRequest:i32 = 20;
/*
static ReparentNotify:i32 = 21;
static ConfigureNotify:i32 = 22;
static ConfigureRequest:i32 = 23;
static GravityNotify:i32 = 24;
static ResizeRequest:i32 = 25;
static CirculateNotify:i32 = 26;
static CirculateRequest:i32 = 27;
static PropertyNotify:i32 = 28;
static SelectionClear:i32 = 29;
static SelectionRequest:i32 = 30;
static SelectionNotify:i32 = 31;
static ColormapNotify:i32 = 32;
static ClientMessage:i32 = 33;
static MappingNotify:i32 = 34;
static GenericEvent:i32 = 35;
static LASTEvent:i32 = 36; // must be bigger than any event #
*/

fn getDisplay() -> Option<*mut Display> {
    unsafe {
        let null = ptr::null();
        let display = XOpenDisplay(null);

        if (ptr::is_null(display)) {
            return None
        } else {
            return Some(display);
        }

    }
}

fn getRootWindow(display: *mut Display) -> Window {
    unsafe {
        return XDefaultRootWindow(display);
    }
}

fn setSelectInput(display: *mut Display, window: Window) {
    unsafe {
        let SubstructureNotifyMask = 1<<19;
        let SubstructureRedirectMask = 1<<20;
        let XSelectInputMask = SubstructureNotifyMask|SubstructureRedirectMask;
        XSelectInput(display, window, XSelectInputMask);
    }
}

fn main() {
    let maybeDisplay = getDisplay();
    let Mod4Mask = (1<<16);
    let GrabModeAsync = 1;

    match maybeDisplay {
        Some(display) => {
            println!("Got display {}", display);
            let root = getRootWindow(display);
            println!("Got root window {}", root);

            setSelectInput(display, root);
            println!("select input set!");

            unsafe {
                xlib::XGrabKey(display, 53, Mod4Mask, root, 1, GrabModeAsync,
                    GrabModeAsync);
                xlib::XGrabKey(display, 45, Mod4Mask, root, 1, GrabModeAsync,
                    GrabModeAsync);

                let mut xevent = Union__XEvent{ data: [0, ..24] };
                loop {
                    XNextEvent(display, ptr::to_mut_unsafe_ptr(&mut xevent));
                    let eventType = *xevent._type();

                    match eventType {
                        MapRequest => {
                            let event = *xevent.xmaprequest();
                            xlib::XMapWindow(display, event.window);
                            xlib::XSetInputFocus(display, event.window,
                                1 /*RevertToPointerRoot*/, 0 /*CurrentTime*/);
                            xlib::XMoveResizeWindow(display, event.window, 0, 0,
                                1920, 1080);
                        }
                        KeyRelease => {
                            let event = *xevent.xkey();
                            println!("Key {}", event.keycode);
                            if (event.keycode == 45) {
                                    let mut focus: Window = 0;
                                    let mut revert: i32 = 0;
                                    xlib::XGetInputFocus(display, &mut focus,
                                        &mut revert);
                                    xlib::XDestroyWindow(display, focus);
                            }
                        }
                        _ => {
                            println!("Unknown Event Type {}", eventType);
                        }
                    }
                }
            }
        }
        None => println!("Error getting display")
    }
}
<commit_msg>set cursor<commit_after>extern mod xlib;
use std::ptr;
use std::option::Option;
use xlib::xlib;
use xlib::{Display, XSelectInput, XOpenDisplay, Window, XDefaultRootWindow};
use xlib::{XNextEvent, Union__XEvent};

// taken from X.h
//static KeyPress:i32 = 2;
static KeyRelease:i32 = 3;
/*static ButtonPress:i32 = 4;
static ButtonRelease:i32 = 5;
static MotionNotify:i32 = 6;
static EnterNotify:i32 = 7;
static LeaveNotify:i32 = 8;
static FocusIn:i32 = 9;
static FocusOut:i32 = 10;
static KeymapNotify:i32 = 11;
static Expose:i32 = 12;
static GraphicsExpose:i32 = 13;
static NoExpose:i32 = 14;
static VisibilityNotify:i32 = 15;
static CreateNotify:i32 = 16;
static DestroyNotify:i32 = 17;
static UnmapNotify:i32 = 18;
static MapNotify:i32 = 19;
*/
static MapRequest:i32 = 20;
/*
static ReparentNotify:i32 = 21;
static ConfigureNotify:i32 = 22;
static ConfigureRequest:i32 = 23;
static GravityNotify:i32 = 24;
static ResizeRequest:i32 = 25;
static CirculateNotify:i32 = 26;
static CirculateRequest:i32 = 27;
static PropertyNotify:i32 = 28;
static SelectionClear:i32 = 29;
static SelectionRequest:i32 = 30;
static SelectionNotify:i32 = 31;
static ColormapNotify:i32 = 32;
static ClientMessage:i32 = 33;
static MappingNotify:i32 = 34;
static GenericEvent:i32 = 35;
static LASTEvent:i32 = 36; // must be bigger than any event #
*/

fn getDisplay() -> Option<*mut Display> {
    unsafe {
        let null = ptr::null();
        let display = XOpenDisplay(null);

        if (ptr::is_null(display)) {
            return None
        } else {
            return Some(display);
        }

    }
}

fn getRootWindow(display: *mut Display) -> Window {
    unsafe {
        return XDefaultRootWindow(display);
    }
}

fn setSelectInput(display: *mut Display, window: Window) {
    unsafe {
        let SubstructureNotifyMask = 1<<19;
        let SubstructureRedirectMask = 1<<20;
        let XSelectInputMask = SubstructureNotifyMask|SubstructureRedirectMask;
        XSelectInput(display, window, XSelectInputMask);
    }
}

fn main() {
    let maybeDisplay = getDisplay();
    let Mod4Mask = (1<<16);
    let GrabModeAsync = 1;

    match maybeDisplay {
        Some(display) => {
            println!("Got display {}", display);
            let root = getRootWindow(display);
            println!("Got root window {}", root);

            setSelectInput(display, root);
            println!("select input set!");

            unsafe {
                let mut wa = xlib::XSetWindowAttributes {
                    background_pixmap: 0,
                    background_pixel: 0,
                    border_pixmap: 0,
                    border_pixel: 0,
                    bit_gravity: 0,
                    win_gravity: 0,
                    backing_store: 0,
                    backing_planes: 0,
                    backing_pixel: 0,
                    save_under: 0,
                    event_mask: 0,
                    do_not_propagate_mask: 0,
                    override_redirect: 0,
                    colormap: 0,
                    cursor: 0,
                };
                wa.cursor = xlib::XCreateFontCursor(display, 68 /*XC_left_ptr*/);
                xlib::XChangeWindowAttributes(display, root,
                    (1<<14) /*CWCursor*/, &mut wa);
                xlib::XGrabKey(display, 53, Mod4Mask, root, 1, GrabModeAsync,
                    GrabModeAsync);
                xlib::XGrabKey(display, 45, Mod4Mask, root, 1, GrabModeAsync,
                    GrabModeAsync);

                let mut xevent = Union__XEvent{ data: [0, ..24] };
                loop {
                    XNextEvent(display, ptr::to_mut_unsafe_ptr(&mut xevent));
                    let eventType = *xevent._type();

                    match eventType {
                        MapRequest => {
                            let event = *xevent.xmaprequest();
                            xlib::XMapWindow(display, event.window);
                            xlib::XSetInputFocus(display, event.window,
                                1 /*RevertToPointerRoot*/, 0 /*CurrentTime*/);
                            xlib::XMoveResizeWindow(display, event.window, 0, 0,
                                1920, 1080);
                        }
                        KeyRelease => {
                            let event = *xevent.xkey();
                            println!("Key {}", event.keycode);
                            if (event.keycode == 45) {
                                    let mut focus: Window = 0;
                                    let mut revert: i32 = 0;
                                    xlib::XGetInputFocus(display, &mut focus,
                                        &mut revert);
                                    xlib::XDestroyWindow(display, focus);
                            }
                        }
                        _ => {
                            println!("Unknown Event Type {}", eventType);
                        }
                    }
                }
            }
        }
        None => println!("Error getting display")
    }
}
<|endoftext|>


<commit_before>//! High-level pieces.

use builtins;
use cell_gc::{self, GcHeapSession, GcLeaf};
use compile;
use env::{Environment, EnvironmentRef};
use errors::*;
use parse;
use std::path::Path;
use value::{BuiltinFnPtr, InternedString, Value};
use vm;

/// Create an environment that supports only core Scheme syntax.
///
/// It supports `(letrec)`, for example, but not `(let)`, `(and)`, or `(or)`.
pub fn core_env<'h>(hs: &mut GcHeapSession<'h>) -> EnvironmentRef<'h> {
    let env = Environment::empty(hs);

    builtins::define_builtins(hs, &env);

    const PRELUDE: &'static str = include_str!("prelude.scm");
    let _ = eval_str(hs, &env, PRELUDE).expect("unexpected error running the prelude");
    env
}

/// Create an environment that supports core syntax plus a handful of goodies
/// like `(let)`, `(and)`, and `(or)`. These are supported using simple-expander.scm
/// instead of psyntax.pp.
pub fn expanded_env<'h>(hs: &mut GcHeapSession<'h>) -> EnvironmentRef<'h> {
    let env = core_env(hs);

    const EXPANDER_CODE: &'static str = include_str!("simple-expander.scm");
    let xenv = env.new_nested_environment(hs);
    let expander = eval_str(hs, &xenv, EXPANDER_CODE)
        .expect("unexpected error initializing the simple expander");
    env.set_expander(expander);

    env
}

pub fn default_env<'h>(hs: &mut GcHeapSession<'h>) -> EnvironmentRef<'h> {
    let env = core_env(hs);

    const EXPANDER_CODE: &'static str = concat!(
        include_str!("psyntax-support.scm"),
        include_str!("psyntax.pp"),
        "\nsc-expand-toplevel\n"
    );
    let xenv = env.new_nested_environment(hs);
    xenv.push(
        InternedString::get("original-eval"),
        Value::Builtin(GcLeaf::new(BuiltinFnPtr(builtins::get_eval()))),
    );
    xenv.push(
        InternedString::get("psyntax-environment"),
        Value::Environment(xenv.clone()),
    );
    xenv.debug_assert_consistent();

    let expander = eval_str(hs, &xenv, EXPANDER_CODE)
        .expect("unexpected error initializing the expander");
    env.set_expander(expander);

    env
}

pub fn eval<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    expr: Value<'h>,
) -> Result<Value<'h>> {
    let expr = env.expand(hs, expr)?;
    let expr = compile::compile_toplevel(hs, &env.senv(), expr)?;
    vm::eval_compiled(hs, env, expr)
}

/// Evaluate a toplevel script, possibly including many definitions and
/// expressions.
pub fn eval_toplevel_forms<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    forms: Vec<Value<'h>>,
) -> Result<Value<'h>> {
    // To help compilation bind as many identifiers statically as possible, we
    // detect infallible definitions here and create the defined binding before
    // compiling any code.
    //
    // As long as env is a global environment, this is a pure optimization
    // (with one caveat, see next paragraph). The only reason we cannot simply
    // predefine *all* bindings is that a runtime error or compilation error
    // may occur.
    //
    // Caveat: We assume that macro expansion never produces code that will
    // fail to compile. If it does, we can err by expanding code that we should
    // have errored out before reaching; this is a problem because expanding
    // code can have the side effect of defining macros (or I guess modules).

    let senv = env.senv();
    let mut result = Value::Unspecified;
    let mut iter = forms.into_iter().peekable();
    while iter.peek().is_some() {
        let mut batch = vec![];
        for form in &mut iter {
            let form = env.expand(hs, form)?;
            let infallible = compile::toplevel_form_is_infallible(hs, &senv, &form);
            batch.push(form.clone());
            if infallible {
                if let Some(name) = compile::toplevel_form_defined_name(hs, &form) {
                    env.define(name, Value::Unspecified);
                }
            } else {
                break;
            }
        }
        let code = compile::compile_toplevel_forms(hs, &env.senv(), batch)?;
        result = vm::eval_compiled(hs, &env, code)?;
    }
    Ok(result)
}

pub fn eval_str<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    code: &str,
) -> Result<Value<'h>> {
    let forms = parse::parse(hs, code)?;
    eval_toplevel_forms(hs, env, forms)
}

pub fn load<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    filename: &Path,
) -> Result<Value<'h>> {
    use std::fs::File;
    use std::io::prelude::*;

    let mut file = File::open(Path::new(filename))
        .chain_err(|| format!("opening file {:?}", filename))?;

    let mut code = String::new();
    file.read_to_string(&mut code)
        .chain_err(|| "reading file")?;

    eval_str(hs, env, &code)
}

pub fn repl() -> Result<()> {
    const REPL_CODE: &'static str = include_str!("repl.scm");
    cell_gc::with_heap(|hs| {
        let env = default_env(hs);
        eval_str(hs, &env, REPL_CODE)?;
        Ok(())
    })
}

#[cfg(test)]
use value::RetType;

#[cfg(test)]
#[allow(dead_code)]
enum Env {
    Core,
    Expanded,
    Full
}

#[cfg(test)]
fn test_eval<R: for<'h> RetType<'h>>(env_type: Env, program: &str, expected: R) {
    use cell_gc::GcHeap;
    use vm::Trampoline;

    let mut heap = GcHeap::new();
    heap.enter(|hs| {
        let env = match env_type {
            Env::Core => core_env(hs),
            Env::Expanded => expanded_env(hs),
            Env::Full => default_env(hs),
        };
        let v = match expected.pack(hs).expect("expected return value should pack OK") {
            Trampoline::Value(v) => v,
            _ => panic!("packing expected return value produced unexpected tail call"),
        };
        let result = eval_str(hs, &env, program).expect("Should eval OK");
        assert_eq!(result, v);
    });
}

#[test]
fn test_2p2e4() {
    test_eval(Env::Core, r"(+ 2 2)", 4);
}

#[test]
fn test_simple_lambda() {
    test_eval(Env::Core, r"((lambda (x y z) (+ x (+ y z))) 3 4 5)", 12);
}

#[test]
fn test_list() {
    test_eval(Env::Core, r#"(equal? "abcd" (apply string (list #\a #\b #\c #\d)))"#, true);
}

#[test]
fn test_simple_lambda_with_psyntax() {
    test_eval(Env::Full, "((lambda (x y z) (+ x (+ y z))) 3 4 5)", 12);
}
<commit_msg>lisp: (trivial) Make a function private.<commit_after>//! High-level pieces.

use builtins;
use cell_gc::{self, GcHeapSession, GcLeaf};
use compile;
use env::{Environment, EnvironmentRef};
use errors::*;
use parse;
use std::path::Path;
use value::{BuiltinFnPtr, InternedString, Value};
use vm;

/// Create an environment that supports only core Scheme syntax.
///
/// It supports `(letrec)`, for example, but not `(let)`, `(and)`, or `(or)`.
pub fn core_env<'h>(hs: &mut GcHeapSession<'h>) -> EnvironmentRef<'h> {
    let env = Environment::empty(hs);

    builtins::define_builtins(hs, &env);

    const PRELUDE: &'static str = include_str!("prelude.scm");
    let _ = eval_str(hs, &env, PRELUDE).expect("unexpected error running the prelude");
    env
}

/// Create an environment that supports core syntax plus a handful of goodies
/// like `(let)`, `(and)`, and `(or)`. These are supported using simple-expander.scm
/// instead of psyntax.pp.
pub fn expanded_env<'h>(hs: &mut GcHeapSession<'h>) -> EnvironmentRef<'h> {
    let env = core_env(hs);

    const EXPANDER_CODE: &'static str = include_str!("simple-expander.scm");
    let xenv = env.new_nested_environment(hs);
    let expander = eval_str(hs, &xenv, EXPANDER_CODE)
        .expect("unexpected error initializing the simple expander");
    env.set_expander(expander);

    env
}

pub fn default_env<'h>(hs: &mut GcHeapSession<'h>) -> EnvironmentRef<'h> {
    let env = core_env(hs);

    const EXPANDER_CODE: &'static str = concat!(
        include_str!("psyntax-support.scm"),
        include_str!("psyntax.pp"),
        "\nsc-expand-toplevel\n"
    );
    let xenv = env.new_nested_environment(hs);
    xenv.push(
        InternedString::get("original-eval"),
        Value::Builtin(GcLeaf::new(BuiltinFnPtr(builtins::get_eval()))),
    );
    xenv.push(
        InternedString::get("psyntax-environment"),
        Value::Environment(xenv.clone()),
    );
    xenv.debug_assert_consistent();

    let expander = eval_str(hs, &xenv, EXPANDER_CODE)
        .expect("unexpected error initializing the expander");
    env.set_expander(expander);

    env
}

pub fn eval<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    expr: Value<'h>,
) -> Result<Value<'h>> {
    let expr = env.expand(hs, expr)?;
    let expr = compile::compile_toplevel(hs, &env.senv(), expr)?;
    vm::eval_compiled(hs, env, expr)
}

/// Evaluate a toplevel script, possibly including many definitions and
/// expressions.
fn eval_toplevel_forms<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    forms: Vec<Value<'h>>,
) -> Result<Value<'h>> {
    // To help compilation bind as many identifiers statically as possible, we
    // detect infallible definitions here and create the defined binding before
    // compiling any code.
    //
    // As long as env is a global environment, this is a pure optimization
    // (with one caveat, see next paragraph). The only reason we cannot simply
    // predefine *all* bindings is that a runtime error or compilation error
    // may occur.
    //
    // Caveat: We assume that macro expansion never produces code that will
    // fail to compile. If it does, we can err by expanding code that we should
    // have errored out before reaching; this is a problem because expanding
    // code can have the side effect of defining macros (or I guess modules).

    let senv = env.senv();
    let mut result = Value::Unspecified;
    let mut iter = forms.into_iter().peekable();
    while iter.peek().is_some() {
        let mut batch = vec![];
        for form in &mut iter {
            let form = env.expand(hs, form)?;
            let infallible = compile::toplevel_form_is_infallible(hs, &senv, &form);
            batch.push(form.clone());
            if infallible {
                if let Some(name) = compile::toplevel_form_defined_name(hs, &form) {
                    env.define(name, Value::Unspecified);
                }
            } else {
                break;
            }
        }
        let code = compile::compile_toplevel_forms(hs, &env.senv(), batch)?;
        result = vm::eval_compiled(hs, &env, code)?;
    }
    Ok(result)
}

pub fn eval_str<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    code: &str,
) -> Result<Value<'h>> {
    let forms = parse::parse(hs, code)?;
    eval_toplevel_forms(hs, env, forms)
}

pub fn load<'h>(
    hs: &mut GcHeapSession<'h>,
    env: &EnvironmentRef<'h>,
    filename: &Path,
) -> Result<Value<'h>> {
    use std::fs::File;
    use std::io::prelude::*;

    let mut file = File::open(Path::new(filename))
        .chain_err(|| format!("opening file {:?}", filename))?;

    let mut code = String::new();
    file.read_to_string(&mut code)
        .chain_err(|| "reading file")?;

    eval_str(hs, env, &code)
}

pub fn repl() -> Result<()> {
    const REPL_CODE: &'static str = include_str!("repl.scm");
    cell_gc::with_heap(|hs| {
        let env = default_env(hs);
        eval_str(hs, &env, REPL_CODE)?;
        Ok(())
    })
}

#[cfg(test)]
use value::RetType;

#[cfg(test)]
#[allow(dead_code)]
enum Env {
    Core,
    Expanded,
    Full
}

#[cfg(test)]
fn test_eval<R: for<'h> RetType<'h>>(env_type: Env, program: &str, expected: R) {
    use cell_gc::GcHeap;
    use vm::Trampoline;

    let mut heap = GcHeap::new();
    heap.enter(|hs| {
        let env = match env_type {
            Env::Core => core_env(hs),
            Env::Expanded => expanded_env(hs),
            Env::Full => default_env(hs),
        };
        let v = match expected.pack(hs).expect("expected return value should pack OK") {
            Trampoline::Value(v) => v,
            _ => panic!("packing expected return value produced unexpected tail call"),
        };
        let result = eval_str(hs, &env, program).expect("Should eval OK");
        assert_eq!(result, v);
    });
}

#[test]
fn test_2p2e4() {
    test_eval(Env::Core, r"(+ 2 2)", 4);
}

#[test]
fn test_simple_lambda() {
    test_eval(Env::Core, r"((lambda (x y z) (+ x (+ y z))) 3 4 5)", 12);
}

#[test]
fn test_list() {
    test_eval(Env::Core, r#"(equal? "abcd" (apply string (list #\a #\b #\c #\d)))"#, true);
}

#[test]
fn test_simple_lambda_with_psyntax() {
    test_eval(Env::Full, "((lambda (x y z) (+ x (+ y z))) 3 4 5)", 12);
}
<|endoftext|>


<commit_before>extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::{parse_macro_input, DataStruct, DeriveInput, Ident, Meta, NestedMeta};

#[proc_macro_derive(Pipeline)]
pub fn derive_pipeline(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl PipelineTrait for #ident {
            fn box_eq(&self, other: &dyn Any) -> bool {
                other.downcast_ref::<Self>().map_or(false, |a| self == a)
            }
            fn as_any(&self) -> &dyn Any {
                self
            }
            fn clone_box(&self) -> Box<dyn PipelineTrait> {
                Box::new(self.clone())
            }
        }
    };

    TokenStream::from(gen)
}

#[proc_macro_derive(AsAny)]
pub fn derive_as_any(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl AsAny for #ident {
            fn as_any(&self) -> &dyn Any {
                self
            }

            fn as_any_mut(&mut self) -> &mut dyn Any {
                self
            }
        }
    };

    TokenStream::from(gen)
}

#[proc_macro_derive(IntoRenderObject)]
pub fn derive_into_render_object(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl From<#ident> for Box<dyn RenderObject> {
            fn from(i: #ident) -> Box<dyn RenderObject> {
                Box::new(i)
            }
        }
    };

    TokenStream::from(gen)
}

#[proc_macro_derive(IntoLayout)]
pub fn derive_into_layout(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl From<#ident> for Box<dyn Layout> {
            fn from(i: #ident) -> Box<dyn Layout> {
                Box::new(i)
            }
        }
    };

    TokenStream::from(gen)
}

#[proc_macro_derive(Event)]
pub fn derive_event(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl Event for #ident {}
    };

    TokenStream::from(gen)
}

#[proc_macro_derive(IntoHandler)]
pub fn derive_into_handler(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl From<#ident> for Rc<dyn EventHandler> {
            fn from(i: #ident) -> Rc<dyn EventHandler> {
                Rc::new(i)
            }
        }
    };

    TokenStream::from(gen)
}

#[proc_macro_derive(WidgetCtx, attributes(property))]
pub fn derive_widget_ctx(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let mut generated = vec![];

    if let syn::Data::Struct(DataStruct { ref fields, .. }) = input.data {
        let filter_fields = fields
            .iter()
            .filter(|f| f.attrs.iter().any(|attr| attr.path.is_ident("property")));

        for field in filter_fields {
            let field_name = field
                .clone()
                .ident
                .unwrap_or_else(|| panic!("Expected the field to have a name"));

            let field_name_str = field_name.to_string();

            for attr in field.attrs.iter() {
                let last_attr_path = attr
                    .path
                    .segments
                    .iter()
                    .last()
                    .expect("Expected at least one segment where #[segment[::segment*](..)]");
                if (*last_attr_path).ident != "property" {
                    continue;
                }

                let meta = match attr.parse_meta() {
                    Ok(meta) => meta,
                    Err(_) => continue,
                };
                let list = match meta {
                    Meta::List(l) => l,
                    _ if meta.path().is_ident("property") => {
                        panic!("Invalid #[new] attribute, expected #[property(..)]")
                    }
                    _ => continue,
                };

                for item in list.nested.iter() {
                    match *item {
                        NestedMeta::Meta(Meta::Path(ref path)) => {
                            let ty = path.get_ident();

                            if let Some(ty) = ty {
                                let getter = Ident::new(
                                    format!("{}_ref", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let setter = Ident::new(
                                    format!("{}_set", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let clone = Ident::new(
                                    format!("{}_clone", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let get_mut = Ident::new(
                                    format!("{}_mut", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let gen = quote! {
                                    /// Gets a reference of the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #getter<'a>(widget: &'a WidgetContainer<'a>) -> &'a #ty {
                                        #ident::panics_on_wrong_type(widget);
                                        widget.get(#field_name_str)
                                    }

                                    /// Gets a mutable reference of the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #get_mut<'a>(widget: &'a mut WidgetContainer<'a>) -> &'a mut #ty {
                                        #ident::panics_on_wrong_type(widget);
                                        widget.get_mut(#field_name_str)
                                    }

                                    /// Sets the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #setter(widget: &mut WidgetContainer, value: impl Into<#ty>) {
                                        #ident::panics_on_wrong_type(widget);
                                        widget.set(#field_name_str, value.into());
                                    }

                                    /// Clones the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #clone(widget: &WidgetContainer) -> #ty {
                                        widget.clone(#field_name_str)
                                    }
                                };

                                generated.push(gen);
                            }

                            break;
                        }
                        _ => continue,
                    }
                }
            }
        }
    }

    let gen = quote! {
        impl #ident {
            #(#generated)*
        }
    };

    TokenStream::from(gen)
}
<commit_msg>proc_macros: update documentation strings<commit_after>extern crate proc_macro;

use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use syn::{parse_macro_input, DataStruct, DeriveInput, Ident, Meta, NestedMeta};

/// Derive an orbtk pipline. It returns a token stream object.
#[proc_macro_derive(Pipeline)]
pub fn derive_pipeline(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl PipelineTrait for #ident {
            fn box_eq(&self, other: &dyn Any) -> bool {
                other.downcast_ref::<Self>().map_or(false, |a| self == a)
            }
            fn as_any(&self) -> &dyn Any {
                self
            }
            fn clone_box(&self) -> Box<dyn PipelineTrait> {
                Box::new(self.clone())
            }
        }
    };

    TokenStream::from(gen)
}

/// Derive an orbtk as_any type. It returns a token stream object.
#[proc_macro_derive(AsAny)]
pub fn derive_as_any(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl AsAny for #ident {
            fn as_any(&self) -> &dyn Any {
                self
            }

            fn as_any_mut(&mut self) -> &mut dyn Any {
                self
            }
        }
    };

    TokenStream::from(gen)
}

/// Derive into an orbtk render object. It returns a token stream object.
#[proc_macro_derive(IntoRenderObject)]
pub fn derive_into_render_object(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl From<#ident> for Box<dyn RenderObject> {
            fn from(i: #ident) -> Box<dyn RenderObject> {
                Box::new(i)
            }
        }
    };

    TokenStream::from(gen)
}

/// Derive into an orbtk layout object. It returns a token stream object.
#[proc_macro_derive(IntoLayout)]
pub fn derive_into_layout(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl From<#ident> for Box<dyn Layout> {
            fn from(i: #ident) -> Box<dyn Layout> {
                Box::new(i)
            }
        }
    };

    TokenStream::from(gen)
}

/// Derive into an orbtk event object. It returns a token stream object.
#[proc_macro_derive(Event)]
pub fn derive_event(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl Event for #ident {}
    };

    TokenStream::from(gen)
}

/// Derive into an orbtk handler object. It returns a token stream object.
#[proc_macro_derive(IntoHandler)]
pub fn derive_into_handler(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let gen = quote! {
        impl From<#ident> for Rc<dyn EventHandler> {
            fn from(i: #ident) -> Rc<dyn EventHandler> {
                Rc::new(i)
            }
        }
    };

    TokenStream::from(gen)
}

/// Derive into an orbtk widget context object. It returns a token stream object.
#[proc_macro_derive(WidgetCtx, attributes(property))]
pub fn derive_widget_ctx(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let ident = &input.ident;

    let mut generated = vec![];

    if let syn::Data::Struct(DataStruct { ref fields, .. }) = input.data {
        let filter_fields = fields
            .iter()
            .filter(|f| f.attrs.iter().any(|attr| attr.path.is_ident("property")));

        for field in filter_fields {
            let field_name = field
                .clone()
                .ident
                .unwrap_or_else(|| panic!("Expected the field to have a name"));

            let field_name_str = field_name.to_string();

            for attr in field.attrs.iter() {
                let last_attr_path = attr
                    .path
                    .segments
                    .iter()
                    .last()
                    .expect("Expected at least one segment where #[segment[::segment*](..)]");
                if (*last_attr_path).ident != "property" {
                    continue;
                }

                let meta = match attr.parse_meta() {
                    Ok(meta) => meta,
                    Err(_) => continue,
                };
                let list = match meta {
                    Meta::List(l) => l,
                    _ if meta.path().is_ident("property") => {
                        panic!("Invalid #[new] attribute, expected #[property(..)]")
                    }
                    _ => continue,
                };

                for item in list.nested.iter() {
                    match *item {
                        NestedMeta::Meta(Meta::Path(ref path)) => {
                            let ty = path.get_ident();

                            if let Some(ty) = ty {
                                let getter = Ident::new(
                                    format!("{}_ref", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let setter = Ident::new(
                                    format!("{}_set", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let clone = Ident::new(
                                    format!("{}_clone", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let get_mut = Ident::new(
                                    format!("{}_mut", field_name).as_str(),
                                    Span::call_site(),
                                );

                                let gen = quote! {
                                    /// Gets a reference of the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #getter<'a>(widget: &'a WidgetContainer<'a>) -> &'a #ty {
                                        #ident::panics_on_wrong_type(widget);
                                        widget.get(#field_name_str)
                                    }

                                    /// Gets a mutable reference of the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #get_mut<'a>(widget: &'a mut WidgetContainer<'a>) -> &'a mut #ty {
                                        #ident::panics_on_wrong_type(widget);
                                        widget.get_mut(#field_name_str)
                                    }

                                    /// Sets the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #setter(widget: &mut WidgetContainer, value: impl Into<#ty>) {
                                        #ident::panics_on_wrong_type(widget);
                                        widget.set(#field_name_str, value.into());
                                    }

                                    /// Clones the property value. Panics if it is the wrong widget type.
                                    #[inline(always)]
                                    pub fn #clone(widget: &WidgetContainer) -> #ty {
                                        widget.clone(#field_name_str)
                                    }
                                };

                                generated.push(gen);
                            }

                            break;
                        }
                        _ => continue,
                    }
                }
            }
        }
    }

    let gen = quote! {
        impl #ident {
            #(#generated)*
        }
    };

    TokenStream::from(gen)
}
<|endoftext|>


<commit_before>use std::io::{self, Read, Write};

/// Name of the compression scheme used in the doc store.
///
/// This name is appended to the version string of tantivy.
pub const COMPRESSION: &'static str = "lz4";

pub fn compress(uncompressed: &[u8], compressed: &mut Vec<u8>) -> io::Result<()> {
    compressed.clear();
    let mut encoder = lz4::EncoderBuilder::new().build(compressed)?;
    encoder.write_all(&uncompressed)?;
    let (_, encoder_result) = encoder.finish();
    encoder_result?;
    Ok(())
}

pub fn decompress(compressed: &[u8], decompressed: &mut Vec<u8>) -> io::Result<()> {
    decompressed.clear();
    let mut decoder = lz4::Decoder::new(compressed)?;
    decoder.read_to_end(decompressed)?;
    Ok(())
}
<commit_msg>Removed 'static in compression_lz4.<commit_after>use std::io::{self, Read, Write};

/// Name of the compression scheme used in the doc store.
///
/// This name is appended to the version string of tantivy.
pub const COMPRESSION: &str = "lz4";

pub fn compress(uncompressed: &[u8], compressed: &mut Vec<u8>) -> io::Result<()> {
    compressed.clear();
    let mut encoder = lz4::EncoderBuilder::new().build(compressed)?;
    encoder.write_all(&uncompressed)?;
    let (_, encoder_result) = encoder.finish();
    encoder_result?;
    Ok(())
}

pub fn decompress(compressed: &[u8], decompressed: &mut Vec<u8>) -> io::Result<()> {
    decompressed.clear();
    let mut decoder = lz4::Decoder::new(compressed)?;
    decoder.read_to_end(decompressed)?;
    Ok(())
}
<|endoftext|>


<commit_before>use bus::Bus;

#[derive(Default)]
struct SysTick
{
    pub rvr : u32,
    pub cvr : u32,
    pub csr : u32
}

#[derive(Default)]
struct Dwt
{
    pub ctrl : u32,
}

#[derive(Default)]
pub struct InternalBus {
    shpr3: u32, // RW, 0xe000_ed20, reset value = SBZ (systick, pendsv bits are zero)
    vtor: u32,  // RW, 0xe000_ed08, reset value = 0
    syst : SysTick,
    dwt : Dwt
    /*
    ACTLR: u32, // RW, 0xe000_e008, reset value = implementation defined

    SYST_CSR: u32, // RW, 0xe000_e010, reset value = 0 or 4,
    SYST_RVR: u32, // RW, 0xe000_e014, reset value = unknown,
    SYST_CVR: u32, // RW, 0xe000_e018, reset value = unknown,
    SYST_CALIB: u32, // R0, 0xe000_e01C, reset value = implementation_defined,

    CPUID: u32, // RO, 0xe000_ed00, reset value = implementation defined
    ICSR: u32,  // RW, 0xe000_ed04, reset value = 0
    AIRCR: u32, // RW, 0xe000_ed0c, reset value = bits [10:8] = 0b000
    SCR: u32,   // RW, 0xe000_ed10, reset value = bits [4,2,1] = 0b000
    CCR: u32,   // RO, 0xe000_ed14, reset value = bits [9:3] = 0b111111
    SHPR2: u32, // RW, 0xe000_ed1c, reset value = SBZ (svcall priority is zero)
    SHCSR: u32, // RW, 0xe000_ed24, reset value = 0
    DFSR: u32,  // RW, 0xe000_ed30, reset value = 0*/

/*DWT_CTRL	Read/write	0xE0001000	0x00000000	See DWT Control Register
DWT_CYCCNT	Read/write	0xE0001004	0x00000000	See DWT Current PC Sampler Cycle Count Register
DWT_CPICNT	Read/write	0xE0001008	-	See DWT CPI Count Register
DWT_EXCCNT	Read/write	0xE000100C	-	See DWT Exception Overhead Count Register
DWT_SLEEPCNT	Read/write	0xE0001010	-	See DWT Sleep Count Register
DWT_LSUCNT	Read/write	0xE0001014	-	See DWT LSU Count Register
DWT_FOLDCNT	Read/write	0xE0001018	-	See DWT Fold Count Register
DWT_PCSR	Read-only	0xE000101C	-	See DWT Program Counter Sample Register
DWT_COMP0	Read/write	0xE0001020	-	See DWT Comparator Registers
DWT_MASK0	Read/write	0xE0001024	-	See DWT Mask Registers 0-3
DWT_FUNCTION0	Read/write	0xE0001028	0x00000000	See DWT Function Registers 0-3
DWT_COMP1	Read/write	0xE0001030	-	See DWT Comparator Registers
DWT_MASK1	Read/write	0xE0001034	-	See DWT Mask Registers 0-3
DWT_FUNCTION1	Read/write	0xE0001038	0x00000000	See DWT Function Registers 0-3
DWT_COMP2	Read/write	0xE0001040	-	See DWT Comparator Registers
DWT_MASK2	Read/write	0xE0001044	-	See DWT Mask Registers 0-3
DWT_FUNCTION2	Read/write	0xE0001048	0x00000000	See DWT Function Registers 0-3
DWT_COMP3	Read/write	0xE0001050	-	See DWT Comparator Registers
DWT_MASK3	Read/write	0xE0001054 	-	See DWT Mask Registers 0-3
DWT_FUNCTION3	Read/write	0xE0001058 	0x00000000	See DWT Function Registers 0-3
PID4	Read-only	0xE0001FD0	0x04	Value 0x04
PID5	Read-only	0xE0001FD4	0x00	Value 0x00
PID6	Read-only	0xE0001FD8	0x00	Value 0x00
PID7	Read-only	0xE0001FDC	0x00	Value 0x00
PID0	Read-only	0xE0001FE0	0x02	Value 0x02
PID1	Read-only	0xE0001FE4	0xB0	Value 0xB0
PID2	Read-only	0xE0001FE8	0x1B	Value 0x1B
PID3	Read-only	0xE0001FEC	0x00	Value 0x00
CID0	Read-only	0xE0001FF0	0x0D	Value 0x0D
CID1	Read-only	0xE0001FF4	0xE0	Value 0xE0
CID2	Read-only	0xE0001FF8	0x05	Value 0x05
CID3	Read-only	0xE0001FFC	0xB1	Value 0xB1*/

}

impl InternalBus {
    fn read_shpr3(&self) -> u32 {
        self.shpr3
    }

    fn write_shpr3(&mut self, value: u32) {
        self.shpr3 = value
    }

    fn write_syst_rvr(&mut self, value: u32) {
        self.syst.rvr = value
    }

    fn write_syst_cvr(&mut self, value: u32) {
        self.syst.cvr = value
    }

    fn write_syst_csr(&mut self, value: u32) {
        self.syst.csr = value
    }

    fn write_vtor(&mut self, value: u32) {
        self.vtor = value
    }

    pub fn new() -> InternalBus {
        InternalBus { vtor : 0, shpr3: 0, syst : SysTick::default(), dwt : Dwt{ ctrl : 0x40000000} }
    }
}

const INTERNAL_BUS_START: u32 = 0xE000_0000;
const INTERNAL_BUS_END: u32 = 0xF000_0000;

impl Bus for InternalBus {
    fn read16(&mut self, addr: u32) -> u16 {
        panic!("half-word access read to system area 0x{:x}", addr);
    }

    fn read32(&mut self, addr: u32) -> u32 {
        match addr {
            0xE000_ED20 => self.read_shpr3(),
            // DWT
            0xE000_1000 => self.dwt.ctrl,
            _ => panic!("bus access fault read addr 0x{:x}", addr),
        }
    }
    fn read8(&mut self, addr: u32) -> u8 {
        panic!("byte access read to system area 0x{:x}", addr);
    }

    fn write32(&mut self, addr: u32, value: u32) {
        match addr {
            0xE000_1000 => self.dwt.ctrl = value,
            0xE000_ED08 => self.write_vtor(value),
            0xE000_ED20 => self.write_shpr3(value),
            0xE000_E010 => self.write_syst_csr(value),
            0xE000_E014 => self.write_syst_rvr(value),
            0xE000_E018 => self.write_syst_cvr(value),
            _ => panic!("bus access fault write addr 0x{:x}={}", addr, value),
        }
    }

    fn write16(&mut self, addr: u32, value: u16) {
        panic!(
            "half-word access write to system area 0x{:x}->{}",
            addr,
            value
        );
    }

    fn write8(&mut self, addr: u32, value: u8) {
        panic!("byte access write to system area 0x{:x}->{}", addr, value);
    }

    fn in_range(&self, addr: u32) -> bool {
        if (addr >= INTERNAL_BUS_START) && (addr < INTERNAL_BUS_END) {
            return true;
        }
        false
    }
}
<commit_msg>Add icsr reg support<commit_after>use bus::Bus;

#[derive(Default)]
struct SysTick
{
    pub rvr : u32,
    pub cvr : u32,
    pub csr : u32
}

#[derive(Default)]
struct Dwt
{
    pub ctrl : u32,
}

#[derive(Default)]
pub struct InternalBus {
    shpr3: u32, // RW, 0xe000_ed20, reset value = SBZ (systick, pendsv bits are zero)
    vtor: u32,  // RW, 0xe000_ed08, reset value = 0
    icsr: u32, // Interrupt Control and State Register RW, 0xe000_ed04, reset value = 0
    syst : SysTick,
    dwt : Dwt
    /*
    ACTLR: u32, // RW, 0xe000_e008, reset value = implementation defined

    SYST_CSR: u32, // RW, 0xe000_e010, reset value = 0 or 4,
    SYST_RVR: u32, // RW, 0xe000_e014, reset value = unknown,
    SYST_CVR: u32, // RW, 0xe000_e018, reset value = unknown,
    SYST_CALIB: u32, // R0, 0xe000_e01C, reset value = implementation_defined,

    CPUID: u32, // RO, 0xe000_ed00, reset value = implementation defined

    AIRCR: u32, // RW, 0xe000_ed0c, reset value = bits [10:8] = 0b000
    SCR: u32,   // RW, 0xe000_ed10, reset value = bits [4,2,1] = 0b000
    CCR: u32,   // RO, 0xe000_ed14, reset value = bits [9:3] = 0b111111
    SHPR2: u32, // RW, 0xe000_ed1c, reset value = SBZ (svcall priority is zero)
    SHCSR: u32, // RW, 0xe000_ed24, reset value = 0
    DFSR: u32,  // RW, 0xe000_ed30, reset value = 0*/

/*DWT_CTRL	Read/write	0xE0001000	0x00000000	See DWT Control Register
DWT_CYCCNT	Read/write	0xE0001004	0x00000000	See DWT Current PC Sampler Cycle Count Register
DWT_CPICNT	Read/write	0xE0001008	-	See DWT CPI Count Register
DWT_EXCCNT	Read/write	0xE000100C	-	See DWT Exception Overhead Count Register
DWT_SLEEPCNT	Read/write	0xE0001010	-	See DWT Sleep Count Register
DWT_LSUCNT	Read/write	0xE0001014	-	See DWT LSU Count Register
DWT_FOLDCNT	Read/write	0xE0001018	-	See DWT Fold Count Register
DWT_PCSR	Read-only	0xE000101C	-	See DWT Program Counter Sample Register
DWT_COMP0	Read/write	0xE0001020	-	See DWT Comparator Registers
DWT_MASK0	Read/write	0xE0001024	-	See DWT Mask Registers 0-3
DWT_FUNCTION0	Read/write	0xE0001028	0x00000000	See DWT Function Registers 0-3
DWT_COMP1	Read/write	0xE0001030	-	See DWT Comparator Registers
DWT_MASK1	Read/write	0xE0001034	-	See DWT Mask Registers 0-3
DWT_FUNCTION1	Read/write	0xE0001038	0x00000000	See DWT Function Registers 0-3
DWT_COMP2	Read/write	0xE0001040	-	See DWT Comparator Registers
DWT_MASK2	Read/write	0xE0001044	-	See DWT Mask Registers 0-3
DWT_FUNCTION2	Read/write	0xE0001048	0x00000000	See DWT Function Registers 0-3
DWT_COMP3	Read/write	0xE0001050	-	See DWT Comparator Registers
DWT_MASK3	Read/write	0xE0001054 	-	See DWT Mask Registers 0-3
DWT_FUNCTION3	Read/write	0xE0001058 	0x00000000	See DWT Function Registers 0-3
PID4	Read-only	0xE0001FD0	0x04	Value 0x04
PID5	Read-only	0xE0001FD4	0x00	Value 0x00
PID6	Read-only	0xE0001FD8	0x00	Value 0x00
PID7	Read-only	0xE0001FDC	0x00	Value 0x00
PID0	Read-only	0xE0001FE0	0x02	Value 0x02
PID1	Read-only	0xE0001FE4	0xB0	Value 0xB0
PID2	Read-only	0xE0001FE8	0x1B	Value 0x1B
PID3	Read-only	0xE0001FEC	0x00	Value 0x00
CID0	Read-only	0xE0001FF0	0x0D	Value 0x0D
CID1	Read-only	0xE0001FF4	0xE0	Value 0xE0
CID2	Read-only	0xE0001FF8	0x05	Value 0x05
CID3	Read-only	0xE0001FFC	0xB1	Value 0xB1*/

}

impl InternalBus {
    fn read_shpr3(&self) -> u32 {
        self.shpr3
    }

    fn write_shpr3(&mut self, value: u32) {
        self.shpr3 = value
    }

    fn write_syst_rvr(&mut self, value: u32) {
        self.syst.rvr = value
    }

    fn write_syst_cvr(&mut self, value: u32) {
        self.syst.cvr = value
    }

    fn write_syst_csr(&mut self, value: u32) {
        self.syst.csr = value
    }

    fn write_vtor(&mut self, value: u32) {
        self.vtor = value
    }

    pub fn new() -> InternalBus {
        InternalBus { vtor : 0, shpr3: 0, syst : SysTick::default(), dwt : Dwt{ ctrl : 0x40000000}, icsr: 0 }
    }
}

const INTERNAL_BUS_START: u32 = 0xE000_0000;
const INTERNAL_BUS_END: u32 = 0xF000_0000;

impl Bus for InternalBus {
    fn read16(&mut self, addr: u32) -> u16 {
        panic!("half-word access read to system area 0x{:x}", addr);
    }

    fn read32(&mut self, addr: u32) -> u32 {
        match addr {
            0xE000_ED20 => self.read_shpr3(),
            // DWT
            0xE000_1000 => self.dwt.ctrl,
            _ => panic!("bus access fault read addr 0x{:x}", addr),
        }
    }
    fn read8(&mut self, addr: u32) -> u8 {
        panic!("byte access read to system area 0x{:x}", addr);
    }

    fn write32(&mut self, addr: u32, value: u32) {
        match addr {
            0xE000_1000 => self.dwt.ctrl = value,
            0xE000_ED04 => self.icsr = value,
            0xE000_ED08 => self.write_vtor(value),
            0xE000_ED20 => self.write_shpr3(value),
            0xE000_E010 => self.write_syst_csr(value),
            0xE000_E014 => self.write_syst_rvr(value),
            0xE000_E018 => self.write_syst_cvr(value),
            _ => panic!("bus access fault write addr 0x{:x}={}", addr, value),
        }
    }

    fn write16(&mut self, addr: u32, value: u16) {
        panic!(
            "half-word access write to system area 0x{:x}->{}",
            addr,
            value
        );
    }

    fn write8(&mut self, addr: u32, value: u8) {
        panic!("byte access write to system area 0x{:x}->{}", addr, value);
    }

    fn in_range(&self, addr: u32) -> bool {
        if (addr >= INTERNAL_BUS_START) && (addr < INTERNAL_BUS_END) {
            return true;
        }
        false
    }
}
<|endoftext|>


<commit_before>#![feature(plugin, custom_attribute)]
#![plugin(gfx_macros)]

extern crate piston;
extern crate vecmath;
extern crate camera_controllers;
extern crate gfx;
extern crate gfx_device_gl;
extern crate sdl2_window;

use std::rc::Rc;
use std::cell::RefCell;
use piston::window::{ AdvancedWindow, WindowSettings, Size };
use camera_controllers::{
    FirstPersonSettings,
    FirstPerson,
    CameraPerspective,
    model_view_projection
};
use gfx::traits::*;
use sdl2_window::{ Sdl2Window, OpenGL, OpenGLWindow };

//----------------------------------------
// Cube associated data

#[vertex_format]
#[derive(Copy, Clone)]
struct Vertex {
    #[as_float]
    a_pos: [i8; 3],
    #[as_float]
    a_tex_coord: [u8; 2],
}

impl Vertex {
    fn new(pos: [i8; 3], tc: [u8; 2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

#[shader_param]
struct Params<R: gfx::Resources> {
    u_model_view_proj: [[f32; 4]; 4],
    t_color: gfx::shade::TextureParam<R>,
}

const VERTEX_SRC: [&'static [u8]; 2] = [ b"
    #version 120
    attribute vec3 a_pos;
    attribute vec2 a_tex_coord;
    varying vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
", b"
    #version 150 core
    in vec3 a_pos;
    in vec2 a_tex_coord;
    out vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
"];

const FRAGMENT_SRC: [&'static [u8]; 2] = [ b"
    #version 120
    varying vec2 v_TexCoord;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture2D(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
", b"
    #version 150 core
    in vec2 v_TexCoord;
    out vec4 o_Color;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"];

//----------------------------------------

fn main() {
    let (win_width, win_height) = (640, 480);
    let mut window = Sdl2Window::new(
        OpenGL::_3_2,
        WindowSettings::new(
            "piston-example-gfx_cube".to_string(),
            Size { width: win_width, height: win_height }
        )
        .exit_on_esc(true)
        .samples(4)
    );

    window.set_capture_cursor(true);

    let vertex = gfx::ShaderSource {
        glsl_120: Some(VERTEX_SRC[0]),
        glsl_150: Some(VERTEX_SRC[1]),
        .. gfx::ShaderSource::empty()
    };
    let fragment = gfx::ShaderSource {
        glsl_120: Some(FRAGMENT_SRC[0]),
        glsl_150: Some(FRAGMENT_SRC[1]),
        .. gfx::ShaderSource::empty()
    };

    let mut device = gfx_device_gl::GlDevice::new(|s| window.get_proc_address(s));
    let frame = gfx::Frame::new(win_width as u16, win_height as u16);
    let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    let vertex_data = vec![
        //top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //bottom (0, 0, -1)
        Vertex::new([ 1,  1, -1], [0, 0]),
        Vertex::new([-1,  1, -1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
        //right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([ 1, -1,  1], [0, 1]),
        //left (-1, 0, 0)
        Vertex::new([-1,  1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([-1,  1, -1], [0, 1]),
        //front (0, 1, 0)
        Vertex::new([-1,  1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
    ];

    let mesh = device.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  6,  5,  6,  4,  7, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 14, 13, 14, 12, 16, // left
        16, 18, 17, 18, 16, 19, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = device.create_buffer_index(index_data)
                      .to_slice(gfx::PrimitiveType::TriangleList);

    let tinfo = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::TextureKind::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let img_info = tinfo.to_image_info();
    let texture = device.create_texture(tinfo).unwrap();
    device.update_texture(
        &texture,
        &img_info,
        &[0x20u8, 0xA0, 0xC0, 0x00]
    ).unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(
            gfx::tex::FilterMethod::Bilinear,
            gfx::tex::WrapMode::Clamp
        )
    );

    let shader_model = device.get_capabilities().shader_model;

    let program = device.link_program(
        vertex.choose(shader_model).unwrap(),
        fragment.choose(shader_model).unwrap()
    ).unwrap();

    let mut graphics = device.into_graphics();

    let data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
    };

    let mut batch = graphics.make_batch(&program, data, &mesh, slice, &state).unwrap();

    let model = vecmath::mat4_id();
    let projection = CameraPerspective {
        fov: 90.0,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();
    let mut first_person = FirstPerson::new(
        [0.5, 0.5, 4.0],
        FirstPersonSettings::keyboard_wasd()
    );

    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;

        first_person.event(&e);

        if let Some(args) = e.render_args() {
            graphics.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                },
                gfx::COLOR | gfx::DEPTH,
                &frame
            );
            batch.params.u_model_view_proj = model_view_projection(
                model,
                first_person.camera(args.ext_dt).orthogonal(),
                projection
            );
            graphics.draw(&batch, &frame).unwrap();
            graphics.end_frame();
        }

        if let Some(_) = e.after_render_args() {
            graphics.device.after_frame();
        }
    }
}
<commit_msg>Upgrade gfx_cube example to latest gfx<commit_after>#![feature(plugin, custom_attribute)]
#![plugin(gfx_macros)]

extern crate piston;
extern crate vecmath;
extern crate camera_controllers;
extern crate gfx;
extern crate gfx_device_gl;
extern crate sdl2_window;

use std::rc::Rc;
use std::cell::RefCell;
use piston::window::{ AdvancedWindow, WindowSettings, Size, OpenGLWindow };
use camera_controllers::{
    FirstPersonSettings,
    FirstPerson,
    CameraPerspective,
    model_view_projection
};
use gfx::traits::*;
use sdl2_window::{ Sdl2Window, OpenGL };

//----------------------------------------
// Cube associated data

#[vertex_format]
#[derive(Copy, Clone)]
struct Vertex {
    #[as_float]
    a_pos: [i8; 3],
    #[as_float]
    a_tex_coord: [u8; 2],
}

impl Vertex {
    fn new(pos: [i8; 3], tc: [u8; 2]) -> Vertex {
        Vertex {
            a_pos: pos,
            a_tex_coord: tc,
        }
    }
}

#[shader_param]
struct Params<R: gfx::Resources> {
    u_model_view_proj: [[f32; 4]; 4],
    t_color: gfx::shade::TextureParam<R>,
}

const VERTEX_SRC: [&'static [u8]; 2] = [ b"
    #version 120
    attribute vec3 a_pos;
    attribute vec2 a_tex_coord;
    varying vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
", b"
    #version 150 core
    in vec3 a_pos;
    in vec2 a_tex_coord;
    out vec2 v_TexCoord;
    uniform mat4 u_model_view_proj;
    void main() {
        v_TexCoord = a_tex_coord;
        gl_Position = u_model_view_proj * vec4(a_pos, 1.0);
    }
"];

const FRAGMENT_SRC: [&'static [u8]; 2] = [ b"
    #version 120
    varying vec2 v_TexCoord;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture2D(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
", b"
    #version 150 core
    in vec2 v_TexCoord;
    out vec4 o_Color;
    uniform sampler2D t_color;
    void main() {
        vec4 tex = texture(t_color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"];

//----------------------------------------

fn main() {
    let (win_width, win_height) = (640, 480);
    let mut window = Sdl2Window::new(
        OpenGL::_3_2,
        WindowSettings::new(
            "piston-example-gfx_cube".to_string(),
            Size { width: win_width, height: win_height }
        )
        .exit_on_esc(true)
        .samples(4)
    );

    window.set_capture_cursor(true);

    let vertex = gfx::ShaderSource {
        glsl_120: Some(VERTEX_SRC[0]),
        glsl_150: Some(VERTEX_SRC[1]),
        .. gfx::ShaderSource::empty()
    };
    let fragment = gfx::ShaderSource {
        glsl_120: Some(FRAGMENT_SRC[0]),
        glsl_150: Some(FRAGMENT_SRC[1]),
        .. gfx::ShaderSource::empty()
    };

    let mut device = gfx_device_gl::GlDevice::new(|s| window.get_proc_address(s));
    let frame = gfx::Frame::new(win_width as u16, win_height as u16);
    let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

    let vertex_data = vec![
        //top (0, 0, 1)
        Vertex::new([-1, -1,  1], [0, 0]),
        Vertex::new([ 1, -1,  1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //bottom (0, 0, -1)
        Vertex::new([ 1,  1, -1], [0, 0]),
        Vertex::new([-1,  1, -1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
        //right (1, 0, 0)
        Vertex::new([ 1, -1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([ 1, -1,  1], [0, 1]),
        //left (-1, 0, 0)
        Vertex::new([-1,  1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([-1,  1, -1], [0, 1]),
        //front (0, 1, 0)
        Vertex::new([-1,  1, -1], [0, 0]),
        Vertex::new([ 1,  1, -1], [1, 0]),
        Vertex::new([ 1,  1,  1], [1, 1]),
        Vertex::new([-1,  1,  1], [0, 1]),
        //back (0, -1, 0)
        Vertex::new([ 1, -1,  1], [0, 0]),
        Vertex::new([-1, -1,  1], [1, 0]),
        Vertex::new([-1, -1, -1], [1, 1]),
        Vertex::new([ 1, -1, -1], [0, 1]),
    ];

    let mesh = device.create_mesh(&vertex_data);

    let index_data: &[u8] = &[
         0,  1,  2,  2,  3,  0, // top
         4,  6,  5,  6,  4,  7, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 14, 13, 14, 12, 16, // left
        16, 18, 17, 18, 16, 19, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = device.create_buffer_index(index_data)
                      .to_slice(gfx::PrimitiveType::TriangleList);

    let tinfo = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::TextureKind::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let img_info = tinfo.to_image_info();
    let texture = device.create_texture(tinfo).unwrap();
    device.update_texture(
        &texture,
        &img_info,
        &[0x20u8, 0xA0, 0xC0, 0x00],
        Some(gfx::tex::TextureKind::Texture2D)
    ).unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(
            gfx::tex::FilterMethod::Bilinear,
            gfx::tex::WrapMode::Clamp
        )
    );

    let shader_model = device.get_capabilities().shader_model;

    let program = device.link_program(
        vertex.choose(shader_model).unwrap(),
        fragment.choose(shader_model).unwrap()
    ).unwrap();

    let mut graphics = device.into_graphics();

    let data = Params {
        u_model_view_proj: vecmath::mat4_id(),
        t_color: (texture, Some(sampler)),
    };

    let mut batch = graphics.make_batch(&program, data, &mesh, slice, &state).unwrap();

    let model = vecmath::mat4_id();
    let projection = CameraPerspective {
        fov: 90.0,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: (win_width as f32) / (win_height as f32)
    }.projection();
    let mut first_person = FirstPerson::new(
        [0.5, 0.5, 4.0],
        FirstPersonSettings::keyboard_wasd()
    );

    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;

        first_person.event(&e);

        if let Some(args) = e.render_args() {
            graphics.clear(
                gfx::ClearData {
                    color: [0.3, 0.3, 0.3, 1.0],
                    depth: 1.0,
                    stencil: 0,
                },
                gfx::COLOR | gfx::DEPTH,
                &frame
            );
            batch.params.u_model_view_proj = model_view_projection(
                model,
                first_person.camera(args.ext_dt).orthogonal(),
                projection
            );
            graphics.draw(&batch, &frame).unwrap();
            graphics.end_frame();
        }

        if let Some(_) = e.after_render_args() {
            graphics.device.after_frame();
        }
    }
}
<|endoftext|>


<commit_before>//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types.

use rustc::ty::layout::{self, TyLayout};
use rustc::ty;
use rustc::mir::interpret::{
    EvalResult,
};

use super::{
    Machine, EvalContext, MPlaceTy, PlaceTy, OpTy, ImmTy,
};

// A thing that we can project into, and that has a layout.
// This wouldn't have to depend on `Machine` but with the current type inference,
// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
{
    /// Get this value's layout.
    fn layout(&self) -> TyLayout<'tcx>;

    /// Make this into an `OpTy`.
    fn to_op(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;

    /// Create this from an `MPlaceTy`.
    fn from_mem_place(MPlaceTy<'tcx, M::PointerTag>) -> Self;

    /// Project to the given enum variant.
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self>;

    /// Project to the n-th field.
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self>;
}

// Operands and places are both values
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for OpTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self)
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace.into()
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_field(self, field)
    }
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for MPlaceTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self.into())
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_field(self, field)
    }
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for PlaceTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        ecx.place_to_op(self)
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace.into()
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self> {
        ecx.place_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.place_field(self, field)
    }
}

// How to traverse a value and what to do when we are at the leaves.
pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
    type V: Value<'a, 'mir, 'tcx, M>;

    /// The visitor must have an `EvalContext` in it.
    fn ecx(&mut self) -> &mut EvalContext<'a, 'mir, 'tcx, M>;

    // Recursive actions, ready to be overloaded.
    /// Visit the given value, dispatching as appropriate to more specialized visitors.
    #[inline(always)]
    fn visit_value(&mut self, v: Self::V) -> EvalResult<'tcx>
    {
        self.walk_value(v)
    }
    /// Visit the given value as a union.  No automatic recursion can happen here.
    #[inline(always)]
    fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx>
    {
        Ok(())
    }
    /// Visit this vale as an aggregate, you are even getting an iterator yielding
    /// all the fields (still in an `EvalResult`, you have to do error handling yourself).
    /// Recurses into the fields.
    #[inline(always)]
    fn visit_aggregate(
        &mut self,
        v: Self::V,
        fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
    ) -> EvalResult<'tcx> {
        self.walk_aggregate(v, fields)
    }
    /// Called each time we recurse down to a field, passing in old and new value.
    /// This gives the visitor the chance to track the stack of nested fields that
    /// we are descending through.
    #[inline(always)]
    fn visit_field(
        &mut self,
        _old_val: Self::V,
        _field: usize,
        new_val: Self::V,
    ) -> EvalResult<'tcx> {
        self.visit_value(new_val)
    }

    /// Called whenever we reach a value with uninhabited layout.
    /// Recursing to fields will *always* continue after this!  This is not meant to control
    /// whether and how we descend recursively/ into the scalar's fields if there are any, it is
    /// meant to provide the chance for additional checks when a value of uninhabited layout is
    /// detected.
    #[inline(always)]
    fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
    { Ok(()) }
    /// Called whenever we reach a value with scalar layout.
    /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the visitor is not
    /// even interested in scalars.
    /// Recursing to fields will *always* continue after this!  This is not meant to control
    /// whether and how we descend recursively/ into the scalar's fields if there are any, it is
    /// meant to provide the chance for additional checks when a value of scalar layout is detected.
    #[inline(always)]
    fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
    { Ok(()) }

    /// Called whenever we reach a value of primitive type.  There can be no recursion
    /// below such a value.  This is the leave function.
    #[inline(always)]
    fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
    { Ok(()) }

    // Default recursors. Not meant to be overloaded.
    fn walk_aggregate(
        &mut self,
        v: Self::V,
        fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
    ) -> EvalResult<'tcx> {
        // Now iterate over it.
        for (idx, field_val) in fields.enumerate() {
            self.visit_field(v, idx, field_val?)?;
        }
        Ok(())
    }
    fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
    {
        // If this is a multi-variant layout, we have find the right one and proceed with that.
        // (No benefit from making this recursion, but it is equivalent to that.)
        match v.layout().variants {
            layout::Variants::NicheFilling { .. } |
            layout::Variants::Tagged { .. } => {
                let op = v.to_op(self.ecx())?;
                let idx = self.ecx().read_discriminant(op)?.1;
                let inner = v.project_downcast(self.ecx(), idx)?;
                trace!("walk_value: variant layout: {:#?}", inner.layout());
                // recurse with the inner type
                return self.visit_field(v, idx, inner);
            }
            layout::Variants::Single { .. } => {}
        }

        // Even for single variants, we might be able to get a more refined type:
        // If it is a trait object, switch to the actual type that was used to create it.
        match v.layout().ty.sty {
            ty::Dynamic(..) => {
                // immediate trait objects are not a thing
                let dest = v.to_op(self.ecx())?.to_mem_place();
                let inner = self.ecx().unpack_dyn_trait(dest)?.1;
                trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                // recurse with the inner type
                return self.visit_field(v, 0, Value::from_mem_place(inner));
            },
            _ => {},
        };

        // If this is a scalar, visit it as such.
        // Things can be aggregates and have scalar layout at the same time, and that
        // is very relevant for `NonNull` and similar structs: We need to visit them
        // at their scalar layout *before* descending into their fields.
        // FIXME: We could avoid some redundant checks here. For newtypes wrapping
        // scalars, we do the same check on every "level" (e.g. first we check
        // MyNewtype and then the scalar in there).
        match v.layout().abi {
            layout::Abi::Uninhabited => {
                self.visit_uninhabited()?;
            }
            layout::Abi::Scalar(ref layout) => {
                self.visit_scalar(v, layout)?;
            }
            // FIXME: Should we do something for ScalarPair? Vector?
            _ => {}
        }

        // Check primitive types.  We do this after checking the scalar layout,
        // just to have that done as well.  Primitives can have varying layout,
        // so we check them separately and before aggregate handling.
        // It is CRITICAL that we get this check right, or we might be
        // validating the wrong thing!
        let primitive = match v.layout().fields {
            // Primitives appear as Union with 0 fields -- except for Boxes and fat pointers.
            layout::FieldPlacement::Union(0) => true,
            _ => v.layout().ty.builtin_deref(true).is_some(),
        };
        if primitive {
            let op = v.to_op(self.ecx())?;
            let val = self.ecx().read_immediate(op)?;
            return self.visit_primitive(val);
        }

        // Proceed into the fields.
        match v.layout().fields {
            layout::FieldPlacement::Union(fields) => {
                // Empty unions are not accepted by rustc. That's great, it means we can
                // use that as an unambiguous signal for detecting primitives.  Make sure
                // we did not miss any primitive.
                debug_assert!(fields > 0);
                self.visit_union(v)?;
            },
            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                // We collect in a vec because otherwise there are lifetime errors:
                // Projecting to a field needs (mutable!) access to `ecx`.
                let fields: Vec<EvalResult<'tcx, Self::V>> =
                    (0..offsets.len()).map(|i| {
                        v.project_field(self.ecx(), i as u64)
                    })
                    .collect();
                self.visit_aggregate(v, fields.into_iter())?;
            },
            layout::FieldPlacement::Array { .. } => {
                // Let's get an mplace first.
                let mplace = if v.layout().is_zst() {
                    // it's a ZST, the memory content cannot matter
                    MPlaceTy::dangling(v.layout(), self.ecx())
                } else {
                    // non-ZST array/slice/str cannot be immediate
                    v.to_op(self.ecx())?.to_mem_place()
                };
                // Now we can go over all the fields.
                let iter = self.ecx().mplace_array_fields(mplace)?
                    .map(|f| f.and_then(|f| {
                        Ok(Value::from_mem_place(f))
                    }));
                self.visit_aggregate(v, iter)?;
            }
        }
        Ok(())
    }
}
<commit_msg>FIXME<commit_after>//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types.

use rustc::ty::layout::{self, TyLayout};
use rustc::ty;
use rustc::mir::interpret::{
    EvalResult,
};

use super::{
    Machine, EvalContext, MPlaceTy, PlaceTy, OpTy, ImmTy,
};

// A thing that we can project into, and that has a layout.
// This wouldn't have to depend on `Machine` but with the current type inference,
// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
{
    /// Get this value's layout.
    fn layout(&self) -> TyLayout<'tcx>;

    /// Make this into an `OpTy`.
    fn to_op(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;

    /// Create this from an `MPlaceTy`.
    fn from_mem_place(MPlaceTy<'tcx, M::PointerTag>) -> Self;

    /// Project to the given enum variant.
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self>;

    /// Project to the n-th field.
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self>;
}

// Operands and places are both values
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for OpTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self)
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace.into()
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.operand_field(self, field)
    }
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for MPlaceTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        _ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        Ok(self.into())
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.mplace_field(self, field)
    }
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
    for PlaceTy<'tcx, M::PointerTag>
{
    #[inline(always)]
    fn layout(&self) -> TyLayout<'tcx> {
        self.layout
    }

    #[inline(always)]
    fn to_op(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
        ecx.place_to_op(self)
    }

    #[inline(always)]
    fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
        mplace.into()
    }

    #[inline(always)]
    fn project_downcast(
        self,
        ecx: &EvalContext<'a, 'mir, 'tcx, M>,
        variant: usize,
    ) -> EvalResult<'tcx, Self> {
        ecx.place_downcast(self, variant)
    }

    #[inline(always)]
    fn project_field(
        self,
        ecx: &mut EvalContext<'a, 'mir, 'tcx, M>,
        field: u64,
    ) -> EvalResult<'tcx, Self> {
        ecx.place_field(self, field)
    }
}

// How to traverse a value and what to do when we are at the leaves.
pub trait ValueVisitor<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
    type V: Value<'a, 'mir, 'tcx, M>;

    /// The visitor must have an `EvalContext` in it.
    fn ecx(&mut self) -> &mut EvalContext<'a, 'mir, 'tcx, M>;

    // Recursive actions, ready to be overloaded.
    /// Visit the given value, dispatching as appropriate to more specialized visitors.
    #[inline(always)]
    fn visit_value(&mut self, v: Self::V) -> EvalResult<'tcx>
    {
        self.walk_value(v)
    }
    /// Visit the given value as a union.  No automatic recursion can happen here.
    #[inline(always)]
    fn visit_union(&mut self, _v: Self::V) -> EvalResult<'tcx>
    {
        Ok(())
    }
    /// Visit this vale as an aggregate, you are even getting an iterator yielding
    /// all the fields (still in an `EvalResult`, you have to do error handling yourself).
    /// Recurses into the fields.
    #[inline(always)]
    fn visit_aggregate(
        &mut self,
        v: Self::V,
        fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
    ) -> EvalResult<'tcx> {
        self.walk_aggregate(v, fields)
    }
    /// Called each time we recurse down to a field, passing in old and new value.
    /// This gives the visitor the chance to track the stack of nested fields that
    /// we are descending through.
    #[inline(always)]
    fn visit_field(
        &mut self,
        _old_val: Self::V,
        _field: usize,
        new_val: Self::V,
    ) -> EvalResult<'tcx> {
        self.visit_value(new_val)
    }

    /// Called whenever we reach a value with uninhabited layout.
    /// Recursing to fields will *always* continue after this!  This is not meant to control
    /// whether and how we descend recursively/ into the scalar's fields if there are any, it is
    /// meant to provide the chance for additional checks when a value of uninhabited layout is
    /// detected.
    #[inline(always)]
    fn visit_uninhabited(&mut self) -> EvalResult<'tcx>
    { Ok(()) }
    /// Called whenever we reach a value with scalar layout.
    /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the visitor is not
    /// even interested in scalars.
    /// Recursing to fields will *always* continue after this!  This is not meant to control
    /// whether and how we descend recursively/ into the scalar's fields if there are any, it is
    /// meant to provide the chance for additional checks when a value of scalar layout is detected.
    #[inline(always)]
    fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<'tcx>
    { Ok(()) }

    /// Called whenever we reach a value of primitive type.  There can be no recursion
    /// below such a value.  This is the leave function.
    #[inline(always)]
    fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx>
    { Ok(()) }

    // Default recursors. Not meant to be overloaded.
    fn walk_aggregate(
        &mut self,
        v: Self::V,
        fields: impl Iterator<Item=EvalResult<'tcx, Self::V>>,
    ) -> EvalResult<'tcx> {
        // Now iterate over it.
        for (idx, field_val) in fields.enumerate() {
            self.visit_field(v, idx, field_val?)?;
        }
        Ok(())
    }
    fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
    {
        // If this is a multi-variant layout, we have find the right one and proceed with that.
        // (No benefit from making this recursion, but it is equivalent to that.)
        match v.layout().variants {
            layout::Variants::NicheFilling { .. } |
            layout::Variants::Tagged { .. } => {
                let op = v.to_op(self.ecx())?;
                let idx = self.ecx().read_discriminant(op)?.1;
                let inner = v.project_downcast(self.ecx(), idx)?;
                trace!("walk_value: variant layout: {:#?}", inner.layout());
                // recurse with the inner type
                return self.visit_field(v, idx, inner);
            }
            layout::Variants::Single { .. } => {}
        }

        // Even for single variants, we might be able to get a more refined type:
        // If it is a trait object, switch to the actual type that was used to create it.
        match v.layout().ty.sty {
            ty::Dynamic(..) => {
                // immediate trait objects are not a thing
                let dest = v.to_op(self.ecx())?.to_mem_place();
                let inner = self.ecx().unpack_dyn_trait(dest)?.1;
                trace!("walk_value: dyn object layout: {:#?}", inner.layout);
                // recurse with the inner type
                return self.visit_field(v, 0, Value::from_mem_place(inner));
            },
            _ => {},
        };

        // If this is a scalar, visit it as such.
        // Things can be aggregates and have scalar layout at the same time, and that
        // is very relevant for `NonNull` and similar structs: We need to visit them
        // at their scalar layout *before* descending into their fields.
        // FIXME: We could avoid some redundant checks here. For newtypes wrapping
        // scalars, we do the same check on every "level" (e.g. first we check
        // MyNewtype and then the scalar in there).
        match v.layout().abi {
            layout::Abi::Uninhabited => {
                self.visit_uninhabited()?;
            }
            layout::Abi::Scalar(ref layout) => {
                self.visit_scalar(v, layout)?;
            }
            // FIXME: Should we do something for ScalarPair? Vector?
            _ => {}
        }

        // Check primitive types.  We do this after checking the scalar layout,
        // just to have that done as well.  Primitives can have varying layout,
        // so we check them separately and before aggregate handling.
        // It is CRITICAL that we get this check right, or we might be
        // validating the wrong thing!
        let primitive = match v.layout().fields {
            // Primitives appear as Union with 0 fields -- except for Boxes and fat pointers.
            layout::FieldPlacement::Union(0) => true,
            _ => v.layout().ty.builtin_deref(true).is_some(),
        };
        if primitive {
            let op = v.to_op(self.ecx())?;
            let val = self.ecx().read_immediate(op)?;
            return self.visit_primitive(val);
        }

        // Proceed into the fields.
        match v.layout().fields {
            layout::FieldPlacement::Union(fields) => {
                // Empty unions are not accepted by rustc. That's great, it means we can
                // use that as an unambiguous signal for detecting primitives.  Make sure
                // we did not miss any primitive.
                debug_assert!(fields > 0);
                self.visit_union(v)?;
            },
            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                // FIXME: We collect in a vec because otherwise there are lifetime errors:
                // Projecting to a field needs (mutable!) access to `ecx`.
                let fields: Vec<EvalResult<'tcx, Self::V>> =
                    (0..offsets.len()).map(|i| {
                        v.project_field(self.ecx(), i as u64)
                    })
                    .collect();
                self.visit_aggregate(v, fields.into_iter())?;
            },
            layout::FieldPlacement::Array { .. } => {
                // Let's get an mplace first.
                let mplace = if v.layout().is_zst() {
                    // it's a ZST, the memory content cannot matter
                    MPlaceTy::dangling(v.layout(), self.ecx())
                } else {
                    // non-ZST array/slice/str cannot be immediate
                    v.to_op(self.ecx())?.to_mem_place()
                };
                // Now we can go over all the fields.
                let iter = self.ecx().mplace_array_fields(mplace)?
                    .map(|f| f.and_then(|f| {
                        Ok(Value::from_mem_place(f))
                    }));
                self.visit_aggregate(v, iter)?;
            }
        }
        Ok(())
    }
}
<|endoftext|>