//! defines `ParseError` and others.
//!
//! パーサーが出すエラーを定義
use std::fmt;

use erg_common::error::{
    ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay, SubMessage,
};
use erg_common::io::Input;
use erg_common::style::{Attribute, Color, StyledStr, StyledString, StyledStrings, THEME};
use erg_common::traits::Stream;
use erg_common::{fmt_iter, fmt_vec_split_with, impl_display_and_error, impl_stream, switch_lang};

use crate::ast::Module;
use crate::token::TokenKind;

#[derive(Debug)]
pub struct LexError(Box<ErrorCore>); // ErrorCore is large, so use Box

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

impl std::error::Error for LexError {}

impl From<ErrorCore> for LexError {
    fn from(core: ErrorCore) -> Self {
        Self(Box::new(core))
    }
}

impl From<LexError> for ErrorCore {
    fn from(err: LexError) -> Self {
        *err.0
    }
}

#[derive(Debug)]
pub struct LexErrors(Vec<LexError>);

impl_stream!(LexErrors, LexError);

impl fmt::Display for LexErrors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "LexErrors({})", fmt_iter(self.0.iter()))
    }
}

impl std::error::Error for LexErrors {}

const ERR: Color = THEME.colors.error;
const WARN: Color = THEME.colors.warning;
const HINT: Color = THEME.colors.hint;
#[cfg(not(feature = "pretty"))]
const ATTR: Attribute = Attribute::Bold;
#[cfg(feature = "pretty")]
const ATTR: Attribute = Attribute::Underline;

impl LexError {
    pub fn new(core: ErrorCore) -> Self {
        Self(Box::new(core))
    }

    pub fn set_hint<S: Into<String>>(&mut self, hint: S) {
        if let Some(sub_msg) = self.0.sub_messages.get_mut(0) {
            sub_msg.set_hint(hint)
        }
    }

    /* Parser Bug */
    pub fn compiler_bug(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
        let mut err = Self::new(ErrorCore::bug(errno, loc, fn_name, line));
        err.set_hint("parser bug");
        err
    }

    pub fn feature_error(errno: usize, loc: Location, name: &str) -> Self {
        let main_msg = switch_lang!(
            "japanese" => format!("この機能({name})はまだ正式に提供されていません"),
            "simplified_chinese" => format!("此功能（{name}）尚未实现"),
            "traditional_chinese" => format!("此功能（{name}）尚未實現"),
            "english" => format!("this feature({name}) is not implemented yet"),
        );
        let main_msg = StyledStr::new(&main_msg, Some(ERR), Some(ATTR)).to_string();
        Self::new(ErrorCore::new(
            vec![SubMessage::only_loc(loc)],
            main_msg,
            errno,
            FeatureError,
            loc,
        ))
    }

    pub fn invalid_none_match(errno: usize, loc: Location, fn_name: &str, line: u32) -> Self {
        let mut err = Self::new(ErrorCore::bug(errno, loc, fn_name, line));
        err.set_hint("None is got");
        err
    }

    pub fn failed_to_analyze_block(errno: usize, loc: Location) -> LexError {
        Self::new(ErrorCore::new(
            vec![],
            switch_lang!(
                "japanese" => "ブロックの解析に失敗しました",
                "simplified_chinese" => "无法解析块",
                "traditional_chinese" => "無法解析塊",
                "english" => "failed to parse a block",
            ),
            errno,
            CompilerSystemError,
            loc,
        ))
    }

    pub fn unexpected_token_error(errno: usize, loc: Location, found: &str) -> ParseError {
        let mut fnd = StyledStrings::default();
        switch_lang!(
            "japanese" =>fnd.push_str("予期しないトークンです: "),
            "simplified_chinese" => fnd.push_str("意外的token: "),
            "traditional_chinese" => fnd.push_str("意外的token: "),
            "english" => fnd.push_str("unexpected token: "),
        );
        fnd.push_str_with_color(found, ERR);
        let main_msg = switch_lang!(
            "japanese" => "無効な構文です",
            "simplified_chinese" => "无效的语法",
            "traditional_chinese" => "無效的語法",
            "english" => "invalid syntax",
        );
        Self::new(ErrorCore::new(
            vec![SubMessage::ambiguous_new(loc, vec![fnd.to_string()], None)],
            main_msg,
            errno,
            CompilerSystemError,
            loc,
        ))
    }

