From f8c7050420284673fd75dd06e5fa769448ef278b Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Wed, 5 Oct 2022 20:37:30 +0200 Subject: [PATCH 1/2] feat: add regular named imports --- Cargo.lock | 4 +- Cargo.toml | 2 +- src/modules/imports/import.rs | 122 ++++++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afd953e9..20d05259 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "heraclitus-compiler" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb9528869f6dd50f112a1ac20c926ab50349396cd7f04753f8b286975b30bec" +checksum = "8b6385fd7370f1c1b6484bee01a7452e14158dc1d4fe0b03d17ba26b96672b0d" dependencies = [ "capitalize", "colored", diff --git a/Cargo.toml b/Cargo.toml index 03042789..d81f6ee6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -heraclitus-compiler = "1.5.2" +heraclitus-compiler = "1.5.3" similar-string = "1.4.2" colored = "2.0.0" diff --git a/src/modules/imports/import.rs b/src/modules/imports/import.rs index 8c50a53e..31d00947 100644 --- a/src/modules/imports/import.rs +++ b/src/modules/imports/import.rs @@ -2,6 +2,7 @@ use std::fs; use heraclitus_compiler::prelude::*; use crate::compiler::AmberCompiler; use crate::modules::block::Block; +use crate::modules::variable::variable_name_extensions; use crate::utils::exports::{Exports, ExportUnit}; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::module::TranslateModule; @@ -9,17 +10,52 @@ use super::import_string::ImportString; #[derive(Debug, Clone)] pub struct Import { - path: ImportString + path: ImportString, + token_import: Option, + token_path: Option, + is_all: bool, + export_defs: Vec<(String, Option, Option)> } impl Import { fn handle_export(&mut self, meta: &mut ParserMetadata, exports: Exports) -> SyntaxResult { - for export in exports.get_exports().iter().cloned() { - match export { - ExportUnit::Function(mut func_decl) => { - func_decl.is_public = false; - if !meta.mem.add_existing_function_declaration(func_decl) { - unimplemented!("Function redefinition"); + let exports = exports.get_exports().iter().cloned(); + for (name, alias, tok) in self.export_defs.drain(..) { + let mut found = false; + for export_unit in exports.clone() { + match export_unit { + ExportUnit::Function(mut func) => { + if &func.name == &name { + found = true; + func.name = alias.unwrap_or(name.clone()); + if !meta.mem.add_existing_function_declaration(func) { + return error!(meta, tok => { + message: format!("Function '{}' is already defined", name) + }) + } + break + } + } + } + } + if !found { + return error!(meta, tok => { + message: format!("Export '{}' not found in module '{}'", &name, self.path.value), + comment: "Exports are case-sensitive" + }) + } + } + if self.is_all { + for export in exports { + match export { + ExportUnit::Function(mut func_decl) => { + let name = func_decl.name.clone(); + func_decl.is_public = false; + if !meta.mem.add_existing_function_declaration(func_decl) { + return error!(meta, self.token_import.clone() => { + message: format!("Function '{}' is already defined", name) + }) + } } } } @@ -27,9 +63,9 @@ impl Import { Ok(()) } - fn add_import(&mut self, meta: &mut ParserMetadata, tok: Option, path: &str) -> SyntaxResult { + fn add_import(&mut self, meta: &mut ParserMetadata, path: &str) -> SyntaxResult { if meta.import_history.add_import(meta.get_path(), path.to_string()).is_none() { - return error!(meta, tok => { + return error!(meta, self.token_path.clone() => { message: "Circular import detected", comment: "Please remove the circular import" }) @@ -37,24 +73,24 @@ impl Import { Ok(()) } - fn resolve_import(&mut self, meta: &mut ParserMetadata, tok: Option) -> Result { + fn resolve_import(&mut self, meta: &mut ParserMetadata) -> Result { match fs::read_to_string(self.path.value.clone()) { Ok(content) => Ok(content), - Err(err) => error!(meta, tok => { + Err(err) => error!(meta, self.token_path.clone() => { message: format!("Could not read file '{}'", self.path.value), comment: err.to_string() }) } } - fn handle_import(&mut self, meta: &mut ParserMetadata, tok: Option, imported_code: String) -> SyntaxResult { + fn handle_import(&mut self, meta: &mut ParserMetadata, imported_code: String) -> SyntaxResult { match meta.import_history.get_export(Some(self.path.value.clone())) { Some(exports) => self.handle_export(meta, exports), - None => self.handle_compile_code(meta, tok, imported_code) + None => self.handle_compile_code(meta, imported_code) } } - fn handle_compile_code(&mut self, meta: &mut ParserMetadata, tok: Option, imported_code: String) -> SyntaxResult { + fn handle_compile_code(&mut self, meta: &mut ParserMetadata, imported_code: String) -> SyntaxResult { match AmberCompiler::new(imported_code.clone(), Some(self.path.value.clone())).tokenize() { Ok(tokens) => { let mut block = Block::new(); @@ -66,24 +102,26 @@ impl Import { let index = meta.get_index(); let scopes = meta.mem.scopes.clone(); // Parse the imported file - meta.push_trace(PositionInfo::from_token(meta, tok)); + meta.push_trace(PositionInfo::from_token(meta, self.token_import.clone())); meta.path = Some(self.path.value.clone()); meta.code = Some(imported_code); meta.expr = tokens; meta.set_index(0); meta.mem.scopes = vec![]; syntax(meta, &mut block)?; - meta.mem.scopes = scopes; - meta.import_history.add_import_block(Some(self.path.value.clone()), block); - meta.import_history.add_export(Some(self.path.value.clone()), meta.mem.exports.clone()); - self.handle_export(meta, meta.mem.exports.clone())?; // Restore snapshot of current file + meta.mem.scopes = scopes; meta.code = code; meta.path = path; meta.expr = expr; - meta.mem.exports = exports; meta.set_index(index); meta.pop_trace(); + // Finalize importing phase + meta.import_history.add_import_block(Some(self.path.value.clone()), block); + meta.import_history.add_export(Some(self.path.value.clone()), meta.mem.exports.clone()); + self.handle_export(meta, meta.mem.exports.clone())?; + // Restore exports + meta.mem.exports = exports; Ok(()) } Err(err) => { @@ -98,28 +136,54 @@ impl SyntaxModule for Import { fn new() -> Self { Self { - path: ImportString::new() + path: ImportString::new(), + token_import: None, + token_path: None, + is_all: false, + export_defs: vec![] } } fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { + self.token_import = meta.get_current_token(); token(meta, "import")?; - let tok = meta.get_current_token(); if meta.mem.get_depth() > 1 { - return error!(meta, tok, "Imports must be in the global scope") + return error!(meta, self.token_import.clone(), "Imports must be in the global scope") + } + match token(meta, "*") { + Ok(_) => self.is_all = true, + Err(_) => { + token(meta, "{")?; + let mut exports = vec![]; + loop { + let tok = meta.get_current_token(); + let name = variable(meta, variable_name_extensions())?; + let alias = match token(meta, "as") { + Ok(_) => Some(variable(meta, variable_name_extensions())?), + Err(_) => None + }; + exports.push((name, alias, tok)); + match token(meta, ",") { + Ok(_) => {}, + Err(_) => break + } + } + self.export_defs = exports; + token(meta, "}")?; + } } - token(meta, "*")?; token(meta, "from")?; - let tok_str = meta.get_current_token(); + self.token_path = meta.get_current_token(); syntax(meta, &mut self.path)?; + // Import code from file or standard library let imported_code = if self.path.value == "[standard library]" { - self.add_import(meta, tok_str, "[standard library]")?; + self.add_import(meta, "[standard library]")?; AmberCompiler::import_std() } else { - self.add_import(meta, tok_str.clone(), &self.path.value.clone())?; - self.resolve_import(meta, tok_str)? + self.add_import(meta, &self.path.value.clone())?; + self.resolve_import(meta)? }; - self.handle_import(meta, tok, imported_code)?; + self.handle_import(meta, imported_code)?; Ok(()) } } From 9874eb5fc9ccbad1b357a8778679ae9e68514f30 Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Wed, 5 Oct 2022 20:54:00 +0200 Subject: [PATCH 2/2] fix lint --- src/modules/imports/import.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/imports/import.rs b/src/modules/imports/import.rs index 31d00947..f75217e9 100644 --- a/src/modules/imports/import.rs +++ b/src/modules/imports/import.rs @@ -25,9 +25,9 @@ impl Import { for export_unit in exports.clone() { match export_unit { ExportUnit::Function(mut func) => { - if &func.name == &name { + if func.name == name { found = true; - func.name = alias.unwrap_or(name.clone()); + func.name = alias.unwrap_or_else(|| name.clone()); if !meta.mem.add_existing_function_declaration(func) { return error!(meta, tok => { message: format!("Function '{}' is already defined", name)