<commit_before>extern crate fbx_direct;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::fs::File;
use std::io::BufReader;

use fbx_direct::reader;
use fbx_direct::reader::EventReader;
use fbx_direct::writer::EventWriter;

fn indent(size: usize) -> String {
    const INDENT: &'static str = "    ";
    (0..size).map(|_| INDENT)
        .fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}

#[test]
fn main() {
    use std::io::Write;

    env_logger::init().unwrap();

    let filename = "tests/assets/blender_2_72b_default.fbx";

    let mut exported1 = std::io::Cursor::new(Vec::<u8>::new());
    {
        let file = BufReader::new(File::open(filename).unwrap());
        let parser = EventReader::new(file);
        let mut emitter = EventWriter::new(exported1.by_ref());
        let mut depth = 0;
        for e in parser {
            match e {
                Ok(ref e@reader::FbxEvent::StartNode { .. }) => {
                    debug!("{}{:?}", indent(depth), e);
                    depth += 1;
                },
                Ok(ref e@reader::FbxEvent::EndNode) => {
                    depth -= 1;
                    debug!("{}{:?}", indent(depth), e);
                },
                Ok(ref e) => {
                    debug!("{}{:?}", indent(depth), e);
                },
                Err(e) => {
                    debug!("Error: {:?}", e);
                    break;
                },
            }
            if let Ok(ref e) = e {
                emitter.write(e.as_writer_event()).unwrap();
            }
        }
    }
    {
        use std::io::{Seek,SeekFrom};
        exported1.seek(SeekFrom::Start(0)).unwrap();
    }

    let mut exported2 = std::io::Cursor::new(Vec::<u8>::new());
    {
        let parser = EventReader::new(exported1.by_ref());
        let mut emitter = EventWriter::new(exported2.by_ref());
        let mut depth = 0;
        for e in parser {
            match e {
                Ok(ref e@reader::FbxEvent::StartNode { .. }) => {
                    debug!("{}{:?}", indent(depth), e);
                    depth += 1;
                },
                Ok(ref e@reader::FbxEvent::EndNode) => {
                    depth -= 1;
                    debug!("{}{:?}", indent(depth), e);
                },
                Ok(ref e) => {
                    debug!("{}{:?}", indent(depth), e);
                },
                Err(e) => {
                    debug!("Error: {:?}", e);
                    break;
                },
            }
            if let Ok(ref e) = e {
                emitter.write(e.as_writer_event()).unwrap();
            }
        }
    }

    assert_eq!(exported1.get_ref(), exported2.get_ref());
}
<commit_msg>Change name of a test function<commit_after>extern crate fbx_direct;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::fs::File;
use std::io::BufReader;

use fbx_direct::reader;
use fbx_direct::reader::EventReader;
use fbx_direct::writer::EventWriter;

fn indent(size: usize) -> String {
    const INDENT: &'static str = "    ";
    (0..size).map(|_| INDENT)
        .fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}

#[test]
fn binary_export_import() {
    use std::io::Write;

    env_logger::init().unwrap();

    let filename = "tests/assets/blender_2_72b_default.fbx";

    let mut exported1 = std::io::Cursor::new(Vec::<u8>::new());
    {
        let file = BufReader::new(File::open(filename).unwrap());
        let parser = EventReader::new(file);
        let mut emitter = EventWriter::new(exported1.by_ref());
        let mut depth = 0;
        for e in parser {
            match e {
                Ok(ref e@reader::FbxEvent::StartNode { .. }) => {
                    debug!("{}{:?}", indent(depth), e);
                    depth += 1;
                },
                Ok(ref e@reader::FbxEvent::EndNode) => {
                    depth -= 1;
                    debug!("{}{:?}", indent(depth), e);
                },
                Ok(ref e) => {
                    debug!("{}{:?}", indent(depth), e);
                },
                Err(e) => {
                    debug!("Error: {:?}", e);
                    break;
                },
            }
            if let Ok(ref e) = e {
                emitter.write(e.as_writer_event()).unwrap();
            }
        }
    }
    {
        use std::io::{Seek,SeekFrom};
        exported1.seek(SeekFrom::Start(0)).unwrap();
    }

    let mut exported2 = std::io::Cursor::new(Vec::<u8>::new());
    {
        let parser = EventReader::new(exported1.by_ref());
        let mut emitter = EventWriter::new(exported2.by_ref());
        let mut depth = 0;
        for e in parser {
            match e {
                Ok(ref e@reader::FbxEvent::StartNode { .. }) => {
                    debug!("{}{:?}", indent(depth), e);
                    depth += 1;
                },
                Ok(ref e@reader::FbxEvent::EndNode) => {
                    depth -= 1;
                    debug!("{}{:?}", indent(depth), e);
                },
                Ok(ref e) => {
                    debug!("{}{:?}", indent(depth), e);
                },
                Err(e) => {
                    debug!("Error: {:?}", e);
                    break;
                },
            }
            if let Ok(ref e) = e {
                emitter.write(e.as_writer_event()).unwrap();
            }
        }
    }

    assert_eq!(exported1.get_ref(), exported2.get_ref());
}
<|endoftext|>


<commit_before>use nom;
use nom::{alpha, alphanumeric, digit, multispace};
use std::str::from_utf8;

// Identifier
// IDENT := /[a-zA-Z_]\w*/g
named!(identx<&str, &str>, re_match!(r"[a-zA-Z_]\w*"));

// Whitespace
named!(whitespace, chain!(many0!(multispace), || { &b""[..] }));<commit_msg>Fix indent parsing rule name<commit_after>use nom;
use nom::{alpha, alphanumeric, digit, multispace};
use std::str::from_utf8;

// Identifier
// IDENT := /[a-zA-Z_]\w*/g
named!(ident<&str, &str>, re_match!(r"[a-zA-Z_]\w*"));

// Whitespace
named!(whitespace, chain!(many0!(multispace), || { &b""[..] }));<|endoftext|>


<commit_before>//! LDAP Client Crate
//!
//! This crate serves as opinionated abstractions over `ldap_protocol`.
//! While it is useful for LDAP clients it will not work well as LDAP Server.

// TODO: Make this a deny.
#![warn(missing_docs)]

#[doc(no_inline)]
extern crate ldap_protocol as protocol;
extern crate mio;

use std::net::TcpStream;
use std::net::ToSocketAddrs;

use std::io::{Read, Write};

use protocol::ber::{self, common};
pub use protocol::Result;

pub mod bind;
mod queue;

/// Core LDAP struct
///
/// This struct contains all state of the LDAP connection this crate establishes.
/// It is used in all LDAP functions.
#[derive(Debug)]
pub struct LDAP
{
    // TODO: Later abstract over io::Read / io::Write
    stream: TcpStream,

    msgid: i32,
}

impl LDAP
{

    /// Connect to the LDAP-Server found at `addr` using plain unencrypted TCP
    pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<LDAP>
    {
        let stream = try!(TcpStream::connect(addr));

        Ok(LDAP
        {
            stream: stream,
            msgid: 0,
        })
    }

    fn send(&mut self, tag: common::Tag) -> Result<()>
    {
        println!("Sending tag: {:?}", tag);
        let tagbuf = try!(ber::encode(tag, self.msgid));
        try!(self.stream.write(tagbuf.as_slice()));

        Ok(())
    }

    pub fn recv(&mut self) -> Result<common::Tag>
    {
        let mut buf = [0; 500];

        let readamount = try!(self.stream.read(&mut buf));
        println!("read: {}", readamount);

        let tag = try!(ber::decode(&mut buf));
        println!("Received tag: {:?}", tag);

        Ok(tag)
    }
}
<commit_msg>Clarify purpose<commit_after>//! LDAP Client Crate
//!
//! This crate serves as opinionated abstractions over `ldap_protocol`.
//! While it is useful for LDAP clients it will not work well as LDAP Server.

// TODO: Make this a deny.
#![warn(missing_docs)]

#[doc(no_inline)]
extern crate ldap_protocol as protocol;
extern crate mio;

use std::net::TcpStream;
use std::net::ToSocketAddrs;

use std::io::{Read, Write};

use protocol::ber::{self, common};
pub use protocol::Result;

pub mod bind;
mod queue;

/// Core LDAP struct
///
/// This struct contains all state of the LDAP connection this crate establishes.
/// It is used in all LDAP functions.
#[derive(Debug)]
pub struct LDAP
{
    // TODO: Later abstract over io::Read / io::Write (for LDAPS and LDAPI implementation)
    stream: TcpStream,

    msgid: i32,
}

impl LDAP
{

    /// Connect to the LDAP-Server found at `addr` using plain unencrypted TCP
    pub fn connect<A: ToSocketAddrs>(addr: A) -> Result<LDAP>
    {
        let stream = try!(TcpStream::connect(addr));

        Ok(LDAP
        {
            stream: stream,
            msgid: 0,
        })
    }

    fn send(&mut self, tag: common::Tag) -> Result<()>
    {
        println!("Sending tag: {:?}", tag);
        let tagbuf = try!(ber::encode(tag, self.msgid));
        try!(self.stream.write(tagbuf.as_slice()));

        Ok(())
    }

    pub fn recv(&mut self) -> Result<common::Tag>
    {
        let mut buf = [0; 500];

        let readamount = try!(self.stream.read(&mut buf));
        println!("read: {}", readamount);

        let tag = try!(ber::decode(&mut buf));
        println!("Received tag: {:?}", tag);

        Ok(tag)
    }
}
<|endoftext|>


<commit_before>use parser::{Conds, Expr, Node, Nodes, Target};
use std::str;
use std::collections::HashSet;
use syn;

struct Generator {
    buf: String,
    indent: u8,
    start: bool,
    locals: HashSet<String>,
}

impl Generator {

    fn new() -> Generator {
        Generator {
            buf: String::new(),
            indent: 0,
            start: true,
            locals: HashSet::new(),
        }
    }

    fn annotations(&self, generics: &syn::Generics) -> String {
        if generics.lifetimes.len() < 1 {
            return String::new();
        }
        let mut res = String::new();
        res.push('<');
        for lt in &generics.lifetimes {
            res.push_str(lt.lifetime.ident.as_ref());
        }
        res.push('>');
        res
    }

    fn init(&mut self, name: &str, generics: &syn::Generics) {
        self.write("impl");
        let anno = self.annotations(generics);
        self.write(&anno);
        self.write(" askama::Template for ");
        self.write(name);
        self.write(&anno);
        self.writeln(" {");

        self.indent();
        self.writeln("fn render_into(&self, writer: &mut std::fmt::Write) {");
        self.indent();
    }

