Skip to main content

typr_core/
lib.rs

1//! # TypR Core
2//!
3//! Pure logic for TypR - a typed superset of R.
4//!
5//! This crate contains the core functionality that can be compiled to WebAssembly:
6//! - Parsing TypR source code
7//! - Type checking
8//! - Transpilation to R
9//!
10//! ## Architecture
11//!
12//! The crate is designed to be platform-agnostic by using trait abstractions
13//! for all I/O operations:
14//!
15//! - [`SourceProvider`]: Provides source code content (replaces `std::fs::read_to_string`)
16//!
17//! ## Usage
18//!
19//! ```rust,ignore
20//! use typr_core::{Compiler, InMemorySourceProvider};
21//!
22//! let mut sources = InMemorySourceProvider::new();
23//! sources.add_source("main.ty", "let x: Number = 42;");
24//!
25//! let compiler = Compiler::new(sources);
26//! let result = compiler.transpile(&compiler.parse("main.ty")?);
27//! println!("R code: {}", result.r_code);
28//! ```
29
30pub mod abstractions;
31pub mod components;
32pub mod processes;
33pub mod utils;
34
35// Re-export main types
36pub use abstractions::*;
37pub use components::context::config::Environment;
38pub use components::context::Context;
39pub use components::error_message::typr_error::TypRError;
40pub use components::language::Lang;
41pub use components::r#type::Type;
42
43// Re-export main functions
44pub use processes::parsing;
45pub use processes::transpiling;
46pub use processes::type_checking::{typing, typing_with_errors, TypingResult};
47
48/// Main compiler interface for TypR
49pub struct Compiler<S: SourceProvider> {
50    source_provider: S,
51    context: Context,
52}
53
54impl<S: SourceProvider> Compiler<S> {
55    /// Create a new compiler with the given source provider
56    pub fn new(source_provider: S) -> Self {
57        Self {
58            source_provider,
59            context: Context::default(),
60        }
61    }
62
63    /// Create a compiler configured for WASM environment
64    ///
65    /// In WASM mode:
66    /// - All external modules are inlined
67    /// - No source() calls are generated
68    /// - Generated files are collected and can be retrieved
69    pub fn new_wasm(source_provider: S) -> Self {
70        use components::context::config::Config;
71
72        let config = Config::default().set_environment(Environment::Wasm);
73        Self {
74            source_provider,
75            context: config.to_context(),
76        }
77    }
78
79    /// Get the current context
80    pub fn get_context(&self) -> Context {
81        self.context.clone()
82    }
83
84    /// Parse source code and return the AST
85    pub fn parse(&self, filename: &str) -> Result<Lang, CompileError> {
86        let source = self
87            .source_provider
88            .get_source(filename)
89            .ok_or_else(|| CompileError::FileNotFound(filename.to_string()))?;
90
91        Ok(parsing::parse_from_string(&source, filename))
92    }
93
94    /// Type check the given AST
95    pub fn type_check(&self, ast: &Lang) -> TypingResult {
96        typing_with_errors(&self.context, ast)
97    }
98
99    /// Transpile AST to R code
100    pub fn transpile(&self, ast: &Lang) -> TranspileResult {
101        use processes::type_checking::type_checker::TypeChecker;
102
103        let type_checker = TypeChecker::new(self.context.clone()).typing(ast);
104        let r_code = type_checker.clone().transpile();
105        let context = type_checker.get_context();
106
107        TranspileResult {
108            r_code,
109            type_annotations: context.get_type_anotations(),
110            generic_functions: context
111                .get_all_generic_functions()
112                .iter()
113                .map(|(var, _)| var.get_name())
114                .filter(|x| !x.contains("<-"))
115                .collect(),
116        }
117    }
118}
119
120/// Result of transpilation
121#[derive(Debug, Clone)]
122pub struct TranspileResult {
123    pub r_code: String,
124    pub type_annotations: String,
125    pub generic_functions: Vec<String>,
126}
127
128/// Compilation errors
129#[derive(Debug, Clone)]
130pub enum CompileError {
131    FileNotFound(String),
132    TypeErrors(Vec<TypRError>),
133}
134
135impl std::fmt::Display for CompileError {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        match self {
138            CompileError::FileNotFound(name) => write!(f, "File not found: {}", name),
139            CompileError::TypeErrors(errors) => {
140                writeln!(f, "Type errors:")?;
141                for err in errors {
142                    writeln!(f, "  - {:?}", err)?;
143                }
144                Ok(())
145            }
146        }
147    }
148}
149
150impl std::error::Error for CompileError {}