<commit_before>extern crate ruroonga_client;
extern crate json_flex;

use json_flex::Unwrap;

use ruroonga_client as groonga;

fn create_table() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("table_create");
    command.set_argument(vec![("name", "Sites"),
                              ("flags","TABLE_HASH_KEY"),("key_type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.load(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn create_column() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("column_create");
    command.set_argument(vec![("table", "Sites"),
                              ("name","title"),("type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.load(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn load() {
    let data = r#"
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]"#;
    let mut request = groonga::HTTPRequest::new();
    let mut load_command = groonga::CommandQuery::new("load");
    load_command.set_argument(vec![("table", "Sites"),
                                   ("input_type","json"), ("values", data)]);
    let load_url = format!("http://localhost:10041{}", load_command.encode());
    println!("load url: {}", load_url);
    let load_res = request.load(load_url);
    let load_result = request.receive(&mut load_res.unwrap());
    println!("result: {}", load_result);
}

#[derive(Clone, Debug)]
struct Result {
    id: i64,
    key: String,
    title: String
}

fn main() {
    create_table();
    create_column();
    load();
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("select");
    command.set_argument(vec![("table", "Sites")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
    let mut decode = groonga::ResultParser::new(result);
    println!("status: {:?}", decode.status().unwrap());
    println!("start: {:?}", decode.start_time().unwrap());
    println!("elapsed: {:?}", decode.elapsed_time().unwrap());
    if decode.status().unwrap().clone() == 0 {
        println!("matched columns: {:?}", decode.matched_columns().unwrap());
        let decoded_vec = decode.result().unwrap().pop().unwrap().unwrap_vec().clone();
        println!("index access: {:?}", decoded_vec[2]);
        // Read got response
        let mut result_vec: Vec<Result> = Vec::new();
        println!("-- Display raw decoded json values --");
        // Skip reading result header
        for v in decoded_vec.iter().skip(2) {
            println!("{:?}", v);
            let raw = v.unwrap_vec();
            let elem = Result { id: raw[0].unwrap_i64().clone(),
                                key: raw[1].unwrap_string().clone(),
                                title: raw[2].unwrap_string().clone() };
            result_vec.push(elem.clone());
        }
        println!("-- Mapped to user-defined struct -- ");
        println!("{:?}", result_vec);
    } else {
        println!("Couldn't get success response.")
    }
}
<commit_msg>Example: Fix wrong API usage<commit_after>extern crate ruroonga_client;
extern crate json_flex;

use json_flex::Unwrap;

use ruroonga_client as groonga;

fn create_table() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("table_create");
    command.set_argument(vec![("name", "Sites"),
                              ("flags","TABLE_HASH_KEY"),("key_type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn create_column() {
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("column_create");
    command.set_argument(vec![("table", "Sites"),
                              ("name","title"),("type","ShortText")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("load url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
}

fn load() {
    let data = r#"
[
{"_key":"http://example.org/","title":"This is test record 1!"},
{"_key":"http://example.net/","title":"test record 2."},
{"_key":"http://example.com/","title":"test test record three."},
{"_key":"http://example.net/afr","title":"test record four."},
{"_key":"http://example.org/aba","title":"test test test record five."},
{"_key":"http://example.com/rab","title":"test test test test record six."},
{"_key":"http://example.net/atv","title":"test test test record seven."},
{"_key":"http://example.org/gat","title":"test test record eight."},
{"_key":"http://example.com/vdw","title":"test test record nine."},
]"#;
    let mut request = groonga::HTTPRequest::new();
    let mut load_command = groonga::CommandQuery::new("load");
    load_command.set_argument(vec![("table", "Sites"),
                                   ("input_type","json"), ("values", data)]);
    let load_url = format!("http://localhost:10041{}", load_command.encode());
    println!("load url: {}", load_url);
    let load_res = request.load(load_url);
    let load_result = request.receive(&mut load_res.unwrap());
    println!("result: {}", load_result);
}

#[derive(Clone, Debug)]
struct Result {
    id: i64,
    key: String,
    title: String
}

fn main() {
    create_table();
    create_column();
    load();
    let mut request = groonga::HTTPRequest::new();
    let mut command = groonga::CommandQuery::new("select");
    command.set_argument(vec![("table", "Sites")]);
    let url = format!("http://localhost:10041{}", command.encode());
    println!("url: {}", url);
    let res = request.get(url);
    let result = request.receive(&mut res.unwrap());
    println!("result: {}", result);
    let mut decode = groonga::ResultParser::new(result);
    println!("status: {:?}", decode.status().unwrap());
    println!("start: {:?}", decode.start_time().unwrap());
    println!("elapsed: {:?}", decode.elapsed_time().unwrap());
    if decode.status().unwrap().clone() == 0 {
        println!("matched columns: {:?}", decode.matched_columns().unwrap());
        let decoded_vec = decode.result().unwrap().pop().unwrap().unwrap_vec().clone();
        println!("index access: {:?}", decoded_vec[2]);
        // Read got response
        let mut result_vec: Vec<Result> = Vec::new();
        println!("-- Display raw decoded json values --");
        // Skip reading result header
        for v in decoded_vec.iter().skip(2) {
            println!("{:?}", v);
            let raw = v.unwrap_vec();
            let elem = Result { id: raw[0].unwrap_i64().clone(),
                                key: raw[1].unwrap_string().clone(),
                                title: raw[2].unwrap_string().clone() };
            result_vec.push(elem.clone());
        }
        println!("-- Mapped to user-defined struct -- ");
        println!("{:?}", result_vec);
    } else {
        println!("Couldn't get success response.")
    }
}
<|endoftext|>


<commit_before>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
use std::sync::Arc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn cell<T:Eq+Hash> (self:&mut Self, ArtId, T) -> Art<T> ;

    fn thunk<Arg:Eq+Hash,T:Eq+Hash>
        (self:&mut Self, id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Hash> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown,
    Root,
    Taken,
    Pair(Arc<Lineage>,Arc<Lineage>),
    ForkL(Arc<Lineage>),
    ForkR(Arc<Lineage>),
    String(String),
    U64(u64),
    Arc(Arc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Arc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Hash(u64),
    Box(Box<T>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural,
    Nominal(Name),
}

pub struct AdaptonState {
    memo_table : HashMap<ArtId, *mut ()>, // memo table
    curr_nmspc : Name, // current_namespace
    curr_artnm : Name, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let root = Arc::new(Lineage::Root);
        let root1 = Name{hash:0, lineage:root.clone()};
        let root2 = Name{hash:0, lineage:root};
        AdaptonState {
            memo_table : HashMap::new (),
            curr_nmspc : root1,
            curr_artnm : root2,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Arc::new(s) }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Arc::new(s) }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(&fst,&snd) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Arc::new(p) }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 1) ) ;
        let h2 = hash::<_>( &(&nm, 2) );
        ( Name{ hash:h1, lineage:Arc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2, lineage:Arc::new(Lineage::ForkR(nm.lineage)) } )
    }
    fn cell<T:Eq+Hash> (self:&mut AdaptonState, id:ArtId, x:T) -> Art<T> {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq+Hash>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq+Hash> (self:&mut AdaptonState, art:Art<T>) -> T {
        panic!("")
    }
}

pub fn main () {

}
<commit_msg>implemented child namespaces<commit_after>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
use std::sync::Arc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn child<T> (self: &mut Self, Name, body:Box<Invoke<(),T>+'static>) -> T ;

    fn cell<T:Eq+Hash> (self:&mut Self, ArtId, T) -> Art<T> ;

    fn thunk<Arg:Eq+Hash,T:Eq+Hash>
        (self:&mut Self, id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Hash> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown,
    Root,
    Pair(Arc<Lineage>,Arc<Lineage>),
    ForkL(Arc<Lineage>),
    ForkR(Arc<Lineage>),
    String(String),
    U64(u64),
    Arc(Arc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Arc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Arc<Lineage>,
    path : Arc<Path>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural,
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Hash(u64),
    Box(Box<T>),
}

pub struct AdaptonState {
    memo_table : HashMap<ArtId, *mut ()>, // memo table
    curr_path : Arc<Path>, // current_namespace
    curr_name : Arc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Arc::new(Path::Empty);
        let root = Arc::new(Name{hash:0, lineage:Arc::new(Lineage::Root), path:empty.clone()});
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Arc::new(s), path:self.curr_path.clone() }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Arc::new(s), path:self.curr_path.clone() }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(&fst,&snd) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Arc::new(p), path:self.curr_path.clone() }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 1) ) ;
        let h2 = hash::<_>( &(&nm, 2) );
        ( Name{ hash:h1,
                lineage:Arc::new(Lineage::ForkL(nm.lineage.clone())),
                path:self.curr_path.clone() } ,
          Name{ hash:h2,
                lineage:Arc::new(Lineage::ForkR(nm.lineage)),
                path:self.curr_path.clone() } )
    }
    fn child<T> (self: &mut Self, nm:Name, body:Box<Invoke<(),T>+'static>) -> T {
        let path_body = Arc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body.invoke(()) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body); x
    }
    fn cell<T:Eq+Hash> (self:&mut AdaptonState, id:ArtId, x:T) -> Art<T> {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq+Hash>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq+Hash> (self:&mut AdaptonState, art:Art<T>) -> T {
        panic!("")
    }
}

pub fn main () {

}
<|endoftext|>


<commit_before>use std::fmt::Show;
use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::rc::Rc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq+Clone+Show> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq+Clone+Show> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq+Clone+Show> (self:&mut Self, MutArt<T>, T) ;

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Clone+Show> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,            // Identifies an Art::Box.
    Structural(u64), // Identifies an Art::Loc.
    Nominal(Name),   // Identifies an Art::Loc.
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),  // No entry in table.
    Loc(Rc<Loc>), // Location in table.
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

#[derive(Show)]
enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

#[derive(Show)]
struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

#[derive(Show)]
struct MutNode<T> {
    loc : Rc<Loc>,
    creators  : Vec<DemPrec>,
    dem_precs : Vec<DemPrec>,
    val : T,
}

#[derive(Show)]
struct ComputeNode<T> {
    loc : Rc<Loc>,
    creators  : Vec<DemPrec>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    val  : Option<T>,
}

#[derive(Show)]
struct DemPrec {
    loc : Rc<Loc>,
}

#[derive(Show)]
struct DemSucc {
    loc : Rc<Loc>,
    dirty : bool
}

pub struct Frame {
    path : Rc<Path>,
    name : Rc<Name>,
}

pub struct AdaptonState {
    table : HashMap<Rc<Loc>, *mut ()>,
    stack : Vec<Frame>,
}

impl Adapton for AdaptonState {

    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        let mut stack = Vec::new();
        stack.push( Frame{path:empty, name:root} ) ;
        AdaptonState {
            table : HashMap::new (),
            stack : stack,
        }
    }

    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }

    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }

    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }

    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }

    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.stack[0].path.clone(), nm)) ;
        let path_pre = replace(&mut self.stack[0].path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.stack[0].path, path_pre) ;
        drop(path_body);
        x
    }

    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }

    fn cell<T:Eq+Clone+Show> (self:&mut AdaptonState, id:ArtId, val:T) -> MutArt<T> {
        let loc = match id {
            ArtId::None => panic!(""),
            ArtId::Structural(hash) => {
                Rc::new(Loc{
                    hash:hash,
                    name:Rc::new(Name{hash:hash,
                                      lineage:Rc::new(Lineage::Structural)}),
                    path:self.stack[0].path.clone()
                })
            }
            ArtId::Nominal(nm) => {
                Rc::new(Loc{
                    hash:nm.hash,
                    name:Rc::new(nm),
                    path:self.stack[0].path.clone() })
            }} ;
        let mut node = Node::Mut(MutNode{
            loc:loc.clone(),
            dem_precs:Vec::new(),
            creators:Vec::new(),
            val:val
        }) ;
        let ptr = unsafe { std::mem::transmute::<*mut Node<T>,*mut ()>(&mut node) } ;
        self.table.insert(loc.clone(), ptr) ;
        MutArt::MutArt(Art::Loc(loc))
    }

    fn set<T:Eq+Clone+Show> (self:&mut Self, cell:MutArt<T>, val:T) {
        match cell {
            MutArt::MutArt(Art::Box(b)) => {
                panic!("cannot set pure value");
            }
            MutArt::MutArt(Art::Loc(loc)) => {
                let node = self.table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut MutNode<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            match *node {
                                Node::Mut(ref mut nd) => nd,
                                ref nd => panic!("impossible: {}", nd)
                            }} ;
                        if (node.val == val) {
                            // Nothing.
                        }
                        else {
                            node.val = val;
                            // TODO: Dirty traversal. Notify/mark demand precs.
                        }
                    }
                }
            }
        }
    }

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }

    fn force<T:Eq+Clone+Show> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(loc) => {
                let node = self.table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut Node<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            &mut ( *node ) } ;
                        match *node {
                            Node::Pure(ref mut nd) => {
                                nd.val.clone()
                            }
                            Node::Mut(ref mut nd) => {
                                // TODO: Record dependency edge
                                nd.val.clone()
                            }
                            Node::Compute(ref mut nd) => {
                                self.stack.push ( Frame{name:loc.name.clone(),
                                                        path:loc.path.clone() } );
                                panic!("TODO");
                                let frame = self.stack.pop();
                                drop(frame);
                            }
                        }
                    }
                }
            }
        }
    }

}