    fn indent(&mut self) {
        self.indent += 1;
    }

    fn dedent(&mut self) {
        self.indent -= 1;
    }

    fn write(&mut self, s: &str) {
        if self.start {
            for _ in 0..(self.indent * 4) {
                self.buf.push(' ');
            }
            self.start = false;
        }
        self.buf.push_str(s);
    }

    fn writeln(&mut self, s: &str) {
        if s.is_empty() {
            return;
        }
        self.write(s);
        self.buf.push('\n');
        self.start = true;
    }

    fn visit_str_lit(&mut self, s: &str) {
        self.write(&format!("\"{}\"", s));
    }

    fn visit_var(&mut self, s: &[u8]) {
        let s = str::from_utf8(s).unwrap();
        if self.locals.contains(s) {
            self.write(&format!("{}", s));
        } else {
            self.write(&format!("self.{}", s));
        }
    }

    fn visit_filter(&mut self, name: &str, val: &Expr) {
        self.write(&format!("askama::filters::{}(&", name));
        self.visit_expr(val);
        self.write(")");
    }

    fn visit_compare(&mut self, op: &str, left: &Expr, right: &Expr) {
        self.visit_expr(left);
        self.write(&format!(" {} ", op));
        self.visit_expr(right);
    }

    fn visit_expr(&mut self, expr: &Expr) {
        match expr {
            &Expr::StrLit(s) => self.visit_str_lit(s),
            &Expr::Var(s) => self.visit_var(s),
            &Expr::Filter(name, ref val) => self.visit_filter(name, &val),
            &Expr::Compare(op, ref left, ref right) =>
                self.visit_compare(op, &left, &right),
        }
    }

    fn visit_target_single(&mut self, name: &[u8]) -> Vec<String> {
        vec![str::from_utf8(name).unwrap().to_string()]
    }

    fn visit_target(&mut self, target: &Target) -> Vec<String> {
        match target {
            &Target::Name(s) => { self.visit_target_single(s) },
        }
    }

    fn write_lit(&mut self, s: &[u8]) {
        self.write("writer.write_str(");
        self.write(&format!("{:#?}", str::from_utf8(s).unwrap()));
        self.writeln(").unwrap();");
    }

    fn write_expr(&mut self, s: &Expr) {
        self.write("writer.write_fmt(format_args!(\"{}\", ");
        self.visit_expr(s);
        self.writeln(")).unwrap();");
    }

    fn write_cond(&mut self, conds: &Conds) {
        for (i, &(ref cond, ref nodes)) in conds.iter().enumerate() {
            match cond {
                &Some(ref expr) => {
                    if i == 0 {
                        self.write("if ");
                    } else {
                        self.write("} else if ");
                    }
                    self.visit_expr(expr);
                },
                &None => { self.writeln("} else"); },
            }
            self.writeln(" {");
            self.indent();
            self.handle(nodes);
            self.dedent();
        }
        self.writeln("}");
    }

    fn write_loop(&mut self, var: &Target, iter: &Expr, body: &Nodes) {

        self.write("for ");
        let targets = self.visit_target(var);
        for name in &targets {
            self.locals.insert(name.clone());
            self.write(&format!("{}", name));
        }
        self.write(" in &");
        self.visit_expr(iter);
        self.writeln(" {");

        self.indent();
        self.handle(body);
        self.dedent();
        self.writeln("}");
        for name in &targets {
            self.locals.remove(name);
        }
    }

    fn handle(&mut self, tokens: &Vec<Node>) {
        for n in tokens {
            match n {
                &Node::Lit(val) => { self.write_lit(val); },
                &Node::Expr(ref val) => { self.write_expr(&val); },
                &Node::Cond(ref conds) => { self.write_cond(&conds); },
                &Node::Loop(ref var, ref iter, ref body) => {
                    self.write_loop(&var, &iter, &body);
                },
            }
        }
    }

    fn finalize(&mut self) {
        self.dedent();
        self.writeln("}");
        self.dedent();
        self.writeln("}");
    }

    fn result(self) -> String {
        self.buf
    }

}

pub fn generate(ast: &syn::DeriveInput, tokens: &Vec<Node>) -> String {
    let mut gen = Generator::new();
    gen.init(ast.ident.as_ref(), &ast.generics);
    gen.handle(tokens);
    gen.finalize();
    gen.result()
}
<commit_msg>Move some code around to group related parts<commit_after>use parser::{Conds, Expr, Node, Nodes, Target};
use std::str;
use std::collections::HashSet;
use syn;

struct Generator {
    buf: String,
    indent: u8,
    start: bool,
    locals: HashSet<String>,
}

impl Generator {

    fn new() -> Generator {
        Generator {
            buf: String::new(),
            indent: 0,
            start: true,
            locals: HashSet::new(),
        }
    }

    fn indent(&mut self) {
        self.indent += 1;
    }

    fn dedent(&mut self) {
        self.indent -= 1;
    }

    fn write(&mut self, s: &str) {
        if self.start {
            for _ in 0..(self.indent * 4) {
                self.buf.push(' ');
            }
            self.start = false;
        }
        self.buf.push_str(s);
    }

    fn writeln(&mut self, s: &str) {
        if s.is_empty() {
            return;
        }
        self.write(s);
        self.buf.push('\n');
        self.start = true;
    }

    fn visit_str_lit(&mut self, s: &str) {
        self.write(&format!("\"{}\"", s));
    }

    fn visit_var(&mut self, s: &[u8]) {
        let s = str::from_utf8(s).unwrap();
        if self.locals.contains(s) {
            self.write(&format!("{}", s));
        } else {
            self.write(&format!("self.{}", s));
        }
    }

    fn visit_filter(&mut self, name: &str, val: &Expr) {
        self.write(&format!("askama::filters::{}(&", name));
        self.visit_expr(val);
        self.write(")");
    }

    fn visit_compare(&mut self, op: &str, left: &Expr, right: &Expr) {
        self.visit_expr(left);
        self.write(&format!(" {} ", op));
        self.visit_expr(right);
    }

    fn visit_expr(&mut self, expr: &Expr) {
        match expr {
            &Expr::StrLit(s) => self.visit_str_lit(s),
            &Expr::Var(s) => self.visit_var(s),
            &Expr::Filter(name, ref val) => self.visit_filter(name, &val),
            &Expr::Compare(op, ref left, ref right) =>
                self.visit_compare(op, &left, &right),
        }
    }

    fn visit_target_single(&mut self, name: &[u8]) -> Vec<String> {
        vec![str::from_utf8(name).unwrap().to_string()]
    }

    fn visit_target(&mut self, target: &Target) -> Vec<String> {
        match target {
            &Target::Name(s) => { self.visit_target_single(s) },
        }
    }

    fn write_lit(&mut self, s: &[u8]) {
        self.write("writer.write_str(");
        self.write(&format!("{:#?}", str::from_utf8(s).unwrap()));
        self.writeln(").unwrap();");
    }

    fn write_expr(&mut self, s: &Expr) {
        self.write("writer.write_fmt(format_args!(\"{}\", ");
        self.visit_expr(s);
        self.writeln(")).unwrap();");
    }

    fn write_cond(&mut self, conds: &Conds) {
        for (i, &(ref cond, ref nodes)) in conds.iter().enumerate() {
            match cond {
                &Some(ref expr) => {
                    if i == 0 {
                        self.write("if ");
                    } else {
                        self.write("} else if ");
                    }
                    self.visit_expr(expr);
                },
                &None => { self.writeln("} else"); },
            }
            self.writeln(" {");
            self.indent();
            self.handle(nodes);
            self.dedent();
        }
        self.writeln("}");
    }

    fn write_loop(&mut self, var: &Target, iter: &Expr, body: &Nodes) {

        self.write("for ");
        let targets = self.visit_target(var);
        for name in &targets {
            self.locals.insert(name.clone());
            self.write(&format!("{}", name));
        }
        self.write(" in &");
        self.visit_expr(iter);
        self.writeln(" {");

        self.indent();
        self.handle(body);
        self.dedent();
        self.writeln("}");
        for name in &targets {
            self.locals.remove(name);
        }
    }

    fn handle(&mut self, tokens: &Vec<Node>) {
        for n in tokens {
            match n {
                &Node::Lit(val) => { self.write_lit(val); },
                &Node::Expr(ref val) => { self.write_expr(&val); },
                &Node::Cond(ref conds) => { self.write_cond(&conds); },
                &Node::Loop(ref var, ref iter, ref body) => {
                    self.write_loop(&var, &iter, &body);
                },
            }
        }
    }

    fn annotations(&self, generics: &syn::Generics) -> String {
        if generics.lifetimes.len() < 1 {
            return String::new();
        }
        let mut res = String::new();
        res.push('<');
        for lt in &generics.lifetimes {
            res.push_str(lt.lifetime.ident.as_ref());
        }
        res.push('>');
        res
    }

    fn init(&mut self, name: &str, generics: &syn::Generics) {
        self.write("impl");
        let anno = self.annotations(generics);
        self.write(&anno);
        self.write(" askama::Template for ");
        self.write(name);
        self.write(&anno);
        self.writeln(" {");

        self.indent();
        self.writeln("fn render_into(&self, writer: &mut std::fmt::Write) {");
        self.indent();
    }

    fn finalize(&mut self) {
        self.dedent();
        self.writeln("}");
        self.dedent();
        self.writeln("}");
    }

    fn result(self) -> String {
        self.buf
    }

}

pub fn generate(ast: &syn::DeriveInput, tokens: &Vec<Node>) -> String {
    let mut gen = Generator::new();
    gen.init(ast.ident.as_ref(), &ast.generics);
    gen.handle(tokens);
    gen.finalize();
    gen.result()
}
<|endoftext|>


<commit_before>use runtime::Runtime;
use storage::backend::StorageBackend;

use module::Module;
use module::ModuleError;
use module::CommandResult;
use module::CommandEnv;

use module::bm::header::build_header;
use storage::json::parser::JsonHeaderParser;
use storage::parser::{Parser, FileHeaderParser};
use storage::file::File;

use clap::ArgMatches;
use regex::Regex;

pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult {
    let url = env.matches.value_of("url").unwrap();
    let tags = get_tags(env.rt, env.matches);
    info!("Adding url '{}' with tags '{:?}'", url, tags);

    let header  = build_header(&String::from(url), &tags);
    let file    = File::new_with_header(module, header);
    let parser  = Parser::new(JsonHeaderParser::new(None));
    let putres  = env.bk.put_file(file, &parser);

    putres.map_err(|sberr| {
        let mut err = ModuleError::new("Storage Backend Error");
        err.caused_by = Some(Box::new(sberr));
        err
    })
}

pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult {
    let tags    = get_tags(env.rt, env.matches);
    let matcher = get_matcher(env.rt, env.matches);

    match matcher {
        Some(reg) => {
            info!("Listing urls with matcher '{}' and with tags {:?}",
                     reg.as_str(),
                     tags);
        }
        None => {
            info!("Listing urls with tags {:?}", tags);
        }
    }

    Ok(())
}

pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult {
    let tags    = get_tags(env.rt, env.matches);
    let matcher = get_matcher(env.rt, env.matches);
    let id      = get_id(env.rt, env.matches);

    match id {
        Some(idstr) => {
            info!("Removing urls with id '{}'", idstr);
        }
        None => {
            match matcher {
                Some(reg) => {
                    info!("Removing urls with matcher '{}' and with tags {:?}",
                             reg.as_str(), tags);
                }
                None => {
                    info!("Listing urls with tags {:?}", tags);
                }
            }
        }
    }

    Ok(())
}

/*
 *
 * Private helpers
 *
 */

fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec<String> {
    debug!("Fetching tags from commandline");
    sub.value_of("tags").and_then(|tags|
                                  Some(tags.split(",")
                                       .into_iter()
                                       .map(|s| s.to_string())
                                       .filter(|e|
                                            if e.contains(" ") {
                                                warn!("Tag contains spaces: '{}'", e);
                                                false
                                            } else {
                                                true
                                            }).collect()
                                      )
                                 ).or(Some(vec![])).unwrap()

}

fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option<Regex> {
    debug!("Fetching matcher from commandline");
    if let Some(s) = sub.value_of("match") {
        if let Ok(r) = Regex::new(s) {
            return Some(r)
        } else {
            error!("Regex error, continuing without regex");
        }
    }
    None

}

fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option<String> {
    debug!("Fetching id from commandline");
    sub.value_of("id").and_then(|s| Some(String::from(s)))
}

<commit_msg>Implement list_command<commit_after>use runtime::Runtime;
use storage::backend::StorageBackend;

use module::Module;
use module::ModuleError;
use module::CommandResult;
use module::CommandEnv;

use module::bm::header::build_header;
use module::bm::header::get_tags_from_header;
use storage::json::parser::JsonHeaderParser;
use storage::parser::{Parser, FileHeaderParser};
use storage::file::File;
use ui::file::{FilePrinter, TablePrinter};

use clap::ArgMatches;
use regex::Regex;

pub fn add_command(module: &Module, env: CommandEnv) -> CommandResult {
    let url = env.matches.value_of("url").unwrap();
    let tags = get_tags(env.rt, env.matches);
    info!("Adding url '{}' with tags '{:?}'", url, tags);

    let header  = build_header(&String::from(url), &tags);
    let file    = File::new_with_header(module, header);
    let parser  = Parser::new(JsonHeaderParser::new(None));
    let putres  = env.bk.put_file(file, &parser);

    putres.map_err(|sberr| {
        let mut err = ModuleError::new("Storage Backend Error");
        err.caused_by = Some(Box::new(sberr));
        err
    })
}

pub fn list_command(module: &Module, env: CommandEnv) -> CommandResult {
    let tags    = get_tags(env.rt, env.matches);
    debug!("Tags: {:?}", tags);
    let parser  = Parser::new(JsonHeaderParser::new(None));
    let printer = TablePrinter::new(env.rt.is_verbose(), env.rt.is_debugging());
    let files   = env.bk.iter_files(module, &parser).and_then(|files| {
        let f = files.filter(|file| {
            if tags.len() != 0 {
                debug!("Checking tags of: {:?}", file.id());
                get_tags_from_header(&file.header()).iter()
                    .any(|t| tags.contains(t))
            } else {
                true
            }
        }).filter(|file| {
            debug!("Checking matches of: {:?}", file.id());
            get_matcher(env.rt, env.matches)
                .and_then(|r| Some(file.matches_with(&r)))
                .unwrap_or(true)
        }).collect::<Vec<File>>();
        Some(f)
    }).unwrap_or(Vec::<File>::new()).into_iter();

    debug!("Printing files now");
    printer.print_files(files);

    Ok(())
}

pub fn remove_command(module: &Module, env: CommandEnv) -> CommandResult {
    let tags    = get_tags(env.rt, env.matches);
    let matcher = get_matcher(env.rt, env.matches);
    let id      = get_id(env.rt, env.matches);

    match id {
        Some(idstr) => {
            info!("Removing urls with id '{}'", idstr);
        }
        None => {
            match matcher {
                Some(reg) => {
                    info!("Removing urls with matcher '{}' and with tags {:?}",
                             reg.as_str(), tags);
                }
                None => {
                    info!("Listing urls with tags {:?}", tags);
                }
            }
        }
    }

    Ok(())
}

/*
 *
 * Private helpers
 *
 */

fn get_tags<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Vec<String> {
    debug!("Fetching tags from commandline");
    sub.value_of("tags").and_then(|tags|
                                  Some(tags.split(",")
                                       .into_iter()
                                       .map(|s| s.to_string())
                                       .filter(|e|
                                            if e.contains(" ") {
                                                warn!("Tag contains spaces: '{}'", e);
                                                false
                                            } else {
                                                true
                                            }).collect()
                                      )
                                 ).or(Some(vec![])).unwrap()

}

fn get_matcher<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option<Regex> {
    debug!("Fetching matcher from commandline");
    if let Some(s) = sub.value_of("match") {
        if let Ok(r) = Regex::new(s) {
            return Some(r)
        } else {
            error!("Regex error, continuing without regex");
        }
    }
    None

}

fn get_id<'a>(rt: &Runtime, sub: &ArgMatches<'a, 'a>) -> Option<String> {
    debug!("Fetching id from commandline");
    sub.value_of("id").and_then(|s| Some(String::from(s)))
}

<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

#[macro_use(sp)]
extern crate move_ir_types;

pub mod cfgir;
pub mod command_line;
pub mod compiled_unit;
pub mod errors;
pub mod expansion;
pub mod hlir;
pub mod ir_translation;
pub mod naming;
pub mod parser;
pub mod shared;
pub mod test_utils;
mod to_bytecode;
pub mod typing;

use codespan::{ByteIndex, Span};
use compiled_unit::CompiledUnit;
use errors::*;
use move_ir_types::location::*;
use parser::syntax::parse_file_string;
use shared::Address;
use std::{
    collections::HashMap,
    fs::File,
    io::{self, Read, Write},
};

//**************************************************************************************************
// Entry
//**************************************************************************************************

/// Given a set of targets and a set of dependencies
/// - Checks the targets with the dependencies (targets can be dependencies of other targets)
/// Does not run compile to Move bytecode
/// Very large programs might fail on compilation even though they have been checked due to size
///   limitations of the Move bytecode
pub fn move_check(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<()> {
    let (files, errors) = move_check_no_report(targets, deps, sender_opt)?;
    if !errors.is_empty() {
        errors::report_errors(files, errors)
    }
    Ok(())
}

/// Move check but it returns the errors instead of reporting them to stderr
pub fn move_check_no_report(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Errors)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    match check_program(pprog_res, sender_opt) {
        Err(errors) => Ok((files, errors)),
        Ok(_) => Ok((files, vec![])),
    }
}

/// Given a set of targets and a set of dependencies
/// - Checks the targets with the dependencies (targets can be dependencies of other targets)
/// - Compiles the targets to Move bytecode
/// Does not run the Move bytecode verifier on the compiled targets, as the Move front end should
///   be more restrictive
pub fn move_compile(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Vec<CompiledUnit>)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    match compile_program(pprog_res, sender_opt) {
        Err(errors) => errors::report_errors(files, errors),
        Ok(compiled_units) => Ok((files, compiled_units)),
    }
}

/// Move check but it returns the errors instead of reporting them to stderr
pub fn move_compile_no_report(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Result<Vec<CompiledUnit>, Errors>)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    Ok(match compile_program(pprog_res, sender_opt) {
        Err(errors) => (files, Err(errors)),
        Ok(units) => (files, Ok(units)),
    })
}

/// Move compile up to expansion phase, returning errors instead of reporting them to stderr
pub fn move_compile_to_expansion_no_report(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Result<expansion::ast::Program, Errors>)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    let res = pprog_res.and_then(|pprog| {
        let (eprog, errors) = expansion::translate::program(pprog, sender_opt);
        check_errors(errors)?;
        Ok(eprog)
    });
    Ok((files, res))
}

//**************************************************************************************************
// Utils
//**************************************************************************************************

/// Runs the bytecode verifier on the compiled units
/// Fails if the bytecode verifier errors
pub fn sanity_check_compiled_units(files: FilesSourceText, compiled_units: Vec<CompiledUnit>) {
    let (_, ice_errors) = compiled_unit::verify_units(compiled_units);
    if !ice_errors.is_empty() {
        errors::report_errors(files, ice_errors)
    }
}

/// Given a file map and a set of compiled programs, saves the compiled programs to disk
pub fn output_compiled_units(
    files: FilesSourceText,
    compiled_units: Vec<CompiledUnit>,
    out_dir: &str,
) -> io::Result<()> {
    std::fs::create_dir_all(out_dir)?;
    let (compiled_units, ice_errors) = compiled_unit::verify_units(compiled_units);
    let files_and_units = compiled_units
        .into_iter()
        .enumerate()
        .map(|(idx, compiled_unit)| {
            let path = format!(
                "{}/transaction_{}_{}.mv",
                out_dir,
                idx,
                compiled_unit.name()
            );
            let file = File::create(path)?;
            Ok((file, compiled_unit))
        })
        .collect::<io::Result<Vec<_>>>()?;
    for (mut file, compiled_unit) in files_and_units {
        file.write_all(&compiled_unit.serialize())?;
    }
    if !ice_errors.is_empty() {
        errors::report_errors(files, ice_errors)
    }
    Ok(())
}

//**************************************************************************************************
// Translations
//**************************************************************************************************

fn check_program(
    prog: Result<parser::ast::Program, Errors>,
    sender_opt: Option<Address>,
) -> Result<cfgir::ast::Program, Errors> {
    let (eprog, errors) = expansion::translate::program(prog?, sender_opt);
    let (nprog, errors) = naming::translate::program(eprog, errors);
    let (tprog, errors) = typing::translate::program(nprog, errors);
    check_errors(errors)?;
    let (hprog, errors) = hlir::translate::program(tprog);
    let (cprog, errors) = cfgir::translate::program(errors, hprog);
    check_errors(errors)?;
    Ok(cprog)
}

