<commit_before>use crate::utils::schemas;
use derivative::Derivative;
use eyre::Result;
use petgraph::{graph::NodeIndex, stable_graph::StableGraph};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{
    collections::HashMap,
    path::{Path, PathBuf},
};
use strum::{Display, EnumString};

/// A resource in a dependency graph (the nodes of the graph)
#[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
#[serde(tag = "type")]
pub enum Resource {
    /// A symbol within code, within a project file
    Symbol(resources::Symbol),

    /// A node within a project file
    Node(resources::Node),

    /// A file within the project
    File(resources::File),

    /// A declared project `Source`
    Source(resources::Source),

    /// A programming language module, usually part of an external package
    Module(resources::Module),

    /// A URL to a remote resource
    Url(resources::Url),
}

pub mod resources {
    use std::path::{Path, PathBuf};

    use super::*;
    #[derive(Debug, Clone, Derivative, JsonSchema, Serialize)]
    #[derivative(PartialEq, Eq, Hash)]
    #[schemars(deny_unknown_fields)]
    pub struct Symbol {
        /// The path of the file that the symbol is defined in
        pub path: PathBuf,

        /// The name/identifier of the symbol
        pub name: String,

        /// The kind of the object that the symbol refers to
        ///
        /// Should be used as a hint only, and as such is excluded from
        /// equality and hash functions.
        #[derivative(PartialEq = "ignore")]
        #[derivative(Hash = "ignore")]
        pub kind: String,
    }

    /// Create a new `Symbol` resource
    pub fn symbol(path: &Path, name: &str, kind: &str) -> Resource {
        Resource::Symbol(Symbol {
            path: path.to_path_buf(),
            name: name.into(),
            kind: kind.into(),
        })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Node {
        /// The path of the file that the node is defined in
        pub path: PathBuf,

        /// The address of the node
        pub address: String,

        /// The type of node e.g. "CodeChunk"
        pub kind: String,
    }

    /// Create a new `Symbol` resource
    pub fn node(path: &Path, address: &str, kind: &str) -> Resource {
        Resource::Node(Node {
            path: path.to_path_buf(),
            address: address.into(),
            kind: kind.into(),
        })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct File {
        /// The path of the file
        pub path: PathBuf,
    }

    /// Create a new `File` resource
    pub fn file(path: &Path) -> Resource {
        Resource::File(File {
            path: path.to_path_buf(),
        })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Source {
        /// The name of the project source
        pub name: String,
    }

    /// Create a new `Source` resource
    pub fn source(name: &str) -> Resource {
        Resource::Source(Source { name: name.into() })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Module {
        /// The programming language of the module
        pub language: String,

        /// The name of the module
        pub name: String,
    }

    /// Create a new `Module` resource
    pub fn module(language: &str, name: &str) -> Resource {
        Resource::Module(Module {
            language: language.into(),
            name: name.into(),
        })
    }

    #[derive(Debug, Clone, Default, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Url {
        /// The URL of the external resource
        pub url: String,
    }

    /// Create a new `Url` resource
    pub fn url(url: &str) -> Resource {
        Resource::Url(Url { url: url.into() })
    }
}

/// The relation between two resources in a dependency graph (the edges of the graph)
#[derive(
    Debug, Display, Clone, PartialEq, Eq, Hash, EnumString, JsonSchema, Serialize, Deserialize,
)]
#[serde(rename_all = "camelCase")]
pub enum Relation {
    Assigns,
    Embeds,
    Imports,
    Includes,
    Links,
    Reads,
    Uses,
    Writes,
}

/// The direction to represent the flow of information from subject to object.
pub enum Direction {
    From,
    To,
}

/// Get the the `Direction` for a `Relation`
pub fn direction(relation: &Relation) -> Direction {
    match relation {
        Relation::Assigns => Direction::To,
        Relation::Embeds => Direction::From,
        Relation::Imports => Direction::From,
        Relation::Includes => Direction::From,
        Relation::Links => Direction::To,
        Relation::Reads => Direction::From,
        Relation::Uses => Direction::From,
        Relation::Writes => Direction::To,
    }
}

/// A subject-relation-object triple
pub type Triple = (Resource, Relation, Resource);

/// A project dependency graph
#[derive(Debug, Default, Clone, Serialize)]
pub struct Graph {
    /// The graph itself
    ///
    /// Use a `petgraph::StableGraph` so that nodes can be added and removed
    /// without changing node indices.
    #[serde(flatten)]
    graph: StableGraph<Resource, Relation>,

    /// Indices of the nodes in the tree
    ///
    /// This is necessary to keep track of which resources
    /// are already in the graph and re-use their index if they are.
    #[serde(skip)]
    indices: HashMap<Resource, NodeIndex>,
}

impl Graph {
    /// Create a new graph
    pub fn new() -> Graph {
        Graph {
            indices: HashMap::new(),
            graph: StableGraph::new(),
        }
    }

    /// Add a triple to the graph
    pub fn add_triple(&mut self, (subject, relation, object): Triple) {
        let subject = if let Some(index) = self.indices.get(&subject) {
            *index
        } else {
            let index = self.graph.add_node(subject.clone());
            self.indices.insert(subject, index);
            index
        };

        let object = if let Some(index) = self.indices.get(&object) {
            *index
        } else {
            let index = self.graph.add_node(object.clone());
            self.indices.insert(object, index);
            index
        };

        let (from, to) = match direction(&relation) {
            Direction::From => (object, subject),
            Direction::To => (subject, object),
        };

        self.graph.add_edge(from, to, relation);
    }

    /// Convert the graph to a visualization nodes and edges
    pub fn to_dot(&self, base_path: &Path) -> String {
        let nodes = self
            .indices
            .iter()
            .map(|(resource, node)| {
                let index = node.index();

                let (shape, fill_color, label) = match resource {
                    Resource::Symbol(symbol) => ("diamond", "#efb8b8", symbol.name.clone()),
                    Resource::Node(node) => (
                        "box",
                        "#efe0b8",
                        format!("{}\\n{}", node.kind, node.address),
                    ),
                    Resource::File(file) => {
                        ("note", "#d1efb8", file.path.to_string_lossy().to_string())
                    }
                    Resource::Source(source) => ("house", "#efb8d4", source.name.clone()),
                    Resource::Module(module) => ("invhouse", "#b8efed", module.name.clone()),
                    Resource::Url(url) => ("box", "#cab8ef", url.url.clone()),
                };

                let node = match resource {
                    Resource::File(..) => {
                        format!(r#"  n{index} [style=invis]"#, index = index,)
                    }
                    _ => format!(
                        r#"  n{index} [shape="{shape}" fillcolor="{fill_color}" label="{label}"]"#,
                        index = index,
                        shape = shape,
                        fill_color = fill_color,
                        label = label.replace('\"', "\\\"")
                    ),
                };

                let path = match resource {
                    Resource::Symbol(symbol) => symbol.path.clone(),
                    Resource::Node(node) => node.path.clone(),
                    Resource::File(file) => file.path.clone(),
                    _ => PathBuf::new(),
                };
                let path = pathdiff::diff_paths(path, base_path)
                    .unwrap_or_default()
                    .to_string_lossy()
                    .to_string();

                (path, node)
            })
            .collect::<Vec<(String, String)>>();

        let mut clusters: HashMap<String, Vec<String>> = HashMap::new();
        for (path, node) in nodes {
            clusters.entry(path).or_default().push(node)
        }

        let path_to_cluster = |path: &Path| {
            clusters
                .keys()
                .position(|key| {
                    *key == pathdiff::diff_paths(path, base_path)
                        .unwrap_or_default()
                        .to_string_lossy()
                        .to_string()
                })
                .unwrap_or(0)
        };

        let subgraphs = clusters
            .iter()
            .enumerate()
            .map(|(index, (label, nodes))| {
                if label.is_empty() {
                    nodes.join("\n")
                } else {
                    [
                        &format!("  subgraph cluster{} {{\n", index),
                        &format!("    label=\"{}\" fillcolor=\"#d1efb8\"\n  ", label),
                        &nodes.join("\n  "),
                        "\n  }",
                    ]
                    .concat()
                }
            })
            .collect::<Vec<String>>()
            .join("\n");

        let edges = self
            .graph
            .edge_indices()
            .filter_map(|edge| {
                if let (Some((from, to)), Some(relation)) = (
                    self.graph.edge_endpoints(edge),
                    self.graph.edge_weight(edge),
                ) {
                    let ltail = if let Some(Resource::File(file)) = self.graph.node_weight(from) {
                        format!(" ltail=\"cluster{}\"", path_to_cluster(&file.path))
                    } else {
                        "".to_string()
                    };

                    let lhead = if let Some(Resource::File(file)) = self.graph.node_weight(to) {
                        format!(" lhead=\"cluster{}\"", path_to_cluster(&file.path))
                    } else {
                        "".to_string()
                    };

                    Some(format!(
                        r#"  n{from} -> n{to} [label="{label}"{ltail}{lhead}]"#,
                        from = from.index(),
                        to = to.index(),
                        ltail = ltail,
                        lhead = lhead,
                        label = relation.to_string(),
                    ))
                } else {
                    None
                }
            })
            .collect::<Vec<String>>()
            .join("\n");

        format!(
            r#"digraph {{
  graph [rankdir=LR compound=true fontname=Helvetica fontsize=12 labeljust=l color=gray]
  node [style=filled fontname=Helvetica fontsize=11]
  edge [fontname=Helvetica fontsize=10]

{subgraphs}

{edges}
}}
"#,
            subgraphs = subgraphs,
            edges = edges
        )
    }
}

