// Copyright 2018 The Fuchsia 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 {
    crate::Rule,
    failure::Fail,
    pest::iterators::{Pair, Pairs},
    serde_derive::Serialize,
    std::collections::{BTreeMap, HashSet, VecDeque},
    std::fmt,
    std::str::FromStr,
};

#[derive(Debug, Fail)]
pub enum ParseError {
    #[fail(display = "The primary namespace was already set")]
    AlreadyPrimaryNamespace,
    #[fail(display = "{} is not yet support", 0)]
    NotYetSupported(String),
    #[fail(display = "{:?} is not expected in this location", 0)]
    UnexpectedToken(Rule),
    #[fail(display = "{} was not included in the input libraries", 0)]
    UnImported(String),
    #[fail(display = "{:?} is an unknown type", 0)]
    UnrecognizedType(String),
    #[fail(display = "Failed to parse because {:?} is not an integer", 0)]
    NotAnInteger(Rule),
    #[fail(display = "Invalid dependencies: {}", 0)]
    InvalidDeps(String),
    #[fail(display = "Expected {:?} to resolve to a {:?}.", 0, 1)]
    InvalidConstType(Constant, Ty),
    #[fail(display = "Declaration not found in namespace")]
    UnknownDecl,
}

#[derive(PartialEq, Eq, Serialize, Default, Debug, Clone, Hash, PartialOrd, Ord)]
pub struct Attr {
    pub key: String,
    pub val: Option<String>,
}

#[derive(PartialEq, Eq, Serialize, Default, Debug, Clone, Hash, PartialOrd, Ord)]
pub struct Attrs(pub Vec<Attr>);

// namespace is only populated if it's not the current/default one
// TODO(bwb) consider populating it or renaming to be more explicit
#[derive(PartialEq, Debug, Eq, Serialize, Clone, Hash, PartialOrd, Ord)]
pub struct Ident {
    namespace: Option<String>,
    name: String,
}

impl Ident {
    /// Construct an identity. If the second parameter is a fully qualified identity, use that
    /// if it is not qualified, place it under the passed in namespace
    pub fn new(namespace: &str, raw_name: &str) -> Ident {
        let v: Vec<&str> = raw_name.rsplitn(2, '.').collect();
        if v.len() > 1 {
            Ident { namespace: Some(v[1].trim().to_string()), name: v[0].trim().to_string() }
        } else {
            Ident {
                namespace: Some(namespace.trim().to_string()),
                name: raw_name.trim().to_string(),
            }
        }
    }

    pub fn new_raw(raw_name: &str) -> Ident {
        let v: Vec<&str> = raw_name.rsplitn(2, '.').collect();
        if v.len() > 1 {
            Ident { namespace: Some(v[1].trim().to_string()), name: v[0].trim().to_string() }
        } else {
            Ident { namespace: None, name: raw_name.trim().to_string() }
        }
    }

    pub fn fq(&self) -> (Option<String>, String) {
        (self.namespace.clone(), self.name.clone())
    }

    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    pub fn is_base_type(&self) -> bool {
        // TODO add more of zx.banjo
        match self.namespace {
            Some(ref n) => n == "zx",
            None => false,
        }
    }
}

impl Attrs {
    #[allow(dead_code)]
    pub fn has_attributes(&self) -> bool {
        self.0.len() > 0
    }

    pub fn has_attribute(&self, key: &str) -> bool {
        self.0.iter().any(|attr| attr.key == key)
    }