fn compile_program(
    prog: Result<parser::ast::Program, Errors>,
    sender_opt: Option<Address>,
) -> Result<Vec<CompiledUnit>, Errors> {
    let cprog = check_program(prog, sender_opt)?;
    to_bytecode::translate::program(cprog)
}

//**************************************************************************************************
// Parsing
//**************************************************************************************************

fn parse_program(
    targets: &[String],
    deps: &[String],
) -> io::Result<(FilesSourceText, Result<parser::ast::Program, Errors>)> {
    let targets = targets
        .iter()
        .map(|s| leak_str(s))
        .collect::<Vec<&'static str>>();
    let deps = deps
        .iter()
        .map(|s| leak_str(s))
        .collect::<Vec<&'static str>>();
    let mut files: FilesSourceText = HashMap::new();
    let mut source_definitions = Vec::new();
    let mut lib_definitions = Vec::new();
    let mut errors: Errors = Vec::new();

    for fname in targets {
        let (def_opt, mut es) = parse_file(&mut files, fname)?;
        if let Some(def) = def_opt {
            source_definitions.push(def);
        }
        errors.append(&mut es);
    }

    for fname in deps {
        let (def_opt, mut es) = parse_file(&mut files, fname)?;
        if let Some(def) = def_opt {
            lib_definitions.push(def);
        }
        errors.append(&mut es);
    }

    let res = if errors.is_empty() {
        Ok(parser::ast::Program {
            source_definitions,
            lib_definitions,
        })
    } else {
        Err(errors)
    };
    Ok((files, res))
}

// TODO replace with some sort of intern table
fn leak_str(s: &str) -> &'static str {
    Box::leak(Box::new(s.to_owned()))
}

fn parse_file(
    files: &mut FilesSourceText,
    fname: &'static str,
) -> io::Result<(Option<parser::ast::FileDefinition>, Errors)> {
    let mut errors: Errors = Vec::new();
    let mut f = File::open(fname)?;
    let mut source_buffer = String::new();
    f.read_to_string(&mut source_buffer)?;
    let no_comments_buffer = match strip_comments_and_verify(fname, &source_buffer) {
        Err(err) => {
            errors.push(err);
            files.insert(fname, source_buffer);
            return Ok((None, errors));
        }
        Ok(no_comments_buffer) => no_comments_buffer,
    };
    let def_opt = match parse_file_string(fname, &no_comments_buffer) {
        Ok(def) => Some(def),
        Err(err) => {
            errors.push(err);
            None
        }
    };
    files.insert(fname, no_comments_buffer);
    Ok((def_opt, errors))
}

//**************************************************************************************************
// Comments
//**************************************************************************************************

/// Determine if a character is an allowed eye-visible (printable) character.
///
/// The only allowed printable characters are the printable ascii characters (SPACE through ~) and
/// tabs. All other characters are invalid and we return false.
pub fn is_permitted_printable_char(c: char) -> bool {
    let x = c as u32;
    let is_above_space = x >= 0x20; // Don't allow meta characters
    let is_below_tilde = x <= 0x7E; // Don't allow DEL meta character
    let is_tab = x == 0x09; // Allow tabs
    (is_above_space && is_below_tilde) || is_tab
}

/// Determine if a character is a permitted newline character.
///
/// The only permitted newline character is \n. All others are invalid.
pub fn is_permitted_newline_char(c: char) -> bool {
    let x = c as u32;
    x == 0x0A
}

/// Determine if a character is permitted character.
///
/// A permitted character is either a permitted printable character, or a permitted
/// newline. Any other characters are disallowed from appearing in the file.
pub fn is_permitted_char(c: char) -> bool {
    is_permitted_printable_char(c) || is_permitted_newline_char(c)
}

fn verify_string(fname: &'static str, string: &str) -> Result<(), Error> {
    match string
        .chars()
        .enumerate()
        .find(|(_, c)| !is_permitted_char(*c))
    {
        None => Ok(()),
        Some((idx, chr)) => {
            let span = Span::new(ByteIndex(idx as u32), ByteIndex(idx as u32));
            let loc = Loc::new(fname, span);
            let msg = format!(
                "Invalid character '{}' found when reading file. \
                 Only ASCII printable characters, tabs (\\t), and line endings (\\n) \
                 are permitted.",
                chr
            );
            Err(vec![(loc, msg)])
        }
    }
}

fn strip_comments(source: &str) -> String {
    const SLASH: char = '/';
    const SPACE: char = ' ';

    let mut in_comment = false;
    let mut acc = String::with_capacity(source.len());
    let mut char_iter = source.chars().peekable();

    while let Some(chr) = char_iter.next() {
        let at_newline = is_permitted_newline_char(chr);
        let at_or_after_slash_slash =
            in_comment || (chr == SLASH && char_iter.peek().map(|c| *c == SLASH).unwrap_or(false));
        in_comment = !at_newline && at_or_after_slash_slash;
        acc.push(if in_comment { SPACE } else { chr });
    }

    acc
}

// We restrict strings to only ascii visual characters (0x20 <= c <= 0x7E) or a permitted newline
// character--\n--or a tab--\t.
fn strip_comments_and_verify(fname: &'static str, string: &str) -> Result<String, Error> {
    verify_string(fname, string)?;
    Ok(strip_comments(string))
}
<commit_msg>[move-lang] Inject file name into error messages about file open errors.<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

#[macro_use(sp)]
extern crate move_ir_types;

pub mod cfgir;
pub mod command_line;
pub mod compiled_unit;
pub mod errors;
pub mod expansion;
pub mod hlir;
pub mod ir_translation;
pub mod naming;
pub mod parser;
pub mod shared;
pub mod test_utils;
mod to_bytecode;
pub mod typing;

use codespan::{ByteIndex, Span};
use compiled_unit::CompiledUnit;
use errors::*;
use move_ir_types::location::*;
use parser::syntax::parse_file_string;
use shared::Address;
use std::{
    collections::HashMap,
    fs::File,
    io::{self, Read, Write},
};

//**************************************************************************************************
// Entry
//**************************************************************************************************

/// Given a set of targets and a set of dependencies
/// - Checks the targets with the dependencies (targets can be dependencies of other targets)
/// Does not run compile to Move bytecode
/// Very large programs might fail on compilation even though they have been checked due to size
///   limitations of the Move bytecode
pub fn move_check(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<()> {
    let (files, errors) = move_check_no_report(targets, deps, sender_opt)?;
    if !errors.is_empty() {
        errors::report_errors(files, errors)
    }
    Ok(())
}

/// Move check but it returns the errors instead of reporting them to stderr
pub fn move_check_no_report(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Errors)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    match check_program(pprog_res, sender_opt) {
        Err(errors) => Ok((files, errors)),
        Ok(_) => Ok((files, vec![])),
    }
}

/// Given a set of targets and a set of dependencies
/// - Checks the targets with the dependencies (targets can be dependencies of other targets)
/// - Compiles the targets to Move bytecode
/// Does not run the Move bytecode verifier on the compiled targets, as the Move front end should
///   be more restrictive
pub fn move_compile(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Vec<CompiledUnit>)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    match compile_program(pprog_res, sender_opt) {
        Err(errors) => errors::report_errors(files, errors),
        Ok(compiled_units) => Ok((files, compiled_units)),
    }
}

/// Move check but it returns the errors instead of reporting them to stderr
pub fn move_compile_no_report(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Result<Vec<CompiledUnit>, Errors>)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    Ok(match compile_program(pprog_res, sender_opt) {
        Err(errors) => (files, Err(errors)),
        Ok(units) => (files, Ok(units)),
    })
}

/// Move compile up to expansion phase, returning errors instead of reporting them to stderr
pub fn move_compile_to_expansion_no_report(
    targets: &[String],
    deps: &[String],
    sender_opt: Option<Address>,
) -> io::Result<(FilesSourceText, Result<expansion::ast::Program, Errors>)> {
    let (files, pprog_res) = parse_program(targets, deps)?;
    let res = pprog_res.and_then(|pprog| {
        let (eprog, errors) = expansion::translate::program(pprog, sender_opt);
        check_errors(errors)?;
        Ok(eprog)
    });
    Ok((files, res))
}

//**************************************************************************************************
// Utils
//**************************************************************************************************

/// Runs the bytecode verifier on the compiled units
/// Fails if the bytecode verifier errors
pub fn sanity_check_compiled_units(files: FilesSourceText, compiled_units: Vec<CompiledUnit>) {
    let (_, ice_errors) = compiled_unit::verify_units(compiled_units);
    if !ice_errors.is_empty() {
        errors::report_errors(files, ice_errors)
    }
}

/// Given a file map and a set of compiled programs, saves the compiled programs to disk
pub fn output_compiled_units(
    files: FilesSourceText,
    compiled_units: Vec<CompiledUnit>,
    out_dir: &str,
) -> io::Result<()> {
    std::fs::create_dir_all(out_dir)?;
    let (compiled_units, ice_errors) = compiled_unit::verify_units(compiled_units);
    let files_and_units = compiled_units
        .into_iter()
        .enumerate()
        .map(|(idx, compiled_unit)| {
            let path = format!(
                "{}/transaction_{}_{}.mv",
                out_dir,
                idx,
                compiled_unit.name()
            );
            let file = File::create(path)?;
            Ok((file, compiled_unit))
        })
        .collect::<io::Result<Vec<_>>>()?;
    for (mut file, compiled_unit) in files_and_units {
        file.write_all(&compiled_unit.serialize())?;
    }
    if !ice_errors.is_empty() {
        errors::report_errors(files, ice_errors)
    }
    Ok(())
}

//**************************************************************************************************
// Translations
//**************************************************************************************************

fn check_program(
    prog: Result<parser::ast::Program, Errors>,
    sender_opt: Option<Address>,
) -> Result<cfgir::ast::Program, Errors> {
    let (eprog, errors) = expansion::translate::program(prog?, sender_opt);
    let (nprog, errors) = naming::translate::program(eprog, errors);
    let (tprog, errors) = typing::translate::program(nprog, errors);
    check_errors(errors)?;
    let (hprog, errors) = hlir::translate::program(tprog);
    let (cprog, errors) = cfgir::translate::program(errors, hprog);
    check_errors(errors)?;
    Ok(cprog)
}