    /* Parser Errors */
    pub fn simple_syntax_error(errno: usize, loc: Location) -> Self {
        Self::new(ErrorCore::new(
            vec![SubMessage::only_loc(loc)],
            switch_lang!(
                "japanese" => "不正な構文です",
                "simplified_chinese" => "无效的语法",
                "traditional_chinese" => "無效的語法",
                "english" => "invalid syntax",
            ),
            errno,
            SyntaxError,
            loc,
        ))
    }

    pub fn syntax_error<S: Into<String>>(
        errno: usize,
        loc: Location,
        desc: S,
        hint: Option<String>,
    ) -> Self {
        Self::new(ErrorCore::new(
            vec![SubMessage::ambiguous_new(loc, vec![], hint)],
            desc,
            errno,
            SyntaxError,
            loc,
        ))
    }

    pub fn unexpected_token<S: fmt::Display>(
        errno: usize,
        loc: Location,
        expected: S,
        got: TokenKind,
    ) -> Self {
        Self::new(ErrorCore::new(
            vec![SubMessage::ambiguous_new(loc, vec![], None)],
            switch_lang!(
                "japanese" => format!("{expected}が期待されましたが、{got}となっています"),
                "simplified_chinese" => format!("期望: {expected}，得到: {got}"),
                "traditional_chinese" => format!("期望: {expected}，得到: {got}"),
                "english" => format!("expected: {expected}, got: {got}"),
            ),
            errno,
            SyntaxError,
            loc,
        ))
    }

    pub fn invalid_chunk_error(errno: usize, loc: Location) -> LexError {
        let msg = switch_lang!(
            "japanese" => "無効な構文です",
            "simplified_chinese" => "无效的语法",
            "traditional_chinese" => "無效的語法",
            "english" => "invalid syntax",
        );
        let hint = switch_lang!(
            "japanese" => "セミコロンを追加するか改行をしてください",
            "simplified_chinese" => "应该添加分号或换行符",
            "traditional_chinese" => "應該添加分號或換行符",
            "english" => "semicolon or newline should be added",
        )
        .to_string();
        Self::syntax_error(errno, loc, msg, Some(hint))
    }

    pub fn syntax_warning<S: Into<String>>(
        errno: usize,
        loc: Location,
        desc: S,
        hint: Option<String>,
    ) -> Self {
        Self::new(ErrorCore::new(
            vec![SubMessage::ambiguous_new(loc, vec![], hint)],
            desc,
            errno,
            SyntaxWarning,
            loc,
        ))
    }

    pub fn invalid_definition_of_last_block(errno: usize, loc: Location) -> LexError {
        Self::syntax_error(
            errno,
            loc,
            switch_lang!(
                "japanese" => "ブロックの終端で変数を定義することは出来ません",
                "simplified_chinese" => "无法在块的末尾定义变量",
                "traditional_chinese" => "無法在塊的末尾定義變量",
                "english" => "cannot define a variable at the end of a block",
            ),
            None,
        )
    }

    pub fn invalid_token_error(
        errno: usize,
        loc: Location,
        main_msg: &str,
        expect: &str,
        found: &str,
    ) -> LexError {
        let expect = StyledStr::new(expect, Some(HINT), Some(ATTR));
        let expect = switch_lang!(
                "japanese" => format!("予期したトークン: {expect}"),
                "simplified_chinese" => format!("期望: {expect}"),
                "traditional_chinese" => format!("期望: {expect}"),
                "english" => format!("expect: {expect}"),
        );
        let found = StyledStr::new(found, Some(ERR), Some(ATTR));
        let found = switch_lang!(
                "japanese" => format!("与えられた: {found}"),
                "simplified_chinese" => format!("但找到: {found}"),
                "traditional_chinese" => format!("但找到: {found}"),
                "english" => format!("but found: {found}"),
        );
        Self::new(ErrorCore::new(
            vec![SubMessage::ambiguous_new(loc, vec![expect, found], None)],
            main_msg,
            errno,
            SyntaxError,
            loc,
        ))
    }

    pub fn invalid_seq_elems_error<S: fmt::Display>(
        errno: usize,
        loc: Location,
        expected: &[S],
        got: TokenKind,
    ) -> LexError {
        let hint = switch_lang!(
            "japanese" => format!("{}が期待されましたが、{got}が与えれられました", fmt_vec_split_with(expected, " または ")),
            "simplified_chinese" => format!("期望: {}，但找到: {got}", fmt_vec_split_with(expected, " 或 ")),
            "traditional_chinese" => format!("期望: {}，但找到: {got}", fmt_vec_split_with(expected, " 或 ")),
            "english" => format!("expect: {}, got: {got}", fmt_vec_split_with(expected, " or ")),
        );
        let msg = switch_lang!(
            "japanese" => "要素の列挙の仕方が不正です",
            "simplified_chinese" => "无效的Sequential元素声明",
            "traditional_chinese" => "無效的Sequential元素聲明",
            "english" => "invalid sequential elements declaration",
        );
        Self::syntax_error(errno, loc, msg, Some(hint))
    }