pub fn main () {

}
<commit_msg>some back-edge maintainence is fleshed out<commit_after>use std::fmt::Show;
use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::rc::Rc;
use std::fmt;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq+Clone+Show> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq+Clone+Show> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq+Clone+Show> (self:&mut Self, MutArt<T>, T) ;

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<(&mut Self, Arg), T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Clone+Show> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,            // Identifies an Art::Box. No dependency tracking.
    Structural(u64), // Identifies an Art::Loc.
    Nominal(Name),   // Identifies an Art::Loc.
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),  // No entry in table. No dependency tracking.
    Loc(Rc<Loc>), // Location in table.
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

#[derive(Show)]
enum Node<A:Adapton,Arg,Res> {
    Pure(PureNode<Res>),
    Mut(MutNode<Res>),
    Compute(ComputeNode<A,Arg,Res>),
}

#[derive(Show)]
struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

#[derive(Show)]
struct MutNode<T> {
    loc : Rc<Loc>,
    creators  : Vec<DemPrec>,
    dem_precs : Vec<DemPrec>,
    val : T,
}

//#[derive(Show)]
struct ComputeNode<A:Adapton,Arg,Res> {
    loc : Rc<Loc>,
    creators  : Vec<DemPrec>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    arg : Arg,
    res : Option<Res>,
    body : Box<Invoke<(&'static mut A, Arg),Res> + 'static>,
}

impl<A:Adapton,Arg,Res> fmt::Show for ComputeNode<A,Arg,Res> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(ComputeNode)")
    }
}

#[derive(Show)]
struct DemPrec {
    loc : Rc<Loc>,
}

#[derive(Show)]
struct DemSucc {
    loc : Rc<Loc>,
    dirty : bool
}

pub struct Frame {
    path : Rc<Path>,
    name : Rc<Name>,
    succs : Vec<DemSucc>,
}

pub struct AdaptonState {
    table : HashMap<Rc<Loc>, *mut ()>,
    stack : Vec<Frame>,
}

impl fmt::Show for AdaptonState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(AdaptonState)")
    }
}

fn node<'x> (st: &'x mut AdaptonState, loc:&Rc<Loc>) -> &'x mut Node<AdaptonState,(),()> {
    let node = st.table.get(loc) ;
    match node {
        None => panic!("dangling pointer: {}", loc),
        Some(ptr) => {
            let ptr = unsafe {
                std::mem::transmute::<
                    *mut (), &mut Node<AdaptonState,(),()> // TODO: () and () is a lie.
                    >(*ptr) } ;
            ptr
        }
    }
}

fn dem_precs<'x> (st: &'x mut AdaptonState, loc: &Rc<Loc>) -> &'x mut Vec<DemPrec> {
    match *(node(st,loc)) {
        Node::Pure(_) => {
            panic!("Node::Pure: no precs")
        },
        Node::Compute(ref mut nd) => {
            &mut nd.dem_precs
        },
        Node::Mut(ref mut nd) => {
            &mut nd.dem_precs
        }
    }
}

fn revoke_demand (st:&mut AdaptonState, src:&Rc<Loc>, succs:&Vec<DemSucc>) {
    for succ in succs.iter() {
        let precs = dem_precs(st, &succ.loc);
        precs.retain(|ref prec| &prec.loc != src);
    }
}

fn invoke_demand (st:&mut AdaptonState, src:Rc<Loc>, succs:& Vec<DemSucc>) {
    for succ in succs.iter() {
        let precs = dem_precs(st, &succ.loc);
        precs.push(DemPrec{loc:src.clone()})
    }
}