/// Get JSON Schemas for this modules
pub fn schemas() -> Result<serde_json::Value> {
    let schemas = serde_json::Value::Array(vec![
        schemas::generate::<Resource>()?,
        schemas::generate::<Relation>()?,
        serde_json::json!({
            "$id": "Triple",
            "title": "Triple",
            "description": "A subject-relation-object triple",
            "type" : "array",
            "items": [
                {
                    "tsType": "Resource"
                },
                {
                    "tsType": "Relation"
                },
                {
                    "tsType": "Resource"
                }
            ],
            "minItems": 3,
            "maxItems": 3
        }),
        serde_json::json!({
            "$id": "Graph",
            "title": "Graph",
            "description": "A project dependency graph",
            "type" : "object",
            "required": ["nodes", "edges"],
            "properties": {
                "nodes": {
                    "description": "The resources in the graph",
                    "type": "array",
                    "items": {
                        "tsType": "Resource",
                        "isRequired": true
                    }
                },
                "edges": {
                    "description": "The relations between resources in the graph",
                    "type": "array",
                    "items": {
                        "type": "array",
                        "items": [
                            {
                                "type": "integer"
                            },
                            {
                                "type": "integer"
                            },
                            {
                                "tsType": "Relation"
                            }
                        ],
                        "minItems": 3,
                        "maxItems": 3
                    }
                }
            },
            "additionalProperties": false
        }),
    ]);
    Ok(schemas)
}
<commit_msg>refactor(Project graph): Show free standing files<commit_after>use crate::utils::schemas;
use derivative::Derivative;
use eyre::Result;
use petgraph::{graph::NodeIndex, stable_graph::StableGraph};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{
    collections::HashMap,
    path::{Path, PathBuf},
};
use strum::{Display, EnumString};

/// A resource in a dependency graph (the nodes of the graph)
#[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
#[serde(tag = "type")]
pub enum Resource {
    /// A symbol within code, within a project file
    Symbol(resources::Symbol),

    /// A node within a project file
    Node(resources::Node),

    /// A file within the project
    File(resources::File),

    /// A declared project `Source`
    Source(resources::Source),

    /// A programming language module, usually part of an external package
    Module(resources::Module),

    /// A URL to a remote resource
    Url(resources::Url),
}

pub mod resources {
    use std::path::{Path, PathBuf};

    use super::*;
    #[derive(Debug, Clone, Derivative, JsonSchema, Serialize)]
    #[derivative(PartialEq, Eq, Hash)]
    #[schemars(deny_unknown_fields)]
    pub struct Symbol {
        /// The path of the file that the symbol is defined in
        pub path: PathBuf,

        /// The name/identifier of the symbol
        pub name: String,

        /// The kind of the object that the symbol refers to
        ///
        /// Should be used as a hint only, and as such is excluded from
        /// equality and hash functions.
        #[derivative(PartialEq = "ignore")]
        #[derivative(Hash = "ignore")]
        pub kind: String,
    }

    /// Create a new `Symbol` resource
    pub fn symbol(path: &Path, name: &str, kind: &str) -> Resource {
        Resource::Symbol(Symbol {
            path: path.to_path_buf(),
            name: name.into(),
            kind: kind.into(),
        })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Node {
        /// The path of the file that the node is defined in
        pub path: PathBuf,

        /// The address of the node
        pub address: String,

        /// The type of node e.g. "CodeChunk"
        pub kind: String,
    }

    /// Create a new `Symbol` resource
    pub fn node(path: &Path, address: &str, kind: &str) -> Resource {
        Resource::Node(Node {
            path: path.to_path_buf(),
            address: address.into(),
            kind: kind.into(),
        })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct File {
        /// The path of the file
        pub path: PathBuf,
    }

    /// Create a new `File` resource
    pub fn file(path: &Path) -> Resource {
        Resource::File(File {
            path: path.to_path_buf(),
        })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Source {
        /// The name of the project source
        pub name: String,
    }

    /// Create a new `Source` resource
    pub fn source(name: &str) -> Resource {
        Resource::Source(Source { name: name.into() })
    }

    #[derive(Debug, Clone, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Module {
        /// The programming language of the module
        pub language: String,

        /// The name of the module
        pub name: String,
    }

    /// Create a new `Module` resource
    pub fn module(language: &str, name: &str) -> Resource {
        Resource::Module(Module {
            language: language.into(),
            name: name.into(),
        })
    }

    #[derive(Debug, Clone, Default, PartialEq, Eq, Hash, JsonSchema, Serialize)]
    #[schemars(deny_unknown_fields)]
    pub struct Url {
        /// The URL of the external resource
        pub url: String,
    }

    /// Create a new `Url` resource
    pub fn url(url: &str) -> Resource {
        Resource::Url(Url { url: url.into() })
    }
}

/// The relation between two resources in a dependency graph (the edges of the graph)
#[derive(
    Debug, Display, Clone, PartialEq, Eq, Hash, EnumString, JsonSchema, Serialize, Deserialize,
)]
#[serde(rename_all = "camelCase")]
pub enum Relation {
    Assigns,
    Embeds,
    Imports,
    Includes,
    Links,
    Reads,
    Uses,
    Writes,
}

/// The direction to represent the flow of information from subject to object.
pub enum Direction {
    From,
    To,
}

/// Get the the `Direction` for a `Relation`
pub fn direction(relation: &Relation) -> Direction {
    match relation {
        Relation::Assigns => Direction::To,
        Relation::Embeds => Direction::From,
        Relation::Imports => Direction::From,
        Relation::Includes => Direction::From,
        Relation::Links => Direction::To,
        Relation::Reads => Direction::From,
        Relation::Uses => Direction::From,
        Relation::Writes => Direction::To,
    }
}

/// A subject-relation-object triple
pub type Triple = (Resource, Relation, Resource);

/// A project dependency graph
#[derive(Debug, Default, Clone, Serialize)]
pub struct Graph {
    /// The graph itself
    ///
    /// Use a `petgraph::StableGraph` so that nodes can be added and removed
    /// without changing node indices.
    #[serde(flatten)]
    graph: StableGraph<Resource, Relation>,

    /// Indices of the nodes in the tree
    ///
    /// This is necessary to keep track of which resources
    /// are already in the graph and re-use their index if they are.
    #[serde(skip)]
    indices: HashMap<Resource, NodeIndex>,
}

impl Graph {
    /// Create a new graph
    pub fn new() -> Graph {
        Graph {
            indices: HashMap::new(),
            graph: StableGraph::new(),
        }
    }