    pub fn get_attribute<'a>(&'a self, key: &str) -> Option<&'a String> {
        if let Some(attr) = self.0.iter().find(|attr| attr.key == key) {
            if let Some(ref val) = attr.val {
                Some(val)
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn from_pair(pair: Pair<'_, Rule>) -> Result<Attrs, ParseError> {
        let mut attrs = Attrs::default();
        let mut doc_string: Option<String> = None; // String::default();
        for inner_pair in pair.into_inner() {
            match inner_pair.as_rule() {
                Rule::doc_comment => {
                    if doc_string.is_none() {
                        doc_string = Some(String::default())
                    }
                    if let Some(ref mut doc_string) = doc_string {
                        *doc_string += inner_pair.as_str().split_at(3).1;
                    }
                }
                Rule::attribute_list => {
                    let attr_string =
                        inner_pair.as_str().trim_start_matches('[').trim_end_matches(']');
                    let attr_pairs = attr_string.split(",");
                    for ap in attr_pairs {
                        if !ap.contains("=") {
                            attrs.0.push(Attr { key: String::from(ap.trim()), val: None });
                        } else {
                            let split: Vec<&str> = ap.split("=").collect();
                            // Strip whitespace and quotes.
                            let val = split[1].trim();
                            let val = val.chars().skip(1).take(val.len() - 2).collect();
                            attrs
                                .0
                                .push(Attr { key: String::from(split[0].trim()), val: Some(val) });
                        }
                    }
                }
                _ => unreachable!(),
            }
        }
        if doc_string.is_some() {
            attrs.0.push(Attr { key: String::from("Doc"), val: doc_string });
        }
        Ok(attrs)
    }
}

#[derive(PartialEq, Eq, Clone, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct Constant(pub String);

impl Constant {
    pub fn from_str(string: &str) -> Self {
        Constant(string.to_string())
    }
}

impl std::fmt::Display for Constant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[derive(PartialEq, Eq, Clone, Serialize, Debug, Hash, PartialOrd, Ord)]
pub enum HandleTy {
    Handle,
    Process,
    Thread,
    Vmo,
    Channel,
    Event,
    Port,
    Interrupt,
    Log,
    Socket,
    Resource,
    EventPair,
    Job,
    Vmar,
    Fifo,
    Guest,
    Timer,
    Bti,
    Profile,
    DebugLog,
}

#[derive(PartialEq, Eq, Clone, Serialize, Debug, Hash, PartialOrd, Ord)]
pub enum Ty {
    Voidptr,
    USize,
    Bool,
    Int8,
    Int16,
    Int32,
    Int64,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    Float32,
    Float64,
    Str { size: Option<Constant>, nullable: bool },
    Vector { ty: Box<Ty>, size: Option<Constant>, nullable: bool },
    Array { ty: Box<Ty>, size: Constant },
    Interface,
    Struct,
    Union,
    Enum,
    Handle { ty: HandleTy, reference: bool },
    // TODO rename this to something less confusing
    Identifier { id: Ident, reference: bool },
}

impl fmt::Display for Ty {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Ty::UInt32 => write!(f, "UInt32"),
            Ty::Identifier { .. } => write!(f, "<Ident>"),
            _ => Err(fmt::Error),
        }
    }
}

impl Ty {
    pub fn is_primitive(&self, ast: &BanjoAst) -> bool {
        match self {
            Ty::Identifier { id, .. } => {
                if id.is_base_type() {
                    return true;
                } else {
                    let resolved_type = ast.id_to_type(id);
                    return resolved_type.is_primitive(&ast);
                }
            }
            Ty::Struct { .. } => false,
            Ty::Union { .. } => false,
            Ty::Interface { .. } => false,
            Ty::Enum { .. } => true,
            Ty::Str { .. } | Ty::Vector { .. } | Ty::Array { .. } | Ty::Handle { .. } => false,
            _ => true,
        }
    }
    pub fn is_reference(&self) -> bool {
        match self {
            Ty::Str { nullable, .. } => *nullable,
            Ty::Vector { nullable, .. } => *nullable,
            Ty::Identifier { reference, .. } => *reference,
            Ty::Handle { reference, .. } => *reference,
            _ => false,
        }
    }