impl Adapton for AdaptonState {

    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        let mut stack = Vec::new();
        stack.push( Frame{path:empty, name:root, succs:Vec::new()} ) ;
        AdaptonState {
            table : HashMap::new (),
            stack : stack,
        }
    }

    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }

    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }

    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }

    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }

    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.stack[0].path.clone(), nm)) ;
        let path_pre = replace(&mut self.stack[0].path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.stack[0].path, path_pre) ;
        drop(path_body);
        x
    }

    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }

    fn cell<T:Eq+Clone+Show> (self:&mut AdaptonState, id:ArtId, val:T) -> MutArt<T> {
        let loc = match id {
            ArtId::None => panic!("a cell requires a unique identity"),
            ArtId::Structural(hash) => {
                Rc::new(Loc{
                    hash:hash,
                    name:Rc::new(Name{hash:hash,
                                      lineage:Rc::new(Lineage::Structural)}),
                    path:self.stack[0].path.clone()
                })
            }
            ArtId::Nominal(nm) => {
                Rc::new(Loc{
                    hash:nm.hash,
                    name:Rc::new(nm),
                    path:self.stack[0].path.clone() })
            }} ;
        let mut node = Node::Mut(MutNode{
            loc:loc.clone(),
            dem_precs:Vec::new(),
            creators:Vec::new(),
            val:val
        }) ;
        let ptr = unsafe { std::mem::transmute::<
                           *mut Node<AdaptonState,(),T>,
                           *mut ()
                           >(&mut node) } ;
        // TODO: Check to see if the cell exists;
        // check if its content has changed.
        // dirty its precs if so.
        self.table.insert(loc.clone(), ptr) ;
        MutArt::MutArt(Art::Loc(loc))
    }

    fn set<T:Eq+Clone+Show> (self:&mut Self, cell:MutArt<T>, val:T) {
        match cell {
            MutArt::MutArt(Art::Box(b)) => {
                panic!("cannot set pure value");
            }
            MutArt::MutArt(Art::Loc(loc)) => {
                let node = self.table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut MutNode<T> = unsafe {
                            let node = std::mem::transmute::<
                                *mut (), *mut Node<AdaptonState,(),T> // TODO: () is a lie.
                                >(*ptr) ;
                            match *node {
                                Node::Mut(ref mut nd) => nd,
                                ref nd => panic!("impossible: {}", nd)
                            }} ;
                        if (node.val == val) {
                            // Nothing.
                        }
                        else {
                            node.val = val;
                            // TODO: Dirty traversal. Notify/mark demand precs.
                        }
                    }
                }
            }
        }
    }

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<(&mut Self, Arg),T>+'static>, arg:Arg) -> Art<T>
    {
        match id {
            ArtId::None => {
                Art::Box(box fn_body.invoke((self,arg)))
            },
            ArtId::Structural(hash) => {
                panic!("")
            },
            ArtId::Nominal(nm) => {
                panic!("")
            }
        }
    }

    fn force<T:Eq+Clone+Show> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(loc) => {
                let node = self.table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut Node<AdaptonState,(),T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<AdaptonState,(),T>>(*ptr) ; // TODO: () is a lie.
                            &mut ( *node ) } ;
                        match *node {
                            Node::Pure(ref mut nd) => {
                                nd.val.clone()
                            },
                            Node::Mut(ref mut nd) => {
                                if self.stack.is_empty() { } else {
                                    self.stack[0].succs.push(DemSucc{loc:loc.clone(),dirty:false});
                                } ;
                                nd.val.clone()
                            },
                            Node::Compute(ref mut nd) => {
                                self.stack.push ( Frame{name:loc.name.clone(),
                                                        path:loc.path.clone(),
                                                        succs:Vec::new(), } );
                                let val = panic!("TODO: run compute node body") ;
                                let mut frame = match
                                    self.stack.pop() { None => panic!(""), Some(frame) => frame } ;
                                revoke_demand( self, &nd.loc, &nd.dem_succs );
                                invoke_demand( self, nd.loc.clone(), &frame.succs );
                                nd.dem_succs = frame.succs;
                                if self.stack.is_empty() { } else {
                                    self.stack[0].succs.push(DemSucc{loc:loc.clone(),dirty:false});
                                };
                                val
                            }
                        }
                    }
                }
            }
        }
    }

}

pub fn main () {

}
<|endoftext|>


<commit_before>use std::fmt;
use world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS};
use super::{AxialType, DefaultFloat, Point2f};
use std::ops::{Add, Div, Index, IndexMut, Mul, Sub};
use math::cgmath::{Array, Zero};

/// A 2-dimensional point in axial coordinates. See [here][hex-blog] for more
/// information.
///
/// [hex-blog]: http://www.redblobgames.com/grids/hexagons/#coordinates
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, packed)]
pub struct AxialPoint {
    pub q: AxialType,
    pub r: AxialType,
}

// TODO: implement cgmath::Array
// TODO: implement cgmath::MatricSpace
// TODO: implement cgmath::EuclideanSpace
// TODO: implement ops::{ ... }
// For all of the above, see
// http://bjz.github.io/cgmath/cgmath/struct.Point2.html
//

impl AxialPoint {
    pub fn new(q: AxialType, r: AxialType) -> Self {
        AxialPoint { q: q, r: r }
    }

    /// Returns the position of the hexagons center in the standard coordinate
    /// system using `world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS}`.
    pub fn to_real(&self) -> Point2f {
        Point2f {
            x: ((2 * self.q + self.r) as DefaultFloat) * HEX_INNER_RADIUS,
            y: (self.r as DefaultFloat) * (3.0 / 2.0) * HEX_OUTER_RADIUS,
        }
    }

    /// Returns the `s` component of corresponding cube coordinates. In cube
    /// coordinates 'q + r + s = 0', so saving `s` is redundant and can be
    /// calculated on the fly when needed.
    pub fn s(&self) -> AxialType {
        -self.q - self.r
    }
}

impl fmt::Debug for AxialPoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("")
            .field(&self.q)
            .field(&self.r)
            .finish()
    }
}

/// ********************Basic Arithmetics************

impl Add<AxialPoint> for AxialPoint {
    type Output = AxialPoint;

    /// adds two Points together similar to vectors
    /// Returns an AxialPoint
    fn add(self, _rhs: AxialPoint) -> AxialPoint {
        AxialPoint {
            q: self.q + _rhs.q,
            r: self.r + _rhs.r,
        }
    }
}

impl Sub<AxialPoint> for AxialPoint {
    type Output = AxialPoint;

    /// substracts two Points similar to vectors
    /// Returns an AxialPoint
    fn sub(self, _rhs: AxialPoint) -> AxialPoint {
        AxialPoint {
            q: self.q - _rhs.q,
            r: self.r - _rhs.r,
        }
    }
}

impl Mul<AxialType> for AxialPoint {
    type Output = AxialPoint;

    /// Multiplies a point and a scalar
    /// Returns an AxialPoint
    fn mul(self, _rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q * _rhs,
            r: self.r * _rhs,
        }
    }
}

impl Div<AxialType> for AxialPoint {
    type Output = AxialPoint;

    /// Divides a point and a scalar
    /// Returns an AxialPoint
    fn div(self, _rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q / _rhs,
            r: self.r / _rhs,
        }
    }
}
/// ********************Zero-Implementation************
impl Zero for AxialPoint {
    fn zero() -> AxialPoint {
        AxialPoint { q: 0, r: 0 }
    }
    fn is_zero(&self) -> bool {
        self.q == 0 && self.r == 0
    }
}

/// ********************Index************

impl Index<usize> for AxialPoint {
    type Output = AxialType;
    fn index<'a>(&'a self, index: usize) -> &'a AxialType {
        match index {
            0 => &self.q,
            1 => &self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}

impl IndexMut<usize> for AxialPoint {
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut AxialType {
        match index {
            0 => &mut self.q,
            1 => &mut self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}

/// ********************Array************

impl Array for AxialPoint {
    type Element = AxialType;

    fn from_value(x: AxialType) -> AxialPoint {
        AxialPoint { q: x, r: x }
    }

    fn sum(self) -> AxialType {
        self.q + self.r
    }

    fn product(self) -> AxialType {
        self.q * self.r
    }

    fn min(self) -> AxialType {
        if self.q < self.r { self.q } else { self.r }
    }
    fn max(self) -> AxialType {
        if self.q < self.r { self.r } else { self.q }
    }
}
<commit_msg>implement cgmath::MetricSpace for axial_point.rs<commit_after>use std::fmt;
use world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS};
use super::{AxialType, DefaultFloat, Point2f};
use std::ops::{Add, Div, Index, IndexMut, Mul, Rem, Sub};
use math::cgmath::{Array, MetricSpace, VectorSpace, Zero};

/// A 2-dimensional point in axial coordinates. See [here][hex-blog] for more
/// information.
///
/// [hex-blog]: http://www.redblobgames.com/grids/hexagons/#coordinates
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, packed)]
pub struct AxialPoint {
    pub q: AxialType,
    pub r: AxialType,
}

// TODO: implement cgmath::Array
// TODO: implement cgmath::MatricSpace
// TODO: implement cgmath::EuclideanSpace
// TODO: implement ops::{ ... }
// For all of the above, see
// http://bjz.github.io/cgmath/cgmath/struct.Point2.html
//

impl AxialPoint {
    pub fn new(q: AxialType, r: AxialType) -> Self {
        AxialPoint { q: q, r: r }
    }

    /// Returns the position of the hexagons center in the standard coordinate
    /// system using `world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS}`.
    pub fn to_real(&self) -> Point2f {
        Point2f {
            x: ((2 * self.q + self.r) as DefaultFloat) * HEX_INNER_RADIUS,
            y: (self.r as DefaultFloat) * (3.0 / 2.0) * HEX_OUTER_RADIUS,
        }
    }

    /// Returns the `s` component of corresponding cube coordinates. In cube
    /// coordinates 'q + r + s = 0', so saving `s` is redundant and can be
    /// calculated on the fly when needed.
    pub fn s(&self) -> AxialType {
        -self.q - self.r
    }
}