    /// Add a triple to the graph
    pub fn add_triple(&mut self, (subject, relation, object): Triple) {
        let subject = if let Some(index) = self.indices.get(&subject) {
            *index
        } else {
            let index = self.graph.add_node(subject.clone());
            self.indices.insert(subject, index);
            index
        };

        let object = if let Some(index) = self.indices.get(&object) {
            *index
        } else {
            let index = self.graph.add_node(object.clone());
            self.indices.insert(object, index);
            index
        };

        let (from, to) = match direction(&relation) {
            Direction::From => (object, subject),
            Direction::To => (subject, object),
        };

        self.graph.add_edge(from, to, relation);
    }

    /// Convert the graph to a visualization nodes and edges
    pub fn to_dot(&self, base_path: &Path) -> String {
        let nodes = self
            .indices
            .iter()
            .map(|(resource, node)| {
                let index = node.index();

                let path = match resource {
                    Resource::Symbol(symbol) => symbol.path.clone(),
                    Resource::Node(node) => node.path.clone(),
                    Resource::File(file) => file.path.clone(),
                    _ => PathBuf::new(),
                };
                let path = pathdiff::diff_paths(&path, base_path)
                    .unwrap_or_default()
                    .to_string_lossy()
                    .to_string();

                let (shape, fill_color, label) = match resource {
                    Resource::Symbol(symbol) => ("diamond", "#efb8b8", symbol.name.clone()),
                    Resource::Node(node) => (
                        "box",
                        "#efe0b8",
                        format!("{}\\n{}", node.kind, node.address),
                    ),
                    Resource::File(..) => ("note", "#d1efb8", path.clone()),
                    Resource::Source(source) => ("house", "#efb8d4", source.name.clone()),
                    Resource::Module(module) => ("invhouse", "#b8efed", module.name.clone()),
                    Resource::Url(url) => ("box", "#cab8ef", url.url.clone()),
                };

                let node = match resource {
                    Resource::File(..) => format!(
                        r#"  n{index} [shape="point", style="invis" label="{label}"]"#,
                        index = index,
                        label = label
                    ),
                    _ => format!(
                        r#"  n{index} [shape="{shape}" fillcolor="{fill_color}" label="{label}"]"#,
                        index = index,
                        shape = shape,
                        fill_color = fill_color,
                        label = label.replace('\"', "\\\"")
                    ),
                };

                (path, node)
            })
            .collect::<Vec<(String, String)>>();

        let mut clusters: HashMap<String, Vec<String>> = HashMap::new();
        for (path, node) in nodes {
            clusters.entry(path).or_default().push(node)
        }

        let path_to_cluster = |path: &Path| {
            clusters
                .keys()
                .position(|key| {
                    *key == pathdiff::diff_paths(path, base_path)
                        .unwrap_or_default()
                        .to_string_lossy()
                        .to_string()
                })
                .unwrap_or(0)
        };

        let subgraphs = clusters
            .iter()
            .enumerate()
            .map(|(index, (label, nodes))| {
                if label.is_empty() {
                    nodes.join("\n")
                } else {
                    [
                        &format!("  subgraph cluster{} {{\n", index),
                        &format!("    label=\"{}\" fillcolor=\"#d1efb8\"\n  ", label),
                        &nodes.join("\n  "),
                        "\n  }",
                    ]
                    .concat()
                }
            })
            .collect::<Vec<String>>()
            .join("\n");

        let edges = self
            .graph
            .edge_indices()
            .filter_map(|edge| {
                if let (Some((from, to)), Some(relation)) = (
                    self.graph.edge_endpoints(edge),
                    self.graph.edge_weight(edge),
                ) {
                    let ltail = if let Some(Resource::File(file)) = self.graph.node_weight(from) {
                        format!(" ltail=\"cluster{}\"", path_to_cluster(&file.path))
                    } else {
                        "".to_string()
                    };

                    let lhead = if let Some(Resource::File(file)) = self.graph.node_weight(to) {
                        format!(" lhead=\"cluster{}\"", path_to_cluster(&file.path))
                    } else {
                        "".to_string()
                    };

                    Some(format!(
                        r#"  n{from} -> n{to} [label="{label}"{ltail}{lhead}]"#,
                        from = from.index(),
                        to = to.index(),
                        ltail = ltail,
                        lhead = lhead,
                        label = relation.to_string(),
                    ))
                } else {
                    None
                }
            })
            .collect::<Vec<String>>()
            .join("\n");

        format!(
            r#"digraph {{
  graph [rankdir=LR compound=true fontname=Helvetica fontsize=12 labeljust=l color=gray]
  node [style=filled fontname=Helvetica fontsize=11]
  edge [fontname=Helvetica fontsize=10]

{subgraphs}

{edges}
}}
"#,
            subgraphs = subgraphs,
            edges = edges
        )
    }
}

/// Get JSON Schemas for this modules
pub fn schemas() -> Result<serde_json::Value> {
    let schemas = serde_json::Value::Array(vec![
        schemas::generate::<Resource>()?,
        schemas::generate::<Relation>()?,
        serde_json::json!({
            "$id": "Triple",
            "title": "Triple",
            "description": "A subject-relation-object triple",
            "type" : "array",
            "items": [
                {
                    "tsType": "Resource"
                },
                {
                    "tsType": "Relation"
                },
                {
                    "tsType": "Resource"
                }
            ],
            "minItems": 3,
            "maxItems": 3
        }),
        serde_json::json!({
            "$id": "Graph",
            "title": "Graph",
            "description": "A project dependency graph",
            "type" : "object",
            "required": ["nodes", "edges"],
            "properties": {
                "nodes": {
                    "description": "The resources in the graph",
                    "type": "array",
                    "items": {
                        "tsType": "Resource",
                        "isRequired": true
                    }
                },
                "edges": {
                    "description": "The relations between resources in the graph",
                    "type": "array",
                    "items": {
                        "type": "array",
                        "items": [
                            {
                                "type": "integer"
                            },
                            {
                                "type": "integer"
                            },
                            {
                                "tsType": "Relation"
                            }
                        ],
                        "minItems": 3,
                        "maxItems": 3
                    }
                }
            },
            "additionalProperties": false
        }),
    ]);
    Ok(schemas)
}
<|endoftext|>


<commit_before>use lexer::TokenValue;
use lexer;
use ast::{Ast, NumberExprAst, VariableExprAst, BinaryExprAst};
use std::from_str;

pub struct Parser<'a> {
    current_token: Option<TokenValue>,
    lexer: lexer::Lexer<'a>
}

impl<'a> Parser<'a> {
    pub fn new(input: &'a str) -> Parser<'a> {
        Parser {
            current_token: None,
            lexer: lexer::Lexer::new(input)
        }
    }

    pub fn bump(&mut self) {
        self.current_token = self.lexer.next_token();
    }

    pub fn parse(&mut self) {

    }

    pub fn parse_number(&mut self) -> Ast {
        let num: i32 = match self.current_token {
            Some(ref token) => from_str(token.value).unwrap(),
            None => { fail!("Invalid token found.") }
        };
        let expr = NumberExprAst(num);
        self.bump();
        return expr;
    }
}

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

    #[test]
    fn parse_number() {
        let mut parser = Parser::new(&"9");
        parser.bump();
        match parser.parse_number() {
            NumberExprAst(r) => assert_eq!(r, 9),
            _ => fail!("Not expected.")
        }
    }
}<commit_msg>peek<commit_after>use lexer::TokenValue;
use lexer;
use ast::{Ast, NumberExprAst, VariableExprAst, BinaryExprAst};
use std::from_str;

pub struct Parser<'a> {
    next_token: Option<TokenValue>,
    current_token: Option<TokenValue>,
    lexer: lexer::Lexer<'a>
}

impl<'a> Parser<'a> {
    pub fn new(input: &'a str) -> Parser<'a> {
        Parser {
            next_token: None,
            current_token: None,
            lexer: lexer::Lexer::new(input)
        }
    }

    pub fn bump(&mut self) {
        if self.next_token.is_some() {
            self.current_token = self.next_token.take();
        } else {
            self.current_token = self.lexer.next_token();
        }
    }

    pub fn peek(&mut self) {
        self.next_token = self.lexer.next_token();
    }

    pub fn parse(&mut self) {

    }

    pub fn parse_number(&mut self) -> Ast {
        let num: i32 = match self.current_token {
            Some(ref token) => from_str(token.value).unwrap(),
            None => { fail!("Invalid token found.") }
        };
        let expr = NumberExprAst(num);
        self.bump();
        return expr;
    }
}

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

