Remove unused system library and simplify environment initialization
The `system.myc` file, containing macros and core utilities, has been removed as its functionality is now handled by an embedded string. This simplifies the build process and eliminates a file that was no longer strictly necessary. Additionally, the `with_cwd()` method on the `Environment` has been removed. The environment now automatically adds the current working directory and its `rtl` subdirectory to the search paths during initialization. This streamlines the setup for file-based usage and ensures standard search paths are always considered.
This commit is contained in:
+32
-26
@@ -19,7 +19,6 @@ use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry}
|
||||
use crate::ast::compiler::optimizer::Optimizer;
|
||||
use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, Specializer};
|
||||
use crate::ast::compiler::tco::{ExecNode, TCO};
|
||||
use crate::ast::rtl;
|
||||
use crate::ast::rtl::intrinsics;
|
||||
use crate::ast::types::{
|
||||
Identity, NodeIdentity, Object, Purity, SourceLocation, StaticType, Value,
|
||||
@@ -28,6 +27,9 @@ use crate::ast::types::{
|
||||
use crate::ast::diagnostics::{DiagnosticLevel, Diagnostics};
|
||||
pub type PipelineGenerator = Box<dyn FnMut() -> bool>;
|
||||
|
||||
const SYSTEM_LIB_SOURCE: &str = include_str!("system.myc");
|
||||
const SYSTEM_LIB_PATH: &str = "<embedded>/system.myc";
|
||||
|
||||
pub struct CompilationResult {
|
||||
pub ast: Option<TypedNode>,
|
||||
pub diagnostics: Diagnostics,
|
||||
@@ -169,22 +171,18 @@ impl Environment {
|
||||
search_paths: Rc::new(RefCell::new(Vec::new())),
|
||||
loaded_modules: Rc::new(RefCell::new(HashSet::new())),
|
||||
};
|
||||
env.register_stdlib();
|
||||
env
|
||||
}
|
||||
crate::ast::rtl::register(&env);
|
||||
|
||||
/// Adds the current working directory to the global search paths.
|
||||
/// This is a builder method to easily initialize an environment for file-based usage.
|
||||
pub fn with_cwd(self) -> Self {
|
||||
// Automatically add standard search paths (CWD and CWD/rtl)
|
||||
if let Ok(cwd) = std::env::current_dir() {
|
||||
self.add_search_path(&cwd);
|
||||
// Also add the rtl subdirectory if it exists
|
||||
env.add_search_path(&cwd);
|
||||
let rtl_path = cwd.join("rtl");
|
||||
if rtl_path.exists() {
|
||||
self.add_search_path(rtl_path);
|
||||
env.add_search_path(rtl_path);
|
||||
}
|
||||
}
|
||||
self
|
||||
|
||||
env
|
||||
}
|
||||
|
||||
pub fn add_search_path(&self, path: impl AsRef<Path>) {
|
||||
@@ -276,16 +274,7 @@ impl Environment {
|
||||
base_path: &Path,
|
||||
all_files: &mut Vec<(PathBuf, Node<UntypedKind>)>,
|
||||
) -> Result<(), String> {
|
||||
let mut directives = self.extract_use_directives(source);
|
||||
|
||||
// Implicitly add #use system if it's not already there and we can resolve it.
|
||||
// This is only done for the root script (when loaded_modules is empty) to avoid redundancy.
|
||||
if !directives.contains(&"system".to_string())
|
||||
&& self.loaded_modules.borrow().is_empty()
|
||||
&& self.resolve_module_paths("system", base_path).is_ok()
|
||||
{
|
||||
directives.insert(0, "system".to_string());
|
||||
}
|
||||
let directives = self.extract_use_directives(source);
|
||||
|
||||
for module_path in directives {
|
||||
let abs_paths = self.resolve_module_paths(&module_path, base_path)?;
|
||||
@@ -352,7 +341,23 @@ impl Environment {
|
||||
pub fn preload_dependencies(&self, source: &str, file_path: Option<&Path>) -> Result<(), String> {
|
||||
let base_path = file_path.and_then(|p| p.parent()).unwrap_or_else(|| Path::new("."));
|
||||
let mut files = Vec::new();
|
||||
|
||||
|
||||
// 1. Always load the embedded system library first as a virtual module
|
||||
let system_path = PathBuf::from(SYSTEM_LIB_PATH);
|
||||
if !self.loaded_modules.borrow().contains(&system_path) {
|
||||
self.loaded_modules.borrow_mut().insert(system_path.clone());
|
||||
let mut parser = Parser::new(SYSTEM_LIB_SOURCE);
|
||||
let untyped_ast = parser.parse_expression();
|
||||
if parser.diagnostics.has_errors() {
|
||||
return Err(format!(
|
||||
"Failed to parse embedded system library:\n{}",
|
||||
parser.diagnostics.items[0].message
|
||||
));
|
||||
}
|
||||
files.push((system_path, untyped_ast));
|
||||
}
|
||||
|
||||
// 2. Collect dependencies from the main source
|
||||
self.collect_dependencies(source, base_path, &mut files)?;
|
||||
|
||||
// Pass 1: Discovery (Globals and Macros)
|
||||
@@ -463,7 +468,7 @@ impl Environment {
|
||||
Some(checker.check(&wrapped_ast, &[], diagnostics))
|
||||
}
|
||||
|
||||
pub fn compile_untyped(&self, untyped_ast: Node<UntypedKind>) -> Result<TypedNode, String> {
|
||||
fn compile_untyped(&self, untyped_ast: Node<UntypedKind>) -> Result<TypedNode, String> {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
let typed_ast_opt = self.compile_pipeline(untyped_ast, &mut diagnostics);
|
||||
@@ -530,9 +535,6 @@ impl Environment {
|
||||
values.push(val);
|
||||
}
|
||||
|
||||
fn register_stdlib(&self) {
|
||||
rtl::register(self);
|
||||
}
|
||||
|
||||
pub fn dump_ast(&self, source: &str) -> Result<String, String> {
|
||||
self.preload_dependencies(source, None)?;
|
||||
@@ -542,6 +544,10 @@ impl Environment {
|
||||
}
|
||||
|
||||
pub fn compile(&self, source: &str) -> CompilationResult {
|
||||
if let Err(e) = self.preload_dependencies(source, None) {
|
||||
return CompilationResult::error(format!("Dependency Error: {}", e));
|
||||
}
|
||||
|
||||
let mut parser = Parser::new(source);
|
||||
let untyped_ast = parser.parse_expression();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user