    pub fn invalid_record_element_err(errno: usize, loc: Location) -> LexError {
        let msg = switch_lang!(
            "japanese" => "レコード型要素の列挙の仕方が不正です",
            "simplified_chinese" => "无效的Record类型元素声明",
            "traditional_chinese" => "無效的Record類型元素聲明",
            "english" => "invalid record type element declarations",
        )
        .to_string();
        let hint = switch_lang!(
            "japanese" => {
                let record = StyledStr::new("レコード型", Some(HINT), Some(ATTR));
                let var = StyledStr::new("属性", Some(HINT), Some(ATTR));
                let def = StyledStr::new("属性=リテラル", Some(HINT), Some(ATTR));
                let obj = StyledStr::new("属性=オブジェクト", Some(HINT), Some(ATTR));
                format!("{record}では{var}か{def}、{obj}のみ宣言することができます")
            },
            "simplified_chinese" => {
                let record = StyledStr::new("Record类型", Some(HINT), Some(ATTR));
                let var = StyledStr::new("属性", Some(HINT), Some(ATTR));
                let def = StyledStr::new("属性=lit", Some(HINT), Some(ATTR));
                let obj = StyledStr::new("属性=object", Some(HINT), Some(ATTR));
                format!("{record}中只能声明 {var}、{def} 或 {obj}")
            },
            "traditional_chinese" => {
                let record = StyledStr::new("Record類型", Some(HINT), Some(ATTR));
                let var = StyledStr::new("屬性", Some(HINT), Some(ATTR));
                let def = StyledStr::new("屬性=lit", Some(HINT), Some(ATTR));
                let obj = StyledStr::new("屬性=object", Some(HINT), Some(ATTR));
                format!("{record}中只能声明 {var}、{def} 或 {obj}")
            },
            "english" => {
                let record = StyledStr::new("Record", Some(HINT), Some(ATTR));
                let var = StyledStr::new("attr", Some(HINT), Some(ATTR));
                let def = StyledStr::new("attr=lit", Some(HINT), Some(ATTR));
                let obj = StyledStr::new("attr=object", Some(HINT), Some(ATTR));
                format!("only {var}, {def} or {obj} can be declared in {record}")
            },
        );
        Self::syntax_error(errno, loc, msg, Some(hint))
    }

    pub fn invalid_data_pack_definition(errno: usize, loc: Location, fnd: &str) -> ParseError {
        let msg = switch_lang!(
            "japanese" => "データクラスの中身が異なります",
            "simplified_chinese" => "数据类的内容无效",
            "traditional_chinese" => "數據類的內容無效",
            "english" => "invalid contents of data class",
        );
        let expt = StyledStr::new("Record Type", Some(HINT), Some(ATTR));
        let expect = switch_lang!(
            "japanese" => format!("予期した型: {expt}"),
            "simplified_chinese" => format!("期望的类型: {expt}"),
            "traditional_chinese" => format!("期望的類型: {expt}"),
            "english" => format!("expect type: {expt}"),
        );
        let fnd = StyledStr::new(fnd, Some(ERR), Some(ATTR));
        let found = switch_lang!(
            "japanese" => format!("与えられた型: {fnd}"),
            "simplified_chinese" => format!("但找到: {fnd}"),
            "traditional_chinese" => format!("但找到: {fnd}"),
            "english" => format!("but found: {fnd}"),
        );
        let sub = SubMessage::ambiguous_new(loc, vec![expect, found], None);
        Self::new(ErrorCore::new(vec![sub], msg, errno, SyntaxError, loc))
    }

    pub fn expect_keyword(errno: usize, loc: Location) -> ParseError {
        let msg = switch_lang!(
            "japanese" => "キーワードが指定されていません",
            "simplified_chinese" => "未指定关键字",
            "traditional_chinese" => "未指定關鍵字",
            "english" => "keyword is not specified",
        );
        let keyword = StyledStr::new("keyword", Some(HINT), Some(ATTR));
        let sub_msg = switch_lang!(
            "japanese" => format!("予期した: {keyword}"),
            "simplified_chinese" => format!("期望: {keyword}"),
            "traditional_chinese" => format!("期望: {keyword}"),
            "english" => format!("expect: {keyword}"),
        );
        let sub = SubMessage::ambiguous_new(loc, vec![sub_msg], None);
        Self::new(ErrorCore::new(vec![sub], msg, errno, SyntaxError, loc))
    }