impl fmt::Debug for AxialPoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("")
            .field(&self.q)
            .field(&self.r)
            .finish()
    }
}

/// ********************Basic Arithmetics************

impl Add<AxialPoint> for AxialPoint {
    type Output = AxialPoint;

    /// adds two Points together similar to vectors
    /// Returns an AxialPoint
    fn add(self, _rhs: AxialPoint) -> AxialPoint {
        AxialPoint {
            q: self.q + _rhs.q,
            r: self.r + _rhs.r,
        }
    }
}

impl Sub<AxialPoint> for AxialPoint {
    type Output = AxialPoint;

    /// substracts two Points similar to vectors
    /// Returns an AxialPoint
    fn sub(self, _rhs: AxialPoint) -> AxialPoint {
        AxialPoint {
            q: self.q - _rhs.q,
            r: self.r - _rhs.r,
        }
    }
}

impl Mul<AxialType> for AxialPoint {
    type Output = AxialPoint;

    /// Multiplies a point and a scalar
    /// Returns an AxialPoint
    fn mul(self, _rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q * _rhs,
            r: self.r * _rhs,
        }
    }
}

impl Div<AxialType> for AxialPoint {
    type Output = AxialPoint;

    /// Divides a point and a scalar
    /// Returns an AxialPoint
    fn div(self, _rhs: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q / _rhs,
            r: self.r / _rhs,
        }
    }
}

impl Rem<AxialType> for AxialPoint {
    type Output = AxialPoint;

    fn rem(self, d: AxialType) -> AxialPoint {
        AxialPoint {
            q: self.q % d,
            r: self.r % d,
        }
    }
}
/// ********************Zero-Implementation************
impl Zero for AxialPoint {
    fn zero() -> AxialPoint {
        AxialPoint { q: 0, r: 0 }
    }
    fn is_zero(&self) -> bool {
        self.q == 0 && self.r == 0
    }
}

/// ********************Index************

impl Index<usize> for AxialPoint {
    type Output = AxialType;
    fn index<'a>(&'a self, index: usize) -> &'a AxialType {
        match index {
            0 => &self.q,
            1 => &self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}

impl IndexMut<usize> for AxialPoint {
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut AxialType {
        match index {
            0 => &mut self.q,
            1 => &mut self.r,
            _ => panic!("Index out of bounds!"),
        }
    }
}

/// ********************Array************

impl Array for AxialPoint {
    type Element = AxialType;

    fn from_value(x: AxialType) -> AxialPoint {
        AxialPoint { q: x, r: x }
    }

    fn sum(self) -> AxialType {
        self.q + self.r
    }

    fn product(self) -> AxialType {
        self.q * self.r
    }

    fn min(self) -> AxialType {
        if self.q < self.r { self.q } else { self.r }
    }
    fn max(self) -> AxialType {
        if self.q < self.r { self.r } else { self.q }
    }
}

/// ******************* Metric-Space************************

impl MetricSpace for AxialPoint {
    type Metric = f32;

    fn distance2(self, other: AxialPoint) -> Self::Metric {
        (((self.q - other.q) * (self.q - other.q)) +
         ((self.r - other.r) * (self.r - other.r))) as f32
    }
    fn distance(self, other: AxialPoint) -> Self::Metric {
        self.distance2(other).sqrt()
    }
}

/// ********************Vector-Space****************************