    pub fn from_pair(ns: &str, pair: &Pair<'_, Rule>) -> Result<Self, ParseError> {
        let rule = pair.as_rule();
        match rule {
            Rule::primitive_type => match pair.as_str() {
                "usize" => Ok(Ty::USize),
                "bool" => Ok(Ty::Bool),
                "int8" => Ok(Ty::Int8),
                "int16" => Ok(Ty::Int16),
                "int32" => Ok(Ty::Int32),
                "int64" => Ok(Ty::Int64),
                "uint8" => Ok(Ty::UInt8),
                "uint16" => Ok(Ty::UInt16),
                "uint32" => Ok(Ty::UInt32),
                "uint64" => Ok(Ty::UInt64),
                "float32" => Ok(Ty::Float32),
                "float64" => Ok(Ty::Float64),
                "voidptr" => Ok(Ty::Voidptr),
                _e => Err(ParseError::UnrecognizedType(pair.as_str().to_string())),
            },
            Rule::handle_type => {
                let mut ty = HandleTy::Handle;
                let mut reference = false;
                for inner_pair in pair.clone().into_inner() {
                    match inner_pair.as_rule() {
                        Rule::handle_subtype => {
                            ty = match inner_pair.as_str() {
                                "process" => HandleTy::Process,
                                "thread" => HandleTy::Thread,
                                "vmo" => HandleTy::Vmo,
                                "channel" => HandleTy::Channel,
                                "event" => HandleTy::Event,
                                "port" => HandleTy::Port,
                                "interrupt" => HandleTy::Interrupt,
                                "log" => HandleTy::Log,
                                "socket" => HandleTy::Socket,
                                "resource" => HandleTy::Resource,
                                "eventpair" => HandleTy::EventPair,
                                "job" => HandleTy::Job,
                                "vmar" => HandleTy::Vmar,
                                "fifo" => HandleTy::Fifo,
                                "guest" => HandleTy::Guest,
                                "timer" => HandleTy::Timer,
                                "bti" => HandleTy::Bti,
                                "profile" => HandleTy::Profile,
                                "debuglog" => HandleTy::DebugLog,
                                _e => {
                                    return Err(ParseError::UnrecognizedType(
                                        inner_pair.as_str().to_string(),
                                    ));
                                }
                            }
                        }
                        Rule::reference => {
                            reference = true;
                        }
                        _e => {
                            return Err(ParseError::UnrecognizedType(
                                inner_pair.as_str().to_string(),
                            ));
                        }
                    }
                }
                Ok(Ty::Handle { ty, reference })
            }
            Rule::integer_type => match pair.as_str() {
                "usize" => Ok(Ty::USize),
                "int8" => Ok(Ty::Int8),
                "int16" => Ok(Ty::Int16),
                "int32" => Ok(Ty::Int32),
                "int64" => Ok(Ty::Int64),
                "uint8" => Ok(Ty::UInt8),
                "uint16" => Ok(Ty::UInt16),
                "uint32" => Ok(Ty::UInt32),
                "uint64" => Ok(Ty::UInt64),
                _e => Err(ParseError::NotAnInteger(rule)),
            },
            Rule::array_type => {
                let vec_contents: Vec<Pair<'_, Rule>> = pair.clone().into_inner().collect();
                let ty = Box::new(Ty::from_pair(ns, &vec_contents[0])?);
                let size = Constant::from_str(vec_contents[1].as_str());
                Ok(Ty::Array { ty, size })
            }
            Rule::identifier_type => {
                let mut iter = pair.clone().into_inner();
                let id = iter.next().unwrap().as_str();
                let reference = if let Some(pair) = iter.next() {
                    match pair.as_rule() {
                        Rule::reference => true,
                        e => {
                            return Err(ParseError::UnexpectedToken(e));
                        }
                    }
                } else {
                    false
                };
                Ok(Ty::Identifier { id: Ident::new(ns, id), reference })
            }
            Rule::string_type => {
                let mut size = None;
                let mut nullable = false;
                for inner_pair in pair.clone().into_inner() {
                    match inner_pair.as_rule() {
                        Rule::constant => {
                            size = Some(Constant::from_str(inner_pair.as_str()));
                        }
                        Rule::reference => {
                            nullable = true;
                        }
                        e => {
                            return Err(ParseError::UnexpectedToken(e));
                        }
                    }
                }
                Ok(Ty::Str { size, nullable })
            }
            Rule::vector_type => {
                let mut iter = pair.clone().into_inner();
                let ty = Box::new(Ty::from_pair(ns, &iter.next().unwrap())?);
                let mut size = None;
                let mut nullable = false;
                for inner_pair in iter {
                    match inner_pair.as_rule() {
                        Rule::constant => {
                            size = Some(Constant::from_str(inner_pair.as_str()));
                        }
                        Rule::reference => {
                            nullable = true;
                        }
                        e => {
                            return Err(ParseError::UnexpectedToken(e));
                        }
                    }
                }
                Ok(Ty::Vector { ty, size, nullable })
            }
            _e => Err(ParseError::UnrecognizedType(pair.as_str().to_string())),
        }
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct StructField {
    pub attributes: Attrs,
    pub ty: Ty,
    pub ident: Ident,
    pub val: Option<Constant>,
}

impl StructField {
    pub fn from_pair(ns: &str, pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let mut attributes = Attrs::default();
        let mut ty = None;
        let mut ident = String::default();
        let mut val = None;
        for inner_pair in pair.into_inner() {
            match inner_pair.as_rule() {
                Rule::attributes => attributes = Attrs::from_pair(inner_pair)?,
                Rule::ident => ident = String::from(inner_pair.as_str()),
                Rule::constant => val = Some(Constant::from_str(inner_pair.as_str())),
                _ => ty = Some(Ty::from_pair(ns, &inner_pair)?),
            };
        }
        Ok(StructField {
            attributes: attributes,
            ty: ty.unwrap(),
            ident: Ident::new_raw(ident.as_str()),
            val: val,
        })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct UnionField {
    pub attributes: Attrs,
    pub ty: Ty,
    pub ident: Ident,
}
impl UnionField {
    pub fn from_pair(ns: &str, pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let fields: Vec<Pair<'_, Rule>> = pair.into_inner().collect();
        let ty = &fields[1];
        Ok(UnionField {
            attributes: Attrs::from_pair(fields[0].clone())?,
            ty: Ty::from_pair(ns, ty)?,
            ident: Ident::new_raw(fields[2].as_str()),
        })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct EnumVariant {
    pub attributes: Attrs,
    pub name: String,
    pub size: Constant,
}
impl EnumVariant {
    pub fn from_pair(pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let fields: Vec<Pair<'_, Rule>> = pair.into_inner().collect();
        Ok(EnumVariant {
            attributes: Attrs::from_pair(fields[0].clone())?,
            name: String::from(fields[1].as_str()),
            size: Constant::from_str(fields[2].as_str()),
        })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct Method {
    pub attributes: Attrs,
    pub name: String,
    pub in_params: Vec<(String, Ty)>,
    pub out_params: Vec<(String, Ty)>,
}

impl Method {
    pub fn from_pair(ns: &str, pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let mut attributes = Attrs::default();
        let mut name = String::default();
        let mut in_params = Vec::new();
        let mut out_params = Vec::new();
        for inner_pair in pair.into_inner() {
            match inner_pair.as_rule() {
                Rule::attributes => {
                    attributes = Attrs::from_pair(inner_pair)?;
                }
                Rule::interface_parameters => {
                    let mut fields: Vec<Pair<'_, Rule>> = inner_pair.into_inner().collect();
                    name = String::from(fields[0].as_str());
                    // TODO cleaner way of getting in/out params
                    let inner_params = fields.remove(1);
                    for in_pair in inner_params.into_inner() {
                        match in_pair.as_rule() {
                            Rule::parameter => {
                                let mut param = in_pair.into_inner();
                                let ty = Ty::from_pair(ns, &param.next().unwrap())?;
                                let name = String::from(param.next().unwrap().as_str());
                                in_params.push((name, ty));
                            }
                            e => return Err(ParseError::UnexpectedToken(e)),
                        }
                    }
                    // might not have any return paramaters
                    if fields.len() > 1 {
                        let inner_params = fields.remove(1);
                        for in_pair in inner_params.into_inner() {
                            match in_pair.as_rule() {
                                Rule::parameter => {
                                    let mut param = in_pair.into_inner();
                                    let ty = Ty::from_pair(ns, &param.next().unwrap())?;
                                    let name = String::from(param.next().unwrap().as_str());
                                    out_params.push((name, ty));
                                }
                                e => return Err(ParseError::UnexpectedToken(e)),
                            }
                        }
                    }
                }
                e => return Err(ParseError::UnexpectedToken(e)),
            }
        }
        Ok(Method { attributes, name, in_params, out_params })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub enum Decl {
    Struct { attributes: Attrs, name: Ident, fields: Vec<StructField> },
    Union { attributes: Attrs, name: Ident, fields: Vec<UnionField> },
    Enum { attributes: Attrs, name: Ident, ty: Ty, variants: Vec<EnumVariant> },
    Constant { attributes: Attrs, name: Ident, ty: Ty, value: Constant },
    Interface { attributes: Attrs, name: Ident, methods: Vec<Method> },
    Alias(Ident, Ident),
}

#[derive(PartialEq, Serialize, Debug)]
pub struct BanjoAst {
    pub primary_namespace: String,
    pub namespaces: BTreeMap<String, Vec<Decl>>,
}

impl BanjoAst {
    pub fn id_to_decl(&self, fq_ident: &Ident) -> Result<&Decl, ParseError> {
        let (namespace, ident) = fq_ident.fq();
        for decl in self.namespaces[&namespace.unwrap_or(self.primary_namespace.clone())].iter() {
            match decl {
                Decl::Interface { name, .. } => {
                    if name.name() == ident {
                        return Ok(decl);
                    }
                }
                Decl::Struct { name, .. } => {
                    if name.name() == ident {
                        return Ok(decl);
                    }
                }
                Decl::Union { name, .. } => {
                    if name.name() == ident {
                        return Ok(decl);
                    }
                }
                Decl::Enum { name, .. } => {
                    if name.name() == ident {
                        return Ok(decl);
                    }
                }
                Decl::Alias(to, _from) => {
                    if to == fq_ident {
                        return Ok(decl);
                    }
                }
                Decl::Constant { name, .. } => {
                    if name.name() == ident {
                        return Ok(decl);
                    }
                }
            }
        }
        return Err(ParseError::UnknownDecl);
    }

    pub fn id_to_type(&self, fq_ident: &Ident) -> Ty {
        let (ns, ident) = fq_ident.fq();
        match ident.as_str() {
            "usize" => return Ty::USize,
            "bool" => return Ty::Bool,
            "int8" => return Ty::Int8,
            "int16" => return Ty::Int16,
            "int32" => return Ty::Int32,
            "int64" => return Ty::Int64,
            "uint8" => return Ty::UInt8,
            "uint16" => return Ty::UInt16,
            "uint32" => return Ty::UInt32,
            "uint64" => return Ty::UInt64,
            "float32" => return Ty::Float32,
            "float64" => return Ty::Float64,
            "voidptr" => return Ty::Voidptr,
            _ => {}
        };

        let namespace = match ns {
            Some(ref n) => n,
            None => &self.primary_namespace,
        };

        for decl in self.namespaces[namespace].iter() {
            match decl {
                Decl::Interface { name, .. } => {
                    if name.name() == ident {
                        return Ty::Interface;
                    }
                }
                Decl::Struct { name, .. } => {
                    if name.name() == ident {
                        return Ty::Struct;
                    }
                }
                Decl::Union { name, .. } => {
                    if name.name() == ident {
                        return Ty::Union;
                    }
                }
                Decl::Enum { name, variants, .. } => {
                    if name.name() == ident {
                        return Ty::Enum;
                    }
                    for variant in variants.iter() {
                        if variant.name == ident {
                            return Ty::Identifier { id: name.clone(), reference: false };
                        }
                    }
                }
                Decl::Alias(to, from) => {
                    if to.name == ident {
                        return self.id_to_type(from);
                    }
                }
                Decl::Constant { name, ty, .. } => {
                    if name.name() == ident {
                        return (*ty).clone();
                    }
                }
            }
        }
        panic!("Unidentified {:?}", fq_ident);
    }

    pub fn id_to_attributes(&self, fq_ident: &Ident) -> Option<&Attrs> {
        let (ns, ident) = fq_ident.fq();

        let namespace = match ns {
            Some(ref n) => n,
            None => &self.primary_namespace,
        };

        for decl in self.namespaces[namespace].iter() {
            match decl {
                Decl::Interface { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Struct { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Union { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Enum { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Alias(to, from) => {
                    if to.name == ident {
                        return self.id_to_attributes(from);
                    }
                }
                Decl::Constant { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
            }
        }
        None
    }

    pub fn parse_decl(
        pair: Pair<'_, Rule>,
        ns: &str,
        _namespaces: &BTreeMap<String, Vec<Decl>>,
    ) -> Result<Decl, ParseError> {
        match pair.as_rule() {
            Rule::struct_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut fields = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str().trim());
                        }
                        Rule::struct_field => fields.push(StructField::from_pair(ns, inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(Decl::Struct { attributes, name: Ident::new(ns, &name), fields })
            }
            Rule::enum_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut variants = Vec::default();
                let mut ty = Ty::UInt32;
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str().trim());
                        }
                        Rule::integer_type => {
                            ty = Ty::from_pair(ns, &inner_pair)?;
                        }
                        Rule::enum_field => variants.push(EnumVariant::from_pair(inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(Decl::Enum { attributes, name: Ident::new(ns, name.as_str()), ty, variants })
            }
            Rule::union_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut fields = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str().trim());
                        }
                        Rule::union_field => fields.push(UnionField::from_pair(ns, inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(Decl::Union { attributes, name: Ident::new(ns, name.as_str()), fields })
            }
            // TODO extend to be more expressive for banjo
            Rule::interface_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut methods = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str());
                        }
                        Rule::interface_method => methods.push(Method::from_pair(ns, inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(Decl::Interface { attributes, name: Ident::new(ns, name.as_str()), methods })
            }
            Rule::const_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut ty = Ty::UInt32;
                let mut value = Constant(String::from(""));
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str());
                        }
                        Rule::identifier_type | Rule::string_type | Rule::primitive_type => {
                            ty = Ty::from_pair(ns, &inner_pair)?;
                        }
                        Rule::constant => {
                            value = Constant::from_str(inner_pair.clone().as_span().as_str());
                        }
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(Decl::Constant { attributes, name: Ident::new(ns, name.as_str()), ty, value })
            }
            e => Err(ParseError::UnexpectedToken(e)),
        }
    }

    /// Finds the `Decl` in the AST for a `Ty` found inside of another `Decl`.
    /// If |ignore_ref| is true and |ty| is a reference to an identifier, `None`
    /// will be returned instead of the appropriate `Decl`.
    fn type_to_decl(&self, ty: &Ty, ignore_ref: bool) -> Option<&Decl> {
        match ty {
            Ty::Array { ref ty, .. } => self.type_to_decl(ty, ignore_ref),
            Ty::Vector { ref ty, .. } => self.type_to_decl(ty, ignore_ref),
            Ty::Identifier { id, reference } => {
                // don't add edge for a reference
                if ignore_ref && *reference {
                    return None;
                }

                let (_, ident) = id.fq();
                for decl in self.namespaces[&self.primary_namespace].iter() {
                    match decl {
                        Decl::Union { name, .. }
                        | Decl::Constant { name, .. }
                        | Decl::Interface { name, .. }
                        | Decl::Enum { name, .. }
                        | Decl::Struct { name, .. } => {
                            if name.name() == ident {
                                return Some(decl);
                            }
                        }
                        Decl::Alias(to, from) => {
                            if to == id {
                                return self.type_to_decl(&self.id_to_type(from), ignore_ref);
                            }
                        }
                    }
                }
                None
            }
            _ => None,
        }
    }

    // An edge from D1 to D2 means that a C needs to see the declaration
    // of D1 before the declaration of D2. For instance, given the banjo
    //     struct D2 { D1 d; };
    //     struct D1 { int32 x; };
    // D1 has an edge pointing to D2. Note that struct and union pointers,
    // unlike inline structs or unions, do not have dependency edges.
    fn decl_dependencies(&self, decl: &Decl) -> Result<HashSet<&Decl>, ParseError> {
        let mut edges = HashSet::new();

        let mut maybe_add_decl = |ty, ignore_ref| {
            if let Some(type_decl) = self.type_to_decl(ty, ignore_ref) {
                edges.insert(type_decl);
            }
        };

        match decl {
            Decl::Interface { methods, .. } => {
                for method in methods {
                    for (_, ty) in method.in_params.iter() {
                        maybe_add_decl(&ty, false);
                    }
                    for (_, ty) in method.out_params.iter() {
                        maybe_add_decl(&ty, false);
                    }
                }
            }
            Decl::Struct { fields, .. } => {
                for field in fields {
                    maybe_add_decl(&field.ty, true);
                }
            }
            Decl::Union { fields, .. } => {
                for field in fields {
                    maybe_add_decl(&field.ty, true);
                }
            }
            Decl::Alias(_to, from) => {
                maybe_add_decl(&self.id_to_type(from), false);
            }
            // TODO(surajmalhtora): Implement constant.
            Decl::Constant { .. } => (),
            // Enum cannot have dependencies.
            Decl::Enum { .. } => (),
        };

        Ok(edges)
    }

    /// Validates that the declarations are cycle free and returns declaration ordering.
    pub fn validate_declaration_deps(&self) -> Result<Vec<&Decl>, ParseError> {
        // The number of undelcared dependencies for each decl.
        let mut degrees: BTreeMap<&Decl, u32> = BTreeMap::new();
        // Records the decls that depend on each other.
        let mut inverse_dependencies: BTreeMap<&Decl, Vec<&Decl>> = BTreeMap::new();

        for decl in self.namespaces.iter().flat_map(|(_, decls)| decls.iter()) {
            degrees.insert(&decl, 0);
        }

        for decl in self.namespaces.iter().flat_map(|(_, decls)| decls.iter()) {
            let deps = self.decl_dependencies(&decl)?;
            for dep in deps.iter().filter(|&dep| dep != &decl) {
                let entry = degrees.get_mut(&decl).unwrap();
                *entry += 1;
                let entry = inverse_dependencies.entry(&dep).or_insert(Vec::new());
                entry.push(&decl);
            }
        }
        // Remove mutability.
        let inverse_dependencies = inverse_dependencies;

        // Start with all decls that have no incoming edges.
        let mut decls_without_deps = degrees
            .iter()
            .filter(|(_, &degrees)| degrees == 0)
            .map(|(&decl, _)| decl)
            .collect::<VecDeque<_>>();

        let mut decl_order = Vec::new();
        // Pull one out of the queue.
        while let Some(decl) = decls_without_deps.pop_front() {
            assert_eq!(degrees.get(decl), Some(&0));
            decl_order.push(decl);

            // Decrement the incoming degree of all other decls it points to.
            if let Some(inverse_deps) = inverse_dependencies.get(decl) {
                for inverse_dep in inverse_deps {
                    let degree = degrees.get_mut(inverse_dep).unwrap();
                    assert_ne!(*degree, 0);
                    *degree -= 1;
                    if *degree == 0 {
                        decls_without_deps.push_back(inverse_dep);
                    }
                }
            }
        }

        if decl_order.len() != degrees.len() {
            // We didn't visit all the edges! There was a cycle.
            return Err(ParseError::InvalidDeps(String::from(
                "There is a cycle in the declarations",
            )));
        }

        Ok(decl_order
            .into_iter()
            .filter(|decl| {
                let ident = match decl {
                    Decl::Interface { name, .. } => name,
                    Decl::Struct { name, .. } => name,
                    Decl::Union { name, .. } => name,
                    Decl::Enum { name, .. } => name,
                    Decl::Alias(to, _from) => to,
                    Decl::Constant { name, .. } => name,
                };
                if let Some(ref ns) = ident.fq().0 {
                    ns == &self.primary_namespace
                } else {
                    true
                }
            })
            .collect())
    }

    // Validates that the constants are of the right type.
    fn validate_constants(&self) -> Result<(), ParseError> {
        // Search ast for constants.
        for (ty, constant) in
            self.namespaces.iter().flat_map(|(_, decls)| decls.iter()).filter_map(|decl| match decl
            {
                Decl::Constant { ty, value, .. } => Some((ty, value)),
                _ => None,
            })
        {
            let Constant(string) = constant;
            if string.len() > 2 && string.get(0..2) == Some("0x") {
                // TODO(bwb): validate constants if hex as well
                return Ok(());
            }
            match ty {
                Ty::Int8 => {
                    i8::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Int16 => {
                    i16::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Int32 => {
                    i32::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Int64 => {
                    i64::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::USize => {
                    usize::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::UInt8 => {
                    u8::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::UInt16 => {
                    u16::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::UInt32 | Ty::UInt64 => {
                    u32::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Bool => {
                    bool::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Str { .. } => {
                    if !string.starts_with("\"") || !string.ends_with("\"") {
                        return Err(ParseError::InvalidConstType(constant.clone(), ty.clone()));
                    }
                }
                _ => {
                    let ident_ty = self.id_to_type(&Ident::new_raw(string));
                    if *ty != ident_ty {
                        return Err(ParseError::InvalidConstType(constant.clone(), ty.clone()));
                    }
                }
            };
        }

        // TODO(surajmalhotra): Find every bound array, string, and validate their bound is a valid
        // usize.
        Ok(())
    }

    pub fn parse(pair_vec: Vec<Pairs<'_, Rule>>) -> Result<Self, ParseError> {
        let mut primary_namespace = None;
        let mut namespaces = BTreeMap::default();

        for pairs in pair_vec {
            for pair in pairs {
                let mut current_namespace = String::default();
                let mut namespace = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::library_header => {
                            for token in inner_pair.into_inner() {
                                if Rule::compound_ident == token.as_rule() {
                                    current_namespace = String::from(token.as_str());
                                    if let Some(primary_namespace) = primary_namespace {
                                        if primary_namespace == current_namespace {
                                            return Err(ParseError::AlreadyPrimaryNamespace);
                                        }
                                    }
                                    primary_namespace = Some(String::from(token.as_str()));
                                }
                            }
                        }
                        Rule::using_decl => {
                            let contents: Vec<&str> =
                                inner_pair.clone().into_inner().map(|p| p.as_str()).collect();
                            namespace.push(Decl::Alias(
                                Ident::new_raw(contents[0]),
                                Ident::new_raw(contents[1]),
                            ));
                        }
                        Rule::using => {
                            for (cnt, pair) in inner_pair.into_inner().enumerate() {
                                if cnt == 0 {
                                    if !namespaces.contains_key(pair.as_str()) {
                                        return Err(ParseError::UnImported(format!(
                                            "{}",
                                            pair.as_str()
                                        )));
                                    }
                                } else {
                                    return Err(ParseError::NotYetSupported(String::from(
                                        "'as' in library imports",
                                    )));
                                }
                            }
                        }
                        Rule::struct_declaration
                        | Rule::union_declaration
                        | Rule::enum_declaration
                        | Rule::interface_declaration
                        | Rule::const_declaration => {
                            let decl =
                                Self::parse_decl(inner_pair, &current_namespace, &namespaces)?;
                            namespace.push(decl)
                        }
                        Rule::EOI => (),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    };
                }
                namespaces.insert(current_namespace, namespace);
            }
        }

        let ast =
            BanjoAst { primary_namespace: primary_namespace.unwrap(), namespaces: namespaces };

        let _ = ast.validate_declaration_deps()?;
        ast.validate_constants()?;

        Ok(ast)
    }
}