    #[test]
    fn parse_number() {
        let mut parser = Parser::new(&"9");
        parser.bump();
        match parser.parse_number() {
            NumberExprAst(r) => assert_eq!(r, 9),
            _ => fail!("Not expected.")
        }
    }

    #[test]
    fn parse_binary() {
        let mut parser = Parser::new(&"9+5");
        parser.bump();
        match parser.parse_number() {
            NumberExprAst(r) => assert_eq!(r, 9),
            _ => fail!("Not expected.")
        }

    }
}<|endoftext|>


<commit_before>//! This module contains implementations of `Dummy` trait

#[cfg(feature = "bigdecimal")]
pub mod bigdecimal;
#[cfg(feature = "chrono")]
pub mod chrono;
#[cfg(feature = "random_color")]
pub mod color;
#[cfg(feature = "rust_decimal")]
pub mod decimal;
#[cfg(feature = "http")]
pub mod http;
#[cfg(feature = "sea-orm")]
pub mod sea_orm;
#[cfg(feature = "semver")]
pub mod semver;
pub mod std;
#[cfg(feature = "time")]
pub mod time;
#[cfg(feature = "uuid")]
pub mod uuid;
#[cfg(feature = "zerocopy_byteorder")]
pub mod zerocopy_byteorder;
<commit_msg>Fix zerocopy feature flag<commit_after>//! This module contains implementations of `Dummy` trait

#[cfg(feature = "bigdecimal")]
pub mod bigdecimal;
#[cfg(feature = "chrono")]
pub mod chrono;
#[cfg(feature = "random_color")]
pub mod color;
#[cfg(feature = "rust_decimal")]
pub mod decimal;
#[cfg(feature = "http")]
pub mod http;
#[cfg(feature = "sea-orm")]
pub mod sea_orm;
#[cfg(feature = "semver")]
pub mod semver;
pub mod std;
#[cfg(feature = "time")]
pub mod time;
#[cfg(feature = "uuid")]
pub mod uuid;
#[cfg(feature = "zerocopy")]
pub mod zerocopy_byteorder;
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]
use std::mem;

use extprim::u128::u128;

use ffi;

use hasher::FastHash;

#[doc(hidden)]
pub struct MetroHash64_1 {}