impl VectorSpace for AxialPoint {
    type Scalar = i32;
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn f(x: int) -> int { x }
fn g(x: int) -> int { 2 * x }

static F: extern fn(int) -> int = f;
static mut G: extern fn(int) -> int = f;

fn main() {
    assert_eq!(F(42), 42);
    unsafe {
        assert_eq!(G(42), 42);
        G = g;
        assert_eq!(G(42), 84);
    }
}
<commit_msg>Changed `fn main` to `pub fn main`<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn f(x: int) -> int { x }
fn g(x: int) -> int { 2 * x }

static F: extern fn(int) -> int = f;
static mut G: extern fn(int) -> int = f;

pub fn main() {
    assert_eq!(F(42), 42);
    unsafe {
        assert_eq!(G(42), 42);
        G = g;
        assert_eq!(G(42), 84);
    }
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate twelve_bit;

use twelve_bit::u12::*;

// MARK: - Tests - Addition

#[test]
fn test_add_operator() {
  assert_eq!(u12![0] + u12![0], u12![0]);
  assert_eq!(u12![0] + u12![1], u12![1]);
  assert_eq!(u12![1] + u12![0], u12![1]);
  assert_eq!(u12![0] + U12::max_value(), U12::max_value());
  assert_eq!(U12::max_value() + u12![0], U12::max_value());
}

#[test]
#[should_panic]
fn test_add_operator_overflow() {
  let _ = U12::max_value() + u12![1];
}

#[test]
fn test_checked_add() {
  assert_eq!(u12![0].checked_add(u12![0]), Some(u12![0]));
  assert_eq!(u12![0].checked_add(u12![1]), Some(u12![1]));
  assert_eq!(u12![1].checked_add(u12![0]), Some(u12![1]));
  assert_eq!(u12![0].checked_add(U12::max_value()), Some(U12::max_value()));
  assert_eq!(U12::max_value().checked_add(u12![0]), Some(U12::max_value()));
  assert_eq!(U12::max_value().checked_add(u12![1]), None);
  assert_eq!(U12::max_value().checked_add(u12![2]), None);
  assert_eq!(U12::max_value().checked_add(U12::max_value()), None);
}

#[test]
fn test_saturating_add() {
  assert_eq!(u12![0].saturating_add(u12![0]), u12![0]);
  assert_eq!(u12![0].saturating_add(u12![1]), u12![1]);
  assert_eq!(u12![1].saturating_add(u12![0]), u12![1]);
  assert_eq!(u12![0].saturating_add(U12::max_value()), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(u12![0]), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(u12![1]), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(u12![2]), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(U12::max_value()), U12::max_value());
}

#[test]
fn test_wrapping_add() {
  assert_eq!(u12![0].wrapping_add(u12![0]), u12![0]);
  assert_eq!(u12![0].wrapping_add(u12![1]), u12![1]);
  assert_eq!(u12![1].wrapping_add(u12![0]), u12![1]);
  assert_eq!(u12![0].wrapping_add(U12::max_value()), U12::max_value());
  assert_eq!(U12::max_value().wrapping_add(u12![0]), U12::max_value());
  assert_eq!(U12::max_value().wrapping_add(u12![1]), u12![0]);
  assert_eq!(U12::max_value().wrapping_add(u12![2]), u12![1]);
  assert_eq!(U12::max_value().wrapping_add(U12::max_value()), u12![0xFFE]);
}

#[test]
fn test_overflowing_add() {
  assert_eq!(u12![0].overflowing_add(u12![0]), (u12![0], false));
  assert_eq!(u12![0].overflowing_add(u12![1]), (u12![1], false));
  assert_eq!(u12![1].overflowing_add(u12![0]), (u12![1], false));
  assert_eq!(u12![0].overflowing_add(U12::max_value()), (U12::max_value(), false));
  assert_eq!(U12::max_value().overflowing_add(u12![0]), (U12::max_value(), false));
  assert_eq!(U12::max_value().overflowing_add(u12![1]), (u12![0], true));
  assert_eq!(U12::max_value().overflowing_add(u12![2]), (u12![1], true));
  assert_eq!(U12::max_value().overflowing_add(U12::max_value()), (u12![0xFFE], true));
}

// MARK: - Tests - Subtraction

#[test]
fn test_sub_operator() {
  let zero = U12::min_value();
  let  one = U12::from(1u8);
  let  max = U12::max_value();

  assert_eq!(zero - zero, zero);
  assert_eq!(one - zero, one);
  assert_eq!(max - zero, max);
  assert_eq!(max - one, (0xFFE as u16).unchecked_into());
}

#[test]
#[should_panic]
fn test_sub_operator_underflow() {
  let one = U12::from(1u8);
  let min = U12::min_value();
  let _ = min - one;
}

#[test]
fn test_checked_sub() {
  let zero = U12::min_value();
  let  one = U12::from(1u8);
  let  two = U12::from(2u8);
  let  max = U12::max_value();

  assert_eq!(zero.checked_sub(zero), Some(zero));
  assert_eq!(zero.checked_sub(one), None);
  assert_eq!(one.checked_sub(zero), Some(one));
  assert_eq!(zero.checked_sub(max), None);
  assert_eq!(max.checked_sub(zero), Some(max));
  assert_eq!(max.checked_sub(one), Some((0xFFE as u16).unchecked_into()));
  assert_eq!(max.checked_sub(two), Some((0xFFD as u16).unchecked_into()));
  assert_eq!(max.checked_sub(max), Some(zero));
}

#[test]
fn test_saturating_sub() {
  let zero = U12::min_value();
  let  one = U12::from(1u8);
  let  two = U12::from(2u8);
  let  max = U12::max_value();

  assert_eq!(zero.saturating_sub(zero), zero);
  assert_eq!(zero.saturating_sub(one), zero);
  assert_eq!(one.saturating_sub(zero), one);
  assert_eq!(zero.saturating_sub(max), zero);
  assert_eq!(max.saturating_sub(zero), max);
  assert_eq!(max.saturating_sub(one), (0xFFE as u16).unchecked_into());
  assert_eq!(max.saturating_sub(two), (0xFFD as u16).unchecked_into());
  assert_eq!(max.saturating_sub(max), zero);
}

#[test]
fn test_wrapping_sub() {
  let zero = U12::min_value();
  let  one = U12::from(1u8);
  let  two = U12::from(2u8);
  let  max = U12::max_value();

  assert_eq!(zero.wrapping_sub(zero), zero);
  assert_eq!(zero.wrapping_sub(one), max);
  assert_eq!(one.saturating_sub(zero), one);
  assert_eq!(zero.wrapping_sub(max), one);
  assert_eq!(max.wrapping_sub(zero), max);
  assert_eq!(max.wrapping_sub(one), (0xFFE as u16).unchecked_into());
  assert_eq!(max.wrapping_sub(two), (0xFFD as u16).unchecked_into());
  assert_eq!(max.wrapping_sub(max), zero);
}

// MARK: - Tests - Multiplication

#[test]
fn test_mul_operator() {
  assert_eq!(U12::from(2u8) * U12::from(0u8), U12::min_value());
  assert_eq!(U12::max_value() * U12::min_value(), U12::min_value());
  assert_eq!(U12::from(2u8) * U12::from(255u8), (510 as u16).unchecked_into());
  assert_eq!(U12::from(255u8) * U12::from(2u8), (510 as u16).unchecked_into());
}

#[test]
#[should_panic]
fn test_mul_operator_overflow() {
  let _ = U12::from(2u8) * 2048u16.unchecked_into();
}

#[test]
fn test_checked_mul() {
  assert_eq!(U12::from(2u8).checked_mul(0u8.into()), Some(U12::min_value()));
  assert_eq!(U12::from(2u8).checked_mul(255u8.into()), Some((510 as u16).unchecked_into()));
  assert_eq!(U12::from(255u8).checked_mul(2u8.into()), Some((510 as u16).unchecked_into()));
  assert_eq!(U12::from(2u8).checked_mul((2048u16).unchecked_into()), None);
  assert_eq!(U12::from(2u8).checked_mul((4095u16).unchecked_into()), None);
}

#[test]
fn test_saturating_mul() {
  assert_eq!(U12::from(2u8).saturating_mul(0u8.into()), U12::min_value());
  assert_eq!(U12::from(2u8).saturating_mul(255u8.into()), (510 as u16).unchecked_into());
  assert_eq!(U12::from(255u8).saturating_mul(2u8.into()), (510 as u16).unchecked_into());
  assert_eq!(U12::from(2u8).saturating_mul((2048u16).unchecked_into()), U12::max_value());
  assert_eq!(U12::from(2u8).saturating_mul((4095u16).unchecked_into()), U12::max_value());
}

#[test]
fn test_wrapping_mul() {
  assert_eq!(U12::from(2u8).wrapping_mul(0u8.into()), U12::min_value());
  assert_eq!(U12::from(2u8).wrapping_mul(255u8.into()), (510 as u16).unchecked_into());
  assert_eq!(U12::from(255u8).wrapping_mul(2u8.into()), (510 as u16).unchecked_into());
  assert_eq!(U12::from(2u8).wrapping_mul((2048u16).unchecked_into()), U12::min_value());
  assert_eq!(U12::from(2u8).wrapping_mul((4095u16).unchecked_into()), (0xFFE as u16).unchecked_into());
}

// MARK: - Tests - Division

#[test]
fn test_div_operator() {
  assert_eq!(U12::max_value() / U12::max_value(), U12::from(1u8));
  assert_eq!(U12::from(2u8) / U12::from(255u8), U12::from(0u8));
  assert_eq!(U12::from(255u8) / U12::from(2u8), U12::from(127u8));
}

#[test]
#[should_panic]
fn test_div_operator_divide_by_zero() {
  let _ = U12::from(2u8) / U12::from(0u8);
}

#[test]
fn test_checked_div() {
  assert_eq!(U12::max_value().checked_div(U12::max_value()), Some(U12::from(1u8)));
  assert_eq!(U12::from(2u8).checked_div(U12::from(255u8)), Some(U12::from(0u8)));
  assert_eq!(U12::from(255u8).checked_div(U12::from(2u8)), Some(U12::from(127u8)));
  assert_eq!(U12::from(255u8).checked_div(U12::from(1u8)), Some(U12::from(255u8)));
  assert_eq!(U12::from(255u8).checked_div(U12::from(0u8)), None);
}

#[test]
fn test_wrapping_div() {
  assert_eq!(U12::max_value().wrapping_div(U12::max_value()), U12::from(1u8));
  assert_eq!(U12::from(2u8).wrapping_div(U12::from(255u8)), U12::from(0u8));
  assert_eq!(U12::from(255u8).wrapping_div(U12::from(2u8)), U12::from(127u8));
  assert_eq!(U12::from(255u8).wrapping_div(U12::from(1u8)), U12::from(255u8));
}

#[test]
#[should_panic]
fn test_wrapping_div_overflow() {
  let _ = U12::from(255u8).wrapping_div(U12::from(0u8));
}

// MARK: - Tests - Negation

#[test]
fn test_checked_neg() {
  assert_eq!(U12::from(0u8).checked_neg(), Some(0u8.into()));
  assert_eq!(U12::from(1u8).checked_neg(), None);
  assert_eq!(U12::from(2u8).checked_neg(), None);
  assert_eq!(U12::from(255u8).checked_neg(), None);
}

#[test]
fn test_wrapping_neg() {
  assert_eq!(U12::from(0u8).wrapping_neg(), 0u8.into());
  assert_eq!(U12::from(1u8).wrapping_neg(), 0xFFFu16.unchecked_into());
  assert_eq!(U12::from(2u8).wrapping_neg(), 0xFFEu16.unchecked_into());
  assert_eq!(U12::from(255u8).wrapping_neg(), 0xF01u16.unchecked_into());
}

#[test]
fn test_overflowing_neg() {
  assert_eq!(U12::from(0u8).overflowing_neg(), (0u8.into(), false));
  assert_eq!(U12::from(1u8).overflowing_neg(), (0xFFFu16.unchecked_into(), true));
  assert_eq!(U12::from(2u8).overflowing_neg(), (0xFFEu16.unchecked_into(), true));
  assert_eq!(U12::from(255u8).overflowing_neg(), (0xF01u16.unchecked_into(), true));
}
<commit_msg>Rewrite Arithmetic tests in terms of u12![] macro.<commit_after>
#[macro_use]
extern crate twelve_bit;

use twelve_bit::u12::*;

// MARK: - Tests - Addition

#[test]
fn test_add_operator() {
  assert_eq!(u12![0] + u12![0], u12![0]);
  assert_eq!(u12![0] + u12![1], u12![1]);
  assert_eq!(u12![1] + u12![0], u12![1]);
  assert_eq!(u12![0] + U12::max_value(), U12::max_value());
  assert_eq!(U12::max_value() + u12![0], U12::max_value());
}

#[test]
#[should_panic]
fn test_add_operator_overflow() {
  let _ = U12::max_value() + u12![1];
}

#[test]
fn test_checked_add() {
  assert_eq!(u12![0].checked_add(u12![0]), Some(u12![0]));
  assert_eq!(u12![0].checked_add(u12![1]), Some(u12![1]));
  assert_eq!(u12![1].checked_add(u12![0]), Some(u12![1]));
  assert_eq!(u12![0].checked_add(U12::max_value()), Some(U12::max_value()));
  assert_eq!(U12::max_value().checked_add(u12![0]), Some(U12::max_value()));
  assert_eq!(U12::max_value().checked_add(u12![1]), None);
  assert_eq!(U12::max_value().checked_add(u12![2]), None);
  assert_eq!(U12::max_value().checked_add(U12::max_value()), None);
}

#[test]
fn test_saturating_add() {
  assert_eq!(u12![0].saturating_add(u12![0]), u12![0]);
  assert_eq!(u12![0].saturating_add(u12![1]), u12![1]);
  assert_eq!(u12![1].saturating_add(u12![0]), u12![1]);
  assert_eq!(u12![0].saturating_add(U12::max_value()), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(u12![0]), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(u12![1]), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(u12![2]), U12::max_value());
  assert_eq!(U12::max_value().saturating_add(U12::max_value()), U12::max_value());
}

#[test]
fn test_wrapping_add() {
  assert_eq!(u12![0].wrapping_add(u12![0]), u12![0]);
  assert_eq!(u12![0].wrapping_add(u12![1]), u12![1]);
  assert_eq!(u12![1].wrapping_add(u12![0]), u12![1]);
  assert_eq!(u12![0].wrapping_add(U12::max_value()), U12::max_value());
  assert_eq!(U12::max_value().wrapping_add(u12![0]), U12::max_value());
  assert_eq!(U12::max_value().wrapping_add(u12![1]), u12![0]);
  assert_eq!(U12::max_value().wrapping_add(u12![2]), u12![1]);
  assert_eq!(U12::max_value().wrapping_add(U12::max_value()), u12![0xFFE]);
}

#[test]
fn test_overflowing_add() {
  assert_eq!(u12![0].overflowing_add(u12![0]), (u12![0], false));
  assert_eq!(u12![0].overflowing_add(u12![1]), (u12![1], false));
  assert_eq!(u12![1].overflowing_add(u12![0]), (u12![1], false));
  assert_eq!(u12![0].overflowing_add(U12::max_value()), (U12::max_value(), false));
  assert_eq!(U12::max_value().overflowing_add(u12![0]), (U12::max_value(), false));
  assert_eq!(U12::max_value().overflowing_add(u12![1]), (u12![0], true));
  assert_eq!(U12::max_value().overflowing_add(u12![2]), (u12![1], true));
  assert_eq!(U12::max_value().overflowing_add(U12::max_value()), (u12![0xFFE], true));
}

// MARK: - Tests - Subtraction

#[test]
fn test_sub_operator() {
  assert_eq!(u12![0] - u12![0], u12![0]);
  assert_eq!(u12![1] - u12![0], u12![1]);
  assert_eq!(U12::max_value() - u12![0], U12::max_value());
  assert_eq!(U12::max_value() - u12![1], u12![0xFFE]);
}

#[test]
#[should_panic]
fn test_sub_operator_underflow() {
  let _ = U12::min_value() - u12![1];
}

#[test]
fn test_checked_sub() {
  assert_eq!(u12![0].checked_sub(u12![0]), Some(u12![0]));
  assert_eq!(u12![0].checked_sub(u12![1]), None);
  assert_eq!(u12![1].checked_sub(u12![0]), Some(u12![1]));
  assert_eq!(u12![0].checked_sub(U12::max_value()), None);
  assert_eq!(U12::max_value().checked_sub(u12![0]), Some(U12::max_value()));
  assert_eq!(U12::max_value().checked_sub(u12![1]), Some(u12![0xFFE]));
  assert_eq!(U12::max_value().checked_sub(u12![2]), Some(u12![0xFFD]));
  assert_eq!(U12::max_value().checked_sub(U12::max_value()), Some(u12![0]));
}

#[test]
fn test_saturating_sub() {
  assert_eq!(u12![0].saturating_sub(u12![0]), u12![0]);
  assert_eq!(u12![0].saturating_sub(u12![1]), u12![0]);
  assert_eq!(u12![1].saturating_sub(u12![0]), u12![1]);
  assert_eq!(u12![0].saturating_sub(U12::max_value()), u12![0]);
  assert_eq!(U12::max_value().saturating_sub(u12![0]), U12::max_value());
  assert_eq!(U12::max_value().saturating_sub(u12![1]), u12![0xFFE]);
  assert_eq!(U12::max_value().saturating_sub(u12![2]), u12![0xFFD]);
  assert_eq!(U12::max_value().saturating_sub(U12::max_value()), u12![0]);
}

#[test]
fn test_wrapping_sub() {
  assert_eq!(u12![0].wrapping_sub(u12![0]), u12![0]);
  assert_eq!(u12![0].wrapping_sub(u12![1]), U12::max_value());
  assert_eq!(u12![1].saturating_sub(u12![0]), u12![1]);
  assert_eq!(u12![0].wrapping_sub(U12::max_value()), u12![1]);
  assert_eq!(U12::max_value().wrapping_sub(u12![0]), U12::max_value());
  assert_eq!(U12::max_value().wrapping_sub(u12![1]), u12![0xFFE]);
  assert_eq!(U12::max_value().wrapping_sub(u12![2]), u12![0xFFD]);
  assert_eq!(U12::max_value().wrapping_sub(U12::max_value()), u12![0]);
}

// MARK: - Tests - Multiplication

#[test]
fn test_mul_operator() {
  assert_eq!(u12![2] * u12![0], U12::min_value());
  assert_eq!(U12::max_value() * U12::min_value(), U12::min_value());
  assert_eq!(u12![2] * u12![255], u12![510]);
  assert_eq!(u12![255] * u12![2], u12![510]);
}

#[test]
#[should_panic]
fn test_mul_operator_overflow() {
  let _ = u12![2] * u12![2048];
}

#[test]
fn test_checked_mul() {
  assert_eq!(u12![2].checked_mul(u12![0]), Some(U12::min_value()));
  assert_eq!(u12![2].checked_mul(u12![255]), Some(u12![510]));
  assert_eq!(u12![255].checked_mul(u12![2]), Some(u12![510]));
  assert_eq!(u12![2].checked_mul(u12![2048]), None);
  assert_eq!(u12![2].checked_mul(u12![4095]), None);
}

#[test]
fn test_saturating_mul() {
  assert_eq!(u12![2].saturating_mul(u12![0]), U12::min_value());
  assert_eq!(u12![2].saturating_mul(u12![255]), u12![510]);
  assert_eq!(u12![255].saturating_mul(u12![2]), u12![510]);
  assert_eq!(u12![2].saturating_mul(u12![2048]), U12::max_value());
  assert_eq!(u12![2].saturating_mul(u12![4095]), U12::max_value());
}

#[test]
fn test_wrapping_mul() {
  assert_eq!(u12![2].wrapping_mul(u12![0]), U12::min_value());
  assert_eq!(u12![2].wrapping_mul(u12![255]), u12![510]);
  assert_eq!(u12![255].wrapping_mul(u12![2]), u12![510]);
  assert_eq!(u12![2].wrapping_mul(u12![2048]), U12::min_value());
  assert_eq!(u12![2].wrapping_mul(u12![4095]), u12![0xFFE]);
}

// MARK: - Tests - Division

#[test]
fn test_div_operator() {
  assert_eq!(U12::max_value() / U12::max_value(), u12![1]);
  assert_eq!(u12![2] / u12![255], u12![0]);
  assert_eq!(u12![255] / u12![2], u12![127]);
}

#[test]
#[should_panic]
fn test_div_operator_divide_by_zero() {
  let _ = u12![2] / u12![0];
}

#[test]
fn test_checked_div() {
  assert_eq!(U12::max_value().checked_div(U12::max_value()), Some(u12![1]));
  assert_eq!(u12![2].checked_div(u12![255]), Some(u12![0]));
  assert_eq!(u12![255].checked_div(u12![2]), Some(u12![127]));
  assert_eq!(u12![255].checked_div(u12![1]), Some(u12![255]));
  assert_eq!(u12![255].checked_div(u12![0]), None);
}

#[test]
fn test_wrapping_div() {
  assert_eq!(U12::max_value().wrapping_div(U12::max_value()), u12![1]);
  assert_eq!(u12![2].wrapping_div(u12![255]), u12![0]);
  assert_eq!(u12![255].wrapping_div(u12![2]), u12![127]);
  assert_eq!(u12![255].wrapping_div(u12![1]), u12![255]);
}

#[test]
#[should_panic]
fn test_wrapping_div_overflow() {
  let _ = u12![255].wrapping_div(u12![0]);
}

// MARK: - Tests - Negation

#[test]
fn test_checked_neg() {
  assert_eq!(u12![0].checked_neg(), Some(u12![0]));
  assert_eq!(u12![1].checked_neg(), None);
  assert_eq!(u12![2].checked_neg(), None);
  assert_eq!(u12![255].checked_neg(), None);
}

#[test]
fn test_wrapping_neg() {
  assert_eq!(u12![0].wrapping_neg(), u12![0]);
  assert_eq!(u12![1].wrapping_neg(), u12![0xFFF]);
  assert_eq!(u12![2].wrapping_neg(), u12![0xFFE]);
  assert_eq!(u12![255].wrapping_neg(), u12![0xF01]);
}

#[test]
fn test_overflowing_neg() {
  assert_eq!(u12![0].overflowing_neg(), (u12![0], false));
  assert_eq!(u12![1].overflowing_neg(), (u12![0xFFF], true));
  assert_eq!(u12![2].overflowing_neg(), (u12![0xFFE], true));
  assert_eq!(u12![255].overflowing_neg(), (u12![0xF01], true));
}
<|endoftext|>


<commit_before>// Copyright 2014 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_must_use)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate rustc;

use rustc::driver::driver::host_triple;
use std::from_str::{from_str};
use std::io;
use std::io::{Command, FilePermission};
use std::io::fs::{mkdir, File};
use std::option::{Option};
use std::os;
use std::str;

#[deriving(PartialEq)]
struct Version {
    major: uint,
    minor: uint
}

impl Version {
    pub fn parse(version_str: &str) -> Option<Version> {
        let mut it = version_str.split('.');
        match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>)) {
            (Some(major), Some(minor)) => Some(Version { major: major, minor: minor }),
            _                          => None
        }
    }
}