    pub fn invalid_non_default_parameter(errno: usize, loc: Location) -> ParseError {
        let msg = switch_lang!(
            "japanese" => "非デフォルト引数はデフォルト引数の後に指定できません",
            "simplified_chinese" => "默认实参后面跟着非默认实参",
            "traditional_chinese" => "默認實參後面跟著非默認實參",
            "english" => "non-default argument follows default argument",
        );

        let walrus = StyledStr::new(":=", Some(HINT), Some(ATTR));
        let sub_msg = switch_lang!(
            "japanese" => format!("{walrus}を使用してください"),
            "simplified_chinese" => format!("应该使用{walrus}"),
            "traditional_chinese" => format!("應該使用{walrus}"),
            "english" => format!("{walrus} should be used"),
        );
        let sub = SubMessage::ambiguous_new(loc, vec![sub_msg], None);
        Self::new(ErrorCore::new(vec![sub], msg, errno, SyntaxError, loc))
    }

    pub fn invalid_colon_style(errno: usize, loc: Location) -> ParseError {
        let desc = switch_lang!(
            "japanese" => "コロンの後ろでカンマを使った区切りは使うことができません",
            "simplified_chinese" => "冒号后不能使用逗号分隔符",
            "traditional_chinese" => "冒號後不能使用逗號分隔符",
            "english" => "comma delimiters cannot be used after a colon",
        );
        let hint = switch_lang!(
            "japanese" => "カンマを削除してください",
            "simplified_chinese" => "应该去掉逗号",
            "traditional_chinese" => "應該去掉逗號",
            "english" => "comma should be removed",
        )
        .to_string();
        Self::syntax_error(errno, loc, desc, Some(hint))
    }

    pub fn unclosed_error(errno: usize, loc: Location, closer: &str, ty: &str) -> ParseError {
        let msg = switch_lang!(
            "japanese" => format!("{ty}が{closer}で閉じられていません"),
            "simplified_chinese" => format!("{ty}没有用{closer}关闭"),
            "traditional_chinese" => format!("{ty}没有用{closer}關閉"),
            "english" => format!("{ty} is not closed with a {closer}"),
        );

        let closer = StyledStr::new(closer, Some(HINT), Some(ATTR));
        let sub_msg = switch_lang!(
            "japanese" => format!("{closer}を追加してください"),
            "simplified_chinese" => format!("{closer}应该被添加"),
            "traditional_chinese" => format!("{closer}應該被添加"),
            "english" => format!("{closer} should be added"),
        );

        let sub = SubMessage::ambiguous_new(loc, vec![sub_msg], None);
        Self::new(ErrorCore::new(vec![sub], msg, errno, SyntaxError, loc))
    }

    pub fn expect_method_error(errno: usize, loc: Location) -> ParseError {
        let mut expect = StyledStrings::default();
        switch_lang!(
            "japanese" => expect.push_str("予期した: "),
            "simplified_chinese" => expect.push_str("期望: "),
            "traditional_chinese" => expect.push_str("期望: "),
            "english" => expect.push_str("expect: "),
        );
        expect.push_str_with_color_and_attr(
            switch_lang!(
                "japanese" => "メソッド",
                "simplified_chinese" => "方法",
                "traditional_chinese" => "方法",
                "english" => "method",
            ),
            HINT,
            ATTR,
        );
        let sub_msg = SubMessage::ambiguous_new(loc, vec![expect.to_string()], None);
        let main_msg = switch_lang!(
            "japanese" => "クラスメソッドの定義が必要です",
            "simplified_chinese" => "需要类方法定义",
            "traditional_chinese" => "需要類方法定義",
            "english" => "class method definitions are needed",
        );
        Self::new(ErrorCore::new(
            vec![sub_msg],
            main_msg,
            errno,
            SyntaxError,
            loc,
        ))
    }