fn compile_program(
    prog: Result<parser::ast::Program, Errors>,
    sender_opt: Option<Address>,
) -> Result<Vec<CompiledUnit>, Errors> {
    let cprog = check_program(prog, sender_opt)?;
    to_bytecode::translate::program(cprog)
}

//**************************************************************************************************
// Parsing
//**************************************************************************************************

fn parse_program(
    targets: &[String],
    deps: &[String],
) -> io::Result<(FilesSourceText, Result<parser::ast::Program, Errors>)> {
    let targets = targets
        .iter()
        .map(|s| leak_str(s))
        .collect::<Vec<&'static str>>();
    let deps = deps
        .iter()
        .map(|s| leak_str(s))
        .collect::<Vec<&'static str>>();
    let mut files: FilesSourceText = HashMap::new();
    let mut source_definitions = Vec::new();
    let mut lib_definitions = Vec::new();
    let mut errors: Errors = Vec::new();

    for fname in targets {
        let (def_opt, mut es) = parse_file(&mut files, fname)?;
        if let Some(def) = def_opt {
            source_definitions.push(def);
        }
        errors.append(&mut es);
    }

    for fname in deps {
        let (def_opt, mut es) = parse_file(&mut files, fname)?;
        if let Some(def) = def_opt {
            lib_definitions.push(def);
        }
        errors.append(&mut es);
    }

    let res = if errors.is_empty() {
        Ok(parser::ast::Program {
            source_definitions,
            lib_definitions,
        })
    } else {
        Err(errors)
    };
    Ok((files, res))
}

// TODO replace with some sort of intern table
fn leak_str(s: &str) -> &'static str {
    Box::leak(Box::new(s.to_owned()))
}

fn parse_file(
    files: &mut FilesSourceText,
    fname: &'static str,
) -> io::Result<(Option<parser::ast::FileDefinition>, Errors)> {
    let mut errors: Errors = Vec::new();
    let mut f = File::open(fname)
        .map_err(|err| std::io::Error::new(err.kind(), format!("{}: {}", err, fname)))?;
    let mut source_buffer = String::new();
    f.read_to_string(&mut source_buffer)?;
    let no_comments_buffer = match strip_comments_and_verify(fname, &source_buffer) {
        Err(err) => {
            errors.push(err);
            files.insert(fname, source_buffer);
            return Ok((None, errors));
        }
        Ok(no_comments_buffer) => no_comments_buffer,
    };
    let def_opt = match parse_file_string(fname, &no_comments_buffer) {
        Ok(def) => Some(def),
        Err(err) => {
            errors.push(err);
            None
        }
    };
    files.insert(fname, no_comments_buffer);
    Ok((def_opt, errors))
}

//**************************************************************************************************
// Comments
//**************************************************************************************************

/// Determine if a character is an allowed eye-visible (printable) character.
///
/// The only allowed printable characters are the printable ascii characters (SPACE through ~) and
/// tabs. All other characters are invalid and we return false.
pub fn is_permitted_printable_char(c: char) -> bool {
    let x = c as u32;
    let is_above_space = x >= 0x20; // Don't allow meta characters
    let is_below_tilde = x <= 0x7E; // Don't allow DEL meta character
    let is_tab = x == 0x09; // Allow tabs
    (is_above_space && is_below_tilde) || is_tab
}

/// Determine if a character is a permitted newline character.
///
/// The only permitted newline character is \n. All others are invalid.
pub fn is_permitted_newline_char(c: char) -> bool {
    let x = c as u32;
    x == 0x0A
}

/// Determine if a character is permitted character.
///
/// A permitted character is either a permitted printable character, or a permitted
/// newline. Any other characters are disallowed from appearing in the file.
pub fn is_permitted_char(c: char) -> bool {
    is_permitted_printable_char(c) || is_permitted_newline_char(c)
}

fn verify_string(fname: &'static str, string: &str) -> Result<(), Error> {
    match string
        .chars()
        .enumerate()
        .find(|(_, c)| !is_permitted_char(*c))
    {
        None => Ok(()),
        Some((idx, chr)) => {
            let span = Span::new(ByteIndex(idx as u32), ByteIndex(idx as u32));
            let loc = Loc::new(fname, span);
            let msg = format!(
                "Invalid character '{}' found when reading file. \
                 Only ASCII printable characters, tabs (\\t), and line endings (\\n) \
                 are permitted.",
                chr
            );
            Err(vec![(loc, msg)])
        }
    }
}

fn strip_comments(source: &str) -> String {
    const SLASH: char = '/';
    const SPACE: char = ' ';

    let mut in_comment = false;
    let mut acc = String::with_capacity(source.len());
    let mut char_iter = source.chars().peekable();

    while let Some(chr) = char_iter.next() {
        let at_newline = is_permitted_newline_char(chr);
        let at_or_after_slash_slash =
            in_comment || (chr == SLASH && char_iter.peek().map(|c| *c == SLASH).unwrap_or(false));
        in_comment = !at_newline && at_or_after_slash_slash;
        acc.push(if in_comment { SPACE } else { chr });
    }

    acc
}

// We restrict strings to only ascii visual characters (0x20 <= c <= 0x7E) or a permitted newline
// character--\n--or a tab--\t.
fn strip_comments_and_verify(fname: &'static str, string: &str) -> Result<String, Error> {
    verify_string(fname, string)?;
    Ok(strip_comments(string))
}
<|endoftext|>


<commit_before>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use anyhow::{bail, Result};
use std::env;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

const MINIGBM_SRC: &str = "../third_party/minigbm";
const VIRGLRENDERER_SRC: &str = "../third_party/virglrenderer";

fn is_native_build() -> bool {
    env::var("HOST").unwrap() == env::var("TARGET").unwrap()
}

/// Returns the target triplet prefix for gcc commands. No prefix is required
/// for native builds.
fn get_cross_compile_prefix() -> String {
    if is_native_build() {
        return String::from("");
    }

    let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
    return format!("{}-{}-{}-", arch, os, env);
}

/// For cross-compilation with meson, we need to pick a cross-file, which
/// live in /usr/local/share/meson/cross.
fn get_meson_cross_args() -> Vec<String> {
    if is_native_build() {
        Vec::new()
    } else {
        vec![
            "--cross-file".to_string(),
            env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
        ]
    }
}

fn build_minigbm(out_dir: &Path) -> Result<()> {
    let lib_path = out_dir.join("libgbm.a");
    if lib_path.exists() {
        return Ok(());
    }

    if !Path::new("../third_party/minigbm/.git").exists() {
        bail!(
            "third_party/minigbm source does not exist, did you forget to \
            `git submodule update --init`?"
        );
    }

    let make_flags = env::var("CARGO_MAKEFLAGS").unwrap();
    let status = Command::new("make")
        .env("MAKEFLAGS", make_flags)
        .env("CROSS_COMPILE", get_cross_compile_prefix())
        .arg(format!("OUT={}", out_dir.display()))
        .arg("CC_STATIC_LIBRARY(libminigbm.pie.a)")
        .current_dir("../third_party/minigbm")
        .status()?;
    if !status.success() {
        bail!("make failed with status: {}", status);
    }

    // minigbm will be linked using the name gbm, make sure it can be found.
    fs::copy(out_dir.join("libminigbm.pie.a"), out_dir.join("libgbm.a"))?;
    Ok(())
}

fn build_virglrenderer(out_dir: &Path) -> Result<()> {
    let lib_path = out_dir.join("src/libvirglrenderer.a");
    if lib_path.exists() {
        return Ok(());
    }

    if !Path::new("../third_party/virglrenderer/.git").exists() {
        bail!(
            "third_party/virglrenderer source does not exist, did you forget to \
            `git submodule update --init`?"
        );
    }

    let minigbm_src_abs = PathBuf::from(MINIGBM_SRC).canonicalize()?;
    let status = Command::new("meson")
        .env("PKG_CONFIG_PATH", &minigbm_src_abs)
        .arg("setup")
        .arg("-Ddefault_library=static")
        .args(get_meson_cross_args())
        .arg(out_dir.as_os_str())
        .current_dir(VIRGLRENDERER_SRC)
        .status()?;
    if !status.success() {
        bail!("meson setup failed with status: {}", status);
    }

    // Add local minigbm paths to make sure virglrenderer can build against it.
    let mut cmd = Command::new("meson");
    cmd.env("CPATH", &minigbm_src_abs)
        .arg("compile")
        .arg("src/virglrenderer")
        .current_dir(out_dir);

    let status = cmd.status()?;
    if !status.success() {
        bail!("meson compile failed with status: {}", status);
    }
    Ok(())
}

fn virglrenderer() -> Result<()> {
    // System provided runtime dependencies.
    pkg_config::Config::new().probe("epoxy")?;
    pkg_config::Config::new().probe("libdrm")?;

    // Use virglrenderer package from the standard system location if available.
    if pkg_config::Config::new().probe("virglrenderer").is_ok() {
        return Ok(());
    }

    // Otherwise build from source.
    let out_dir = PathBuf::from(env::var("OUT_DIR")?);
    let minigbm_out = out_dir.join("minigbm");
    let virglrenderer_out = out_dir.join("virglrenderer");
    build_minigbm(&minigbm_out)?;
    build_virglrenderer(&virglrenderer_out)?;

    println!(
        "cargo:rustc-link-search={}/src",
        virglrenderer_out.display()
    );
    println!("cargo:rustc-link-search={}", minigbm_out.display());
    println!("cargo:rustc-link-lib=static=virglrenderer");
    println!("cargo:rustc-link-lib=static=gbm");
    Ok(())
}

fn main() -> Result<()> {
    #[cfg(feature = "virgl_renderer")]
    virglrenderer()?;

    Ok(())
}
<commit_msg>Use constants for third_party code locations rather than hard-coding.<commit_after>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use anyhow::{bail, Result};
use std::env;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

const MINIGBM_SRC: &str = "../third_party/minigbm";
const VIRGLRENDERER_SRC: &str = "../third_party/virglrenderer";

fn is_native_build() -> bool {
    env::var("HOST").unwrap() == env::var("TARGET").unwrap()
}

/// Returns the target triplet prefix for gcc commands. No prefix is required
/// for native builds.
fn get_cross_compile_prefix() -> String {
    if is_native_build() {
        return String::from("");
    }

    let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
    let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
    return format!("{}-{}-{}-", arch, os, env);
}

/// For cross-compilation with meson, we need to pick a cross-file, which
/// live in /usr/local/share/meson/cross.
fn get_meson_cross_args() -> Vec<String> {
    if is_native_build() {
        Vec::new()
    } else {
        vec![
            "--cross-file".to_string(),
            env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
        ]
    }
}

