kdl_script/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::{fs::File, io::Read, path::Path, sync::Arc};
4
5use kdl::KdlDocument;
6use miette::{Diagnostic, NamedSource};
7use thiserror::Error;
8
9pub use parse::{KdlScriptParseError, ParsedProgram, PunEnv};
10pub use types::{Definition, DefinitionGraph, KdlScriptTypeError, TypedProgram};
11
12#[cfg(feature = "eval")]
13pub mod eval;
14pub mod parse;
15pub mod spanned;
16#[cfg(test)]
17mod tests;
18pub mod types;
19
20#[derive(Debug, Error, Diagnostic)]
21pub enum KdlScriptError {
22    #[error(transparent)]
23    Io(#[from] std::io::Error),
24
25    #[error(transparent)]
26    #[diagnostic(transparent)]
27    Kdl(#[from] kdl::KdlError),
28
29    #[error(transparent)]
30    #[diagnostic(transparent)]
31    Parse(#[from] KdlScriptParseError),
32
33    #[error(transparent)]
34    #[diagnostic(transparent)]
35    Type(#[from] KdlScriptTypeError),
36}
37
38pub struct ErrorHandler {
39    pub error_style: ErrorStyle,
40    pub error_mode: ErrorMode,
41}
42
43pub enum ErrorMode {
44    Gather(Vec<KdlScriptError>),
45    Scream,
46}
47
48pub enum ErrorStyle {
49    Human,
50    Json,
51}
52
53pub struct Compiler {
54    // error_handler: ErrorHandler,
55    pub source: Option<Arc<NamedSource>>,
56    pub parsed: Option<Arc<ParsedProgram>>,
57    pub typed: Option<Arc<TypedProgram>>,
58}
59
60pub type Result<T> = std::result::Result<T, KdlScriptError>;
61
62impl Compiler {
63    pub fn new() -> Self {
64        Self {
65            /*
66            error_handler: ErrorHandler {
67                error_mode: ErrorMode::Scream,
68                error_style: ErrorStyle::Human,
69            },
70             */
71            source: None,
72            parsed: None,
73            typed: None,
74        }
75    }
76
77    pub fn compile_path(
78        &mut self,
79        src_path: impl AsRef<Path>,
80    ) -> std::result::Result<Arc<TypedProgram>, KdlScriptError> {
81        let src_path = src_path.as_ref();
82        let input_name = src_path.display().to_string();
83        let mut input_file = File::open(src_path)?;
84        let mut input_string = String::new();
85        input_file.read_to_string(&mut input_string)?;
86
87        self.compile_string(&input_name, input_string)
88    }
89
90    pub fn compile_string(
91        &mut self,
92        input_name: &str,
93        input_string: String,
94    ) -> std::result::Result<Arc<TypedProgram>, KdlScriptError> {
95        let input_string = Arc::new(input_string);
96
97        let src = Arc::new(miette::NamedSource::new(input_name, input_string.clone()));
98        self.source = Some(src.clone());
99
100        let kdl_doc: KdlDocument = input_string.parse::<kdl::KdlDocument>()?;
101        let parsed = Arc::new(parse::parse_kdl_script(self, src, &kdl_doc)?);
102        self.parsed = Some(parsed.clone());
103        let typed = Arc::new(types::typeck(self, &parsed)?);
104        self.typed = Some(typed.clone());
105
106        Ok(typed)
107    }
108
109    pub fn eval(&mut self) -> std::result::Result<Option<i64>, KdlScriptError> {
110        if let (Some(src), Some(parsed)) = (&self.source, &self.parsed) {
111            if parsed.funcs.contains_key("main") {
112                let val = eval::eval_kdl_script(src, parsed)?;
113                return Ok(Some(val));
114            }
115        }
116        Ok(None)
117    }
118}
119
120impl Default for Compiler {
121    fn default() -> Self {
122        Self::new()
123    }
124}