    pub fn expect_accessor(errno: usize, loc: Location) -> ParseError {
        let msg = switch_lang!(
            "japanese" => "無効な構文です",
            "simplified_chinese" => "无效的语法",
            "traditional_chinese" => "無效的語法",
            "english" => "invalid syntax",
        );
        let sub_msg = switch_lang!(
            "japanese" => "アクセッサ―が期待されています",
            "simplified_chinese" => "期望存取器",
            "traditional_chinese" => "期望存取器",
            "english" => "expect accessor",
        )
        .to_string();
        let sub = SubMessage::ambiguous_new(loc, vec![sub_msg], None);
        Self::new(ErrorCore::new(vec![sub], msg, errno, SyntaxError, loc))
    }

    pub fn invalid_acc_chain(errno: usize, loc: Location, found: &str) -> ParseError {
        let expt = switch_lang!(
            "japanese" => {
                let method = StyledStr::new("メソッド", Some(HINT), Some(ATTR));
                let lit = StyledStr::new("NatLit", Some(HINT), Some(ATTR));
                let newline = StyledStr::new("改行", Some(HINT), Some(ATTR));
                let arr = StyledStr::new("配列", Some(HINT), Some(ATTR));
                format!("予期: {method}、{lit}、{newline}、{arr}")
            },
            "simplified_chinese" => {
                let method = StyledStr::new("方法", Some(HINT), Some(ATTR));
                let lit = StyledStr::new("NatLit", Some(HINT), Some(ATTR));
                let newline = StyledStr::new("换行", Some(HINT), Some(ATTR));
                let arr = StyledStr::new("数组", Some(HINT), Some(ATTR));
                format!("期望: {method}, {lit}, {newline}, {arr}")
            },
            "traditional_chinese" => {
                let method = StyledStr::new("方法", Some(HINT), Some(ATTR));
                let lit = StyledStr::new("NatLit", Some(HINT), Some(ATTR));
                let newline = StyledStr::new("换行", Some(HINT), Some(ATTR));
                let arr = StyledStr::new("數組", Some(HINT), Some(ATTR));
                format!("期望: {method}, {lit}, {newline}, {arr}")
            },
            "english" => {
                let method = StyledStr::new("method", Some(HINT), Some(ATTR));
                let lit = StyledStr::new("NatLit", Some(HINT), Some(ATTR));
                let newline = StyledStr::new("newline", Some(HINT), Some(ATTR));
                let arr = StyledStr::new("array", Some(HINT), Some(ATTR));
                format!("expect: {method}, {lit}, {newline}, {arr}")
            },
        );

        let fnd = switch_lang!(
            "japanese" =>format!("与えられた: {}", StyledStr::new(found, Some(ERR), None)),
            "simplified_chinese" => format!("但找到: {}", StyledStr::new(found, Some(ERR), None)),
            "traditional_chinese" => format!("但找到: {}", StyledStr::new(found, Some(ERR), None)),
            "english" => format!("but found: {}", StyledStr::new(found, Some(ERR), None)),
        );
        let sub = SubMessage::ambiguous_new(loc, vec![expt, fnd], None);
        let msg = switch_lang!(
            "japanese" => "無効なアクセス呼び出しです",
            "simplified_chinese" => "无效的访问调用",
            "traditional_chinese" => "無效的訪問調用",
            "english" => "invalid access call",
        )
        .to_string();
        Self::new(ErrorCore::new(vec![sub], msg, errno, SyntaxError, loc))
    }

    pub fn expect_type_specified(errno: usize, loc: Location) -> ParseError {
        let msg = switch_lang!(
            "japanese" => "型指定が不正です",
            "traditional_chinese" => "无效的类型说明",
            "simplified_chinese" => "無效的類型說明",
            "english" => "invalid type specification",
        );
        Self::syntax_error(errno, loc, msg, None)
    }

    pub fn duplicate_elem_warning(errno: usize, loc: Location, elem: String) -> Self {
        let elem = StyledString::new(elem, Some(WARN), Some(Attribute::Underline));
        Self::new(ErrorCore::new(
            vec![SubMessage::only_loc(loc)],
            switch_lang!(
                "japanese" => format!("重複する要素です: {elem}"),
                "simplified_chinese" => format!("{elem}"),
                "traditional_chinese" => format!("{elem}"),
                "english" => format!("duplicated element: {elem}"),
            ),
            errno,
            SyntaxWarning,
            loc,
        ))
    }
}

pub type LexResult<T> = Result<T, LexError>;

pub type ParseError = LexError;
pub type ParseErrors = LexErrors;
pub type ParseWarning = LexError;
pub type ParseWarnings = LexErrors;
pub type ParseResult<T> = Result<T, ()>;