fn build_minigbm(out_dir: &Path) -> Result<()> {
    let lib_path = out_dir.join("libgbm.a");
    if lib_path.exists() {
        return Ok(());
    }

    if !Path::new(MINIGBM_SRC).join(".git").exists() {
        bail!(
            "{} source does not exist, did you forget to \
            `git submodule update --init`?",
            MINIGBM_SRC
        );
    }

    let make_flags = env::var("CARGO_MAKEFLAGS").unwrap();
    let status = Command::new("make")
        .env("MAKEFLAGS", make_flags)
        .env("CROSS_COMPILE", get_cross_compile_prefix())
        .arg(format!("OUT={}", out_dir.display()))
        .arg("CC_STATIC_LIBRARY(libminigbm.pie.a)")
        .current_dir(MINIGBM_SRC)
        .status()?;
    if !status.success() {
        bail!("make failed with status: {}", status);
    }

    // minigbm will be linked using the name gbm, make sure it can be found.
    fs::copy(out_dir.join("libminigbm.pie.a"), out_dir.join("libgbm.a"))?;
    Ok(())
}

fn build_virglrenderer(out_dir: &Path) -> Result<()> {
    let lib_path = out_dir.join("src/libvirglrenderer.a");
    if lib_path.exists() {
        return Ok(());
    }

    if !Path::new(VIRGLRENDERER_SRC).join(".git").exists() {
        bail!(
            "{} source does not exist, did you forget to \
            `git submodule update --init`?",
            VIRGLRENDERER_SRC
        );
    }

    let minigbm_src_abs = PathBuf::from(MINIGBM_SRC).canonicalize()?;
    let status = Command::new("meson")
        .env("PKG_CONFIG_PATH", &minigbm_src_abs)
        .arg("setup")
        .arg("-Ddefault_library=static")
        .args(get_meson_cross_args())
        .arg(out_dir.as_os_str())
        .current_dir(VIRGLRENDERER_SRC)
        .status()?;
    if !status.success() {
        bail!("meson setup failed with status: {}", status);
    }

    // Add local minigbm paths to make sure virglrenderer can build against it.
    let mut cmd = Command::new("meson");
    cmd.env("CPATH", &minigbm_src_abs)
        .arg("compile")
        .arg("src/virglrenderer")
        .current_dir(out_dir);

    let status = cmd.status()?;
    if !status.success() {
        bail!("meson compile failed with status: {}", status);
    }
    Ok(())
}

fn virglrenderer() -> Result<()> {
    // System provided runtime dependencies.
    pkg_config::Config::new().probe("epoxy")?;
    pkg_config::Config::new().probe("libdrm")?;

    // Use virglrenderer package from the standard system location if available.
    if pkg_config::Config::new().probe("virglrenderer").is_ok() {
        return Ok(());
    }

    // Otherwise build from source.
    let out_dir = PathBuf::from(env::var("OUT_DIR")?);
    let minigbm_out = out_dir.join("minigbm");
    let virglrenderer_out = out_dir.join("virglrenderer");
    build_minigbm(&minigbm_out)?;
    build_virglrenderer(&virglrenderer_out)?;

    println!(
        "cargo:rustc-link-search={}/src",
        virglrenderer_out.display()
    );
    println!("cargo:rustc-link-search={}", minigbm_out.display());
    println!("cargo:rustc-link-lib=static=virglrenderer");
    println!("cargo:rustc-link-lib=static=gbm");
    Ok(())
}

fn main() -> Result<()> {
    #[cfg(feature = "virgl_renderer")]
    virglrenderer()?;

    Ok(())
}
<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core,no_std)]

extern crate core;
extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;

use core::prelude::*;

use hil::Controller;

pub static mut CHIP : Option<sam4l::Sam4l> = None;

pub static mut FIRESTORM : Option<Firestorm> = None;

pub struct Firestorm {
    chip: &'static mut sam4l::Sam4l,
    console: drivers::console::Console<sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static mut hil::gpio::GPIOPin; 14]>
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn with_driver<F, R>(&mut self, driver_num: usize, mut f: F) -> R where
            F: FnMut(Option<&mut hil::Driver>) -> R {

        f(match driver_num {
            0 => Some(&mut self.console),
            1 => Some(&mut self.gpio),
            _ => None
        })
    }

}

pub unsafe fn init() -> &'static mut Firestorm {
    CHIP = Some(sam4l::Sam4l::new());
    let chip = CHIP.as_mut().unwrap();

    let usart3 = &mut chip.usarts[3];
    chip.pb09.configure(Some(sam4l::gpio::PeripheralFunction::A));
    chip.pb10.configure(Some(sam4l::gpio::PeripheralFunction::A));

    FIRESTORM = Some(Firestorm {
        chip: chip,
        console: drivers::console::Console::new(usart3),
        gpio: drivers::gpio::GPIO::new(
            [ &mut chip.pc10, &mut chip.pc19, &mut chip.pc13
            , &mut chip.pa09, &mut chip.pa17, &mut chip.pc20
            , &mut chip.pa19, &mut chip.pa14, &mut chip.pa16
            , &mut chip.pa13, &mut chip.pa11, &mut chip.pa10
            , &mut chip.pa12, &mut chip.pc09])
    });

    let firestorm = FIRESTORM.as_mut().unwrap();

    usart3.configure(sam4l::usart::USARTParams {
        client: &mut firestorm.console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    firestorm.console.initialize();

    firestorm
}

<commit_msg>Cleanup platform initialization<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(core,no_std)]

extern crate core;
extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;

use core::prelude::*;

use hil::Controller;

pub static mut CHIP : Option<sam4l::Sam4l> = None;

pub static mut FIRESTORM : Option<Firestorm> = None;

pub struct Firestorm {
    chip: &'static mut sam4l::Sam4l,
    console: drivers::console::Console<sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static mut hil::gpio::GPIOPin; 14]>
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    pub fn with_driver<F, R>(&mut self, driver_num: usize, mut f: F) -> R where
            F: FnMut(Option<&mut hil::Driver>) -> R {

        f(match driver_num {
            0 => Some(&mut self.console),
            1 => Some(&mut self.gpio),
            _ => None
        })
    }

}