impl FastHash for MetroHash64_1 {
    type Value = u64;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u64 {
        let mut hash = 0_u64;

        unsafe {
            ffi::metrohash64_1(bytes.as_ref().as_ptr() as *const u8,
                               bytes.as_ref().len() as u64,
                               seed,
                               mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher!(MetroHasher64_1, MetroHash64_1);

#[doc(hidden)]
pub struct MetroHash64_2 {}

impl FastHash for MetroHash64_2 {
    type Value = u64;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u64 {
        let mut hash = 0_u64;

        unsafe {
            ffi::metrohash64_2(bytes.as_ref().as_ptr() as *const u8,
                               bytes.as_ref().len() as u64,
                               seed,
                               mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher!(MetroHasher64_2, MetroHash64_2);

#[doc(hidden)]
pub struct MetroHash128_1 {}

impl FastHash for MetroHash128_1 {
    type Value = u128;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u128 {
        let mut hash = u128::zero();

        unsafe {
            ffi::metrohash128_1(bytes.as_ref().as_ptr() as *const u8,
                                bytes.as_ref().len() as u64,
                                seed,
                                mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher_ext!(MetroHasher128_1, MetroHash128_1);

#[doc(hidden)]
pub struct MetroHash128_2 {}

impl FastHash for MetroHash128_2 {
    type Value = u128;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u128 {
        let mut hash = u128::zero();

        unsafe {
            ffi::metrohash128_2(bytes.as_ref().as_ptr() as *const u8,
                                bytes.as_ref().len() as u64,
                                seed,
                                mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher_ext!(MetroHasher128_2, MetroHash128_2);

#[inline]
pub fn hash64(s: &[u8]) -> u64 {
    MetroHash64_1::hash(&s)
}

#[inline]
pub fn hash64_with_seed(s: &[u8], seed: u32) -> u64 {
    MetroHash64_1::hash_with_seed(&s, seed)
}

#[inline]
pub fn hash128(s: &[u8]) -> u128 {
    MetroHash128_1::hash(&s)
}

#[inline]
pub fn hash128_with_seed(s: &[u8], seed: u32) -> u128 {
    MetroHash128_1::hash_with_seed(&s, seed)
}

#[cfg(test)]
mod tests {
    use std::hash::Hasher;

    use extprim::u128::u128;

    use hasher::{FastHash, HasherExt};
    use super::*;

    #[test]
    fn test_cityhash64_1() {
        assert_eq!(MetroHash64_1::hash(b"hello"), 15663805623366682943);
        assert_eq!(MetroHash64_1::hash_with_seed(b"hello", 123),
                   1128464039211059189);
        assert_eq!(MetroHash64_1::hash(b"helloworld"), 4615394705531318333);

        let mut h = MetroHasher64_1::new();

        h.write(b"hello");
        assert_eq!(h.finish(), 15663805623366682943);

        h.write(b"world");
        assert_eq!(h.finish(), 4615394705531318333);
    }

    #[test]
    fn test_cityhash64_2() {
        assert_eq!(MetroHash64_2::hash(b"hello"), 12352443828090181231);
        assert_eq!(MetroHash64_2::hash_with_seed(b"hello", 123),
                   5558499743061241201);
        assert_eq!(MetroHash64_2::hash(b"helloworld"), 13816693401637061492);

        let mut h = MetroHasher64_2::new();

        h.write(b"hello");
        assert_eq!(h.finish(), 12352443828090181231);

        h.write(b"world");
        assert_eq!(h.finish(), 13816693401637061492);
    }

    #[test]
    fn test_cityhash128_1() {
        assert_eq!(MetroHash128_1::hash(b"hello"),
                   u128::from_parts(3402816320040206173, 8267579177094204812));
        assert_eq!(MetroHash128_1::hash_with_seed(b"hello", 123),
                   u128::from_parts(12815203692632715937, 16954909965332884860));
        assert_eq!(MetroHash128_1::hash(b"helloworld"),
                   u128::from_parts(9114061290236148431, 9070923966242366617));

        let mut h = MetroHasher128_1::new();

        h.write(b"hello");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(3402816320040206173, 8267579177094204812));

        h.write(b"world");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(9114061290236148431, 9070923966242366617));
    }

    #[test]
    fn test_cityhash128_2() {
        assert_eq!(MetroHash128_2::hash(b"hello"),
                   u128::from_parts(8645868589955642073, 18321434607751955537));
        assert_eq!(MetroHash128_2::hash_with_seed(b"hello", 123),
                   u128::from_parts(18306880534314458917, 13865612537680895339));
        assert_eq!(MetroHash128_2::hash(b"helloworld"),
                   u128::from_parts(16062202743590172306, 17411406382482299971));

        let mut h = MetroHasher128_2::new();

        h.write(b"hello");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(8645868589955642073, 18321434607751955537));

        h.write(b"world");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(16062202743590172306, 17411406382482299971));
    }
}
<commit_msg>fix test case name<commit_after>#![allow(non_camel_case_types)]
use std::mem;

use extprim::u128::u128;

use ffi;

use hasher::FastHash;

#[doc(hidden)]
pub struct MetroHash64_1 {}

impl FastHash for MetroHash64_1 {
    type Value = u64;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u64 {
        let mut hash = 0_u64;

        unsafe {
            ffi::metrohash64_1(bytes.as_ref().as_ptr() as *const u8,
                               bytes.as_ref().len() as u64,
                               seed,
                               mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher!(MetroHasher64_1, MetroHash64_1);

#[doc(hidden)]
pub struct MetroHash64_2 {}

impl FastHash for MetroHash64_2 {
    type Value = u64;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u64 {
        let mut hash = 0_u64;

        unsafe {
            ffi::metrohash64_2(bytes.as_ref().as_ptr() as *const u8,
                               bytes.as_ref().len() as u64,
                               seed,
                               mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher!(MetroHasher64_2, MetroHash64_2);

#[doc(hidden)]
pub struct MetroHash128_1 {}

impl FastHash for MetroHash128_1 {
    type Value = u128;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u128 {
        let mut hash = u128::zero();

        unsafe {
            ffi::metrohash128_1(bytes.as_ref().as_ptr() as *const u8,
                                bytes.as_ref().len() as u64,
                                seed,
                                mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher_ext!(MetroHasher128_1, MetroHash128_1);

#[doc(hidden)]
pub struct MetroHash128_2 {}

impl FastHash for MetroHash128_2 {
    type Value = u128;
    type Seed = u32;

    #[inline]
    fn hash_with_seed<T: AsRef<[u8]>>(bytes: &T, seed: u32) -> u128 {
        let mut hash = u128::zero();

        unsafe {
            ffi::metrohash128_2(bytes.as_ref().as_ptr() as *const u8,
                                bytes.as_ref().len() as u64,
                                seed,
                                mem::transmute(&mut hash));
        }

        hash
    }
}

impl_hasher_ext!(MetroHasher128_2, MetroHash128_2);

#[inline]
pub fn hash64(s: &[u8]) -> u64 {
    MetroHash64_1::hash(&s)
}

#[inline]
pub fn hash64_with_seed(s: &[u8], seed: u32) -> u64 {
    MetroHash64_1::hash_with_seed(&s, seed)
}

#[inline]
pub fn hash128(s: &[u8]) -> u128 {
    MetroHash128_1::hash(&s)
}

#[inline]
pub fn hash128_with_seed(s: &[u8], seed: u32) -> u128 {
    MetroHash128_1::hash_with_seed(&s, seed)
}

#[cfg(test)]
mod tests {
    use std::hash::Hasher;

    use extprim::u128::u128;

    use hasher::{FastHash, HasherExt};
    use super::*;

    #[test]
    fn test_metrohash64_1() {
        assert_eq!(MetroHash64_1::hash(b"hello"), 15663805623366682943);
        assert_eq!(MetroHash64_1::hash_with_seed(b"hello", 123),
                   1128464039211059189);
        assert_eq!(MetroHash64_1::hash(b"helloworld"), 4615394705531318333);

        let mut h = MetroHasher64_1::new();

        h.write(b"hello");
        assert_eq!(h.finish(), 15663805623366682943);

        h.write(b"world");
        assert_eq!(h.finish(), 4615394705531318333);
    }

    #[test]
    fn test_metrohash64_2() {
        assert_eq!(MetroHash64_2::hash(b"hello"), 12352443828090181231);
        assert_eq!(MetroHash64_2::hash_with_seed(b"hello", 123),
                   5558499743061241201);
        assert_eq!(MetroHash64_2::hash(b"helloworld"), 13816693401637061492);

        let mut h = MetroHasher64_2::new();

        h.write(b"hello");
        assert_eq!(h.finish(), 12352443828090181231);

        h.write(b"world");
        assert_eq!(h.finish(), 13816693401637061492);
    }

    #[test]
    fn test_metrohash128_1() {
        assert_eq!(MetroHash128_1::hash(b"hello"),
                   u128::from_parts(3402816320040206173, 8267579177094204812));
        assert_eq!(MetroHash128_1::hash_with_seed(b"hello", 123),
                   u128::from_parts(12815203692632715937, 16954909965332884860));
        assert_eq!(MetroHash128_1::hash(b"helloworld"),
                   u128::from_parts(9114061290236148431, 9070923966242366617));

        let mut h = MetroHasher128_1::new();

        h.write(b"hello");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(3402816320040206173, 8267579177094204812));

        h.write(b"world");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(9114061290236148431, 9070923966242366617));
    }

    #[test]
    fn test_metrohash128_2() {
        assert_eq!(MetroHash128_2::hash(b"hello"),
                   u128::from_parts(8645868589955642073, 18321434607751955537));
        assert_eq!(MetroHash128_2::hash_with_seed(b"hello", 123),
                   u128::from_parts(18306880534314458917, 13865612537680895339));
        assert_eq!(MetroHash128_2::hash(b"helloworld"),
                   u128::from_parts(16062202743590172306, 17411406382482299971));

        let mut h = MetroHasher128_2::new();

        h.write(b"hello");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(8645868589955642073, 18321434607751955537));

        h.write(b"world");
        assert_eq!(h.finish_ext(),
                   u128::from_parts(16062202743590172306, 17411406382482299971));
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.

//! # Translation of inline assembly.

use llvm;
use trans::build::*;
use trans::callee;
use trans::common::*;
use trans::cleanup;
use trans::cleanup::CleanupMethods;
use trans::expr;
use trans::type_of;
use trans::type_::Type;

use syntax::ast;
use std::ffi::CString;
use libc::{c_uint, c_char};

// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
                                    -> Block<'blk, 'tcx> {
    let fcx = bcx.fcx;
    let mut bcx = bcx;
    let mut constraints = Vec::new();
    let mut output_types = Vec::new();

    let temp_scope = fcx.push_custom_cleanup_scope();

    let mut ext_inputs = Vec::new();
    let mut ext_constraints = Vec::new();

    // Prepare the output operands
    let outputs = ia.outputs.iter().enumerate().map(|(i, &(ref c, ref out, is_rw))| {
        constraints.push((*c).clone());

        let out_datum = unpack_datum!(bcx, expr::trans(bcx, &**out));
        output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
        let val = out_datum.val;
        if is_rw {
            ext_inputs.push(unpack_result!(bcx, {
                callee::trans_arg_datum(bcx,
                                       expr_ty(bcx, &**out),
                                       out_datum,
                                       cleanup::CustomScope(temp_scope),
                                       callee::DontAutorefArg)
            }));
            ext_constraints.push(i.to_string());
        }
        val

    }).collect::<Vec<_>>();

    // Now the input operands
    let mut inputs = ia.inputs.iter().map(|&(ref c, ref input)| {
        constraints.push((*c).clone());

        let in_datum = unpack_datum!(bcx, expr::trans(bcx, &**input));
        unpack_result!(bcx, {
            callee::trans_arg_datum(bcx,
                                    expr_ty(bcx, &**input),
                                    in_datum,
                                    cleanup::CustomScope(temp_scope),
                                    callee::DontAutorefArg)
        })
    }).collect::<Vec<_>>();
    inputs.push_all(&ext_inputs[..]);

    // no failure occurred preparing operands, no need to cleanup
    fcx.pop_custom_cleanup_scope(temp_scope);

    let mut constraints = constraints.iter()
                                     .map(|s| s.to_string())
                                     .chain(ext_constraints.into_iter())
                                     .collect::<Vec<String>>()
                                     .connect(",");

    let mut clobbers = ia.clobbers.iter()
                                  .map(|s| format!("~{{{}}}", &s))
                                  .collect::<Vec<String>>()
                                  .connect(",");
    let more_clobbers = get_clobbers();
    if !more_clobbers.is_empty() {
        if !clobbers.is_empty() {
            clobbers.push(',');
        }
        clobbers.push_str(&more_clobbers[..]);
    }

    // Add the clobbers to our constraints list
    if clobbers.len() != 0 && constraints.len() != 0 {
        constraints.push(',');
        constraints.push_str(&clobbers[..]);
    } else {
        constraints.push_str(&clobbers[..]);
    }

    debug!("Asm Constraints: {}", &constraints[..]);

    let num_outputs = outputs.len();

    // Depending on how many outputs we have, the return type is different
    let output_type = if num_outputs == 0 {
        Type::void(bcx.ccx())
    } else if num_outputs == 1 {
        output_types[0]
    } else {
        Type::struct_(bcx.ccx(), &output_types[..], false)
    };

    let dialect = match ia.dialect {
        ast::AsmAtt   => llvm::AD_ATT,
        ast::AsmIntel => llvm::AD_Intel
    };

    let asm = CString::new(ia.asm.as_bytes()).unwrap();
    let constraints = CString::new(constraints).unwrap();
    let r = InlineAsmCall(bcx,
                          asm.as_ptr(),
                          constraints.as_ptr(),
                          &inputs,
                          output_type,
                          ia.volatile,
                          ia.alignstack,
                          dialect);

    // Again, based on how many outputs we have
    if num_outputs == 1 {
        Store(bcx, r, outputs[0]);
    } else {
        for (i, o) in outputs.iter().enumerate() {
            let v = ExtractValue(bcx, r, i);
            Store(bcx, v, *o);
        }
    }

    // Store expn_id in a metadata node so we can map LLVM errors
    // back to source locations.  See #17552.
    unsafe {
        let key = "srcloc";
        let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(),
            key.as_ptr() as *const c_char, key.len() as c_uint);

        let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.to_llvm_cookie());

        llvm::LLVMSetMetadata(r, kind,
            llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));
    }

    return bcx;

}

// Default per-arch clobbers
// Basically what clang does

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
fn get_clobbers() -> String {
    "".to_string()
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn get_clobbers() -> String {
    "~{dirflag},~{fpsr},~{flags}".to_string()
}
<commit_msg>Fix a bug in inline assembly codegen where host clobbers were always used regardless of target<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.

//! # Translation of inline assembly.

use llvm;
use trans::build::*;
use trans::callee;
use trans::common::*;
use trans::cleanup;
use trans::cleanup::CleanupMethods;
use trans::expr;
use trans::type_of;
use trans::type_::Type;

use syntax::ast;
use std::ffi::CString;
use libc::{c_uint, c_char};

// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
                                    -> Block<'blk, 'tcx> {
    let fcx = bcx.fcx;
    let mut bcx = bcx;
    let mut constraints = Vec::new();
    let mut output_types = Vec::new();

    let temp_scope = fcx.push_custom_cleanup_scope();

    let mut ext_inputs = Vec::new();
    let mut ext_constraints = Vec::new();

    // Prepare the output operands
    let outputs = ia.outputs.iter().enumerate().map(|(i, &(ref c, ref out, is_rw))| {
        constraints.push((*c).clone());

        let out_datum = unpack_datum!(bcx, expr::trans(bcx, &**out));
        output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
        let val = out_datum.val;
        if is_rw {
            ext_inputs.push(unpack_result!(bcx, {
                callee::trans_arg_datum(bcx,
                                       expr_ty(bcx, &**out),
                                       out_datum,
                                       cleanup::CustomScope(temp_scope),
                                       callee::DontAutorefArg)
            }));
            ext_constraints.push(i.to_string());
        }
        val

    }).collect::<Vec<_>>();

    // Now the input operands
    let mut inputs = ia.inputs.iter().map(|&(ref c, ref input)| {
        constraints.push((*c).clone());

        let in_datum = unpack_datum!(bcx, expr::trans(bcx, &**input));
        unpack_result!(bcx, {
            callee::trans_arg_datum(bcx,
                                    expr_ty(bcx, &**input),
                                    in_datum,
                                    cleanup::CustomScope(temp_scope),
                                    callee::DontAutorefArg)
        })
    }).collect::<Vec<_>>();
    inputs.push_all(&ext_inputs[..]);

    // no failure occurred preparing operands, no need to cleanup
    fcx.pop_custom_cleanup_scope(temp_scope);

    let clobbers = ia.clobbers.iter()
                              .map(|s| format!("~{{{}}}", &s))
                              .collect::<Vec<String>>();

    // Default per-arch clobbers
    // Basically what clang does
    let arch_clobbers = match bcx.sess().target.target.arch.as_slice() {
        "x86" | "x86_64" => vec!("~{dirflag}", "~{fpsr}", "~{flags}"),
        _                => Vec::new()
    };

    let all_constraints= constraints.iter()
                                    .map(|s| s.to_string())
                                    .chain(ext_constraints.into_iter())
                                    .chain(clobbers.into_iter())
                                    .chain(arch_clobbers.into_iter()
                                               .map(|s| s.to_string()))
                                    .collect::<Vec<String>>()
                                    .connect(",");

    debug!("Asm Constraints: {}", &all_constraints[..]);

    // Depending on how many outputs we have, the return type is different
    let num_outputs = outputs.len();
    let output_type = match num_outputs {
        0 => Type::void(bcx.ccx()),
        1 => output_types[0],
        _ => Type::struct_(bcx.ccx(), &output_types[..], false)
    };

    let dialect = match ia.dialect {
        ast::AsmAtt   => llvm::AD_ATT,
        ast::AsmIntel => llvm::AD_Intel
    };

    let asm = CString::new(ia.asm.as_bytes()).unwrap();
    let constraint_cstr = CString::new(all_constraints).unwrap();
    let r = InlineAsmCall(bcx,
                          asm.as_ptr(),
                          constraint_cstr.as_ptr(),
                          &inputs,
                          output_type,
                          ia.volatile,
                          ia.alignstack,
                          dialect);

    // Again, based on how many outputs we have
    if num_outputs == 1 {
        Store(bcx, r, outputs[0]);
    } else {
        for (i, o) in outputs.iter().enumerate() {
            let v = ExtractValue(bcx, r, i);
            Store(bcx, v, *o);
        }
    }

    // Store expn_id in a metadata node so we can map LLVM errors
    // back to source locations.  See #17552.
    unsafe {
        let key = "srcloc";
        let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(),
            key.as_ptr() as *const c_char, key.len() as c_uint);

        let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.to_llvm_cookie());

        llvm::LLVMSetMetadata(r, kind,
            llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));
    }

    return bcx;

}

<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.

/*!
Support for parsing unsupported, old syntaxes, for the
purpose of reporting errors. Parsing of these syntaxes
is tested by compile-test/obsolete-syntax.rs.

Obsolete syntax that becomes too hard to parse can be
removed.
*/

use ast::{Expr, ExprLit, LitNil};
use codemap::{Span, respan};
use parse::parser;
use parse::token;

use std::gc::{Gc, GC};

/// The specific types of unsupported syntax
#[deriving(PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
    ObsoleteOwnedType,
    ObsoleteOwnedExpr,
    ObsoleteOwnedPattern,
    ObsoleteOwnedVector,
    ObsoleteManagedType,
    ObsoleteManagedExpr,
}

pub trait ParserObsoleteMethods {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> Gc<Expr>;
    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str);
    fn is_obsolete_ident(&mut self, ident: &str) -> bool;
    fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}

impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
        let (kind_str, desc) = match kind {
            ObsoleteOwnedType => (
                "`~` notation for owned pointers",
                "use `Box<T>` in `std::owned` instead"
            ),
            ObsoleteOwnedExpr => (
                "`~` notation for owned pointer allocation",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteOwnedPattern => (
                "`~` notation for owned pointer patterns",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteOwnedVector => (
                "`~[T]` is no longer a type",
                "use the `Vec` type instead"
            ),
            ObsoleteManagedType => (
                "`@` notation for managed pointers",
                "use `Gc<T>` in `std::gc` instead"
            ),
            ObsoleteManagedExpr => (
                "`@` notation for a managed pointer allocation",
                "use the `box(GC)` oeprator instead of `@`"
            ),
        };

        self.report(sp, kind, kind_str, desc);
    }

    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> Gc<Expr> {
        self.obsolete(sp, kind);
        self.mk_expr(sp.lo, sp.hi, ExprLit(box(GC) respan(sp, LitNil)))
    }

    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str) {
        self.span_err(sp,
                      format!("obsolete syntax: {}", kind_str).as_slice());

        if !self.obsolete_set.contains(&kind) {
            self.sess
                .span_diagnostic
                .handler()
                .note(format!("{}", desc).as_slice());
            self.obsolete_set.insert(kind);
        }
    }

    fn is_obsolete_ident(&mut self, ident: &str) -> bool {
        match self.token {
            token::IDENT(sid, _) => {
                token::get_ident(sid).equiv(&ident)
            }
            _ => false
        }
    }

    fn eat_obsolete_ident(&mut self, ident: &str) -> bool {
        if self.is_obsolete_ident(ident) {
            self.bump();
            true
        } else {
            false
        }
    }
}
<commit_msg>obsolete.rs: fix typo in message<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.

/*!
Support for parsing unsupported, old syntaxes, for the
purpose of reporting errors. Parsing of these syntaxes
is tested by compile-test/obsolete-syntax.rs.

Obsolete syntax that becomes too hard to parse can be
removed.
*/

use ast::{Expr, ExprLit, LitNil};
use codemap::{Span, respan};
use parse::parser;
use parse::token;

use std::gc::{Gc, GC};

/// The specific types of unsupported syntax
#[deriving(PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
    ObsoleteOwnedType,
    ObsoleteOwnedExpr,
    ObsoleteOwnedPattern,
    ObsoleteOwnedVector,
    ObsoleteManagedType,
    ObsoleteManagedExpr,
}

pub trait ParserObsoleteMethods {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> Gc<Expr>;
    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str);
    fn is_obsolete_ident(&mut self, ident: &str) -> bool;
    fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}

impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
    /// Reports an obsolete syntax non-fatal error.
    fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
        let (kind_str, desc) = match kind {
            ObsoleteOwnedType => (
                "`~` notation for owned pointers",
                "use `Box<T>` in `std::owned` instead"
            ),
            ObsoleteOwnedExpr => (
                "`~` notation for owned pointer allocation",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteOwnedPattern => (
                "`~` notation for owned pointer patterns",
                "use the `box` operator instead of `~`"
            ),
            ObsoleteOwnedVector => (
                "`~[T]` is no longer a type",
                "use the `Vec` type instead"
            ),
            ObsoleteManagedType => (
                "`@` notation for managed pointers",
                "use `Gc<T>` in `std::gc` instead"
            ),
            ObsoleteManagedExpr => (
                "`@` notation for a managed pointer allocation",
                "use the `box(GC)` operator instead of `@`"
            ),
        };

        self.report(sp, kind, kind_str, desc);
    }

    /// Reports an obsolete syntax non-fatal error, and returns
    /// a placeholder expression
    fn obsolete_expr(&mut self, sp: Span, kind: ObsoleteSyntax) -> Gc<Expr> {
        self.obsolete(sp, kind);
        self.mk_expr(sp.lo, sp.hi, ExprLit(box(GC) respan(sp, LitNil)))
    }

    fn report(&mut self,
              sp: Span,
              kind: ObsoleteSyntax,
              kind_str: &str,
              desc: &str) {
        self.span_err(sp,
                      format!("obsolete syntax: {}", kind_str).as_slice());

        if !self.obsolete_set.contains(&kind) {
            self.sess
                .span_diagnostic
                .handler()
                .note(format!("{}", desc).as_slice());
            self.obsolete_set.insert(kind);
        }
    }

    fn is_obsolete_ident(&mut self, ident: &str) -> bool {
        match self.token {
            token::IDENT(sid, _) => {
                token::get_ident(sid).equiv(&ident)
            }
            _ => false
        }
    }

    fn eat_obsolete_ident(&mut self, ident: &str) -> bool {
        if self.is_obsolete_ident(ident) {
            self.bump();
            true
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! asn1_info {
  ($rs_type:ty, $asn1_ty:expr, $class:expr, $tagnum:expr, $constructed:expr) => (
    impl $crate::serial::traits::Asn1Info for $rs_type {
      fn asn1_tag() -> $crate::tag::Tag {
        $crate::tag::Tag {
          class: $class.into(),
          tagnum: $tagnum.into(),
          constructed: $constructed,

        }
      }

      fn asn1_type() -> $crate::tag::Type {
        $crate::tag::Type::from($asn1_ty)
      }
    }
  )
}

#[macro_export]
macro_rules! asn1_sequence_info {
  ($rs_type:ty, $asn1_ty:expr) => (
    impl $crate::serial::traits::Asn1Info for $rs_type {
      fn asn1_tag() -> $crate::tag::Tag {
        $crate::tag::Tag {
          class: $crate::tag::Class::Universal,
          tagnum: (0x10 as u8).into(),
          constructed: true,
        }
      }

      fn asn1_type() -> $crate::tag::Type {
        $asn1_ty.into()
      }
    }
  )
}

#[macro_export]
macro_rules! asn1_sequence_serialize {
  ($rs_type:ty, $($item:ident),*) => (
    impl serial::traits::Asn1Serialize for $rs_type {
      fn serialize_imp<W: io::Write>(&self, writer: &mut W) -> Result<(), $crate::err::EncodeError> {
        let mut bytes = Vec::new();
        let mut count: u64 = 0;
        // For each declared sequence member, serialize it onto the stream.
        $(
          count += 1;
          try!(
            serial::traits::Asn1Serialize::serialize_exp(&self.$item, &mut bytes)
          );
          let tag = $crate::tag::TagLen {
            tag: $crate::tag::Tag {
              class: $crate::tag::Class::ContextSpecific,
              tagnum: count.into(),
              constructed: true,
            },
            len: Some(bytes.len() as $crate::tag::LenNum).into(),
          };
          try!(tag.write_taglen(writer));
          try!(writer.write(&mut bytes));

          bytes.clear();
        )*
        Ok(())
      }
    }
  )
}

#[macro_export]
macro_rules! asn1_sequence_deserialize {
  ($rs_type:ident, $($item:ident),*) => (
    impl serial::traits::Asn1Deserialize for $rs_type {
      fn deserialize_imp<I: Iterator<Item=io::Result<u8>>>(reader: &mut I, _: $crate::tag::Len) -> Result<Self, $crate::err::DecodeError> {
        Ok( $rs_type { $(
          $item: {
            let tag = try!($crate::tag::TagLen::read_taglen(reader));
            let _ = tag;
            try!($crate::serial::traits::Asn1Deserialize::deserialize_exp(reader))
          },
        )* })
      }
    }
  )
}
<commit_msg>Add documentation for sequence macros<commit_after>//! The macros in this module can implement the serialisation traits for Sequences and
//! Sets.
//!
//! ```
//! #[macro_use] extern crate asn1_cereal; fn main() {
//!   struct SomeSequence {
//!     a: u64,
//!     b: u32,
//!     c: String,
//!   }
//!
//!   asn1_sequence_info!(SomeSequence, "SOME_SEQUENCE");
//!   asn1_sequence_serialize!(SomeSequence, a, b, c);
//!   asn1_sequence_deserialize!(SomeSequence, a, b, c);
//! }
//! ```
//!
//! Note that these macros can also be used for a SET, but not a
//! SEQUENECE OF, or SET OF. (These are more appropriate as Vec
//! or Set).

#[macro_export]
/// This macro is a compact way of defining asn1_info for a type.
macro_rules! asn1_info {
  ($rs_type:ty, $class:expr, $tagnum:expr, $constructed:expr, $asn1_ty:expr) => (
    impl $crate::serial::traits::Asn1Info for $rs_type {
      fn asn1_tag() -> $crate::tag::Tag {
        $crate::tag::Tag {
          class: ($class as u8).into(),
          tagnum: $tagnum as $crate::tag::TagNum,
          constructed: $constructed,

        }
      }

      fn asn1_type() -> $crate::tag::Type {
        $crate::tag::Type::from($asn1_ty)
      }
    }
  )
}

#[macro_export]
/// This macro is a compact way of defining the Asn1Info trait implementation
/// for a struct that represents an ASN.1 structure. If a custom class or tag
/// number is required, asn1_info! should be used instead.
macro_rules! asn1_sequence_info {
  ($rs_type:ty, $asn1_ty:expr) => (
    impl $crate::serial::traits::Asn1Info for $rs_type {
      fn asn1_tag() -> $crate::tag::Tag {
        $crate::tag::Tag {
          class: $crate::tag::Class::Universal,
          tagnum: (0x10 as u8).into(),
          constructed: true,
        }
      }

      fn asn1_type() -> $crate::tag::Type {
        $asn1_ty.into()
      }
    }
  )
}

#[macro_export]
/// This macro will generate an Asn1Serialize implementation for a struct
/// that represents an ASN.1 structure.
///
/// Note that struct fields need to be manually specificied, and serialization
/// will occur in that order. If you don't list a field, it won't get
/// serialized. Each of these fields need to implement Asn1Serialize,
/// otherwise compilation will fail.
///
/// If some form of procedural macros are eventually stabilised,
/// listing the fields in the macro might not be required.
macro_rules! asn1_sequence_serialize {
  ($rs_type:ty, $($item:ident),*) => (
    impl $crate::serial::traits::Asn1Serialize for $rs_type {
      fn serialize_imp<W: std::io::Write>(&self, writer: &mut W) -> Result<(), $crate::err::EncodeError> {
        let mut bytes = Vec::new();
        let mut count: u64 = 0;
        // For each declared sequence member, serialize it onto the stream.
        $(
          count += 1;
          try!(
            $crate::serial::traits::Asn1Serialize::serialize_exp(&self.$item, &mut bytes)
          );
          let tag = $crate::tag::TagLen {
            tag: $crate::tag::Tag {
              class: $crate::tag::Class::ContextSpecific,
              tagnum: count.into(),
              constructed: true,
            },
            len: Some(bytes.len() as $crate::tag::LenNum).into(),
          };
          try!(tag.write_taglen(writer));
          try!(writer.write(&mut bytes));

          bytes.clear();
        )*
        Ok(())
      }
    }
  )
}

#[macro_export]
/// This macro will generate an Asn1Deserialize implementation for a struct
/// that represents an ASN.1 structure.
///
/// Note that all struct fields need to be manually specificied, and
/// deserialization will occur in that order. Unlike the deserialize macro,
/// all fields must be specified. Each of these fields need to implement
/// Asn1Deserialize, otherwise compilation will fail.
///
/// If some form of procedural macros are eventually stabilised,
/// listing the fields in the macro might not be required.
macro_rules! asn1_sequence_deserialize {
  ($rs_type:ident, $($item:ident),*) => (
    impl $crate::serial::traits::Asn1Deserialize for $rs_type {
      fn deserialize_imp<I: Iterator<Item=std::io::Result<u8>>>(reader: &mut I, _: $crate::tag::Len) -> Result<Self, $crate::err::DecodeError> {
        Ok( $rs_type { $(
          $item: {
            let tag = try!($crate::tag::TagLen::read_taglen(reader));
            let _ = tag;
            try!($crate::serial::traits::Asn1Deserialize::deserialize_exp(reader))
          },
        )* })
      }
    }
  )
}
<|endoftext|>


<commit_before>//! An ordered list of middleware that performs tested transformations.

use crate::{wire::middleware, Error};
use std;

/// A middleware pipeline.
pub trait Pipeline : std::fmt::Debug
{
    fn encode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error>;
    fn decode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error>;
}

/// Creates an instance of the default middleware.
pub fn default() -> Default {
    Default::default()
}

/// Defines a new middleware pipeline that implements `Pipeline`.
#[macro_export]
macro_rules! define_middleware_pipeline {
    ($ty:ident { $( $mw_name:ident : $mw_ty:ty ),* } ) => {
        #[derive(Clone, Debug)]
        pub struct $ty
        {
            $( pub $mw_name : $mw_ty),*
        }

        impl $ty
        {
            /// Gets the middleware pipeline.
            pub fn middleware_mut(&mut self) -> ::std::collections::VecDeque<&mut dyn $crate::wire::Middleware> {
                #[allow(unused_mut)]
                let mut middleware = ::std::collections::VecDeque::new();

                $( middleware.push_front(&mut self.$mw_name as &mut dyn $crate::wire::Middleware); )*

                middleware
            }
        }

        impl $crate::wire::middleware::Pipeline for $ty
        {
            fn encode_data(&mut self, mut data: Vec<u8>)
                -> Result<Vec<u8>, $crate::Error> {
                use $crate::wire::Middleware;

                $( data = self.$mw_name.encode_data(data)?; )*

                Ok(data)
            }

            fn decode_data(&mut self, mut data: Vec<u8>)
                -> Result<Vec<u8>, $crate::Error> {
                for middleware in self.middleware_mut() {
                    data = middleware.decode_data(data)?;
                }

                Ok(data)
            }
        }
    };
}

// The default middleware pipeline.
#[cfg(feature = "middleware-compression")]
define_middleware_pipeline!(Default {
    compression: middleware::compression::Compression
});

// The default middleware pipeline.
#[cfg(not(feature = "middleware-compression"))]
define_middleware_pipeline!(Default {
});

impl std::default::Default for Default
{
    fn default() -> Self {
        Default {
            // The default middleware pipeline.
            #[cfg(feature = "middleware-compression")]
            compression: middleware::compression::Compression::Disabled,
        }
    }
}

#[cfg(test)]
mod test
{
    use crate::{wire, wire::middleware::Pipeline, Error};

    define_middleware_pipeline!(NullPipeline {
        encryption: NullMiddleware,
        compression: NullMiddleware
    });

    #[derive(Clone, Debug)]
    pub struct NullMiddleware;

    impl wire::Middleware for NullMiddleware
    {
        fn encode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> { Ok(data) }
        fn decode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> { Ok(data) }
    }

    #[test]
    fn successfully_passes_data_through_the_pipeline() {
        let mut null_pipeline = NullPipeline {
            encryption: NullMiddleware,
            compression: NullMiddleware,
        };

        let data = vec![7, 2, 5, 5, 1, 2, 3, 4, 2, 4, 8];

        assert_eq!(null_pipeline.encode_data(data.clone()).unwrap(), data.clone());
        assert_eq!(null_pipeline.decode_data(data.clone()).unwrap(), data.clone());
    }
}

<commit_msg>Fix compiler warnings when middleware-compression feature is disable and the default pipeline is a NOP<commit_after>//! An ordered list of middleware that performs tested transformations.

use crate::Error;
use std;

/// A middleware pipeline.
pub trait Pipeline : std::fmt::Debug
{
    fn encode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error>;
    fn decode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error>;
}

/// Creates an instance of the default middleware.
pub fn default() -> Default {
    Default::default()
}

/// Defines a new middleware pipeline that implements `Pipeline`.
#[macro_export]
macro_rules! define_middleware_pipeline {
    ($ty:ident { $( $mw_name:ident : $mw_ty:ty ),* } ) => {
        #[derive(Clone, Debug)]
        pub struct $ty
        {
            $( pub $mw_name : $mw_ty),*
        }

        impl $ty
        {
            /// Gets the middleware pipeline.
            pub fn middleware_mut(&mut self) -> ::std::collections::VecDeque<&mut dyn $crate::wire::Middleware> {
                #[allow(unused_mut)]
                let mut middleware = ::std::collections::VecDeque::new();

                $( middleware.push_front(&mut self.$mw_name as &mut dyn $crate::wire::Middleware); )*

                middleware
            }
        }

        impl $crate::wire::middleware::Pipeline for $ty
        {
            #[allow(unused_mut)]
            fn encode_data(&mut self, mut data: Vec<u8>)
                -> Result<Vec<u8>, $crate::Error> {
                use $crate::wire::Middleware;

                $( data = self.$mw_name.encode_data(data)?; )*

                Ok(data)
            }

            fn decode_data(&mut self, mut data: Vec<u8>)
                -> Result<Vec<u8>, $crate::Error> {
                for middleware in self.middleware_mut() {
                    data = middleware.decode_data(data)?;
                }

                Ok(data)
            }
        }
    };
}

// The default middleware pipeline.
#[cfg(feature = "middleware-compression")]
define_middleware_pipeline!(Default {
    compression: crate::wire::middleware::compression::Compression
});

// The default middleware pipeline.
#[cfg(not(feature = "middleware-compression"))]
define_middleware_pipeline!(Default {
});

impl std::default::Default for Default
{
    fn default() -> Self {
        Default {
            // The default middleware pipeline.
            #[cfg(feature = "middleware-compression")]
            compression: crate::wire::middleware::compression::Compression::Disabled,
        }
    }
}

#[cfg(test)]
mod test
{
    use crate::{wire, wire::middleware::Pipeline, Error};

    define_middleware_pipeline!(NullPipeline {
        encryption: NullMiddleware,
        compression: NullMiddleware
    });

    #[derive(Clone, Debug)]
    pub struct NullMiddleware;

    impl wire::Middleware for NullMiddleware
    {
        fn encode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> { Ok(data) }
        fn decode_data(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> { Ok(data) }
    }

    #[test]
    fn successfully_passes_data_through_the_pipeline() {
        let mut null_pipeline = NullPipeline {
            encryption: NullMiddleware,
            compression: NullMiddleware,
        };

        let data = vec![7, 2, 5, 5, 1, 2, 3, 4, 2, 4, 8];

        assert_eq!(null_pipeline.encode_data(data.clone()).unwrap(), data.clone());
        assert_eq!(null_pipeline.decode_data(data.clone()).unwrap(), data.clone());
    }
}

<|endoftext|>