impl std::fmt::Show for Version {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:u}.{:u}", self.major, self.minor)
    }
}

impl PartialOrd for Version {
    fn lt(&self, other: &Version) -> bool {
        self.major < other.major || (self.major == other.major && self.minor < other.minor)
    }
}

fn cd(path: &Path) {
    if !os::change_dir(path) {
        fail!("Package script error: Failed to `cd` into `{}`", path.display());
    }
}

fn main() {
    let pcre_libdir = match os::getenv("PCRE_LIBDIR") {
        None            => {
            let pcre_config_output = match Command::new("pcre-config").arg("--prefix").output() {
                Err(e) => {
                    match e.kind {
                        io::FileNotFound => fail!("Package script error: Could not run `pcre-config` because no such executable is in the executable search PATH. Make sure that you have installed a dev package for libpcre and/or make sure that libpcre's bindir is added to your PATH (currently \"{}\").", os::getenv("PATH").unwrap_or(String::from_str(""))),
                        _ => fail!("Package script error: Could not run `pcre-config`: {}", e.to_str())
                    }
                },
                Ok(pcre_config_output) => pcre_config_output
            };
            if !pcre_config_output.status.success() {
                fail!("Package script error: `pcre-config --prefix` failed");
            }
            let output_ptr = pcre_config_output.output.as_ptr();
            let output_len = pcre_config_output.output.len();
            let prefix_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
            // `pcre-config` adds a newline to the end, which we need to trim away.
            String::from_str(prefix_str.as_slice().trim()).append("/lib")
        },
        Some(pcre_libdir) => pcre_libdir
    };
    let pcre_lib_path = Path::new(pcre_libdir);

    let workspace_path = os::getcwd();

    // Check the version
    let target_build_path = workspace_path.join("build").join(host_triple());
    if !target_build_path.exists() {
        if mkdir(&target_build_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create target build directory `{}`", target_build_path.display());
        }
    }
    let out_path = target_build_path.join("pcre");
    if !out_path.exists() {
        if mkdir(&out_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create output directory `{}`", out_path.display());
        }
    }

    let versioncheck_rs_path = out_path.join("versioncheck.rs");
    {
        let mut f = match File::create(&versioncheck_rs_path) {
            Err(e) => fail!("Package script error: Failed to open `{}` for writing: {:s}", versioncheck_rs_path.display(), e.to_str()),
            Ok(f) => f
        };
        let contents = format!("\
extern crate libc;

use std::c_str::\\{CString\\};
use libc::\\{c_char, c_int, c_uchar, c_void\\};
use std::ptr;
use std::ptr::\\{RawPtr\\};
use std::slice;

type options = c_int;
struct pcre;
struct pcre_extra;

\\#[link(name = \"pcre\")]
extern \\{
    static pcre_free: extern \"C\" fn(ptr: *c_void);

    fn pcre_compile(pattern: *c_char, options: options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *pcre;
    fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: options, ovector: *mut c_int, ovecsize: c_int) -> c_int;
    fn pcre_version() -> *c_char;
\\}

fn main () \\{
    unsafe \\{
        let version_cstring = CString::new(pcre_version(), false);
        let version_str = version_cstring.as_str().unwrap().to_string();

        let pattern = \"^\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\";
        pattern.with_c_str(|pattern_c_str| \\{
            let mut err: *c_char = ptr::null();
            let mut erroffset: c_int = 0;
            let code = pcre_compile(pattern_c_str, 0, &mut err, &mut erroffset, ptr::null());
            if code.is_null() \\{
                if code.is_null() \\{
                    let err_cstring = CString::new(err, false);
                    match err_cstring.as_str() \\{
                        None          => fail!(\"pcre_compile() failed at offset \\{\\}\", erroffset as uint),
                        Some(err_str) => fail!(\"pcre_compile() failed at offset \\{\\}: \\{\\}\", erroffset as uint, err_str)
                    \\}
                \\}
            \\}
            assert!(code.is_not_null());

            let ovecsize = 1 * 3;
            let mut ovector = Vec::from_elem(ovecsize, 0 as c_int);
            version_str.with_c_str_unchecked(|version_c_str| \\{
                let rc = pcre_exec(code, ptr::null(), version_c_str, version_str.len() as c_int, 0, 0, ovector.as_mut_ptr(), ovecsize as c_int);
                if rc < 0 \\{
                    fail!(\"pcre_exec() failed\");
                \\}

                print!(\"\\{\\}\", version_str.as_slice().slice_to(*ovector.get(1) as uint));
            \\});

            pcre_free(code as *c_void);
        \\});
    \\}
\\}
");
        f.write_str(contents.as_slice()).map_err(|e| -> () {
            fail!("Package script error: Failed to write to `{}`: {:s}", versioncheck_rs_path.display(), e.to_str());
        });
    }

    // Compile and run `versioncheck.rs`
    cd(&out_path);
    let rustc_output = match Command::new("rustc").arg("versioncheck.rs").arg("-L").arg(pcre_lib_path.display().to_str()).output() {
        Err(e) => fail!("Package script error: Failed to run `rustc`: {:s}", e.to_str()),
        Ok(rustc_output) => rustc_output
    };
    if !rustc_output.status.success() {
        println!("{}", str::from_utf8(rustc_output.output.as_slice()));
        println!("{}", str::from_utf8(rustc_output.error.as_slice()));
        fail!("Package script error: `rustc versioncheck.rs` failed: {}", rustc_output.status);
    }
    let versioncheck_output = match Command::new("./versioncheck").output() {
        Err(e) => fail!("Package script error: Failed to run `./versioncheck`: {:s}", e.to_str()),
        Ok(versioncheck_output) => versioncheck_output
    };
    if !versioncheck_output.status.success() {
        println!("{}", str::from_utf8(versioncheck_output.output.as_slice()));
        println!("{}", str::from_utf8(versioncheck_output.error.as_slice()));
        fail!("versioncheck error: {}", versioncheck_output.status);
    }
    cd(&workspace_path);

    let output_ptr = versioncheck_output.output.as_ptr();
    let output_len = versioncheck_output.output.len();
    let output_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
    debug!("output_str = `{}`", output_str);

    // The "no debug symbols in executable" warning may be present in the output.
    // https://github.com/mozilla/rust/issues/3495
    let mut output_rsplit_iter = output_str.as_slice().split('\n').rev();
    let version_str: String = match output_rsplit_iter.next() {
        None              => output_str.clone(),
        Some(version_str) => version_str.to_string()
    };

    debug!("libpcre version {:s}", version_str.as_slice());

    let min_required_version = Version::parse("8.20").unwrap();
    let pcre_version = match Version::parse(version_str.as_slice()) {
        None               => fail!("Package script error: Failed to parse version string '{}'", version_str.as_slice()),
        Some(pcre_version) => pcre_version
    };

    if pcre_version < min_required_version {
        fail!("Package script error: Found libpcre version {}, but at least version {} is required", version_str.as_slice(), min_required_version.to_str());
    }

    // Create directories `bin` and `lib`
    let bin_path = workspace_path.join("bin");
    if !bin_path.exists() {
        if mkdir(&bin_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create the `bin` directory");
        }
    }
    let lib_path = workspace_path.join("lib");
    if !lib_path.exists() {
        if mkdir(&lib_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create the `lib` directory");
        }
    }

    // Compile libpcre-*.rlib
    match Command::new("rustc").arg("--out-dir").arg(lib_path.display().to_str()).arg("src/pcre/mod.rs").arg("-L").arg(pcre_lib_path.display().to_str()).output() {
        Err(e) => fail!("Package script error: Failed to run `rustc`: {:s}", e.to_str()),
        Ok(rustc_output) => {
            if !rustc_output.status.success() {
                println!("{}", str::from_utf8(rustc_output.output.as_slice()));
                println!("{}", str::from_utf8(rustc_output.error.as_slice()));
                fail!("Package script error: `rustc src/pcre/mod.rs` failed: {}", rustc_output.status);
            }
        }
    }

    match Command::new("rustc").arg("-o").arg(bin_path.join("pcredemo").display().to_str()).arg("src/pcredemo/main.rs").arg("-L").arg("lib").arg("-L").arg(pcre_lib_path.display().to_str()).output() {
        Err(e) => fail!("Package script error: Failed to run `rustc`: {:s}", e.to_str()),
        Ok(rustc_output) => {
            if !rustc_output.status.success() {
                println!("{}", str::from_utf8(rustc_output.output.as_slice()));
                println!("{}", str::from_utf8(rustc_output.error.as_slice()));
                fail!("Package script error: `rustc src/pcredemo/main.rs` failed: {}", rustc_output.status);
            }
        }
    }
}
<commit_msg>Update to build with latest rustc.<commit_after>// Copyright 2014 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused_must_use)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate rustc;

use rustc::driver::driver::host_triple;
use std::from_str::{from_str};
use std::io;
use std::io::{Command, FilePermission};
use std::io::fs::{mkdir, File};
use std::option::{Option};
use std::os;
use std::str;

#[deriving(PartialEq)]
struct Version {
    major: uint,
    minor: uint
}

impl Version {
    pub fn parse(version_str: &str) -> Option<Version> {
        let mut it = version_str.split('.');
        match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>)) {
            (Some(major), Some(minor)) => Some(Version { major: major, minor: minor }),
            _                          => None
        }
    }
}

impl std::fmt::Show for Version {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:u}.{:u}", self.major, self.minor)
    }
}

impl PartialOrd for Version {
    fn lt(&self, other: &Version) -> bool {
        self.major < other.major || (self.major == other.major && self.minor < other.minor)
    }
}

fn cd(path: &Path) {
    if !os::change_dir(path) {
        fail!("Package script error: Failed to `cd` into `{}`", path.display());
    }
}

fn main() {
    let pcre_libdir = match os::getenv("PCRE_LIBDIR") {
        None            => {
            let pcre_config_output = match Command::new("pcre-config").arg("--prefix").output() {
                Err(e) => {
                    match e.kind {
                        io::FileNotFound => fail!("Package script error: Could not run `pcre-config` because no such executable is in the executable search PATH. Make sure that you have installed a dev package for libpcre and/or make sure that libpcre's bindir is added to your PATH (currently \"{}\").", os::getenv("PATH").unwrap_or(String::from_str(""))),
                        _ => fail!("Package script error: Could not run `pcre-config`: {}", e.to_str())
                    }
                },
                Ok(pcre_config_output) => pcre_config_output
            };
            if !pcre_config_output.status.success() {
                fail!("Package script error: `pcre-config --prefix` failed");
            }
            let output_ptr = pcre_config_output.output.as_ptr();
            let output_len = pcre_config_output.output.len();
            let prefix_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
            // `pcre-config` adds a newline to the end, which we need to trim away.
            String::from_str(prefix_str.as_slice().trim()).append("/lib")
        },
        Some(pcre_libdir) => pcre_libdir
    };
    let pcre_lib_path = Path::new(pcre_libdir);

    let workspace_path = os::getcwd();

    // Check the version
    let target_build_path = workspace_path.join("build").join(host_triple());
    if !target_build_path.exists() {
        if mkdir(&target_build_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create target build directory `{}`", target_build_path.display());
        }
    }
    let out_path = target_build_path.join("pcre");
    if !out_path.exists() {
        if mkdir(&out_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create output directory `{}`", out_path.display());
        }
    }

    let versioncheck_rs_path = out_path.join("versioncheck.rs");
    {
        let mut f = match File::create(&versioncheck_rs_path) {
            Err(e) => fail!("Package script error: Failed to open `{}` for writing: {:s}", versioncheck_rs_path.display(), e.to_str()),
            Ok(f) => f
        };
        let contents = format!("\
extern crate libc;

use std::c_str::{{CString}};
use libc::{{c_char, c_int, c_uchar, c_void}};
use std::ptr;
use std::ptr::{{RawPtr}};
use std::slice;

type options = c_int;
struct pcre;
struct pcre_extra;

#[link(name = \"pcre\")]
extern {{
    static pcre_free: extern \"C\" fn(ptr: *c_void);

    fn pcre_compile(pattern: *c_char, options: options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *pcre;
    fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: options, ovector: *mut c_int, ovecsize: c_int) -> c_int;
    fn pcre_version() -> *c_char;
}}

fn main () {{
    unsafe {{
        let version_cstring = CString::new(pcre_version(), false);
        let version_str = version_cstring.as_str().unwrap().to_string();

        let pattern = \"^\\\\d+\\\\.\\\\d+\";
        pattern.with_c_str(|pattern_c_str| {{
            let mut err: *c_char = ptr::null();
            let mut erroffset: c_int = 0;
            let code = pcre_compile(pattern_c_str, 0, &mut err, &mut erroffset, ptr::null());
            if code.is_null() {{
                if code.is_null() {{
                    let err_cstring = CString::new(err, false);
                    match err_cstring.as_str() {{
                        None          => fail!(\"pcre_compile() failed at offset {{}}\", erroffset as uint),
                        Some(err_str) => fail!(\"pcre_compile() failed at offset {{}}: {{}}\", erroffset as uint, err_str)
                    }}
                }}
            }}
            assert!(code.is_not_null());

            let ovecsize = 1 * 3;
            let mut ovector = Vec::from_elem(ovecsize, 0 as c_int);
            version_str.with_c_str_unchecked(|version_c_str| {{
                let rc = pcre_exec(code, ptr::null(), version_c_str, version_str.len() as c_int, 0, 0, ovector.as_mut_ptr(), ovecsize as c_int);
                if rc < 0 {{
                    fail!(\"pcre_exec() failed\");
                }}

                print!(\"{{}}\", version_str.as_slice().slice_to(*ovector.get(1) as uint));
            }});

            pcre_free(code as *c_void);
        }});
    }}
}}
");
        f.write_str(contents.as_slice()).map_err(|e| -> () {
            fail!("Package script error: Failed to write to `{}`: {:s}", versioncheck_rs_path.display(), e.to_str());
        });
    }

    // Compile and run `versioncheck.rs`
    cd(&out_path);
    let rustc_output = match Command::new("rustc").arg("versioncheck.rs").arg("-L").arg(pcre_lib_path.display().to_str()).output() {
        Err(e) => fail!("Package script error: Failed to run `rustc`: {:s}", e.to_str()),
        Ok(rustc_output) => rustc_output
    };
    if !rustc_output.status.success() {
        println!("{}", str::from_utf8(rustc_output.output.as_slice()));
        println!("{}", str::from_utf8(rustc_output.error.as_slice()));
        fail!("Package script error: `rustc versioncheck.rs` failed: {}", rustc_output.status);
    }
    let versioncheck_output = match Command::new("./versioncheck").output() {
        Err(e) => fail!("Package script error: Failed to run `./versioncheck`: {:s}", e.to_str()),
        Ok(versioncheck_output) => versioncheck_output
    };
    if !versioncheck_output.status.success() {
        println!("{}", str::from_utf8(versioncheck_output.output.as_slice()));
        println!("{}", str::from_utf8(versioncheck_output.error.as_slice()));
        fail!("versioncheck error: {}", versioncheck_output.status);
    }
    cd(&workspace_path);

    let output_ptr = versioncheck_output.output.as_ptr();
    let output_len = versioncheck_output.output.len();
    let output_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
    debug!("output_str = `{}`", output_str);

    // The "no debug symbols in executable" warning may be present in the output.
    // https://github.com/mozilla/rust/issues/3495
    let mut output_rsplit_iter = output_str.as_slice().split('\n').rev();
    let version_str: String = match output_rsplit_iter.next() {
        None              => output_str.clone(),
        Some(version_str) => version_str.to_string()
    };

    debug!("libpcre version {:s}", version_str.as_slice());

    let min_required_version = Version::parse("8.20").unwrap();
    let pcre_version = match Version::parse(version_str.as_slice()) {
        None               => fail!("Package script error: Failed to parse version string '{}'", version_str.as_slice()),
        Some(pcre_version) => pcre_version
    };

    if pcre_version < min_required_version {
        fail!("Package script error: Found libpcre version {}, but at least version {} is required", version_str.as_slice(), min_required_version.to_str());
    }

    // Create directories `bin` and `lib`
    let bin_path = workspace_path.join("bin");
    if !bin_path.exists() {
        if mkdir(&bin_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create the `bin` directory");
        }
    }
    let lib_path = workspace_path.join("lib");
    if !lib_path.exists() {
        if mkdir(&lib_path, FilePermission::from_bits_truncate(0x1FF)).is_err() {
            fail!("Package script error: Failed to create the `lib` directory");
        }
    }

    // Compile libpcre-*.rlib
    match Command::new("rustc").arg("--out-dir").arg(lib_path.display().to_str()).arg("src/pcre/mod.rs").arg("-L").arg(pcre_lib_path.display().to_str()).output() {
        Err(e) => fail!("Package script error: Failed to run `rustc`: {:s}", e.to_str()),
        Ok(rustc_output) => {
            if !rustc_output.status.success() {
                println!("{}", str::from_utf8(rustc_output.output.as_slice()));
                println!("{}", str::from_utf8(rustc_output.error.as_slice()));
                fail!("Package script error: `rustc src/pcre/mod.rs` failed: {}", rustc_output.status);
            }
        }
    }

    match Command::new("rustc").arg("-o").arg(bin_path.join("pcredemo").display().to_str()).arg("src/pcredemo/main.rs").arg("-L").arg("lib").arg("-L").arg(pcre_lib_path.display().to_str()).output() {
        Err(e) => fail!("Package script error: Failed to run `rustc`: {:s}", e.to_str()),
        Ok(rustc_output) => {
            if !rustc_output.status.success() {
                println!("{}", str::from_utf8(rustc_output.output.as_slice()));
                println!("{}", str::from_utf8(rustc_output.error.as_slice()));
                fail!("Package script error: `rustc src/pcredemo/main.rs` failed: {}", rustc_output.status);
            }
        }
    }
}
<|endoftext|>