pub unsafe fn init() -> &'static mut Firestorm {
    CHIP = Some(sam4l::Sam4l::new());
    let chip = CHIP.as_mut().unwrap();

    FIRESTORM = Some(Firestorm {
        chip: chip,
        console: drivers::console::Console::new(&mut chip.usarts[3]),
        gpio: drivers::gpio::GPIO::new(
            [ &mut chip.pc10, &mut chip.pc19, &mut chip.pc13
            , &mut chip.pa09, &mut chip.pa17, &mut chip.pc20
            , &mut chip.pa19, &mut chip.pa14, &mut chip.pa16
            , &mut chip.pa13, &mut chip.pa11, &mut chip.pa10
            , &mut chip.pa12, &mut chip.pc09])
    });

    let firestorm : &'static mut Firestorm = FIRESTORM.as_mut().unwrap();

    chip.usarts[3].configure(sam4l::usart::USARTParams {
        client: &mut firestorm.console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    chip.pb09.configure(Some(sam4l::gpio::PeripheralFunction::A));
    chip.pb10.configure(Some(sam4l::gpio::PeripheralFunction::A));

    firestorm.console.initialize();
    firestorm
}

<|endoftext|>


<commit_before>use api::query::Query;

#[derive(Serialize, Deserialize, Debug)]
pub struct ResultRow {
    pub gene_uniquename: String,
    pub sequence: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct QueryAPIResult {
    pub query: Query,
    pub status: String,
    pub rows: Vec<ResultRow>,
}
<commit_msg>Omit the sequence field from output if empty<commit_after>use api::query::Query;

#[derive(Serialize, Deserialize, Debug)]
pub struct ResultRow {
    pub gene_uniquename: String,
    #[serde(skip_serializing_if="Option::is_none")]
    pub sequence: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct QueryAPIResult {
    pub query: Query,
    pub status: String,
    pub rows: Vec<ResultRow>,
}
<|endoftext|>


<commit_before>use prolog::ast::*;
use prolog::builtins::*;
use prolog::codegen::*;
use prolog::heap_iter::*;
use prolog::heap_print::*;
use prolog::fixtures::*;

pub(crate) mod machine_state;

use std::collections::HashMap;
use std::ops::Index;
use std::rc::Rc;
use std::vec::Vec;

pub struct Machine {
    ms: machine_state::MachineState,
    code: Code,
    code_dir: CodeDir,
    op_dir: OpDir,
    cached_query: Option
}

impl Index<CodePtr> for Machine {
    type Output = Line;

    fn index(&self, ptr: CodePtr) -> &Self::Output {
        match ptr {
            CodePtr::TopLevel(_, p) => {
                match &self.cached_query {
                    &Some(ref cq) => &cq[p],
                    &None => panic!("Out-of-bounds top level index.")
                }
            },
            CodePtr::DirEntry(p) => &self.code[p]
        }
    }
}

impl Machine {
    pub fn new() -> Self {
        let (code, code_dir, op_dir) = build_code_dir();

        Machine {
            ms: machine_state::MachineState::new(),
            code: code,
            code_dir: code_dir,
            op_dir: op_dir,
            cached_query: None
        }
    }

    pub fn failed(&self) -> bool {
        self.ms.fail
    }

    fn add_user_code<'a>(&mut self, name: Rc<Atom>, arity: usize, offset: usize) -> EvalSession<'a>
    {
        match self.code_dir.get(&(name.clone(), arity)) {
            Some(&(PredicateKeyType::BuiltIn, _)) =>
                return EvalSession::ImpermissibleEntry(format!("{}/{}", name, arity)),
            _ => {}
        };

        self.code_dir.insert((name, arity), (PredicateKeyType::User, offset));
        EvalSession::EntrySuccess
    }

    pub fn add_fact<'a>(&mut self, fact: &Term, mut code: Code) -> EvalSession<'a>
    {
        match fact {
            &Term::Clause(_, ref name, _) | &Term::Constant(_, Constant::Atom(ref name)) => {
                let p = self.code.len();
                let arity = fact.arity();

                self.code.append(&mut code);
                self.add_user_code(name.clone(), arity, p)
            },
            _ => EvalSession::NamelessEntry
        }
    }

    pub fn add_rule<'a>(&mut self, rule: &Rule, mut code: Code) -> EvalSession<'a>
    {
        match &rule.head.0 {
            &QueryTerm::Term(Term::Clause(_, ref name, _))
          | &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => {
                let p = self.code.len();
                let arity = rule.head.0.arity();

                self.code.append(&mut code);
                self.add_user_code(name.clone(), arity, p)
            },
            _ => EvalSession::NamelessEntry
        }
    }

    pub fn add_predicate<'a>(&mut self, clauses: &Vec<PredicateClause>, mut code: Code)
                             -> EvalSession<'a>
    {
        let p = self.code.len();

        if let Some(ref clause) = clauses.first() {
            if let Some(name) = clause.name() {
                let arity = clause.arity();

                self.code.append(&mut code);
                self.add_user_code(name.clone(), arity, p)
            } else {
                EvalSession::NamelessEntry
            }
        } else {
            EvalSession::ImpermissibleEntry(String::from("predicate must have clauses."))
        }
    }

    fn cached_query_size(&self) -> usize {
        match &self.cached_query {
            &Some(ref query) => query.len(),
            _ => 0
        }
    }

    fn execute_instr(&mut self)
    {
        let instr = match self.ms.p {
            CodePtr::TopLevel(_, p) => {
                match &self.cached_query {
                    &Some(ref cq) => &cq[p],
                    &None => return
                }
            },
            CodePtr::DirEntry(p) => &self.code[p]
        };

        match instr {
            &Line::Arithmetic(ref arith_instr) =>
                self.ms.execute_arith_instr(arith_instr),
            &Line::BuiltIn(ref built_in_instr) =>
                self.ms.execute_built_in_instr(&self.code_dir, built_in_instr),
            &Line::Choice(ref choice_instr) =>
                self.ms.execute_choice_instr(choice_instr),
            &Line::Cut(ref cut_instr) =>
                self.ms.execute_cut_instr(cut_instr),
            &Line::Control(ref control_instr) =>
                self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
            &Line::Fact(ref fact) => {
                for fact_instr in fact {
                    if self.failed() {
                        break;
                    }

                    self.ms.execute_fact_instr(&fact_instr);
                }

                self.ms.p += 1;
            },
            &Line::Indexing(ref indexing_instr) =>
                self.ms.execute_indexing_instr(&indexing_instr),
            &Line::IndexedChoice(ref choice_instr) =>
                self.ms.execute_indexed_choice_instr(choice_instr),
            &Line::Query(ref query) => {
                for query_instr in query {
                    if self.failed() {
                        break;
                    }

                    self.ms.execute_query_instr(&query_instr);
                }

                self.ms.p += 1;
            }
        }
    }

    fn backtrack(&mut self)
    {
        if self.ms.b > 0 {
            let b = self.ms.b - 1;

            self.ms.b0 = self.ms.or_stack[b].b0;
            self.ms.p  = self.ms.or_stack[b].bp;

            if let CodePtr::TopLevel(_, p) = self.ms.p {
                self.ms.fail = p == 0;
            } else {
                self.ms.fail = false;
            }
        } else {
            self.ms.p = CodePtr::TopLevel(0, 0);
        }
    }

    fn query_stepper<'a>(&mut self)
    {
        loop
        {
            self.execute_instr();

            if self.failed() {
                self.backtrack();
            }

            match self.ms.p {
                CodePtr::DirEntry(p) if p < self.code.len() => {},
                _ => break
            };
        }
    }

    fn record_var_places<'a>(&self,
                             chunk_num: usize,
                             alloc_locs: &AllocVarDict<'a>,
                             heap_locs: &mut HeapVarDict<'a>)
    {
        for (var, var_data) in alloc_locs {
            match var_data {
                &VarData::Perm(_) => {
                    let e = self.ms.e;

                    let r = var_data.as_reg_type().reg_num();
                    let addr = self.ms.and_stack[e][r].clone();

                    heap_locs.insert(var, addr);
                },
                &VarData::Temp(cn, _, _) if cn == chunk_num => {
                    let r = var_data.as_reg_type();
                    let addr = self.ms[r].clone();

                    heap_locs.insert(var, addr);
                },
                _ => {}
            }
        }
    }

    fn run_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
    {
        let end_ptr = CodePtr::TopLevel(0, self.cached_query_size());

        while self.ms.p < end_ptr {
            if let CodePtr::TopLevel(mut cn, p) = self.ms.p {
                match &self[CodePtr::TopLevel(cn, p)] {
                    &Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
                        self.record_var_places(cn, alloc_locs, heap_locs);
                        cn += 1;
                    },
                    _ => {}
                }

                self.ms.p = CodePtr::TopLevel(cn, p);
            }

            self.query_stepper();

            match self.ms.p {
                CodePtr::TopLevel(_, p) if p > 0 => {},
                _ => break
            };
        }
    }

    fn fail<'a>(&mut self) -> EvalSession<'a>
    {
        if self.ms.ball.1.len() > 0 {
            let h = self.ms.heap.h;
            self.ms.copy_and_align_ball_to_heap();

            EvalSession::QueryFailureWithException(self.print_term(&Addr::HeapCell(h)))
        } else {
            EvalSession::QueryFailure
        }
    }

    pub fn submit_decl<'a>(&mut self, decl: &Declaration) -> EvalSession<'a>
    {
        match decl {
            &Declaration::Op(prec, spec, ref name) => {
                if is_infix!(spec) {
                    match self.op_dir.get(&(name.clone(), Fixity::Post)) {
                        Some(_) => return EvalSession::OpIsInfixAndPostFix,
                        _ => {}
                    };
                }

                if is_postfix!(spec) {
                    match self.op_dir.get(&(name.clone(), Fixity::In)) {
                        Some(_) => return EvalSession::OpIsInfixAndPostFix,
                        _ => {}
                    };
                }

                if prec > 0 {
                    match spec {
                        XFY | XFX | YFX => self.op_dir.insert((name.clone(), Fixity::In),
                                                              (spec, prec)),
                        XF | YF => self.op_dir.insert((name.clone(), Fixity::Post), (spec, prec)),
                        FX | FY => self.op_dir.insert((name.clone(), Fixity::Pre), (spec,prec)),
                        _ => None
                    };
                } else {
                    self.op_dir.remove(&(name.clone(), Fixity::Pre));
                    self.op_dir.remove(&(name.clone(), Fixity::In));
                    self.op_dir.remove(&(name.clone(), Fixity::Post));
                }

                EvalSession::EntrySuccess
            }
        }
    }

    pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalSession<'a>
    {
        let mut heap_locs = HashMap::new();

        self.cached_query = Some(code);
        self.run_query(&alloc_locs, &mut heap_locs);

        if self.failed() {
            self.fail()
        } else {
            EvalSession::InitialQuerySuccess(alloc_locs, heap_locs)
        }
    }

    pub fn continue_query<'a>(&mut self, alloc_l: &AllocVarDict<'a>, heap_l: &mut HeapVarDict<'a>)
                              -> EvalSession<'a>
    {
        if !self.or_stack_is_empty() {
            let b = self.ms.b - 1;
            self.ms.p = self.ms.or_stack[b].bp;

            if let CodePtr::TopLevel(_, 0) = self.ms.p {
                return EvalSession::QueryFailure;
            }

            self.run_query(alloc_l, heap_l);

            if self.failed() {
                self.fail()
            } else {
                EvalSession::SubsequentQuerySuccess
            }
        } else {
            EvalSession::QueryFailure
        }
    }

    fn print_var(&self, r: Ref) -> String
    {
        let disp = DisplayFormatter {};
        let iter = HeapCellIterator::new(&self.ms, r);

        let mut printer = HeapCellPrinter::new(iter, disp);

        printer.print()
    }

    // NEW ---
    fn print_term(&self, addr: &Addr) -> String
    {
        match addr {
            &Addr::Con(ref c) =>
                format!("{}", c),
            &Addr::Lis(h) | &Addr::HeapCell(h) | &Addr::Str(h) =>
                self.print_var(Ref::HeapCell(h)),
            &Addr::StackCell(fr, sc) =>
                self.print_var(Ref::StackCell(fr, sc))
        }
    }

/*
    fn print_term(&self, addr: &Addr) -> String
    {
        let mut viewer = HeapCellViewer::new(&self.ms.heap,
                                             &self.ms.and_stack,
                                             addr);

        let mut result = String::new();

        while let Some(view) = viewer.next() {
            match view {
                CellView::Con(ref r) =>
                    result += format!("{}", r).as_str(),
                CellView::HeapVar(cell_num) => {
                    result += "_";
                    result += cell_num.to_string().as_str();
                },
                CellView::StackVar(_, cell_num) => {
                    result += "s_";
                    result += cell_num.to_string().as_str();
                },
                CellView::Str(_, ref name) =>
                    result += name.as_str(),
                CellView::TToken(TToken::Bar) => {
                    match viewer.peek() {
                        Some(CellView::Con(&Constant::EmptyList)) => {
                            viewer.next();
                        },
                        Some(CellView::TToken(TToken::LSBracket(loc))) => {
                            result += ", ";

                            viewer.next();
                            viewer.remove_token(loc);
                        },
                        _ => result += " | "
                    };
                },
                CellView::TToken(token) =>
                    result += token.as_str()
            };
        }

        result
    }
*/
    pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
        let mut result = String::new();

        for (var, addr) in var_dir {
            if result != "" {
                result += "\n\r";
            }

            result += var.as_str();
            result += " = ";

            result += self.print_term(addr).as_str();
        }

        result
    }

    pub fn or_stack_is_empty(&self) -> bool {
        self.ms.b == 0
    }

    pub fn clear(&mut self) {
        self.reset();
        self.code.clear();
        self.code_dir.clear();
    }

    pub fn reset(&mut self) {
        self.ms.reset();
    }

    pub fn op_dir(&self) -> &OpDir {
        &self.op_dir
    }
}

<commit_msg>remove commented out print_term<commit_after>use prolog::ast::*;
use prolog::builtins::*;
use prolog::codegen::*;
use prolog::heap_iter::*;
use prolog::heap_print::*;
use prolog::fixtures::*;

pub(crate) mod machine_state;

use std::collections::HashMap;
use std::ops::Index;
use std::rc::Rc;
use std::vec::Vec;

pub struct Machine {
    ms: machine_state::MachineState,
    code: Code,
    code_dir: CodeDir,
    op_dir: OpDir,
    cached_query: Option
}

impl Index<CodePtr> for Machine {
    type Output = Line;

    fn index(&self, ptr: CodePtr) -> &Self::Output {
        match ptr {
            CodePtr::TopLevel(_, p) => {
                match &self.cached_query {
                    &Some(ref cq) => &cq[p],
                    &None => panic!("Out-of-bounds top level index.")
                }
            },
            CodePtr::DirEntry(p) => &self.code[p]
        }
    }
}

impl Machine {
    pub fn new() -> Self {
        let (code, code_dir, op_dir) = build_code_dir();

        Machine {
            ms: machine_state::MachineState::new(),
            code: code,
            code_dir: code_dir,
            op_dir: op_dir,
            cached_query: None
        }
    }

    pub fn failed(&self) -> bool {
        self.ms.fail
    }

    fn add_user_code<'a>(&mut self, name: Rc<Atom>, arity: usize, offset: usize) -> EvalSession<'a>
    {
        match self.code_dir.get(&(name.clone(), arity)) {
            Some(&(PredicateKeyType::BuiltIn, _)) =>
                return EvalSession::ImpermissibleEntry(format!("{}/{}", name, arity)),
            _ => {}
        };

        self.code_dir.insert((name, arity), (PredicateKeyType::User, offset));
        EvalSession::EntrySuccess
    }

    pub fn add_fact<'a>(&mut self, fact: &Term, mut code: Code) -> EvalSession<'a>
    {
        match fact {
            &Term::Clause(_, ref name, _) | &Term::Constant(_, Constant::Atom(ref name)) => {
                let p = self.code.len();
                let arity = fact.arity();

                self.code.append(&mut code);
                self.add_user_code(name.clone(), arity, p)
            },
            _ => EvalSession::NamelessEntry
        }
    }

    pub fn add_rule<'a>(&mut self, rule: &Rule, mut code: Code) -> EvalSession<'a>
    {
        match &rule.head.0 {
            &QueryTerm::Term(Term::Clause(_, ref name, _))
          | &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => {
                let p = self.code.len();
                let arity = rule.head.0.arity();

                self.code.append(&mut code);
                self.add_user_code(name.clone(), arity, p)
            },
            _ => EvalSession::NamelessEntry
        }
    }

    pub fn add_predicate<'a>(&mut self, clauses: &Vec<PredicateClause>, mut code: Code)
                             -> EvalSession<'a>
    {
        let p = self.code.len();

        if let Some(ref clause) = clauses.first() {
            if let Some(name) = clause.name() {
                let arity = clause.arity();

                self.code.append(&mut code);
                self.add_user_code(name.clone(), arity, p)
            } else {
                EvalSession::NamelessEntry
            }
        } else {
            EvalSession::ImpermissibleEntry(String::from("predicate must have clauses."))
        }
    }

    fn cached_query_size(&self) -> usize {
        match &self.cached_query {
            &Some(ref query) => query.len(),
            _ => 0
        }
    }

    fn execute_instr(&mut self)
    {
        let instr = match self.ms.p {
            CodePtr::TopLevel(_, p) => {
                match &self.cached_query {
                    &Some(ref cq) => &cq[p],
                    &None => return
                }
            },
            CodePtr::DirEntry(p) => &self.code[p]
        };

        match instr {
            &Line::Arithmetic(ref arith_instr) =>
                self.ms.execute_arith_instr(arith_instr),
            &Line::BuiltIn(ref built_in_instr) =>
                self.ms.execute_built_in_instr(&self.code_dir, built_in_instr),
            &Line::Choice(ref choice_instr) =>
                self.ms.execute_choice_instr(choice_instr),
            &Line::Cut(ref cut_instr) =>
                self.ms.execute_cut_instr(cut_instr),
            &Line::Control(ref control_instr) =>
                self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
            &Line::Fact(ref fact) => {
                for fact_instr in fact {
                    if self.failed() {
                        break;
                    }

                    self.ms.execute_fact_instr(&fact_instr);
                }

                self.ms.p += 1;
            },
            &Line::Indexing(ref indexing_instr) =>
                self.ms.execute_indexing_instr(&indexing_instr),
            &Line::IndexedChoice(ref choice_instr) =>
                self.ms.execute_indexed_choice_instr(choice_instr),
            &Line::Query(ref query) => {
                for query_instr in query {
                    if self.failed() {
                        break;
                    }

                    self.ms.execute_query_instr(&query_instr);
                }

                self.ms.p += 1;
            }
        }
    }

    fn backtrack(&mut self)
    {
        if self.ms.b > 0 {
            let b = self.ms.b - 1;

            self.ms.b0 = self.ms.or_stack[b].b0;
            self.ms.p  = self.ms.or_stack[b].bp;

            if let CodePtr::TopLevel(_, p) = self.ms.p {
                self.ms.fail = p == 0;
            } else {
                self.ms.fail = false;
            }
        } else {
            self.ms.p = CodePtr::TopLevel(0, 0);
        }
    }

    fn query_stepper<'a>(&mut self)
    {
        loop
        {
            self.execute_instr();

            if self.failed() {
                self.backtrack();
            }

            match self.ms.p {
                CodePtr::DirEntry(p) if p < self.code.len() => {},
                _ => break
            };
        }
    }

    fn record_var_places<'a>(&self,
                             chunk_num: usize,
                             alloc_locs: &AllocVarDict<'a>,
                             heap_locs: &mut HeapVarDict<'a>)
    {
        for (var, var_data) in alloc_locs {
            match var_data {
                &VarData::Perm(_) => {
                    let e = self.ms.e;

                    let r = var_data.as_reg_type().reg_num();
                    let addr = self.ms.and_stack[e][r].clone();

                    heap_locs.insert(var, addr);
                },
                &VarData::Temp(cn, _, _) if cn == chunk_num => {
                    let r = var_data.as_reg_type();
                    let addr = self.ms[r].clone();

                    heap_locs.insert(var, addr);
                },
                _ => {}
            }
        }
    }

    fn run_query<'a>(&mut self, alloc_locs: &AllocVarDict<'a>, heap_locs: &mut HeapVarDict<'a>)
    {
        let end_ptr = CodePtr::TopLevel(0, self.cached_query_size());

        while self.ms.p < end_ptr {
            if let CodePtr::TopLevel(mut cn, p) = self.ms.p {
                match &self[CodePtr::TopLevel(cn, p)] {
                    &Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
                        self.record_var_places(cn, alloc_locs, heap_locs);
                        cn += 1;
                    },
                    _ => {}
                }

                self.ms.p = CodePtr::TopLevel(cn, p);
            }

            self.query_stepper();

            match self.ms.p {
                CodePtr::TopLevel(_, p) if p > 0 => {},
                _ => break
            };
        }
    }

    fn fail<'a>(&mut self) -> EvalSession<'a>
    {
        if self.ms.ball.1.len() > 0 {
            let h = self.ms.heap.h;
            self.ms.copy_and_align_ball_to_heap();

            EvalSession::QueryFailureWithException(self.print_term(&Addr::HeapCell(h)))
        } else {
            EvalSession::QueryFailure
        }
    }

    pub fn submit_decl<'a>(&mut self, decl: &Declaration) -> EvalSession<'a>
    {
        match decl {
            &Declaration::Op(prec, spec, ref name) => {
                if is_infix!(spec) {
                    match self.op_dir.get(&(name.clone(), Fixity::Post)) {
                        Some(_) => return EvalSession::OpIsInfixAndPostFix,
                        _ => {}
                    };
                }

                if is_postfix!(spec) {
                    match self.op_dir.get(&(name.clone(), Fixity::In)) {
                        Some(_) => return EvalSession::OpIsInfixAndPostFix,
                        _ => {}
                    };
                }

                if prec > 0 {
                    match spec {
                        XFY | XFX | YFX => self.op_dir.insert((name.clone(), Fixity::In),
                                                              (spec, prec)),
                        XF | YF => self.op_dir.insert((name.clone(), Fixity::Post), (spec, prec)),
                        FX | FY => self.op_dir.insert((name.clone(), Fixity::Pre), (spec,prec)),
                        _ => None
                    };
                } else {
                    self.op_dir.remove(&(name.clone(), Fixity::Pre));
                    self.op_dir.remove(&(name.clone(), Fixity::In));
                    self.op_dir.remove(&(name.clone(), Fixity::Post));
                }

                EvalSession::EntrySuccess
            }
        }
    }

    pub fn submit_query<'a>(&mut self, code: Code, alloc_locs: AllocVarDict<'a>) -> EvalSession<'a>
    {
        let mut heap_locs = HashMap::new();

        self.cached_query = Some(code);
        self.run_query(&alloc_locs, &mut heap_locs);

        if self.failed() {
            self.fail()
        } else {
            EvalSession::InitialQuerySuccess(alloc_locs, heap_locs)
        }
    }

    pub fn continue_query<'a>(&mut self, alloc_l: &AllocVarDict<'a>, heap_l: &mut HeapVarDict<'a>)
                              -> EvalSession<'a>
    {
        if !self.or_stack_is_empty() {
            let b = self.ms.b - 1;
            self.ms.p = self.ms.or_stack[b].bp;

            if let CodePtr::TopLevel(_, 0) = self.ms.p {
                return EvalSession::QueryFailure;
            }

            self.run_query(alloc_l, heap_l);

            if self.failed() {
                self.fail()
            } else {
                EvalSession::SubsequentQuerySuccess
            }
        } else {
            EvalSession::QueryFailure
        }
    }

    fn print_var(&self, r: Ref) -> String
    {
        let disp = DisplayFormatter {};
        let iter = HeapCellIterator::new(&self.ms, r);

        let mut printer = HeapCellPrinter::new(iter, disp);

        printer.print()
    }

    // NEW ---
    fn print_term(&self, addr: &Addr) -> String
    {
        match addr {
            &Addr::Con(ref c) =>
                format!("{}", c),
            &Addr::Lis(h) | &Addr::HeapCell(h) | &Addr::Str(h) =>
                self.print_var(Ref::HeapCell(h)),
            &Addr::StackCell(fr, sc) =>
                self.print_var(Ref::StackCell(fr, sc))
        }
    }

    pub fn heap_view(&self, var_dir: &HeapVarDict) -> String {
        let mut result = String::new();

        for (var, addr) in var_dir {
            if result != "" {
                result += "\n\r";
            }

            result += var.as_str();
            result += " = ";

            result += self.print_term(addr).as_str();
        }

        result
    }

    pub fn or_stack_is_empty(&self) -> bool {
        self.ms.b == 0
    }

    pub fn clear(&mut self) {
        self.reset();
        self.code.clear();
        self.code_dir.clear();
    }

    pub fn reset(&mut self) {
        self.ms.reset();
    }

    pub fn op_dir(&self) -> &OpDir {
        &self.op_dir
    }
}
<|endoftext|>