#[derive(Debug)]
pub struct DesugaringError {
    pub core: ErrorCore,
}

impl DesugaringError {
    pub const fn new(core: ErrorCore) -> Self {
        Self { core }
    }
}

#[derive(Debug)]
pub struct DesugaringErrors(Vec<DesugaringError>);

impl_stream!(DesugaringErrors, DesugaringError);

pub type DesugaringResult<T> = Result<T, DesugaringError>;

#[derive(Debug)]
pub struct ParserRunnerError {
    pub core: ErrorCore,
    pub input: Input,
}

impl_display_and_error!(ParserRunnerError);

impl ErrorDisplay for ParserRunnerError {
    fn core(&self) -> &ErrorCore {
        &self.core
    }
    fn input(&self) -> &Input {
        &self.input
    }
    fn caused_by(&self) -> &str {
        ""
    }
    fn ref_inner(&self) -> Option<&Self> {
        None
    }
}

impl ParserRunnerError {
    pub const fn new(core: ErrorCore, input: Input) -> Self {
        Self { core, input }
    }
}

#[derive(Debug)]
pub struct ParserRunnerErrors(Vec<ParserRunnerError>);

impl std::error::Error for ParserRunnerErrors {}

impl_stream!(ParserRunnerErrors, ParserRunnerError);

impl MultiErrorDisplay<ParserRunnerError> for ParserRunnerErrors {}

impl fmt::Display for ParserRunnerErrors {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt_all(f)
    }
}

impl ParserRunnerErrors {
    pub fn convert(input: &Input, errs: ParseErrors) -> Self {
        Self(
            errs.into_iter()
                .map(|err| ParserRunnerError::new(*err.0, input.clone()))
                .collect(),
        )
    }
}

pub type ParserRunnerResult<T> = Result<T, ParserRunnerError>;

pub type LexerRunnerError = ParserRunnerError;
pub type LexerRunnerErrors = ParserRunnerErrors;
pub type ParserRunnerWarning = ParserRunnerError;
pub type ParserRunnerWarnings = ParserRunnerErrors;
pub type LexerRunnerResult<T> = Result<T, LexerRunnerError>;

#[derive(Debug)]
pub struct CompleteArtifact<A = Module, Es = ParseErrors> {
    pub ast: A,
    pub warns: Es,
}

impl<A, Es> CompleteArtifact<A, Es> {
    pub fn new(ast: A, warns: Es) -> Self {
        Self { ast, warns }
    }

    pub fn map<U>(self, f: impl FnOnce(A) -> U) -> CompleteArtifact<U, Es> {
        CompleteArtifact {
            ast: f(self.ast),
            warns: self.warns,
        }
    }
}

#[derive(Debug)]
pub struct IncompleteArtifact<A = Module, Es = ParseErrors> {
    pub ast: Option<A>,
    pub warns: Es,
    pub errors: Es,
}

impl<A> From<ParserRunnerErrors> for IncompleteArtifact<A, ParserRunnerErrors> {
    fn from(value: ParserRunnerErrors) -> IncompleteArtifact<A, ParserRunnerErrors> {
        IncompleteArtifact::new(None, ParserRunnerErrors::empty(), value)
    }
}

impl<A> From<LexErrors> for IncompleteArtifact<A, ParseErrors> {
    fn from(value: LexErrors) -> IncompleteArtifact<A, ParseErrors> {
        IncompleteArtifact::new(None, ParseErrors::empty(), value)
    }
}

impl<A, Es> IncompleteArtifact<A, Es> {
    pub fn new(ast: Option<A>, warns: Es, errors: Es) -> Self {
        Self { ast, warns, errors }
    }

    pub fn map_errs<U>(self, f: impl Fn(Es) -> U) -> IncompleteArtifact<A, U> {
        IncompleteArtifact {
            ast: self.ast,
            warns: f(self.warns),
            errors: f(self.errors),
        }
    }

    pub fn map_mod<U>(self, f: impl FnOnce(A) -> U) -> IncompleteArtifact<U, Es> {
        IncompleteArtifact {
            ast: self.ast.map(f),
            warns: self.warns,
            errors: self.errors,
        }
    }
}

#[derive(Debug)]
pub struct ErrorArtifact<Es = ParseErrors> {
    pub warns: Es,
    pub errors: Es,
}

impl<Es> ErrorArtifact<Es> {
    pub fn new(warns: Es, errors: Es) -> ErrorArtifact<Es> {
        Self { warns, errors }
    }
}
